Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Animation movement and figting

This thread is locked; no one can reply to it. rss feed Print
Animation movement and figting
Pontus Wallberg
Member #7,196
May 2006

Hello.

Im making a game in C++, but I have rused in to some problems that I hope you can help me with or give advice about what I can do.

1. The first thing I want to do is making it look like the main character is moving, like changing pictures between like 4-5 pictures if I press the UP-Key, and another 4-5picuters when hitting the DOWN-key. You get the idea i hope? Because now it looks like the character i sliding on the map, because it's 1 picture for each key. Any tips ? Code?

2. The second thing I want to do is making figthing possible. Right now the main char can run in to eniemes randomly placed on the map, then it starts a new window, kind of looking like Pokemon style, the main char on side och the enimie on the other. So in this place I want to be able to attack of course perhaps something else like run och defence. But in order for this to happen I must make HP points/bar Exp points/bar and hitpower like that stuff. I have been making some classes for Main char and Enimies, but I dont get it to work and have no Idea how to make a HP / Exp bar. So any tips on this ?

I would be greatful for any tips you have on either qeustion.

You should perhaps have my code:

#include <allegro.h>
#include <time.h>
#include <stdlib.h>
#include <cstdlib>
#include <Math.h>

BITMAP *Buffer;
BITMAP *char_up;
BITMAP *char_down;
BITMAP *char_left;
BITMAP *char_right;
BITMAP *Bakgrund;
BITMAP *theMouse;
BITMAP *mainMenuBack;
BITMAP *mainMenuExit;
BITMAP *mainMenuOptions;
BITMAP *mainMenuNewGame;
BITMAP *mainMenuContinue;
BITMAP *fight_bg;
BITMAP *char_up_fight;
BITMAP *enemy_fight;
BITMAP *blackscreen;
BITMAP *loadingScreen;

