Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
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 2912 times)
0 Members and 1 Guest are viewing this topic.
Offline AppleSauce
« Posted 2014-06-16 23:44:27 »

Game Maps

I started working on my newest project today and it got me wondering. When games with huge tile maps like the olden day Legends of zelda were created, were the maps drawn manually and the programmers mainly added collision to it, or did the programmers take the tiles and make huge a** for loops for the map? I thought, maybe just load the maps and just create special classes for each object, containing its' own separate collision and methods. I had some intense and creative ideas I wanted to apply.

Scrolling

How does scrolling effect work. would I draw the map and then have the screen move according the players' coordinates?
Offline Rayvolution

JGO Kernel


Medals: 216
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #1 - Posted 2014-06-17 00:02:54 »

There's about 50 zillion ways to do it. But I use a huge for loop that while looping, also detects the edges of the screen so it only renders tiles actually on the screen. For collision/object detection, I search the entire entire map's tiles for a blocked/collision property and build my collision system based on that ... and as for map movement, I made the camera detect where the player is and follow him around.

Really you're asking for many different systems, that all have to work together and are all dependent on how you build the others. So it's kinda complicated to give a single unified answer. Cheesy

- Raymond "Rayvolution" Doerr.
Retro-Pixel Castles - Survival Sim/Builder/Roguelike!
LIVE-STREAMING DEVELOPMENT: http://www.twitch.tv/SG_Rayvolution
Offline BurntPizza
« Reply #2 - Posted 2014-06-17 00:05:42 »

Tile collision from the guys at Metanet, of N+ fame: http://www.metanetsoftware.com/technique/tutorialB.html
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline AppleSauce
« Reply #3 - Posted 2014-06-17 00:12:26 »

Awwww. I know this is programming but I thought this could be a lot simpler. I planned on just designing the giant tile maps and using a camera to follow the players' position. The thing is, I don't know how the coordinates would work for this :/.
Offline BurntPizza
« Reply #4 - Posted 2014-06-17 00:16:56 »

Awwww. I know this is programming but I thought this could be a lot simpler. I planned on just designing the giant tile maps and using a camera to follow the players' position. The thing is, I don't know how the coordinates would work for this :/.

That's basically how it is done, in the case of "player is camera" you render everything from player.x - screenWidth/2 to player.x + screenWidth/2. To figure out where that lies on your tilemap, you use a screenCoord to worldCoord transformation function, which is usually just a division by tile size.

It is really simple stuff.
Offline AppleSauce
« Reply #5 - Posted 2014-06-17 00:34:09 »

Do I have to make all the collision boxes move downward every time the player presses the up key?
Offline BurntPizza
« Reply #6 - Posted 2014-06-17 00:47:10 »

Do I have to make all the collision boxes move downward every time the player presses the up key?

No. I'll stop right here and recommend you invest yourself at least a little bit in some design philosophy called MVC. It stands for Model-View-Controller and is a system in which you separate the functions of various aspects of your application from each other.

For instance, your tilemap is a Model (of the tile data). It is rendered to the screen in a particular way, the particular way is described by the View, in the case of 2D, top-down tilemaps mostly the transformation function I mentioned earlier. The Model and View are manipulated via user-input by the Controller.

The tilemap contains the collision data, which is used to determine collisions etc. It has no effect on rendering, it is separate. Nothing "moves down" when the player presses the up key, the player object moves up in the Model, and the View renders the scene with the player in the center (if that is what your are doing), creating the illusion that everything is moving around the player. Why move all but one thing when you can move just the one thing?

MVC, being as abstract as it is, can be applied in endless ways, so I'll stop here (I think you can get the basic idea) and let you go look at some of the numerous tutorials if you need more.
Offline AppleSauce
« Reply #7 - Posted 2014-06-17 01:01:44 »

makes sense. I was thinking about how to apply this and drew a visual.



