Lisp Game Jam Log #4

Screenshot showing a game level with two characters, a coin, and a gem.Today I started on the physics engine for my game. I have implemented the entity record type, which represents dynamic objects like players and items, and the body record type, which represents the physical attributes of an entity, such as its position, velocity, acceleration, dimensions, and mass.

CHICKEN Scheme has several object-oriented programming libraries that support inheritance (I even created my own for fun a few years ago). But so far, I have just been using basic Scheme record types (structures with named slots), and using composition instead of inheritance.

In other words, instead of having the entity type inherit position, velocity, etc. attributes from the body type, an entity has a slot which holds a body. And instead of having a player type and a coin type and a gem type which inherit from entity, an entity has slots to hold other objects which define its appearance and behavior. I’m not opposed to using inheritance when the need arises, but so far while making this game I have not needed it.

Today I also wrote a simple physics update function (apply the acceleration to the velocity, then the velocity to the position), and I now have moving player characters on the screen. There is no collision or user input yet, but by setting the initial attributes of the characters, I can make them fly through the air in a parabola, then fall down off the bottom of the screen. I also added a coin and a gem entity to the scene, just for kicks.

I added user-customizable scaling for the window, since the graphics are a bit small (each tile is 21-by-21 pixels). I’ve shrunk the screenshot in this post so it wouldn’t be too wide, but you can click it to see the full version. The default scale is 200%, but users can edit the settings.scm file to change that if you want. In the future, that file will have other settings like the keyboard/joystick bindings.

The settings file, like the level file, is just a collection of s-expressions. I’m using CHICKEN Scheme’s built-in read-file procedure, which reads (but does not evaluate) all the s-expressions in a file and returns them as a list. This is probably not super secure, since users might be able to exploit the reader in some way to inject code, but it sure is convenient. Besides, security is not a high priority in the heat of a game jam.

My next step is to add detection and resolution of collisions. If this were a shorter game jam, or if I had more complex scenes, I would definitely just use a pre-built physics engine like Chipmunk. But, I think I have enough time to implement a good enough physics engine to handle a simple platformer game like this.

P.S. The in-progress source code is available.

P.P.S. The sprites are from Kenney Game Assets. I got them from donating about a year ago, and they are licensed CC0 public domain. An older version of the same sprites is available with no payment required.

Lisp Game Jam Log #3

Screenshot of a very simple game level. I did not get quite as far on my game today as I hoped, due to distractions and other activities taking up time. But, I did write the level loader. You might notice that the level in the first screenshot here is the simple level from my last post.

Screenshot of a more complex game level.After I got the level loader working, I created a more complex and interesting level (shown here), to suggest some of the gameplay possibilities. The two players would start on either side of the water, and coins and gems would randomly appear at various locations throughout the level: up on the floating platforms (so players have to climb), hovering in the air between the platforms (so players have to jump and fall), and down in the water (so players have to dive down). The coins and gems would probably only last a few seconds before disappearing, so players would have to hurry to get them. Gems would be rarer and worth more than coins, so players would sometimes have to decide whether it is better to stay in an advantageous position near the top and hope that a gem appears (high risk, high reward), or leave that position to go collect more coins (low risk, low reward).

Here is the level in text format:

(prop title "Level 1")
(prop author "John Croisant")
(prop num-players 2)
(row (--- --- --- --- --- --- --- --- --- --- --- ---))
(row (--- --- --- --- --- --- --- --- --- --- --- ---)
     (T01 ~~~ T02 ~~~ T03 T04 ~~~ T05 ~~~ ~~~ T06 ~~~))
(row (--- PLT Gh- --- --- --- --- Gh- PLT GhL GhR ---))
(row (--- PLM --- --- --- --- --- --- PLM --- --- ---))
(row (--- PLM --- --- --- --- --- --- PLM --- --- ---)
     (~~~ ~~~ ~~~ T07 ~~~ T08 ~~~ T09 ~~~ ~~~ ~~~ ~~~))
