Archive Forums (lite version).  Gaming, Game Development, and Anime community!


PDA

View Full Version : RPG Engine


neozf
05-12-2007, 08:26 AM
After the thread in General Discussion I decided to try to make a RPG Engine, most of the ideas are based off my old one made in DarkBasic.
I currently have some of the basics working, you can move the character around, it will change which direction it's facing and it can't walk off the map.
Currently 75 lines, 25 of which are to draw the map alone :/
It uses Allegro, the graphics are 25x25.
#include <allegro.h>

BITMAP *Face_D;
BITMAP *Face_L;
BITMAP *Face_U;
BITMAP *Face_R;
BITMAP *Tile_Grass;
BITMAP *Tile_Wall;
int x=50;
int y=50;
int Face_Direction=1; //1= Down, 2= Left, 3= Up, 4= Right.


int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

Face_D = load_bitmap( "Face_D.bmp", NULL);
Face_L = load_bitmap( "Face_L.bmp", NULL);
Face_U = load_bitmap( "Face_U.bmp", NULL);
Face_R = load_bitmap( "Face_R.bmp", NULL);
Tile_Grass = load_bitmap( "Tile_Grass.bmp", NULL);
Tile_Wall = load_bitmap( "Tile_Wall.bmp", NULL);

acquire_screen();


while ( !key[KEY_ESC] ){
if (Face_Direction==1) draw_sprite( screen, Face_D, x, y);
else if (Face_Direction==2) draw_sprite( screen, Face_L, x, y);
else if (Face_Direction==3) draw_sprite( screen, Face_U, x, y);
else if (Face_Direction==4) draw_sprite( screen, Face_R, x, y);

if (key[KEY_UP] && y>=75){ y=y-25; Face_Direction=3;}
else if (key[KEY_DOWN] && y<=125){ y=y+25; Face_Direction=1;}
else if (key[KEY_RIGHT] && x<=125){ x=x+25; Face_Direction=4;}
else if (key[KEY_LEFT] && x>=75){ x=x-25; Face_Direction=2;}
rest(50);
rectfill( screen, 0, 0, 640, 480, makecol( 0, 0, 0));
draw_sprite(screen, Tile_Grass, 50,50);
draw_sprite(screen, Tile_Wall, 75,50);
draw_sprite(screen, Tile_Wall, 100,50);
draw_sprite(screen, Tile_Wall, 125,50);
draw_sprite(screen, Tile_Grass, 150,50);
draw_sprite(screen, Tile_Grass, 50,75);
draw_sprite(screen, Tile_Wall, 75,75);
draw_sprite(screen, Tile_Wall, 100,75)
draw_sprite(screen, Tile_Wall, 125,75);
draw_sprite(screen, Tile_Grass, 150,75);
draw_sprite(screen, Tile_Grass, 50,100);
draw_sprite(screen, Tile_Grass, 75,100);
draw_sprite(screen, Tile_Grass, 100,100);
draw_sprite(screen, Tile_Grass, 125,100);
draw_sprite(screen, Tile_Grass, 150,100);
draw_sprite(screen, Tile_Grass, 50,125);
draw_sprite(screen, Tile_Grass, 75,125);
draw_sprite(screen, Tile_Grass, 100,125);
draw_sprite(screen, Tile_Grass, 125,125);
draw_sprite(screen, Tile_Grass, 150,125);
draw_sprite(screen, Tile_Grass, 50,150);
draw_sprite(screen, Tile_Grass, 75,150);
draw_sprite(screen, Tile_Grass, 100,150);
draw_sprite(screen, Tile_Grass, 125,150);
draw_sprite(screen, Tile_Grass, 150,150);
release_screen();
}
readkey();

return 0;

}
END_OF_MAIN();Right now I'm trying to shorten the code for the map drawing, if anyone has an idea of how to make it smaller post here and I'll try to get it to work.
After that I need to work on getting it to not let you walk on things like walls (my last idea for that didn't work...).

Google
--

Travis
05-12-2007, 11:32 AM
Okay, well, first things first, try condensing both of your if-else bundles of mayhem into one or two switch statements. The syntax is like so...

switch (some variable): {
case 1:
statement;
statement;
break;
case 2:
statement;
statement;
break;
default:
statement;
statement;
break;
}

The variable must be some integer value (although characters will work as well, since they are enumerated: a, b, c, d, e,...). After each 'case', you will put one such potential value. In your case, you might use something like Face_Direction for your variable, and 1, 2, 3, and 4 as your case values. The 'default' section is sort of like switch's 'else'. It is just the default behavior in case any of your given values do not apply.

The other thing I would do to clean up and condense your code would be to represent your map in a 2-dimensional array, like int map[20][20]. Then, make two functions: One to populate the array with what will be in what square (Looks like right now you have grass and wall... a good, simple start). Don't worry about coordinates, just picture your map as a grid... some squares are grass, others are wall. Then just put a 0 in the array where walls are and 1 where grass is.

Your second function will actually display the map, and it will take the index values, multiply them by 25, and put the corresponding bitmap at those coordinates.

That should clean things up a lot. Sorry, I'd help you convert your code more, but I have to leave for work soon. Look into switch statements some more, and try and figure out the math of converting grid array indices into pixel coordinates. It's not very difficult, and I think you can figure it out. Good luck, Neo.

neozf
05-12-2007, 02:15 PM
Managed to finaly fix that bug with it letting you walk onto walls :/
80 lines so far.
#include <allegro.h>

BITMAP *Face_D;
BITMAP *Face_L;
BITMAP *Face_U;
BITMAP *Face_R;
BITMAP *Tile_Grass;
BITMAP *Tile_Wall;
int x=0;
int y=0;
int Oldx;
int Oldy;
int TileX = 0;
int TileY = 0;
int Map[5][5]={1,2,2,2,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1}; //1=Grass, 2=Wall.
int Face_Direction=1; //1= Down, 2= Left, 3= Up, 4= Right.


int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

Face_D = load_bitmap( "Face_D.bmp", NULL);
Face_L = load_bitmap( "Face_L.bmp", NULL);
Face_U = load_bitmap( "Face_U.bmp", NULL);
Face_R = load_bitmap( "Face_R.bmp", NULL);
Tile_Grass = load_bitmap( "Tile_Grass.bmp", NULL);
Tile_Wall = load_bitmap( "Tile_Wall.bmp", NULL);

acquire_screen();


while ( !key[KEY_ESC] ){
Oldx=x;
Oldy=y;



switch(Face_Direction){
case 1:
draw_sprite( screen, Face_D, x*25, y*25);
break;
case 2:
draw_sprite( screen, Face_L, x*25, y*25);
break;
case 3:
draw_sprite( screen, Face_U, x*25, y*25);
break;
case 4:
draw_sprite( screen, Face_R, x*25, y*25);
break;
}



if (key[KEY_UP] && y>=1){ y=y-1; Face_Direction=3;}
else if (key[KEY_DOWN] && y<=4){ y=y+1; Face_Direction=1;}
else if (key[KEY_RIGHT] && x<=4){ x=x+1; Face_Direction=4;}
else if (key[KEY_LEFT] && x>=1){ x=x-1; Face_Direction=2;}
rest(50);
rectfill( screen, 0, 0, 640, 480, makecol( 0, 0, 0));
if (Map[x][y]==2){x=Oldx; y=Oldy;}
for (TileY = 0; TileY <= 4; ++TileY){

for (TileX = 0; TileX <=4; ++TileX){
if(Map[TileX][TileY]==1) draw_sprite(screen, Tile_Grass,TileX*25,TileY*25);
else draw_sprite(screen,Tile_Wall,TileX*25,TileY*25);
}
}
release_screen();
}
readkey();

return 0;

}
END_OF_MAIN();

Amnistar
05-12-2007, 10:04 PM
Make sure your switch statement has a defualt of some sort (I think it's neccessary to compile) which could be any of the directions (probably down? Idle person faces down).

Travis
05-13-2007, 02:03 AM
'default:' is as optional as 'else' is for an if statement. It's a useful thing to consider, but it isn't always necessary. Neo's code compiles and works. He's mainly trying to figure out ways to better organize his code so it is smaller, perhaps more efficient, and easier to maintain.

The next thing for him to do will be using classes to encapsulate the graphics and position data.

neozf
05-13-2007, 05:33 AM
Yea, I'm still reading up on classes.

Edit: I managed to get something working, but when I try to put the BITMAP *graphic stuff into the class it won't compile.
#include <allegro.h>

BITMAP *Face_D;
BITMAP *Face_L;
BITMAP *Face_U;
BITMAP *Face_R;
BITMAP *Menu;
BITMAP *Cursor;
BITMAP *Menu_Screen;
int current=1; //1= Game, 2= Menu.
//int CursorX=0;
int CursorY=0;
int x=0;
int Menu_Show=0;
int y=0;
int Oldx;
int Oldy;
int Map[5][5]={1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,1,1, 1}; //1=Grass, 2=Wall.
int Face_Direction=1; //1= Down, 2= Left, 3= Up, 4= Right.

BITMAP *Tile_Grass;
BITMAP *Tile_Wall;
int TileX, TileY;
class Tile{

public:
void display();

}tile;

void Tile::display(){
for (TileY = 0; TileY <= 4; ++TileY){

for (TileX = 0; TileX <=4; ++TileX){
if(Map[TileX][TileY]==1) draw_sprite(screen, Tile_Grass,TileX*25,TileY*25);
else draw_sprite(screen,Tile_Wall,TileX*25,TileY*25);
}
}
}

int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0);

Face_D = load_bitmap( "Face_D.bmp", NULL);
Face_L = load_bitmap( "Face_L.bmp", NULL);
Face_U = load_bitmap( "Face_U.bmp", NULL);
Face_R = load_bitmap( "Face_R.bmp", NULL);
Tile_Grass = load_bitmap( "Tile_Grass.bmp", NULL);
Tile_Wall = load_bitmap( "Tile_Wall.bmp", NULL);
Menu = load_bitmap( "Menu.bmp", NULL);
Cursor = load_bitmap( "Cursor.bmp", NULL);
Menu_Screen = load_bitmap( "Menu_Screen.bmp", NULL);

acquire_screen();


while ( !key[KEY_ESC] ){
Oldx=x;
Oldy=y;



switch(Face_Direction){
case 1:
draw_sprite( screen, Face_D, x*25, y*25);
break;
case 2:
draw_sprite( screen, Face_L, x*25, y*25);
break;
case 3:
draw_sprite( screen, Face_U, x*25, y*25);
break;
case 4:
draw_sprite( screen, Face_R, x*25, y*25);
break;
}
draw_sprite( screen, Menu, 0,125);

if(current==1){
if (key[KEY_UP] && y>=1){ y=y-1; Face_Direction=3;}
else if (key[KEY_DOWN] && y<=3){ y=y+1; Face_Direction=1;}
else if (key[KEY_RIGHT] && x<=3){ x=x+1; Face_Direction=4;}
else if (key[KEY_LEFT] && x>=1){ x=x-1; Face_Direction=2;}
}
else{
if(Menu_Show==1){draw_sprite( screen, Menu_Screen, 0,0);}
if(CursorY==0){draw_sprite( screen, Cursor, 3, 127);}
else{draw_sprite( screen, Cursor, 3, 148);}
if (key[KEY_UP] && CursorY==1){ CursorY--;}
else if(key[KEY_DOWN] && CursorY==0){ CursorY++; }
if(key[KEY_Z]){Menu_Show=1;}
if(key[KEY_X]){current=1;Menu_Show=0;}

}

if (key[KEY_Z]){current=2;}

rest(100);
rectfill( screen, 0, 0, 100, 150, makecol( 0, 0, 0));
if (Map[x][y]==2){x=Oldx; y=Oldy;}
tile.display();

release_screen();
}
readkey();

return 0;
}
END_OF_MAIN();Also, how would I get it to make a window instead of going full screen?

EDIT:More changes made, I added a menu to it which you can access using Z and close using X.

Another Edit: Screenshot!http://www.editingarchive.com/imgs/328.jpg It looks strange because I had to save it as a Jpeg file, the graphics are in .bmp though. All made by me using MS Paint :D

Travis
05-13-2007, 11:18 AM
Wow! Great job so far, Neo! You're really going through this engine... +10 for showing that someone can belt out at least a simple, working prototype in a day or so.

We'll work on getting the classes just right, but as for the window/fullscreen thing, that should be an option specified when you initialize the Allegro screen. I'll try looking through the API and see if I can find anything.

Edit: Okay, one... use this: http://alleg.sourceforge.net/stabledocs/en/allegro.html
That is the API for Allegro, and you will need it if you are going to change things like if you want Hardware Acceleration or Windowed Mode or other such system-level operations. For your issue with the Windowing mode, specify GFX_AUTODETECT_WINDOWED instead of GFX_AUTODETECT in your call to set_gfx_mode().

neozf
05-13-2007, 12:18 PM
Current source code, Class for the Tile/Map making seem to be finished, just an error somewhere causing it not to load correctly.

Edit: Bah, putting // infront of tile.display(); seems to fix it but then the map won't show (Yes I know why). So that means that the crash is being caused by the class somewhere, anyone got an idea as to where in the class it is?

ElyCyan
05-14-2007, 08:59 AM
Mmm, I approve highly of this thread.

neozf
05-14-2007, 07:02 PM
Current version, Map class added, still not working correctly due to a bug in the tile class :/
#include <allegro.h>

BITMAP *Face_D;
BITMAP *Face_L;
BITMAP *Face_U;
BITMAP *Face_R;
BITMAP *Menu;
BITMAP *Cursor;
BITMAP *Menu_Screen;
int current=1; //1= Game, 2= Menu.
int CursorY=0;
int x=0;
int Menu_Show=0;
int y=0;
int Oldx;
int Oldy;
int Map1[5][5]={1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,1,1, 1}; //1=Grass, 2=Wall.
int Face_Direction=1; //1= Down, 2= Left, 3= Up, 4= Right.
class Tile{
int TileX, TileY;
BITMAP *Tile_Grass;
BITMAP *Tile_Wall;
public:
Tile();
void display();
}tile;

Tile::Tile(){
Tile_Grass = load_bitmap( "Tile_Grass.bmp", NULL);
Tile_Wall = load_bitmap( "Tile_Wall.bmp", NULL);
TileX=0; TileY=0;
}


void Tile::display(){
if(Map1[TileX][TileY]==1) draw_sprite(screen, Tile_Grass,TileX*25,TileY*25);
else draw_sprite(screen,Tile_Wall,TileX*25,TileY*25);
}



class Map{
Tile tile_array[5][5];
public:
void display();
Map();
}map;


void Map::display(){
for (int MapY = 0; MapY <= 4; MapY++){
for (int MapX = 0; MapX <=4; MapX++){
tile_array[MapX][MapY].display();
}
}
}


Map::Map(){tile_array[5][5]={}; }


class Character{};


int main(){

allegro_init();
install_keyboard();
set_color_depth(16);
set_gfx_mode( GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);

Face_D = load_bitmap( "Face_D.bmp", NULL);
Face_L = load_bitmap( "Face_L.bmp", NULL);
Face_U = load_bitmap( "Face_U.bmp", NULL);
Face_R = load_bitmap( "Face_R.bmp", NULL);
Menu = load_bitmap( "Menu.bmp", NULL);
Cursor = load_bitmap( "Cursor.bmp", NULL);
Menu_Screen = load_bitmap( "Menu_Screen.bmp", NULL);

acquire_screen();


while ( !key[KEY_ESC] ){
Oldx=x;
Oldy=y;



switch(Face_Direction){
case 1:
draw_sprite( screen, Face_D, x*25, y*25);
break;
case 2:
draw_sprite( screen, Face_L, x*25, y*25);
break;
case 3:
draw_sprite( screen, Face_U, x*25, y*25);
break;
case 4:
draw_sprite( screen, Face_R, x*25, y*25);
break;
}
draw_sprite( screen, Menu, 0,125);

if(current==1){
if (key[KEY_UP] && y>=1){ y=y-1; Face_Direction=3;}
else if (key[KEY_DOWN] && y<=3){ y=y+1; Face_Direction=1;}
else if (key[KEY_RIGHT] && x<=3){ x=x+1; Face_Direction=4;}
else if (key[KEY_LEFT] && x>=1){ x=x-1; Face_Direction=2;}
}
else{
if(Menu_Show==1){draw_sprite( screen, Menu_Screen, 0,0);}
if(CursorY==0){draw_sprite( screen, Cursor, 3, 127);}
else{draw_sprite( screen, Cursor, 3, 148);}
if (key[KEY_UP] && CursorY==1){ CursorY--;}
else if(key[KEY_DOWN] && CursorY==0){ CursorY++; }
if(key[KEY_Z]){Menu_Show=1;}
if(key[KEY_X]){current=1;Menu_Show=0;}

}

if (key[KEY_Z]){current=2;}

rest(100);
rectfill( screen, 0, 0, 250, 250, makecol( 0, 0, 0));
if (Map1[x][y]==2){x=Oldx; y=Oldy;}

map.display();

release_screen();
}
readkey();

return 0;
}
END_OF_MAIN();