I've been building a game center game for iOS and it works great so far. I finally started testing the game and theres (obviously) some latency, which is causing the game to be out of sync.
Basically I have 2 players, each controlling a game character. The game character can shoot fireballs and iceballs etc. These attacks do damage, and they have effects. For example. the ice ball effect will freeze the opponent for 3 seconds if it makes contact. the fireball will do extended fire damage for 3 seconds.
so the problem is, when I was playing against my brother, because of the latency, my game said I had 40 health left and he was down to 0, while on his device, the game said I had 0 and he had 20.
This means that attacks were registering/colliding on one device (based on the positions of the characters/fireballs) and not on the other. and vice versa.
I'm currently using the default peer-to-peer game-center architecture. Would using a client-server architecture (one person becomes the server) solve this out-of-sync problem?
if not, what other options do I have with the game kit API?
I've found a solution to this problem.
Note: this will be a relatively long answer.
One thing that I did implement was the use of udp for some of my data transfers that are not as critical as others. For example, since I'm sending movement data about 10 times a second, I figured its ok if 1 or 2 of the 10 get lost once in a while.
Now to the actual problem:
So what was happening is the following- since I'm using a p2p architecture, both clients have a delay when they see the game 'world'. This means that on my device, I see the enemy player at a position that is delayed 100-200 milli seconds. (so he was actually there 100-200 ms in the past).
The problem with this, is when I shoot a projectile at the enemy, and I see a collision, if the collision was right on the edge of his sprite (his feet or head), in his screen, he was already past that position - PLUS - my fireball appears 100ms delayed on his screen. This means on his device, he was able to dodge my attack. This can happen a random number of times, but I'd guess its probably below 30% of the time. 70%, both devices see the collision.
The solution
What I came up with is to send a message to the other player when either device sees a collision. And remember, each device has no idea if the other saw a collision or not. So I have no way of knowing whether both devices saw a collision, or only 1, and the other saw that the attack was dodged.
This means I have to send a message to the other player every time theres a collision. Now, because of the way I've architected my game, when a collision is sent, I'm automatically applying the collision event (meaning, damage dealt, projectile effect that took place - like ice bolt freezing the player it collided with) This is problematic, because what if both devices saw the collision. That means both devices are sending each other a message of collision, and applying collisions again.
To get around this, I've added a "spell number" to each spell/attack, and when a collision happens, I save this number with the player that the collision happened with as the "last collision spell number". So if a collision takes place with that spell, the player knows he/she already collided with that specific object, so collision logic doesn't run twice.
Related
How does one handle sound triggered on contact with other nodes in SceneKit without SCNAudioSource class (SCNAudioSource is only available in iOS9). What frameworks should be used, which are preferable?
I will be doing the following: I am just animating a box falling on the ground and than roll a few times. It would be nice if a could ad a realistic "hit" sound every time the box hits the ground. I have also implemented a method that calculates the current linear and rotational speed so that I can link the volume level of a hit proportional to the speed of box at that time.
I was thinking I could use physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact)and produce the sound in here, but I am a little sceptical, because this gets called really a lot.
I've got a scene where a certain number of nodes spawn at the top of the screen and another batch of nodes at the bottom. Now if they collide, I want the game to end which it does, the only problem is that the collision causes a major frame drop or stutter/lag whatever you can think. It basically stops the game for a second and it continues.
The nodes don't have textures. There are no sounds playing when the nodes collide. I've stripped everything down and left just the nodes to collide and the problem persists. I can't point a finger at where it's really coming from since i've left nothing unturned and the scene is not complex 8/9 nodes most at a time.
This doesn't always happen sometimes the nodes collide and everything runs smooth. The only other information i can provide is that the nodes are moving rather fast so they fly in and out of the scene within 0.05 seconds which i tried setting it to a longer duration the problem still persists just more rarely. When the game is over the user has the option to present the scene again which adds the scene from the beginning.
This question leans more toward people who might have had a similar issue , since I don't know what more information I can provide. (Square nodes collide right away the game stops for a second and continues). Thanks.
I am creating this sort of first person shooter game for the iPhone 6 Plus, but when I introduce any lights to the scene, the frame rate goes from an already barely acceptable 12fps to an absolutely unplayable 2fps. Also, introducing a particle system with more than ten particles in it takes the frame rate to 9fps. I have already made it so that it adds all the walls and doors to a map node, and then flattens it using flattenedClone and adds that. I am unsure what else I can do without switching to Metal. But I am also wondering about this because if SceneKit were so slow, why would it even exist?
Problem solved: get a developer licence!
I've made my way through the pages of SO questions regarding sprite-kit, the docs, available demos, and the vast empty space that is my brain to try and figure this one out but have come up short.
Working on a proof-of-concept that is a turn-based (using Game Center), physics-based game. Players take turns placing a node amongst a collection of other nodes and letting the physics play out. Where I'm flummoxed is in determining that all collisions have played out and the turn has ended.
It would seem that the nodes never stop colliding.
This is a tricky task with physics simulations.
First of all, with gravity enabled you always have a force acting upon bodies that may prevent it from resting. So you need to test every body every couple of steps (or every frame if you must) to see whether its velocity vector length is smaller than a given threshold. Then manually set the body's resting state to YES.
The bodies may wake up again during contacts, so it is crucial to perform this step after contact resolution in didSimulatePhysics.
The trick is in finding a threshold that is large enough to guarantee an end to the "physics entanglements" while not being too high to make objects stop where they clearly shouldn't.
Even then you probably also need to set a timer that starts when every body's velocity is below another (higher) threshold indicating that there will likely be little forces coming from those bodies anyway, and if after a grace period (ie 10 seconds) the bodies are still not all resting but below this threshold, consider the collisions resolved (as far as the game is concerned).
Also the number of bodies still not resting may be an indicator to end the game, ie if there are only 3 or 4 bodies of dozens still moving, there's probably not much going to happen as well.
Im using Union server for my iOS (Starling) billiard game.
So far the connections work great.
My question is:
How would you handle the transfer of the ball positions from the opponent.
Lets say I make the break, and I want to copy that shot to the other player?
Do you think its a good idea to send a message over union every frame (x, y)?
Will this cause latency problems?
First about your question:
The game is installed on both devices, the rules are same. So on shot send the white balls force and all other properties you modify. On the receiving device add that force etc. and the ball will repeat the action done by the sending user.
Now the sad part:
I will be the first one to disappoint you - even if you solve your problem and send the message from player to player with out problems the result won't be pleasant: box2d calculations are optimised for performance, but the result will differ as it's calculated with approximate accuracy. As a result even on the same device the balls will end up in a different location on different runs. You won't notice it in one-two hits, but after playing for a minute you'll end up with deferent ball locations.
You can also try to send a message of every ball position in space after all balls stop moving and relocate the remote users ball positions. After that "correcting" message was received return the control to the player.
We had a similar game and I just wrote my own 2d engine. If you're working only with ball to ball and ball to rectangle collisions it's easy to write your own engine.