(row (--- PLM GhL GhR --- --- --- GhL GhM GhR PLT ---))
(row (--- PLM --- --- --- --- --- --- --- --- PLM ---))
(row (--- PLM --- --- --- --- --- --- --- --- PLM ---)
     (~~~ ~~~ ~~~ ~~~ T10 ~~~ ~~~ T11 ~~~ ~~~ ~~~ ~~~))
(row (GM- GM- GHR --- --- --- --- --- --- --- PLM ---))
(row (GC- GC- GHr GHR --- --- --- --- --- --- PLM ---)
     (~~~ ~~~ ~~~ ~~~ P1~ ~~~ ~~~ ~~~ P2~ ~~~ ~~~ ~~~))
(row (GC- GC- GC- GHr GR- WT- WT- WT- GL- GM- GM- GM-))
(row (GC- GC- GC- GC- GC- W-- W-- W-- GC- GC- GC- GC-)
     (~~~ ~~~ ~~~ ~~~ ~~~ ~~~ T12 ~~~ ~~~ ~~~ ~~~ ~~~))

The T01 through T12 IDs indicate tiles where treasure might appear at random. They are scattered all around so players would have to keep moving. They couldn’t just camp in one spot and get lots of treasure.

If you compare this format to my last post, you can see that the list of tile IDs is now nested within the row s-expression. This makes the relationship more clear to humans (before it was ambiguous whether ids described the row above or below), and also made the level-loading logic simpler to implement.

Tomorrow I will start implementing players. That will be a lot more complex to implement than tiles were. I will probably need to implement a crude physics engine with tile collision detection. And eventually, I’ll probably need an animation system to handle the different player poses and animations.

Lisp Game Jam Log #2

Screenshot showing several 2D player images, grassy terrain, and water arranged in a simple scene. I am making progress on my game jam entry. Last night I was able to make the code to load a spritesheet from Kenney Game Assets, using spritesheet code I previously wrote for my eggsweeper example game. To test that the sprites were defined correctly, I arranged a simple scene, shown here in the screenshot.

I then started working on the data structures for representing a game level. So far I have a level type, which holds many individual tiles, each of which has a tiletype that defines the appearance and default properties of a tile. A level is not responsible for managing entities such as players or items; those things be managed by a scene type, which will also hold a reference to the level.

As I was drifting off to sleep last night (or rather, tossing and turning with my head full of ideas), I pondered different approaches to defining a level format. I want the level format to be pretty simple and text-based, so that levels can be created in a text editor, without the need for a dedicated level editor program.

One easy-to-implement format would be to simply have s-expression based list of all the tiles in the map. But that would be pretty hard to visualize and modify in the text editor. I also considered having two parts to each level: a s-expression file describing metadata and logic, and an PNG image file where each pixel color represents a different tiletype. This might be easier for people to visualize and edit, but harder to implement.

Right now I am leaning towards a simple s-expression format with tiles of three characters, separated by spaces, like so:

(prop title "My First Level")
(prop author "John Croisant")
(prop num-players 2)
(row --- --- --- --- ---)
(ids ~~~ ~~~ C1~ ~~~ ~~~)
(row --- --- PLT --- ---)
(ids P1~ ~~~ ~~~ ~~~ P2~)
(row GL- GM- GR- WT- GL-)

Here, each row expression defines a row of tiles. --- means empty space, and other three-character strings describe tile types: PLT (Prop/Ladder/Top), GL- (Grass/Left), GM- (Grass/Middle), GR- (Grass/Right), and WT- (Water/Top).

Each ids expression assigns three-character IDs to the tiles above it. The IDs can be used to assign special gameplay behavior to that tile. The ~~~ means the above tile has no ID, so the tile doesn’t have any special behavior. This level has tiles with IDs C1~ (Coin 1), P1~ (Player 1), and P2~ (Player 2). Probably there will be many pre-defined special IDs for gameplay, plus the ability to define custom IDs. The custom IDs could be used to connect a button tile to a trap tile, for example.

This level also has a few prop expressions to define extra level properties. The title and author properties are metadata about the level. The num-players property indicates how many players the level is designed for.

I think this format will strike a good balance between ease of implementation, ease of visualization, and ease of editing.

Lisp Game Jam Log #1

