Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (487)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (552)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  How to render specific area?  (Read 866 times)
0 Members and 1 Guest are viewing this topic.
Offline tyeeeee1
« Posted 2013-03-25 21:22:35 »

I'm currently attempting to change my map loading/rendering code so that only the area within x number of blocks in all directions of the sprites' location are rendered. I know how this should work but I'm not sure how to change the code for it to work in the way that I want it to work.
The way that I'm planning to have it work is that, because the maps are tile-based, it will render all the tiles that you can see on screen and 1 tile in each direction off screen so that when the player is moving it will have enough space and time to render the new tiles so that you don't start seeing a black background.

Below is the code that I use to load the map. Each pixel on the image corresponds to a tile that will be loaded; when the tiles are being rendered there is a switch statement that, depending on the value at a certain (X,Y) location in the 2D map[][] array, will render a specific tile. This code is based off of another piece of code that I managed to find while googling one day.
I need to somehow change it so that it will only load a certain area of the image based upon four sets of (X, Y) coordinates) instead of loading the entire image pixel by pixel by line by line.

Edit: All code is in the third post


This snippit of code is what I use to render the map. It takes the map[][] array that is loaded from the method above and then goes through every single position in the map[][] array and, depending on the value at that point, renders a specific tile.

Edit: All code is in the third post.

Thanks in advance to anyone who can help me figure out how to solve my problem.
Offline UprightPath
« Reply #1 - Posted 2013-03-25 21:54:14 »

Ack! While your case statement there will work (And you'll have to do probably do something like it somewhere) it's not the best way to handle that. This is more about your switch statement than anything. You should pull out that g.draw command and put it into a method that you call:
1  
2  
3  
private void drawSprite(Sprite sprite, int col, int pos, int playerX, int playerY) {
g.drawImage(sprite, column*40 - playerX, row * 40 - playerY, null);
}

Then you can do something a bit better than that switch statement by doing something like:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
HashMap<Integer, Sprite> sprites = new HashMap<Integer, Sprite>();
private void init() {
sprites.put(SpriteColorNumber, SpriteResource); // For each one.
}

// ... Lots of stuff

//Render Map
       for(int row = 0; row < mapHeight; row++)
        {
            for(int column = 0; column < mapWidth; column++)
            {
drawSprite(sprites.get(currentMap[column][row]), row, col, playerX, playerY);
}
}

Of course, translating the pixel values into indexes into a bounded array or something would result in better efficiency... But ah, getting off track there, hah.

Whew! That said for your problem about painting the only a sub-section of the map, you first need to decide how you're going to do it? Are you centering the displayed section on the player? And if so, when he gets to an edge of your map will the map stop following him?

If it doesn't stop then it's really simple:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
int startX = (playerX - halfWidth) / tileX - 1;
int startY = (playerY - halfHeight) / tileY - 1;
int endX = (playerX + halfWidth) / tileX + 1;
int endY = (playerY + halfHeight) / tileY + 1;

for(int i = startX; i < endX; i++) {
for(int j = startY; j < endY; j++) {
// Render code!
}
}


For the other way (With the camera stopping at the edges) I've got a code snippet somewhere (It's a class that holds the screen bounds and stuff like that) but I'll have to dig it out.

Offline tyeeeee1
« Reply #2 - Posted 2013-03-25 22:47:49 »

Thanks for the reply. I've attempted to add something similar to what you wrote into the code (I've pasted the part I'm talking about below) but I can't seem to figure out the variables due to how I've written my code. I probably should have posted all of the code to give anyone a better understanding of how it works, Anyways...

Do the playerY & playerX variables represent the current area in the map[][] array where the player is?
Do the halfHeight & haldWidth variables represent the amount of tiles from where the player is standing on to the edge of the screen?
What do tileX and tile Y represent?

Quote
int startX = (playerX - halfWidth) / tileX - 1;
int startY = (playerY - halfHeight) / tileY - 1;
int endX = (playerX + halfWidth) / tileX + 1;
int endY = (playerY + halfHeight) / tileY + 1;

