Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (539)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (603)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 [2] 3
  ignore  |  Print  
  Efficient game maps and Scrolling  (Read 3293 times)
0 Members and 1 Guest are viewing this topic.
Offline Rayvolution

« JGO Spiffy Duke »


Medals: 256
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #30 - Posted 2014-06-17 03:09:36 »

taking into consideration all the code posted here, I would suggest doing something like I did to setup your tile engine:

Here's how my system works (generally speaking):
- it has a 3D int array, for X, Y and Layer coordinates.
- The entire tileset is stored in 1 or more spritesheets.
- The sprite sheets are iterated through, assigning each image on each sheet a global tileID (IE: 1 = dirt, 2 = grass, etc) and sticks them in a HashMap<Integer, Image>. (Where Integer is the tileID of that tile and Image is the sprite, not the entire sheet)
- When rendering, you just iterate through the 3D int array (or 2D if you dont care about layers)
- Every time a tileID is found, go to a HashMap and ask for the value (the image) at the integer key(the global tile ID) and render it.

My map engine is a lot more complicated than that, but thats the super basic basics on how I fetch images off sprite sheets without making a 2D/3D image array or something silly. The end result is your entire map is just a ton of ints in an array.

- Raymond "Rayvolution" Doerr.
Retro-Pixel Castles - Survival Sim/Builder/Roguelike!
LIVE-STREAMING DEVELOPMENT: http://www.twitch.tv/SG_Rayvolution
Offline AppleSauce
« Reply #31 - Posted 2014-06-17 03:13:18 »

taking into consideration all the code posted here, I would suggest doing something like I did to setup your tile engine:

Here's how my system works (generally speaking):
- it has a 3D int array, for X, Y and Layer coordinates.
- The entire tileset is stored in 1 or more spritesheets.
- The sprite sheets are iterated through, assigning each image on each sheet a global tileID (IE: 1 = dirt, 2 = grass, etc) and sticks them in a HashMap<Integer, Image>. (Where Integer is the tileID of that tile and Image is the sprite, not the entire sheet)
- When rendering, you just iterate through the 3D int array (or 2D if you dont care about layers)
- Every time a tileID is found, go to a HashMap and ask for the value (the image) at the integer key(the global tile ID) and render it.

My map engine is a lot more complicated than that, but thats the super basic basics on how I fetch images off sprite sheets without making a 2D/3D image array or something silly.


Can you show some psuedocode for this. I get what your saying with the IDs, but I want to see how to apply this and find that ID.

well what i have there is a 1d array called tileSprites[] which stores each type of sprite
then i have a 2d array called map[][] which stores an index for which sprite to use from tileSprites.

Got it.  Grin
Offline Rayvolution

« JGO Spiffy Duke »


Medals: 256
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #32 - Posted 2014-06-17 03:31:41 »

Can you show some psuedocode for this. I get what your saying with the IDs, but I want to see how to apply this and find that ID.

hmm, I'll try. This is assuming you already have a spritesheet and image class of some kind that can grab the variables for you. Since I don't know if you're using Slick, Lib, LWJGL or even just J2D you'll have to plug that stuff in yourself.

Step one: Load the images into a HashSet,assigning them a tileID in the order you stick them in:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
   private HashMap<Integer, Image> tiles = new HashMap<Integer, Image>();
   private YourSpriteSheetClass tileSpriteSheet = new //Your sprite sheet.

   private void loadTiles(){
     
      int tileSheetH = tileSpriteSheet.getHorizontalCount(); //Get your horizontal sheet count (how many sprites wide the sheet is)
      int tileSheetV = tileSpriteSheet.getVerticalCount(); //Get your vertical sheet count (how many sprite tall the sheet is)
     
      for (int x = 0; x < tileSheetH; x++) {
         for (int y = 0; y < tileSheetV; y++) {
            tiles.put((x*tileSheetV)+y, tileSheets.get(tileSheet).getSprite(x, y));
         }
      }
   }

   //Getter you'll need for the other class later to fetch the images.
   public THashMap<Integer, Image> getTiles(){return tiles;}


Step two: Render the map by fetching the tile IDs and grabbing the image from the HashMap:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
//if you don't care about layers, make it int[][] and remove mapLayers.
private int mapHeight = //your map height
private int mapWidth = //your map width
private int mapLayers = //How many layers you have, if any.
private int[][][] mapArray; = new int[mapHeight][mapWidth][mapLayers];

//NOTE::: You also need a method to build the actual mapArray with values!

private void render(){
   for (int x = 0; x < mapWidth; x++) {
      for (int y = 0; y < mapHeight; y++) {
         //Where you're seeing if X/Y is even in the viewport, if it's not, don't bother rendering.
         if (((x*tileWidth)+mapX > tileWidth*-1) && ((x*tileWidth)+mapX < displayWidth+tileWidth) && ((y*tileHeight)+mapY > tileHeight*-1) && ((y*tileHeight)+mapY < displayHeight+tileHeight)){
            for (int l = 0; l < mapLayers; l++) {
               //Assuming you store tiles by a tileID and tileID 0 is "no tile", you just skip attempting to render it.
               if (!(mapArray[x][y][l] == 0){
                  //Draw the tile! Depending on what libraries you use, everything after .get may need modified to work with your image class.
                  tileLoaderClassFromStepOne.getTiles().get(mapArray[x][y][l]).draw(mapX+(x*tileWidth), mapY+(y*tileHeight));
               }
            }
         }
      }
   }
}


I *think* that covers it for the basics.

(EDIT: Remember, this is still using my technically-not-as-good-as-BP's loop, if you want to squeeze some performance out, use his loop.)

- Raymond "Rayvolution" Doerr.
Retro-Pixel Castles - Survival Sim/Builder/Roguelike!
LIVE-STREAMING DEVELOPMENT: http://www.twitch.tv/SG_Rayvolution
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Rayvolution

« JGO Spiffy Duke »


Medals: 256
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #33 - Posted 2014-06-17 04:33:58 »

Here's an updated version of the rendering code, using BP's method.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
private void render(){
   //The + and - 2 is to push the rendering bounds slightly outside the
   //viewport, that way you have a slight buffer of extra off-screen tiles being rendered.
   int startX = getMapRenderTileLeftX()-2;
   int startY = getMapRenderTileLeftY()-2;
   int endX = getMapRenderTileRightX()+2;
   int endY = getMapRenderTileRightY()+2;
   
   for(int x = startX; x < endX; x++) {
      for(int y = startY; y < endY; y++) {
         for (int l = 0; l < mapLayers; l++) {
            //So you dont try to fetch illegal values in your array you need these 2 if statements.
            if ((!(x < 0)) && (!(x > mapWidth-1))){
               if ((!(y < 0)) && (!(y > mapHeight-1))){
                  //Assuming you store tiles by a tileID and tileID 0 is "no tile",
                  //you just skip attempting to render it.
                  if (!(mapArray[x][y][l] == 0){
                     tileLoaderClassFromStepOne.getTiles().get(mapArray[x][y][l]).draw(mapX+(x*tileWidth), mapY+(y*tileHeight));
                  }
               }
            }
         }
      }
   }
}

   public int getMapRenderTileLeftX(){return (int)(mapX*-1)/tileWidth;}
   public int getMapRenderTileLeftY(){return (int)(mapY*-1)/tileHeight;}
   public int getMapRenderTileRightX(){return (int)((mapX*-1)+displayWidth)/tileWidth;}
   public int getMapRenderTileRightY(){return (int)((mapY*-1)+displayHeight)/tileHeight;}


- Raymond "Rayvolution" Doerr.
Retro-Pixel Castles - Survival Sim/Builder/Roguelike!
LIVE-STREAMING DEVELOPMENT: http://www.twitch.tv/SG_Rayvolution
Offline AppleSauce
« Reply #34 - Posted 2014-06-17 04:45:56 »

1  
if (!(mapArray[x][y][l] == 0){


What is the 1 and 0 in those parameters?

EDIT: I'm probably going to use Slick2D because I don't know how to animate with LWJGL, so you can refer to Slick2D.
Offline Rayvolution

« JGO Spiffy Duke »


Medals: 256
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #35 - Posted 2014-06-17 04:49:30 »

mapArray[x][y][LETTER L]
Tongue

Yes, I'm one of those nutbags who actually uses the lowercase L. Smiley

If you're using slick, my code should be pretty easy to plug in play, just use slick's image and spritesheet classes.

EDIT: The == 0 is checking if the tileID there is "0", where "0" should be "no tile exists" and to not bother rendering anything.

- Raymond "Rayvolution" Doerr.
Retro-Pixel Castles - Survival Sim/Builder/Roguelike!
LIVE-STREAMING DEVELOPMENT: http://www.twitch.tv/SG_Rayvolution
Offline AppleSauce
« Reply #36 - Posted 2014-06-17 04:52:11 »

mapArray[x][y][LETTER L]
Tongue

Yes, I'm one of those nutbags who actually uses the lowercase L. Smiley

If you're using slick, my code should be pretty easy to plug in place, just use slick's image and spritesheet classes.

Ha, okay, I think I got this. I'll have to look into it in the morning because my brain is powering down now. Just to clarify, this code would only render what's within the screen width and height right?
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 289
Exp: 5 years



« Reply #37 - Posted 2014-06-17 04:56:18 »

Alright. I'm going to bed (hopefully) so I can't really answer questions until tomorrow, but here's the prototype:

Click to Play

(ignore the GIF color-merge junk)

Full source: http://pastebin.java-gaming.org/8eaf049789a

Do what you want with it, but I wouldn't want to use it as the base engine for an actual game, it's just an example.
Also the input controls are a bit wonky, didn't feel like sorting them out.
Read the comments for stuff you can tweak (like the clipping trim in paint() )
Offline AppleSauce
« Reply #38 - Posted 2014-06-17 04:58:08 »

Alright. I'm going to bed (hopefully) so I can't really answer questions until tomorrow, but here's the prototype:

Click to Play

(ignore the GIF color-merge junk)

Full source: http://pastebin.java-gaming.org/8eaf049789a

Do what you want with it, but I wouldn't want to use it as the base engine for an actual game, it's just an example.
Read the comments for stuff you can tweak (like the clipping trim in paint() )


Did you spend a lot of time working on that for me?  Cry I feel so honered, thanks! I also will check it out in the morning.
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 289
Exp: 5 years



« Reply #39 - Posted 2014-06-17 04:59:40 »

Did you spend a lot of time working on that for me?  Cry I feel so honered, thanks! I also will check it out in the morning.

Not too much, mostly spent trying to pull J2D crap back from the long forgotten corners of my brain.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline AppleSauce
« Reply #40 - Posted 2014-06-17 05:01:29 »

Did you spend a lot of time working on that for me?  Cry I feel so honered, thanks! I also will check it out in the morning.

Not too much, mostly spent trying to pull J2D crap back from the long forgotten corners of my brain.

J2D? I should have said Slick2D or LWJGL with VBOs, but I still remember J2D.(What I used to think all games used)
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 289
Exp: 5 years



« Reply #41 - Posted 2014-06-17 05:04:18 »

Didn't feel like pulling out the big guns for a simple demo, plus this way it all fits nicely into a single source file.  Smiley
Should be pretty trivial to translate, as the rendering lib used is only the V in MVC. The other parts (most of the code) stay the same.
Offline AppleSauce
« Reply #42 - Posted 2014-06-17 05:11:10 »

MVC?
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 289
Exp: 5 years



« Reply #43 - Posted 2014-06-17 05:20:16 »

MVC?

See reply #6.
Offline Rayvolution

« JGO Spiffy Duke »


Medals: 256
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #44 - Posted 2014-06-17 05:27:10 »

[slightderail]
Thanks BP for indirectly showing me a better way to loop through the map, gave my game a 5-10~ FPS boost with the framerate uncapped. Went from 105-110~ to 115-120~. Not a huge difference, but every little bit is a good bit. Tongue
[/slightderail]

- Raymond "Rayvolution" Doerr.
Retro-Pixel Castles - Survival Sim/Builder/Roguelike!
LIVE-STREAMING DEVELOPMENT: http://www.twitch.tv/SG_Rayvolution
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 289
Exp: 5 years



« Reply #45 - Posted 2014-06-17 05:30:08 »

[slightderail]
Thanks BP for indirectly showing me a better way to loop through the entire map, gave my game a 5-10~ FPS boost with the framerate uncapped. Went from 105-110~ to 115-120~. Not a huge difference, but every little bit is a good bit. Tongue
[/slightderail]

No prob. Also that technique you were using has a slowdown that is linear with map size, so it'd be even more detrimental the larger the maps are.
Offline Rayvolution

« JGO Spiffy Duke »


Medals: 256
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #46 - Posted 2014-06-17 05:33:05 »

No prob. Also that technique you were using has a slowdown that is linear with map size, so it'd be even more detrimental the larger the maps are.

Very true. I didn't even consider that since my game is locked into 512x512 anyway for game balance reasons.

- Raymond "Rayvolution" Doerr.
Retro-Pixel Castles - Survival Sim/Builder/Roguelike!
LIVE-STREAMING DEVELOPMENT: http://www.twitch.tv/SG_Rayvolution
Offline AppleSauce
« Reply #47 - Posted 2014-06-17 06:28:04 »

I studied the code for a while and am still a bit confused. Why do you check if the x < the y length? Is it because they are the same?

1  
 for (int x = 0; x < tiles[y].length; x++


I have a good amount of questions and they might just be too much. Is there some kind of article that can help sum this up?
Offline LiquidNitrogen
« Reply #48 - Posted 2014-06-17 06:38:48 »

you might find it easier to learn if you start from nothing and build up each piece by yourself. make a big 2d map, put random tiles in it and draw a portion of that to the screen without moving. then add in the scrolling ability, then add in more layers. Its often hard to understand a complex system when you havnt built all the components of similar systems before.
get something to work, then ask the question "what small part do i change next to make it more like the way i want it", then work out how to make that change, one by one. this is probably a good idea, since you will eventually want to add a lot more complexity to your tile engine so you will want to understand it quite well.

Offline HeroesGraveDev

JGO Kernel


Medals: 310
Projects: 11
Exp: 3 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #49 - Posted 2014-06-17 06:45:22 »

http://www.cokeandcode.com/main/tutorials/tile-maps/

Offline AppleSauce
« Reply #50 - Posted 2014-06-18 02:15:09 »

I tried it myself and this is the best I could think of(for now). I have'nt implemented any camera rendering, but I just want to ask how this is so far.

Code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
import java.io.IOException;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;

public class IntroState extends State {
   
   private static final int TileSize = 64;
   
   //image tile i use
   private Image tile;
   
   //map width in pixels
   int map_width = 500;
   int map_height = 500;
   
   
   public void render(Graphics g) {
     
      for (int x = 0; x < map_width; x += TileSize){
         
      for (int y = 0; y < map_height; y+= TileSize) {
         
         g.drawImage(tile,  x, y);
         
      }
      }
     
   }

   public void init() throws SlickException, IOException {
      tile = new Image("res/tile.png");
     
     
   }

   public void update(int delta, Input input) {
     
   }


}


The output:



I was pretty proud of how much I did by myself with such little code. If you didn't notice, the images have a white space between them that I drew around them when I made it.

Now, when I see you guys use a tile class, what would one look like. Maybe some psuedo code with a bunch of fake methods for an example. How would I apply that tile class also?
Offline AppleSauce
« Reply #51 - Posted 2014-06-18 03:09:46 »

How do I move the screen in slick2D? Whenever I do g.translate it moves back.
Offline Rayvolution

« JGO Spiffy Duke »


Medals: 256
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #52 - Posted 2014-06-18 03:37:44 »

what are you trying to do exactly? Move the map around?

- Raymond "Rayvolution" Doerr.
Retro-Pixel Castles - Survival Sim/Builder/Roguelike!
LIVE-STREAMING DEVELOPMENT: http://www.twitch.tv/SG_Rayvolution
Offline LiquidNitrogen
« Reply #53 - Posted 2014-06-18 04:47:39 »

a basic tile class would contain an image member and a rendering method.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
class Tile{
    Image image;

    public Tile(Image desiredImage){
        image = desiredImage;
    }

    public render(int x, int y){
         g.drawImage(image,  x, y);
    }
}


To get different tiles you will have to create some sort of list into which you load your different tile images at the beginning of the program,
now when you use "new Tile()" to create a tile to place into your 2d map array, you will tell it which image the tile will be using.

you will then be able to say in your rendering loop:
1  
    map[x][y].render(x*tileWidth, y*tileHeight);



Offline LiquidNitrogen
« Reply #54 - Posted 2014-06-18 05:04:04 »

You dont really need to move the screen around either.. thats what the cameraX and cameraY are for

When ever you draw ANYTHING that is part of the world and you want to change its screen position when the camera moves you subtract the camera position from the images position. eg:

1  
    g.drawImage(image,  x - camearX, y - cameraY);


This shifts the whole lot over without any stuffing around or extra work. The only thing you need to do to move your camera view is to change the cameraX and cameraY variables. it applies to all your tiles, sprites, effects but not to GUI elements.

ps, your rendering loop will work better if you step it by 1 each step rather than by tileSize (otherwise its hard to read from your map array), multiply them up to screen co-ordinates while rendering instead.

Offline AppleSauce
« Reply #55 - Posted 2014-06-18 05:17:26 »

Blame typos on my phone  Pointing

I did it without a 2D or  3d array actually.  I made a rectangle that replaces the camera and only blocks that intersect it are rendered. All I have to do is specify the width and height of the map in tiles.  To draw a certain tile,  I have a seperate x and y coordinate and stuff.  I'm  not looking at the code right now but I did what you said (differently ) except for using any kind of arrays. I have to multiply the block width/height  when I want to draw a tile but apparently that's what I'm supposed to do.

Short story I made a faster tile engine than I planned. My first file engine too.  I'll  post the fps and source code in the morning.  Also,  even though this is my first tile engine,  is it wrong to paste bin.  It feels like only experts paste bin.  Smiley Smiley
Offline LiquidNitrogen
« Reply #56 - Posted 2014-06-18 05:26:22 »

pastebin is good for anything over a few lines of code.

how do you do it without a 2d array? you cant store/retrieve or alter your tile map without a map Wink

Offline kpars

JGO Kernel


Medals: 122
Projects: 5
Exp: 4 years


// No Comment.


« Reply #57 - Posted 2014-06-18 05:48:40 »

I don't exactly get what you're trying to do here. Are you just trying to move the map around the screen?

That should incredibly simple.

Pseudo-Code:
1  
2  
3  
4  
5  
6  
public void render(Graphics g, int map_offset_x, int map_offset_y)
{
    for (int x = map_offset_x; x < map_width + map_offset_x; x += TileSize)
        for (int y = map_offset_y; y < map_height + map_offset_y; y += TileSize)
            g.drawImage(tile, x, y);
}

You're just telling the program to render the map starting at a different location, the coordinates for that location being
map_offset_x
and
map_offset_y
.

- Jev

Offline AppleSauce
« Reply #58 - Posted 2014-06-18 18:45:09 »

Here's the paste bin for my magic
http://pastebin.java-gaming.org/eaf09587a99

And the output:
Offline LiquidNitrogen
« Reply #59 - Posted 2014-06-18 21:46:19 »

Looks like you're getting somewhere now. Next try to make it so you can have different types of tiles. You'll need arrays for that. You could either use random tiles first untill you work out how to change them with the mouse, or you could hard code the map during setup.

When I'm starting a new project, I usually start by making a very simple map editor. That gives me 2 good things: I can experiment with designing levels very early in development, and most of the rendering code is the same for the editor as it is for the game so it gets used for both.

Pages: 1 [2] 3
  ignore  |  Print  
 
 

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (35 views)
2014-12-15 09:26:44

Mr.CodeIt (26 views)
2014-12-14 19:50:38

BurntPizza (53 views)
2014-12-09 22:41:13

BurntPizza (86 views)
2014-12-08 04:46:31

JscottyBieshaar (48 views)
2014-12-05 12:39:02

SHC (63 views)
2014-12-03 16:27:13

CopyableCougar4 (66 views)
2014-11-29 21:32:03

toopeicgaming1999 (126 views)
2014-11-26 15:22:04

toopeicgaming1999 (117 views)
2014-11-26 15:20:36

toopeicgaming1999 (34 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!