RPG game (Arrays, Structs Message boxes)
Antone333

To start with, I am making an RPG (rogue like more or less) and it is all made using the the console. I am wanting to work on remaking it using allegro. I know how to use a tile map for integers and am thinking i know how to do simple collision within the array. but i do not like having to make my maps using integers. it is difficult for me to keep track of. So two ways i came up with to solve this are as follow:
1: make the tile map read the characters and create the map that way
2: Convert character array into integer array and then from there i know how to make tile map already

maps look something like this

@ player, # wall, M mountain(mine), T tree, W water, + next map, - previous map

~ just for the sake of this forum wont let me put in a bunch of ' ' it still doesnt quite come out right. but what ever.

map[][] =
{
"##########",
"#@~~~~~MM#",
"#~~~TT~~M#",
"#~~~~~~~~#",
"#~~~WW~~~#",
"#-~~~W~~+#",
"##########"
}
so any help with this is greatly appreciated.

next, I have a very poor inventory system and it is pretty much a pain in the ass to get anything done using it... and yet i have a bunch of items already in game using all integers.

Can someone point me in the right direction to learning structs for an inventory and banking system? see the attached files for how i have it already. it works how i have it but i know there has to be a better way to do this. see lines 801 for inventory and 3844 for bank also see 2190 for cutting down wood, fishing mining and cooking are similar in structure.

Finally i want to know if there is a way to make a native message box where the buttons are custom. for example.

ALLEGRO_MESSAGEBOX_YES_NO now what if i wanted to ask the player if they want to go to the left or the right for example

ALLEGRO_MESSAGEBOX_LEFT_RIGHT I know that this doesnt work. but i want to know if there is a way of doing something along these lines

SiegeLord

al_show_native_message_box does have a buttons argument which in principle lets you have custom buttons. It doesn't look like that's implemented under Windows though (but some quick searching suggests that this is possible).

Edgar Reynaldo

You can use <pre></pre> tags for that :

       ###

To make a tilemap of integer tiles from a map of char you can simply map your chars to integers :

#SelectExpand
1typedef struct TILEINFO { 2 char c; 3 const char* description; 4 int index; 5 ALLEGRO_BITMAP* tile; 6} 7 8TILEINFO tileinfo[] = { 9 {'#' , "Wall" , 0 , al_load_bitmap("Wall.png" }, 10 {'@' , "Player" , 1 , al_load_bitmap("Player.png" }, 11 {'~' , "Empty" , 2 , al_load_bitmap("Empty.png" }, 12 {'M' , "Mountain" , 3 , al_load_bitmap("Mountain.png" }, 13 {'T' , "Tree" , 4 , al_load_bitmap("Tree.png" }, 14 {'W' , "Water" , 5 , al_load_bitmap("Water.png" }, 15 {'+' , "PlusLevel" , 6 , al_load_bitmap("PlusLevel.png"} 16}; 17 18#define TILEINFOSIZE 7 19 20//Then you have your char map : 21const char* map1[] = { 22 {"######"}, 23 {"#@~~M#"}, 24 {"#~~MM#"}, 25 {"#W~T+#"}, 26 {"######"}, 27 {0} 28}; 29 30const char** map = map1; 31// to draw (all of) your map : 32int row = 0; 33int y = mapy; 34while (map[row] != 0) { 35 int i = 0; 36 int x = mapx; 37 while (i < strlen(map[row])) { 38 for (int ndx = 0 ; ndx < TILEINFOSIZE ; ++ndx) { 39 if (tileinfo[ndx].c == map[row][i]) { 40 al_draw_bitmap(tileinfo[ndx].tile , x , y , 0); 41 break; 42 } 43 } 44 ++i; 45 x += TILEWIDTH; 46 } 47 ++row; 48 y += TILEHEIGHT; 49}

You have a serious need to learn how to use arrays and maps and textfiles. Your code would be hundreds of times shorter.

Even a simple std::map<std::string , int> would be useful for keeping track of inventory. You can simply use things like map["Item"]++ or map["Axes"]--.

beoran

A char in C is also an integer with a small range so if you cleverly lay out your tiles in a tile atlas, no conversion will be needed.

I looked at your source code and yes, you need to learn how to use structs and arrays. There are pleny of tutorial web sites or books on C that can help you get started but here a few untested ideas (in C, not C++) you could use and complete:

#SelectExpand
1 2struct Item { 3 int number; 4 const char * name; 5 int type; 6 int effect; 7 int quality; 8}; 9 10struct Skill { 11 int number; 12 const char * name; 13 int type; 14 int effect; 15}; 16 17enum ItemType { 18 ITEM_EQUIPMENT = 1, 19 ITEM_USABLE = 2, 20 ITEM_MATERIAL = 4, 21}; 22 23enum SkillType { 24 SKILL_COMBAT = 1, 25 SKILL_GATHERING= 2, 26 SKILL_CRAFTING = 4, 27}; 28 29enum Effect { 30 NO_EFFECT = 1, 31 HEALING_EFFECT = 2, 32 FIRE_EFFECT = 4, 33 ICE_EFFECT = 8, 34 SHOCK_EFFECT = 16, 35 DARK_EFFECT = 32, 36 LIGHT_EFFECT = 64, 37 MANA_EFFECT = 128, 38 COMBAT_EFFECT = 256, 39 MINING_EFFECT = 512, 40}; 41 42enum ItemNumber { 43 ITEM_RUSTY_AXE, 44 ITEM_STEEL_AXE, 45 ITEM_METREAL_AXE, 46 ITEM_POTION, 47 ITEM_ELIXIR, 48}; 49 50enum SkillNumber { 51 SKILL_AXES, 52 SKILL_SWORDS, 53 SKILL_MINING, 54}; 55 56struct Item items[] = { 57 {ITEM_RUSTY_AXE , "Rusty Axe" , ITEM_EQUIPMENT, COMBAT_EFFECT, 5 }, 58 {ITEM_STEEL_AXE , "Steel Axe" , ITEM_EQUIPMENT, COMBAT_EFFECT, 10 }, 59 {ITEM_METREAL_AXE, "Methreal Axe", ITEM_EQUIPMENT, COMBAT_EFFECT, 20 }, 60 {ITEM_POTION , "Potion" , ITEM_USABLE , HEALING_EFFECT, 5 }, 61 {ITEM_ELIXIR , "Elixir" , ITEM_USABLE , HEALING_EFFECT, 20 }, 62}; 63 64struct Skill skills[] = { 65 {SKILL_AXES , "Axe Skill" , SKILL_COMBAT , COMBAT_EFFECT }, 66 {SKILL_MINING, "Minging Skill" , SKILL_GATHERING, MINING_EFFECT }, 67}; 68 69enum Constants { 70 INVENTORY_MAX = 30, 71 BEING_SKILL_MAX = 30, 72}; 73 74 75struct InventoryItem { 76 int item_number; 77 int amount; 78}; 79 80struct BeingSkill { 81 int skill_number; 82 int level; 83 int experience; 84}; 85 86 87struct Being { 88 int hp, hpmax; 89 int mp, mpmax; 90 int money; 91 struct InventoryItem[INVENTORY_MAX] items; 92 struct BeingSkill[BEING_SKILL_MAX] skills; 93}; 94 95struct Being player;

Audric

Edgar, I don't think you can set the bitmaps this way because it would call al_load_bitmap() too early.
A workaround is to add the file names in the struct array, and keep the pointer to bitmap at NULL initially. After allegro initialization (and graphic mode selection, I think) you can loop on the array:

for(i = 0; i < sizeof(tileinfo)/sizeof(tileinfo[0]); i++)
   tileinfo[i].tile = al_load_bitmap(tileinfo[i].filename};

Antone333

beoran i at least sort of know what structs are, but when it comes to enum i am very lost and have no idea how to use those.

one of the biggest things that i need help with for structs is how once i have created all the item structures and what not do i then make the program read every single struct without me having to specifically write them all out the way i currently have it.

and also another thing i will add is for the tiles i would prefer to just have all the tiles in one .png this is what i made a good while back. i started working with allegro about 2 months ago but got very frustrated because i broke off more then i knew how to do in c++ let alone allegro. but this is the tile sheet i made. it was a very rough drawing and i will likely redraw it for the specific need of this current game.

one last thing too, Edgar Reynaldo, i would also prefer to keep my maps as a 2d array. and i also know how to use text files... but i am also lazy. and just have not gotten around to moving all of the maps into text files. i mean there are 70 of them. haha that is going to take forever. When i do finally move the map to a text file i will have to make all the blank spaces ~ right? but that wont matter when i do finally work out the tiles.

if i do something like this. i dont see how to tell what item the character has. if the player has a sword is there a way of doing something like get item.id and then it will run through all the item1.id item2.id and so on and see what matches and then tell you that if item.id = item1.id then you have a sword.

#include <iostream>

using namespace std;

char end[5];

struct item
{
string name;
int id;
};

int main()
{
item item1;
item item2;

item1.name = "sword";
item2.name = "ax";
item1.id = 1;
item2.id = 2;

cout << item1.name << " " << item1.id << endl << endl << item2.name << " " << item2.id;

cin >> end[5];
return 0;
}

beoran

In C, an enum is just a way to define several integer constants. Look it up, it's
worth learning!

Once you use arrays of structs as I suggested, you can start making loops an lookups to do things, in stead of hard-coding everything. It's hard to explain in short, I suggest you learn more about the C language to better understand how this would work.

It's certainly possible to use a single bitmap for the tiles (this is called a "tile atlas"). You need to use either sub-bitmaps or Alegro's more complex bitmap drawing functions that select the part of the single bitmap you want to display.

As for seeing which item a player has, withc what I suggested, you would look up the item's id in the item array, and then you know which name to display, which effects it has, etc. What an item is and which items the player has are two different things and should be stored in different variables.

Antone333

so it would be something more or less like

the item is 1
item is sword

the player has 1

if item is = item has
player has sword
that way they are separate?

Does anyone know a good book that i can buy to help me? might as well go with something based on game programming as that is what i am working on right now. but even if not. just a good book in general for learning c++ would be nice.

Edgar Reynaldo

Audric has a good point. I'm just used to C++ where you can declare anything you want anywhere. :D That would be a better method.

Antone333 said:

one last thing too, Edgar Reynaldo, i would also prefer to keep my maps as a 2d array. and i also know how to use text files... but i am also lazy. and just have not gotten around to moving all of the maps into text files. i mean there are 70 of them. haha that is going to take forever. When i do finally move the map to a text file i will have to make all the blank spaces ~ right? but that wont matter when i do finally work out the tiles.

That's the thing, they are a 2D array. map[row][column] gives you the char at column,row (x,y). You just index it by row first. You can make a 2D array of char like this :

char map1[][] = {
   {'#','#','#'},
   {'#','W','#'},
   {'#','+','#'},
   {'#','#','#'}
};

But notice doing it this way you have to enclose everything in single quotes ''. Because they are char literals. A literal is a predefined string or data.

Antone333

so would it be easier the way i have my maps set up just to have individual files for each tile?

Edgar Reynaldo

You can just change your TILEINFO struct to accept x,y,w,h members to store the location of the tile on your atlas.

Thread #614571. Printed from Allegro.cc