Rendered at 14:09:47 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
tedavis 1 days ago [-]
This is excellent! What was the biggest challenge you found while developing the sequel?
tom32i 1 days ago [-]
It was clearly dynamic "trail" geometry:
in curvytron your trail grows behind you as you go, so on each frame most of active players trail "capsule" 3D geometries have changed.
I started by blindly recalculate every geometry on every frame, work well enough for a time but I think you can see the optimisation problem coming...
On each frame the trail gets only 1 new point and the rest of its points (dozens) has not changed, yet you recalculate every segment vertices (and normals, etc) for every point, just to add one new segment at the end and finally add the half-sphere cap.
And this is done by Three.js: so by the CPU, not in GPU yet.
What I did was write a dynamic capsule geometry, with pre-allocated geometry buffer and the capacity to add 1 point at each frame by just filling the missing vertices, normals, etc fo the point. Resulting in a massing performance improvement.
Side note: when the player stop "drawing" and leave a hole behind, the detached trail become inactive and just stop being re-computed at each frame.
andai 13 hours ago [-]
Nice! The game is fun.
How did you handle the reconnection?
tom32i 8 hours ago [-]
Thanks!
Reconnection relies on two mechanisms:
Server side — Secured client identification:
When you connect to the game, the server forges and sends you a unique secure token. If you lose connection, your client and player data on the server aren't removed but just "parked" into an offline list of clients. Your player is left without a pilot for a moment. As soon as you reconnect with a valid token, the server is able to restore your client and plug you back into your player's controls. You're back in the game!
Client side — Ubiquitous game data:
For reconnection to work on the player's end, I also need every client arriving in the middle of a game to get the exact same state as a client that connected from the start. This means sending every connecting client all the meaningful data about the current game: state, player positions, speed, size, ongoing bonus positions and timings, etc. I designed the game with this requirement from the very start: each new feature must follow this pattern, and the client must support building the game's world on the fly from this data.
in curvytron your trail grows behind you as you go, so on each frame most of active players trail "capsule" 3D geometries have changed.
I started by blindly recalculate every geometry on every frame, work well enough for a time but I think you can see the optimisation problem coming...
On each frame the trail gets only 1 new point and the rest of its points (dozens) has not changed, yet you recalculate every segment vertices (and normals, etc) for every point, just to add one new segment at the end and finally add the half-sphere cap. And this is done by Three.js: so by the CPU, not in GPU yet.
What I did was write a dynamic capsule geometry, with pre-allocated geometry buffer and the capacity to add 1 point at each frame by just filling the missing vertices, normals, etc fo the point. Resulting in a massing performance improvement.
Side note: when the player stop "drawing" and leave a hole behind, the detached trail become inactive and just stop being re-computed at each frame.
How did you handle the reconnection?
Reconnection relies on two mechanisms:
Server side — Secured client identification: When you connect to the game, the server forges and sends you a unique secure token. If you lose connection, your client and player data on the server aren't removed but just "parked" into an offline list of clients. Your player is left without a pilot for a moment. As soon as you reconnect with a valid token, the server is able to restore your client and plug you back into your player's controls. You're back in the game!
Client side — Ubiquitous game data: For reconnection to work on the player's end, I also need every client arriving in the middle of a game to get the exact same state as a client that connected from the start. This means sending every connecting client all the meaningful data about the current game: state, player positions, speed, size, ongoing bonus positions and timings, etc. I designed the game with this requirement from the very start: each new feature must follow this pattern, and the client must support building the game's world on the fly from this data.