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


return the oldest one



   if ( i_head != i_tail )

      {

      is_event=1;



      event->type=in[i_head].type;

      event->sub_type=in[i_head].sub_type;

      event->x=in[i_head].x;

      event->y=in[i_head].y;

      event->data1=in[i_head].data1;

      event->data2=in[i_head].data2;



      i_head++;

      if ( i_head == MAX_INPUT )

         i_head=0;

      }



   return is_event;

}





/* ---------------------- main() ------------------------ October 8,1998 */

void main(void)

{

   int done=0;

   event_t event;



   printf("Alex Russell dos graphic course\n");

   printf("Press ESC to exit\n");



   read_joy_buttons();

   last_b0=b0;

   last_b1=b1;



   read_joy();

   last_joy_x=joy_x;

   last_joy_y=joy_y;



   init_keyboard();

   init_mouse();



   while ( !done )

      {

      if ( check_input(&event) )

         {

         switch ( event.type )

            {

            case JOY:

               switch ( event.sub_type )

                  {

                  case J_MOVE:

                     printf("JOY MOVE x %d y %d\n",

                        event.x, event.y);

                     break;



                  case J_BUTTON0:

                     printf("Button 0 is %s\n",

                        event.data1 ? "UP" : "DOWN");

                     break;



                  case J_BUTTON1:

                     printf("Button 1 is %s\n",

                        event.data1 ? "UP" : "DOWN");

                     break;

                  }

               break;



            case MOUSE:

               switch ( event.sub_type )

                  {

                  case M_MOVE:

                     printf("Mouse move x %d y %d\n",

                        event.x, event.y);

                     break;



                  case M_R_BUT_DOWN:

                     printf("MOUSE R Button DOWN\n");

                     break;



                  case M_R_BUT_UP:

                     printf("MOUSE R Button UP\n");

                     break;



                  case M_L_BUT_DOWN:

                     printf("MOUSE L Button DOWN\n");

                     break;



                  case M_L_BUT_UP:

                     printf("MOUSE L Button UP\n");

                     break;

                  }

               break;



            case KEY:

               printf("KEY %s = 0x%0x %d\n",

                  event.sub_type == KEY_UP ? "UP" : "DOWN",

                  event.data1, event.data1);



               if ( event.data1 == 1 ) // scancode for ESC is 1

                  done=1;

               break;

            }

         }



      }



   deinit_mouse();

   deinit_keyboard();



}



Chapter 4 Exercises1. Why is reading the joystick slow.2. What is the advantage of a single input queue containing input from all input devices?
3. What other types of events, other than mouse, keyboard, and joystick could go into an event queue?
4. Write a function to convert the scan codes for the normal a to z keys to ascii.
5. Many games do not require a fully analog joystick. Write a program that turns the joystick into a game pad. IE it only returns JOY_X_UP, JOY_X_DOWN, JOY_X_CENTRE, and the same codes for y. Assume the joystick is centred at the start of the program, and that 1/3 from centre is the threshold for movement.
6. Why is polled input not desirable, especially for the mouse.


Chapter 5


Collision Detection
Collision detection is figuring out when one object has hit another. For example you want to know when a bullet travelling across the screen has hit on the of sprites that represents an alien craft. We will cover the basics of collision detection in detail, and advanced methods will only be discussed briefly.
Detecting a point in a rectangle.This is simple, the point is in a rectangle if both its x and y coordinate are within the rectangle.



typedef struct

   {

   int x, y;

   }

point_t;



typedef struct

   {

   int x0, y0, x1, y1;

   }

rect_t;



point_t p;

rect_t r;



p.x=100;

p.y=100;



r.x0=50;

r.y0=50;

r.x1=150;

r.y1=120;



if ( p.x >= r.x0 && p.x <= r.x1 && p.y >= r.y0 && p.y1 <= r.y1 )

   {

   // it has hit

   }



// and how to check that the pixel is NOT in the rectangle

if ( p.x < r.x0 || p.x > r.x1 || p.y < r.y0 || p.y > r.y1 )

   {

   // point is not in the rect

   }



rect_t  r1, r2;



// Check for r1 in r2

if ( r1.x0 >= r2.x0 && r1.x1 <= r2.x1 && r1.y0 >= r2.y0 && r1.y1 <= r2.y1 )

   {

   // r1 is in r2

   }



//This checks for r1 NOT in r2

if ( r1.x0 > r2.x1 || r1.x1 < r2.x0 || r1.y0 > r2.y1 || r1.y1 < r2.y0 )

   {

   // r1 does not touch r2

   }



