[java] 2D scrolling map problem

Started by
3 comments, last by Alrecenk 17 years, 9 months ago
I'm making a 2D game with a tilemap. Before I splitted my map into different mapareas and everytime you change to a different maparea it needed to be loaded again into a variable. Then I draw the visible part to the screen. One maparea is a bufferedimage of 2000*2000. The size of my tiles is 32*32. Now I want to make one big map. Without the loading screens in between. But I don't know where to start. First I thought of making my mapareas smaller and always store the current mapareaimage with 8 mapareasimages around and than draw only the needed part to the screen. But this will take to much memory I think. I also tried to render the needed images to a BufferedImage and than draw it to the screen but this didn't worked either. My framerates drops from more than 300 to 100. Drawing the tiles directly to the screen makes the screen flicker a bit. If anyone can put my on the right track or give me a good solution I would be very thankful.
Advertisement
Hi.

This a typical question. To give an optimal suggestion, I first need to know how your game works. Does the map scroll consistently? (like a side-scroller with a constant angle and a constant pace?) or does your map move inconsisently (like in a map that scrolls based on user input, variation in speed etc).

There are multiple viable solutions. I usually prefer a tile-based approach. Not because it necessarily is better performance wise, but because it offers greater flexibility. Lets say some object explodes (what can I say, I am a fan of explosions), - perhaps you want to get inventive and add some crater-like graphics to your background. In such a case, it would be better to have a 32*32 tile overlay to make the crater than most other things.

If you want a simple background that scrolls (and possibly loops), like a side-scroller, the choice is much up to you, - the big image works as well. But if you need to think about hardware accelleration, a 2000*2000 image might be too huge to be accellerated. If you use tiles, at least *some* of the tiles will be accellerated.

There are so many cases here, I'll just refer you to this link:
http://fivedots.coe.psu.ac.th/~ad/jg/ch062/index.html
(the pdf)

The chapter handles background scrolling, paralax scrolling, and tile-maps. It might give you some ideas.

Good luck ;)
Development blog, The Omega Sector -- http://www.omegasector.org
Thanks for you reply.

I've read through the whole book of "killer game programming in java" but
that doesn't solve my problem. Or maybe I missed something...

But it's not a side-scrolling game. Everything is based on the
users input.

This is how my game looked before.


The mapareas are stored in a two dimension array like this.
(X is the current maparea where the user is.)

0 0 0 0
0 X 0 0
0 0 0 0

Now I need a smooth change between two or more mapareas without a loading. Cause it is possible that you have parts of 4 mapareas on the screen at the same time,I can't use bufferedImages for all of them like I did before. It uses
way to much memory.
I used the tile-system like the next simplified code but that gave me a drop
down of my framerate. But I'll first try to render it directly to the screen.
I use double buffering.

	private void drawMap(Graphics g){		BufferedImage bimage = new BufferedImage(ge.screen.getPWidth(), ge.screen.getPWidth(), BufferedImage.TYPE_INT_RGB);	    Graphics2D g2d = bimage.createGraphics();				int aantalx = ge.screen.getPWidth()/32 +1;		int aantaly = ge.screen.getPHeight()/32 + 2;				for(int j=0;j<aantaly;j++){			for(int i=0;i<aantalx-5;i++){				g2d.drawImage(image,i*32,j*32,32,32,null);			}			for(int i=aantalx-5;i<aantalx;i++){				g2d.drawImage(image1,i*32,j*32,32,32,null);			}		}		g2d.dispose();				g.drawImage(bimage,startx,starty,ge.screen.getPWidth(),ge.screen.getPHeight(),null);			}


Hi.

The chapter describes how to seamlessly implement a looping background image. You can apply the same technique to seamlessly sow different background images together :)
Development blog, The Omega Sector -- http://www.omegasector.org
I would recommend you store your images as tiles since you don't appear to have any multiple tile objects. Then have an area be a 2D array of object references.
Image images[] = (your images) ;int area[][] = new int[20][20] ;int areax, areay, tilesize ;for(a=0;a<20;a++){for(b=0;b<20;b++){g.drawimage(images[area[a]],areax+tilesize*a,areay+tilesize*b,this) ;}}


Not having the same image data drawn over and over should allow you to use less memory and thus load more areas at once without memory problems. Perhaps I am misunderstanding, but I do not see why you would be having memory issues...




Also, on a hopefully less useless note, if you want your game to keep running while you load or initialize large levels then you may want to do so in a seperate thread. The runnable interface is quite easy to use.

I have some code for loading a similar area based game, maybe this will be useful.
region area[]= new double[4] ;//0 =upper left, 1 = upper right, 2 = lower left, 3= lower right .....int nx = (int)(x+0.5) ;//use actual x and y to determine the nearest area pointint ny = (int)(y+0.5) ;	  	//reloads a portion of the level if necessaryyif(nx!=pnx){//if closest point moved in the x axisif(pnx<nx){// if moved rightarea[0] = area[1] ;area[2] = area[3] ;area[1] = getarea(nx,ny-1) ;area[3] = getarea(nx,ny) ;pnx = nx ;}if(pnx>nx){// if moved leftarea[1] = area[0] ;area[3] = area[2] ;area[0] = getarea(nx-1,ny-1) ;area[2] = getarea(nx-1,ny) ;pnx = nx ;}}	  	if(ny!=pny){//if closest point moved in the y axis	if(pny<ny){// if moved down	  area[0] = area[2] ;	  area[1] = area[3] ;	  area[2] = getarea(nx-1,ny) ;	  area[3] = getarea(nx,ny) ;	  pny = ny ;	 }	 if(pny>ny){// if moved up	  area[2] = area[0] ;	  area[3] = area[1] ;	  area[0] = getarea(nx-1,ny-1) ;	  area[1] = getarea(nx,ny-1) ;	  pny = ny ;	  }}

It loads four areas at once (they will need to be fairly large so that you rarely see multiples at once I use 10000*10000) . It loads the four closest areas to the current location(x,y). To use this wit your x and y measured in pixels just divide the x and y by the area size prior to this.

[Edited by - Alrecenk on July 21, 2006 2:54:47 AM]

This topic is closed to new replies.

Advertisement