Since the player (view I think) moves up, the other entities (models) keep their location? The weird thing is, I would have to draw the items starting from 0x, 0y which would be the upper left corner of the map. So then, the map would have to start at the upper left corner? (Please say yes)
Offline CodeHead

JGO Knight


Medals: 41


From rags to riches...to rags.


« Reply #8 - Posted 2014-06-17 01:19:41 »

Since the player (view I think) moves up, the other entities (models) keep their location?

Yes. At least in the case where the player avatar is the only MOB. For simplicity sake, think of the player as your cameraman moving through the world (model) as opposed to the world moving around the cameraman.

The weird thing is, I would have to draw the items starting from 0x, 0y which would be the upper left corner of the map. So then, the map would have to start at the upper left corner? (Please say yes)

Indeed, although when you're rendering (as previously mentioned), you'd render player position +/- minus the appropriate x and y distances.

Arthur: Are all men from the future loud-mouthed braggarts?
Ash: Nope. Just me baby...Just me.
Offline AppleSauce
« Reply #9 - Posted 2014-06-17 01:23:14 »

Glad to hear that! So, if I just drew a tile map with a tile creator and drew the image to the screen, could i work from there? I don't think loading maps from a file would be easy. I also don't see how a for loop would be necessary  to draw detailed parts of the map.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline CodeHead

JGO Knight


Medals: 41


From rags to riches...to rags.


« Reply #10 - Posted 2014-06-17 01:33:54 »

Glad to hear that! So, if I just drew a tile map with a tile creator and drew the image to the screen, could i work from there? I don't think loading maps from a file would be easy. I also don't see how a for loop would be necessary  to draw detailed parts of the map.

When prototyping, I usually just load up 2 tile images and use a loop to fill a 2D array with alternating instances of the image. As for loading maps from a file it can be as easy or complex as you choose to make it. Don't be afraid to try new things though just because they could be complex. The best way to build your programming muscles is to bite off slightly more than you think you can chew.

You'll always need at least one outer loop for rendering the map no matter how simple or complex it is. Inner loops are usually used for rendering multiple layers of tiles on a map. As long as you're sensible in how you handle sparse data sets, you can still get a nice balance of detail and efficiency. Smiley

Arthur: Are all men from the future loud-mouthed braggarts?
Ash: Nope. Just me baby...Just me.
Offline AppleSauce
« Reply #11 - Posted 2014-06-17 01:36:34 »

AAAAAAAHHHHHH! I really want to just draw it and get on, but the array of maps sounds more professional even though I have no idea how to do it.
Offline BurntPizza
« Reply #12 - Posted 2014-06-17 01:38:15 »

You don't "have" to do anything a particular way. The tiles and objects residing on them can be represented any way you want.



In this example, tiles are simply in an array,
Tile[][] tiles;


Each tile can contain a
List<Entity> entities;


These entities have their own collision bounds, AABBs in this case. Collision can be easily determined and resolved.

Rendering tiles can be done something like this: (in top-left coordinate system, can be easily converted to others)

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
// just to go along with the image
final int screenWidthInTiles = 7;
final int screenHeightInTiles = 5;


int startY = Math.floor(player.y) - screenHeightInTiles / 2;
int startX = Math.floor(player.x) - screenWidthInTiles / 2;
for(int y = startY; y < startY + screenHeightInTiles; y++) {
    for(int x = startX; x < startX + screenWidthInTiles; x++) {
        Tile tile = tiles[y][x];
        setColor(tile.color);
        int tileX = (x - startX) * TILE_WIDTH; // transform to screen coords
        int tileY = (y - startY) * TILE_HEIGHT;
        fillRect(tileX, tileY, TILE_WIDTH, TILE_HEIGHT);
       
        // ok, so I'm cheating here, I'm lazy.
        for(Entity e : tile.entities)
            e.render();
    }
}


EDIT: it should be noted that everything is stored and done in world coordinates, screen coords are calculated as needed when rendering, and only then.
Offline AppleSauce
« Reply #13 - Posted 2014-06-17 01:41:29 »