bool Quit = false;
bool loading = true;
bool lastLoopMouseDown, mouse1release;
int data[100], level=0, enemy[100];
int menuWidth, menuHeight, menuX, menuY;
bool menuBtnPress, menuToggle, mouseOver1, mouseOver2, mouseOver3, enterLvl;
bool mainMenuOn = true;
/*void drawFightMenu(int MenuX, int MenuY)
{
int MenuW = 300;
int MenuH = 70;
int AminX = MenuX+11;
int AmaxX = MenuX+(MenuW/2)-5;
int AminY = MenuY+11;
int AmaxY = MenuX+(MenuW/2)-5;
rectfill(Buffer, MenuX, MenuY, MenuX+MenuW, MenuY+MenuH, makecol(0, 0, 0));
rectfill(Buffer, MenuX+2, MenuY+2, MenuX+MenuW-2, MenuY+MenuH-2, makecol(100, 100, 100));
rectfill(Buffer, MenuX+10, MenuY+10, MenuX+(MenuW/2)-4, MenuY+(MenuH/2)-4, makecol(0, 0, 0));
if(mouse_x<1_maxX && mouse_x>1_minX && mouse_y<1_maxY && mouse_y>1_minY)
rectfill(Buffer, MenuX+11, MenuY+11, MenuX+(MenuW/2)-5, MenuY+(MenuH/2)-5, makecol(130, 130, 130));
else
rectfill(Buffer, MenuX+11, MenuY+11, MenuX+(MenuW/2)-5, MenuY+(MenuH/2)-5, makecol(100, 100, 100));

textout_ex(Buffer, font, "Attack", MenuX+15, MenuY+18, makecol(0, 0, 0), -1);

draw_sprite(Buffer, theMouse, mouse_x, mouse_y);
}*/
void drawMenu()
{
if(mouse_x>(230) && mouse_y>(100) && mouse_x<(410) && mouse_y<(120)) mouseOver1 = true;
else mouseOver1 = false;
if(mouse_x>(230) && mouse_y>(130) && mouse_x<(410) && mouse_y<(150)) mouseOver2 = true;
else mouseOver2 = false;
if(mouse_x>(230) && mouse_y>(160) && mouse_x<(410) && mouse_y<(180)) mouseOver3 = true;
else mouseOver3 = false;
if(menuToggle)
{
rectfill(blackscreen, 0, 0, SCREEN_W, SCREEN_H, makecol(0, 0, 0));
set_trans_blender(0, 0, 0, 200);
draw_trans_sprite(Buffer, blackscreen, 0, 0);

rectfill(Buffer, 218, 88, 422, 193, makecol(0, 0, 0));
rectfill(Buffer, 220, 90, 420, 191, makecol(100, 100, 100));

rectfill(Buffer, 229, 99, 411, 121, makecol(0, 0, 0));
rectfill(Buffer, 229, 129, 411, 151, makecol(0, 0, 0));
rectfill(Buffer, 229, 159, 411, 181, makecol(0, 0, 0));

if(mouseOver1) rectfill(Buffer, 230, 100, 410, 120, makecol(130, 130, 130));
else rectfill(Buffer, 230, 100, 410, 120, makecol(100, 100, 100));
if(mouseOver2) rectfill(Buffer, 230, 130, 410, 150, makecol(130, 130, 130));
else rectfill(Buffer, 230, 130, 410, 150, makecol(100, 100, 100));
if(mouseOver3) rectfill(Buffer, 230, 160, 410, 180, makecol(130, 130, 130));
else rectfill(Buffer, 230, 160, 410, 180, makecol(100, 100, 100));

textout_ex(Buffer, font, "Exit to Windows", 240, 107, makecol(0, 0, 0), -1);
textout_ex(Buffer, font, "Exit to Main Menu", 240, 137, makecol(0, 0, 0), -1);
textout_ex(Buffer, font, "Return to game", 240, 167, makecol(0, 0, 0), -1);

if(mouse_x>(230) && mouse_y>(100) && mouse_x<(410) && mouse_y<(120) && mouse_b & 1) Quit=true;
if(mouse_x>(230) && mouse_y>(130) && mouse_x<(410) && mouse_y<(150) && mouse_b & 1) mainMenuOn=true;
if(mouse_x>(230) && mouse_y>(160) && mouse_x<(410) && mouse_y<(180) && mouse_b & 1) menuToggle=false;
draw_sprite( Buffer, theMouse, mouse_x, mouse_y);
}
}
int xPic, yPic, charDir, xLoc, yLoc;
bool resting;
void moveChar()
{
if((xLoc*64)<xPic)
{
resting=false;
xPic--;
}
else{resting=true;}
if((xLoc*64)>xPic)
{
resting=false;
xPic++;
}
else{resting=true;}
if((yLoc*48)<yPic)
{
resting=false;
yPic--;
}
else{resting=true;}
if((yLoc*48)>yPic)
{
resting=false;
yPic++;}
else{resting=true;}
};

void setLocs(int newXloc, int newYloc){ xLoc=newXloc; yLoc=newYloc-1; };
void setPic(){ xPic=(xLoc*64); yPic=(yLoc*48); };
void setPicDown(){ xPic=(xLoc*64); yPic=((yLoc+1)*48); };
void setPicLeft(){ xPic=((xLoc-1)*64); yPic=(yLoc*48); };
void setPicRight(){ xPic=((xLoc+1)*64); yPic=(yLoc*48); };
void setPicUp(){ xPic=(xLoc*64); yPic=((yLoc-1)*48); };
void resetLvlData()
{
int rs = 0;
while(rs<=100)
{
data[rs]=0;
rs++;
}
};
void resetEnemyData()
{
int rs = 0;
while(rs<=100)
{
enemy[rs]=0;
rs++;
}
};

