
Own Goals Not Allowed
Welcome to this really short devlog for my game âOwn Goals Not Allowedâ.
(Previously called Splitball in my notes. Then it was called âNo Own Goals Allowedâ, but the combination of No Own is just hard to read and pronounce.)
Itâs my first âweekend projectâ. Previously, I basically worked on my main project(s) all days of the week, but it was just burning me out. So from now on, Iâm trying to switch it up during the weekends.
For that, I needed (game) ideas that were short and simple enough that I can make them in 2-3 days. And theyâd actually be finished and fully playable.
Whatâs the idea?
Youâre playing a very simplified game of soccer. Two goals on opposing sides. Walk into the ball to hit it. Score in your opponentâs goal.
Simple, right?
But hereâs the twist: youâre not playing one game ⌠youâre playing multiple at the same time.
When you move up (for example), your character moves up in all fields.
This seemed like a simple idea that would work wonders, as itâs really hard to keep track of multiple fields. And itâs even harder to not accidentally score own goals.
Thatâs where the second rule comes from: own goals are 10 points for the opponent. (Which is, you know, a lot more than 1 point.)
Thatâs the whole idea! Letâs start.
Day 1: Basics
I laid down the basic components/systems I needed and powered through them. (I have enough confidence in my game creation skills at this point that I donât bother testing at this stage. Maybe thatâs a mistake, but it does make it fast.)
Field Manager: Can add/remove fields and position them correctly (centered on the screen). Also has helper functions for aggregating data about fields, most notably the score.
Field: dynamically creates boundaries, but leaves a gap at the top/bottom for a goal. Most work went into making this look acceptable. As fields, goals, etcetera can be any size, I couldnât just pre-create a few beautiful sprites and slap them on there.
I spent quite some time making it obvious which goal was which, as that seemed important :p If the top goal is from team 0, almost everything at the top of the field is colored the same way. But not exactly everything, as that looked ugly and too âharshâ. The field is still just green.
Balls: just a RigidBody with high bounciness. It has code to:
Cap its velocity (so it never comes to a stop, but also never goes to fast)
Teleport (e.g. after someone scores, the ball resets)
Track who was the last player to touch it (to figure out if something was an own goal)
Players: just a RigidBody again with high bounciness. It has code to:
- Move (slightly momentum-based: a small period where it speeds up/slows down before reaching the desired speed)
Erm, yeah, thatâs it. Simple idea, right?
Day 1: Input -> Fields
When created, fields spawn a ball and a player character for each player.
The ball gets a slight push, but otherwise is completely controlled by physics and its own script.
The players are, obviously, controlled by you.
A global âinputâ script polls input for all players, then sends it through to all the fields, who send it through to their player characters.
This is way cheaper than adding a separate input script/module to every instance of every player. Itâs also more flexible for me, as I can (for example) completely cut off a player with a single line from this script.
One downside? Players canât randomly walk to a different field. (Which they could before, as the goals are open.) But that was never a planned feature anyway.
Day 1: Checking goals
Surprisingly, checking whether an object has fully crossed a line, and then resetting it, is more annoying than you think.
Using an Area? Youâd need to position it precisely so it triggers when the ball is over the line.
What if a player touches the ball again when itâs inside the goal?
If the ball immediately resets, it leads to âinsta-goalsâ for the opponent, as you still need to walk back after scoring.
Etcetera.
I chose to:
Do a basic y-coordinate check: if ball is higher than goal line, someone scored.
When a ball is reset, it is âfrozenâ for a second or so.
Sometimes, the ball also, erm, wouldnât reset. Iâm at my wits end on this one and think itâs just a bug from the (altogether quite buggy) physics engine, so I ended up just completely destroying the ball when scored and placing a new one. Not optimal, but who cares.
Day 1: Extra Rules
After testing this, the idea was working, but far from really fun.
Fields were a bit crowded on high player counts. And most people, intuitively, still focused on one field only.
I added two simple rules to make the game asymmetrical:
When you score, that character is removed from that field. (Unless itâs the last one you have.)
When you get scored on, a player on your team thatâs not on the field yet, is added.
In other words, if one team does great on a field, then itâs slowly hindered while the other team is helped. With this system, you canât focus on one field, as thereâs a low chance everyone is there.
Day 1: Visuals
The rest of this day was spent
Adding loads of visuals, indicators, feedback. (With a game happening on multiple fields, you really need this to make sense of it all.)
Finding bugs/issues/doubts and trying to find ways to fix them.
For example, everything in the game is already animated. (When a field appears, it does a short tween. When a player appears, same thing. When score changes, the text has a flashy/bouncy tween as well.)
Players/balls have a particle trail when walking. Thereâs a wild explosion on goals (and game over).
I added a simple Game Over and Pause screen to close the game loop. (Always important to do that quickly: being able to start, play, end, then restart the game. Itâs the loop that makes a game, well, a game.)
The goals were a bit empty being holes, so I spent way too much time programming a bouncy/wavy line ⌠that reacts to a goal. (So when the ball flies in, the line displaces as if the ball caused it, wobbling for a few seconds afterwards. Looks cool, not sure if it was worth the time though :p)
Day 1: The Issues
Here are the issues with which I went to bed:
I need some simple rule for adding/removing fields during the game.
Forcefully moving physics objects (outside the physics simulation) is bad. So when a field is added, I shouldnât have to move other fields to make space/center it ⌠but how?
I needed a way for players to manually move between fields. (Adds more strategy, fits the theme of the game, helps soften annoying situations where one team is completely wiped from a field.)
Right now, âgoal blockingâ is a pretty viable strategy. Just place all bodies you have in front of the goal and done. How to prevent this?
The game needs just a bit more than it currently is.
Day 2: Solutions to Issues
Sleeping is a good thing.
Field Changes
Solution #1: fields are added/removed when somebody own goals. Adds to the theme, it happens enough (in my testing) to make it worth it, but not so often that you go crazy from all the fields.
(With the space we have, this means the number of fields is wobbling between 2-4, which I think is a good balance.)
Add a Camera
Solution #2: use the age-old trick of âdonât move the world, move a camera in the opposite directionâ. Fields are simply added to the end of the current field list, then the camera is moved to fit them on-screen. (So existing fields are never moved.)
Teleports
Solution #3: gates/teleports. But I didnât want to make them really prominent features of the map, as weâre already out of space, and if players start teleporting too much the game is just chaos.
Instead, thereâs one gate in the left wall of a field, and one in the right. Obviously, the right teleport of a field brings you to the left one of the field next to it.
As such, they basically explain themselves and you know exactly where you go. You can also accidentally use one, but not so easy you get annoyed.
(Because itâs a one-time teleport, that is something the physics engine can handle if I code it properly.)
Varying the Fields
Solution #4: Of course, the whole idea of the game itself already softens the âgoal blockingâ problem.
Because you canât position characters individually, itâs really hard to block the goal in all fields.
Because own goals carry such a penalty, you donât want to be close to your goal and accidentally hit it last.
But itâs not enough. Here are ways to shake things up, hopefully enough to prevent this âŚ
Goal size and position are somewhat random.
Fields can be rotated (so that the other team is at the top)!
When you are close to your goal ⌠it grows in size. (And when you are far it shrinks.)
That last rule is a bit exotic, but it fits well. It also punishes being âtoo presentâ on one field, because thatâd mean thereâs no space to stay away from your goal.
Powerups
Solution #5: well ⌠powerups! Itâs a game about moving. All you can do is determine where you are and where you are not.
Those games are perfectly suited for powerups that you grab by being somewhere, or avoid by purposely not going there.
I had some doubts about the implementation. Wouldnât it be too easy to accidentally grab one if they triggered so easily?
But in the end, I applied the lessons I learned from previous games. If you add powerups, they should be âŚ
Rare
So impactful it feels unfair
Immediately clear on first sight
If theyâre not rare, you shouldâve just made their effect a permanent/global thing, because being individual powerups is senseless.
If theyâre not impactful, players donât care about picking them up.
If theyâre not immediately clear, players will be confused about what happens, or stop playing for ten seconds to figure it out.
To finish it off, one last rule to tie it all together: picking up a powerup in one field activates it for all your characters (in all fields).
(Weâre still in the first hour of day 2, Iâm just writing down these ideas, then Iâll implement them. Which is where weâre going now!)
Day 2: Gates & Fields
These were quite quick to implement, but revealed their subtle issues later on (as they always do).
Many bugs came from the fact that âCollisions/Events could still happen while a field was being removed.â (What if a player enters a teleport to a field right when itâs destroying itself? What if someone scores another own goal on a field removing itself, and it comes back?)
Once I realized this, I added a simple variable âbusy_removingâ, and when true, everything just stops and calls to events are ignored.
When a field is removed, I also forgot that:
Its score would also be destroyed. Solution? Keep a âpermanent scoreâ counter as well. When a field is removed, add its values to that, so its remembered from now on.
A player might end up without characters. Solution? Check this, if so, add a random one to a random other field.
The links between gates wouldnât work anymore. Solution? Just call for a complete ârelinkâ of all existing fields on removal.
(General rule: itâs often way easier to just recalculate/redo/update everything when any change happens. Way less error prone, more flexible and robust in the long run. Yes, donât do this when the update is very expensive, but if thatâs the case, the algorithm youâre writing is probably at the core of your game and you should take more care anyway.)
Day 2: Input Screen
I quickly decided that an in-game tutorial with several images popping-up just wasnât a good idea.
If I wanted to explain all the rules, itâd be too much information, not in the spirit of the game. But not explaining anything also isnât great.
So, on the main screen, thereâs a big image on the left with just 4 short lines and example images, explaining the core:
Hit the ball
Score goals
Donât score own goals
We play until X points
Thatâs really all you need to know to start playing. The rest shows itself during gameplay.
On the right, we have the login screens. To make my 2-day deadline, I decided to keep it very simple. All you can do is:
Add a new player/device
Ready yourself ( => once everyone is ready, the game starts)
Remove yourself
But interactive menus are awesome, so this is one as well. When logged in, you get a player character (confined to your box). The keys for movement are shown in the background and you can move around. In fact, to ready/remove you must move yourself to that area of the login screen.
This makes the menu much more lively, fun, unique. But it also teaches the buttons!
Great. (I had some trouble with removing players not updating the background device dictionary correctly, but that turned out to be a bug with my general library. I had to âportâ it to Godot 4, from Godot 3, and a few mistakes slipped in.)
This means the game is fully playable. You can start, login, learn the buttons/objective, play the whole game, and someone wins in the end. (I could publish it like this, if I wanted.)
Day 2: Powerups
I did a playtest for a different game (my main project) around this time. So, no progress for a few hours here, but lots of insight on how to improve that other project.
Anyway, itâs evening now. Letâs try to pump out the powerup system and a few good ones.
Very quickly, I realized that powerups across the field just werenât a good idea. It was so easy to grab one ⌠and even easier to accidentally grab one and donât know what the hell just happened, because you werenât looking at that field
Solution 1: Make them quite small and place them in the corners => only a weak fix
Solution 2: Powerups are yours by hitting them with the ball => harder to do, encourages looking for who last touched a ball, but still not a complete fix.
Solution 3: powerups spawn between teleports. In other words, when you teleport from field A to field B, you get the powerup showing between them.
Very thematic, encourages/discourages teleporting at different moments, harder to do accidentally, and more visible. (Thereâs nothing else showing in that space.)
Thatâs what I went with.
Sounds easier than it is to implement. (Because we have to find pairs of gates that are not already being used, which are not at the extreme of the map, and remove them properly when their fields are removed, as well as reposition the powerup properly when the gates reposition.) But I got there in the end.
Which powerups sound fun?
I saw several categories:
Those that allow defending/attacking in the field to your right or to your left. In other words, do something about a field where you are not. (I can just draw an arrow on those powerups and flip it when needed.)
Those that mess with your movement and ball hits (as that is all you have, and it transfers well to all your characters)
Those that give variation to prevent many issues I mentioned. (Camping on your goal line, focusing on one field only, etcetera.)
I was running out of time, though, and I realized I actually didnât have that many great ideas for this. So I kept the list small.
Eventually, my creative juices were just depleted, so I went to bed with some work on this left to go.
Day 3: Finishing touches
The next day, I woke up and immediately drew all the icons and finished the missing powerups.
Then I powered through a list of small issues or improvements, which I thought were important enough to work on. (For example: ramps in the corners to prevent balls getting stuck there.)
Which left me with some polishing left to do:
Some sound effects and something resembling a soundtrack
Some animations/tweens/particles where they were missing (mostly the newer stuff I implemented)
This was quite some hours of work. Which taught me my next weekend project should be even simpler and shorter than this one.
Day 3: Bots?
And lastly a question: do I add bots to this game? (Limiting the game to 2+ players only is always a great way to ensure almost nobody will or can try it.)
Itâs not really trivial to add bots, but also not the hardest thing in the world.
So I pulled the trigger and did it, as the final task for this project.
In the main menu, you can turn on âbotsâ.
All players are in the same team. At game start, as many unique âbotsâ are started as there are players.
Each bot checks for the closest ball and tries to get behind it. (Between the ballâs trajectory and their goal.)
When spread over multiple fields, the bot focuses on the closest ball first.
Not great, but itâs something.
Day 3: Mustnât forget
Marketing. Of course, Iâm not talking about really marketing this game, but I also canât just upload it without a piece of text or a few screenshots.
So another half hour was spent getting those screenshots, writing that text, making a logo thatâs somewhat decent.
And with that, we could finally, definitively, upload this game and call it done.
Conclusion
Thatâs it. My first âweekend projectâ. A very simple game about playing soccer on multiple fields simultaneously.
Still took too long and became too complex in certain parts. But all in all, especially for me and my bad habit of overscoping, it was a great training in keeping something small and finishing it in a really short time.
It was also a nice diversion from my regular, bigger projects. And another idea thatâs been bugging the back of my mind for weeks that I can now put to rest with a satisfied heart.
(Forgot to mention: I also tried a different structure for organizing projects in this one. Not sure if I like it better, need more projects to determine that. But it was, again, something different and something educational.)
The end result is ⌠fine, I guess. But thatâs what I always say about my own work :p
Until the next devlog,
Pandaqi
An update
Before releasing, I actually did come back and fix some issues. It seemed too important not to do.
The biggest ones:
Overcrowding: if multiple players just gang up on you or the ball, they get total control, and thereâs nothing you can do.
Corners: same thing. Ball is in a corner? Someone else is there as well? Itâs basically stuck and wonât get out.
How to solve this?
Solution 1: We just make the ball much bigger and the players much smaller. A player canât stop a ball thatâs 10 times its size. Itâs harder to provide a brick wall if itâs really thin.
Solution 2: Add a small âstunâ when players collide.
Solution 3: Make corners much bouncier, so players/balls fly away from it anyhow.
Solution 4: And then allow the ball to have more influence on players, pushing them out the way. (Now players are basically much heavier and in control.)
Solution 5: Add random obstacles inside the fields to prevent players from moving just anywhere, or moving like a gang/group.
In general, I already wanted to increase the size of the field relative to the ball/players by quite a bit. Currently it was a bit cramped and left too little options.
So these changes should go hand in hand.
In the end, I decided to simplify/streamline these ideas (as I noticed some extra problems with them), with the simple rule: when you hit the ball/another player, you bounce away from it.
This means you simply canât overcrowd, or just walk the ball into the goal, as youâre being bounced around the place. By tweaking the physics a bit, I was able to make this feel nice, and balance chaos with strategy/control.
Lastly, I added some âquality of lifeâ features:
Particles when you grab a powerup (or a powerup someone grabbed affects you)
Text feedback with a hint as to what the powerup does
A graphic with an overview of powerups. (Not in-game, but useful for myself and in the marketing.)
More powerups to balance it all.
Instead of making corners âsuper bouncyâ, I simply gave them a timer that pushes away everything near it once a second. When that happens, it plays a nice animation of a growing circle, somewhat âexplainingâ to players what happens there.
Also, because I opened the project in a newer version of the software, it unexpectedly broke some stuff. So I had to waste some time figuring out exactly what broke and why. Among those were bots: suddenly they walked away from the ball instead of towards it :p
But then I decided it was really done. I tested it with some people, used that footage for trailer/screenshots, and this project is done!