I haven’t been doing much work on new projects recently. Mainly, I’ve been perusing my archives looking for interesting things to play around with. Some of them needed some light work to get working again but really I just wanted to experience them.

I did come across one old projects which I’ll talk about here: a game I called Side Scroller 95.  And yes, the “95” refers to Windows 95.

This was a remake of Side Scroller, a QBasic game I made back in the day. Having played around with Delphi programming after a while, and finding a bunch of DirectX 7 components, I set about recreating this game.  I’m not sure why I decided to remake this game vs. making something new. Was it because it was simple enough to try, or I found the levels interesting? Maybe? I can’t really say.

SS95 showing level E2M2.

Anyway, there wasn’t much to this game from the beginning. All the movement was cell based, with the usual assortment of solid tiles, hazards, and keys and locks (no pickups though). I eventually added a simple enemy as well: a robot which just went from left to right.

Level set 2 has the more interesting levels. This is S2E7, showing the player loose breath while underwater.
Level S2E8, with a "gold" tile scheme and backdrop.
Level S2E10, with a rainbow scheme and lots of invisible laser emitters.
Level S2E11, with an "underwater" scheme, which is just blues and greens. Also note the only enemy of the game, which was a robot that moved from left to right.

This project really showcases my crappy art skills at the time (I wish I could say they improved, but that would be a lie). The tiles and sprites were creating using MSPaint. This was back in the day when MSPaint was actually quite usable for pixel art, where drawing a rectangle actually rendered a rectangle then and there, rather than product an object which could be moved around (it’s just not the same now). The backgrounds were made by making gradients in Microsoft Word, taking a screenshot, and cropping them. And the sound effects were taken from the PC version of Metal Gear Solid (the WAV files were just sitting there on the file system).

The level editor. Unfortunately, it doesn't render well in Crossover so here's how it looks in Delphi 7's form designer.
The "Level Properties" form in the level editor, showing how Sprites were configured. Adding sprites were an absolute nightmare.

The game itself is pretty unremarkable, although I would say that one attribute that I really enjoyed doing is adding level scripts. These were Pascel scripts — interpreted by a Delphi control I found — that intercepted events, such as triggers or timeouts, and modified the level in some way. This was done late in the project, so it wasn’t used much, but it did make for some unique level-specific elements in the later levels. An example of one of the level scripts is provided below. This added platforms which ascended one cell at a time when activated. I forget most of what the built-ins did but I believe the OnActivateX hooks fired when a switch was triggered and the OnTimedEventX fired when a timer elapsed. 

unit LevelScr;

uses SSUTIL;

const
  INT_STX  = 0;
  INT_STY  = 1;
  INT_EDX  = 2;
  INT_EDY  = 3;

  INT_CURX = 4;
  INT_CURY = 5;

procedure LevSetupMove(sx, sy, ex, ey: integer);
begin
  SetStackInteger(INT_STX, sx); 
  SetStackInteger(INT_STY, sy);
  SetStackInteger(INT_EDX, ex);
  SetStackInteger(INT_EDY, ey);

  SetStackInteger(INT_CURX, sx);
  SetStackInteger(INT_CURY, sy);
end;

procedure OnActivate1(tag: integer; ison: boolean);
begin
  case tag of
    1: LevSetupMove(6, 9, 6, 5);
    2: LevSetupMove(18, 9, 18, 4);
    3: begin
     LevSetupMove(20, 19, 20, 16);
     Level.SetTile(21, 18, 52);
       end;
    4: LevSetupMove(11, 23, 11, 19);
    5: LevSetupMove(10, 23, 10, 17);
    6: LevSetupMove(9, 17, 9, 15);
    7: LevSetupMove(9, 15, 9, 13);
    8: LevSetupMove(9, 13, 9, 11);
  end;
  SetupTimer(1, 2, 1, true); 
end;

procedure OnActivate2(tag: integer; ison: boolean);
begin
  case tag of
    1: LevSetupMove(20, 20, 20, 16);
  end;
  SetupTimer(2, 2, 1, true); 
end;

procedure OnTimedEvent1(event: integer);
var cx, cy: integer;
begin
    
  cx := StackInteger(INT_CURX);
  cy := StackInteger(INT_CURY);

  if ((cx = StackInteger(INT_EDX)) and
    (cy = StackInteger(INT_EDY))) then
  begin
    ResetTimer(1);
  end
  else
  begin
    Level.SetTile(cx, cy, 12);
    cy := cy - 1;
    Level.SetTile(cx, cy, 13);

    SetStackInteger(INT_CURX, cx);
    SetStackInteger(INT_CURY, cy);
    PlaySound(11, false);
  end;
end;

procedure OnTimedEvent2(event: integer);
var cx, cy: integer;
begin
    
  cx := StackInteger(INT_CURX);
  cy := StackInteger(INT_CURY);

  if ((cx = StackInteger(INT_EDX)) and
    (cy = StackInteger(INT_EDY))) then
  begin
    ResetTimer(2);
    Explode(cy, cx);
  end
  else
  begin
    cy := cy - 1;
    Level.SetTile(cx, cy, 0);

    SetStackInteger(INT_CURX, cx);
    SetStackInteger(INT_CURY, cy);
    PlaySound(11, false);
  end;
end;

end.

One other hallmark of this project was completely gutting all the hard-coded logic and moving it into a game definition file. I build a pretty simple “game designer” tool which managed all the artwork, tile and sprite definitions, and also had custom logic implemented using that same Pascal interpreter I was using for the level scripts. I never used it for anything than the “Side Scroller” game, apart from a recreation of the File Platform game I also built way back when.

The game definition editor, showing the image tab.
How tile logic was configured. This was modelled after the triggers used in Red Alert's map editor.
How sprite logic was configured.
Game logic scripts, which was used to extend the built-in actions.

Again, nothing about this was remarkable, and for a long time I had no way to get this working. But thanks to Whisky I managed to launch this for the first time in ages and have a play. I don’t know when I’ll be able to do so again, nor whether it’s a good use of my time to try, so I recorded some screencasts of the gameplay which you can see here:

The desire to move away from cell-based movement and physics continued my drive in making platform based games in Delphi. I eventually managed to build such a game, which I will talk about once I can get it working again.