void setLvl(int prevLvl, int lvl)
{
enterLvl = false;
if(lvl==1)
{
Bakgrund = load_bitmap( "SchoolEntrance.bmp", NULL);
resetLvlData();
level = lvl;
data[0] = 1;
data[1] = 1;
data[2] = 1;
data[3] = 1;
data[5] = 1;
data[6] = 1;
data[7] = 1;
data[8] = 1;
data[9] = 1;
resetEnemyData();
enemy[67]=1;
if(prevLvl==0)
{
setLocs(7,9);
setPicDown();
charDir=2;
}
if(prevLvl==2)
{
setLocs(4,1);
setPicUp();
charDir=4;
}
}
if(lvl==2)
{
Bakgrund = load_bitmap("kullensShop.bmp", NULL);
resetLvlData();
level = lvl;
data[0] = 1;
data[1] = 1;
data[2] = 1;
data[3] = 1;
data[4] = 1;
data[6] = 1;
data[7] = 1;
data[8] = 1;
data[9] = 1;
data[10] = 1;
data[19] = 1;
data[20] = 1;
data[29] = 1;
data[30] = 1;
data[39] = 1;
data[40] = 1;
data[48] = 1;
data[49] = 1;
data[50] = 1;
data[60] = 1;
data[69] = 1;
data[70] = 1;
data[79] = 1;
data[80] = 1;
data[89] = 1;
data[90] = 1;
data[91] = 1;
data[92] = 1;
data[93] = 1;
data[95] = 1;
data[96] = 1;
data[97] = 1;
data[98] = 1;
data[99] = 1;
resetEnemyData();
if(prevLvl==1)
{
setLocs(4,8);
setPicDown();
}
charDir=2;
}
};
bool enemyContact()
{
if(enemy[(yLoc*10)+xLoc]==1) return true;
else return false;
};
void drawMainMenu()
{
bool Con = false;
bool New = false;
bool Opt = false;
bool Exi = false;
bool FaDe = false;
int fadeInt = 0;
if(mainMenuOn)
{
mainMenuBack = load_bitmap( "mainmenu.bmp", NULL);
mainMenuExit = load_bitmap( "mainmenuexit.bmp", NULL);
mainMenuOptions = load_bitmap( "mainmenuoptions.bmp", NULL);
mainMenuNewGame = load_bitmap( "mainmenunewgame.bmp", NULL);
mainMenuContinue = load_bitmap( "mainmenucontinue.bmp", NULL);
}
while(mainMenuOn)
{
if(!mouse_b&1 && lastLoopMouseDown)mouse1release=true;
draw_sprite(Buffer, mainMenuBack, 0, 0);
if(mouse_x<295 && mouse_x>267 && mouse_y<359 && mouse_y>335 && !Con && !New && !Opt)
{
if(mouse_b&1){Exi=true;}
else{draw_sprite(Buffer, mainMenuExit, 265, 333);}
if(!mouse_b&1 && Exi) {mainMenuOn=false;Quit=true;}
}
else if(mouse_x<268 && mouse_x>218 && mouse_y<292 && mouse_y>269 && !Con && !New && !Exi)
{
if(mouse_b&1){Opt=true;}
else{draw_sprite(Buffer, mainMenuOptions, 216, 267);}
}
else if(mouse_x<228 && mouse_x>171 && mouse_y<233 && mouse_y>209 && !Con && !Exi && !Opt)
{
if(mouse_b&1){New=true;}
else{draw_sprite(Buffer, mainMenuNewGame, 169, 208);}
if(!mouse_b&1 && New) {mainMenuOn=false;setLvl(0, 1);menuToggle=false;loading=true;if(loading)draw_sprite(scre
en, loadingScreen, 0, 0);}
}
else if(mouse_x<196 && mouse_x>134 && mouse_y<169 && mouse_y>143 && !Exi && !New && !Opt)
{
if(mouse_b&1){Con=true;}
else{draw_sprite(Buffer, mainMenuContinue, 134, 143);}
if(!mouse_b&1 && Con)
{
FaDe = true;
menuToggle=false;
}
}
else if(!mouse_b&1) {Exi=false;Opt=false;New=false;Con=false;}
if(Exi)draw_sprite(Buffer, mainMenuExit, 266, 334);
if(Opt)draw_sprite(Buffer, mainMenuOptions, 217, 268);
if(New)draw_sprite(Buffer, mainMenuNewGame, 170, 209);
if(Con)draw_sprite(Buffer, mainMenuContinue, 135, 144);

if(fadeInt<253 && FaDe)fadeInt+=3;
if(fadeInt>=253)mainMenuOn=false;
mouse1release=false;
if(mouse_b&1) lastLoopMouseDown=true;
else lastLoopMouseDown=false;
draw_sprite(Buffer, theMouse, mouse_x, mouse_y);

rectfill(blackscreen, 0, 0, SCREEN_W, SCREEN_H, makecol(0, 0, 0));
set_trans_blender(0, 0, 0, fadeInt);
draw_trans_sprite(Buffer, blackscreen, 0, 0);

draw_sprite(screen, Buffer, 0, 0);
}

};
void toggleMenu()
{
if(!menuToggle && menuBtnPress)
{
menuToggle = true;
}
else if(menuToggle && menuBtnPress)
{
menuToggle = false;
}
menuBtnPress = false;
};
void battle(int enemy)
{
menuBtnPress = true;
bool battleOn = true;
bool fight_start = false;
int char_pan = -320;
int enemy_pan = 640;
fight_bg = load_bitmap( "fight_bg.bmp", NULL);
char_up_fight = load_bitmap( "char_up_fight.bmp", NULL);
enemy_fight = load_bitmap( "fjortis.bmp", NULL);
while(battleOn)
{
if(key[KEY_ESC])
{
toggleMenu();
}
else menuBtnPress = true;
if(key[KEY_S] && !menuToggle)
{
battleOn=false;
}
draw_sprite(Buffer, fight_bg, 0, 0);

if(Quit) battleOn=false;
draw_sprite(Buffer, char_up_fight, char_pan, 0);
draw_sprite(Buffer, enemy_fight, enemy_pan, 0);

if(char_pan<0 && !menuToggle)char_pan++;
if(enemy_pan>320 && !menuToggle)enemy_pan--;
//else if(char_pan==0) drawFightMenu(300,350);

drawMenu();
drawMainMenu();
draw_sprite(screen, Buffer, 0, 0);
}
destroy_bitmap(fight_bg);
destroy_bitmap(char_up_fight);
destroy_bitmap(enemy_fight);
};

