![](./img/border_left_content.png) | Latest Blog Post:
A few more months of Game Dev study | Posted by: Owen, 01 Feb 2015 01:21 | Another semester done and dusted. Here’s some of the stuff I've made in the three modules of Game Systems, Narrative Design and Game Programming in my part-time BSc Honours Degree in Computer Game Development course at DIT.
Most recent first.
Game Programming: Pac-Man
Finished just this last weekend and presented in the first class of the new semester this week was our Game Programming assignment. The brief was relatively straight-forward; make a 2D game in Unity, taking inspiration from a classic game, creating as much of the game in code as possible. I took that as a challenge! I decided to revisit a past failure in order to make a pixel-perfect procedural Pac-Man. Not quite inspiration, but a full out clone.
The only Unity primatives I used in this project are Quads, and they're just to there to hold the textures. Those texture don't actually exist until the game is running
To give an example here is Pac-Man's death animation
There are 11 distinct frames of animation there. Here is how those 11 frames are represented as data in code.
Code: protected int[,] pixelDeathData = new int[SIZE,SIZE]{
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0,35, 0, 0, 0, 0,35, 0, 0, 0, 0, 0},
{ 0,29,29, 0, 0, 0,35, 0, 0,35, 0, 0,35,29,29, 0},
{ 0,22,29,37, 0, 0, 0, 0, 0, 0, 0,35,29,29,22, 0},
{28,22,22,22,36, 0, 0, 7, 7, 0, 0,29,22,22,22,28},
{27,19,19,22,22,29,13,12,12,13,29,22,33,34,19,27},
{26,18,39,39,17,16,15,14,14,15,16,17,18,18,18,26},
{11,25,10, 5, 5, 4, 3, 2, 2, 3, 4,32, 5,10,25,11},
{21,24, 5, 5,31, 4, 3, 2, 2, 3, 4, 4,32, 5,24,21},
{ 0,40,24,31, 4, 3,30, 8, 8,30, 3, 4, 4,24,40, 0},
{ 0, 0, 0,20,23,31, 9, 1, 1, 9,31,23,20, 6, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
And here is how that data is past to the custom "Painter" function that creates those frames, using the first and last frame as examples...
Code: Texture2D f1 = Painter(pixelDeathData, new int[]{1,2,3,4,5,8,9,10,15,16,17,18,19,22,29,30,31,32,33,34,36,37,38,39});
Texture2D fl = Painter(pixelDeathData, new int[]{30,31,32,33,34,35,36,37,38,39});
All perfectly clear, right. Right?!
Okay, so that may need a little explanation. Lets take the case of a very simple 2x2 4 frame animation
Starting with the first frame (yellow on top row) we define our two-dimensional array, pixelArray, as:
{1,1},
{0,0}
If we were then to use our Painter function now we'd get back that first frame
Code: Texture2D frame1 = Painter(pixelArray, new int[]{1});
But we can't actually use the function yet as we need to enter the data for all the frames beforehand (which is the entire point, use one array instead of four).
So on the next frame there are four different states a pixel can be over the two frames:
{1,2},
{0,3}
0 off for both frames
1 on for first frame but off for second
2 on for both frames
3 off for first frame but on for second
This means the function call for the first frame changes slightly
Code: Texture2D frame1 = Painter(pixelArray, new int[]{1,2});
Texture2D frame2 = Painter(pixelArray, new int[]{2,3});
And so on, until we have all frames. For this simple example it only take one extra step
{1,2},
{4,3}
so all four frames can be defined
Code: Texture2D frame1 = Painter(pixelArray, new int[]{1,2});
Texture2D frame2 = Painter(pixelArray, new int[]{2,3});
Texture2D frame3 = Painter(pixelArray, new int[]{3,4});
Texture2D frame4 = Painter(pixelArray, new int[]{1,4});
For such a simple case that is pretty straightforward, but for eleven 16x16 frames it gets really unwieldy, especially if you need to debug your mistakes. If I were to do it again (and I might just do that to try and complete the game) would be to treat the binary version of the integer values in the array as a third dimension (where each bit represents the state for a particular frame). Then bit-shift off each bit one frame at a time.
Overall I'm really happy with what was submitted. I followed the Pac-Man Dossier as closely as I could trying to replicate everyting from Ghost AI to Pac-Man turning around corners. I even coded in the effects of a buffer overflow from the original arcade cabinet (where when ghosts are attempting to find a spot x tiles in front of Pac-Man, that spot will also be x tiles to the left if Pac-Man is facing up).
But as a port it is not feature complete (missing bonus fruit, warning flashing on ghosts exiting frightened mode, ghosts do not use a pseudo random number generator with path finding in frightened mode [they just use their scatter home target], no cut scenes). There are also a few bugs, the most noticeable being if ghosts are in the middle of exiting the ghost house when Pac-Man eats an enigizer (causing the ghosts to enter Frightened mode) then those ghosts won't move at their full speed for that level on exiting Frightened mode.
Can you spot the differences? There are many
So I may revisit this one to finish it off. And it's something I'd recommend to anyone who is starting to get in to making games; as a Journeyman exercise try and recreate a classic game as closely as you can, replicate everything from movement and scores to menu screens (though not necessarily procedural asset creation). It gives you a good appreciation of what it takes complete a game (without the uncertainty of your own game design decisions getting in the way).
The game can be played here, and the source of the unity project can be downloaded here.
Narrative Design: Saturn Descending
Next up, Narrative Design. For this module we had to create a mini text adventure game using a program called Twine, which makes these types of text games.
Twine games are somewhat known for more personal or thought provoking games (like Depression Quest). So I wanted to take this opportunity to kind of do the same and create a main character that experiences social anxiety, so that the player gets a feel for what someone in that situation might go through (although it may be a bit over exaggerated at times, or drift off into general anxiety). There are elements in there that reflect me of a few years ago and even the slightly better me of today (stutters are annoying!)
The story/game itself is a bit so-so; pacing is a bit off, some character interactions aren't earned, and there isn't enough for the player to do to direct the story. But I guess it is what it is... a product of a deadline.
Takes about 5-10 minutes to play through, with different content in places depending on the choices you make.
Saturn Descending [Warning! Contains trace amounts of Science-Fiction!]
Game Systems: Prototypes, oh so many prototypes!
This module started out by introducing the basics of Unity and then quickly moving on to making a prototype to a set theme each week.
But before the avalanche of prototypes we had to make an atmospheric environment, with a beginning and an end. So I decided to try a low-poly volcano, where you can see your destination from the start but not the full path you have to travel to get there.
There is no game here, just an environment to travel through, hopping from one pad to the next.
Peace:
Then came the prototypes, first up was the theme "Peace". For this I decided to make a game about the apparent 'keeping the peace' or maintaining equilibrium in the nuclear arms race.
Balance of Power [Play Here]
Playing on the side of the US (didn't have time to set up the USSR to be played) you have to assemble your ICBMs in order to maintain your stockpile of warheads, but if you work too fast, or too slowly, you'll tip the scales and trigger a nuclear war. This was the most 'complete' of the prototypes as a game.
Oppression:
Next up was Oppression. I'm marking this one down as a failure, due to limited time, and not much worth sharing although I did demo what little I had in class, which can be seen here (may or may not display correctly due to shader shenanigans).
Change:
This was by far my favourite as it combines two things I really want to learn more about, Shaders and real-time mesh deformation.
Double-click and drag to deform [Play Here]
This is one I'll be working on more in the Game Production module this semester, fleshing it out in to a real game.I'm thinking it'll be one where you have to stretch or compress the terrain in order to create veins of resources within the mountains
The Sun/Son:
Next was "The Sun" or "The Son" if you preferred. I decided to go for Son and made the beginnings of a simple game about inheritance.
Here you combine two shapes to create a child shape that takes properties from both. Missing from this is a target shape that you would try to create after a number of generations from the supplied starting shapes.
Completeness:
This was another relatively simple one due to lack of time. Completeness brought to mind diminishing returns. The goal here is to try and fill the screen with the circles before they turn yellow. Growing the circles slows the rate at which they change colour, but the larger they become the less effective they are at slowing the change.
There is no victory condition so you just 'play' 'til you lose.
Wrath of Kitty!
Last, and not quite least, is week 6. For this we could take the theme from Ludum Dare, Dublin GameCraft game jam (both of which were that weekend) or... some other theme that was mentioned that I've completely forgotten. For Ludum Dare it was "Game all on one screen" and for GameCraft it was "Wrath of Kitty". Since I was attending GameCraft I went for the Kitty.
This wasn't too successful a game jam for me (yet again), so this is pretty simple. You play as the baby and you have to pull the tails of the cats, without letting any of them see you otherwise they all startle and run away.
So that's it. All the stuff I made last semester. Some a bit meh, others I actually liked how they turned out for the most part. On to another 3 months of making! | Tags: Games, Programming, GameCraft, DIT, Game Jam, me me me | Comments: (1) |
| ![](./img/border_right_content.png) |