Game design breakdown - The Old Lady game
Return of Rozen
I'm back and more ready than ever!
Having a break after building so many games, and the tedious exam session, and seeing game jams being as popular as ever, I now have reemerged. My new motivation (and some help from my family) has developed into this game. It's not super wild and it does incorporate many already know techniques in Godot, but I found it refreshing and helpful in cementing my knowledge about the different tools the Godot game engine has to offer.
A learning experience
The design process of this game was fairly simple for me, as I did not base this game off of my own plan, but another idea my family had. They helped me create a design document, created prototypes for assets and playtested the game. I was the one who did all the behind the scenes work (programming, fleshing out ideas, finishing touches, UI design and so on). Even though I did not do as much as I normally do for the smaller games I make, I still feel I contributed enough to the game to leave a mark, and I learnt a few new tricks along the way.
To start off with, let's celebrate that this is my first game with a health system. Yay! This idea was not proposed by me, but I coded a simple setter function along with a matching statement to determine the bus's health and to show how much health they should show (which can be seen above the bus). I used an animated sprite to switch textures, though I may have also been able to use a normal sprite if I had created a 2d atlas texture resource.
Here is the code that I used:
var health := 3 :
set(value):
health = value
match value:
3:
%Health_bar.play("Green")
2:
%Health_bar.play("Yellow")
1:
%Health_bar.play("Red")
0:
%Health_bar.play("Dead")
I refamiliarized myself with functions, connecting signals through an autoload (a global script which can be seen in every part of the game, also known as a singleton), tweening node properties, collision detection for areas and a few other bits and bobs.
Offsetting a problem
My initial code:
inst.global_position = Vector2(32, 272) + 20* Vector2(sin(direction+PI),-cos(direction+PI)).normalized()
One of the big troubles I had was after prototyping the bullets. I had a script which instantiated bullets a set distance away from a point. This was fine for basic aiming, however the code did not function correctly when the walking stick came into play. I wanted the bullets to shoot out of the end of the crooked walking stick, to make it feel like a weapon. The problem arose as the end of the walking stick is offset by an amount from it's global position, and this must also be accounted for when rotating the stick.
To resolve this issue, I played around with the variables of the position offset. This wasn't very fruitful as the position offset was not constant when rotating, causing the bullet to spawn above or below the intended target. At one point I noticed that my scalar multiplier was too small (I had initially thought 20 units was enough, but the walking stick sprite was actually 32 units long), which did fix part of the problem.
After a small tea break, the solution came to me: A rotation offset. Since the end of the crooked stick was always at some angle from the direction of the sprite, I could define some offset angle for the bullet position, which I would apply to my bullet when I spawn (instantiate) it.
My final code:
inst.global_position = Vector2(32, 272) + 32 * Vector2(sin(direction+PI/8),-cos(direction+PI/8)).normalized()
A Pi-ece of mathematics
As seen in the code snippet above, I decided on the offset value of Pi/8 radians. But why did I choose this arbitrary number? This number is not random, in fact it's close to what maths tells use it needs to be. Vector2(32, 272) defines the point at which the position at which the cane rotates around. At the start, when the rotation is 0 degress, the cane is pointing upwards. The end of the cane is at Vector2(44, 242). We can use trigonometry to find the angle from the vertical the offset needs to be.
Let O be out offset angle we are trying to find from the vertical line.
Tan(O) = opposite/adjacent = dx/dy
We know that tan(O) = (32-44)/(272-242) = -12/30= -2/5
A quick note here: Godot has a flipped horizontal axis. This means the higher the y-value, the lower you go on the screen. Therefore for the mathematics to work here, we need to invert our result.
O = tan^-1(2/5) = 21.801 (to 3dp)
We can compare this to the value of Pi/8 radians = 22.5 degrees to see that this approximation is good enough (with less than 4% error)
This is why I decided that Pi/8 radians would be a good offset angle for the spawn position of the bullets.
If you play around in the game, you'll also notice that I have included a barrier to prevent the player rotating the gun a full 360. This was included as the player did not need to shoot downwards. I could have used a clamping function, but instead I used a simple if statement to detect the rotation angle of the cane.
Ending notices
I did plan on adding a few more mechanics, like the buses getting longer over time (currently they just move back and forth on the screen, I had initially intended for them to go off the screen and come back on longer). But once I had the prototype running, I felt like the scope of the project was already enough, and it didn't need any extra mechanics.
This process has not been particularly tough, since I knew many of the tools already. Now it's time for a bigger challenge. I plan on participating in this month's game-like game with the theme "ski-free". I already have a fleshed out design document, with detailed explanations of how each mechanic works, and a few sketches of weapons. Here is the synopsis of the game:
"Space exploration game with resource collection and crafting, boss fights, scrolling levels with collectables and a ship builder."
This is going to be a bit journey, so I'll keep you updated. I will post a few devlogs underlining key design points and more experiences I have along the way.
Questions you may have:
Q: Why does the game feel to slow/fast on my computer?
A: I have not implemented deltatime into my movement functions, and as a result the speed of the movement if defined by your monitor or screens framerate. I plan on learning the proper use of deltatime for future projects (and may implement it into this project) once I have a better understanding of how it works and when to apply it.
Q: Which part of game design do you prefer the most?
A: I quite like designing engaging puzzles, as I play mostly puzzle games. It requires a lot of thought to find well designed and intricate puzzles. I am also a fairly proficient programmer using Godot, though bugfixing can be quite annoying.
Q: Do you have any future plans?
A: I would like to get more into creating sound effects and music scores to improve the sound quality of my game. I would also be interested in looking at collaborating with more people in the future.
Leave a comment
Log in with itch.io to leave a comment.