How to avoid dynamics deformation using UIDynamicAnimator - ios

I have a simple tetris-like app where I am dropping square colored labels from the top of the view and they pile up once they collide with the bottom border of the window.
I am using the iOS dynamics framework to simulate the gravity and the collision.
I have 2 questions:
How can I eliminate completely the bouncing effect when the blocs collide with the bottom border? I have tried setting the elasticity of the collision behaviour to 0 ( the documentation say that this implies no bouncing at all) but the blocs still bounce a bit.
So I guess it is a bug in the documentation at least. can anybody confirm this before someone will suggest to try other workarounds?
Another technique I have tried are to set a very high resistance when the object starts the collision and resetting it to low resistance when the collision ends. The problem with this approach is that this behaviour which is generic for all the blocks, would cause the other falling blocks to be affected ( and slowed down) every time there is a collision happening at the bottom
the second question is about how can I stop the animation engine to squeeze the blocks while the pile up ( simulating the real-world effect of gravity over non completely rigid bodies) In my app I can clearly see that the blocks are not aligned because they get squeezed up by the weight of the blocks above.
How can I avoid this behaviour? I have tried to set the density to 1 and the elasticity to 0 without luck.
I have also noticed that some blocks at the bottom have the y coordinate = 481 which means that they have been pushed out of their parent view. How is this possible given that the bottom is considered as a collision boundary?

To eliminate bouncing effect, you need to add a UIDynamicItemBehavior to your animator. And set the property "elasticity" on the UIDynamicItemBehavior to 0. You can also set the "resistance" property on your UIDynamicItemBehavior to 1 or the max, CGFLOAT_MAX.

Related

Wierd gaps appearing in between SKSpriteNode - swift

