Worked on general accessibility and minor irritating bugs
Added a main menu and game over menus
Added a second test level
Reorganized the project a couple of times
Generally weekends are not a good time for me, so that’s a reasonably good progress considering. I am not happy with all the hacks and cheats I am allowing myself to put in the code. I’m not used to this methodology at all, but it’s all for the sake of efficiency, we’ll fix that tomorrow :)
Today was mostly dedicated to visuals. I started the day with 3 new block types:
ground/grass – which replaced the previous giant ground box, and allowed for making holes
water – so that the holes don’t look so awkward (its an impassible indestructible block, which allows for bullets to fly trough)
crates – for now they just take two hits, jiggle a bit and get destroyed (a little bit like bricks), but I have huge plans for them
Then I decided to add some texture, because plain colors were starting to look boring. I also meddled with Unity animations and finally got the hang of them (I think). Minor game-play tweaks, minor setting adjustments here and there, but nothing really significant on the functional side.
Well technically 3 and a half. I started this project on Sunday (15th of September). Lest see if we can finish it in one month :) I’ve been wanting to learn Unity for quite a while now, especially because every client seems to demand it nowadays (so many people develop games for the Android). Usually I would go around and try to get inspiration from a number of games, movies, books or plain concepts, then try to blend them and try to get something original. This time around though I decided simply to make a clone of an old Nintendo classic (clones are something I generally despise). No, it’s not Mario.
It’s BattleCity
One of the greatest things about NES games is that they are inherently simple (due to hardware limitations), a tiny set of rules with small number of objects and simple interactions between them. With such constraints it is hard to make something monstrous which goes out of control and never sees the light of day.
Lets see if we can pull this off with Unity.
Up until now I had only launched Unity a couple of times, just to test the waters, but never done anything serious with it.
Mind you, I have been crating games since I was 15, every experienced software developer would say, once you’ve learned a couple of languages it no longer matters what you write code in, C# is no exception (it’s essentially “C++ meets Java”). The user interface and Unity’s API and features was something I had to get more familiar with, so half of the time I spent in tutorials. My impression of Unity is that it’s one of the most powerful RAD tools for game development. Seriously, for a person who’s never used a professional editor with a powerful engine it’s just mind-blowing, and that wasn’t one of the things they thought at my uni.
What used to baffle me about it was the component based architecture, normally I would wrinkle and try to figure out how to make best use of a tool, so that my code can be reused later on (I tend to over-think software design and obsess with quality), this time I decided to just go with it and optimize, redesign and generalize later. After all the generally accepted right way to get things done is the lazy way – YAGNI and “don’t fix it if it ain’t broken”.
Mah game
Surprisingly I was able to prototype a somewhat complete 3D clone in those three days (in terms of mechanics anyways). But why not, if I can make a Ludum Dare game in a weekend using Game Maker Studio, why should I not be able to create a complete game in the same amount of time with Unity.I decided not to deviate from the original game too much, at least at first with an imposed constraint that I can remove features, but not add new ones, so that I can keep the number under control while learning. That turned out to be a little harder than I though (and my game is already starting to differ from its ancestor), but I’m trying to tame my imagination and get to a finish point this week. The current feature set includes:
Indestructible blocks (steel) and destructible blocks (brick blocks made out of 8 bricks)
Bush blocks – hide tanks
Holes – tanks cannot pass through them (like the water in the original)
Enemy and Player tank spawners (each being able to spawn and upkeep a limited amount of tanks)
Simple enemy AI – enemy tanks just go around and shoot randomly… like cockroaches with shotguns
Additionally
Tanks are able to move and shoot in 8 directions
Provisions have been made for multiple teams (can you feel the PvP :))
Some work has been made to support Z layers (Y in unity), so that the gameplay is actually 3D (and not just the graphics)
Besides this I have a growing number of features I want to add, but I’m cautious not to start on them too early. There are no power-ups yet and I may or may not add them in the first version.
Historically my individual projects have suffered from a syndrome called “feature creeps”, they always start small but grow exponentially in complexity until the point they are impossible to complete. Other times immense amount of time gets spent on features which turn out to be unimportant. Either way the finish line remains out of sight and the passion that started the project eventually burns out.
A healthy response to a problem is to acknowledge that you are not the first person to have experienced it. Others have probably found the solution, in which case Google becomes your best friend.
Here are some resources that aim to answer the question:
This morning was a morning well spent, despite being constantly distracted I managed to roll up my sleeves and do a lua function parser for Notepad++ (rather than wasting my time with actual work). In the process I learned that a) Notepad++ function list doesn’t support lua by default, you have to add them manually, b) the function list looks very pretty and allows not only function but class definitions as well c) regex have lookaheads, lookbacks and K.
I used this StackOverflow question as a starting point, but noticed that the solution that best matched my situation ignores table functions. This was unacceptable because most of my code tends to be structured in classes. After fiddling around with it I got it just about right.
The first thing to do is locate functionList.xml and open it. It may reside in the installation directory or %APPDATA%Notepad++, depending on your installation. Open it and add to <associationMap> the the folloing:
This will group together functions defined as <class>.<function> and <class>:<function> (or <class>.<class>./:<function>) and place them in their appropriate classes in the Function List viewer. It will also capture lose global or local functions and display them as normal. It will unfortunately accept illegal constructs and definitions, but you get compile errors for those.
It’s been almost a year since I officially started the project, although I haven’t been working on it full-time (I had to leave the project in July and only picked it back up this January). I really wanted to keep a full development log, but got carried away developing… and for a significant amount of time I had no internet connection, but enough excuses, lets do a quick (edit: I mean long) recap…
TDD vs Prototyping
TDD Sucked
My last post was in May. The first change that occurred after I came back to it was to abandon test-driven development. Test driven development is great when you have a specification and a good idea of how things should work. It shined when I was writing physics because I had already done the research and had a very specific thing that needed implementing, so TDD allowed me to write code and test every edge case, it put in a mindset where I was thinking about the code critically. But when I wanted to play with new ideas it was stiffening, I would have to write a test, write an implementation, write more test, fix bugs only to find that the idea sucked and I had to throw away all that work. It was a major buzz-kill and at times it felt like I was making negative progress (I didn’t even consider that was possible). Other way it was a hinderance was when I needed to make tiny changes and tweak stuff, often time I had to also make dozens of other changes to all the test cases as well. As much as I liked the idea of TDD it was clear it had to die.
Rapid Prototyping
Enter rapid prototyping… once I threw unit testing out of window things got wild. In a matter of a few hours there were tops chasing each other and clashing in battles, going in and out of the arena. I was just blurting out code, testing, fixing and refining and doing rapid iterations like this let me drive the development, I got to see what ideas worked and what didn’t, it felt like my productivity went through the roof. And the best part is I decided to not treat this as experimental code that I have to throw away, this could be my production – write messy functions throw in magic numbers see how stuff works, find a nice set of operations and values that make the game fun to play and then refactor everything and clean it up. It went from “test first” to “implementation first” approach, but implementation wasn’t even the focus anymore, it was the game – I made a conscious choice not to care about the code until later and it paid off.
In hindsight I think I was misusing TDD, it definitely has its place in the world, but it’s not something you can force onto every project. Game development is at its best when it is able to cycle through ideas fast and organically grow fun experiences without unnecessary friction.
Model View Controller
The first milestone was making the dyzx human controlled, but later I added some basic AI that could chase, go random and/or avoid being kicked out. At all times I tried to stick to MVC model (model-view-controller) and that came with many benefits.
Model
All gameplay rules and abstract representations of game objects strictly live inside the “model”. Anything physics, damage or abilities related for instance is part of the model, and the model is indiscriminate of how things look or sound, it also doesn’t care about how inputs are mapped or what AI are targeting, it merely runs a simulation. If you take away the rendering and the logistic of controlling, the model will still happily run by itself which is great because now you can slap it on a headless server and it will be fine. Or you can run it at 1000x speed to simulate battles (to train AI, idunno…). The model is also independent of Love2D as it doesn’t need any of its functionality (it is pure lua), so if I wanted I could move it to a 3D engine, and I would have to rewrite the controller and the view layers but the core gameplay is already there and functional.
Controller
The controller part is where human input and AI-s operate, both of them drive the dyzk model by setting a “control vector” that is the only input the model needs. The player controller handles remapping keys, joystick axes, mouse and touch input adjusting it relative to the camera and feeding it into the player’s own dyzk model. Likewise the ai controller does its “thinking” based on where other dyzx are where it wishes to go and some random randomness and feeds that into the model. The controller can reference the model as much as it needs since it often needs to know what the current game state is in order to make appropriate decisions, it doesn’t however necessarily care about the view.
View
The view is the thing that is concerned with how things look and sound like, it’s what handles the rendering of the dyzx the amount of spin blur the shading of the arena, etc… it is the purely cosmetic part of the game. It can references both the model and the controller as it is the layer on top of everything, it needs to know where things are what state they’re in or where they’re going it also needs to provide feedback to what inputs are pressed or what are doing (even when those don’t result in changes to the game state).
Evolution of Game
Arena rendering
The arena had a pretty nice visual evolution. At first it was darkness (just a normal map), the first natural step after that was to use that normal map to lit it up, and so there was (directional) light… just simple diffuse shading but it does wonders. Eventually I added point lights as well these would spawn when dyzx clash along with some sparks lines. I did all that in shaders and even though we’re just working in 2D here it helped make things look more three dimensional.
There was one more sort of significant change for the looks of the arena – it used to use a normal map generate from a heightmap image, the algorithm that generates it works fine for gameplay but visually it results in some nasty staircasing due to pixels having discrete values (i.e. quantization error). I really didn’t like that so I tried to fix it with a better algorithm – I needed a way to fit a smooth curve onto discrete points and the obvious choice was to use a Bezier, that was better but still not ideal (I probably could have done a better job). I decided to explore a different route – procedural heightmap. In a nutshelf to generate a height map you just need to call a sampling function, give it coordinates and it spews out a height, the kicker is both the coordinates and the height can be floating point numbers. We’re not bound to raster values anymore and the beauty of it is that to sample an image we just implement the same function as our classic image sampler. After all I still want to support image heightmap and allow people to make their own arenas in photoshop, so I will revisit normal map generation from grayscale images later again.
I made a procedural sampler for the test map (the dome with the bumps) mainly just using a couple of sine, cosines and a for loop for the bumps. Here I realized another advantage procedural sampler has over an image sampler – it is very easy to compose multiple samplers and use parameters. I could have a plain dome, a dome with 8 small bumps, a dome with 4 large bumps, a dome with a dome inside it, possibilities were endless and I didn’t need to create new assets, just link a few functions and set a few parameters. Procedural heightmaps are here to stay.
Out of Arena + Holes
But more interesting than the visuals were the gameplay aspects of the arena. At first the dyzx (tops) were merely controlled by the normal map, but beyond that the arena didn’t have any function. First I implemented the out of arena rule – when dyzx leave the stadium they die instantly, so this became one of the win/lose conditions. With that came the idea of holes and conveniently enough I could implement them the same way. Because everything the arena does is either based on its normal map or its height map all I need to do was designate a height value of 0 to mean “hole”, naturally everything outside the arena is also hole, when a dyzk is over a hole it dies (simples).
Arena Collision + Walls
Later on I implemented another rule – arena collision. Up until that point dyzx were only able to collide with other dyzx, but there was nothing specifically preventing them from bumping into the terrain (by the default rules they would just elevate). Adding that was not difficult, the collision is again based on the height map. All I needed to do was check the height of the arena ahead of where a dyzk is travelling – we already know the dyzk’s location, its velocity and its radius, which meant I knew the exact location where I need to sample the arena each frame and check if that is higher than the dyzk, it was a no brainer. But when I was testing I found that sometimes it would miss the collision when dyzx were moving too fast so I refined it a little such that it a line instead of a single point (taking into account speed and where next frame will take us). As for collision resolution, we just treat the arena as an infinite mass object and pretty much use the same logic as we do for dyzk-dyzk resolution.
The arena collision was a great tool, I could use it to make some interesting stages and could also strategically place walls next to the edges of the arena (or near holes) to prevent players from falling out. But now… there was another “bug” I found with it. I noticed that when the dyzk goes straight forward head on into a wall, it would bump into the terrain as intended, however it was possible to come at a sloped wall from the side at such an angle collision would not trigger and that resulted in the coolest unintended mechanic – the wall ride!
That’s when it dawned on me the arena was not just a container for dyzx to battle, it was more than that – it was an obstacle course for doing cool tricks and moving around in style – a skate park if you will. The interaction between a dyzk and the arena could be fun on its own, and if it was that would mean so much more for the battles, now there is an extra layer of skill to master that complements the core – efficiently getting to or away from your opponents and using the terrain to your advantage would add more depth, so that got me thinking in what other ways I could utilize the arena…
3D Gameplay
Meet the third dimension! As I mentioned earlier the game was 2D, with the exception of the height map there was never really a need for a third coordinate, dyzx only ever needed an X and a Y coordinate and whenever I needed a Z would just sample the arena – strictly speaking they were glued to the ground, and that made sense. I avoided using Z for a good reason – it was hard to convey depth when you have a top-down orthographic camera looking at 2D circles on a shaded quad. However the more I thought about it the more I wanted the Z, so I added it. It allowed me to implement a jumping ability which was a cool way to dodge an attack, jump over an obstacle or get someplace higher, it also let me add a “catch air” mechanic – dyzx carry over vertical momentum when driving of ramps which allows them to fly off for a little before landing, and you know what means – you can now jump over holes! (actually I had to fix holes to not kill you if you’re in the air :D).
The problem with perceiving “depth” was still there though, all I had just done was to add a “z” coordinate to the model, I still needed to convey that to the players, and that’s when it got a little tricky.
Fake 3D Rendering
I couldn’t really use shadows, as some 2.5D games have done, I thought about using an overlay (a circle that gets bigger or a progress/jump bar) but that would look weird too. Instead I opted for another solution – fake perspective. So, you know how things that are closer to your face appear to be bigger than things that are further, even when they are the same size – that is true perspective. Fake perspective is when things that are closer to your face are actually bigger than those further. I scaled dyzks based on their Z coordinate – they wouldn’t be offset to the side, they would just be bigger, but that looked perfectly convincing and sold the idea of depth. This is what I wanted, only problem with that however was that this scaling was not purely visual, in order for collisions to continue to work I needed to scale the model. And that’s what I did (but deep down I knew it was a hack). The game now looked even more 3D, even though it was just small tricks like shading, skewing and fake perspective.
I also tried implementing true perspective (those attempts failed). True perspective worked great for the dyzx; without me having to change their model they looked accurately in 3D. The main issue was the arena – in true perspective each point has to be offset according to the heightmap, which… fine… we can do in code correctly but it has to be done every time the camera moves if I didn’t want it to look very off and skewed, which is computationally expensive (trust me I tried it). The other option is to use paralax mapping in the shader, it achieves the same result, but to make sure the arena self occludes correctly I had to make it overly complex and again was too slow. But even more than that I had to make sure the arena can now occlude the dyzx, up until that point I never had to worry about that… so I would need to introduce a depth buffer. Needless to say I gave up on the idea. I dabbled with it, but it wasn’t worth it.
Here’s a video that shows some bits:
The Future
There is still a whole lot more to do. I’ll be really happy once I manage to get online multiplayer working (but it will probably be some time before that happens).
I am having some doubts about continuing development in Love2D however. I love lua and love2D because of they are really cute and code is portable (it just runs on VM and in theory can run on any platform), but the reality of things is that love2D is not officially ported on many platforms, so there will be a lot of legwork to get it working on consoles. Also there are less available code libraries.
Having just finished polishing parts of the gameplay and implementing UI system I came to realize how much code heavy Love2D is – it took me 3 weeks to make a simple (albeit fancy) main menu. Also despite coding carefully with optimisation in mind some things like image generation, processing and manipulation is kinda slow with Lua, so at some point I will need to move code to C++ anyway.
If I am to rewrite code I am starting to consider learning an industry standard engine (also thinking about employability skills, lua is not very hot on the job market). I want to learn Unity and continue this project there, but if so I want to make some smaller games first to avoid making mistakes on this project that I will have to go back and fix, as this is the game I really want to make but I want to make it right.
No more exams, no more side distractions, no more time wasters… I know I’ve been saying that for over a month now, but I hope this is the last time I say it.
Unity’s support for android (and iOS) is now free and I’ve been postponing it, but I think it’s high time I actually learned how to use unity, LOVE 2D is awesome (it’s 2d, it’s open source and it’s lua based, what’s not to like) but it’s platform support is still lacking and I was hoping to be able to make games for OUYA by this summer.
Unity’s 3D and even though I don’t particularly mind 3D games I know from experience that they are harder to produce, and not just the art, but the code, and usually 3D is an unnecessary complication in terms of mechanics (few games really benefit from the 3rd dimension).
I also took too long before I started serious work on the Battle Dyzx project, and lost interest, so I’ll drop it (and come back at some time later). I’m starting a strategy game with dice, which I do not have a name for yet. I’ll need to detail the rules in another post, but the main idea is that it is based on constructing a set of dice and cards and reading and manipulating probability in order to win. It should be a game which looks and feels like gambling, but is about making and controlling the odds rather than a series of random events. There are gonna be monsters too :)
Ok, time to do some management. University’s just ended… only formalities are left, which means no more deadlines and restrictions, I have all the time I need, and can use every hour of every day, so let’s make sure I do it efficiently.
A couple of other game ideas ended up in discussion – a traveling merchant in post-apocalyptic world. It was Emo’s idea which is why I was keen on continuing it, but we couldn’t get it to a point where it has any objectives or final goals, so it would end up being a toy and toys aren’t that fun. As it turns Emo wouldn’t be available in the following few months, he’s got a busy schedule, I alone wouldn’t attempt to tackle it especially when I haven’t got a clear idea of the gameplay nor have I prototyped it, besides I would lose interest if I’m not working in a team, therefore I shall continue with “Battle Dyzx” for now. The primary objective is to get a (incomplete) working version ASAP.
TDD is occasionally helpful, but very distracting and slows the process, I start to feel like it better to do RAD instead of XP. Next steps will be to properly address what needs to be done and try to plan at least a few weeks ahead.
Unity has announced that mobile games tools are now free, I have to absolutely learn how to use it and start using it. So there might be a slight change of plans. The game has to be 3D unity based!
21-26 May
This will be the basis for the multilayer and the battle system itself
Get a spinning disc working
integrate joypad control
make a server
have two discs remotely controlled on the same server
27 May – 2 June
Dedicate most of this to the battle system,
collisi0n
clashes
more physics battle mechanics
Later on start thinking about progression, how to improve the performance of tops over time, possibly without adding too many artificial numbers I would love to keep all data associated with the image only.
Top War sounds a little generic and uninspired, it was a placeholder after all.
After a giving it some thought I realized that a small flat circular object is not a top, but rather a disc. After tilting it a bit it looks even flatter than it should .
see what I mean? It’s flat : )
I could of course draw a line or a beam through the center of the image but that would be too easy. Instead I decided to declare the spinning objects to be discs. I thought disx sounds cool, after a while it turned into dizx and I though “I need to get a Y in there” so it became dyzx – seemed to be unique enough in google, especially in combination with “battle” it yelds no results, so I claimed it! :3
Did creating of a normal map from a depth mask yesterday, which will be used by the game physics. It was quite a challenge to get it right in the first place and then to get to perform well in lua (here’s the relevant source bit). Just for the fun of it I made the top follow the normals and this is the fruit of all that effort:
It still takes about 1 to 5 seconds to process a 1024×1024 image, but at least I’m sure it does it in the most optimal way :)
It is sort of important to save CPU cycles when doing physics stuff because all of this will have to be handled by the server. Love2D allows saving of image data so once computed it could be stored for later. And if bad comes to worse this can always be implemented in C…
Next step will be getting this tested and integrated in the trunk (boring stuff) and making of a server and a client.