Sign in to follow this  

VC++ Studio linker problem

This topic is 3857 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok I don't know what's up. Here's my error I get:
------ Rebuild All started: Project: TankWars, Configuration: Debug Win32 ------
Deleting intermediate and output files for project 'TankWars', configuration 'Debug|Win32'
Compiling...
tankwar.c
Linking...
tankwar.obj : error LNK2019: unresolved external symbol _forward referenced in function _getinput
C:\Documents and Settings\Nate\My Documents\Visual Studio 2005\Projects\TankWars\Debug\TankWars.exe : fatal error LNK1120: 1 unresolved externals

And here's the function getinput()
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(10);
}

I've already: 1. Properties -> C/C++ -> General -> Additional Include Directories: alleg.lib 2. Properties -> C/C++ -> Code Generation -> Runtime Library: Multi-threaded DLL (/MD) 3. Properties -> C/C++ -> Advanced -> Compile As: Compile as C CODE (/TC) 4. Properties -> Linker -> Input -> Additional Dependencies: alleg.lib 5. Properties -> Manifest Tool -> General -> Use FAT32 Work-around: Yes 6. Properties -> Manifest Tool -> Input and Output -> Embed Manifest: No

Share this post


Link to post
Share on other sites
Quote:
Original post by jflanglois
What is the forward() function? Show us both the declaration and the definition, and where they are.


jfl.


Hah. Ok. I wasn't sure whether or not you needed ALL the other functions, but okay.

tankwar.h

#ifndef _TANKWAR_H
#define _TANKWAR_H

#include "allegro.h"

#define MODE GFX_AUTODETECT_WINDOWED
#define WIDTH 640
#define HEIGHT 480
#define BLOCKS 5
#define BLOCKSIZE 100
#define MAXSPEED 2
#define BULLETSPEED 10
#define TAN makecol(255, 242, 169)
#define CAMO makecol(64, 142, 66)
#define BURST makecol(255, 289, 73)

struct tagTank
{
int x, y;
int dir, speed;
int color;
int score;
}tanks[2];

struct tagBullet
{
int x, y;
int alive;
int xspd, yspd;
}bullets[2];

int gameover = 0;

void drawtank(int num);
void erasetank(int num);
void movetank(int num);
void explode(int num, int x, int y);
void updatebullet(int num);
int checkpath(int x1, int y1, int x2, int y2, int x3, int y3);
void clearpath(int num);
void fireweapon(int num);
void forward(int num);
void backward(int num);
void turnleft(int num);
void turnright(int num);
void getinput();
void setuptanks();
void score(int);
void print(const char* s, int c);
void setupdebris();
void setupscreen();

#endif




tankwar.c

#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 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 boundary of th enemy tank?
if( (x > tx - 16) && (x < tx + 16) && (y > ty - 16) && (y < ty + 16) )
score(num);

//draw som erandom circles for "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 the 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_ex(screen, font, SCREEN_W / 2 - 50, 1, 2, 0, "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 an dspeed 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;
//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 forwar(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(10);
}

/**********************************************************************
* 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_ex(screen, font, SCREEN_W - 70 * (player+1), 1, BURST, 0, "P%d: %d", player+1, points);
}

/**********************************************************************
* setuptanks function
* set up the starting conditions 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(MODE, WIDTH, HEIGHT, 0, 0);
if( ret != 0 )
{
allegro_message(allegro_error);
return;
}

//print title
textprintf_ex(screen, font, 1, 1, BURST, 0, "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 - 1, TAN);
}

/**********************************************************************
* main function
* start point of the program
**********************************************************************/


int main(void)
{
//intialize everything
allegro_init();
install_keyboard();
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);
}

//end program
allegro_exit();
return 0;
}
END_OF_MAIN()


Share this post


Link to post
Share on other sites
typo:


void forwar(int num)
{
tanks[num].speed++;
if(tanks[num].speed > MAXSPEED)
tanks[num].speed = MAXSPEED;
}



forwar != forward

When you have a linker error that means it can't find the implementation of the function. That always means you either didn't implement it or aren't linking to the library that contains the definition.

In this case, you didn't implement it because you spelled it wrong.

-me

Share this post


Link to post
Share on other sites
Quote:
Original post by Palidine
When you have a linker error that means it can't find the implementation of the function. That always means you either didn't implement it or aren't linking to the library that contains the definition.

In this case, you didn't implement it because you spelled it wrong.

-me

Exactly, and that's why I wanted you to give us both the declaration and the definition. I was hoping you would spot your own error that way.

Other causes apart from mispelling the identifier are mismatched return type/parameters and mismatched const/volatile specifiers (for member functions, but it looks like you are using C).


jfl.

Share this post


Link to post
Share on other sites

This topic is 3857 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this