Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite #56

Draft
wants to merge 75 commits into
base: master
Choose a base branch
from
Draft

Rewrite #56

wants to merge 75 commits into from

Conversation

tversteeg
Copy link
Owner

@tversteeg tversteeg commented Jul 21, 2023

Another attempt at rewriting it, this time using the pixels crate for rendering pixels as both a WASM- and a desktop application.

I ended up not liking bevy for my previous attempt. I'm also removing the ECS (for now) since it added a lot of complexity. Furthermore, I'm trying to keep the code as simple as possible without any "smart" solutions for future long-term problems that might not even occur. And nothing screams "keeping-it-simple" like writing your own physics engine, right? I fell in the trap of writing complicated things again…

The physics engine is based on Extended Position Based Dynamics, I'm roughly following this paper but of course only for 2D. The bevy_xpbd crate is also a great source. For collision detection, I first planned to use the parry crate, but I also wanted to give this a shot myself. I got the Separating Axis Theorem to work properly for the narrow-phase collision detection, but I couldn't get proper contact points, so I switched to parry. At first I implemented the broad-phase detection using a Spatial Hash Grid with a fixed bucket size. The performance was not so great and due to all buckets being statically allocated the size of the grid was also very limited. So I switched to the bvh-arena crate.

After getting the physics engine somewhat functional, I did manage that the performance was quite bad. I played around with different benchmarks and profiling to see what was the culprit, and it's mostly related to the data layout of RigidBody, which grew to be a huge struct with 224 bytes of data. Of course iterating over this is not very efficient cache-wise, so I made the decision to locally refactor the rigidbody structure into an ECS, abstracting this behind getters and setters using the handles I previously also used so it wouldn't leak into the rest of the game logic.

2023-08-15_21-50

To make the terrain destructible similarly to Worms and also to allow creation of simple breakable projectiles such as stones or shrapnel, I've implemented a solid shape type, which is a bitmap that automatically generates a sprite with an outline. It also automatically generates a polygon collider by doing a Marching Squares algorithm on the first outline pixel it finds. This is then simplified with an implementation of the Ramer-Douglas-Peucker algorithm.

2023-08-25_22-03

Another major improvement is the assets_manager crate I've integrated. This allows for hot-reloading of assets, which saves a tremendous amount of time with tweaking variables and waiting for re-compiles.

The art style is inspired by the vector art of my previous bevy attempt, but now it's a pixel-art version of that. I'm procedurally generating the terrain in quite a simple way: a buffer is created for each horizontal height and a random factor is to everyone from its previous neighbor, also a direction is changed every set amount of pixels as an additional factor. I could have created a prettier implementation with something like perlin noise but this suffices for now.

http://tversteeg.nl/castle-game/

Some progress screenshares:

collision-detection.webm
rigidbodies.webm
walking-unit.webm
box-debug.webm
draw-hole.webm

@tversteeg tversteeg marked this pull request as draft July 21, 2023 20:21
@tversteeg
Copy link
Owner Author

tversteeg commented Aug 25, 2023

Note for finding islands in the solid shape algorithm:

  1. When removing or adding pixels create a bitmap the size of the update rectangle with everything that has been added or removed, two maps if both.
  2. If removed: within the negative pixels of the bitmap with the removal deltas create flood-filled islands for each pixel with an unique ID.
  3. For each edge of an island where there are pixels do a marching squares algorithm to get the collider shape.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant