Today after work I spent some hours working on my video game, so I figured I could blog about it here while it’s on my mind. Whenever I mention it in future blogs, I’ll just give a link to this post for the backstory on it.
I’m calling my video game ‘Omnia’, which is a latin word that means ‘All things’ or ‘Everything’. I named it that because its a fun project for me to work on “everything” I’ve wanted to see in a game, and try to demonstrate/practice “everything” I know how to do when it comes to programming. In the story of the game, you’re going to end up being the hero that saves “everything” – not just the world, or the universe, or the multiverse, but… everything. I don’t know, it just made sense when I thought of it so I kept rolling with it.
I worked on Omnia for a total of about 2 months, spread out over 6 years! That’s… a month of work in December 2013 to start it, another week or two in 2015 when I got bored, a week in 2019 when I stumbled across the code in a random folder, and now I worked on it this last week here in 2020 to take a break from school/responsibilities.
Thinking I’d keep working on it regularly back in 2013, I started making little YouTube videos to demonstrate my progress with it… calling it ‘Project Naturalist’ and posting as ‘Submodern studios’ so I didn’t have to use my real name. Weeks later I got my first real tech job and didn’t touch it for years!
So now that I’m busier than I’ve ever been, I figured it would be the perfect time to start working on Omnia again…
What did I work on today?
So – today I added a big task list of plans to the readme file in the game’s repository which you can see on its github repo here and I worked on rewriting the game engine to use JavaFX.
If you don’t code, that last sentence probably didn’t mean anything to you. I’ll explain some of it here so non-programmers might understand. Then I’ll go into some more detail about my plans for the game.
What’s a repo?
Video games are basically just fancy apps. Whether they run on a computer, a smart phone, or a PlayStation… at the core, they’re just another app. Apps are made with code and programmers keep track of their code in something called a repository. Repositories (or ‘repos’ for short) track the changes you make to your code over time. They make it easy to undo changes you’ve made to your code. They make it easy to have multiple people work on the same project without messing up each other’s work. They make stuff like fixing bugs (mistakes in your code) easier. They just improve a programmer’s life overall. Repositories, repos, are good.
What’s a github?
Github.com is a website that makes it easy to put your code repository online and share it with other people. I use it as a portfolio to showcase what I’ve worked on, and what I’m working on right now. When I work with other people on a project we’ll usually use github to organize our work.
What’s a readme file?
When you go to a repo page on github, and scroll down a little, you’ll usually see some description or info about the repository, the code in it, or the project. Here’s a screenshot of Omnia’s github page:
What you see there in that screenshot is a basic description of my video game project. It’s 2D, that means 2 dimensional. It’s ‘retro’, that means it looks and plays like an old video game from the 90s like something on Nintendo, Super Nintendo or Sega Genesis.
What’s a game engine?
Just like the engine of a car makes it go, so does the engine of a video game. It’s all the logic that lets the video game know what to show on the screen while you’re playing it. Every video game has an engine. Most older video games had engines that were designed specifically for that video game and wouldn’t work for other video games. Nowadays there are video game engines that can make a trillion different types of video games, available for anyone to use. Two of the most popular ones are called Unreal and Unity, but there are literally hundreds out there to choose from. If you want to create a video game but don’t want learn how to code, you can use one of those engines and be well on your way to getting started.
My main reason for making a video game is to get better at programming and practice it outside of work. So I’m making my own game engine to run Omnia. That means A LOT more work to create relatively simple things in the game, but I’ve found it to be a lot more fun and rewarding.
Every time you plat the game, the game engine works by going through a 4 step process.
- You set up all the stuff the game needs when it begins. Like the window, images, and other resources.
- You set up the actual game code. Like all the logic for the menus, levels, player, enemies, and set them up with their resources and images.
- You start the Game Loop. This is the most important part of most types of games. The loop is a repeating cycle that takes your controller/keyboard input, updates the game logic, and renders the game images to the screen. It does that cycle over and over, 60 times every second – or more in better performing games (120 times, 240 times, etc. every second).
- You get rid of all the stuff you setup in steps 1 and 2. This last step happens when the Game Loop ends and you’re turning off the game.
I made Omnia’s game engine by following a few YouTube tutorials and making changes to the code to get what I liked out of all of them. There are a bunch of different ways to do each of those 4 steps I just described, some of those ways seemed like they worked better than others. I tried to learn, experiment, test, and retest as much as I could.
What’s a Java?
Java is a programming language. It’s the programming language that Android devices run on and when you make a computer app with it, that computer app can run on many different types of computer operating systems. Even ATM machines, cable boxes, servers, and a ton of random devices and companies use Java. So even though Java isn’t the best language to use for game development (compared to C++ or C#), I’ve opted to use it for this game to practice. It’s really hard (almost impossible) to make incredible, realistic, modern, 3D video games with Java. That’s ok because this game isn’t like that. Java can make games with more simple graphics, but fun game systems/logic. A good example everyone uses to defend the idea of making a game with Java is Minecraft, because it was made with Java. When I started learning Java in 2013, Minecraft was really picking up popularity. Even though Minecraft was made by just one person, it’s become the best-selling video game of all time, and it was sold to Microsoft for $2.4 Billion in 2014. Either way, that’s not the point – if I can make a game that sells just 1 copy I’ll be happy.
What’s this games story?
Well, I don’t know yet. But I have a lot of ideas! I just need to start writing them down. Today I started writing down ideas for the world that the game is set in. I figured that would be a good first step toward a story. I put those ideas on this page: https://wforbes.net/omnia-story-notes .. I’ll probably change that page a lot, so if you’re reading this in the future, it’ll probably be different. Hello future person, I hope the future is nice and better than 2020 and you have many cute puppies and chocolate-chip cookie dough icecream.
So, without a story… what can you do in Omnia so far?
Not much! It’s really basic. That’s why for the longest time I just called it a ‘Game Engine’, not a ‘Game’. Here’s what it does so far….
When you launch the game, the Main Menu opens. The clouds in the background slowly move from right to left. You use the arrow keys to select an option from the menu:
This week I made it possible to open either the Top-Down game level or the Platformer game level from this Main Menu. Before, these engines had to be run separately. The goal is to switch between the levels directly, but doing this with the menu was an easier way to start working on and comparing the two types of game levels.
Top-Down game level
The Top-Down option opens a view of the game that looks like the first Zelda or Final Fantasy games from the late 80s, or the first Pokemon games on GameBoy:
In the screenshots, your character is the one with the name ‘ghosty’ above its head. You can walk around in this Top-Down view and as you move the game screen follows you. There’s one enemy ‘skele’ that can pace back and forth, or randomly wander the level. When you collide (walk into) the enemy, you both stop moving. When you stand in the water your character is submerged. The water animates to make it look like theres little waves. When you collide with the grey tiles they act like walls, you can’t walk over them.
Top-Down algorithm concepts
The level that you see in those screenshots was designed by a 64×64 pixel image – the level map, where each pixel represents a type of tile by what color it is. Green is grass, blue is water, grey is a wall:
The level rendering algorithm reads the pixels in that image and decides which type of tile to render for the level based on the pixel’s color. Then it gets the full graphic for the tile from these portions of the Spritesheet image:
The level rendering algorithm sees a light green pixel in the level map image, goes to get the third tile in the first row of the spritesheet, then renders it to the screen. It sees a blue pixel in the level map, and goes to get the first tile in the 5th row, then animates it with the other two tiles in the 5th row to create the wave effect. The pink tiles you see there aren’t being used yet. The algorithm sees Black, Dark Grey, Light Grey, and White on the spritesheet and translates those to any color you need when the game is running. So far I’ve used Black as transparent color.
The full spritesheet is 256×256 pixels and contains all the graphics for the Top-Down view of the game:
Here you see the tiles for the level up in the top left corner of the sheet, as well as a few sprites for different characters, fonts, and other random things. Since each tile is 8×8 pixels, the spritesheet has 32×32 tiles. Characters use 2×2 tiles each for all their walking positions. The algorithm mirrors these walking positions if they’re facing left. So there’s enough room for 32 different characters.
Why do it this way? It’s really efficient on storage and RAM. The Spritesheet takes up 4.2kb of space and the level map takes up 520 bytes. Even if this was expanded to a huge level with dozens of different tiles and hundreds of different character models, it’d be almost impossible for the storage requirements to go above 100kb. Even with hundreds of levels of this size, you’re looking at less than 20mb.
Storing the game’s graphics this way is also necessary because of the way the code renders the graphics. The rendering algorithm uses an array of integers to represent the pixels with color information bit-shifted into and out of each integer to store the Red, Green, and Blue data in it. It renders each individual pixel to an object in the code that represents the screen, then renders that object to the game canvas. It’s very different than other more simplistic algorithms I’ve seen for drawing graphics, but it’s fast and really efficient.
To render something on the screen, you give it the X and Y position on the level you want it to appear, what tile on the spritesheet to use (which is stored as a single number, you add the X tile position to the Y tile position multiplied by 32), the color information for that tile (stored into another bit-shifted integer that contains number rgb data of 4 different colors) and you can either mirror it in vertical or horizontal direction or you can scale it to appear larger on the screen.
So, it’s extremely easy to design new tiles and sprites… everything is so small and the details are so simple that quickly producing a lot of content quickly would be easy for people without many digital art skills. It performs very quickly and doesn’t use very much memory too. The trade-off is that it’s more challenging to code this way in comparison to other techniques. For example, to have the player do anything aside from walking around (or swimming) will require many new functions to control how that activity should be rendered.
Top-Down: weekly progress
This week I added a simple Pause menu that you can open by pressing the Escape key. It stops all the logic and rendering; and opens a menu similar to the main menu. You can use this to return to the Main Menu or quit the game. This was the first time you could easily switch between Menu, Top-Down, and Platformer without restarting the game – a big milestone 🙂
Platformer game level
The other ‘Platformer’ option on the Main Menu opens a game view that looks similar to games like Super Mario World, Super Metroid, Mega Man 7, Sonic, or other platformer action style games of the early 90s:
Walk in either direction and jump. Holding the jump button causes you to jump a little higher. Holding the Shift button while jumping causes you to ‘glide’ so that you fall at a slower rate. You can perform a few different attacks: shoot a ‘fireball’ for a ranged attack, ‘scratch’ for a melee attack, and ‘phase’ to avoid an enemy. Shooting a fireball uses your fire resources, and shooting while scratching causes a stream of fireballs to shoot.
Platformer algorithm concepts
Instead of rendering with small tiles and individual pixels with many different game objects on each spritesheet, the Platformer algorithm uses entire spritesheets for each game object. Full-sized images for backgrounds, and much larger images for the tiles of the levels.
These larger sprite sheets obviously take up more storage. Just for this one character and the few tiles that make up its level, it uses 9Kb. The background image is about 16Kb. So storing the dozens of characters, dozens of more tiles, and a few backgrounds (to give a parallax effect) to create a fully finished level might take up to 20Mb of memory if they’re really detailed and production-ready, if you aren’t careful. That’s 10 times more memory than the Top-Down game view, but still, rather tame compared to professional realistic 3D games.
To draw out the level, it uses a map file made up of numbers to represent which tiles to place where. Surprisingly this needs 2Kb which is 4 times more memory than the tilemap of pixels that Top-Down uses!
Although the sprites, tiles, and map files that Platformer needs uses much more memory; the code to render the platformer game view is much simpler and easier to work with. It just requires more work to design and manually draw out the images for the the graphics.
The logic of the movement and actions you take while playing determine what to render. That ‘animation’ variable is an object that cycles through sprites on the sprite sheet. The actual rendering itself is done with the Java Graphics2D object provided by the Java language libraries, so this avoids having to code the pixel by pixel rendering logic yourself. I’m not sure how much better or worse this performs for the processor of the device, but it’s certainly more simple.
Platformer: weekly progress
This week I added a ‘Death Menu’ that appears when you die – like falling into a gap in the level. It works like the Top-Down pause menu and gives you the option to retry the level, go back to the main menu, or exit the game.
Concepts on a User Interface
This week I also started to work on a UI, User Interface, for the Top-Down game view when I quickly started to realize that it would be a huge undertaking. I added a white box with black borders and had some realizations…
Not only would I have to code the logic and render all the graphics for text, buttons, and other visual elements… I’d have to figure out the text inputs so users could type things into the UI. I would have to make the UI respond to mouse input to work the buttons and drag the UI windows. And then rework the rendering algorithm to more easily enable partial transparency so the UI doesn’t completely block the view of the level and the characters. That could be made easier by using the platformer rendering logic for the UI instead… but I slowly started to get a headache as I started to plan the code for this.
It was time to try a completely different solution…
What’s a JavaFX?
Java comes with a UI framework and library built in called JavaFX, it can make creating a UI much easier. If I can use JavaFX in Omnia I won’t have to sit there for weeks toiling over buttons and game windows that only kind-of work right. Many headaches avoided. The problem is that it would require rewriting the game from the ground up because JavaFX needs to run totally different code for the Window, Game Loop, Canvas, and Images to render onto it. So I spent the last few days learning how JavaFX works and researching different solutions having to do with that. This is what I have so far…
I got the basic parts of the game logic working and the Main Menu runs – and it runs much better than it used to. The background animation moves more smoothly, the text is rendered more smoothly. Everything is more smooth. Like a dolphin or a seal or something. It’s nice.
The code that JavaFX needs to run is much more simple, too… here’s the code that runs the old game loop:
And here’s the code that runs the JavaFX game loop:
That GameLoopTimer has a ‘handle’ method that runs every time a frame is ready to render in the window.. so pausing and calculations on the time between frames can happen here:
With everything so far, this includes some trade-offs. JavaFX tries to always run at 60 fps, I don’t have to code anything to try to make that happen. This simplicity sacrifices some customization … the old game loop was able to run at over 300 fps (on my mid-range gaming computer) if I wanted it to. I would just put an extra loop around the render function that counted down a different nanoSecond difference. I also can’t see a way to access the Thread that JavaFX is running on. It’s just not always clear what all the variables are or where to get them. I may just need to learn more about it, or just learn to get over it and be happy with the 60fps game loop that it provides.
Either way I’m mostly excited to see what kind of UI system is possible with JavaFX and other things it might provide me to use. I’ll be working on this a little bit at a time for the rest of the week and update on my progress in a later blog post or a video or something.
What’s the task list I made today?
It’s clear that the game still needs a gigantic amount of work. Many different fixes, changes, new systems, and a ton of other stuff. I made a long list of ideas that I’ll be working through during 2021. The list is on the Omnia repo readme on github … and man, is it long. Here’s a couple screenshots that show the next stuff I’m working on:
Beyond just working on the UI windows I’m planning stuff like adding Buildings, Doors that take you to other levels, Chat Bubbles, Merchants and other types of NPCS, Money, Inventory, Quests … and thats just in the Top-Down game view. I want to add a Turn-Based game view and other types. I want to have it connect to the internet for online play, run it on Android or a web app, and… just so much stuff.
The funny thing is, I might end up only working on it for a few weeks and then ignore it for another 6 years 🙂
Thanks for reading….
A cute puppy
As promised by this post’s title. Here’s a cute puppy.