Summary


I did not stop to write blog style entries as I was writing my game.
However, I'd like to give an overview of my though process bellow.

I didn't join the game Jam until a day after it started. Unfortunately, real life takes priority. My first step was to choose something familiar which could be done in only a handful of days. I've done games for competitions before but those spanned a couple months. This was going to be less than two weeks. In my early days of programming, I had huge gaps between college classes to work on game projects.

I set myself to make a "bullet hell" style shmup. They're the most pathetically lazy genre to make (OK OK they are gorgeous and time consuming if done CORRECTLY). I happen to be a big "shmup" fan going way back with arcade and consoles games. I won a few competitions over at what was once Shmup-Dev. I know this genre and I know the basic components needed to make a game in this genre.

Making a Shmup: The Minimum Components

To make a basic shmup you need a handful of objects. No, really, that's it. If you're using an OOP approach it's pretty easy. (Don't ask me for Functional Programming or ECS approaches-I don't know those). Usually you need about 4 objects:
1. Player Object - Stores position, HP, a firing timer, lives, hitbox or hit circle
2. Bullet - Stores position, speed (Player and Enemy just push the same instance of Bullet into different containers)
3. Enemy Object - Much like the player object, hell you can use a single object for both and just store them different containers.
4. Game Controller/Engine - Engine is a bloated term but you need a singleton to store logic and structure the game events 

Got that? Good. Now throw all that away and notice the horrid horrid thing I've done in my game. I've made a single object that can be all of those objects. My objects are simply defined by where they're stored. In rushing to produce a game, I did not want to define 4 objects which had similar attributes. But there is a cost to such laziness. How did I get away from the edge case member variables like the shot timer? I simply made the player auto fire when he touched an enemy bullet. How did I get away from the Game Engine? By using global state variables and pushing the logic into horrid spaghetti code. So I'm not using strict OOP nor Functions only. I don't believe in a one size fits all approach. It's certainly not good for rushing to get something done. You need to be able to bend the code to what you need in the smallest amount of time possible.

I mentioned that I used a single object "obj" for most of my game components. Again, the big trick is to define something by what container it is stored in. My enemies go in the enemy container, my player is a stand alone instance, and my shots go into an enemy shot container etc. These objects are so similar in my game that they need only be defined by where they're stored, not specializations. This is not always the case. Please don't go making "god" objects instead of specializing when you DO have more time. Objects just tend to be very similar in shmups (well the most basic ones). 

Simple interactions are also part of the charm of shmups. All my game objects use circle to circle collision. It lazily describes each "obj" class. There were one or two edge cases not covered by my naughty monolithic obj class. My Emitter class was taken from an earlier project and modified. I'm rather happy with it. It just stores lists of parameters, a shot function (assigned by the game reducing coupling from project to project), and step indicies for when it needs to call the shot function with saved parameter lists. It worked mostly as originally written. For this game, I modified it to also store shot color. Speaking of color, I decided very early on that I'd only use a handful of predefined colors. This would reduce me having to write (vec2 r g b a) each time I wanted a color. I could just go *RED* for example.

I thought I'd try picking colors by hand rather than using the standard RGB permutations for the 8 or so standard DOS era colors. So I popped open GrafX2 and used the palette tool set to HSV mode to eye through what I thought each color should look like. I had to ask myself "Which of these looks most to me like yellow?" as I moved the color components around. I did this for what I culturally knew to be the primary western colors. The big trick is to pick visually when trying to make similar colors. If you try to use math and not your own vision you'll soon find out that yellow and green are overpoweringly bright compared to purple and blue of what should be the same overall RGB triplet value. Pick with your eyes, not with numbers. The most annoying thing was converting the 256 base to 0.0 - 1.0 format for each RGB triplet so I wrote a little conversion function in the Scratch buffer of Emacs to quicken the process.

The game mostly went off without a hitch when I got into programming the logic. I've kind of been here a few times. (Remember I deliberately chose something I was familiar with). I still don't have a handle around the live REPL and occasionally I'd have to restart the program to do major structural changes or mutate state after the game had been initialized. Perhaps the "live programming" aspect of Lisp is touted a bit too much and gets a bit thin when you're doing major structural changes to the game's guts. It seems to work best for configuring small things while the program runs. Despite being able to use my old Emitter class, I'm not happy with the game's patterns. They are weak, bland, and don't push the player around enough. BUT dear reader, you may choose to edit levels.lisp and make better. :)

I'm probably one of a handful of people to use the new trivial-gamekit library for a Lisp game jam. It's damned good and will only get better with time. It FEELS very much like what I'd like to develop with given a short time. When you've only got a handful of days and you have to go immediately to the GLSL level, you've hobbled yourself at the starting line. I need "draw-circle", not 300 lines of GLSL granularity. Everything I needed was there borodust has done a great job with all my bitching and moaning about simplicity in a game engine. Abstraction abstraction abstraction is the key for fast 2D games. It's all there, I just wish I would have used some multimedia to test that area of his library.

Speaking of trivial-gamekit my roughest bit was multi platform deployment. Something about generating and encrypting github keys and "continuous deployment" across two services ... borodust gave me a good hand here. (Thanks man, I owe you one). It is a very different time today than when you were just responsible to make backup floppies of your Borland TurboBASIC games. :) In some ways I feel bad for the new programmer today. They have more processes and options than ever before and it is daunting.

Anyway, my game is just to show support to the Lisp Community. It's not my best work ever but it is just one more voice showing support of Lisp (not the fake ones mind you ex Haskell in Parens). Lisp got a LOT right early on. It's very powerful and very flexible. I read a lot of articles about new programmers squabbling about C#, Java and C++ but at the end of the day these are still only grasping at the flexibility of the second oldest family of programming languages. New Lisps are being rolled into the Functional as a Panacea (FaaP) mantra and it's unfortunate as Lisp should be heavily multi paradigm. But I digress, thanks for reading this far. You really must have nothing better to do.

Thanks for your time!
Enjoy my game, maybe make it better. :P

Files

mds-x86-64-windows-v1.0.2.zip 20 MB
Apr 28, 2018
mds-x86-64-osx-v1.0.2.zip 17 MB
Apr 28, 2018
mds-x86-64-linux-v1.0.2.zip 18 MB
Apr 28, 2018
mds-1.0.2.zip 10 kB
Apr 28, 2018

Get Minimal Danmaku Simulator

Leave a comment

Log in with itch.io to leave a comment.