Unnamed Commodore 64 Dungeon Crawler Devlog #0


Hello everyone!

Half a year ago I decided to launch my new Commodore 64 game project.

My previous project by the name of "The Last Effort" was published in the august of 2023. It was not fully completed because of my lack of knowledge and maybe laziness. For example, that game has no music and sound effects at all. After releasing this game I was quite sure, that it'll be my last Commodore project. I was exhausted!


But time has passed and I thought that I still love Commodore and I still want to make games for it. I always had a dream: to create something like dungeon crawler not in fantasy but in the modern world style. And so I decided to create this kind of game for Commodore 64.

First of all I have had to decide, which rendering method will be more useful for not-so-fast 8-bit 6510 CPU.  I heard that the old dungeon crawler games (Eye of the Beholder or The Bards Tale) used very simple method. There were blocks of graphics in RAM, converted to the required perspective, size and position. And the game engine simply gets this data from RAM and stores in the Screen Memory. Easy, but it takes too much RAM to hold all of the graphics.

 

But I wanted to draw each wall with a separate texture (too much RAM space). So I had no other option but to use raycasting like in the famous Wolfenstein 3D.

There are 16 textures for each level in my solution (and levels will boot from floppy disk). And raycasting engine draws this textures on the screen according to the level layout. It sounds great, but you can ask me: how on earth can Commodore 64 produce raycasting with its 8-bit 1 MHz CPU, no division and floating point numbers?

And my answer will be: "Lookup tables".


Firstly, in my game player can turn himself only for 4 directions (N E S W). Therefore I don't need to calculate all of the angles and other trigonometric stuff.  Secondly, each ray don't need to check all of the X-Y points of the level. It simply checks for only 3 blocks of the level in front of the player (according to the lookup table).

If the ray founds a solid block in front of it, game engine goes to the other lookup table with texture scaling data. And it scales and draws one column of the texture in the screen buffer (and then the screen buffer goes to the screen memory).

First table contains data for each block that each ray should check (3 blocks total for each ray): number of current block, texture column size, texture offsets, texture masks etc.

The second table contains information about pixel indexes for each texture column height. For example, column of height 16 contains indexes from 0 to 15. But if the height of texture column is 32, indexes will be: 0,0,1,1,2,2,3,3,... 30,30,31,31.

This is how it works:

But of course it'll be too slow do draw it on the whole Commodore screen (320*200 pixels), so the actual gameplay screen is only 128*128 pixels. And I'm using bitmap multicolor mode (with double-wide pixels), that's why the actual size of the gameplay screen is 64*128 (and only 64 rays are producing each frame).

What I have for now:

  • 24*24 blocks (bytes) levels;
  • 16 textures for each level;
  • 64 sprites for each level (level objects);
  • 64 triggers for each level (maybe I'll increase this number);
  • 4 enemies for each level (sprites and parameters) and random enemy encounters;
  • 8 weapons that player can pick up and use;
  • 4 HUD text zones (messages, inventory, fight zone, player status)

1. Level

Level is just a 24 by 24 byte array. Each byte contains information about texture, collision, visibility, sprite and trigger data (on or off). I'll tell about sprites and triggers later.

2. Textures

Each texture is 32 bytes long (8x16 pixels), and there are 16 of them for each game map. 512 bytes total. Not good, not terrible. And for I decided to load all map data from diskette, it's nothing at all.

There are all of the textures for the first game map:

3. Sprites

First of all we need to separate two concepts: Sprites (movable blocks of pixels produced by the videochip on the screen) and Objects  (have images and parameters and can be visible by player on the map). Ok, I SHOULD call them Objects, but for some reason I called them just Sprites in my code. It's confusing. That's why I will call them Objects within this article.

One level has 64 Objects. To declare that one block of the map has an Object, we need to turn on the 4-th bit of it. Each Object has X-Y position, image reference and 6 colors. But that is not so simple because one Object consists of 4 videochip Sprites. 

One videochip Sprite is 24x21 pixels and in multicolor mode it can use 3 colors. But two of them should be the same for all Sprites!

And here we go! This is the pistol. As you can see, it uses dark grey and light grey for general colors. But moreover the bottom left Sprite uses brown color, and all other Sprites use very-light grey.

4. Triggers

It'll be much easier to explain. Triggers make the game playable. For now I have only 9 types of triggers:

  • Doors - moves player to the position and then switches this position to another (I use this when there is only 1 door block);
  • Teleport - just moves player to another position (I use this when there are two door blocks);
  • Message - prints any text in the message text zone below the game screen;
  • Erase Block - deletes the map block on the given coordinates (if any);
  • Erase Object - deletes the object on the given coordinates (if any);
  • Change Texture - changes the texture on the given coordinates;
  • Add Key - adds one of 8 possible keys;
  • Add Weapon - adds the weapon according to the parameters;
  • Disactivate Another Trigger - speaks for itself;
  • Change Map - loads another map from the diskette;

I have 64 triggers for one map, and to declare the trigger we need to turn on the fifth bit of the map byte.

Each trigger has it's type, X-Y position, 4 arguments, two flags (single use and availability) and keys flags (trigger can be activated only if player has necessary key or keys).

This is how some triggers work (Change Texture+Erase Block):

5. Enemies

For one level I have only 4 enemies (but I haven't done fighting and roleplay systems yet). Each enemy has it's own image (consists of 4 videochip Sprites, but two times extended in width and height) and parameters like health, armor etc.

When you investigating the map there is 8% chance to meet the enemy. 

This is how my first enemy looks like:

6. Weapons

There will be only 8 weapons and 6 types of ammo. Each weapon has its own parameters and image (sprite). And if you pick the weapon, it will be drawn on the right side of the screen, and you can choose it. My idea is that all enemies have weakness for some kind of weapons. And you need to choose the right gun to fight them.

For now I drew only three weapons: wrench, pistol and nailer.

7. Text zone

Commodore 64 (in 6502 processor actually) has the great thing called Interruptions. When the raster is on any screen line you can say: "Stop right there, criminal processor", and the processor will jump to another program location immediately.

That's why it's possible to combine bitmap multicolor mode and text mode, like I did.

Below the actual game screen I have text zone that can be  switched to 4 different states: status, inventory, fight and messages like this:

To be continued ...

And that's all for now. The game is not in its final condition, but I'm working hard on it.

There are some things that I want to deal with:

  • Roleplay system. It'll be simple system with only 4 parameters and random numbers;
  • Level switching. The whole idea was about this. One level is about 6.64 Kb. According to the size of one diskette I can make about 17 levels (I think this number will decrease to 10 later). And I need to create separate textures and enemies for all of them.
  • Plot. I have some ideas but not the finished script.
  • Music. The biggest problem for me because I'm not a musician.
  • Optimising. Commodore 64 doesn't forgive mistakes so I need to concentrate on bugs.

Get Decade of Ruin (C64)

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.