Topic : DOS Game Programming
Author : Alexander Russell
Page : << Previous 10  Next >>
Go to page :


up development of your game, e.g. level editors.
One thing that will greatly simplify game design, and making additions to the game, is to separate the drawing of the screen from the game's logic. By logic I mean any code that moves things, calculates things, times things, or otherwise controls the game.
Testing is an important aspect of any programming project. The best way to test a new function is to plug it into a SMALL test program before adding it to the main program code. Always make test code as simple as possible so that you are testing the new code, not the test stub.
Another concern is to time things so that the game runs at the same speed on computers of different speeds. This is done by using a timer on the PC that runs at the same speed on all PC's. One easy to use timer for DOS games is the BIOS TICK. This is an unsigned long integer that increases by one 18.6 time per second.



// PC bios data area pointer to incrementing unsigned long int

#define TICKS       (*(volatile unsigned long far *)(0x0040006CL))



In practice this timer is a bit on the slow side to provide smooth animation. The PC also provides a timer that can generate an int8 at programmable intervals. We can then hook an ISR to this interrupt and use it to time all the game events. Many PC music and sound packages also use this interrupt and provide some sort of timing function. Do not change the int8 timer if using a music package that is also using the int8 service.
NOTE: the int8 timer is used to time many DOS and BIOS functions. The old timer interrupt should be called at approximately its original rate of 18.6 times per second.
Installing an int8 timer, and programming it to run at 60Hz


volatile unsigned long fast_tick, slow_tick;

static void interrupt (far *oldtimer)(void);   /* BIOS timer handler */



void deinit_timer(void);





/*



   You don't have to call the old timer, but if you don't

   you have to write some code to cleanup in de-init that

   fixes DOS's internal clock.



   Its also considered 'good form' to call the old int.

   If everyone does, then everything that other TSR's etc...

   may have installed will also work.



   If you skip the little chunk of ASM code- the out 20-

   you WILL LOCKUP all interrupts, and your computer



   Anyways, this test replacement just increments a couple of

   long ints.

*/

/* ---------------------- new_timer() ------------------- August 23,1994 */

static void interrupt new_timer(void)

{

   asm cli

   fast_tick++;



   if ( !(fast_tick & 3) ) // call old timer ever 4th new tick

      {

      oldtimer();  // not the best way to chain

      slow_tick++;

      }

   else

      {

      // reset PIC

      asm {

          mov al, 20h

          out 20h, al

          }

      }



   asm sti

}





/* see that 1st line of inline asm?



   to set whatever clock speed you want load

   bx with 1193180/x where x is the clock speed you want in Hz.



*/

/* ---------------------- init_timer() ------------------ August 23,1994 */

void init_timer(void)

{



   slow_tick=fast_tick=0l;

   oldtimer=getvect(8); // save old timer



   asm cli



   // speed up clock

   asm {

         mov     bx,  19886     //  set the clock speed to 60Hz (1193180/60)

         mov     al,  00110110b

       out     43h, al

         mov     al,  bl

   out     40h, al

       mov     al,  bh

         out     40h, al

      }



   setvect(8, new_timer);



   asm sti

}





/* ---------------------- deinit_timer() ---------------- August 23,1994 */

void deinit_timer(void)

{

   asm cli



   // slow down clock   1193180 / 65536 = 18.2, but we use zero



   asm {

         xor bx,  bx          // min rate 18.2 Hz when set to zero

       mov al,  00110110b

         out 43h, al

   mov al,  bl

       out 40h, al

         mov al,  bh

   out 40h, al

      }



   setvect(8, oldtimer);  // restore oldtimer



   asm sti


}



Now that we have a timer how is it used to time things? For each element in the game that must be timed we store a number that indicates the NEXT time it should move. This number is set by getting the current time, and adding to it.
Example of timing the movement of a pixel


int x,y;  // pixel location

int dx, dy;  // speed of pixel

unsigned long next_time;

int done=0;

int loop;



x=100;

y=100;



dx=1;

dy=1;



next_time=fast_tick + 3;  // fast tick is incremented by the int8 ISR



while ( !done )

   {

   // if the computer is quick, we may draw the pixel many times without moving.

   if ( fast_tick >= next_time )

      {

      // if the computer is slow, we may have to move the pixel more than once

      // for it to be were it belongs

      loop=fast_tick - next_time;

      

      while ( loop-- )

         {

         x+=dx;

         y+=dy;

         }



      next_time=fast_tick + 3;

      }

   

   put_pixel(x,y, 5);

   update_buffer();

   }



This timing technique causes slow computers to keep up by `skipping' frames (also referred to as `dropping' frames). The animation will not be smooth, but things will move at the correct speed. Usually you should try to aim at your game running at about 60 frames per second on whatever computer is current without skipping frames. 30 frames per second is the minimum for smooth animation.
Chapter 5 Exercises1. Write a program that draws a filled rectangle in the centre of the screen, and bounces one pixel. If the pixel hits the centre rectangle it will bounce, and the rectangle will change colour.2. Write a program that draws a filled rectangle in the centre of the screen, and bounces one pixel. If the pixel hits the centre rectangle it keeps going straight, and the rectangle changes colour until the pixel is no longer touching it.
3. Write a program that bounces 3 small sprites. The spites will bounce off the `walls' and each other.
4. Write a program that fills the screen with rectangles as wide as the screen that alternate with two colours. When the space bar is pressed have the second colour change to the first colour. A second press of the space bar restores the original colour.
5. Write a program to extract the palette from a PCX file, and store it to a second file.
6. You have written a game that has a information screen at the bottom, and the top displays a playing field that changes dramatically with each level including changing all the colours used. What will happen to the bottom score board when you change levels?
7. Write a program that changes the colour of a solid rectangle using colour cycling.
8. Write a program that makes a series of narrow rectangles appear to scroll using colour cycling.
9. Write a program that bounces one sprite on the screen. Pressing Q will speed it up, Pressing A will slow it down. Use a timer to control its speed. How else could you change its speed?
10. What are three (of many) things you should plan before starting programming a game.


Chapter 6


Break Out
In this chapter we are going to develop a simple game of Break Out. There will be two sections of bricks at the top of the screen, a paddle at the bottom, and the score and number of balls remaining at the very top. We will support the mouse, and joystick to move the paddle, and allow the user to select the joystick at the start of the game. A plain background will be used. The bricks will be rectangular bitmaps, the ball a small sprite. The ball will speed up every time it hits 5 bricks. The bricks in each row will be worth one point more than bricks in the previous row. We will not be supporting any fancy options like laser paddles. The ball will bounce at different angles depending on where it hits the paddle.
Code we will need:Load sprites into memory
Draw paddle
Draw ball
Draw initial screen
Draw score
Erase hit brick
Move ball
Move paddle
Detect collision with brick
Bounce off paddle with varying angles.
Time everything
Art we will need:Paddle
Ball
Bricks
Background (?)
Utilities we will need:Drawing program
Convert

Page : << Previous 10  Next >>