Special CasesIf the rectangles to be checked are tiled you do not check each tile one after the other. Instead you directly calculate which tile the point is on.



int w;    // width of tile

int h;    // height of tile

int tile_x, tile_y;

point_t p;



p points to a pixel. We want to know which tile it is on. Each tile has its own (x, y) coordinate where each tile is counted as 1 coordinate value.


tile_x=p.x / w;

tile_y=p.y / h;



Pixel-wise Collision DetectionUsually comparing one rectangle to another gives a close enough collision for a game, but when collision must be accurate to the pixel because of irregular shaped sprites you can compare the bitmaps using pixel-wise collision detection.
Only one colour is transparent in a sprite, and if you use zero it simplifies pixel-wise collision detection because you can then test for collisions using the logical `and' operation.
Sometimes you cam also check for collisions by checking the colour of the pixels on the screen under the moving object. This generally only works for games with simple artwork.
http://www.strangecreations.com has good articles on collision detection.
Colour managementMode13h supports 256 colours selected from almost 300,000 colours. The BIOS can be used to set the current palette of colours, but as usual that is the slowest method. The palette can be set by directly using the ports on the VGA. To prevent snow and flicker the palette is only changed during the vertical blank.
This is the code to set the whole palette.



unsigned char palette[768];   // 256 colour, 3 bytes each = 768 bytes



void set_palette(unsigned char *p)

{

// wait for vertical re-trace

   while ( inportb(INPUT_STATUS_0) & 8 )

      ;

   while ( !(inportb(INPUT_STATUS_0) & 8) )

      ;



asm   {

         /* set palette, taking advantage of the auto-increment feature */

         xor   al, al   // set al to zero, the first colour to set

         mov   dx, 03c8h      // port for the vga palette control

         out   dx, al     // tell the vga we want to change colours, starting with zero

         mov   cx, 768     // number of bytes to send

         mov   si, p     // si points to the colours to copy over

         mov   dx, 03c9h   // port to send the colours to

         rep   outsb           //  send the palette values over

         }

}


And to set part of the palette. Start is the first colour to be changed, and num is the number of sequential colours to set.



/* ---------------------- setvga_part_palette() ---------- March 28,1993 */

void setvga_part_palette(char *p, short start, short num)

{



   p+=start*3;

   num*=3;



      // wait for vertical re-trace

   while ( inportb(INPUT_STATUS_0) & 8 )

      ;

   while ( !(inportb(INPUT_STATUS_0) & 8) )

      ;



   asm   {

         /* set partial palette */

         mov   ax, start

         mov   dx, 03c8h

         out   dx, al

         mov   cx, num

         mov   si, p

         mov   dx, 03c9h

         rep   outsb

         }

}



Where do you get palettes? You extract them from the drawing files. The VGA palette only uses 6 bits for each RGB value, but most files store them using 8 bits. If you load a palette and all the colours are wrong then you can often correct this by shifting each RGB value to the right by 2 as was done in the PCX file reading code.
Being able to change the palette as you wish allows you to use a wider variety of art and colours making your game more interesting. It is important to plan the use of the 256 colours that are available. One idea is to reserve the first 16 colours for common elements that appear throughout the game, for example the colours used in the user interface. You also might want to reserve colours for special effects like colour cycling.
Colour CyclingColour cycling is a technique that gives the illusion of movement by changing the palette rapidly. Usually a set of colours is set to gradually change from a start colour to a middle colour, and back to the start colour. If you then draw a filled rectangle with one of these colours and cycle the colours the rectangle will appear to rotate. Colour cycling can be used for water and fire effects also. To cycle colours means to move all the colours in the set forward by one, and move the last colour back to the beginning. This is repeated at regular intervals.
Code to cycle a set of colours.



/* do colour cycling, starting with color start, num sequential colors */

/* ---------------------- cycle_palette() ---------------- March 28,1993 */

void cycle_palette(short start, short num)

{

   BYTE t[3];

   short x1, x2, len;



   num--;

   len=num*3;





   x1=start*3;

   x2=len + x1;



   /* cycle the palette  */

   memcpy(t, palette+x1, 3);

   memmove(palette+x1, palette+x1+3, len);

   memcpy(palette+x2, t, 3);



   /* set new palette */

   num++;

   setvga_part_palette(palette, start, num);

}



Timing a game, and game designTime spent planning your game will save you huge amounts time and effort with the programming. Before starting ANY programming plan out your game. Think about what data elements you will need to track, how the user will control the game. What functions and systems will be required to draw the game, and calculate all the game logic. Often you will want to write tools to speed

Page : << Previous 9  Next >>