for(int i = startX; i < endX; i++) {
for(int j = startY; j < endY; j++) {
// Render code!
}
}



I'll post the movement code along with the rest of the rendering code so that you can see how I'm doing everything.

This is the render/logic 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  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
package Screens;

import Core.GameCanvas;
import Core.ResourceHandler;
import Entity.CollisionDetection;
import Entity.Player;
import java.awt.Graphics2D;

public class ScreenGame extends Screen
{
    private int[][] currentMap;
    private GameCanvas canvas;
    private ResourceHandler resource;
    private Player player;
    private CollisionDetection collision;
    private int playerXLocation, playerYLocation, playerDirection;
    private boolean playerIsWalking;
    private int mapWidth, mapHeight;
    private int spriteCounter = 0, spriteCounterTwo = 0;
   
    public ScreenGame(GameCanvas canvas)
    {
        this.canvas = canvas;
        resource = new ResourceHandler();
        player = new Player();
        resource.loadImages();
        collision = new CollisionDetection();
    }
   
    public void logicUpdate()
    {
        setCurrentMap();
        collision.logicUpdate();
        player.logicUpdate();
        playerXLocation = player.getXLocation();
        playerYLocation = player.getYLocation();
        playerIsWalking = player.getIsWalking();
        playerDirection = player.getDirection();
        mapWidth = currentMap.length;
        mapHeight = currentMap[0].length;
        spriteCounterTwo++;
       
        //This while statement checks 4 different points around the player's sprite, if any of them return false then the player's position is changed until they all return true.
       while(collision.checkPointCollision(playerXLocation - 12, playerYLocation + 22) == false /*LowerLeftPoint*/ || collision.checkPointCollision(playerXLocation + 12, playerYLocation + 22) == false /*Lower Right Point*/ || collision.checkPointCollision(playerXLocation - 12, playerYLocation) == false /*Middle Left Point*/ || collision.checkPointCollision(playerXLocation + 12, playerYLocation) == false /*Middle Right Point*/)
        {
            switch(playerDirection)
            {
                case 0:
                {
                    player.setXLocation(1);
                    playerXLocation++;
                    break;
                }
               
                case 1:
                {
                    player.setYLocation(1);
                    playerYLocation++;
                    break;
                }
                   
                case 2:
                {
                    player.setXLocation(-1);
                    playerXLocation--;
                    break;
                }
                   
                case 3:
                {
                    player.setYLocation(-1);
                    playerYLocation--;
                    break;
                }
            }
        }
    }
   
    /////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////
   