The January 2016 Lisp Game Jam officially started earlier tonight. I haven’t participated in a game jam for several years, and I’m excited. Game jams are exciting (and stressful) in general, but I’m also excited because this is my first jam using a Lisp dialect, plus it is an opportunity to use the CHICKEN Scheme bindings to SDL2 and related libraries, which I have been working on for the past several months. (I’m also excited because at least two other people are planning on using my bindings for the jam, which is a nice feeling.)

This game jam does not have a prescribed theme, so I’m free to make any game. I’ve been pondering for weeks about what kind of game I might make for the jam. My goal is to produce another example game for the bindings, so I want the result to be clearly organized, well documented, and to demonstrate the capabilities of the bindings. In particular, I want to try to push the boundaries of performance. My previous game library project, Rubygame, struggled with raw performance, partly because of the performance limitations of Ruby in those days, and partly because I didn’t put much effort into optimization. So, I’m keen to see what I can achieve with CHICKEN Scheme and these bindings.

Thinking about what type of game I’d like to make for the jam, I had two main ideas: a scrolling space shooter à la Tyrian, or a platformer à la Mario Bros. I also briefly considered a Harvest Moon-like RPG, but decided I wouldn’t be able to make it fun in 7 days, and the laid-back gameplay style wouldn’t push any performance boundaries.

Between the space shooter and the platformer, the space shooter would be a more interesting example, because I could try to achieve solid performance while having hundreds of bullets and ships on screen at the same time, and it could use the function bindings I recently added for 2D accelerated rendering. But, those bindings aren’t actually released yet (they are scheduled for version 0.2), so it wouldn’t be as easy for people to install the bindings and play the game. So, I am going to make the platformer game for this jam, and then make the space shooter at some later date.

This game jam allows us to use preexisting free assets (images, sound, music), so to make things easy for myself I am going to use a lot of assets from the Kenney Game Assets pack. (You have to donate money to get the assets from the official store, but they are licensed CC0 public domain, so no doubt they are available somewhere for free.)

In terms of gameplay, I’m thinking the game will be a rowdy local multiplayer game, where players compete to collect the most treasure, like the old Super Mario Bros. Battle Mode. At the most basic level, it could just be treasure periodically appearing at random places on the level, and the players scrambling to reach it first, with no real interaction between players. If I have time, I could add various ways for the players to interact and interfere with each other: bouncing and bumping into each other, triggering traps, throwing items, etc.

This game design is simple and flexible enough that I’m confident I’ll be able to complete something fun during the game, especially since we have 7 days. I will probably try to include 2 or 3 built-in levels, and have a simple text-based file format so that people could create their own levels.

chicken-sdl2-ttf 0.1 Released

Screenshot of the chicken-sdl2-ttf demo program, displaying the text "Hello, World!" three times. Last week I released version 0.1 of chicken-sdl2-ttf (aka the sdl2-ttf egg). This provides bindings to SDL_ttf 2, the font rendering library for SDL. This library is compatible with chicken-sdl2, which I released a couple weeks ago.

SDL_ttf is thankfully a fairly small library, so I was able to create and document complete bindings to it in less than a week, in advance of the January 2016 Lisp Game Jam, which has just started a half hour ago.

My plans now are:

  1. Create a game for the game jam!
  2. Release chicken-sdl2 0.2 (the main new feature is 2D accelerated rendering).
  3. Create bindings for SDL_mixer, and possibly SDL_gfx.

chicken-sdl2 and chicken-sdl2-image 0.1 Released

Today I released two new library bindings to make it easier to develop games with the CHICKEN Scheme programming language:

CHICKEN Scheme has excellent FFI support, so it was previously possible to use SDL2 from CHICKEN Scheme — possible, but not convenient or straightforward. I have made an effort to create programmer-friendly, convenient, thorough, and well-documented bindings. These bindings take care of the annoying low-level C stuff for you, so you can focus on making your game.

Although the version numbers for these libraries are only 0.1, they are ready to start using now. Some features have not been implemented yet, but it is already possible to create many types of games, even 3D games using OpenGL (when combined with the gl-utils or opengl egg, for example). Several demos and example programs are available to help you get started. Large backwards-incompatible changes are unlikely, but there may be small tweaks and fixes to the API if problems are discovered. There may be some bugs, but they will be fixed promptly if you report them to the issue tracker.

I also intend to eventually create bindings for other libraries, such as SDL2_ttf (for text rendering), SDL2_mixer (for sound effects and music), and SDL2_gfx (for shape drawing and image transformation).

In related news, there is a 7-day Lisp Game Jam coming up the first week of January. I will be creating a new example game using these bindings, and hanging out in the IRC channel (my handle is “jacius”) to answer questions about the bindings, CHICKEN Scheme, and SDL in general.

Cloje types vs host types, revisited

While preparing the Cloje 0.2 release last week, I came across something I had written, part of the goals for Cloje:

Importing all of Cloje will allow you to write code in a language very similar to Clojure. Or if you prefer, you will be able to pick and choose which pieces of Cloje to import, so that you are still mostly writing code in Scheme/Lisp, but with some added features from Clojure.

I had written that over a month ago, long before I had explored host interop issues. Reading it again during the release preparations made me wonder if I had neglected this use case when considering the host interop API design.

My consideration of host interop was from the angle of someone who was writing in Cloje, and wanted to interact with certain host language features or libraries. I hadn’t really considered someone who was writing in the host language, and wanted to integrate certain Cloje features or libraries. It made me wonder whether it was accurate to say that users would be able to “mostly write code in Scheme/Lisp”, considering that much of Cloje will probably depend on a bunch of new types.

This got me thinking on a more fundamental level about Cloje’s stance regarding host types. Should it be possible (and acceptable/idiomatic) for Cloje users to decide to write Cloje programs that primarily (or exclusively) use host types? Or are Cloje users expected to primarily use Cloje types, and only use host types for host interop?

Note: When I talk about “Cloje types” and “host types” in this post, I am mostly thinking of lists, vectors, hash maps/tables, and strings. Those are the types where Cloje and the host language would have “colliding” types (analogous types with different implementations), and thus the source of possible trouble. Certain other types (such as symbols, numbers, and functions) are the same type in Cloje as on the host, so no conversion (implicit or explicit) would be needed.

To help me organize my thoughts and guide my decision, I have sketched out a few scenarios for different stances Cloje might take regarding host types, and explored some of the implications of each scenario. Continue reading Cloje types vs host types, revisited

Cloje 0.2.0 Released

Cloje icon Yesterday I tagged version 0.2 of Cloje. If you want to play around with it, you can clone the repository. Installation and usage instructions are available in the README.

In terms of features, the biggest changes in Cloje 0.2.0 are the addition of hash sets (an unordered collection of distinct elements), and several set operations based on the clojure.set standard library. Please read the release notes for the full list of changes in Cloje 0.2.0.

Also noteworthy is that the goal of Cloje has changed since 0.1. For reasons described in the Cloje 0.1 Post-Mortem, Cloje will no longer attempt to faithfully emulate Clojure. Instead, the new goal is to bring the best aspects of Clojure to Scheme/Lisp. The first effects of this new direction can be seen in the new set operations, whose behavior is more predictable and consistent than clojure.set when given non-set collections. The old goal would have required me to laboriously recreate Clojure’s quirks and bugs, rather than address and fix them.

Tentative plans for 0.3 are to create placeholder types (vectors, maps, etc.) and an API to convert between Cloje types and host types. This will set the stage for adding Clojure-style immutable persistent data structures in the future. The placeholder types will be immutable, but not (yet) have the structural sharing of Clojure’s types.

Besides writing code, I will also be dedicating a significant portion of my project time to establishing policies, project documentation (how to start contributing, etc.), and outreach to help get more people involved in the project, especially people from underrepresented groups.

Designing Cloje’s host interop API

Lately I have been working on designing Cloje’s host interop API. I had the outlines of a design for the API already, but as I started filling in the details and thinking about different use cases, I realized that my simple design would have had some serious problems in actual use. The host interop API was scheduled for Cloje 0.2, but I have decided to push it back to 0.3 to give me time to get it right.

I wrote this post mostly for my own benefit, to help me focus and organize my thoughts. But, it might be interesting to anyone interested in API design. Continue reading Designing Cloje’s host interop API