ijonatron

Members
  • Content Count

    6
  • Joined

  • Last visited

About ijonatron

  • Rank
    Newbie

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. ijonatron

    Smooth movement in a short amount of time

    Just made another slightly different version here where the player is a square moving around the canvas. In this one, movement seems smooth to me, leading me to believe that maybe the jitter is from the tiling sprite? Anyone have any insight on this?
  2. ijonatron

    Smooth movement in a short amount of time

    Ok so I threw together a quick fiddle. Player movement is shown by moving a tiling sprite towards the mouse target. I just grabbed a random image to use as the background with lots of lines and colors so jitter would be more noticeable. This looks very close to how my project does right now. There is a very slight jitter in movement that I can't seem to smooth out. I'm open to any and all suggestions🙂.
  3. ijonatron

    Smooth movement in a short amount of time

    Thanks Ivan, which method looks good? The constant movement by velocity and the delta or the interpolation? In the case of the first one, the issue is that it moves faster on the client than on the server due to different loop rates. In the case of the second, I could try making a fiddle but the project is relatively complex with a server and such so I'm not 100% sure I can replicate the behavior but I'll try.
  4. I'm facing a frustrating conflict between client prediction and smooth movement that hopefully someone can help me out with. Every 15ms, the client gets a target from the mouse position and sends it off to the server and immediately simulates the effects. I'll call this the input tick. When an update is received from the server, the client compares its current state with the server's state + any unacknowledged input. They should usually match pretty closely and in my implementation they do. Because the details of that interaction are out of the scope Pixi, that's all I'll say about that. Just know that it currently works as expected. My issue is that when the client simulates the effects of each movement, it is moving across relatively large amounts of pixels very quickly, leading to understandably jittery movement. Each input tick, the player needs to move upwards of 8 pixels which seems small but is very noticeable if it isn't smooth. Here is my movement code... const distance = getDistance(this.local.pos.x, target.x, this.local.pos.y, target.y); this.local.direction = Math.atan2(distance.y, distance.x); /* speed = 8 */ this.local.pos.x += speed * Math.cos(this.local.direction); this.local.pos.y += speed * Math.sin(this.local.direction); The movement works as intended but in a jittery fashion. So I tried instead setting the player velocity like so... /* speed = 8 */ this.local.vel.x = speed * Math.cos(this.local.direction); this.local.vel.y = speed * Math.sin(this.local.direction); Then in Pixi's ticker, update the position like so... this.local.pos.x += this.local.vel.x * delta; this.local.pos.y += this.local.vel.y * delta; The delta here is the ticker's deltaTime which should make for smooth frame rate independent movement. And it does!😁 Except it throws the whole prediction-reconciliation aspect out of whack.😩 This is because now the player is moving with the animation loop and at a different speed due to the delta. I also tried lerping between the current position and the predicted position but I think that since the input tick rate is so low, the lerp function is only interpolating between a couple states. I tried doing this in the Pixi ticker loop... /* this is reset every 15ms with each input tick */ sincePrediction += app.ticker.elapsedMS; const smoothPeriod = 15; const delta = sincePrediction / smoothPeriod; manager.interpolate(_.clamp(delta, 1)); Then in the "manager.interpolate" method using the lerp function to interpolate between the previous and next state. But as I said, I think since 15ms is so low, lerping essentially just jumps to the next state here. So, I need a way to smoothly move to the new position up until the next prediction tick hits in 15ms. Sorry for the long question, I wanted to be thorough. Please let me know if any more info is needed. Any suggestions, advice, and help is appreciated
  5. ijonatron

    Entity interpolation with Pixi.js

    (-‸ლ) Just realized I was using the wrong ticker value... Instead of adding ticker.deltaTime to t I should have been adding ticker.elapsedMS. Still very new to Pixi 😬 Maybe someone else will have the same problem and find this...
  6. ijonatron

    Entity interpolation with Pixi.js

    Hey everyone! Just joined this forum hoping someone could help me out here... I'm working on a test project to try out some of these concepts. I'm currently working on entity interpolation and I think I'm pretty close to it working, but the moving objects still seem jittery. On the back end I'm sending snapshots of player positions every 50ms... // send snapshots setInterval(() => { const snapshot = { timestamp: Date.now(), players }; ws.clients.forEach(client => { client.send(pack('snapshot', snapshot)); }); }, 50); These snapshots are being received on the client like so... const sync = snapshot => { // keep the last 2 snapshots if (snapshots.length === 2) snapshots.shift(); snapshots.push(snapshot); snapshot.players.forEach(player => { let manager = playerManagers.find(mngr => mngr.id === player.id); ... manager.updateRemote(player); }); t = 0; }; The manager here is a class instance associated with each player that controls the sprite's position, rotation, etc. Here is that updateRemote method... updateRemote = player => { this.local = this.remote ? this.remote : player; this.remote = player; } What this does is set the manager's local and remote properties. These are the states that the sprite should interpolate between. Then here is the Pixi.js ticker... let t = 0; ticker.add(() => { t += ticker.deltaTime; let lag = 50; if (snapshots.length >= 2) lag = snapshots[1].timestamp - snapshots[0].timestamp; playerManagers.forEach(manager => manager.interpolate(t / lag)); }); Here I am increasing t by the ticker's deltaTime and dividing that by the time between the two snapshots (or the intended time if there aren't two snapshots available). Remember above that t is reset each time a snapshot is received. This means when a snapshot was just received, t will be 0 and start counting up. When another snapshot is received, t will be at 50 (or whatever the real lag is) then be set back to 0 and repeat. In other words, t / lag will be between 0 and 1 for the lerp function... Here is that interpolate method... interpolate = delta => { this.sprite.position.set( lerp(this.local.pos.x, this.remote.pos.x, delta), lerp(this.local.pos.y, this.remote.pos.y, delta), ); this.sprite.rotation = lerp(this.local.direction, this.remote.direction, delta); } And the lerp function is the second formula here. AFAIK this should give me smooth movement between the past snapshot (local) and the new one (remote), but movement still seems choppy and jittery. I'm fairly new to interpolation, prediction, and other game networking concepts so hopefully someone can help me out here. Please let me know if any more information is needed.