ok so i am making an RPG game. I am in the process of rewriting the ENTIRE game using allegro and a simple tile set that i have made myself.
but every time i as for help people always tell me one of two things with my program.
1:
they tell me that i need to use structures for my inventory/banking system
2:
they tell me to take the map arrays out of my program and put them in their own separate files
I know more or less how to use a struct but i have no idea how to use it for the purpose that i want.
People dont have to tell me that this is ugly I realize its a terrible god aweful way to make an inventory/banking system. but it was what i knew how to do.
believe me i have worked on this for a very long time and I dont know how to change it to be more efficient. so could someone please help me out.
i know most people hate it when people ask for exactly how to do it. but that is pretty much what im asking for at this point, but please explain it to me in great detail if you can.
You can find the function that actually allows you to mine and get ore at: 1555
you can find the inventory storing at: 801
you can find the ore banking at: 5152
ok my computer is being extremely slow at the moment and wont upload my attachment so you can find it here on google sites:
https://sites.google.com/site/temprpgquestion/go-here-for-the-program
Thank you all for the help in advance. i really appreciate it.
so i am working on the menu screen right now and this is what i have so far
My first suggestion is to break your file apart. Don't EVER be afraid of splitting a single large file into smaller parts.
It makes the individual parts easier to read.
It lets you know when things are too tightly coupled (things that rely on each other "too much").
It helps you avoid distraction.
My second suggestion: Instead of telling us the line numbers you need advice with, specify the name of the function you need help on.
Line 1555: void Start_Mining()
Line 801: void Items_List()
Line 5152: (no method; just an if() block)
My third suggestion: Within your Bank_Action() function, you have long if() blocks. Break those out into their own functions. I'd love to see this 3300-line function broken down to something a little more manageable:
Now within Bank_Prompt_To_Deposit(), you have its own if() blocks:
You'd do the same for all the rest of the stuff.
Last of all, I'm not exactly sure what question you're asking.
...please explain it to me in great detail if you can...
What did you want explained?
Something that would shorten your level select code would be a function pointer array. Then all you would need to do is index the array to run the function to select the level.
Example :
But what you really want is probably to load each level from a file. nvm, can't read
@OnlineCop
Wow. yeah i did not think about that. It would take care of not knowing how to use structs. i would still have to use that big long ugly list everything out but it would be so much easier just to list it once in its own function. thanks a bunch.
I think that two things will help this code: the use of struct or class, and replacing redundant code with functions. Many things can be simplified, like when you have text that is identical in all places except maybe the monster name or the amount of damage taken.
One example is void Monster_1():
You can convert this into a simple function that you can reuse multiple times:
As you can see, the text is almost the same for each battle, the logic is nearly the same, and you can simply pass in parameters to change the parts that should differ.
Next, use of struct or class. For C++, they are identical except that the former makes everything public unless you specify otherwise, and the latter makes everything private unless you specify (respectively).
Two perfect candidates for a struct are monsters and the player.
This is the general structure of the Player. It doesn't contain any data (yet). It just specifies that anything that gets defined as a Player will have a Name, will have Health and Attack/Defence attributes, and so forth.
You create an instance of the player (which will contain values for all the attributes) like:
S_Player player;
Now, you pass around the player and it's much easier to understand whether "Health" belongs to monster.Health or player.Health.
If you're struggling to understand any of these, ask.
Yeah I get both of those just fine and will for sure be adding them into my current remaking of the project. Someone along the line of that console based game told me that I should make the inventory into I think they said boolean structure. And I was like... what? And so I didn't implant that. I tried looking it up and stuff but I just could not wrap my mind around any way to take a structure such as tuna fish; and tuna.amount; and use that in my inventory system any different then how I am already using my inventory system.couldn't quite figure out how a boolean would go in there to make it different.
So where I have those big long if statements where I list everysingle item in the game and repeat for every single item in the game.
am I able to pass something like this:
If(tuna + Items list <= BankSpace)
store the item of so much amount;
I'm on my phone at the moment because I couldn't sleep so I don't really remember how that one went exactly. But is that possible to pass all the items through a function like that in an if statement? so I don't have to type so much? Because that was by far the worst part of typing that code and why I stopped working on it where i did.
Thanks a lot for all the help you guys.
Yes, it's actually a good idea to pass things through functions for that reason.
I suggest that you create an enumeration:
Then you create an array:
int All_Ores[Number_Of_Ores];
Now instead of keeping track of individual ores, you can specify exactly ONE array, index any of the individual ores whenever you want, and counting up the total ores is as simple as iterating over the array:
int Total_Ore_Count = 0; for (int i = 0; i < Number_Of_Ores; i++) { Total_Ore_Count += All_Ores[i]; } cout << "You have " << Total_Ore_Count << " ores in your inventory.";
You're also able to update only the ore you care about:
All_Ores[Mithril_Ore] += 5;
If you do that with all your other items as well (one for fish types, one for wood types), then you can get rid of that long if() block and condense it down to only a handful of lines.
Thanks a bunch. i more or less get how to use enum but i think i could use that one.
can i have an enum within an enum
for example
enum AllItems
{
enum AllOres
{
copper, tin, so on, number of ore
};
enum AllFish
{
Trout, tuna, so on, number of fish
};
number of total items
};
/
/
/
/
/
and also could you please help me figure this out?
what i am doing is simply just getting the map to change by changing the Level X and Y value in the code itself. but when i change it like this:
from
x and y = 0
to
x = 1
y = 0
nothing happens. it still only displays the first map. but when i get rid of the else and have a double if statement then the opposite happens. only the second map is drawn to the screen.
i am doing basically the same type of code i used for my character movement in the console to move between the maps. and will have a copy of the map arrays that is left blank except for the added in character and npc. this way i can manipulate on top of the drawn map without having to redraw it. and also the only way i know how to do collision detection.
void LevelSelect()
{
int LevelSelectArray[10][10] = {
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
{31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
{41, 42, 43, 44, 45, 46, 47, 48, 49, 50},
{51, 52, 53, 54, 55, 56, 57, 58, 59, 60},
{61, 62, 63, 64, 65, 66, 67, 68, 69, 70},
{71, 72, 73, 74, 75, 76, 77, 78, 79, 80},
{81, 82, 83, 84, 85, 86, 87, 88, 89, 90},
{91, 92, 93, 94, 95, 96, 97, 98, 99, 100}
};
int LevelX;
int LevelY;
bool FirstTime = true;
if(FirstTime)
{
LevelX = 0;
LevelY = 0;
FirstTime = false;
}
if(ArrayLevelSelect[LevelX][LevelY] = 1)
{
Level1();
}
else if(ArrayLevelSelect[LevelX][LevelY] = 2)
{
Level2();
}
}
//for the example the only difference is the 5 and the 10
void Level1()
{
int Level[5][5] = {
{1, 1, 1, 1, 1},
{1, 0, 0, 0, 1},
{1, 0, 0, 0, 1},
{1, 0, 0, 5, 1},
{1, 1, 1, 1, 1}
};
memcpy(Map, Level, sizeof(Level));
}
void Level2()
{
int Level[5][5] = {
{1, 1, 1, 1, 1},
{1, 0, 0, 0, 1},
{1, 0, 0, 0, 1},
{1, 0, 0, 10, 1},
{1, 1, 1, 1, 1}
};
memcpy(Map, Level, sizeof(Level));
}
Nope. Enums are not nestable.
ok so they are not nestable. but what if i did something like this?
enum all ore
{
copper, number of ores
}
enum all fish
{
tuna, number of fish
}
enum all items
{
Number of ores, number of fish
}
You can probably do that. though the last enum may not be needed (I'm not sure of the purpose for that).
Just note that each enum starts from 0 if you don't give it a starting value.
The last enum is not needed: correct. HOWEVER, it just "happens" to be the total number of all the items in the enum, so you don't have to try to determine the enum's size at runtime (or remember all the places that you hardcoded the size) in case you need to add any more enum values.
Logically, you want to separate your "fish" from your "ores". Wood doesn't feed you, so won't make sense to have inside of a massive enum or array that contains food-based items. In the same vein, weapons aren't armor.
It makes a LOT more sense to me to have multiple for() loops, one after the other, than to have some massive array of "everything in the game". My mind just doesn't work like that.
if(ArrayLevelSelect[LevelX][LevelY] = 1)
You are assigning the value of 1 into ArrayLevelSelect[LevelX][LevelY] here. You probably meant == (equality).
Next, onto the subject of your maps.
I have always been of the mindset that all levels in a map should potentially be different sizes: the memory can be allocated when you need it, and freed when you're done with it.
Some maps are the "interiors" of a large house, so they can be smaller. Other maps are vast oceans with a special hidden island right in the middle of them, and can be much larger.
When you create a level, there should be a class that is specifically dedicated to all aspects of its generation and tear-down. You should pass in the level number you want loaded, and get a level back. You should pretend that you have NO idea what's going on "behind the curtain" when you request a level from it.
This class might have the array in memory. It might load it in from a file. It might parse a Tiled-generated XML file. That's the point: it should be a mystery to everything else so you can change it at any time in the future, and as long as "give me level X" always returns a predictable map structure, how it works should always be a black box.
Last of all, DON'T (did you see all the emphasis I put there?) create function calls for levels and things that "will come". Don't copy-and-paste 70 "placeholder" levels when you really only have about 7-8 truly defined. Don't do placeholder fish/wood/weapons/armor. Don't create "dummy" monsters that you'll revisit "someday".
It might make you much less overwhelmed if you drop your file down from the nearly 10,000 lines to about 5,000. Strip away ALL pre-"defined" stuff: get rid of levels 9-70. Get rid of all enemies but two: the rat, and maybe the spider. Get rid of all types of fish. You can leave some of the fish/wood/monster "types" in comments somewhere so you remember them later, but get them out of your current codebase.
Once you have all that, post your new source file results, and we'll move on to breaking them apart into individual files.
Your Monsters should be in one or more files (either a massive monster.cpp file, or individual monster_rat.cpp/monster_spider.cpp files). Your Items should be in one or more files (items.cpp or item_wood.cpp/item_fish.cpp, etc.). Etcetera, etcetera.
OnlineCop, while I agree that separating the item types could be more logical, its a lot more work to manage. Using a single item namespace allows for more efficient loading and saving as you don't have to figure out the category of the item first, and no item ids will ever overlap.
I think that the superfluous enum in Tomasu view was this:
enum all items
{
Number of ores, number of fish
}
The "last item in an enum is the one that enumerates the enum itself" is quite handy
I think that the superfluous enum in Tomasu view was this:
Not only is it superfluous, it also won't work as intended, since it will give the number of ores as 0, the number of fish as 1, etc...
Well in case it is strongly typed I guess ti would be only superfluous, but of course in this case......er now that I come to think of it, would it be even possible?
The names should clash as multiple definition? (too rusty to remember )
Thomas, while I agree with this, I'm trying to work with his code on his programming level.
If I were talking to LennyLen, Arthur or Trent, I'd be suggesting more advanced methods. I feel that these topics wouldn't be appropriate for where he's at now, so I'm doing my best to suggest things that will help him get this project far enough along that he can see some significant success.
Thomas, while I agree with this, I'm trying to work with his code on his programming level.
I honestly think throwing more code at the problem just makes it harder an item is an item, no matter the category. I think that is pretty darn simple
@OnlineCop
Oh. wow. duh. haha == i know that. thats a silly mistake.
ok so my maps work well now and i have loaded 2 in.
I have also drawn in my player in a layer on top of the tilemap like this:
1 wall 2 grass 0 player
11111
12221
12221
12221
11111
11111
10221
12221
12221
11111
in the second array the only thing that gets drawn is the player and everything else is blank. i did this so the player can move freely ontop of the map without changing the map itself.
so a couple of things.
first of all, I know i am going to get crap for having all those huge arrays in my program itself. i get it. they should be in different files. and i am also seeing the result of it when the game is loading in the maps. it takes a minute. and this is only 2 maps!
but i dont know how to use an array in a txt file like that. i have tried but i only know how to do simple variables and store them in an array using fstream. so if someone could help me out with that i would be grateful.
and also, i am trying to figure out how to at this time make the player move. I am going for the same type of movement i have in my console game that i will repost. but i am pretty sure i will have to make the game redraw every time and i thought i had that working but it doesnt work so i will post my current project aswell
and a final question comes when i create my inventory equipment and my incomplete date time thing. when you create them by pressing the "buttons" on the toolbar display it takes a couple of clicks before the new display shows up. and at line 373 of Game() i thought that would close the window. but for some reason it doesnt and i dont know why.
/
/
/
/
/
for the console game go to Line 1164 GameMechanics() to see how the player moves when down is pressed
for the Allegro 5 game go to line 470 PlayerMovement() to see how i thought the player should move when down is pressed.
just above there at 444 of Game() is where i draw the two tilemaps
and PlayerMovement() is passed through Game() at line 321
/
/
/
/
/
/
Thank you all so much for the help!