game programming workshop

132
Beginning Game Programming Murray State University Computer Science and Information Systems Dr. Bob - [email protected]

Upload: narigadu

Post on 12-May-2015

639 views

Category:

Entertainment & Humor


5 download

TRANSCRIPT

Page 1: Game programming workshop

BeginningGame Programming

Murray State UniversityComputer Science and Information Systems

Dr. Bob - [email protected]

Page 2: Game programming workshop

This Workshop

The goal of this workshop is to give you a head start in beginning your study of game programming.

CD - Includes C/C++ compiler and code editor (IDE), Allegro 4.2 game development software library, tutorials and demo programs, other software tools useful for creating computer games.

Workshop covers:

Overview of Game Programming

How to Install C/C++ Compiler and Allegro

Using the Integrated Development Environment (IDE)

Running, reviewing, and modifying demo programs.

Page 3: Game programming workshop

Game Programming as a Career

Computer game development is probably the most rapidly growing field in high technology today, but it is important to understand that you need to keep your options open.

"People looking at games courses… [should] consider what else you might be able to do if you can't get into the industry, where else you can go... somebody studying computer science, maths, or physics and then coming into a programming role, means that they can then go off into a number of different industries and be successful."

- Matthew Jeffrey (Head of Global Talent Brand at EA)

"Developers are considering applicants who have more general degrees (such as in computer science or fine art), even though these programs don't always give their students industry-specific training."

- Ben Kuchera (Opposable Thumbs journal)

Page 4: Game programming workshop

"In my school, I had a game project with a random team. I did all the work while they played guitar hero and occasionally contributed barely-usable code (despite multiple efforts to engage them). I got a job and they did not. Could there be a correlation?!? I think there is! "

- Quasius

"I'm a programmer. I left the game industry and now I have better pay, much lower hours, and more flexibility (work from home, set my own hours). Now I actually have time to play games."

- nvanderh

“More and more companies are recruiting right from colleges. Regardless, of what college you go to, you can still get a job in the games industry provided you have a certain proficiency in the following areas.” Math, Physics, Extensive knowledge of C++, AI Programming, Graphics, Tools Development, Operating Systems, and Compilers."

- Matt Gilgenbach, a video game developer

Comments from Game Developers

Page 5: Game programming workshop

Why Game Programming?

FORTUNE! GLORY! FUN!Programming games can be more fun than playing them.

Computer/Video Game Industry is now larger than the Movie Industry

A great new game can make its creator famous.

Game programming teaches many computer science (CS) topics:

Real-Time Systems Issues

Modeling/Physics

Graphics and Animation

Sound Generation

Graphical Design and Layout

Human/Computer Interfaces

Scientific Visualization

:

:

Page 6: Game programming workshop

Types of Games

Classic Arcade

1st Person Shooter

RPG

Sports/Racing

Board Games

Adventure/Puzzle Solving

Flight Simulators

World Simulations

Strategy/Wargames

Fighting Games

Page 7: Game programming workshop

Can One Person Still Write a Great Game ?

While many popular computer games are the result of 100s of programmers, designers, writers, artists, and producers, there is still a place for the lone programmer. The growing popularity of online (e.g. applet-level) games and games on PDA's, handhelds, and even cell-phones need great games. Lone programmers and small start-up game companies can fill this need.

YES!

Page 8: Game programming workshop

Great Games come from Great Ideas

Each of the types of games started out as one game and one person's idea.

Page 9: Game programming workshop

Establishing and Maintaining a Game Theme

One of the most important and most difficult parts of game design is a finding a good theme. The theme of a game affects the mood of the player. It is important to put some thought into choosing an good theme before jumping into the details of game design and development. Keep the theme of your game in mind as you design game objects, the background and characters, choose sounds, and decide on the order of the action.

Page 10: Game programming workshop

The Game Loop

UpdateGame State

Get User Input

Sound

Graphics

Setup Game

done?

Stop Game

no

yes

wait

time through loop must be short and the

same for each pass

the amount of waitdepends on what else

has been done in this pass

Page 11: Game programming workshop

Why Use Dev_C/C++ and Allegro

Open Source - That is to say, FREE!!!

Runs on PC's, or Mac's using most any Operating System:

Hugh Developer Network & Many User/Support Groups

http://alleg.sourceforge.net/wip.html

http://www.allegro.cc/

Large Number of Games and Software Tools Available

• Microsoft Windows • Linux• Mac OS X• Solaris• BeOS• FreeBSD

Page 12: Game programming workshop

Enough Talk Already!Let's Get Started!!!

Installing Dev_C/C++

Open your Game Programming Workshop CD and copy the file named devcpp-4.9.9.2_setup.exe to your computer's desktop.

Run this install program. (Use the default values for all options.)

Find and open the Dev_Cpp folder on your computer (This folder should be installed at the root level, i.e. at C:\ )

Copy the folder named Test_Dev_Cpp from the CD into this folder.

Double click on the Dev-C++ desktop icon to launch the compiler.

Under File, choose Open Project or File..., and from inside the Dev-Cpp Test folder, select Test_Dev_Cpp.dev.

Under the Execute menu, select Compile and Run.

Page 13: Game programming workshop

Loading the Allegro Software Library

Open the Allegro-minGW-4.2.0 folder on your CD.

Open the Dev_Cpp folder on your computer. Locate the folders named lib and include.

Copy the contents of the lib folder on the CD into the lib folder on your computer. (Note: Don't copy the folder, just its contents.

Copy the contents of the include folder on the CD (including the sub-folder named allegro) into the include folder on your computer.

Copy the contents of the bin folder on the CD into the C:\Windows\System32\ folder on your computer. (These are files with a .dll extension)

From your CD copy the folder named Test_Allegro into the Dev_Cpp folder on your computer.

From the File menu, choose Open Project or File... and select Test_Allegro.dev.

From the Execute menu, choose Compile and Run.

Page 14: Game programming workshop

Wow! That was easy...Now we are ready to create our own projects.

1. Click on New Project taskbar icon.

2. Create an Empty Project named First_Project3. Create a new source file called main.cpp and add it to the current project.

Page 15: Game programming workshop

Wow! That was easy...Now, we will learn how to create our own project...

4. Right-click First_Project and choose Project Options5. Under the General Tab select Win32 GUI Type

6. Under Parameters Tab add the line -lalleg to Linker and click on OK.

You are now ready to begin writing a graphics program.

Page 16: Game programming workshop

#include <allegro.h>

int main(void)

{

allegro_init();

allegro_exit();

return 0;

}

END_OF_MAIN()

First_Project

// includes allegro library in project

// starts and ends allegro// graphics commands go between these lines

Enter this text in the editor, save, compile and run it.

Since there are no graphics commands, nothing will appear but you should get an error-free compile.

Page 17: Game programming workshop

What Happened?If you typed everything correctly your program should have compiled and run with no messages and no display. Otherwise you will see error messages... The first error wll be

highlighted in the text with a message trying to tell you what when wrong.

Fix each error in the order they appear and only one at a time. This is because the error checker is a dumb program that can get lost.

This problem is so common it has a special name:

ERROR PROPAGATION

Page 18: Game programming workshop

#include <allegro.h>

int main(void)

{

allegro_init();

set_gfx_mode(GFX_SAFE, 640, 480, 0, 0);

install_keyboard();

while(!key[KEY_ESC]);

allegro_exit();

return 0;

}

END_OF_MAIN()

First_Project

Now add these lines between allegro_init() and allegro_exit(): set_gfx_mode( ) defines a display 640 x 480 pixels install_keyboard( ) lets your program take command from the keyboard while(!key[KEY_ESC]) tells the program to wait on this line until the ESC key has been pressed

Page 19: Game programming workshop

#include <allegro.h>

int main(void)

{

allegro_init();

set_gfx_mode(GFX_SAFE, 640, 480, 0, 0);

install_keyboard();

while(!key[KEY_ESC]);

allegro_exit();

return 0;

}

END_OF_MAIN()

First_Project

When we run the program this time, a rectangular display window named First_Project should appear with a black background. This is the window that will display the graphics, when we tell the program what to display.

Allegro gives this window the name, screen.

The whle( ) statement tells the program to wait until the user presses the ESC key.

Page 20: Game programming workshop

Drawing in the Graphics Window

#include <allegro.h>

#define BLUE makecol(0,0,255)

int main(void)

{

allegro_init();

set_gfx_mode(GFX_SAFE, 640, 480, 0, 0);

install_keyboard();

rect(screen,50,60,150,160,BLUE);

while(!key[KEY_ESC]);

allegro_exit();

return 0;

}

END_OF_MAIN()

defines the color BLUE using red, green, blue (RGB) values

this statement tells the program to draw a rectanglein the graphics window withone corner at x=50, y=60 andthe opposite corner at x=150and y=160 (100x100 pixel box)

Page 21: Game programming workshop

A Closer Look

640

480

0,0

each point in this window is defined by a pair of numbers (x,y)

640,0

50,60

150,160

incr

easi

ng y

increasing x

rect(screen,50,60,150,160,BLUE)

Page 22: Game programming workshop

RGB Color Values

Each value is a number between 0 and 255.

Mixing Light is additiveso 255,255,255 makeswhite

255,0,0

255,0,255

255,255,0

0,255,0

0,0,255

0,255,255

0,0,0 = BLACK makecol(rval,gval,bval) can beused to create over 16 millioncolors

Page 23: Game programming workshop

Try These Drawing Commands

int my_color;

my_color = makecol(255,255,0);

putpixel(screen,320,240,my_color);

line(screen,10,100,630,100,my_color);

rectfill(screen,200,300,250,370,makecol(100,0,200));

circle(screen,230,110,30,makecol(50,200,10));

circlefill(screen,500,400,10,makecol(0,0,100));

ellipsefill(screen,185,210,100,30,makecol(50,50,50));

ellipsefill(screen, 180,200,100,30,makecol(255,0,0));

ellipse(screen, 175,195,100,30,makecol(255,180,180));

Page 24: Game programming workshop

Example Shapes

putpixel(screen,320,240,my_color);

line(screen,10,100,630,100,my_color);

rectfill(screen,200,300,250,370,makecol(100,0,200));

circle(screen,230,110,30,makecol(50,200,10));

circlefill(screen,500,400,10,makecol(0,0,100));

ellipsefill(screen,185,210,100,30,makecol(50,50,50));ellipsefill(screen, 180,200,100,30,makecol(255,0,0)); ellipse(screen, 175,195,100,30,makecol(255,180,180));

Page 25: Game programming workshop

A First Look atANIMATION

x = max_x/2; y = max_y/2; vx = 2; vy = -3; while(!key[KEY_ESC]) { xold = x; yold = y; x = x + vx; y = y + vy; if(x<=radius || x>=max_x-radius) vx = -vx; if(y<=radius || y>=max_y-radius) vy = -vy; circle(screen,xold,yold,radius,BLACK); circle(screen,x,y,radius,BLUE); rest(20); }

x,y is the ball position (starts in the middle of the screen

the speed of the ball in the x and y directions - vx,vy

old position of ball

new position of ball

if ball reaches the edge, it bounces off (v = -v)

erase (undraw) old balldraw new ball

wait awhile (milliseconds)

Page 26: Game programming workshop

Bouncing Ball Demo

Copy the folder named BouncingBall_Demo_01 from your CD to the Dev-Cpp folder on your computer.

Open this folder and then load the project BouncingBall_Demo_01.dev

Compile and Run this program

Modify the values of vx, vy and the value in the rest( ) function. With each change, run the program and notice the effect of your changes.

motion in x direction andy direction are kept separate

position of ball as a function of time is p = p0 + v0t + 1/2 at2

Note the scaryPhysics Formula

Page 27: Game programming workshop

install_keyboard();while(!key[KEY_ESC]) { pxold = px; pyold = py; x = x + vx; y = y + vy; px = (int)x; py = (int)y; //watch out for sticky walls if(px<=radius || px>=max_x-radius) vx = -vx; if(py<=radius || py>=max_y-radius) vy = -vy; circle(screen,pxold,pyold,radius,BLACK); circle(screen,px,py,radius,BLUE); rest(20); if(key[KEY_LEFT]) vx = vx - 0.1; if(key[KEY_RIGHT]) vx = vx + 0.1; if(key[KEY_UP]) vy = vy - 0.1; if(key[KEY_DOWN]) vy = vy + 0.1; }

Making a Program Respond to User Keyboard Entry

keyboard entryarrow keys change the x and y velocity of the ball

Page 28: Game programming workshop

Interactive Bouncing Ball Demo

Copy the folder named BouncingBall_Demo_02 from your CD to the Dev-Cpp folder of your computer

Open the project and run it.

Notice the effect of holding down one or more of the arrow keys.

End the program and review the source code for the user actions.

Modify the program and add key controls (such as the digit keys) to change the color or size of the ball.

circle(screen,px,py,radius,BLUE);

Allegro defines KEYS as,

A = KEY_A 1 = KEY_1 : Z = KEY_Z

Page 29: Game programming workshop

play_sample(sample_filename, volume, panning, pitch, FALSE);

Sound

Allegro gives us an easy way to add sound to our game programs.

name of sample sound file to play

volume 0 to 255

speaker balance 0 to 255 (128 for equal balance)

frequency at which sample sound is played (1000 is normal)

looping (repeat sound) FALSE = no, TRUE = yes

Page 30: Game programming workshop

SAMPLE *boing1;SAMPLE *boing2;if (install_sound(DIGI_AUTODETECT, MIDI_NONE, "") != 0) { allegro_message("Error initializing sound system"); return 1;}boing1 = load_sample("boing1.wav");boing2 = load_sample("boing2.wav");

Adding Sound to the Bouncing Ball

Before using the play_sample( ) function, we have to tell the computer which sounds we will be playing. Add this code to BouncingBall_Demo_02 near the top of main.cpp (just after install_keyboard( ) will be fine).

Copy the sound files boing1.wav and boing2.wav from the Sound Files folder into the BouncingBall_Demo_02 folder.

Page 31: Game programming workshop

if (px<=radius || px>=max_x-radius){ vx = -vx; play_sample(boing1, 128, 128, 1000, FALSE);}

if (py<=radius || py>=max_y-radius){ vy = -vy; play_sample(boing2, 255, 128, 1000, FALSE);}

Now add the play_sample( ) functions to the bounce detection code. Since we are adding a second line of code to the if statements, we will need to add curley brackets to hold them. Otherwise the program will not know that the sound files should be played only when the conditional statement in the if( ) is true

After modifying and running your version of the Bouncing Ball, try running BouncingBall_Demo to compare. In this version we set the pitch based on the speed of the ball...

Page 32: Game programming workshop

SAMPLE *sample1; SAMPLE *sample2; int panning = 128; int pitch = 1000; int volume = 128;

//initialize the program allegro_init(); install_keyboard(); install_timer(); set_gfx_mode(MODE, WIDTH, HEIGHT, 0, 0);

//install a digital sound driver if (install_sound(DIGI_AUTODETECT, MIDI_NONE, "") != 0) { allegro_message("Error initializing sound system"); return 1; }

WAV Sound Demoleft-right balance, volume, & pitch control

Page 33: Game programming workshop

//display program informationtextout_ex(screen,font,"PlayWave Program (ESC to quit)",0,0,15,0);textprintf_ex(screen,font,0,10,15,0,"Snd Driver: %s",digi_driver->name);textout_ex(screen,font,"Playing clapping.wav...",0,20,15,0);textout_ex(screen,font,"Left,Right - Pan Left,Right",0,50,15,0);textout_ex(screen,font,"Up,Down - Pitch Raise,Lower",0,60,15,0);textout_ex(screen,font,"-,+ - Volume Down,Up",0,70,15,0);

//load the wave filesample1 = load_sample("evil_laugh.wav");sample2 = load_sample("clapping.wav");

if (!sample1 || !sample2) { allegro_message("Error reading wave file"); return 1;}

//play the sample with loopingplay_sample(sample1, volume, panning, pitch, TRUE);play_sample(sample2, volume, panning, pitch, TRUE);

Page 34: Game programming workshop

while (!key[KEY_ESC]) { //change the panning if ((key[KEY_LEFT]) && (panning > 0)) panning--; else if ((key[KEY_RIGHT]) && (panning < 255)) panning++;

//change the pitch (rounding at 512) if ((key[KEY_UP]) && (pitch < 16384)) pitch = ((pitch * 513) / 512) + 1; else if ((key[KEY_DOWN]) && (pitch > 64)) pitch = ((pitch * 511) / 512) - 1;

//change the volume if (key[KEY_EQUALS] && volume < 255) volume++; else if (key[KEY_MINUS] && volume > 0) volume--;

//adjust the sample adjust_sample(sample1, 255-volume, 255-panning, pitch, TRUE); adjust_sample(sample2, volume, panning, pitch, TRUE);

//pause rest(5);}

destroy_sample(sample1);destroy_sample(sample2);remove_sound();

Page 35: Game programming workshop

PongThe First Computer Game

We are going to look inside PONG, the first computer

game.

review Pong_Demo_01& Pong_Demo_02

Page 36: Game programming workshop

Deconstructing Pong

game space

the game is played in a rectangular box

ball

the ball travels in a straight line until hitting an obstacle

ball bounces off top and bottom of game space

bounces off right face of left paddle and left face of right paddle

if ball encounters sides of game space point is scored and play restarts

left and right paddles

paddles stay on sides of game space can move up and down only

paddles can put "english" on ball if ball hits near the top or the bottom

scoreboard

keeps a record of players scores - first to 11 wins

Page 37: Game programming workshop

init allegro

init

init variables

new game?

save old positiions

end loop

game loop

ball at top orbottom

ball hit paddle

ball miss paddle

quit game?

update scoreboard

players input

animate

score & reset

return ball

bounce ball

paddles at topor bottom stop paddle

exit allegro

Pong GameBlock Diagram

yes

no

Page 38: Game programming workshop

// initialize game state padLeftX = 20; // left paddle x-position padRightX = SCREEN_W - 20; // right paddle x-position padLeftY = SCREEN_H/2; // left paddle y-position padRightY = SCREEN_H/2; // right paddle y-position bxi = SCREEN_W/2; // starting ball x-position byi = SCREEN_H/2; // starting ball y-position bvyi = 0; // starting ball y-velocity bvxi = 2; // starting ball x-velocity bx = bxi; // ball x-position by = byi; // ball y-position bvx = bvxi; // ball x-velocity bvy = bvyi; // ball y-velocity Lcount = 0; // left-player score Rcount = 0; // right-player score

Initialize Game State - PONG

Page 39: Game programming workshop

// check for game quit if (key[KEY_ESC]) done = true; // save current paddle and ball positions before updates padLeftYold = padLeftY; padRightYold = padRightY; bxold = bx; byold = by; // update ball position bx += bvx; by += bvy;

// bounce ball off top and bottom of game space if (by <= 0 | by >= SCREEN_H) bvy = -bvy;

Top of Main Loop - PONG

Page 40: Game programming workshop

// manage ball hitting left paddle if ((bx <= padLeftX + padWidth/2) & (abs(padLeftY - by)<=padHeight/2)) { bx = padLeftX + padWidth/2; bvx = - bvx; bvy = 0; if (padLeftY-by<-padHeight/5) bvy = + 1; if (padLeftY-by>padHeight/5) bvy = - 1; if (padLeftY-by<-padHeight/4) bvy = + 2; if (padLeftY-by>padHeight/4) bvy = - 2; }

// manage ball hitting right paddle if ((bx >= padRightX - padWidth/2) & (abs(padRightY - by)<=padHeight/2)) { bx = padRightX - padWidth/2; bvx = - bvx; bvy = 0; if (padLeftY-by<-padHeight/5) bvy = + 1; if (padLeftY-by>padHeight/5) bvy = - 1; if (padRightY-by<-padHeight/4) bvy = + 2; if (padRightY-by>padHeight/4) bvy = - 2; }

Manage Ball Hitting Paddle - PONG

Page 41: Game programming workshop

if(padLeftY<padHeight/2) padLeftY = padHeight/2;

if(padLeftY>SCREEN_H - padHeight/2) padLeftY = SCREEN_H - padHeight/2;

if(padRightY<padHeight/2) padRightY = padHeight/2;

if(padRightY>SCREEN_H - padHeight/2) padRightY = SCREEN_H - padHeight/2;

Checking Game Space Limits

padHeight

padLeftY

(0,0)

?

After player inputs have been handled the new positions of the movable objects need to be checked to ensure that they are within the game space limits. What to do to keep the objects inside the game space depends on the object's function. For the paddles, you can just replace the new position with the limiting position as if it has hit a boundary.

Page 42: Game programming workshop

// manage ball missing left paddle if (bx < padLeftX + padWidth/2) { rectfill(screen,0,0,SCREEN_W,SCREEN_H,BLACK); Rcount += 1; bx = bxi + SCREEN_W/3; by = byi; bvy = 0; bvx = -bvxi; } // manage ball missing right paddle if (bx > padRightX - padWidth/2) { rectfill(screen,0,0,SCREEN_W,SCREEN_H,BLACK); Lcount += 1; bx = bxi - SCREEN_W/3; by = byi; bvy = 0; bvx = bvxi; } // update scoreboard rectfill(screen, SCREEN_W/2-25,0,SCREEN_W/2+25,20,BLACK); textprintf_ex(screen, font, SCREEN_W/2-20, 10, 15, -1, "%d %d", Lcount, Rcount);

Manage Ball Passing Paddle - PONG

Page 43: Game programming workshop

// manage user input for paddle movementif (key[KEY_A]) padLeftY -= padVy;if (key[KEY_Z]) padLeftY += padVy;if (key[KEY_K]) padRightY -= padVy;if (key[KEY_M]) padRightY += padVy;

Players Move Paddles Using A,Z and K,M Keys - PONG

Page 44: Game programming workshop

// manage paddles touching boundary of game space if (padLeftY<padHeight/2) padLeftY = padHeight/2;

if (padLeftY>SCREEN_H - padHeight/2) padLeftY = SCREEN_H - padHeight/2;

if (padRightY<padHeight/2) padRightY = padHeight/2;

if (padRightY>SCREEN_H - padHeight/2) padRightY = SCREEN_H - padHeight/2;

Stop Paddles at Boundary of Game Space - PONG

Page 45: Game programming workshop

// animate ball and paddlescirclefill(screen,bxold,byold,rad,BLACK);circlefill(screen,bx,by,rad,YELLOW);rectfill(screen,padLeftX-padWidth/2,padLeftYold-padHeight/2, padLeftX+padWidth/2,padLeftYold+padHeight/2,BLACK);rectfill(screen,padRightX-padWidth/2,padRightYold-padHeight/2, padRightX+padWidth/2,padRightYold+padHeight/2,BLACK);rectfill(screen,padLeftX-padWidth/2,padLeftY-padHeight/2,padLeftX+ padWidth/2,padLeftY+padHeight/2,GREEN);rectfill(screen,padRightX-padWidth/2,padRightY-padHeight/2,padRightX+ padWidth/2,padRightY+padHeight/2,RED);rest(1);

Animate Game - PONG

Page 46: Game programming workshop

Adding some Excitement with a Bit of Randomness

Version 01 of Pong_Demo is functional but BORING! Lets add some excitement by increasing the speed of the return ball each time the ball hits the center of the paddle.

We can also randomize the speed of the ball a little every now and then.

Insert the following lines of code at the bottom of the if( ) that deals with the ball hitting the paddle (both left and right).

if (bvy == 0) bvx -= 1;if (bvx<-8) bvy += rand() % 4 - 2;if (rand() % 100 > 94) bvy += rand() % 4 - 2;

You can skip the exercise and run Pong_Demo_02 to see the changes.

Page 47: Game programming workshop

KING PONG

Now run King_Pong to see the value of adding sound to your game.

Page 48: Game programming workshop

(0,0)

(0,SCREEN_H)(SCREEN_W,SCREEN_H)

(SCREEN_W,0)

maintain 4 to 3 aspect ratio

Game Space Layout

Page 49: Game programming workshop

Keyboard Input Demo - Displays an open circle on screen.  Circle can be moved using the arrow keys.  The diameter of the circle can be changed using the Page-Up and Page-Down keys.  Movement of circle is limited to keep circle on screen.

Mouse Graphics Demo - The program demonstrates the use of the mouse in Allegro.  Mouse movement moves a spot on the screen.  Pressing the LEFT, RIGHT, or both mouse buttons changed the color of the spot.

Gamepad Demo - A USB game controller must be plugged in for this program to function.  Program detects the game pad and shows a simple graphical display indicating the number of joysticks (2-axis) and sliders (1-axis) controls, and the number of buttons including the front fire buttons.  Program moves a yellow spot in screen, controlled by 1st 2-axis control, the size of the spot is changed by pressing button 7 and 8 and six different sound events are invoked by pressing buttons 1 through 6.

Computer Input Demo Programs

Page 50: Game programming workshop

allegro_init();install_keyboard();

Keyboard Demorun keyboard_input_demo

Page 51: Game programming workshop

Mouse Input DemoMouse_Graphics_Demo

allegro_init();install_mouse();

Page 52: Game programming workshop

Joystick Input Demojoystick_demo & joystick_graphics_demo

plug in generic gamepad (USB) first

allegro_init();install_joystick(JOY_TYPE_AUTODETECT);

Page 53: Game programming workshop

GamePad Graphics Demogamepad_demo

Page 54: Game programming workshop

while(!keypressed()){ //graphics loop poll_joystick(); xold = x; yold = y; radius_old = radius; if(joy[0].stick[0].axis[0].pos<0) x = x - 2; if(joy[0].stick[0].axis[0].pos>0) x = x + 2; if(joy[0].stick[0].axis[1].pos<0) y = y - 2; if(joy[0].stick[0].axis[1].pos>0) y = y + 2; if(joy[0].button[6].b>0) radius = radius - 1; if(joy[0].button[7].b>0) radius = radius + 1; if(x>max_x) x = max_x; if(x<0) x = 0; if(y>max_y) y = max_y; if(y<0) y = 0; if(radius<2) radius = 2; if(radius>100) radius = 100; if(xold!=x || yold!=y || radius_old!=radius) circlefill(screen,xold,yold,radius_old,BLACK); circlefill(screen,x,y,radius,YELLOW);

GamePad Graphics Control DemoSample Source Code

Page 55: Game programming workshop

BITMAP *buffer;::

int ret = set_gfx_mode(GFX_AUTODETECT_WINDOWED, max_x, max_y, 0, 0);if (ret!=0){ allegro_message(allegro_error); return 1;}buffer = create_bitmap(SCREEN_W, SCREEN_H);

::

clear_bitmap(buffer);blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

Double Buffering

The purpose of double buffering is to eliminate or reduce the flicker in an animation due to drawing directly on the display being viewed (screen). Instead we will draw on a bitmap elsewhere in memory and then transfer (blit) the completed image to the screen in one operation.

Page 56: Game programming workshop

Draw_Sprite_Demo

Demonstrates loading and displaying background image, loading, animation and scaling of sprites, and blitting to replace background under moving sprite.  Includes loading and playing sound with volume as a function of distance from a specific point. Movement of sprite is through arrow keys.  Sound is invoked with spacebar, when Carman sprite is close to Chef. Special Features:  A simple 3D effect is achieved by scaling sprite as it moves up and down in scene.

Page 57: Game programming workshop

Sample Graphics Output

Page 58: Game programming workshop

int main(){ char *filename = "southpark_town.bmp"; BITMAP *bkg_image; BITMAP *cartman;

int x, y;double scale;int xold,yold;int vol = 128;int max_x = 640;int max_y = 480;

SAMPLE *chef_hello; int volume = 255; int pan = 128; int pitch = 1000;

//initialize the program allegro_init();

install_keyboard();set_color_depth(16);

set_gfx_mode(GFX_AUTODETECT_WINDOWED, max_x, max_y, 0, 0); if (install_sound(DIGI_AUTODETECT, MIDI_NONE, "") != 0) { allegro_message("Error initializing sound system"); return 1; }

Draw Sprite Demo

Page 59: Game programming workshop

//load the wave file chef_hello = load_sample("chef-hello_there_children.wav"); bkg_image = load_bitmap(filename, NULL); if (!bkg_image) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading %s", filename); return 1; } blit(bkg_image, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

//rectfill(screen,0,0,max_x,max_y,GREEN); //print some status information textprintf_ex(screen,font,0,0,WHITE,0,"Resolution = %ix%i", SCREEN_W, SCREEN_H); textprintf_ex(screen, font, 0, 10, WHITE,0,"Color depth = %i", bitmap_color_depth(screen));

//load the cartman bitmap cartman = load_bitmap("cartman.bmp", NULL); x = SCREEN_W/2 - cartman->w/2; y = SCREEN_H/2;

Page 60: Game programming workshop

//main loopwhile (!key[KEY_ESC]){ scale = (max_y/2 + 4.0*(double)(y-max_y/2))/(double)(max_y/2); stretch_sprite(screen, cartman, x, y, scale*cartman->w,scale*cartman->h);

textprintf_ex(screen,font,0,20,WHITE,0, "Location = %ix%i", x, y); rest(20); xold = x; yold = y; if(key[KEY_UP]) y = y - 1; if(key[KEY_DOWN]) y = y + 1; if(key[KEY_LEFT]) x = x - 2; if(key[KEY_RIGHT])x = x + 2; if(xold!=x || yold!=y) blit(bkg_image, screen, x, y, x, y, scale*cartman->w,scale*cartman->h); if(x>max_x-cartman->w-20) x = max_x-cartman->w-20; if(x<-20) x = -20; if(y>max_y-cartman->h) y = max_y-cartman->h; if(y<max_y/2) y = max_y/2; vol = 255 - abs(x-425) - abs(y-250); if(vol<0) vol = 0; if(key[KEY_SPACE] && vol>10) { stop_sample(chef_hello); play_sample(chef_hello,vol,128,1000,FALSE); rest(100); }}

Page 61: Game programming workshop

Rotating Sprites Demo

rotate_sprite(buffer,sprite,x,y,itofix(ang));

ang is the angle of rotation in allegro units

0 - 360 degrees = 0 - 255 allegro angle units

Angles (ang) must be converted from integer to fixed precision type values using the itofix( ) function included in the allegro library.

Page 62: Game programming workshop

Fifty-Two Pickuprun CardDemo

As an example of accessing sprites from a two-dimensional sprite sheet, we will drop cards randomly onto the screen from a 52-card deck. Actually we will be selecting card images at random, so there will be many more that 52 cards displayed.

Page 63: Game programming workshop

950

392

98

73

(rank*73,suit*98)

rank = (0..12)

suit = (0..3)

Managing the Cards Sprite

Page 64: Game programming workshop

void main(void){ int cardwidth = 73; int cardheight = 98; int width = 1180; int height = 720; char *filename = "cards_orig.bmp"; BITMAP *cards; BITMAP *buffer; allegro_init(); install_keyboard(); set_color_depth(16); int ret = set_gfx_mode(GFX_AUTODETECT_WINDOWED, width, height,0,0); cards = load_bitmap(filename, NULL); buffer = create_bitmap(width,height); clear_bitmap(buffer); srand(time(NULL)); while(!key[KEY_ESC]) { blit(cards,buffer,rand()%13*cardwidth,(rand()%4)*cardheight, rand()%(width-cardwidth),rand()%(height-cardheight), cardwidth,cardheight); blit(buffer,screen,0,0,0,0,width,height); } allegro_exit();}END_OF_MAIN()

Complete Source Code - 52 Pick-Up

Page 65: Game programming workshop

Sample Run

Page 66: Game programming workshop

Translucent Sprites

Translucent sprites are used for many special effects. The principle behind translucency is to combine the r,g,b values of two pixels occupying the same location in a bitmap. Normally you replace the background pixels with the overlaying sprite pixels using the blit( ) function. We will set a to a value between 0.0 and 1.0 to represent the fraction of the foreground pixel to be used, so (1-a) will be the amount of the background pixel used.

int pixbk, rbk, gbk, bbk;int pixsp, rsp, gsp, bsp;

pixbk = getpixel(bkgimage,i,j);pixsp = getpixel(spriteimg,k,m);

rbk = getr(pixbk); rsp = getr(pixsp); gbk = getg(pixbk); gsp = getg(pixsp);bbk = getb(pixbk); bsp = getb(pixsp);

rbk = alpha*rbk + (1.0-alpha)*rsp;gbk = alpha*gbk + (1.0-alpha)*gsp;bbk = alpha*gbk + (1.0-alpha)*bsp;

pixbk = makecol(rbk,gbk,bbk);

Page 67: Game programming workshop

Card Drop Screen SaverCardScreenSaver demos translucent sprites

In this example we will modify the previous card demo to cause the cards to fade out after they have been dropped onto the screen. This demo woul make a good screen saver. After each card drop will will reduce the brightness of every pixel of the screen image using the function dimmer( ).

void dimmer(void){ int pix; int r,g,b; for(int i=0;i<width;i++) for(int j=0;j<height;j++) { pix = getpixel(buffer,i,j); r = getr(pix); g = getg(pix); b = getb(pix); r -= 8; g -= 8; b -= 8; if(r<0) r=0; if(g<0) g=0; if(b<0) b=0; pix = makecol(r,g,b); putpixel(buffer,i,j,pix); }}

Page 68: Game programming workshop

while(!key[KEY_ESC]) { blit(cards,buffer,rand()%13*cardwidth,(rand()%4)*cardheight, rand()%(width-cardwidth),rand()%(height-cardheight), cardwidth,cardheight); dimmer(); blit(buffer,screen,0,0,0,0,width,height); } allegro_exit();

Modified Main Loop

Page 69: Game programming workshop

Sample Run

Page 70: Game programming workshop

Animated Sprite Demouses Prince of Persia Sprite Sheet

Page 71: Game programming workshop
Page 72: Game programming workshop
Page 73: Game programming workshop
Page 74: Game programming workshop
Page 75: Game programming workshop
Page 76: Game programming workshop
Page 77: Game programming workshop
Page 78: Game programming workshop

Sprite Sheet

728 x 90 pixelseach image region is 728/13 = 56 x 90 pixelsdefault transparency color is magenta rgb = (255,0,255)

num_steps = 0; while(!key[KEY_ESC]) { for(int i=0;i<13;i++) { move = num_steps*step_size; blit(bkg_image, buffer, 660-move-10, 380, 660-move-10, 380, 76, 90); masked_blit(sprite_sheet,buffer, i*56,0,660-move,380,56,90); blit(buffer,screen,0,0,0,0,SCREEN_W,SCREEN_H); num_steps +=1; if(move>720) num_steps = 0; rest(80); } }

selects the proper segment of thesprite sheet to display

covers old sprite with the proper region ofthe background image

Page 79: Game programming workshop

char *backname = "BlueBkg.bmp"; char *spritename = "alladin.bmp"; BITMAP *bkg_image; BITMAP *sprite_sheet; BITMAP *buffer; int sprite_width = 56; int sprite_height = 90; int step_size = 5; int num_steps; int move; //initialize the program allegro_init();

install_keyboard();set_color_depth(16);

set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0); bkg_image = load_bitmap(backname, NULL); if (!bkg_image) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading %s", backname); return 1; } sprite_sheet = load_bitmap(spritename,NULL); if(!sprite_sheet) { set_gfx_mode(GFX_TEXT,0,0,0,0); allegro_message("Error loading %s", spritename); return 1; }

Page 80: Game programming workshop

buffer = create_bitmap(SCREEN_W, SCREEN_H);clear_bitmap(buffer);blit(bkg_image,buffer,0,0,0,0,640,480);masked_blit(sprite_sheet,buffer,0,0,15,130,728,90); num_steps = 0;while(!key[KEY_ESC]){ for(int i=0;i<13;i++) { move = num_steps*step_size; blit(bkg_image, buffer, 660-move-10, 380, 660-move-10, 380, 76, 90); masked_blit(sprite_sheet,buffer, i*56,0,660-move,380,56,90); blit(buffer,screen,0,0,0,0,SCREEN_W,SCREEN_H); num_steps +=1; if(move>720) num_steps = 0; rest(80); }}destroy_bitmap(bkg_image);destroy_bitmap(sprite_sheet);allegro_exit();return 0;

Page 81: Game programming workshop

Sprite Sheet for The Prince of Persia

Page 82: Game programming workshop

Creating a Sprite Image

Tank Composed ofPower Point 3D Objects

finished sprite sheet with transparency

reference image

In PowerPoint the objects are movable, so animations are much simpler to create. Make sure that each copy of the sprite is equally spaced in the sprite sheet.

sprite_width = 98 pixels

Page 83: Game programming workshop

Tank Sprite Demo

Implements an animated sprite of a tank with a separately moveable gun tube (barrel) on the turret. Tank motions is controlled using the Z and X keys. 

Gun barrel elevation is controlled using the Q and A keys.  Uses a sprite sheet created using Power Point and Paint Shop Pro (see Lecture 9 for more info). 

Demonstrates the integration of multi-part sprites with rotate_sprite( ), masked_blit( ) and normal blit( ) functions. 

Special Features:  Sounds are integrated with sprite actions and left-to-right panning is used to adjust the sound levels in each speaker to correspond to sprite position.

Z and X move tank backward and forward

Q and A raise and lower turret gun

Page 84: Game programming workshop

Sample Output

Z - move backwardX - move forward

Q - barrel upA - barrel down

Page 85: Game programming workshop

char *backname = "BlueBkg.bmp"; char *spritename = "tank_sprite_sheet_sm.bmp"; char *turretname = "turretsprite.bmp"; BITMAP *bkg_image; BITMAP *sprite_sheet; BITMAP *turret_sprite; BITMAP *buffer; SAMPLE *backsound; SAMPLE *tanksound; SAMPLE *turretsound; int sprite_width = 98; int sprite_height = 60; int step_size = 5; int num_steps,i; int move = 0; int tankpan; int turret_ang = 255; bool tankon = false; bool turreton = false;

Tank Sprite Demo Setup

Frames of moving tank are separated by 98 pixels horizontally and fit in a 98 x 60 pixel rectangle.

The smallest move increment is set to 5 pixels. The horizontal position of the tank is set by,

move = num_steps * step_size

Page 86: Game programming workshop

//initialize the programallegro_init();install_keyboard();set_color_depth(16);set_gfx_mode(GFX_AUTODETECT_WINDOWED, 760, 480, 0, 0); bkg_image = load_bitmap(backname, NULL);sprite_sheet = load_bitmap(spritename,NULL);turret_sprite = load_bitmap(turretname,NULL); buffer = create_bitmap(SCREEN_W, SCREEN_H);clear_bitmap(buffer);blit(bkg_image,buffer,0,0,0,0,760,480); //install a digital sound driverif (install_sound(DIGI_AUTODETECT, MIDI_NONE, "") != 0) { allegro_message("Error initializing sound system"); return 1;} backsound = load_sample("dead_wind_loop.wav");tanksound = load_sample("tankgo.wav");turretsound = load_sample("turret.wav");play_sample(backsound, 128, 128, 1000, TRUE);

Loading Bitmaps and WAV Files

Page 87: Game programming workshop

i = 0;num_steps = 0;

rotate_sprite(buffer,turret_sprite,36,413,itofix(255));

masked_blit(sprite_sheet,buffer, 15,10, 15, 405, sprite_width,sprite_height);

blit(buffer,screen,0,0,0,0,SCREEN_W,SCREEN_H);

i=0 i=1 i=2 i=3

Initial Position

Page 88: Game programming workshop

while(!key[KEY_ESC]){ // barrel up

// barrel down // tank backward // tank forward // turn off tanksound //turn off turretsound // draw and display next frame}

Actions in Main Game Loop

Page 89: Game programming workshop

// barrel up if(key[KEY_Q]){ turret_ang -= 1; if(turret_ang<200) turret_ang=200; if(!turreton) { play_sample(turretsound,255,tankpan,1000,TRUE); turreton = true; } adjust_sample(turretsound,255,tankpan,1000,TRUE);} // barrel downif(key[KEY_A]){ turret_ang += 1; if(turret_ang>255) turret_ang = 255; if(!turreton) { play_sample(turretsound,255,tankpan,1000,TRUE); turreton = true; } adjust_sample(turretsound,255,tankpan,1000,TRUE);}

Turret Gun Actions

Page 90: Game programming workshop

Turret Gun Tube Rotation

rotate_sprite(turret_sprite, buffer,destx,desty,itofix(ang));

255

192

ang

turret_sprite is twice as long as barrel because axis of rotation is at the center of the image and we wish to rotate barrel about one end.

placement of barrel in destination image is offset so that back end of barrel is aligned with front of tank turret.

Page 91: Game programming workshop

// tank backwardif(key[KEY_X]){ i = (i+1) % 4; num_steps +=1; move = num_steps*step_size; tankpan = 255*move/SCREEN_W; if(!tankon) { play_sample(tanksound,255,tankpan,1000,TRUE); tankon = true; } adjust_sample(tanksound,255,tankpan,1000,TRUE);} // tank forwardif(key[KEY_Z]){ i = i-1; if(i<0) i=3; num_steps -=1; move = num_steps*step_size; tankpan = 255*move/SCREEN_W; if(!tankon) { play_sample(tanksound,255,tankpan,1000,TRUE); tankon = true; } adjust_sample(tanksound,255,tankpan,1000,TRUE);}

Tank Motion Actions

Page 92: Game programming workshop

// turn off tanksoundif(!key[KEY_X] && !key[KEY_Z]){ stop_sample(tanksound); tankon = false;} // turn off turretsoundif(!key[KEY_A] && !key[KEY_Q]){ stop_sample(turretsound); turreton = false;} // draw and display next frameblit(bkg_image, buffer, 0,0,0,0,SCREEN_W,SCREEN_H);rotate_sprite(buffer,turret_sprite,36 + move,413,itofix(turret_ang));masked_blit(sprite_sheet,buffer, 15+i*sprite_width, 10, 15 + move, 405, sprite_width,sprite_height); blit(buffer,screen,0,0,0,0,SCREEN_W,SCREEN_H);rest(80);

Stop Sounds Actions and Display

Page 93: Game programming workshop

Collision Detection - Atomic FirefliesCollision_Detection_Demo_02

for(int k=0;k<Num-1;k++) for(int m=k+1;m<Num;m++) collide(k,m);

void collide(int k, int m){ if([collision_check]) { // handle collision }}

double dist(int k, int m){ return sqrt(pow((ball[k].x-ball[m].x),2.0) + pow((ball[k].y-ball[m].y),2.0));}

Note: Straight-line distance is not the most efficient method for detecting collisions. Compare with hit( ) function shown later.

Page 94: Game programming workshop

Collision Detection Demo

Program creates an array of small moving objects that bounce around the screen.  For each frame, the location of all pairs of objects are compared.  When a pair is detected to have collided, the event is marked with an explosion event.  The explosion event begins a sixteen frame explosion sequence with its position and velocity equal to the everage position and velocity of the pair of colliding objects.  Special Features:  Demonstrates display of multiple animated events.

Collision_Detection_Demo uses left and right arrow to change the number of fireflies on screen.

Page 95: Game programming workshop

Collision Detection - Atomic Fire Flies

Page 96: Game programming workshop

struct ball_state { double x; double y; double vx; double vy; int px; int py; int pxold; int pyold;} ball[100];

struct fire_state { double x; double y; double vx; double vy; int count;} fire[100];c

Moving Balls and Explosion Struct Lists

Page 97: Game programming workshop

void draw_explosion(int x, int y, int& c){ masked_blit(explosion,buffer,(c % 4)*64,(c/4)*64,x-32,y-32,64,64); c += 1;}

256 x 256 pixel imageof explosion

col = c % 4row = c / 4

sprite images are 64 x 64 pixels

Extracting Frames from 2D Sprite

Sometimes sprite sheets are arranged in two-dimensional arrays of images. In these cases we need to determine in which row and column each image is placed so that they can be accessed and displayed in the proper sequence.

Page 98: Game programming workshop

for(int k=0;k<bcount-1;k++) for(int m=k+1;m<bcount;m++) collide(k,m); for(int q=0;q<fcount;q++){ if(fire[q].count==0) play_sample(explode[rand()%4],rand()%56+200,rand()%256, 800+rand()%400,FALSE); draw_explosion((int)fire[q].x,(int)fire[q].y,fire[q].count); fire[q].x += fire[q].vx; fire[q].y += fire[q].vy;}

remove_fireballs();

Managing Multiple Animated Sprites

Successive frames of two or more animated sprites should be displayed concurrently. In this example the frame count (fcount) is set to 0 by the draw_explosion( ) function so it can be removed from the active sprite list, fire[ ].

draw_explosion( ) increments frame countof the explosion sprites

Page 99: Game programming workshop

for(int i = 0; i<bcount;i++){ ball[i].pxold = ball[i].px; ball[i].pyold = ball[i].py; ball[i].x = ball[i].x + ball[i].vx + rand()%4-2; ball[i].y = ball[i].y + ball[i].vy + rand()%4-2; ball[i].px = (int)ball[i].x; ball[i].py = (int)ball[i].y;

if(ball[i].px<=radius || ball[i].px>=max_x-radius) { ball[i].vx = -ball[i].vx; if(ball[i].x>=radius) ball[i].x=(double)(max_x-radius); else ball[i].x=(double)radius; } if(ball[i].py<=radius || ball[i].py>=max_y-radius) { ball[i].vy = -ball[i].vy; if(ball[i].y>=radius) ball[i].y=(double)(max_y-radius); else ball[i].y=radius; } circlefill(buffer,ball[i].pxold,ball[i].pyold,radius,ORANGE); circlefill(buffer,ball[i].px,ball[i].py,radius,BLUE);}

Managing An Array of Moving Objects

Page 100: Game programming workshop

int hit(int k, int m, int range){ int xsep; int ysep; xsep = (int) (ball[k].x - ball[m].x); ysep = (int) (ball[k].y - ball[m].y); if(xsep<range && xsep>-range && ysep<range && ysep>-range) return 1; else return 0;}

void collide(int k, int m){ if(hit(k,m,close_enough)) { fcount+=1; fire[fcount-1].x = (ball[k].x + ball[m].x)/2.0; fire[fcount-1].y = (ball[k].y + ball[m].y)/2.0; fire[fcount-1].vx = (ball[k].vx + ball[m].vx)/2.0; fire[fcount-1].vy = (ball[k].vy + ball[m].vy)/2.0; fire[fcount-1].count = 0; }}

Detecting Collisions and Managing the Collision List

Page 101: Game programming workshop

void remove_fireballs(void){ int inc = 0; int dec = 0; bool done = (fcount<=0); while(!done) { if(fire[inc].count>15 && dec<fcount) dec += 1; if(dec<fcount) { fire[inc] = fire[dec]; if(fire[inc].count<=15) { inc += 1; dec += 1; } } done = (dec>=fcount); } fcount = inc;}

Removing Completed Fireballs from the Fire[ ] List

fire[.] list is scanned and all members with count>15 are dropped.

fcount is reduced by the number of members eliminated.

12

2

2

16

4

16

16

7

8

inc dec12

2

4

7

8

inc dec

16

16

7

8

fire[]

Page 102: Game programming workshop

Setting the World View

Scrolling

Defining Fixed Objects and Their Actions/Reactions Background Foreground Block Movable/Breakable

Defining Characters and other Animated Objects Player Opponents Animated Interactive Object

Loading Maps

Controlling Display

Side Scrolling Games

Page 103: Game programming workshop

Scrolling

Horizontal (or vertical) scrolling gives us the freedom to implement a game world that is much larger than our display screen. Through the use of double buffering and blitting we can smoothly move through the game always displaying a view of the game centered on the action and our character.

Page 104: Game programming workshop

Scanning a Panoramic ImageA Step Toward Horizontal Scrolling

while(!key[KEY_ESC]){ if(key[KEY_LEFT]) { blitx -= 3; if(blitx<0) blitx = 0; } if(key[KEY_RIGHT]) { blitx += 3; if(blitx+SCREEN_W>bkgwidth) blitx = bkgwidth - SCREEN_W; } blit(bkgimage,buffer,blitx,blity,0,0,SCREEN_W,SCREEN_H); blit(buffer,screen,0,0,0,0,SCREEN_W,SCREEN_H);}

blitx and blity define the corner of the portion of the bkgimage that will be displayed.

bounding conditions are used to ensure that the display window stays inside the limits of the bkgimage.

display screen

Page 105: Game programming workshop

// Horizontal Scrolling Demo 1

#include <allegro.h>

int max_x = 640; int max_y = 480; int blitx = 0; int bkgwidth = 7249; int bkgheight = 529; int blity = 0;

char *filename = "talafar.bmp"; BITMAP *bkgimage; BITMAP *buffer;

void main(void){ allegro_init(); install_keyboard(); set_color_depth(16); int ret = set_gfx_mode(GFX_AUTODETECT_WINDOWED, max_x, max_y, 0, 0); bkgimage = load_bitmap(filename,NULL); buffer = create_bitmap(SCREEN_W, SCREEN_H); while(!key[KEY_ESC]) { if(key[KEY_LEFT]) { blitx -= 3; if(blitx<0) blitx = 0; } if(key[KEY_RIGHT]) { blitx += 3; if(blitx+SCREEN_W>bkgwidth) blitx = bkgwidth - SCREEN_W; } blit(bkgimage,buffer,blitx,blity,0,0,SCREEN_W,SCREEN_H); blit(buffer,screen,0,0,0,0,SCREEN_W,SCREEN_H); rest(1); }}END_OF_MAIN()

Page 106: Game programming workshop

The Central Object

int max_x = 640;int max_y = 529;int chxmin = 10;int chxmax = 7239;int chymin = 0;int chymax = 519;int bkgwidth = 7249;int bkgheight = 529;int blitx = 320;int blity = 40;

double chx,chy,chvx,chvy,chax,chay;double chvxmax = 20.0;double chvxmin = -20.0;double bounce = 0.8;double dt = 0.1;

x

y

chx - x positionchy - y positionchvx - x velocitychvy - y velocitychax - x accelerationchay - y acceleration

Page 107: Game programming workshop

Motion in a Constant Gravitational Field

Separate the motion in the x direction (horizontal) from motion in the y direction (vertical). Gravity acts in the negative y direction (-9.8 m/s2). There is no force in the x direction on a moving object (without friction).

x

y

x, y - object locationvx, vy - object velocityay - object acceleration due to gravity = -9.8 meters/second/second.

Page 108: Game programming workshop

chx = 30.0;chy = (double)chymax;chvx = 0.0; chvy = 0.0;chay = 9.8; chax = 0.0;

chvy = chvy + chay*dt;chvx = chvx + chax*dt;chy = chy + chvy*dt + 0.5*chay*dt*dt;chx = chx + chvx*dt + 0.5*chax*dt*dt;

if(key[KEY_LEFT]) { chax -= 1.0; if(chax<-5.0) chax = -5.0; }

if(key[KEY_RIGHT]) { chax += 1.0; if(chax>5.0) chax=5.0; }

main loop

Motion Controlled by Acceleration

Page 109: Game programming workshop

blitx = (int)chx - SCREEN_W/2;blity = (int)chy - SCREEN_H/2;

if(blitx<0) blitx = 0;if(blitx+SCREEN_W>bkgwidth) blitx = bkgwidth - SCREEN_W;

if(blity<0) blity = 0;if(blity+SCREEN_H>bkgheight) blity = bkgheight - SCREEN_H;

circlefill(bkgimage,(int)chx,(int)chy,8,makecol(255,0,0));blit(bkgimage,buffer,blitx,blity,0,0,SCREEN_W,SCREEN_H);blit(buffer,screen,0,0,0,0,SCREEN_W,SCREEN_H);

Positioning the Display Screen in the World View

First the display screen is centered on the ball and then its horizontal and/or vertical position is shifted as needed to keep the display inside the world view.

Page 110: Game programming workshop

Drawing a Bitmap - Sample Output

Page 111: Game programming workshop

#include <allegro.h>int main(void){ char *filename = "game_bkg.bmp"; BITMAP *image; int ret; allegro_init(); install_keyboard(); set_color_depth(16); ret = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0); if (ret != 0) { allegro_message(allegro_error); return 1; } //load the image file image = load_bitmap(filename, NULL); if (!image) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message( "Error loading %s" , filename); return 1; } //display the image blit(image, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); //done drawing--delete bitmap from memory destroy_bitmap(image); //display video mode information textprintf_ex(screen,font, 0, 0, 1, -1, "%dx%d" ,SCREEN_W,SCREEN_H); //wait for keypress while (!keypressed()); allegro_exit(); return 0;}END_OF_MAIN()

Loading a Bitmap

Page 112: Game programming workshop

Sample Run

Page 113: Game programming workshop

Embedding Fixed Objects

vpix

hpix

map arraynrows

ncols

game bkg image

We can associate a text array with the game world specifying the location of fixed sprites and other game objects. The size of each sprite region in pixels is given by,

Each region will be represented by an integer in the map array. The value of the integer will determine the properties of the object; such as, movable, breakable, background, foreground, etc...

spwidth = hpix/ncols

spheight = vpix/nrows

Page 114: Game programming workshop

Sprite Width = = 29 pixels

Sprite Height = = 20 pixels

Map Array Details

0

0

0

0

0 0 0

0

0

29 x 20 pixels

250

281 2

7250 250

56028

0 - no sprite

1 - background sprite

2 - block (immovable)

3 - movable

4 - breakable

5 - other objects (such as ramps and pits).

Page 115: Game programming workshop

#include <fstream.h>

struct cell{ int sprnum; int block; int breakable; int row; int col;}map[28][250];

void load_map(void){ ifstream inFile; inFile.open("map.dat"); for(int r=0;r<nrows;r++) for(int c=0;c<ncols;c++) inFile >> map[r][c].sprnum; inFile.close();}

Loading Map Array

Page 116: Game programming workshop

Displaying the Map Array Cells in the Game World View

load_map(); for(int r = 0;r<nrows;r++){ for(int c = 0;c<ncols; c++) { cnum = map[r][c].sprnum; if(cnum == 0) col = BLUE; if(cnum == 1) col = GREEN; if(cnum == 2) col = RED; if(cnum == 3) col = YELLOW; rectfill(bkgimage, c*pwidth+2, r*pheight+2, (c+1)*pwidth-3, (r+1)*pheight-3,col); }}

leaves some spacearound each cell

pwidth = width of cell in pixelspheight = height of cell in pixels

Page 117: Game programming workshop

struct block{ int xmin; int xmax; int ymin; int ymax;}blocks[100];

for(int r = 0;r<nrows;r++) for(int c = 0;c<ncols;c++) if(map[r][c].sprnum==2) { blocks[numblocks].xmin = pwidth*c; blocks[numblocks].xmax = pwidth*(c+1); blocks[numblocks].ymin = pheight*r; blocks[numblocks].ymax = pheight*(r+1); numblocks += 1; }

Building a List of Blocking Cells

defines the limitseach blocking cell

Page 118: Game programming workshop

When ball region is inside block a collision is detected. Since there the ball can be in only one place a hit is set and all other block tests are suspended for this moment in the game.

We must also determine which surface of the block the ball has contacted. In this example we use the closest edge.

Warning: When there is a tie, odds things can happen. We'll refer to these anomalies as "special features" of the game. :-)

Managing Collisions

Page 119: Game programming workshop

hit = false;for(int i=0;i<numblocks;i++){ if(inside(chx,chy,sep,blocks[i]) && !hit) { hit = true; dtime = 0; diffxleft = abs(((int)chx+sep) - blocks[i].xmin); diffxright = abs(((int)chx-sep)-blocks[i].xmax); diffytop = abs(((int)chy+sep) - blocks[i].ymin); diffybottom = abs(((int)chy-sep) - blocks[i].ymax); diffx = min(diffxleft,diffxright); diffy = min(diffytop,diffybottom); if(diffx<diffy) { chvx = - chvx; if(diffxleft<diffxright) chx = blocks[i].xmin - sep; else chx = blocks[i].xmax + sep; } else { chvy = - chvy; if(diffytop<diffybottom) chy = blocks[i].ymin - sep; else chy = blocks[i].ymax + sep; } }}

Code for Managing Collisions with Blocks

Page 120: Game programming workshop

hstart = ((int)chx-pwidth)/pwidth;hfinish = ((int)chx+pwidth)/pwidth;vstart = ((int)chy-pheight)/pheight;vfinish = ((int)chy+pheight)/pheight;

if(hstart<0) hstart = 0;if(hfinish>ncols) hfinish = ncols;if(vstart<0) vstart = 0;if(vfinish>nrows) vfinish = nrows;for(int r=vstart;r<=vfinish;r++) for(int c=hstart;c<=hfinish;c++) { cnum = map[r][c].sprnum; if(cnum == 0) col = BLUE; if(cnum == 1) col = GREEN; if(cnum == 2) col = RED; if(cnum == 3) col = YELLOW; rectfill(bkgimage, c*pwidth+2, r*pheight+2, (c+1)*pwidth-3, (r+1)*pheight-3,col); }

Redrawing Background Cells

Page 121: Game programming workshop

Sample Displays

Page 122: Game programming workshop
Page 123: Game programming workshop
Page 124: Game programming workshop
Page 125: Game programming workshop

x0 = 0 x1 = 2x x2 = 4x x3 = 2xy0 = 0 y1 = -x y2 = 0 y3 = x

Laying Down the Base

Nrow

bitmap

Ncol

2x

x

tcol = (Ncol - c)/Ncol

xstart = tcol*x0 + (1-tcol)*x1

ystart = tcol*y0 + (1-tcol)*y1

xfinish = tcol*x3 + (1-tcol)*x2

yfinish = tcol*y3 + (1-tcol)*y2

trow = (Nrow - r)/Nrow

x = trow*xstart + (1-trow)*xfinish

y = trow*ystart + (1-trow)*yfinish

(x2y2)

(x1y1)

(x3y3)

(x0y0)

Page 126: Game programming workshop

3D Modeling byOrthographic Projection

Page 127: Game programming workshop

Classic Isometric (3/4) View

Page 128: Game programming workshop

x/2 pixels

Alternative Methods for Surface Transformation

px,py

bx,by

x pixels

Nro

w

Ncol

2/,2/0

21

210

210

02/12/,, sizesizesizebysizebxpypx

021

42

22

M =

Page 129: Game programming workshop

Diablo II

Page 130: Game programming workshop

Diablo II - Zoom

Page 131: Game programming workshop

Diablo II - Level Editor Detail

Page 132: Game programming workshop

Lessons Learned

There are limits to what we are able to cover in this workshop. If your dream is to create a Massive Multiplayer Role-Playing Game (MMRPG), you will have to take solace in the fact that the lessons learned in this workshop apply directly to game development projects that are much bigger than can be accomplished here.

Understanding the physics of motion and body on body iterations is the same for all applications.

The incorporation of and manipulation of sound applies to the simple single-player game as well as the larger multiplayer game.

The techniques of animation can be applied equally well to an animated sprite as to a intro/segway video sequence.

The methods to maintain real-time interactions as the complexity of the game scene varies are the same for any level of complexity.

The skills developed in creating an enjoyable single-player game are essential for development of an (MMRPG).