int frames = 0;
int FPS = 0;
void fps()
{
FPS = frames;
frames=0;
};

void increeseXloc()
{
if(xLoc*64==xPic && xLoc<9 && data[((yLoc+1)*10)+(xLoc+1)]==0)
{
xLoc++;
if(rand()%50 == 1)
battle(1);
}
};
void increeseYloc(){
if(yLoc*48==yPic && yLoc<8 && data[(yLoc+2)*10+xLoc]==0)
{
yLoc++;
if(rand()%50 == 1)
battle(1);
}
};
void decreeseXloc()
{
if(xLoc*64==xPic && xLoc>0 && data[(yLoc+1)*10+(xLoc-1)]==0)
{
xLoc--;
if(rand()%50 == 1)
battle(1);
}
};
void decreeseYloc()
{
if(yLoc*48==yPic && yLoc>-1 && data[(yLoc)*10+xLoc]==0)
{
yLoc--;
if(rand()%50 == 1)
battle(1);
}
};
int main()
{
int intKeyPress = 0;

bool BtnUp = true;

menuToggle = false;
menuBtnPress = false;

if (allegro_init() != 0)
return 1;
install_keyboard();
install_mouse();
set_color_depth(32);

if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
if (set_gfx_mode(GFX_SAFE, 640, 480, 0, 0) != 0) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
return 1;
}
}
set_window_title("FINAL FAMILY");
set_palette(desktop_palette);

loadingScreen = load_bitmap("load.bmp", NULL);
if(loading)draw_sprite(screen, loadingScreen, 0, 0);

