I've built a platformer (prototype) using SpriteKit and I have a question which I haven't seen answered anywhere, including official documentation.
Since I'm starting to get impaired frame rates, I decided to remove nodes and re-add them dynamically to my scene based on their distance (essentially if they are offscreen or on) from the player's location. This seems to work fine and I can get 60fps. But this doesn't work the case of bodies that are jointed (such as a rope bridge).
I'm seeing exceptions during removal. I've finally managed to fix this by walking each node.physicsBody's joints and removing those before removing the node itself. In restoring them, I originally though that nesting each bridge under a single SKNode was the answer but this doesn't help with the joints that are added to the SKPhysicsWorld. I've played with using mutable arrays to hold onto everything but haven't figured out how remove or reattach all the nodes as they are essentially a chain. My last thought it to try to subclass the joints so that I can mark which bridge they belong to and rebuild the entire bridge in one pass as any portion of it gets close to being onscreen.
There must be an easier way to remove and rehydrate nodes (with joints). I'm probably missing something obvious. Any ideas?
Related
I have a kinematic body in my game that I switch to a dynamic body when it needs to jump so the physics simulation can handle all the complexities of gravity. I do this by replacing the entire physics body of the node. However, doing this also resets all the customisation you can do to physics bodies. Is there any way to change the physics body of a node without creating a new one? Or at least a way that somehow “copies” all the values like restitution, angular dampening, etc.
What I’ve tried so far:
Changing the type property on a physics body but the documentation says it’s supposed to be a constant (even though it’s a get-set property???). I don’t want to go against the documentation so I don’t think this should be the right way
Experimenting with pointers and reflections to copy the values somehow. I started reading about Mirror yesterday so I’m not sure if functionality like this even would be possible, but I am considering it.
Using the copy() function, however, I’d still have to manually copy all the small settings
Please let me know if there’s a way to switch the physics body type while preserving its properties such as bitmasks, physics settings, etc.
Thanks
As a SCNPhysicsBody consists of its own "constructed" geometry, you will need to recreate it each time you want to change it. But you could i.Ex. predefine all physicsBodies you need (dynamic, static, kinematic, including all properties like bitmasks, etc...) in a set of variables or constants and then you assign the one you want at the moment you need it.
I am going to make simple 2D game in Defold game engine and I am new in this area. My question is, I have 2 game objects every object has sprites in it. A sprite in the first game object must be background for sprites of second object. I have designed it well but when I run (or render, I don't know how to call properly) it sometimes sprites of second game object are invisible and some times everything is OK.
The same issue if I set main backgruon image for the game. Please share your experiences with me. Thanks beforehand.
You posted the same question on the official Defold forum so I'm going to replicate the answer you got there here on SO as well. The solution is to make sure that the depth of two game objects that overlap isn't the same. If two objects have the same depth and overlap you might sometimes see one in front of the other and sometimes vice versa. The default render script allows a z-range of -1 to 1 (you can use fractional z-values to get fine grained control), but you can copy it from builtins and increase the range if you want to. Something like -10 to 10 is usually a good enough value.
I'm trying to understand the proper way to move "obstacle" objects in corona/box2d. I want to know how to write my code so that the movement is deterministic and in-step with the physics engine. Is this possible?
I'm familiar with Unity which has a physics update (FixedUpdate). Where you can add a bit of code to execute on every physics step. This keeps the physics deterministic, frame and system time independent.
For example, in my game I want to do things like: Make a platform that moves back and forth, make an object that scales up and down in size. I would still like the physics to work properly and allow the ball in my game to bounce off of these for example. Depending on the case, I imagine that I should use either kinematic or dynamic bodies.
I've searched around and the way to periodically manipulate these objects is to use:
timer.performWithDelay. But this has an issue mentioned in the docs "Timers run on system time. If the app is suspended, running timers will not be automatically paused"
Listening to an enterFrame event. But this has a similar issue, if the frame rate drops then the object won't be moved enough. We can use delta time to deal with this, but this has determinism issues (moving an object too much on a lag spike).
transition.to. I'm guessing this is implemented with timer.performWithDelay and has the same issues.
I don't think that any of these will behave deterministic. Any suggestions? Thanks for the help.
You should really use:
object:setLinearVelocity(xVelocity, yVelocity)
or
object:applyForce(xForce, yForce)
instead of transition.to.
I'm a total newcomer to SpriteKit and game development in general, I've been toying with SpriteKit to make a strategy game set in space.
My backend architecture use a grid system to represent the Universe, I have empty cases and cases with systems/planets/etc...
My grid is backed by GameplayKit GKGridGraph, I use an algorithm that generate a node with random properties for each node of the grid and I subclassed it to add a custom entity to it, which all the properties of this specific universe case.
To render it, I simply use SKShapeNode and SKPriteNode with various colors, shapes and textures.
I enumerate all nodes (GKGridGraphNode) in my GKGridGraph instance, and for each of those nodes I get generate the corresponding SKNode (my SKNode generations is a component of each GKGridGraphNode entity attached object), and I set them a position, and add them as a child to my main node (let's call it mapNode) which is a simple SKNode. In the end it looks like a grid.
It works well for a 30/30 grid, I have 60 FPS while scrolling my grid (custom implementation, I modify my mapNode positon as the user move his fingers).
But as soon as I try a 50/50 or a 100/100 grid, I have literally too many nodes on the screen for the scrolling to works. I know I shouldn't add every of my node on the screen, so I thought about various strategies and I wanted some input on them:
Instead of scrolling my mapNode, I could render only the nodes I see on the screen, and then add/remove nodes as the user scroll left/right/up/down. So it's not really scrolling anymore, it simulate it. I can think of it, but not really how I should implement it in practice. Is it the right solution?
Maybe I could render all my node as one big node? Is there a way to do that? But then I'll loose functions such as nodeAtPosition, which I use extensively to get the entity (custom object) associated with my nodes.
Edit: Actually, my current code is open source, here is the scene in I'm rendering: https://github.com/Dimillian/LittleOrion/blob/master/Little%20Orion/Little%20Orion/scenes/UniverseScene.swift
Is there any other smart way of doing that?
SKTileMapNode was made just for this in Xcode 8
https://www.raywenderlich.com/137216/whats-new-spritekit-ios-10-look-tile-maps
Alternatively, you would only want to load the nodes that are in and near your current view. You would need an algorithm to do this, and would be a big headache compared to tilemaps.
I suspect the algo would involve checking which nodes are in the view's .frame' and then using 'addChild' on them--concurrently, add a reference to them to an array, which you would check against nextupdate()andremoveFromParent` if they were no longer visible ..
It would get hairy trying to optimize this though. The goal would be to load only a few nodes out on each end so that way you have some buffer in moving the camera (less updates).
You could create a math function to pre-determine which nodes are where in relation to the current frame coordinates--so you don't have to iterate through the nodes--but that would require even a lot more work and headache--and it's what people developing on consoles, etc, have to do with high-end games and limited power.
I recommend skimming through a Direct3d/DirectX/OpenGL game development book, just to get an idea of what goes into everything... They aren't hard to find: walk into a bookstore and look for the thickest / heaviest book--that will be the DirectX game development book.
You will see how what we can do with 30 lines in SK requires thousands of lines and vector calculus in C++ and low-level AV frameworks. It will give you an appreciation, understanding, and perspective of game dev, which will help you in your SK journeys :)
I'm using Cocos2D and Box2D for a game with some physics. There's an occasional problem where my "ball/bullet/destroyer" object gets stuck between two "target" objects and takes forever to work its way out.
This is silly because a collision between the bullet and the target object should destroy the target. (Normally, of course, this works fine.)
It hasn't gone to sleep as in this question, because it's vibrating around like crazy in the tiny little space between the two objects.
I have the bullet as a "bullet" object in Box2D.
Is there some minimum distance that the objects have to be in a previous frame in order to count as a collision?
The trick was that for a given "cluster" of contacts, the Box2D contact listener calls (in this order):
BeginContact()
PreSolve() // As many times as necessary
PostSolve() // As many times as necessary
EndContact()
I was, by default, only getting contacts from EndContact() which meant that a series of fast collisions would all happen before their effects were evaluated. I moved my destroy-type code into PostSolve() and all was well.