9
\$\begingroup\$

I am using Direct3D with the D3DXSPRITE wrapper to draw the tiles to the screen. I have a tile class which contains members such as collision and tile type, then i have an array of tiles e.g.

Tile grid[256][256];

Which would be a better method?

-Draw the player in the center of the screen and offset where the map draws.

-Move the player with the camera following.

I was using the first method, but its getting really complicated when you get to the top left edge of the map, and when other players/enemies are on the map and moving at the same time

if i make the camera follow the player, would i have to call spriteBatch->Draw(...) for every single grid tile even though only a few can fit on the screen?

\$\endgroup\$

4 Answers 4

4
\$\begingroup\$

It's probably best to do all updates and calculations in "real", world units and move the camera. Your spriteBatch may perform culling itself but if it's too slow you can try to determine what tiles need to be displayed on screen and only draw those.

\$\endgroup\$
1
  • \$\begingroup\$ You probably are going to want to write code to only draw those sprites which are visible, especially if you find that you need to increase the size of your grid. \$\endgroup\$
    – CariElf
    May 16, 2011 at 21:46
2
\$\begingroup\$

Moving the camera in world coordinates and have your character move around the world is the easiest way to approach this problem, working in world coordinates means you dont need to do any extra calculations when it boils down to all the other systems which must work on a relative coordinates system and also understand where they are in world coordinates.

Since you are working in 2D another good tip is to do some spatial partitioning the easiest way would be to create a virtual world grid system, this will allow you to manage each tile individually by associating sprites and other resources on a per tile basis, so in essence the process would be:

  • create some tile class which can hold the boundary coordinates for the tile and whatever resources that specific tile may need ( sprites, enemies, etc.. ).

  • decide on the size of your world and create a 2D array ( you could use one dimension and access it as 2D ) of tiles each one representing a bit of your world with all of its associated resources.

  • only draw resources from the tile the player is in and its neighbours.

With a grid you can easily find out which tile the player is in based on it's position relative to the start of the grid.

To work around the problem you mentioned about the camera you need to make the player and the camera two independent systems where the camera wont travel any further than the centre of the edge tiles so when the player travels to that tile he can still travel throughout the entire tile as he is bound by world coordinates ( i.e. no longer centered on the screen ) but the camera is locked.

\$\endgroup\$
0
\$\begingroup\$

I use a surface. I create the entire world on an off screen surface and keep an x and y coordinate. I alter these as the player moves and each frame draw a 1028 x 768 rectangle from the surface to the backbuffer using x and y.

as for other people I give them an x and y and let them move around the world as they please, when drawing I check if there x and y is in the 1028 x 768 rectangle and if so draw them (I use textures for people).

I have the player in the centre of the screen and check if the edge of the world has reached the edge of the screen. In this circumstance the player moves about the screen to the edge of the world and back to the centre then the world starts moving again. it seems hard and took me a while but is not to bad to do.

I use 64 x 64 tiles and the biggest world I have used so far is 50 x 60 tiles.

This is all done in direct x with c++

\$\endgroup\$
6
  • 1
    \$\begingroup\$ This seems like a HUGE memory hog. Keeping the entire world drawn in a surface off-screen is going to run you into memory issues once you start wanting to do things like having multiple (animated) layers for your world and expanding it further than what you have now. It would be much better to keep the information about the world and only draw the parts/objects that need to be drawn when they need to be drawn. Just my 2 cents. :) \$\endgroup\$ May 17, 2011 at 14:14
  • \$\begingroup\$ @Drackir I think you misunderstand. only the world is drawn off screen, things like the other people are tracked and drawn on the backer buffer when they are needed. also I do not see myself doing more that 70 x 70 world. when I say world I mean area, this could be a town a dungeon or the inside of a house, when the player moves between them the off screen surface is reconstructed. yes it takes memory but 2d tiles on modern terrabite drives makes it negligible and a few seconds loading is a small price to pay for smooth scrolling and animation. but yes there are better and harder ways :) \$\endgroup\$
    – Skeith
    May 17, 2011 at 14:50
  • \$\begingroup\$ The surface should be stored in the GFX card memory, not on the hard drive. However, I believe if the GFX card memory is too large, it will move the surfaces onto the HD which would considerably slow things down. Admittedly, it's been a while since I've dealt with that stuff so I don't remember exactly how it worked, but I guess as long as you're not drawing too big of a world it would be ok. :) \$\endgroup\$ May 17, 2011 at 15:00
  • \$\begingroup\$ @Drackir That is interesting to know, I never thought of it like that. I found that this way gives me a smoother scroll that if I dynamically drew new tiles so I think it fits ok but I will have to look into that. \$\endgroup\$
    – Skeith
    May 17, 2011 at 15:45
  • \$\begingroup\$ I was working on a game where I had maps 31x31 but they were attached together side-by-side. I was trying working from someone else's engine and they would draw all the maps surrounding the one the player was on; so nine maps in total. Each map had several (I think 6) layers. So like 31x31x9x6 = 51894 tiles being drawn (max of course; not all tiles were full) every time the user switches maps. That was a huge slow-down for me, so I rewrote the drawing routine to only draw the tiles surrounding the player as far as 1 tile past the edge of the screen (to handle partial tiles while moving). \$\endgroup\$ May 17, 2011 at 16:06
0
\$\begingroup\$

It's quite normal for the code to get a bit of a pain in the corners of a tiled world, when working out which tiels to draw, and simultaneously ensuring the camera doesn't go 'off-world'. Those edge cases are basically the most compelx thing about implementing a 2D tile-based world thats larger than the screen res. It gets much more complex if you support zooming in, and zoom-to-cursor :D

\$\endgroup\$

You must log in to answer this question.