Allegro.cc - Online Community

Allegro.cc Forums » Installation, Setup & Configuration » Using Dev-Cpp to compile static library

Credits go to BAF for helping out!
This thread is locked; no one can reply to it. rss feed Print
Using Dev-Cpp to compile static library
Bob Keane
Member #7,342
June 2006

After a bit of a vacation, I decided to return to game programming. I am using Bloodshed's Dev-Cpp ide for simplicity. I entered and compiled a program, but when linking, I get the following errors:

"[linker error] undefined reference to 'backward' (2x)
[linker error] undefined reference to 'rans'
[linker error] undefined reference to 'testprintf-ex'".

I selected project > project options then parameters, under compiler I had "-DALLEGRO_STATICLINK", under C++ compiler I had "_DALLEGRO_STATICLINK", and under linker, I had (in this order) "-lalleg_s -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lole32 -ldinput -lddraw -ldxguid -lwinmm -ldsound".

To create the project, I selected file, new project, multimedia and allegro static library, the programming language was set to C. I was able to compile and link with no problems before, but I cannot remember how. What did I miss? I am using allegro 4.2.0. Thanks in advance.

By reading this sig, I, the reader, agree to render my soul to Bob Keane. I, the reader, understand this is a legally binding contract and freely render my soul.
"Love thy neighbor as much as you love yourself means be nice to the people next door. Everyone else can go to hell. Missy Cooper.
The advantage to learning something on your own is that there is no one there to tell you something can't be done.

BAF
Member #2,981
December 2002
avatar

Well, I don't know what backward is, rans... what's that. Is that a misspelling of rand()? And testprintf-ex should be textprintf_ex.

[edit] Can you post the source?

Bob Keane
Member #7,342
June 2006

Its a long one. I am trying to adapt Game Programming All In One's tank war to suit my needs. I have not added my changes yet.

Source(main.c):
[code]
/* Sea War By Bob Keane My first attempt at programming a game. This game is
based on the Game Programming All In One sample game Tank War. Changes include multiple enemy ships,
A storyline and random ship movement. I will change as necessary when possible.
*/

#include "seawar.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 the tank's 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 the 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 the location of the 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 field 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, 4);

// 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,-1,"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 thte 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 direction, 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 direction, 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 weaponin 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;
}

//reverse function decrease the tank's speed.
void reverse(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_LEFT])
turnleft(1);
if (key[KEY_DOWN])
backward(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, -1, "P%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(rans()%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
testprintf_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-2, TAN);
}

//main function start point of the program
int main(void)
{
// initialize 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();
[/code]


Header (seawar.h):
[code]
/* SeaWar.h This file contains basic information for the game SeaWar. Written by Bob Keane
*/

#ifndef _SEAWAR_H
#define _SEAWAR_H
#include <stdio.h>
#include <stdlib.h>
#include "allegro.h"

// define some game constants
#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,189,73)

// Define the tank structure
struct tagTank
{
int x,y;
int dir, speed;
int color;
int score;
} tanks[2];

// define the bullet structure
struct tagBullet
{
int x,y;
int alive;
int xspd,yspd;
} bullets[2];

int gameover = 0;

// function prototypes
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

[/code]

Errors (compile log):

Compiler: Default compiler
Building Makefile: "C:\Dev-Cpp\SeaWar\Makefile.win"
Executing make...
make.exe -f "C:\Dev-Cpp\SeaWar\Makefile.win" all
gcc.exe main.o seawar_private.res -o "seawar.exe" -L"C:/Dev-Cpp/lib" -mwindows -lalleg_s -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lole32 -ldinput -lddraw -ldxguid -lwinmm -ldsound

main.o(.text+0x12bf):main.c: undefined reference to `backward'
main.o(.text+0x1332):main.c: undefined reference to `backward'
main.o(.text+0x1654):main.c: undefined reference to `rans'
main.o(.text+0x17cb):main.c: undefined reference to `testprintf_ex'
collect2: ld returned 1 exit status

make.exe: *** [seawar.exe] Error 1

Execution terminated


[edit] Sorry about that.

By reading this sig, I, the reader, agree to render my soul to Bob Keane. I, the reader, understand this is a legally binding contract and freely render my soul.
"Love thy neighbor as much as you love yourself means be nice to the people next door. Everyone else can go to hell. Missy Cooper.
The advantage to learning something on your own is that there is no one there to tell you something can't be done.

spunit262
Member #5,545
February 2005
avatar

Please put that in [code][/code] tags.

gnolam
Member #2,030
March 2002
avatar

Solution:

Quote:

main.o(.text+0x1654):main.c: undefined reference to `rans'

Misspelling of rand.
Referenced in: color = makecol(rans()%255, rand()%255, rand()%255);

Quote:

main.o(.text+0x17cb):main.c: undefined reference to `testprintf_ex'

Misspelling of textprintf_ex.
Referenced in: testprintf_ex(screen, font, 1, 1, BURST, 0, "Tank War - %dx%d", SCREEN_W, SCREEN_H);

Quote:

main.o(.text+0x12bf):main.c: undefined reference to `backward'

Just plain doesn't exist. The "reverse()" function is probably what's intended.
Referenced in:

 if (key[KEY_S])
     backward(0);

and

if (key[KEY_DOWN])
     backward(1);

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

BAF
Member #2,981
December 2002
avatar

Just what I said, just less detailed because I didn't have the source. :P

Bob Keane
Member #7,342
June 2006

Looks like I need a new pair of glasses. Thanks.

By reading this sig, I, the reader, agree to render my soul to Bob Keane. I, the reader, understand this is a legally binding contract and freely render my soul.
"Love thy neighbor as much as you love yourself means be nice to the people next door. Everyone else can go to hell. Missy Cooper.
The advantage to learning something on your own is that there is no one there to tell you something can't be done.

Go to: