/////////////////////////////////////////////////////////////////////////
// Game Programming All In One, Second Edition
// Source Code Copyright (C)2004 by Jonathan S. Harbour
// Chapter 4 - Tank War Game
/////////////////////////////////////////////////////////////////////////
#include "tankwar.h"
/////////////////////////////////////////////////////////////////////////
// drawtank function
// construct the tank using drawing functions
/////////////////////////////////////////////////////////////////////////
void drawtank(int num)
{
int x = tanks[num].x;
int y = tanks[num].y;
int dir = tanks[num].dir;
//draw tank body and turret
rectfill(screen, x-11, y-11, x+11, y+11, tanks[num].color);
rectfill(screen, x-6, y-6, x+6, y+6, 7);
//draw the treads based on orientation
if (dir == 0 || dir == 2)
{
rectfill(screen, x-16, y-16, x-11, y+16, 8);
rectfill(screen, x+11, y-16, x+16, y+16, 8);
}
else
if (dir == 1 || dir == 3)
{
rectfill(screen, x-16, y-16, x+16, y-11, 8);
rectfill(screen, x-16, y+16, x+16, y+11, 8);
}
//draw the turret based on direction
switch (dir)
{
case 0:
rectfill(screen, x-1, y, x+1, y-16, 8);
break;
case 1:
rectfill(screen, x, y-1, x+16, y+1, 8);
break;
case 2:
rectfill(screen, x-1, y, x+1, y+16, 8);
break;
case 3:
rectfill(screen, x, y-1, x-16, y+1, 8);
break;
}
}
/////////////////////////////////////////////////////////////////////////
// erasetank function
// erase the tank using rectfill
/////////////////////////////////////////////////////////////////////////
void erasetank(int num)
{
//calculate box to encompass the tank
int left = tanks[num].x - 17;
int top = tanks[num].y - 17;
int right = tanks[num].x + 17;
int bottom = tanks[num].y + 17;
//erase the tank
rectfill(screen, left, top, right, bottom, 0);
}
/////////////////////////////////////////////////////////////////////////
// movetank function
// move the tank in the current direction
/////////////////////////////////////////////////////////////////////////
void movetank(int num)
{
int dir = tanks[num].dir;
int speed = tanks[num].speed;
//update tank position based on direction
switch(dir)
{
case 0:
tanks[num].y -= speed;
break;
case 1:
tanks[num].x += speed;
break;
case 2:
tanks[num].y += speed;
break;
case 3:
tanks[num].x -= speed;
}
//keep tank inside the screen
if (tanks[num].x > SCREEN_W-22)
{
tanks[num].x = SCREEN_W-22;
tanks[num].speed = 0;
}
if (tanks[num].x < 22)
{
tanks[num].x = 22;
tanks[num].speed = 0;
}
if (tanks[num].y > SCREEN_H-22)
{
tanks[num].y = SCREEN_H-22;
tanks[num].speed = 0;
}
if (tanks[num].y < 22)
{
tanks[num].y = 22;
tanks[num].speed = 0;
}
}
/////////////////////////////////////////////////////////////////////////
// explode function
// display random boxes to simulate an explosion
/////////////////////////////////////////////////////////////////////////
void explode(int num, int x, int y)
{
int n;
//retrieve location of enemy tank
int tx = tanks[!num].x;
int ty = tanks[!num].y;
//is bullet inside the boundary of the enemy tank?
if (x > tx-16 && x < tx+16 && y > ty-16 && y < ty+16)
score(num);
//draw some random circles for the "explosion"
for (n = 0; n < 10; n++)
{
rectfill(screen, x-16, y-16, x+16, y+16, rand() % 16);
rest(1);
}
//clear the area of debris
rectfill(screen, x-16, y-16, x+16, y+16, 0);
}
/////////////////////////////////////////////////////////////////////////
// updatebullet function
// update the position of a bullet
/////////////////////////////////////////////////////////////////////////
void updatebullet(int num)
{
int x = bullets[num].x;
int y = bullets[num].y;
if (bullets[num].alive)
{
//erase bullet
rect(screen, x-1, y-1, x+1, y+1, 0);
//move bullet
bullets[num].x += bullets[num].xspd;
bullets[num].y += bullets[num].yspd;
x = bullets[num].x;
y = bullets[num].y;
//stay within the screen
if (x < 5 || x > SCREEN_W-5 || y < 20 || y > SCREEN_H-5)
{
bullets[num].alive = 0;
return;
}
//draw bullet
x = bullets[num].x;
y = bullets[num].y;
rect(screen, x-1, y-1, x+1, y+1, 14);
//look for a hit
if (getpixel(screen, bullets[num].x, bullets[num].y))
{
bullets[num].alive = 0;
explode(num, x, y);
}
//print the bullet's position
textprintf(screen, font, SCREEN_W/2-50, 1, 2,
"B1 %-3dx%-3d B2 %-3dx%-3d",
bullets[0].x, bullets[0].y,
bullets[1].x, bullets[1].y);
}
}
/////////////////////////////////////////////////////////////////////////
// checkpath function
// check to see if a point on the screen is black
/////////////////////////////////////////////////////////////////////////
int checkpath(int x1,int y1,int x2,int y2,int x3,int y3)
{
if (getpixel(screen, x1, y1) ||
getpixel(screen, x2, y2) ||
getpixel(screen, x3, y3))
return 1;
else
return 0;
}
/////////////////////////////////////////////////////////////////////////
// clearpath function
// verify that the tank can move in the current direction
/////////////////////////////////////////////////////////////////////////
void clearpath(int num)
{
//shortcut vars
int dir = tanks[num].dir;
int speed = tanks[num].speed;
int x = tanks[num].x;
int y = tanks[num].y;
switch(dir)
{
//check pixels north
case 0:
if (speed > 0)
{
if (checkpath(x-16, y-20, x, y-20, x+16, y-20))
tanks[num].speed = 0;
}
else
//if reverse dir, check south
if (checkpath(x-16, y+20, x, y+20, x+16, y+20))
tanks[num].speed = 0;
break;
//check pixels east
case 1:
if (speed > 0)
{
if (checkpath(x+20, y-16, x+20, y, x+20, y+16))
tanks[num].speed = 0;
}
else
//if reverse dir, check west
if (checkpath(x-20, y-16, x-20, y, x-20, y+16))
tanks[num].speed = 0;
break;
//check pixels south
case 2:
if (speed > 0)
{
if (checkpath(x-16, y+20, x, y+20, x+16, y+20 ))
tanks[num].speed = 0;
}
else
//if reverse dir, check north
if (checkpath(x-16, y-20, x, y-20, x+16, y-20))
tanks[num].speed = 0;
break;
//check pixels west
case 3:
if (speed > 0)
{
if (checkpath(x-20, y-16, x-20, y, x-20, y+16))
tanks[num].speed = 0;
}
else
//if reverse dir, check east
if (checkpath(x+20, y-16, x+20, y, x+20, y+16))
tanks[num].speed = 0;
break;
}
}
/////////////////////////////////////////////////////////////////////////
// fireweapon function
// configure a bullet's direction and speed and activate it
/////////////////////////////////////////////////////////////////////////
void fireweapon(int num)
{
int x = tanks[num].x;
int y = tanks[num].y;
//ready to fire again?
if (!bullets[num].alive)
{
bullets[num].alive = 1;
//fire bullet in direction tank is facing
switch (tanks[num].dir)
{
//north
case 0:
bullets[num].x = x;
bullets[num].y = y-22;
bullets[num].xspd = 0;
bullets[num].yspd = -BULLETSPEED;
break;
//east
case 1:
bullets[num].x = x+22;
bullets[num].y = y;
bullets[num].xspd = BULLETSPEED;
bullets[num].yspd = 0;
break;
//south
case 2:
bullets[num].x = x;
bullets[num].y = y+22;
bullets[num].xspd = 0;
bullets[num].yspd = BULLETSPEED;
break;
//west
case 3:
bullets[num].x = x-22;
bullets[num].y = y;
bullets[num].xspd = -BULLETSPEED;
bullets[num].yspd = 0;
}
}
}
/////////////////////////////////////////////////////////////////////////
// forward function
// increase the tank's speed
/////////////////////////////////////////////////////////////////////////
void forward(int num)
{
tanks[num].speed++;
if (tanks[num].speed > MAXSPEED)
tanks[num].speed = MAXSPEED;
}
/////////////////////////////////////////////////////////////////////////
// backward function
// decrease the tank's speed
/////////////////////////////////////////////////////////////////////////
void backward(int num)
{
tanks[num].speed--;
if (tanks[num].speed < -MAXSPEED)
tanks[num].speed = -MAXSPEED;
}
/////////////////////////////////////////////////////////////////////////
// turnleft function
// rotate the tank counter-clockwise
/////////////////////////////////////////////////////////////////////////
void turnleft(int num)
{
tanks[num].dir--;
if (tanks[num].dir < 0)
tanks[num].dir = 3;
}
/////////////////////////////////////////////////////////////////////////
// turnright function
// rotate the tank clockwise
/////////////////////////////////////////////////////////////////////////
void turnright(int num)
{
tanks[num].dir++;
if (tanks[num].dir > 3)
tanks[num].dir = 0;
}
/////////////////////////////////////////////////////////////////////////
// getinput function
// check for player input keys (2 player support)
/////////////////////////////////////////////////////////////////////////
void getinput()
{
//hit ESC to quit
if (key[KEY_ESC])
gameover = 1;
//WASD / SPACE keys control tank 1
if (key[KEY_W])
forward(0);
if (key[KEY_D])
turnright(0);
if (key[KEY_A])
turnleft(0);
if (key[KEY_S])
backward(0);
if (key[KEY_SPACE])
fireweapon(0);
//arrow / ENTER keys control tank 2
if (key[KEY_UP])
forward(1);
if (key[KEY_RIGHT])
turnright(1);
if (key[KEY_DOWN])
backward(1);
if (key[KEY_LEFT])
turnleft(1);
if (key[KEY_ENTER])
fireweapon(1);
//short delay after keypress
rest(15);
}
/////////////////////////////////////////////////////////////////////////
// score function
// add a point to the specified player's score
/////////////////////////////////////////////////////////////////////////
void score(int player)
{
//update score
int points = ++tanks[player].score;
//display score
textprintf(screen, font, SCREEN_W-70*(player+1), 1, BURST,
"P%d: %d", player+1, points);
}
/////////////////////////////////////////////////////////////////////////
// setuptanks function
// set up the starting condition of each tank
/////////////////////////////////////////////////////////////////////////
void setuptanks()
{
//player 1
tanks[0].x = 30;
tanks[0].y = 40;
tanks[0].dir = 1;
tanks[0].speed = 0;
tanks[0].color = 9;
tanks[0].score = 0;
//player 2
tanks[1].x = SCREEN_W-30;
tanks[1].y = SCREEN_H-30;
tanks[1].dir = 3;
tanks[1].speed = 0;
tanks[1].color = 12;
tanks[1].score = 0;
}
/////////////////////////////////////////////////////////////////////////
// setupdebris function
// set up the debris on the battlefield
/////////////////////////////////////////////////////////////////////////
void setupdebris()
{
int n,x,y,size,color;
//fill the battlefield with random debris
for (n = 0; n < BLOCKS; n++)
{
x = BLOCKSIZE + rand() % (SCREEN_W-BLOCKSIZE*2);
y = BLOCKSIZE + rand() % (SCREEN_H-BLOCKSIZE*2);
size = (10 + rand() % BLOCKSIZE)/2;
color = makecol(rand()%255, rand()%255, rand()%255);
rectfill(screen, x-size, y-size, x+size, y+size, color);
}
}
/////////////////////////////////////////////////////////////////////////
// setupscreen function
// set up the graphics mode and game screen
/////////////////////////////////////////////////////////////////////////
void setupscreen()
{
//set video mode
int ret = set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 800, 600, 0, 0);
if (ret != 0) {
allegro_message(allegro_error);
return;
}
//print title
textprintf(screen, font, 1, 1, BURST,
"Tank War - %dx%d", SCREEN_W, SCREEN_H);
//draw screen border
rect(screen, 0, 12, SCREEN_W-1, SCREEN_H-1, TAN);
rect(screen, 1, 13, SCREEN_W-2, SCREEN_H-2, TAN);
}
/////////////////////////////////////////////////////////////////////////
//Game message
//The message that appears at the start of the game
/////////////////////////////////////////////////////////////////////////
void gamemessage(void)
{
allegro_message("Welcome to Tank War! The game where you fight against a freind in Tanks!");
}
///////////////////////////////////////////////////////////////////////////
//Main game
//This function runs the game
///////////////////////////////////////////////////////////////////////////
void rungame(void)
{
install_timer();
srand(time(NULL));
setupscreen();
setupdebris();
setuptanks();
//game loop
while(!gameover)
{
//erase the tanks
erasetank(0);
erasetank(1);
//check for collisions
clearpath(0);
clearpath(1);
//move the tanks
movetank(0);
movetank(1);
//draw the tanks
drawtank(0);
drawtank(1);
//update the bullets
updatebullet(0);
updatebullet(1);
//check for keypresses
if (keypressed())
getinput();
//slow the game down (adjust as necessary)
rest(30);
}
//////////////////////////////////////////////////////////////////////////
//Title screen
//This function creates the title screen
//////////////////////////////////////////////////////////////////////////
void title_screen(void)
{
texout_centre(screen, font, "Welcome to Tank war!", SCREEN_W/2, 50, 14);
if (key[KEY_ENTER])
rungame();
}
/////////////////////////////////////////////////////////////////////////
// main function
// start point of the program
/////////////////////////////////////////////////////////////////////////
void main(void)
{
//initialize everything
allegro_init();
gamemessage();
install_keyboard();
title_screen();
//end program
allegro_exit();
}
END_OF_MAIN();
Code wont compile
I made some modifications to a sample game that came with"game programming all in one" and made some errors. Heres the code:
I get the following error:
567 C:\Dev-Cpp\Allegro projects\Tank War\main.c
[Warning] static declaration for `WinMain' follows non-static
originally, I got an eror from my rungame() function, and nothing from this.After changing a few things, I get an error form END_OF_MAIN but not run game. could somebody tell me how to fix the problem I have now, and also if there is something wrong with my rungame() function, so I dont get errors from it later? Thanks!
At first glance, the while loop in your rungame() function seems to be missing a closing curly brace. Try adding one to the end of the function or where the while block should end.
I'm not familiar with Allegro, is END_OF_MAIN() your function or Allegro's? You haven't posted the code for that function.
I'm not familiar with Allegro, is END_OF_MAIN() your function or Allegro's? You haven't posted the code for that function.
Try removing the semicolon after END_OF_MAIN(). The Allegro documentation doesn't indicate a semicolon, and since it is a macro it is unclear what effect that semicolon may have on the expanded.
If you're using MSVC 6, select all of your code (Ctrl+A) and then have it auto-formatted (Alt+F8). This can reveal improper scope and nesting sometimes. Make sure that all braces are matched. (I don't know the auto-format keyboard shortcut for MSVC 7+.)
If you're using MSVC 6, select all of your code (Ctrl+A) and then have it auto-formatted (Alt+F8). This can reveal improper scope and nesting sometimes. Make sure that all braces are matched. (I don't know the auto-format keyboard shortcut for MSVC 7+.)
ok,thanks for the help. I dont know if what you said will help(I can fix my code at the moment) but I hope it works. END_OF_MAIN(), has a semicoloon after it in the book im using, and has never caused a problem before. void main is also used in the book, and it works fine. I will change it though. I will add the extra curly brace after the rungame function. thanks!
I fixed everything but now I get a new error;
[Linker error] undefined reference to `texout_centre'
any help? I never got this error before
[Linker error] undefined reference to `texout_centre'
any help? I never got this error before
Looks to be a typo.
Undefined reference means you're generally calling a function that doesn't exist...
Undefined reference means you're generally calling a function that doesn't exist...
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement