Sign in to follow this  

Tile Based - "Correct way"

This topic is 4662 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Im making a top down view 2d tile game, i draw the entire map image to a buffered image, now when the user uses the arrow keys i simply redraw the map croping it differently. Is this the correct way of doing this is a game? I dont have any experience in game programming and i cant see into the future and see problems i might have atm. Is it ok doing wat i am currently doing, or to make things easier in the long run should i change my method to another method lyk: Giving the player a position in the map array, then redrawing the entire map and player to the buffered image and showing that. Cheers, Nick

Share this post


Link to post
Share on other sites
I don't see any problems with your way, as long as you divide a large map into chunks. Then, just don't let the, "camera" go past them and when the player goes off screen, load the new map.

Share this post


Link to post
Share on other sites
The way im currently doing it the player never actually leaves the middle of the screen, is that ok?

And also the reason i was asking the first question is because ive started thinking about collision detection, and im just wondering if the way i do it will work still? its much easier putting the user in the 2d array for the map, then u can see if they are going to walk into lyk a wall of sumtin.

Share this post


Link to post
Share on other sites
Ok, couple of points. Firstly, I'm not sure you want to be drawing the entire map as that almost defeats the purpose of using a tile-based system. The idea being that the map is broken down into managable chunks so you only need to be checking and drawing those around immediately around you (within the camera view). Bare in mind, if you know your camera location and you know how many tiles fit on the screen you can determine which tiles you should be drawing at any frame.

Secondly, you'd never need the player inside your array of tiles. When it comes to collision detection you will want to query individual tiles but that can be done without physically placing a player in with them. So let's say you wanted a collision check for the left side of your player (assuming this is a top-down view - the theory still applies to side-on though)

1. Determine the world coordinates of the players left side. This would probably be

// determine world position of players left side
player_location_x - player_width/2




Obviously your variable names will be different.

2. Determine which tile that point is inside.

// determine which tile players left edge is inside/over
player_leftside/tile_width
// take note: that would only determine which collumn the left side is in.
// you'd need another check with the player center to detemrine the y value





3. Act appropriately. If the tile is solid, push them back to a point where they are no longer colliding.


As for the player never leaving the center of the screen that isn't a problem. Given time you could add some smoothing to the camera but for now just keep it functional. Hopefully your camera is contained within a class so you can easily update it's behaviour without too much hassle.


Anyway, that's the basic gist of the process so I hope it helps.

Share this post


Link to post
Share on other sites
The reason i and drawing the map the way i am is because i only need to draw the 2d array to the buffered image once (at program start), from then on i just draw a crop of that image to the bufferedStratergy. Is this still incorrect or not as efficient?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If this is DirectDraw7 or GDI then prepare for counter-intuition.

Blitting one screensized subrectangle from a very large surface (many times the screen size) is usualy a lot slower than blitting many smaller rectangles stored in seperate small surfaces.

The idea here is that the very large surface cannot be (or is not in the case of GDI) stored in video memory yet the driver is designed to let the hardware perform all actions involved in the blit. Thus the entire large surface is shuttled through the agp/pci bus every time you blit even though you only wish to blit a small portion of it.

Tiles are your friend even when your map cannot re-use tiles.

Share this post


Link to post
Share on other sites
Ok, well the main reason im drawing the complete map to buffered image then drawing a crop of that is because i think it is the easiest way to draw my bullets, it draws them to the map so that if i move it still goes to that position on the map, not that position on the screen? I draw a bullet to the map at the user x + cropX and y + crop Y, and it destination is x + cropX and y + cropY.

You get wat im saying?

EG:

FULL MAP


|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
||....................C......................................................||
||....................C......................................................||
||............1....0..C....................0.................................||
||....................C......................................................||
||....................C......................................................||
||C.C.C.C.C.C.C.C.C.C.C..........................0...........................||
||...........................................................................||
||...........................................................................||
||...........................................................................||
||...........................................................................||
||...........................................................................||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

. Is grass
1 is the player
0 is a bullet
C is the cropped image

All bulets have been shot from the current pos of the player.
The are drawn to the entire map, only the crop is shown, this is the simplest way i could think of.

Any better way?

Share this post


Link to post
Share on other sites
Yeah, I get ya and to be quite honest it is probably rather inneficient to crop such a large image each frame. Although you have only 'drawn' it the once, as the AP points out, the clipping process is not going to be too efficient (irrespective of the API). It will be trimming down a large amount of image data which is not adviseable. Furthermore, if you wanted a larger map, that would mean a larger initial image which would further slow the cropping process.

What I would suggest is a system that only draws the tiles currently in the view of the camera. This will mean a loop of drawing a couple of dozen tiles each frame but that will actually be faster, and more flexible too.

Share this post


Link to post
Share on other sites

Any objects (i.e. bullets are renderd after the tile's have been drawn, you draw them at theur current position _minus_ the camera coordinates. This allows the objects to scroll around the screen as well as the map.

I dont like the idea of cropping a huge image. I've seen a guy do both techniques (clipping and tile-based rendering) and the clipping one runs slower generally and takes longer to load (loading/rendering a huge image takes longer than loading a couple of tiles), so all round is just slow. Stay clear of it and do a nice tile rendering loop.

Keeping the player in the middle of the screen... uhmm... the player should be able to move anywhere, i think it works out better if the player has coordinates relative to the map, then the camera is positioned in such a way that it always appears that the player is in the middle of the screen... Maybe its just the way of how i think objects exist, but i think object collsion etc will be easy as you wont have to keep adding camera coords to the player's position every time you wanna compare it agains another object in the level...

I'd check out tutorials on 2d-tile-based-rendering techniques, google it.
You should pick it up in no time!

Chris

Share this post


Link to post
Share on other sites
I agree that this is a very poor way to do this. The only time this would be a good idea was if the map was very small (only a couple screens) and you're doing multiplayer-split-screen or something. Start each frame from a blank slate and draw everything on the screen, blit, and repeat.

Share this post


Link to post
Share on other sites
How you can (or should) do it is for each layer to have a surface of it's own.

This surface would be the current viewable area. So, if your engine was 320x240, and you had 20 tiles x 15 tiles, it would draw all of those for each layer onto a seperate surface.

Then, each frame, you draw the layers on the screen in order. This way, you aren't drawing every tile every single frame, it's only when the viewport changes or the tiles are animating.

I'm not sure, but I think this is much more efficient than drawing the tiles each frame. And it's definately more effecient than drawing the entire map on load.

Share this post


Link to post
Share on other sites
Yeah i initially started only drawing the tiles needed, tahts just the way i learnt, but then i couldnt igure out how to draw the bullets to the position on the map they were heading for, not the position on the screen, so i would draw them to the entire map lol so yeah ive picked up that this is a bad design, so using the tile rendering process, how can i make it so when i shoot a bullet (bullets travell very slow atm (intentionally) at an object and move it still shoots to that object not the position on the screen?

Share this post


Link to post
Share on other sites
Keep the bullets position in variables according to the array position of the tilesk, then when drawing, clip it like the tiles, only draw the tiles needed and if the bullet is over one of these tiles, draw it after drawing the tile.

Share this post


Link to post
Share on other sites
Ok i think i get wat u mean :) Is this correct:



bullet x = 500
bullet y = 500

bullet x array value = x / width of x tiles
bullet y array value = y/ height of y tiles

for(int x = 0; x < 34; x++){

for(int y = 0; y < 32; y++){

if(map[x][y] == 0){

g2D.drawImage(grass, y * 50, x * 50, null);

}

if(map[x][y] == 1){

g2D.drawImage(rock, y * 50, x * 50, null);

}

if(map[x][y] == 2){

g2D.drawImage(rock, y * 50, x * 50, null);

}

if(map[x][y] == 4){

g2D.drawImage(water, y * 50, x * 50, null);

}


}
}


it = reference.bullets.iterator();
while(it.hasNext()){

temp = (Bullet)it.next();
if(temp.bullet x array value is in the domain of the tiles just painted && temp.bullet y array value is in the range of the tiles just painted){
g2D.drawOval((int)temp.bx, (int)temp.by, 10,
10);
}


v++;

}





Is this close to wat i would have todo? or hve i misunderstood horribly?

Share this post


Link to post
Share on other sites

This topic is 4662 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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