#13 Zones: to drop or not to drop
Welcome to the thirteenth devlog!
One of the most important aspects of the game I haven’t talked about before, is the “zone”.
Every package goes from one zone (starting position) to another zone (destination).
In my code and project files, I named these pickup zones (where you pick up the package) and dropzones (where you drop the package). I don’t know why. They aren’t even the most convenient names, but they work well for me.
These zones had the following requirements:
- Be very clearly visible
- Check when a package is laying on top of it.
- Have quite a large margin (a big area where a package counts as delivered)
- Have its own color and shape that make it uniquely identifiable.
The final design
I went through a few quick ideas and possibilities, and decided to use the following technique:
- A “destination” is nothing more than an image laying flat on the ground. This gives me great flexibility, as I can change the image shape, rotate it, scale it, and put it anywhere I want. (It’s also cheap for performance.)
- This image currently consists of a pattern of package icons and diagonal lines. This works quite well, but it might change to something fancier/more beautiful in the future.
- Above this image is an Area (like with the pressure buttons from the previous devlog). This area covers the sprite and about 0.5 units above it. Any package that enters the area, immediately starts “pending for delivery”. And if the package stays in the area for 3 seconds, delivery was successful.
(If you look closely, you can also see a blue thin line in a rectangle around the zone. That’s the CollisionShape of the Area that detects packages.)
This technique is good for performance, clearly visible (especially because the image has a bright color and is unshaded, which means it is always regarded as “not in shadow”), and detects packages quickly. The area already registers a package a few milliseconds before it hits the ground, or if it’s still tumbling over, which feels nicer and more responsive than if the package was only registered when it laid flat on the dropzone.
Design decision #1
When delivery is successful, the package stays on the area (unlike most games where it would disappear or fade away), and turns static (and green). A delivered package, will stay where it is for the rest of the level, and will not be movable.
I decided to do this for several reasons:
- It adds a subtle strategic layer. As the level progresses, dropzones are filled, and you get less space to drop your package. In some cases, you need to think carefully about where you drop something, or you’re shooting yourself in the foot because future packages can’t be easily delivered.
- It can be used to your advantage. If you stack two packages, once they’ve become static, you can stand on top of them and maybe jump to a place that is otherwise unreachable! In some cases, I’ve been able to build a bridge of packages over a small gap.
- It feels better. In real life, a package also wouldn’t suddenly disappear. It would stay where it is (until the recipient picked it up and brought it inside/did something with it). As the level progresses, you now get a sense of achievement and persistency: look at all these dropzones you helped fill up!
So far, players have been loving and hating this mechanic at different times, which is exactly what I want :p
Design decision #2
I needed a way to make the zones stand out even more, as well as a good way to show the SHAPE of the zone.
Eventually, I decided on a sort of “street sign” (or “totem pole”) technique: in the center of every zone is a sign that shows the zone shape. This sign is simply part of the world, which means packages collide with it.
I’m in doubt about this system. On one hand, it feels very natural and works well in most cases. As long as you’re not too far away, you can see the shape of the zone. The sign is immediately recognizable and just feels like part of the terrain.
On the other hand, if you happen to be on the wrong side, you cannot see the shape at all. There are times when the sign is just extremely annoying, as it bounces a carefully delivered package away from the zone. (Also, the sign isn’t modeled very well, I can do better now.)
For now, the system stays in place. But in the future, I might create something that looks better, isn’t too annoying, and can show the zone shape from all directions.
There can be any number of zones in a level. Right now, I expect the average number of zones to be 4 or 5, but I don’t know how things will pan out.
As such, it’s not very useful to use a fixed list of colors. Instead, I took some time to learn about “equidistant colors”: how to generate N colors that are as unique/different as possible.
The default formulas I found made the colors very soft, which looks great and cute, but made the zones unrecognizable. So I cranked up the saturation and brightness to maximum, and that works great so far.
I get beautiful colors, which are easy to recognize, no matter the number of zones.
NOTE: By this time, I realized that I had many colors in the game … how was I going to give unique colors to players as well? Would I just generate even more equidistant colors? I decided to do something else instead for the player: make them recognizable by number and pattern. I’ll explain this properly in a future devlog.
Navigation between zones
Some devlogs ago, I mentioned that I tried to make the computer automatically calculate the distance (and route) between two zones. I needed this to calculate the estimated time it would take players to complete a delivery. I tried Godot’s built-in nodes (Navigation and NavigationMeshInstance), but they did nothing for me.
But my brain doesn’t like giving up. The next morning I awoke with a memory I didn’t know I had: the Godot docs mentioned something about a native A* implementation in their code. (A* is one of the most common pathfinding algorithms in games. It’s versatile, it’s fast, it’s not too hard to work with.)
So I checked it out, wrote some code, and voila! I now have a script that creates an A* graph from the given level map, and can return the path between two points at any time. Because this is implemented in Godot Engine itself, it’s incredibly fast. You don’t know how happy I am about that, because I know that pathfinding can easily be a performance hog.
So far, even calculating the path almost every frame is no problem. In the final game, I might only need to calculate paths at the start and a few times during the level, so that’s all fine.
Well, this time I really just explained how I already did things. But I hope this gave a clear idea about how zones work (both their functionality and visual representation). Next devlog, I will talk about something else that I should have talked about sooner: making unique players that are easy to follow/see at all times. I also got the chance to playtest some more – I’ll give the results in the next devlog.
Get Package Party
Leave a comment
Log in with itch.io to leave a comment.