The Big Moo (supreme leader of all yakkind) was lounging on a hot, sunny beach when a tsunami warning came in. Thankfully, you're on duty, piloting the brand new Yak-O-Matic 3000, perfect for dropping yaks out of the sky.
Your mission is to strategically stack those yaks to construct impromptu bridges, towers and sacrificial battering rams to save The Big Moo from the tsunami.
Don't panic. Just Yak Stack.
No followers yet
Once you ship this you can't edit the description of the project, but you'll be able to add more devlogs and re-ship it as you add new features!
I've now created a build script to make my life slightly easier. It means that:
- I don't need to remember the long command for building (cargo +nightly build -Zprofile-hint-mostly-unused
)
- I don't need to remember to export SVGs as PNGs every time I create or edit them
This was originally a bash script but then I realised that bash doesn't work how I want it to on windows which is sad, so I redid it in python and discovered the argparse library which is cool! (Unfortunately I can't do this all in WSL because of bugs in how WSL handles input events)
I also linted the rust codebase which is nice.
Cleaned code up a bit and also made the transitioning from stack to conga mode a bit better. Now yaks stop crouching if they aren't supporting another yak (or if they're stuck), and the mode buttons are disabled until the transition has finished. I was also finding that yaks were sometimes getting a little bit stuck on the seams between other yaks and the ground, so if it is detected that a yak is stuck and isn't falling, it is given a little bit of vertical velocity to help it get clear of the seam. Hopefully.
I've now added buttons. Which was surprisingly hard. I wanted to be able to edit buttons' enabled/hover/clicked/disabled space altogether, so settled for a spritesheet-esque approach in inkscape. This worked great except for the fact that using an AtlasTexture didn't always seem to correctly crop to the correct portion of the atlas - this was an incredibly easy fix (just needed to set a minimum size for the button) but took ages to figure out. I also modularised things a bit more including texture loading - textures are now loaded from pngs where possible and fall back to svgs. I'll probably put png conversion in a build step in the future so i don't need to remember to do it manually and to help clean up source control.
The buttons are for switching yak configurations - at the moment these configurations are stacked and conga. To get from stack to conga I thought I'd just have the yaks crouch down so they slide off of each other - this works fairly well and I just need to get them to stop crouching and also stop sliding once they're on the ground and not under any more yaks. No idea how I'll re-stack them - possibly something to do with having some of them sit down and act as ramps? I think controlling jumping yaks will be very difficult!
The last couple of hours of dev time have been spent cleaning up the file structure and also making some tweaks to the code & art. I was experiencing some really funky issues where textures weren't aligning with their collision boxes - I believe this is because i was scaling textures by non-integer scale factors. Don't know why that's a problem but it is what it is. So I jiggled things around a bit and now everything aligns nicely; yaks' collision boxes are also now perfect squares which is nice.
In terms of cleaning things up, I removed old test files, moved assets into their own folder that's a bit more organised, added a README.md and also added a license (I went for the MPL-2.0 which is roughly equivalent to MIT OR APACHE-2.0, the standard license in the rust ecosystem).
Have a yak (now with a square collision box [from bottom of taller legs to top and sides of body]) as the attachment.
I have spent literally hours playing around with different things to try and get stacking and sliding working correctly (and I think I've done some other stuff that I wasn't able to devlog due to the SoM website being down). See the attached video for an example of yak stacking working properly!
The way it works is as follows:
- Each Chunk
of terrain is a StaticBody2D
rather than a TileMapLayer
. This allows tiles to be grouped into rectangles rather than being lots of squares - this helps with ghost collisions. At some point I may go back to using TileMapLayer
for rendering, but keep using custom colliders, but only if rendering becomes a performance issue. It should be noted that as of godot v4.5 (not yet released on stable channel), TileMap colliders are chunked into larger quadrants in order to reduce ghost collisions, but I didn't find this to work at all.
- Rather than the yaks moving and the ground staying still, the ground moves (backwards) with the yaks staying still and sliding along it. This greatly improves the stability of the physics. In order to make the ground move visually and also apply physics as if it were moving, I had to both set a constantlinearvelocity in each chunk and also change the position on each physics frame. This caused some issues with wrapping chunks around for infinite scrolling, since position updates in a signal handler seem to be overwritten by position updates in physics_process, so these position updates needed to be deferred.
- because the yaks don't need to be moved left/right, i replaced the CharacterBody2D
s with RigidBody2D
s (with rotation locked to avoid chaotic spinning) - this worked really well and makes things pretty stable
- because yaks don't move any more, they were sometimes set to 'sleep' by the godot physics engine, which caused them to hover in mid air if a yak underneath them was impeded by a block - this was fixed easily because you can tell the engine to not put bodies to sleep
- yaks that go offscreen are now removed to save on resources - this means I've got rid of camera zooming temporarily but I plan to bring it back at some point
now i just need to figure out how to move yaks into different configurations, which is going to be difficult now that they're rigid bodies :( fun times!
Got smooth camera zooming and sort-of-stacking of yaks working. I'm quite pleased with the camera zooming as a first attempt, but overall I feel it could be a lot better - it should really zoom out until all active yaks are in view, but at the moment it just decreases the zoom by 8(?)% if the edge of a yak goes off screen, regardless of how far off it goes.
Yak stacking also only works up to four yaks for some reason, but I'm glad I managed to get it working at all. In order to get the yaks to stack, I had to inspect the most recent collisions of each yak, and only set the horizontal velocity to a positive value if one of those collisions was with a Chunk
node (i.e. the floor) - I can't just use the native is_on_floor
method because that detects other yaks as the floor too! Because yaks currently have friction of 1.0, if a yak is on top of another yak it will immediately slow down to stationary (relative to the other yak), so that all works out fine. I also briefly experimented with using a RigidBody2D rather than a CharacterBody2D for the yaks, to give me more fine-grained control, but I was totally out of my depth there.
Next I want to work on making stacking work better, then removing abandoned yaks (i.e. those which are no longer moving) from the scene (so we don't get infinite camera zoom)
Got infinite scrolling (+ infinite(?) yak spawning) working! Infinite scrolling was surprisingly easy - I just use a VisibleOnScreenNotifier2D to signal when a chunk of terrain goes offscreen, at which point it is transported to the right of the other chunks. I had to learn about godot's signals for this, but they're surprisingly simple, and using rust makes this so much easier, because the godot
crate provides typed signals, which make it much much easier to reason about what's happening where. I still need to make it so that when the camera zooms out, more chunks are created if needed. Once I've done some camera zooming stuff, I'd like to start playing with making yaks actually stack on top of each other rather than just walking along and shmooshing into a line.
Today I worked towards getting infinite scrolling + terrain generation - at the moment the 'terrain' is just flat, with an extra block on top 20% of the time. It's also not quite infinite yet - I still need to make chunks wrap round to the front when they're offscreen. Yaks are also now programmatically generated, so my node tree in the godot editor is looking quite empty. I suspect I am not really doing things in 'the godot way', especially as rather than using the built in ready
hook, I'm doing my setup manually - that's just because I don't really know yet what order things are initialised in. Next up I also want the camera to be able to zoom out if the yack gets offscreen - this will be useful for when I start implementing stacking and the stacks get tall; at some point I'll also want to implement the wave coming so that yaks that lag behind are removed.
In the video attached I am jumping over hurdles à la Chrome Dino Game; this is just a temporary mechanic to test the scrolling and terrain generation!
Used the godot tutorial on the jumpstart website (https://v1.jumpstart.hackclub.com/guide.html) to create a very basic platformer. This wasn't just blindly following a tutorial though, as I had to translate the scripting bit to rust, which worked out ok once I'd figured out where things are. Although yak stack won't be a platformer per se, it will need that sort of physics, and using a tilemap for the terrain should work fairly well (and it'll be a lot easier than anything else). Just need to figure out how to do scrolling (presumably just move the camera, but I'll need to figure out how to discard unneeded sections of the tilemap) and also procedurally generate said tilemap - hopefully that's possible. Then I'll need to figure out how to add new nodes at run time (for many yaks), and then I can start figuring out the actual game mechanics. Exciting times!
I decided to try and learn to use godot for this (but using rust of course); this is my first time using a game engine so it'll be interesting. The attached video is what I've got working so far; I wanted to (as a test) use arrow key inputs to control the spinning speed of the yak but there seems to be some sort of input control issue with WSLg, so I'm now going to have to install rust (and godot) on my windows system :( Then I can get started actually creating this game hopefully!