    @Override
    public void render(Graphics2D g)
    {
        //Updates Logic in other Methods
       logicUpdate();
       
        //Render Map
       for(int row = 0; row < mapHeight; row++)
        {
            for(int column = 0; column < mapWidth; column++)
            {
                switch(currentMap[column][row]) //Note: To increase the player's walking speed just times both the playerXPosition and playerYPosition by a speed multiplyer
               {
                    case -1237980: //Grass
                   {
                        g.drawImage(resource.getSprite(2, 0, 0), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }

                    case -3584: //Grass Flower 1
                   {
                        g.drawImage(resource.getSprite(2, 0, 1), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }

                    case -16735512: //Grass Flower 2
                   {
                        g.drawImage(resource.getSprite(2, 0, 2), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }

                    case -14503604: //Stone Path
                   {
                        g.drawImage(resource.getSprite(2, 0, 3), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }
                       
                    case -14503860: //Stone Path
                   {
                        g.drawImage(resource.getSprite(2, 0, 4), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }
                       
                    case -14504116: //Stone Path
                   {
                        g.drawImage(resource.getSprite(2, 0, 5), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }
                       
                    case -14504372: //Stone Path
                   {
                        g.drawImage(resource.getSprite(2, 0, 6), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }
                       
                    case -14504628: //Stone Path
                   {
                        g.drawImage(resource.getSprite(2, 0, 7), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }
                       
                    case -14504884: //Stone Path
                   {
                        g.drawImage(resource.getSprite(2, 0, 8), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }
                       
                    case -14505140: //Stone Path
                   {
                        g.drawImage(resource.getSprite(2, 0, 9), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }
                       
                    case -14505396: //Stone Path
                   {
                        g.drawImage(resource.getSprite(2, 0, 10), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }
                       
                    case -14505652: //Stone Path
                   {
                        g.drawImage(resource.getSprite(2, 0, 11), column*40 - playerXLocation, row * 40 - playerYLocation, null);
                        break;
                    }
                }
            }
        }
       
       
        //Render Player
       //Whenever you get diagonal movement animations on the player sprite create more direction numbers for the diagonal movement and then add the stuff to render the diagonal animations below
       if (!playerIsWalking)
        {
            spriteCounter = 0;
            spriteCounterTwo = 0;
        }
        else if(playerIsWalking && spriteCounter == 0)
        {
            spriteCounter = 1;
        }
       
        if (spriteCounter == 0 && !playerIsWalking)
        {
            g.drawImage(resource.getSprite(0, playerDirection, spriteCounter), 628, 499, null);
        }
        else if (spriteCounter == 1 && playerIsWalking && spriteCounterTwo >= 15)
        {
             g.drawImage(resource.getSprite(0, playerDirection, spriteCounter), 628, 499, null);
             spriteCounter++;
             spriteCounterTwo = 0;
        }
        else if (spriteCounter == 1 && playerIsWalking && spriteCounterTwo < 15)
        {
             g.drawImage(resource.getSprite(0, playerDirection, spriteCounter), 628, 499, null);
        }
        else if (spriteCounter == 2 && playerIsWalking && spriteCounterTwo >= 15)
        {
            g.drawImage(resource.getSprite(0, playerDirection, spriteCounter), 628, 499, null);
            spriteCounter--;
            spriteCounterTwo = 0;
        }
        else if (spriteCounter == 2 && playerIsWalking && spriteCounterTwo < 15)
        {
            g.drawImage(resource.getSprite(0, playerDirection, spriteCounter), 628, 499, null);
        }
    }
   
    //Set methods
   public void setCurrentMap()
    {
        currentMap = resource.getMap();
    }
}


Movement
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  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
package Entity;

import Core.KeyboardListener;
import java.awt.event.KeyEvent;

public class Player extends Entity
{
    private int xLocation = 0, yLocation = 0, direction = 0;
    private boolean isWalking = false;
   
    public Player()
    {
    }
   
    public void logicUpdate()
    {
        if(KeyboardListener.isKeyPressed(KeyEvent.VK_W) || KeyboardListener.isKeyPressed(KeyEvent.VK_UP))
        {
            //Up
           yLocation--;
            isWalking = true;
            direction = 1;
        }
        else if(KeyboardListener.isKeyPressed(KeyEvent.VK_S) || KeyboardListener.isKeyPressed(KeyEvent.VK_DOWN))
        {
            //Down
           yLocation++;
            isWalking = true;
            direction = 3;
        }
        else if(KeyboardListener.isKeyPressed(KeyEvent.VK_A) || KeyboardListener.isKeyPressed(KeyEvent.VK_LEFT))
        {
            //Left
           xLocation--;
            isWalking = true;
            direction = 0;
        }
        else if(KeyboardListener.isKeyPressed(KeyEvent.VK_D) || KeyboardListener.isKeyPressed(KeyEvent.VK_RIGHT))
        {
            //Right
           xLocation++;
            isWalking = true;
            direction = 2;
        }
        else
        {
            isWalking = false;
        }
    }
   
    //Set Methods
   public void setXLocation(int x)
    {
        xLocation += x;
    }
   
    public void setYLocation(int x)
    {
        yLocation += x;
    }
    //Get Methods
   public int getXLocation()
    {
        return xLocation;
    }
   
    public int getYLocation()
    {
        return yLocation;
    }
   
    public boolean getIsWalking()
    {
        return isWalking;
    }
   
    public int getDirection()
    {
        return direction;
    }
}



To get where the player's position on the map[][] array is, I use this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
int tempInt = 15;
        int tempIntTwo = 12;
       
        if(playerXLocation> 0)
        {
            tempInt = 16;
        }
       
        if(playerYLocation> 0)
        {
            tempIntTwo = 13;
        }
       
        int xPositionOnMap = ((playerXLocation/ 40)) + tempInt;
        int yPositionOnMap = ((playerYLocation/ 40)) + tempIntTwo;


As for the improvements to the switch statement, that'll help a lot! I'm first going to look into hashmaps first before I attempt to use them.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline UprightPath
« Reply #3 - Posted 2013-03-25 23:07:12 »

Ah, next time use the pastebin (Link below the text area) for a large chunk of code. :3

Alright, I was making some assumptions based on the code you had posted, here they are:
1) The player's location is represented by a screen pixel location (In this case, the center of their sprite).
2) You know the dimensions of your screen.

The first assumption leads to playerX being the player's X pixel location and that playerY is the player's Y pixel location. (I was hand typing things I try to keep the length of my variable names short, those two values are playerXLocation and playerYLocation respectively. Assuming that it's pixel data).
The second assumption allows us to find the displayed bounds of the screen by tiles. Let's say that the player's location is (400,500) and that the display is (480,320), and that tiles are 40 pixels wide/high. Looking at we can substitute and get
int startX = (playerX - halfWidth) / tileX - 1;
startX = (400 - 240) / 40 - 1;
startX = (160) / 40 - 1;
startX = 4 - 1;
startX = 3.
This means that to only call paint for tiles on the screen, we'd start drawing at 3 and end at some endX (Which we'd find in the same way).

Anyway, your paint loop would compute those four values and use them as a bounds for painting. Ah, I can post some code (My aborted platformer project) which has some code for doing the bound finding and paint loop.

Offline tyeeeee1
« Reply #4 - Posted 2013-03-26 15:55:53 »

Hmm... I can't see if it's working or not but I've altered the map rendering code. I tried using a very large map (400x400 pixels in size which is a lot of tiles) and you could easily see that the game was slower and lagging just as it did before I edited the rendering code. I'm going to try and mess around with the code to see if I can check if it's working somehow.

Edit:
Derp, it looks like I forgot to add the startY, startX, endX, endY to the for loop that renders the map... Back to testing!

Edit 2:
I'm getting a lot of ArrayIndexOutOfBounds errors. Attempting to figure out a fix for them now...

Edit 3:
After testing out your code a little bit I managed to create a variant of it that works somewhat the same although I still get ArrayIndexOutOfBounds errors. I'm working on fixing them now.

Edit 4:
Managed to get it working properly. All that's left now is to figure out how to optimize map loading so that it doesn't spend a few minutes loading a 1000x1000 pixel image and then error out because it's using 100% CPU. Everything except for the map loading is working amazingly compared to how it was before, thanks a ton! Grin
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

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

The first screenshot will be displayed as a thumbnail.

CopyableCougar4 (23 views)
2014-08-22 19:31:30

atombrot (34 views)
2014-08-19 09:29:53

Tekkerue (30 views)
2014-08-16 06:45:27

Tekkerue (28 views)
2014-08-16 06:22:17

Tekkerue (18 views)
2014-08-16 06:20:21

Tekkerue (27 views)
2014-08-16 06:12:11

Rayexar (65 views)
2014-08-11 02:49:23

BurntPizza (41 views)
2014-08-09 21:09:32

BurntPizza (31 views)
2014-08-08 02:01:56

Norakomi (41 views)
2014-08-06 19:49:38
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

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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!