Note: I have tried this answer: Gap between SKSpriteNodes in SpriteKit collision detection
I am getting gaps in between my SKSpriteNodes, after 5 minutes of letting my game run. Here is my code to make the node:
let tileNode = SKSpriteNode(imageNamed: "world1Tile\(tileNumber).png")
tileNode.position.x = x
tileNode.position.y = y
tileNode.size.width = 128
tileNode.size.height = 128
tileNode.zPosition = 10
tileNode.physicsBody = SKPhysicsBody(rectangleOf: tileNode.size)
tileNode.physicsBody!.isDynamic = false
tileNode.physicsBody!.restitution = 0
tileNode.physicsBody!.allowsRotation = false
tileNode.name = "Tile"
row.append(tileNode)
When I remove the physics body, it is running fine. Here is are some images to show you what I mean:
This image has a physics body, and was taken after immediately after running the app.
This image was taken 5 minutes after running the app.
Why is this happening? I assume it has something to do with the physics body, because my app looks exactly like the first picture, even an hour after running the app if there is no physics body. What physics body property should I change to stop this from happening? Any help would be appreciated.
I had a similar issue not too long ago, where gaps were appearing between nodes that were tiled (although I didn't use physics). Based on this answer, I found that if you want perfect alignment between nodes, it is best to ensure that the positions of nodes as well as the nodes' width and height are whole numbers.
I would suggest to round-off the x and y values of the position of tileNode and see if it will make any difference .
I'm guessing there is no gap. you probably have 'showPhysics' to true in your gameviewcontroller, and the line appears as a gap to me.
compare position with and without the pb to verify.
I had similar problem where gaps between sprites started appearing after around 5 minutes of scrolling with constant speed (game with infinite scroll). I did not use physics and I even had all positions, widths, heights rounded to integer value. I was scrolling the camera and adding new sprites one right after another and everything was working fine except after around 5 minutes of that infinite scrolling gaps begin to appear just as in your case. I spent some time in looking for a solution and it turned out that the problem was that when positions of my objects were becoming big that is in my case X position in the scene was around 150000 then those gaps started to appear and also I noticed that this problem occurred only on devices which had to scale the scene. I was using aspect fill with default scene size for iPhone 6 resolution and those gaps only appeared on iPhone 5 but on iPhone 6 I did not notice them. I was able to fix that issue by subtracting some constant value from X position of all objects (including camera position) from time to time so that everything on the scene relatively did not change position to the camera and look the same but actually absolute positions were changed to keep them low. I guess that larger position values like 150000 and scene scaling cause some floating point rounding issue in SpriteKit and that is why gaps are then becoming visible.
So based on my experience if you have similar gaps I recommend using integer values for all positions, widths, heights and additionally keep values of objects positions of all objects low.
For future reference in case someone is still searching for this, here are my experiences:
If tiles have PhysicsBodies, they are prone to making gaps. A solution for me was making a blank SKNode as a child of the tile, and assigning the PhysicsBody to that.
If possible, make sure bit masks are set in a way that tiles can't collide with each other.
As stated in a previous answer, make sure all measurements are integers and rounded in a way that doesn't leave a one unit gap between them.
A related problem is also SpriteKit's PhysicsBody drifting. There are some threads about this (e.g. https://forums.developer.apple.com/thread/27057 ), and it seems to be abug. In my case, the problem was a combination of PhysicsBodies causing random small gaps, and the drifting making some of them larger. The steps above removed the small gaps. Unfortunately the only workaround for the drifting problem in my case was to only generate PhysicsBodies for nodes that are within a certain distance from the player and destroying them after they are left behind.
For future reference for anyone who needs, I found an different answer specific to my problem. As JohnV said, I may need to round of values when setting the position, but when running the code, I found out that I also need to do that when running SKActions.

SceneKit Directional Light causing flickering

I'm trying to add a directional light in Scenekit to cast shadows, but it is causing weird artefacts on objects.
The orange block below has a material with default settings and the diffuse set to orange.
The directional light is pointing downwards, and the scale is increased, otherwise it has default settings. (Making the scale smaller still has the same issue).
When I pan the camera around the texture is covered in flickering lines and dots, it looks terrible.
This isn't visible on the simulator, only the device. What is going on and how can I fix it?
Thanks to Toyos I now know that self-shadowing is what's causing the lines. The docs for shadowBias say setting this value should correct it, but for me it made no difference.
In the end I fixed it by rotating the directional light by 2 degrees. It was originally at -90, pointing straight down. Changing this to -88 has completely removed all the artefacts.
Configure the zNear/zFar range of your light to make it as small as possible (but not clipping your world). The smaller the zRange is the more precision you will get.
You can also play with the shadowBias to limit the self shadowing artefacts

iOS SpriteKit strong collision issues

I wrote few simple SpriteKit games and always had problems with strong collisions behaviour. Even now with my latest game in development the same issue appears quite randomly.
Game-play area is inside edgeLoopFromRect physics body
There are some objects (with circle physics body) bouncing around
But sometimes (this happens very rarely) when a strong collision (edge <- body1 <- body2) happens directly near the edgeLoopFromRect physics body, sometimes colliding-object (body1) jumps out. I am totally confused how to debug this kind of behaviour.
EDIT: I have recorded a video of what exactly happens:
Physics engine collapses
For the demo I have made impulse strength (the biggest blue ball) on purpose 10-times stronger, so the effect can be seen sooner. Look what happens after 10-15 seconds. Physics totally collapses. This can be seen by background totally going off and balls fly into the unknown.
Note: everything I do in this demo is applying impulse on the blue ball.
You need to enable usesPreciseCollisionDetection. This will force SpriteKit to calculate the physics positions of the entire movement, which will now prevent it from popping out. Code for this would look like this in Objective-C:
self.body1.physicsBody.usesPreciseCollisionDetection = YES;
And in Swift:
body1.physicsBody?.usesPreciseCollisionDetection = true
This will have a performance impact, but will prevent your glitch from happening. You will probably have to do this for all of the circular physics bodies that you have moving around.

Adjacent SKPhysicsBody not working properly

I am having a problem when trying to put two blocks that have physics bodies on top of one another.
http://s1173.photobucket.com/user/Kyle_Decot/media/example_zps02f027fe.mp4.html
As you can see in the video I am able to place my block on top of the stacked blocks even though they are placed right on top of one another.
Both the player block and the other blocks inherit from a base Block class which looks like this
#import "Block.h"
#implementation Block
+ (void)loadSharedAssets {
}
- (id)initWithColor:(UIColor *)color size:(CGSize)size {
self = [super initWithColor:color size:size];
if (self) {
self.texture = [SKTexture textureWithImageNamed:#"tile"];
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: self.size];
self.physicsBody.usesPreciseCollisionDetection = YES;
self.physicsBody.dynamic = NO;
}
return self;
}
#end
Update
I've added a picture to make the problem a little more clear. Essentially the problem is that even though the blue blocks are right above one another, I am still able to jump up (w/ the red block) and sit on the edge of the bottom blue block (which shouldn't be possible). It seems something is off w/ the physics bodies or something.
You can see that the red block is slightly higher than the adjacent blue block for some reason and "sits" on the edge of the bottom blue block. when I jump up against it.
EDIT: replaced original suggestion with answer
Scrolling to section 4.5 Edge Shapes of the box2d documentation and you will find the cause of this (SpriteKit uses Box2D under the hood for it's physics implementation)
In many cases a game environment is constructed by connect several edge shapes end-to-end. This can give rise to an unexpected artifact when a polygon slides along the chain of edges. In the figure below we see a box colliding with an internal vertex. These ghost collisions are caused when the polygon collides with an internal vertex generating an internal collision normal.
The two edges here (edge1 and edge2) are the left hand side edges of the two blue boxes in your game (so picture it rotated 90 digs counter-clockwise)
Box2D introduced ChainShapes to get around this issue (which you can find referenced in section 5.6 Edge Shapes.
The idea is to replace groups of square physics bodies with a chain of these vertices whenever generating more than one box at the same time.
I believe you can access these within SpriteKit by using bodyWithEdgeChainFromPath and passing in a Core Graphics path consisting of the corner points of the boxes you want to combine to form the collision chain
I could imagine that tiny numerical errors in the simulation run by SpriteKit, in particular regarding collision detection and motion will make the red box indeed sit on the edge of the lower blue box. This position may be stable simply because the blue box accelerates the red box leftwards for the short amount of time it remains on screen.
A solution could be to use specific body types that merge the different configurations of boxes with smooth left vertical surfaces that occur in your game. In the specific case, it would be a box that is twice as high than wide. Before you spend a lot of time on this, you could test first of all, if removing the lower blue box stops the red box from getting stuck.
You don't need to define different Block classes for different box configurations: your initWithColor:(UIColor *)color size:(CGSize)size already appears to accept different sizes, but you might want to provide additional texture tiles and identifiers for those to select from.
EDIT: since you've clarified your question a bit and you seem to want the red one to fall back to the ground, while the blue blocks stay where they were, it seems that the bodies may be too rough, which makes them stick, and the red one doesn't slide off.
There's the friction property - modifying it can turn the body from a rough one (1.0) to one that's as smooth as an ice cube (0). Per the documentation, the default value is 0.2, which may still be too rough for your needs. Try setting it to physicsBody.friction = 0.0 in all involved bodies.
EDIT 2: it seems that it's a deeper bug. You can try the following workarounds to achieve your desired effect, if you want to sacrifice a little accuracy:
set your first blue block physics body to the target rectangle size, then make each subsequent lower block body 1-2 pixels narrower, so that you evade the 'lip'
set your physics bodies to circles rather than rectangles if all else fails - bodyWithCircleOfRadius:self.size.width*0.5. For a fast enough simulation, this might do.

Handling very fast moving objects in Sprite Kit

I have an object that is moving very fast (max velocity 900). When it reaches max speed it starts to create trailing objects or motion blur.
But I just want it to be the object moving fast. I am running on 60 fps.
I like the speed of the object but I don't like how its getting rendered (motion blur). How do I handle this?
This object bounces all around the screen with a restitution of 1.02, because I want to make it pick up speed as it keeps bouncing. I want to make it go faster thats why I did the 1.02 restitution.
The motion blur may simply be due to the LCD display having an "afterglow". So the position the object was in the previous frame is still a little brighter in the next frame because it takes some time for the crystals inside the LCD to return to the unlit state.
This causes "motion blur" on any moving object on the screen, and is of course more noticeable the faster the object moves. You may even be able to make out multiple versions of the same objects at different light levels trailing behind the object's position.
This effect may also depend somewhat on the device and model, and is often called 'ghosting'.
Regardless, there's nothing you can do about the "motion blur" caused by the LCD screen's afterglow effect. Here's a good article explaining the effects and their causes.
Hmm... you'll have trouble getting it to render smoothly.
At that speed (900 points per second) it will move 15 points every FRAME if running at 60 fps. That's a significant amount to move in such a short amount of time. In about 1/3 of a second it will travel entirely across the screen.
I'm guessing it will be getting to the limit of the ability of the hardware. Both the processor, the screen and your actual eyes. I imagine you'll also hit physics errors too with it possibly escaping through walls etc...
Can you show a video of how it is currently behaving?

Resources