Devlog: Godot Game - Level 3-2 and a Rotating Platform

Okay, time to start level 3-2. This, like level 3-1, is in the mountainous regions. Except this time, the player will be a little higher. So that means jagged platforms, more verticality, lots of gaps: a real sense that care of where one steps must be taken.

Starting with some platforming to give this sense: a few narrow safe areas, separated by pits, leading into an area with platforms.

CleanShot 2025-10-22 at 21.23.18.png

Now, I have two choices of mechanics here: I can have the rotating platform, or I can have an area of the tile map fall away when the player lands on it. I think I prefer the rotating platform for the sole reason that adding the falling away platform may be a little overwhelming for the player.

Actually, no. Danger and instability is the feeling I want to go for here. So I’ll add the falling platform, followed by a large safe area where the player can see the rotating player. Also, since this is a new mechanic, it’s only right that the player should play with it in a safe area first.

Okay, I’ve added the falling platform. Well to be honest, I designated an area of the field where the falling platform will go. This leads into a large safe area which would be an ideal place to introduce the rotating platforms I have in mind.

I’m thinking of a scene with an AnimationPlayer that will do the actual rotation animation: as in rotate the sprites from 0° to 90°. The question is, do I want the entire sequence timed using the AnimationPlayer? As in, have a single animation that will rotate the platform all 4 times, with gaps between each stage? Or should I stick with the AnimationPlayer simply animating a 90° rotation, and having another thing timing the wait time between stages?

I think I prefer the latter. That way, I have more control over the pause between stage rotations. I can do things like disable it, or making it configurable. All desirable features.

I guess the next question then is whether I want the AnimationPlayer at all. Wouldn’t it be more flexible to do the animation in code? Probably, but I’m not sure I want that flexibility, at least not yet. Maybe in time it would be needed, but I think for now, I’ll just stick with the AnimationPlayer.

So, let’s start building out the animation. I think I’ll start with four animations, each one rotate the platform from θ to θ+90°, just from different starting positions. I’ll use names that include the start and end angles, like rotate_0_to_90, to allow for bidirectional rotation, should I decided to add that. Angle 0° will be up, and rotation will be clockwise. I think each rotation will be 0.5 seconds at speed 1, just so I have a consistent speed control. I can adjust the speed of the overall playback on the AnimationPlayer itself.

CleanShot 2025-10-25 at 16.22.23.png

Okay, animations made. Now to think of collision. I don’t like the idea of a collision box rotating along with the platforms. I’m not too certain about how well this plays with the physics engine, and even if there were no issues, non-orthogonal geometry is just not a thing in this game. So what I’m thinking of doing is adding two collision boxes, one horizontal and one vertical, and just toggling between the two as the platform moves into position. While the platform is rotating, both boxes will be turned off.

Ooh, I didn’t know the collision layer could be added as a animatable track. That’s pretty cool.

CleanShot 2025-10-25 at 16.33.27.png

Now to add a Timer which will actually dictate the cadence. The included code is nice and neat: basically take the current rotation of the sprites in degrees, add 90 to it, and produce a string which will become the next animation to play:

func _on_timer_timeout() -> void:
	var next = _next_animation()
	animation_player.play(next)

func _next_animation() -> String:
	var rot = int(sprites.rotation * 180 / PI) % 360
	return "rotate_%s_to_%s" % [rot, rot + 90]

Added it to a test level, and I had to speed up the AnimationPlayer to 3x normal speed, just so that the movement is snappy enough to justify the loss of collision during the rotation. It may need further adjusting a little later, but so far works pretty well. Although I do think I need to telegraph when the platform is about to move.

Oh, I remember how I’m going to telegraph to the player when the platform is about to rotate! It’s to be an indicator panel mounted at the front that will rotate slowly on it’s own. When it reaches a new orientation it will pause, then the platform behind it will rotate.

Okay, new sprite. How the heck did I choose a canvas size with non-even dimensions and still end up with a sprite that doesn’t have a definitive centre line? 🤦

CleanShot 2025-10-28 at 21.21.15.png

Turns out it was how I was removing the upper and lower circles. I was using the eraser for that, and I didn’t position it properly.

CleanShot 2025-10-28 at 21.24.05.png Okay, here’s the sprite:

CleanShot 2025-10-28 at 21.29.07.png

Now to think about animating it. I’m wondering if it would be possible to simply add it to the same animation player as the platform. The thing is, I would like them to be somewhat independent. The indicator should move on it’s own accord, even when the platform sprite is rotating to a new orientation. I would also like the indicator to take on the platform rotation cadence, sending it a signal when it reaches a stop (this will remove the need for the Timer).

Can I do that all in a single scene though? Maybe with two animation players? I’ll try that and see how viable it is.

Okay, just tried that, and yes, using two AnimationPlayers is viable. Now to prepare the animation. The current rotation period is 3 seconds so I’ll start with a 6 second animation that would just rotate the indicator over 180° with a slight pause halfway to trigger the platform. One good thing about the indicator’s symmetry is that one animation can cover the full rotation. Although be sure to change the loop wrap mode to “Clamp”, otherwise you’ll see the sprite spin round to 0° when the animation repeats.

CleanShot 2025-10-28 at 21.58.34.png

Here’s the full thing in action. And yeah, adding the indicator was pretty crucial in the end. The platform’s wouldn’t have been fair otherwise.