This is my first time seeing somthing like this so I'm still a bit lost.. But I see how rendering only what is on the camera keeps the fps higher
Offline BurntPizza
« Reply #14 - Posted 2014-06-17 01:45:31 »

This is my first time seeing somthing like this so I'm still a bit lost.. But I see how rendering only what is on the camera keeps the fps higher


Indeed, and when you have lots of complex entities, lighting, particles systems, etc etc, it actually becomes quite necessary to not render all the things going on in the universe all the time.
Offline syszee
« Reply #15 - Posted 2014-06-17 02:02:52 »

There's about 50 zillion ways to do it. But I use a huge for loop that while looping, also detects the edges of the screen so it only renders tiles actually on the screen. For collision/object detection, I search the entire entire map's tiles for a blocked/collision property and build my collision system based on that ... and as for map movement, I made the camera detect where the player is and follow him around.

Really you're asking for many different systems, that all have to work together and are all dependent on how you build the others. So it's kinda complicated to give a single unified answer. Cheesy


Yea, mind giving me a completely unrelated tutorial for that loading only in view? xD

Offline AppleSauce
« Reply #16 - Posted 2014-06-17 02:21:13 »

It looks so hard. Couldn't I just make the graphics render whenever the camera touches its' camera collision bound or somthing?
Offline CodeHead

JGO Knight


Medals: 41


From rags to riches...to rags.


« Reply #17 - Posted 2014-06-17 02:35:05 »

You could, but I was under the assumption that you were looking for efficient methods; iterating over the whole map each frame is definitely not efficient unless your map takes up 1 screen or less. BP's method is pretty simple. Walk through it in your mind a few times and it will click. Wink

Arthur: Are all men from the future loud-mouthed braggarts?
Ash: Nope. Just me baby...Just me.
Offline AppleSauce
« Reply #18 - Posted 2014-06-17 02:47:28 »

I concentrated on reading it and understand it exxcept for this line.
1  
2  
int tileX = (x - startX) * TILE_WIDTH; // transform to screen coords
        int tileY = (y - startY) * TILE_HEIGHT;

So startX is the players' current position at all times right? If your subtracting the tiles' x/y by the players' x/y, wouldn't it move the player further? What would a keypress look like ?
Offline Rayvolution

JGO Kernel


Medals: 216
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #19 - Posted 2014-06-17 02:50:35 »

An alternative is doing something like this, but this DOES iterating over the entire map, only rendering the tiles it detects as in the viewport.

BP's way is technically a faster way of going about it because you don't iterate the entire map, but this is how I do it. Although looking at BP's I may try his way and see how much faster it could be.

EDIT: fixed some stuff.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
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)){
         //Assuming you store tiles by a tileID and tileID 0 is "no tile", you just skip attempting to render it.
         if (!(mapArray[x][y] == 0){
            //render tile X/Y
         }
      }
   }
}



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

JGO Knight


Medals: 41


From rags to riches...to rags.


« Reply #20 - Posted 2014-06-17 02:51:21 »

No. The code BP posted always draws the character at the center of the screen. StartX is the left edge of your view and is computed by taking the player's position and subtracting 1/2 of the screen width.

Arthur: Are all men from the future loud-mouthed braggarts?
Ash: Nope. Just me baby...Just me.
Offline CodeHead

JGO Knight


Medals: 41


From rags to riches...to rags.


« Reply #21 - Posted 2014-06-17 02:52:33 »

BP's way is technically a faster way of going about it because you don't iterate the entire map, but this is how I do it. Although looking at BP's I may try his way and see how much faster it could be.

I foresee an easy optimization in your future. Smiley

Arthur: Are all men from the future loud-mouthed braggarts?
Ash: Nope. Just me baby...Just me.
Offline BurntPizza
« Reply #22 - Posted 2014-06-17 02:54:09 »

