Skip to main content
GameDev.net gamedev.net
🔒 Locked

Tile Based - "Correct way"

Started by NickyP101 Mar 9, 2005 at 4:08 AM 12 replies 2k views
Original Post
NickyP101
NickyP101
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
Foot Soldier
Foot Soldier
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.
Sure is a big 'ol world.
NickyP101
NickyP101
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.
ghosted
ghosted
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 sideplayer_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/overplayer_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.
NickyP101
NickyP101
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?
NickyP101
NickyP101
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?
ghosted
ghosted
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.
lightfoot256
lightfoot256

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
MasterWorks
MasterWorks
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.
Muzlack
Muzlack
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.
--Muzlack
NickyP101
NickyP101
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?
kburkhart84
kburkhart84
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.


NickyP101
NickyP101
Ok i think i get wat u mean :) Is this correct:

bullet x = 500bullet y = 500bullet x array value = x / width of x tilesbullet 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?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.