char_up = load_bitmap("char_up.bmp", NULL);
char_down = load_bitmap("char_down.bmp", NULL);
char_left = load_bitmap("char_left.bmp", NULL);
char_right = load_bitmap("char_right.bmp", NULL);

blackscreen = create_bitmap(SCREEN_W, SCREEN_H);

theMouse = load_bitmap("mouse.bmp", NULL);

setLvl(0, 1);

Buffer = create_bitmap(640, 480);

int dir = 3;

install_int(fps, 1000);
install_int(moveChar, 3);

srand(time(NULL));

while(!Quit)
{
frames++;

if(loading)draw_sprite(screen, loadingScreen, 0, 0);
if(!mouse_b&1 && lastLoopMouseDown)mouse1release=true;

drawMainMenu();

draw_sprite(Buffer, Bakgrund, 0, 0);

//moveChar();

if(xLoc==4 && yLoc==-1 && yPic==(48*-1) && level==1 && enterLvl) setLvl(1, 2);
if(xLoc==4 && yLoc== 8 && yPic==(48*8) && level==2 && enterLvl) setLvl(2, 1);

if(xLoc!=0 && xLoc!=9 && yLoc!=-1 && yLoc!=8) if(resting) enterLvl = true;

if(charDir==1){draw_sprite(Buffer, char_left, xPic, yPic);}
else if(charDir==2){draw_sprite(Buffer, char_up, xPic, yPic);}
else if(charDir==3){draw_sprite(Buffer, char_right, xPic, yPic);}
else if(charDir==4){draw_sprite(Buffer, char_down, xPic, yPic);}
else {draw_sprite(Buffer, char_down, xPic, yPic);}
textprintf_ex(Buffer, font, 10, 10, makecol(255, 255, 255), 1, "FPS: %d", FPS);

if(enemyContact()&&resting) textout_ex(Buffer, font, "CONTACT!", 10, 30, makecol(0, 0, 0), -1);

drawMenu();

acquire_screen();
draw_sprite(screen, Buffer, 0, 0);
release_screen();

if(key[KEY_A] && !menuToggle)
{
battle(1);
}
if(key[KEY_ESC])
{
toggleMenu();
}
else menuBtnPress = true;

if(key[KEY_LEFT] && !menuToggle)
{
if(resting)
{
decreeseXloc();
charDir=1;
BtnUp = false;
}
}
else if(key[KEY_RIGHT] && !menuToggle)
{
if(resting)
{
increeseXloc();
charDir=3;
BtnUp = false;
}
}
else if(key[KEY_UP] && !menuToggle)
{
if(resting)
{
decreeseYloc();
charDir=2;
BtnUp = false;
}
}
else if(key[KEY_DOWN] && !menuToggle)
{
if(resting)
{
increeseYloc();
charDir=4;
BtnUp = false;
}
}
else if(resting){ BtnUp = true; }
mouse1release=false;
if(mouse_b&1) lastLoopMouseDown=true;
else lastLoopMouseDown=false;
loading = false;
}
return 0;
}
END_OF_MAIN();

//Pundus

kdevil
Member #1,075
March 2001
avatar

1) Say you have an array of bitmaps for the character:

BITMAP *walking[FRAMES];
float walkingcount;
const float animation_speed = 0.5;
int walkingframe;

//each time the character moves forward:
walkingcount += animation_speed;
if (walkingcount >= FRAMES) walkingcount = 0;
walkingframe = int(walkingcount);

//when drawing:
draw_sprite(somebuffer, walking[walkingframe], x, y);

2) I didn't look at the code (use the [CODE] [/CODE] tags!), but a quick and simple HP bar would be something like:

const int barlength = 123;
const int barheight = 32;
float HP, MAX_HP;
rect(somebitmap, 0, 0, barlength, barheight, somecolor);
rectfill(somebitmap, 0, 0, int(HP / MAX_HP) * barlength, barheight, somecolor);

-----
"I am the Black Mage! I casts the spells that makes the peoples fall down!"

umperio
Member #3,474
April 2003
avatar