I'll post something better than that contrived example here in a bit, a little more concrete.
Offline Rayvolution

JGO Kernel


Medals: 216
Projects: 2
Exp: 1 year


Resident Crazyman


« Reply #23 - Posted 2014-06-17 02:54:42 »

BP's way is technically a faster way of going about it because you don't iterate the entire map, but this is how I do it. Although looking at BP's I may try his way and see how much faster it could be.

I foresee an easy optimization in your future. Smiley

I might give it a shot, but I just use a simple 3D int array that I iterate though, so it runs pretty fast. The only time it ever does anything beyong the basic iteration is if it detects X/Y is within the viewport *and* has a value that isnt 0.

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

I'll post something better than that contrived example here in a bit, a little more concrete.

I would really appreciate that, I'm still having a bit of trouble, but i got the general idea.
Offline AppleSauce
« Reply #25 - Posted 2014-06-17 02:59:35 »


I foresee an easy optimization in your future. Smiley

Yay! Inspiration.
Offline LiquidNitrogen
« Reply #26 - Posted 2014-06-17 03:01:16 »

Heres the very basic idea of drawing a scrolling tile map in kind of pseudocode.

1  
2  
3  
4  
5  
for (int x = 0; x < 18; x++){
for (int y = 0; y < 14; y++){
    Tile.draw(tileSprites[map[x+cameraX][y+cameraY]], (x+cameraX)*TileSize, (y+cameraY)*TileSize);
}
}


simply change the cameraX and cameraY with the arrow keys and it will move around.
thats the first challenge, after that works you can get it to draw the correct amount of tiles to fill the screen, limit the camera so it doesnt try to draw tiles which are off the edge of the map, then add in your entities, which fit in quite easily, depending on how you stored them.

Offline AppleSauce
« Reply #27 - Posted 2014-06-17 03:03:51 »

Heres the very basic idea of drawing a scrolling tile map in kind of pseudocode.

1  
2  
3  
4  
5  
for (int x = 0; x < 18; x++){
for (int y = 0; y < 14; y++){
    Tile.draw(tileSprites[map[x+cameraX][y+cameraY]], (x+cameraX)*TileSize, (y+cameraY)*TileSize);
}
}


simply change the cameraX and cameraY with the arrow keys and it will move around.
thats the first challenge, after that works you can get it to draw the correct amount of tiles to fill the screen, limit the camera so it doesnt try to draw tiles which are off the edge of the map, then add in your entities, which fit in quite easily, depending on how you stored them.

Sorry but some of that confuses me. I should probably look into using 2d arrays.
Offline CodeHead

JGO Knight


Medals: 41


From rags to riches...to rags.


« Reply #28 - Posted 2014-06-17 03:05:09 »

I might give it a shot, but I just use a simple 3D int array that I iterate though, so it runs pretty fast. The only time it ever does anything beyong the basic iteration is if it detects X/Y is within the viewport *and* has a value that isnt 0.

I'd still be worried about the impacts on caching, but any technique that provides acceptable results is a good technique. Cool

Arthur: Are all men from the future loud-mouthed braggarts?
Ash: Nope. Just me baby...Just me.
Offline LiquidNitrogen
« Reply #29 - Posted 2014-06-17 03:05:17 »

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.

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.

Longarmx (38 views)
2014-10-17 03:59:02

Norakomi (29 views)
2014-10-16 15:22:06

Norakomi (24 views)
2014-10-16 15:20:20

lcass (28 views)
2014-10-15 16:18:58

TehJavaDev (56 views)
2014-10-14 00:39:48

TehJavaDev (55 views)
2014-10-14 00:35:47

TehJavaDev (46 views)
2014-10-14 00:32:37

BurntPizza (64 views)
2014-10-11 23:24:42

BurntPizza (36 views)
2014-10-11 23:10:45

BurntPizza (78 views)
2014-10-11 22:30:10
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

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
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!