Hello everyone, im really new to Programming, i'm reading books and also follow Online Tutorials to create my own RPG game as a "Learning" project.
Ive runned into this Problem tho, ive tried to search it up but havent found any usefull help so i'm posting here to see if anyone could crack this problem to help me out.
I got this beginning of a RPG game with a Character with Sprite Animation, also Screen Scrolling, now im trying to add Tile maps and im not applying them directly in my code, i have a seperate .txt file that im trying to load it from, but somehow i cant get this to work, when i run the code i dont get ANY errors, just that the tiles are invisible... The online tutorial ive been follow did the exacly same thing and its working for him, i tried after hours and hours to copy his code and just run it to see what happend, and same thing happend nothing... code runns perfectly in my compiler with no erros but nothing shows up... is it something wrong with my Compiler? my installation of Allegro5? I mean everything els works in the Allegro 5 Library so i dont really understand..
id preciate if anyone could look over my code and see if im doing something wrong!
Here is the code:
If you want to post code, just place it between <code></code> tags.
Thanks alot LennyLen,
for some reason my mind set was set at [] instead of <>
Heres my code to a simple Tilemap application thingy, it loads a map thats 32*40, 32*30 and instead of drawing each tile separately (like you do) it makes a bitmap from the tiles, which can be easily updated/drawn - reducing cpu% from 30-50 to around 4%
You can edit it/do whatever you want with it if it helps
http://i.imgur.com/11tVr.png
Thanks alot Angeljruiz!
I will have to read through this code for a VERY long time
i recognize alot of it but im very new to programming as you can probebly see, thanks alot tho for sharing your code with me to help me with my problem
ifstream Map("Map1.txt");
Hmm, getting error, dont really know where you are going with it, think its a typo but cant figure out what it should say.
I was thinking about going with this approach with my current game, but my maps are 1024x1024 tiles big and the tiles are 16x16 pixels. This translates to a 16384x16384 image which would take up 1 GB of video RAM.
...yeah, had to take a different approach, more like how the NES works.
Yeah my code wasent really optimal, but thats fine i love to learn, so people that could improve my knowledge i really appreciate it, tho right now im having problem with the ifstream Map("Map1.txt"); in Angel's Code, hmm like i said my Knowledge is really thin im learning new things everyday!
Yeahh making it into a bitmap only works if the map isnt that big :p
But im not at my house right now so i cant give you the map but the format is really easy its just 0-4 40 number wide and 30 numbers high, tiles with the #0 are solid the rest arent
I guess ill give you the sprites to go with it too :p
@Kris - how did you load/display your tiles?
yeah that would be great Angel so i could have a look how everything is working together, its just in the code the ifstream map("map1.txt");
The ifstream is a typo isent it? because i get an error,if stream map,fstream map, doesent work either,ive tried to think what it should say but im stuck there
I dont know why you would be getting a error like that. If you didnt already know ifstream is a (i)nput (f)ile stream. Its used to open read/write to files. Its functions are declared in the fstream header so if you have #include <fstream> in your code it should work
That is extremly odd, yeah i got <fstream> included, and thank you for explaining what ifstream does, hmm... this is very odd...
void loadmap(int Tiles[][30]) { int x(0), y(0); int temp; ifstream map("map.txt"); if (Map.is_open())
ifstream map("map.txt"); <---- identifier ifstream is Undefined
if (Map.is_open()) <---- identifier "map" is undefined
Im not sure exactly... If you have the header file included and using namespace std right under it and you're compiling it as a c++ file, not a c file, it should work
Alright i got the ifstream to work now, the problem was i forgot the "using namespace std;" stupid noob mistake, now i get the 'map' undeclared identifier, so i gotta look why it is undeclared, i must have forgot something in the code, Anyway if you could attache the sprite image and the .txt so i could just have a look at it how it works i would appreciate it a ton! When your at your home that is.
thanks again Angel
You have ifstream map and Map.is_open() , there capitalized differently :p
Ill be home i about 2 hours but you could easily make the map.txt file by just filling 40x30 with ones and just use any sprite for the character
Yeah thank you i missed the small M so now my code runns into NO errors, tho nothing shows up when i use the txt file, to be exact im writing the 1's like this:
1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
Anyway the same problem like my own code, nothing shows up.
and im sorry i meant the tiles not the sprites before, i think im messing something up in my .txt file or my tiles.png file and thats why nothin shows up, so ill just wait until you get the time to send me your files so i can have a look what i'm doing wrong here
map1.txt
http://art.devsader.com/content/contributions/sprites/BoyKnight_Moosader.png <- Save as Player.png
http://art.devsader.com/content/contributions/textures/FloorTiles_Moosader.png <- Save as Tiles.png
And uncomment the first set of switch statements and comment out the 2nd set
EDIT:
Also go check out moosader.com , its where i got the sprites from (they have no copy right so you can do whatever with them) , it has alot of free sprites and tutorials, its actually what got me coding
Alright, thanks alot Angel, trying everything out right now, i get the concept now ive learned ALOT by starting this Topic, i see now that i have to make every tiles 32x32 and then the program will just crop 1 image 32x32 and assigning a numer to the tile right so lets say, 1 = grass tile, if i assigne it to be the first 32x32 in the png to 1?
Also i get this error now, Debug error R6010 Abort. i have no idea why im getting it i guess something has the wrong value in my code, ill just post my new code if anyone ever got time to throw an eye on it.
[EDIT] When i switch the position of the :
loadmap(Tiles);
updateBitTile(Tiles, BitTile, tiles, display);
to higher up in the code the Error R6010 abort is gone, but still no Tiles are shown, just a black window with my lonely Character sprite , tho if i uncomment the Switch code Case 0 and Case 1, and then comment out the al_draw_bitmap_region(tiles, Tiles[x][y]*32, 0, 32, 32, x*32, y*32, NULL);
i get no error but still no tile map, if i uncomment the:
al_draw_bitmap_region(tiles, Tiles[x][y]*32, 0, 32, 32, x*32, y*32, NULL);
i get Error again, same one R6010, hmmm
@Kris - how did you load/display your tiles?
Loading's easy. Just have them all together on a single bitmap and load it in, then create sub-bitmaps off of it for sake of simplicity for each kind of tile.
The maps themselves are procedurally generated at present, though eventually I have to incorporate saving and loading of them since a single run through my game will take several hours.
But as for displaying them, I took a page out of the book of the NES. Older game consoles don't have the power to constantly refresh the tiles on-screen, nor the memory to store an active bitmap of an entire map/level, but because these older systems were specifically designed around a tile/sprite concept, they have a tile page (sometimes referred to as the "name page") where a series of tiles can be stored and this page can be drawn to the screen from any spot, wrapping around at its edges. This way, only tiles that have freshly come on screen need to actually be updated, and the rest are simply there already from previous drawing operations.
This is essentially the same approach I've taken. I have a tile page which is essentially a 4096x4096 texture (largest safe size, takes up 64 MB of video RAM) that wraps around and only has tiles written to it when they change or come into view. At present, the only way to pull this off with Allegro is using the primitives add-on, as textures will not wrap with the standard bitmap functions. To know how many rows/columns to draw, I track positional data relative to the edges of a camera frame and as this frame moves, the system tracks how many new rows and columns worth of tiles to draw. I can also request the system to redraw the entire tile page, which is necessary when first booting in or if the camera needs to jump to a new spot immediately.
This is definitely the hardest way to do it, but offers the best performance possible. With very small tile sizes like I'm using, this method is a must to avoid the overhead of thousands of tile drawing calls per frame. With typical tile sizes though, it doesn't make a huge difference on modern hardware.
Ohh thats really cool, ill have to check that out. Could you give some sample code?
As for EnClave it seems like you never actually draw the tiles, just the character
Just draw the BitTiles bitmap as you would normally with its x and y positions as 0 minus the offset values (OffsetX and OffsetY in my code)
Its wierd tho Angel even if i copy your code straight off, if i save the Tiles, and Knight png to my project folder, if i create a cPlayer class in Header file and check that no errors accure when i debug the program i get ERROR R6010 Abort, and i cant do anything with it, thats what is very wierd...I know im being a Pain in the ass right now but i seriously cant figure it out... been trying to fix the Tilemaps 3 different ways now i either get nothing or Error R6010... i dont get it
Alright try this
This code checks for bad sprites, which is something i shoulda done in the the first place, and the collision is better now.
Just make sure that the sprites are in the same directory as the executable, just because its in the project folder doesnt mean its going to put it in right directory. Like in xcode you have to specifically tell it to copy the sprites to the executable folder. Hopefully this works X)
Angel....You are my HERO! thank you for being so PATIENT with me, it FINNALY worked... it was such a stupid mistake that its to embarassing to tell ... Anyway Thank you.
Haha no problem
Ohh thats really cool, ill have to check that out. Could you give some sample code?
Nope!
The big reason why I can't really is because the system is specifically tailored for the game I'm making. In order for the code to make sense, I would have to provide you with the entire rendering, mapping, and tile processing source code, which is not going to happen.
It also still has some minor bugs which I'm going to be addressing as development of my game continues. Also, because it's inteded to be a commercial indie title, I don't want to share routines that took an extreme amount of effort to code. At least, not until the game's out.
What I can say though is that the key to making it work is creating a large texture for your tile page and treat camera positions on it with modulo values. (IE: For a 4096x4096 texture, your camera's XY coordinates on it would have fmod(coord,4096.0f) applied.) Then just use Allegro's primitives add-on to draw from the texture WITHOUT applying fmod to your source coordinates so that the texture wraps around its edges when drawing it to the screen.
If you only use the primitive functions to draw to the texture you can avoid having to fmod anything, but Allegro's bitmap drawing functions are far-better optimized for drawing lots of things at once, whereas with the primitives add-on you have to queue up all of your drawing ops into an array before you make them. (Though you can draw a ton more stuff per frame this way if you feel up to the challenge.)
It's a lot more complicated than that though and again, unless you're working with tile sizes so small that you have to draw over a thousand or two per frame, the performance boost is not worth the effort. Since I have to render 15,000 tiles per frame... yeah...
Kris or Angel or anyone?, i have a question, when i draw tiles from my TXT document it follows the 0 1 2 3 4 5 6 depending on my PNG file, the first 64x64 is grass so its = 0, then the other is a stone tile, then it automaticly = 1 because they are like that in the Tilesheet, but it only reads horizontal and now ive runned out of tiles in my png file because it only reads horizontal, i got 17 tiles right now each is 64x64, is there anyway to read the tiles that are under it so for an example:
The numbers represent a Tile in the PNG file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [STOP at the PNG file]
18 19 20 21 22 23 24 25 26 27 28 29 30 31 [is there anyway to continue like this?]
Thanks in advance,
EnClave
_tile_sheet = VZ_LoadBitmap("Textures","vz_tiles_1.png",ALLEGRO_VIDEO_BITMAP|ALLEGRO_MIN_LINEAR|ALLEGRO_MAG_LINEAR|ALLEGRO_NO_PREMULTIPLIED_ALPHA); if (_tile_sheet == NULL) FatalErrorMsg(8,display); for (z = 0; z < VZ_MAX_FRAMES; z++) if ((tile_bmp[z] = al_create_sub_bitmap(_tile_sheet,(z%51)*20+2,(z/51)*20+2,16,16)) == NULL) FatalErrorMsg(9,display);
This is my tile loading code. Typically, you want to modulo one coordinate by the number of tiles per col/row, and divide the other. In my case, each column goes up by 1 and each row by 51, so I modulo the X by 51 and divide the Y by 51, then just multiply each by the space between each tile.
I also extend my tiles by 2 pixels in both directions since I have to be prepared to scale them. In fact, this a good practice to do with ALL 2D graphics using hardware acceleration that need to be joined together out of pieces, like status bars and whatnot.
Kris, I see you use things like FatalErrorMsg(8,display); apparently with 8 or 9 to get information about the point where the problem was raised.
In case you don't know, compilers provide macros like _FILE_ and _LINE_ that expand into source filename and line number.
This allows writing macros like
#define FATAL_ERR Error_handler(__FILE__, __LINE__)
Then you can use the macro any number of time, each occurence will pass a different filename + line number.
Edit: GCC additionally provides _func_ which is the function's name.
Thats understandable kris :p Thanks for introducing me to a interesting concept tho
@Enclave what do you mean?
In case you don't know, compilers provide macros like FILE and LINE that expand into source filename and line number.
Didn't know that... but it wouldn't really help me much anyways since I can actually use the MSVC10 debugger with A5 projects and the FatalErrorMsg() routine I developed is intended for end-users to know what went wrong if something does go wrong in the completed product.
My only problem at the moment is that the popups produced by the FatalErrorMsg() routine are appearing BEHIND the Allegro window, and when I try to shut the program down with an exit() call it's turning Allegro off before calling my additional uninitialization routines, which crashes the program. Meh, I'll figure out how to make that all work soon enough, it's not a high priority right now.
Why don't use allegro native dialogs? They work fine. Unless there's a crash already happened, of course.
Why don't use allegro native dialogs? They work fine. Unless there's a crash already happened, of course.
I am.
void FatalErrorMsg (int errornum, ALLEGRO_DISPLAY *display) { if (display != NULL) al_show_mouse_cursor(display); al_show_native_message_box(display, "Vectorzone - Fatal Error", _errormsg[errornum], NULL, NULL, ALLEGRO_MESSAGEBOX_ERROR); exit(1); }
this is my code to load tiles right now,
BlockSize = 64
and I'm kind of loading the pngs from the .txt files, like this:
[TileSet]
test.png
[Map]
3 3 3 5 5 5 5 5 5
3 3 3 5 5 5 5 5 5
4 3 3 5 5 5 5 5 5
my problem is tho that in my Tilesheet my program can only load tiles horizontal right now my .png file is 1088x64 because it can only load horizontal but now i have runned out of space in the .png file, i want it to be example 1088x128 and the program can load the tiles on the second row aswell.
Well in my code i fix that by keeping the x value and increasing it every time it reads a value and once it gets to the maximum tiles per row or whatever i reset it to 0 then increment the y value. Why dont you just do that ? :p
(obviously im not very good at explaining)
The thing was i couldent implement your "Loading maps code" into my own code and i dont want to like straight copy your code because i dont recognize anything there hehe, hmm i really have water above my head right now, this is extremly complicated i might need to change this code, because i followed some guys tutorial but i dont understand it so well, damn, i just want a nice working Mapload function
But mine is so much simpler than yours, albeit maybe a little bit more cryptic looking X)
Heres a deep explaination of my code
To keep track of all the tiles i just use a simple 2d array of ints
int tiles[40][30];
I then open up a file then keep looping until it is the end of the file, keeping track of how many values have been stored, once 40 values (the number of how many tiles per row) has been stored it must mean that its time to increase the y value because all the tiles in that row are filled up.
//openfile bla bla bla while (File >> temp) //loops until end { Tiles[x][y] = temp; x++; //next tile in the row if (x == TILES_PER_ROW /*40*/) //all the rows are filled up { x = 0; //reset it y++; //next column } }
Then, as ive already explained, i just make a bitmap out of the tiles then i just draw the bitmap as you would with any other bitmap.
Im not saying this is the best way to do this but its definately a good way to start off and get a feel of things.
Also i didnt compile this code, its only for example so if there are anything syntax errors thats why
Yeah, actully i borrowed your code and implemented in my code, it runs good but now it just creates a bitmap and only using the:
BitTile = al_create_bitmap(800, 600);
so it doesent matter what i do in my .txt document it takes like the first tile in my png file and just copys it to 800 x 600, here is a screenshot
do you know why it does that?
Emm im not sure, maybe bad input? I know when you give bad input it just keeps repeating the last good input. Also check the updateBitMap function and make sure its actually drawing the tile that the input corrisponds to.
Yeah this is extremly wierd can it have something to do with i changed your [40][30] to [100][100] because i want to make bigger maps?
anyway with some touching of the code i end up with this,
also there is the png file im using and also the update code, hmm
One of the ways I debug a problem like this is to actually do all the logic, step by step, in my head, following along in my code. You can either do this in a forwards motion to determine what the result should be, or a backwards motion to determine what you need to start with to get the result you want.
However, I just noticed something obvious: You're only going up by increments of 32 when pulling tile references, not 64 like your tile sizes are.
I also noticed that tile #0 is a brick wall. Usually it's best to make tile #0 your empty, undefined tile for sake of if statements.
I actully havent had any luck on the Working TileMap yet, its still doesent update as it should do, it only creates a wierd big Tile of 800, 600 because its set like that in the BitTile = al_create_bitmap(800, 600);
Its extremly wierd, i dont know what to do anymore ive been experimenting with my code changed alot of values, switching locations of the updates but still nothing, just does the same thing, if anyone with sharper eyes and knowledge could spot something out i would really appreciate it, been working with this for 2 days now withouth any luck, also when i have Screen scrolling on my Game my Mouse event doesent work either, it works fine if i stay in place in the beginning of the game but when i start to move it doesent update as it should so it just lacks behind all the time, here is my code if anyone have the time to just look over it a quickie!
When I get EXTREMELY stuck with a problem like this, I like to add keyboard-sensitive stepping in my code.
In your case, what this would mean is adding some routines to your tilemap rendering code so that it only draws one tile, shows the result on-screen, then waits for you to press a key. Then it draws the next tile, waits for a keypress, repeat until you press a specific key to signal the program to stop running.
This would at least let you visually see how your tiles are being rendered one by one and you may be able to tell what the trouble is as a result.
You don't need extra code to do that, just a debugger