View Single Post
Old 19 April 2021, 15:32   #1
pink^abyss
Registered User
 
Join Date: Aug 2018
Location: Untergrund/Germany
Posts: 292
Wrong Way Driver - Tech

Some people wanted to hear more about how Wrong Way Driver was created.

Here are some details:

The game is written for OCS A500 + 512kb (tho with some extra work it would fit into 512kb only).

C++20
The game was born out of an experiment if it would be possible to code a fast Amiga 500 game
using C++20 with Coroutines and Lambdas. Bartmans "Amiga C/C++ Compile, Debug & Profile" which i used
has support for them. I guess this is the very first C++20 program written on any Amiga computer

Coroutines
Coroutines let you 'pause' or 'yield' your code and continue later at the same point. The context for
them is not stored on the stack but on a heap. Here is a pseudo example how i used them in the title screen
to move the logo, print some text and wait for the fire button in parallel by launching another coroutine.

Code:
coroutineHandler.add([&]() -> coro
{
   //move in the logo 
   for(int x=-160;x<160;x++)
   {
      showLogo(x);
      co_yield 0; //wait for next frame
   }

   co_yield 50; //wait 50 frames

   //add another coroutine to wait for fire button in parallel
   coroutineHandler.add([=]() -> coro
   {
       while(1)
       { 
          if(fireButtonPressed())
             gGame.setState(Game::State::intro);

          co_yield 0;
       }
   }

   //show blinking text
   while(1)
   {
      auto text=printText("Press Fire!);
      co_yield 20;
      clearText(text);
      co_yield 20;
   }
}
"coroutineHandler" is a container for the coroutines. The coroutineHandler is embedded in the current gameState and 'ticked' from there.
If i change the gameState then the coroutineHandler gets deleted. So i don't have to care about dangling coroutines.

Memory Managment
For this game i used again no dynamic memory managment (so no 'new' and 'delete', but only placement 'new'). I used preallocated Frame- and Poolheaps.
I described such heaps already for Tinyus Tech.

Sprites
Sprites are used for the "WRONG WAY DRIVER" and "ABYSS" logo and all HUD elements like the coin/gas counter and score display.
On the title screen i use 3 color sprites, and when playing the game i use attached 15 color sprites.
A single 128x224 sized area, with two bitplanes, is used for all sprites. A software driver sorts, splits, blits and multiplexes them into this
area each frame as needed. Writing an optimal sprite driver is a madmans task.

The city skyline
The city area uses dual playfield for parallax scrolling. Various copper splits are used to make it look
like more then two playfields. Also sprites are displayed above to make it look like 4 parallax layers are there.

The pseudo 3D street
The street is created with 5 parallaxed stripes. Each uses 16 frames of animation (3kb altogether packed).
They are blitted into the backbuffer and into the restorebuffer each frame.
The different cars, coins and gas symbols are just one image each. On startup i precalc 11 zoom images for each of them.
The street area runs in 4 bitplanes. I used two coppersplits to parallax animate the front and back side of the street.

Bobs
I use 16 and 32 pixel wide bobs for all zooming objects. Each bob can have a variable height.
For optimal performance i blit all of those after waiting for the last displayed line.

Audio
All insturments+fx take 34kb, and are precalced on startup (Pretracker!).
Channel 4 is used mainly for delay sounds and can be interrupted by SoundFx.

Game size
The game was crunched with Shrinkler from 135kb to to 61kb. The large size is mainly because of the used GCC optimizations (lto,-Ofast).
Without GCC optimizations the game is only half as big. By sprinkling #pragmas over non time critical code the size could be further reduced.


Thanks for reading.

Last edited by pink^abyss; 20 April 2021 at 15:02.
pink^abyss is offline  
 
Page generated in 0.06514 seconds with 11 queries