Michael Faerber
Member #4,800
July 2004
avatar

Quote:

HTML Mockup Code

As a nitpicker, I have to say that the forums don't use HTML! ::)

--
"The basic of informatics is Microsoft Office." - An informatics teacher in our school
"Do you know Linux?" "Linux? Isn't that something for visually impaired people?"

Pontus Wallberg
Member #7,196
May 2006

Ok, I didn't know about the code tags, this is my first post on allegro.

I just want to ask something about kdevils answer on the first question.

Ok say that I make that array, how do declare the array to the diffrent Bitmaps, I mean where in the code do should I load the the diffrent Bitmaps? And also should I make 4 diffrents arrays for each UP,DOWN,LEFT,RIGTH key?

Thx for the answer man and I will use the code tags next time.

//Pundus

umperio
Member #3,474
April 2003
avatar

Quote:

I will use the code tags next time.

You can still edit your first post and use the code tags now.

Pontus Wallberg
Member #7,196
May 2006

Its says that its to big if i put it between code tags, max is 64 kb and the my post i 110 kb with the code tags. :-/

Mokkan
Member #4,355
February 2004
avatar

Maybe attach the source file instead?

And to answer your latest question, you can use a multidimensional array... so like, frames[LEFT][0], frames[LEFT][1], etc... maybe that's what you want? You might do that for each action, like walkframes[LEFT][0], and punchframes[LEFT][0].

kdevil
Member #1,075
March 2001
avatar

Yeah, you could use multidimensional arrays. As for loading the bitmaps:

//instead of char_right = load_bitmap("char_right.bmp", NULL);
walking[RIGHT][0] = load_bitmap("char_right0.bmp", NULL);
walking[RIGHT][1] = load_bitmap("char_right1.bmp", NULL);
walking[RIGHT][2] = load_bitmap("char_right2.bmp", NULL);
//etc...

-----
"I am the Black Mage! I casts the spells that makes the peoples fall down!"

Onewing
Member #6,152
August 2005
avatar

Ick, that sounds like a lot of maintenance to me. I use a sprite class that has a BITMAP for a picture containning all the character motions and one BITMAP that is used for storing the single image. Every time I change where I'm grabbing from off the set-of-pictures-bitmap, I update the single-motion bitmap. This way, outside of the class, I only have to worry about the single-motion bitmap (and I don't really have to worry about that either, considering the class takes care of drawing itself too). This isn't a new method or anything. ;)

------------
Solo-Games.org | My Tech Blog: The Digital Helm

kdevil
Member #1,075
March 2001
avatar

True, my example certainly isn't the best way to deal with sprites. I'd instead use a datafile, a sprite class like you said, or something else that requires less "copy & paste", but as a simple example it works well enough.

-----
"I am the Black Mage! I casts the spells that makes the peoples fall down!"

LennyLen
Member #5,313
December 2004
avatar

Some things I picked up from your code...

int rs = 0;
while(rs<=100)
{
data[rs]=0;
rs++;
}

This is the same as:

for (int rs = 0; rs < 100; rs++) data[rs] = 0;

Also, your version will crash when rs == 100. You only declared data as an array of 100 ints, which is data[0..99].

This applies to your resetEnemyData() function as well.

Your setLvl() function is extremely inelegant. I can't suggest a better method, since I'm not sure what you're doing, and the code is too messy (especially without indentation) for me to bother deciphering it. But, with 35 lines in a row of data[##] = 1;, you really need to look at finding a better way.

I also noticed that your main() function is 140 lines long. You should break it up into smaller sections, such as setup routines, input routines, output routines. Then group related functions together in their own files and link them together rather than having one huge source file.

Pontus Wallberg
Member #7,196
May 2006

Hello again guys!

I really appreciate all the help you have gave me. I have just one more question, I'm going to make it possible to attack the enemies when they pop up. Should I make a class for the enemies, where I declare the HP, Strength, Level, Hitpower? I just one some pointers where to begin, it always the hardest. :D

//Pundus

Go to: