Sign in to follow this  
Mythios

Problems with 2D Tile Engine C++ SDL

Recommended Posts

Hey guys, I'm currently having a lot of problems with a tile tutorial. I've been trying to split it up into separate files - the tutorial was obtained from "http://lazyfoo.net/SDL_tutorials/lesson29/index.php". I got it compiling fine but the display is far from right. I can scroll around on mine but the dot will vanish once i move off the first tile. So I'd take it the problem is that my setup for displaying the tile map is incorrect. Here's a small snippet of code I'm using for it. main.cpp
//Show the tiles
for( int t = 0; t < TOTAL_TILES; t++ )
{
		tiles[t]->show(&camera, screen, tileSheet, clips);		
}

tile_class.cpp
void Tile::show(SDL_Rect *pCamera, SDL_Surface *pScreen, SDL_Surface *pTileSheet, SDL_Rect pClips[])
{
    if( check_collision(pCamera, &box) == true )
    {
		SDL_Rect offset;
    
		//Get offsets
		offset.x = box.x - pCamera->x;
		offset.y = box.y - pCamera->y;

		SDL_BlitSurface(pTileSheet, pClips, pScreen, &offset );
    }
}

As you can see it's not actually taking in a value for what tile to display. But even so I'm not sure how to setup the display as I'm pulling stuff from other files. I'm using VS 2005 with SDL and SDL Image - the full source code, images and map I've uploaded here "http://www.mediafire.com/?sharekey=3ce971b5802be32cd2db6fb9a8902bda" if anyone is willing to take a look at how i've gone wrong. I setup VS 2005 how Lazy Foo's first tutorial is setup. Any help would be a big thanks. I been working on this for a while now and on other forums but so far I'm not getting much luck. Thanks for your time, Scott.

Share this post


Link to post
Share on other sites
Quote:
I'd take it the problem is that my setup for displaying the tile map is incorrect.

Actually, the tile map works fine. It's displaying the dot that's the 'gotcha!'

You're using the box's position as an argument to the source rect of the surface to blit:

SDL_BlitSurface(pDot, &box, pScreen, &offset );

So, the further the user scrolls on the tile map, less and less of the dot is drawn! In fact, just 20 pixels' scroll and the dot becomes invisible.

The second argument to this function is used to adjust which specific portion of pDot is drawn. Since you want to blit the whole surface, just pass in a NULL for this argument.

Share this post


Link to post
Share on other sites
EDIT: Well thanks to you now i can make the dot scroll around like mad haha. Thank you. Now hopefully i'll find an answer to my other problem :D

Awesome thank you, i see that problem there and i'll try to fix it up now. Only other problem is now getting it to display the different tiles - as i can only load 1 tile type into it :(

Share this post


Link to post
Share on other sites
This one is a case of the evil array.

Here's what you've got now:

void Tile::show(SDL_Rect *pCamera, SDL_Surface *pScreen, SDL_Surface *pTileSheet, SDL_Rect pClips[])
{
if( check_collision(pCamera, &box) == true )
{
SDL_Rect offset;

//Get offsets
offset.x = box.x - pCamera->x;
offset.y = box.y - pCamera->y;

SDL_BlitSurface(pTileSheet, pClips, pScreen, &offset );
}
}

pClips is an array of SDL_Rects. When you pass in pClips, the base pointer of the array, you get the first element. That first element happens to be a green tile in your case. Every tile, no matter its type, will show up as a green tile. We need to get to the appropriate place in the array, and then take a pointer to THAT element::

SDL_BlitSurface(pTileSheet, pClips, &pScreen[type], &offset );



Share this post


Link to post
Share on other sites
EDIT: I just relised where the other tiles are meant to be - apart from grass is all black. Can't believe i didn't register that. I think i just got to excited to not see all grass haha. Well yeah where the other tiles are meant to be its all black and as soon as the screen/camera moves they turn into retarded grass. If the player crosses over them it leaves a trail of the player

Haha "Evil Array" Damn your good though - this is working now except when i scroll - once the tiles start to scroll they start to like blend and blurr and cross over and stuff - you know goes all retarded on me lol.

Thanks so much for getting me this far though. Been a big help :D

Share this post


Link to post
Share on other sites
I'm not sure what the problem is this time. It works fine on my computer with those minor changes. Can you describe it in more detail, or if you've changed the drawing code, or provide a screenshot? ;)

Share this post


Link to post
Share on other sites
This is a dirty backbuffer. I didn't notice it because on my system those black areas are orange sandy looking tiles.

What's happening is that you draw a frame, display it, and then use the same surface as before to draw the next frame. If there are areas you don't fill in completely (which in your case is the black tile-less areas) then the second frame can show through. Then you scroll a little more and the third frame draws, has some places that aren't filled in which now shows parts of the second frame which might show parts of the first frame, and so on.

The easiest solution is simply to clear the backbuffer of any data the previous frame had and start fresh. You can do this using SDL_FillRect:

SDL_FillRect(screen, NULL, 0); // surface, dest rect, color

This will fill the surface with a specified color (black, in this case). Put that line just before you begin drawing the frame and the backbuffer will start out solid black and you won't see other frames bleeding through.

Share this post


Link to post
Share on other sites
Ok that fixes it so no tiles blend with each other now - but for me they are still black? It's not showing up the other tiles from the tile sheet :( - So it looks like the previous picture but they are black with no blending.

I set it up like this which I think is correct

SDL_FillRect(screen, NULL, 0);
//Show the tiles
for( int t = 0; t < TOTAL_TILES; t++ )
{
tiles[t]->show(&camera, screen, tileSheet, clips);
}




Well apart from that i know that its saying that they are different tiles as i turned back on my tile collision

bool touches_wall(SDL_Rect *pBox, Tile *tiles[])
{
//Go through the tiles
for( int t = 0; t < iTOTAL_TILES; t++ )
{
//If the tile is a wall type tile
if( ( tiles[t]->get_type() >= iTILE_CENTER ) && ( tiles[ t ]->get_type() <= iTILE_TOPLEFT ) )
{
//If the collision box touches the wall tile
if( (check_collision(pBox, &tiles[t]->get_box() ) == true ) ) // if(check_collision(pBox, tiles[t]->get_box() == true ))
{
return true;
}
}
}

//If no wall tiles were touched
return false;
}



With the adjustment of adding an ampersand to tiles[t]->get_box() which i forgot to before oops. So at the least this proves those tiles are there. They are just not loading up the graphics from the tile sheet for them

Share this post


Link to post
Share on other sites
Everything works as expected on my end. I haven't had the black tile problem (in fact, I had to fake it to get the dirty buffer problem you had) and the tiles have been appearing normally for me ever since the array pointer problem was fixed.

Put a breakpoint on the Tile::show function and find out what values it's reporting for offset and pClips[type]. If I had to guess, I'd say it's a problem there.

Share this post


Link to post
Share on other sites
http://i210.photobucket.com/albums/bb317/mythios1/myGamedebug.jpg

Personally I'm a little lost in what I'm meant to be looking for exactly with debug at the moment. What program are you using to run this project in and such. Do you have it loading any different dll's in the code generation? If it's not to much trouble do you think it would be possible to send me your project and load that up to see if it comes out any different?

Thanks a heap for your help mate - I'm learning stuff slowly but it's giving me a lot better understanding :D

email: mythios1@optusnet.com.au

Cheers mate

Share this post


Link to post
Share on other sites
I'm using exactly the same as you, VS2005 (express edition). It has to be some difference between our computers or compilers because I downloaded your exact project, re-fixed the few problems and ran it with the same results -- everything is peachy.

Go to the Tile::show() function, click on the first line in the function and press F9 to set a breakpoint there. Then press F5 to run the program and it will run until that breakpoint, where it will pause.

In the debug pane (it's on the bottom left for me, possibly different location for you), click on the tab you want (in this case locals, to see local-scope variables) to see a list of variables and their current values. Use the step-in/step-over/step-out functions (F10, F11, and shift+F10 respectively) to move through the code line by line, keeping an eye on values and looking for oddities. There's a lot of commands and useful things you can do in this way, and the more you experiment and test, the more you can get out of it.

Note: You can mouse-over variables to see a small popup with their current value.

[edit] I see you've already got some understanding of it. pClips as it is isn't particularly useful to debug since C++ views it as a simple pointer. Add a new temporary variable so you can see the src rect for each tile:

SDL_Rect srcRect(pClips[type]);

SDL_BlitSurface(pTileSheet, &srcRect, pScreen, &offset );

Now find a tile that shows up black. I assume type == 0 is the green tile you have no problem seeing, so I'd add something like

if (type != 0) {
int dummy = 5;
}

Then set a breakpoint on the int and go from there. You'll be interested mostly in the value of srcRect and whether it's a valid coordinate or not. If it isn't, then you've probably found the problem. If it is, then this part is working fine and the problem lies elsewhere.

Share this post


Link to post
Share on other sites
Well my VS 2005 is set up how lazy foo's setup guide is. Now one way we might be able to test this problem would be. The code of mine your using can you build it as a release? As i can't the runtime dll in the code generation is ruining that for me i think. Mines set to the dll lazy foo had used in his tutorial 01. Ill be back soon sorry just heading out for a bit :D

Share this post


Link to post
Share on other sites
What do you mean, the runtime DLL? I looked over his directions and there's nothing there that would prevent you from compiling in release mode.

[edit]I just tried, compiling in release works fine for me.

Share this post


Link to post
Share on other sites
Ok - now I'm confused heh. WIth me using your

SDL_Rect srcRect(pClips[type]);

SDL_BlitSurface(pTileSheet, &srcRect, pScreen, &offset );

Everything displays how it should now - whats the difference with doing this?

[EDIT]

Below are the errors i get if i compile as a release which confuses me?

I get one of these for every file pretty much
1>Compiling...
1>tile_class.cpp
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(590) : warning C4312: 'type cast' : conversion from 'uintptr_t' to 'void *' of greater size


And then this after all of that :(
1>Linking...
1>main.obj : error LNK2001: unresolved external symbol _SDL_Flip
1>main.obj : error LNK2001: unresolved external symbol _SDL_WM_SetCaption
1>main.obj : error LNK2001: unresolved external symbol _SDL_Init
1>main.obj : error LNK2001: unresolved external symbol _SDL_FillRect
1>main.obj : error LNK2001: unresolved external symbol _SDL_PollEvent
1>main.obj : error LNK2001: unresolved external symbol _SDL_SetVideoMode
1>main.obj : error LNK2001: unresolved external symbol _SDL_Quit
1>main.obj : error LNK2001: unresolved external symbol _SDL_FreeSurface
1>main.obj : error LNK2001: unresolved external symbol _SDL_Delay
1>graphix.obj : error LNK2001: unresolved external symbol _IMG_Load
1>graphix.obj : error LNK2001: unresolved external symbol _SDL_SetColorKey
1>graphix.obj : error LNK2001: unresolved external symbol _SDL_MapRGB
1>graphix.obj : error LNK2001: unresolved external symbol _SDL_DisplayFormat
1>dot_class.obj : error LNK2001: unresolved external symbol _SDL_UpperBlit
1>timer_class.obj : error LNK2001: unresolved external symbol _SDL_GetTicks
1>MSVCRT.lib(crtexe.obj) : error LNK2001: unresolved external symbol _main
1>C:\Documents and Settings\Scottie\My Documents\Visual Studio 2005\Projects\SDL_FIRST_RUN My Game -Using Tiling Engine\Release\SDL_FIRST_RUN.exe : fatal error LNK1120: 16 unresolved externals
1>Build log was saved at "file://c:\Documents and Settings\Scottie\My Documents\Visual Studio 2005\Projects\SDL_FIRST_RUN My Game -Using Tiling Engine\SDL_FIRST_RUN\Release\BuildLog.htm"
1>SDL_FIRST_RUN - 17 error(s), 8 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Share this post


Link to post
Share on other sites
There shouldn't be any difference, at least there isn't with my compiler.

Quote:

Heh i'll past the errors soon, when i build in release i get a heap of linker errors, yet debug compiles fine hmmm

Did you set the release configuration too? Right-click on your project in the solution explorer and select properties. In the upper-left hand of that screen, there's a drop-down box which says Active(Debug) if you're in debug and Active(Release) if you're in release. They're separate settings, so you'll need to set up both.

Share this post


Link to post
Share on other sites
[EDIT] Fixed now haha - forgot to add the .map file. Oh i'm such a looser :D

Sorry for this long post, Build Succeeds now - i forgot to added the additional libraries lol. other than that i get these:

But i'd gather these are fine?

It only puts the .exe in the release folder though - so i manually added the required .dll files which i know i have to. Only now my question is - i put the 2 .png files in there with it but when i load it up - it brings up a console quickly and then just closes?


1>------ Rebuild All started: Project: SDL_FIRST_RUN, Configuration: Release Win32 ------
1>Deleting intermediate and output files for project 'SDL_FIRST_RUN', configuration 'Release|Win32'
1>Compiling...
1>timer_class.cpp
1>tile_class.cpp
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(590) : warning C4312: 'type cast' : conversion from 'uintptr_t' to 'void *' of greater size
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(566) : while compiling class template member function 'std::istreambuf_iterator<_Elem,_Traits> std::num_get<_Elem,_InIt>::do_get(_InIt,_InIt,std::ios_base &,std::ios_base::iostate &,void *&) const'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _InIt=std::istreambuf_iterator<char,std::char_traits<char>>
1> ]
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(1367) : see reference to class template instantiation 'std::num_get<_Elem,_InIt>' being compiled
1> with
1> [
1> _Elem=char,
1> _InIt=std::istreambuf_iterator<char,std::char_traits<char>>
1> ]
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(590) : warning C4312: 'type cast' : conversion from 'uintptr_t' to 'void *' of greater size
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(566) : while compiling class template member function 'std::istreambuf_iterator<_Elem,_Traits> std::num_get<_Elem,_InIt>::do_get(_InIt,_InIt,std::ios_base &,std::ios_base::iostate &,void *&) const'
1> with
1> [
1> _Elem=wchar_t,
1> _Traits=std::char_traits<wchar_t>,
1> _InIt=std::istreambuf_iterator<wchar_t,std::char_traits<wchar_t>>
1> ]
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(1373) : see reference to class template instantiation 'std::num_get<_Elem,_InIt>' being compiled
1> with
1> [
1> _Elem=wchar_t,
1> _InIt=std::istreambuf_iterator<wchar_t,std::char_traits<wchar_t>>
1> ]
1>dot_class.cpp
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(590) : warning C4312: 'type cast' : conversion from 'uintptr_t' to 'void *' of greater size
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(566) : while compiling class template member function 'std::istreambuf_iterator<_Elem,_Traits> std::num_get<_Elem,_InIt>::do_get(_InIt,_InIt,std::ios_base &,std::ios_base::iostate &,void *&) const'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _InIt=std::istreambuf_iterator<char,std::char_traits<char>>
1> ]
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(1367) : see reference to class template instantiation 'std::num_get<_Elem,_InIt>' being compiled
1> with
1> [
1> _Elem=char,
1> _InIt=std::istreambuf_iterator<char,std::char_traits<char>>
1> ]
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(590) : warning C4312: 'type cast' : conversion from 'uintptr_t' to 'void *' of greater size
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(566) : while compiling class template member function 'std::istreambuf_iterator<_Elem,_Traits> std::num_get<_Elem,_InIt>::do_get(_InIt,_InIt,std::ios_base &,std::ios_base::iostate &,void *&) const'
1> with
1> [
1> _Elem=wchar_t,
1> _Traits=std::char_traits<wchar_t>,
1> _InIt=std::istreambuf_iterator<wchar_t,std::char_traits<wchar_t>>
1> ]
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(1373) : see reference to class template instantiation 'std::num_get<_Elem,_InIt>' being compiled
1> with
1> [
1> _Elem=wchar_t,
1> _InIt=std::istreambuf_iterator<wchar_t,std::char_traits<wchar_t>>
1> ]
1>graphix.cpp
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(590) : warning C4312: 'type cast' : conversion from 'uintptr_t' to 'void *' of greater size
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(566) : while compiling class template member function 'std::istreambuf_iterator<_Elem,_Traits> std::num_get<_Elem,_InIt>::do_get(_InIt,_InIt,std::ios_base &,std::ios_base::iostate &,void *&) const'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _InIt=std::istreambuf_iterator<char,std::char_traits<char>>
1> ]
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(1367) : see reference to class template instantiation 'std::num_get<_Elem,_InIt>' being compiled
1> with
1> [
1> _Elem=char,
1> _InIt=std::istreambuf_iterator<char,std::char_traits<char>>
1> ]
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(590) : warning C4312: 'type cast' : conversion from 'uintptr_t' to 'void *' of greater size
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(566) : while compiling class template member function 'std::istreambuf_iterator<_Elem,_Traits> std::num_get<_Elem,_InIt>::do_get(_InIt,_InIt,std::ios_base &,std::ios_base::iostate &,void *&) const'
1> with
1> [
1> _Elem=wchar_t,
1> _Traits=std::char_traits<wchar_t>,
1> _InIt=std::istreambuf_iterator<wchar_t,std::char_traits<wchar_t>>
1> ]
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(1373) : see reference to class template instantiation 'std::num_get<_Elem,_InIt>' being compiled
1> with
1> [
1> _Elem=wchar_t,
1> _InIt=std::istreambuf_iterator<wchar_t,std::char_traits<wchar_t>>
1> ]
1>collision.cpp
1>main.cpp
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(590) : warning C4312: 'type cast' : conversion from 'uintptr_t' to 'void *' of greater size
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(566) : while compiling class template member function 'std::istreambuf_iterator<_Elem,_Traits> std::num_get<_Elem,_InIt>::do_get(_InIt,_InIt,std::ios_base &,std::ios_base::iostate &,void *&) const'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>,
1> _InIt=std::istreambuf_iterator<char,std::char_traits<char>>
1> ]
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(1367) : see reference to class template instantiation 'std::num_get<_Elem,_InIt>' being compiled
1> with
1> [
1> _Elem=char,
1> _InIt=std::istreambuf_iterator<char,std::char_traits<char>>
1> ]
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(590) : warning C4312: 'type cast' : conversion from 'uintptr_t' to 'void *' of greater size
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(566) : while compiling class template member function 'std::istreambuf_iterator<_Elem,_Traits> std::num_get<_Elem,_InIt>::do_get(_InIt,_InIt,std::ios_base &,std::ios_base::iostate &,void *&) const'
1> with
1> [
1> _Elem=wchar_t,
1> _Traits=std::char_traits<wchar_t>,
1> _InIt=std::istreambuf_iterator<wchar_t,std::char_traits<wchar_t>>
1> ]
1> C:\Program Files\Microsoft Visual Studio 8\VC\include\xlocnum(1373) : see reference to class template instantiation 'std::num_get<_Elem,_InIt>' being compiled
1> with
1> [
1> _Elem=wchar_t,
1> _InIt=std::istreambuf_iterator<wchar_t,std::char_traits<wchar_t>>
1> ]
1>Linking...
1>Generating code
1>Finished generating code
1>Embedding manifest...
1>Build log was saved at "file://c:\Documents and Settings\Scottie\My Documents\Visual Studio 2005\Projects\SDL_FIRST_RUN My Game -Using Tiling Engine\SDL_FIRST_RUN\Release\BuildLog.htm"
1>SDL_FIRST_RUN - 0 error(s), 8 warning(s)
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

Share this post


Link to post
Share on other sites
Those are 64 bit compatibility warnings. You can disable them by setting "Detect 64-bit Portability issues" to "No" in the C/C++ -> General portion of your project properties.
Quote:
i put the 2 .png files in there with it but when i load it up - it brings up a console quickly and then just closes?

Are you running the release EXE from within the VS environment? If you are, then the root directory is the same as the project directory.

MyProject\Release\MyProgram.exe

Running from within VS = put those files in MyProject
Running from outside VS = same as MyProgram.exe's directory

Share this post


Link to post
Share on other sites
Mate thank you so much for all your time and effort you have put into helping me here. It's really helped a heck of a lot for me. So seriously thank you heaps! Only other question now is - i know the code is very messy. So i was wondering if you could guide me which of the functions that are in the main i would probably able to move into the tile class. Mainly so I can neaten it up and actually have a tile engine sort of thing i can use for games i create :)

Thanks a heap man!

Share this post


Link to post
Share on other sites
Learn to use and love vectors. They're all around better than arrays in my book.

As for cleaning up your code, it's a matter of preference. I like everything wrapped up neatly in objects with as little internal information exposed as possible. You could do the same, and write a Tilemap (as opposed to your current tile class) class that takes string arguments for the tile sheet and the map, and the work of loading the sheet and map with the tile offsets is neatly tucked away.

Share this post


Link to post
Share on other sites
I kind of get what you mean but a lot of that goes over my head still lol. Mainly as this is my first time using SDL as well so getting use to a lot of it and stuff. I also need to get better at using vectors and iterating through them and what not as i never use them much. I've always stuck with arrays but that's probably a bad idea.

Cheers

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this