Normally I do my work on Mac. I use Xcode and Unity, it has my favourite graphics app and tile map app, and I am generally quite happy navigating OS X.
But I still need Windows for one app and one app only. FamiTracker! FamiTracker is by far my favourite music making app. Everything just sounds awesome when it sounds like the NES.
Today I booted up Windows ye olde Windows laptop to do some sound effects for TinyShooter.
On top of sprites I’ve created a simple animation format. It is a cel animation based format (https://en.wikipedia.org/wiki/Traditional_animation)
So the format is as simple as just listing a bunch of images that should be rendered in order, and for how many frames each image should be rendered.
The classes are AnimationFrameDefinition, AnimationSequenceDefinition and Animation.
AnimationFrame is static data that describe an individual frame of the animation, like which image to use, the duration of that frame, hotspot and other flags like flipping etc.
AnimationSequenceDefinition is also static data and contain a list of AnimationFrameDefinitions together with sequence specific data such as if the sequence should loop, how many frames it have etc.
Animation is the runtime data that describe which AnimationSequenceDefinition should be played, on which game object the animation should be played, which frame in the sequence it is currently on etc.
I have started thinking about having some sort of scene describing objects in the game such as the player, enemies, pick ups, etc, and where the live in a scene that is bigger than just the screen.
So I’ve created a GameObject class and a Camera class. Both of them are purely runtime data for now.
A GameObject describe where in the scene an object should live. It also describe how the object should be visualized, with for example an image or an animation. A game object can also have custom data and function pointers so different game objects can have different meaning and logic applied.
On a high level the camera describe where in the world the screen should visualize the scene. If there are two objects too far apart to be seen on the screen at the same time the camera can pan between them.
On a lower level the camera simply describe a transform that is applied on each game object when it is time to render to the screen.
Audio in TAGE is made up of three components so far. AudioData, AudioSource and AudioMixer. TAGE can only play FM samples yet but I have plans to build a simple audio synthesizer to generate audio for both music and sound effects, to keep the binary size down.
But for now TAGE is only playing FM samples.
So AudioData is static data and describe the wave form of the sample, and the number of samples. AudioSource describe the runtime information, so it have a reference to the AudioData that should be played, and how many samples have been played so far.
The AudioMixer then takes a bunch of AudioSources and mix then down into a signal that output to the Arduino, like how the AudioZero library works.
Giving the Audio_Handler a quick look I’ve done a rough estimate that the AudioZero example spend about 15% of the CPU time to play audio, and I don’t have or want to spend that amount of CPU on audio. So I’ve reduce my output sample rate to 11025Hz mono and to reduce the CPU time further I will probably make a custom Audio_Handler that is less generic.
But that is for future Magnus to do.
To render fullscreen ”images” and still keep the size of the binary down I’ve implemented tiled rendering in TAGE. (I probably shouldn’t use the word ”image” here because I don’t mean image as in the data format in TAGE) If you are unfamiliar with tiled rendering you can read about it here, https://en.wikipedia.org/wiki/Tile_engine
Just like with images and sprites I’ve split up static and runtime data. So static data in this context is tile maps and tile banks, and the runtime data is TileRenderer.
So I can have multiple TileRenderers rendering at the same time, using the same tile map and tile bank. (Not that I know when I’d use the same tile map AND tile bank, more common is that I use the same tile bank but different tile maps, to do like parallax effects of a scrolling background, for example)
So a tile bank is describing the pixel data of the tiles, the tile map describe which tile to be rendered where, and the tile renderer will describe where in the screen to render which tile map combined with which tile bank.
The first thing I implemented in TAGE was images and sprites.
An image is the data describing an image, like for example the width, height and pixel data.
A sprite on the other hand, is describing where on the screen an image should be rendered. Several sprites can refer to the same image data, but rendering that image to different places on the screen.
So I have ”static” data (the image) and ”runtime” data (the sprite). This split in data is a concept that I use for many parts of the engine, like for animations, sound and backgrounds.
To be able to run any games I needed to render graphics, manage input, play sound, detect collision etc. So I’ve built a library with a simple set of functions, like render sprites, tile maps, play audio and read input.
I call that library TinyArcade Game Engine, or TAGE. The library is on GitHub at https://github.com/MagnusRunesson/TAGE/ . It is heavily under development still, with obvious features still not implemented, other features implemented but not very efficiently, and probably filled with bugs. But it is a start at least.
In the coming posts I will describe the different parts of TAGE.
My name is Magnus Runesson and I am super excited about the TinyArcade.
I’m a long time C/C#/assembler programmer with a few games to my resume. Last big game I worked on is Angry Birds 2 for mobile devices.
And now I’m looking to learn something new, the TinyArcade platform. I am also new to Arduino so it is a bit of an uphill struggle, but it is very exciting writing games for such limited devices.
There are many thins I haven’t figured out yet since I’m new to Arduino and doesn’t actually have a TinyArcade kit to try my things on yet, so at the moment it is mostly trying to wrap my head around the limitations of the hardware. So that is what my first few blog posts will be about.
I have a GitHub repository for the work I’m doing. It is at https://github.com/MagnusRunesson/TAGE if you’re interested.
Until next time!