Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have my map stored in 2 arrays:

  • Tiles : Tile names
  • TileTypes : SOLID or BASIC

I want to be able to walk through BASIC Tiles (Like ground tiles). But not the SOLID Tiles (Like wall tiles).

I have tried many ways of doing this and I always fail.

Map Code:

package game;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;


import javax.imageio.ImageIO;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.Color;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;



public class Map {
     Random random=new Random();
    public int BushProbability=8;

    public int ticks;
    public int waterType;

    public int MX=384;
    public int MY=284;

    int mapWidth=1000;
    int mapSize;
    public String[][] Tiles = new String[(mapWidth+1)*2][(mapWidth+1)*2];
    public String[][] TileTypes = new String[(mapWidth+1)*2][(mapWidth+1)*2];
    int Tile;

    public Texture grass;
    public Texture stone;
    public Texture water;
    public Texture bush;

    public Texture water1;
    public Texture water2;
    public Texture water3;

    public Texture stone1;


    BufferedImage map = null;

    public void Init()
    {
        try {
            grass = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Tiles/Grass.png"));
            bush = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Tiles/Bush.png"));
            stone = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Tiles/Stone.png"));
            water1 = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Tiles/Water.png"));
            water2 = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Tiles/Water1.png"));
            water3 = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Tiles/Water2.png"));
            stone1 = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Tiles/Stone1.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

     public void LoadMap()
        {
         File file= new File("res/map.png");
        try {
            map = ImageIO.read(file);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        mapWidth=map.getWidth();
        mapSize=mapWidth*mapWidth;

            for(int Y = 0;Y<mapWidth;Y++){
                for(int X = 0;X<mapWidth;X++){

                      // Getting pixel color by position x=100 and y=40 
                      int clr=  map.getRGB(X,Y); 
                      int  red   = (clr & 0x00ff0000) >> 16;
                      int  green = (clr & 0x0000ff00) >> 8;
                      int  blue  =  clr & 0x000000ff;

              if(red==0&&green==0&&blue==0){
                  Tiles[X][Y]="VOID";
                  TileTypes[X][Y]="SOLID";
                  //System.out.println("BLACK "+X+" "+Y);
              }
              if(red==255&&green==0&&blue==0){
                  if(random.nextInt(5)==0){
                      Tiles[X][Y]="SOLIDSTONE1";
                      TileTypes[X][Y]="SOLID";
                  }else{
                  Tiles[X][Y]="SOLIDSTONE2";
                  TileTypes[X][Y]="SOLID";
                  }
                  //System.out.println("RED "+X+" "+Y);
              }
              if(red==0&&green==255&&blue==0){


                  if(random.nextInt(BushProbability)==0){
                      Tiles[X][Y]="BUSH"; 
                      TileTypes[X][Y]="BASIC";
                  }else{
                  Tiles[X][Y]="GRASS";}
                  //System.out.println("GREEN "+X+" "+Y);
              }
              if(red==0&&green==0&&blue==255){
                  Tiles[X][Y]="WATER";
                  TileTypes[X][Y]="SOLID";
                 // System.out.println("BLUE "+X+" "+Y);
              }

            }
            }
            }       




        public void RenderMap()
        { ticks++;
        if(ticks==10){
            waterType++;
            if(waterType==3){waterType=1;}
            ticks=0;
        }
        if(waterType==0){
            water=water1;
        }if(waterType==1){
            water=water2;
        }
        if(waterType==2){
            water=water3;
        }

            for(int X=0;X<mapWidth;X++){
                for(int Y=0;Y<mapWidth;Y++){

                    if(Tiles[X][Y]=="GRASS"){
                        Color.white.bind();
                        grass.bind(); // or GL11.glBind(texture.getTextureID());

                        GL11.glBegin(GL11.GL_QUADS);
                            GL11.glTexCoord2f(0,0);
                            GL11.glVertex2f((MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,0);
                            GL11.glVertex2f(grass.getTextureWidth()+(MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,1);
                            GL11.glVertex2f(grass.getTextureWidth()+(MX+(X*32)),grass.getTextureHeight()+(MY+(Y*32)));
                            GL11.glTexCoord2f(0,1);
                            GL11.glVertex2f((MX+(X*32)),grass.getTextureHeight()+(MY+(Y*32)));
                        GL11.glEnd();
                    }

                    if(Tiles[X][Y]=="SOLIDSTONE2"){
                        Color.white.bind();
                        stone.bind(); // or GL11.glBind(texture.getTextureID());

                        GL11.glBegin(GL11.GL_QUADS);
                            GL11.glTexCoord2f(0,0);
                            GL11.glVertex2f((MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,0);
                            GL11.glVertex2f(stone.getTextureWidth()+(MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,1);
                            GL11.glVertex2f(stone.getTextureWidth()+(MX+(X*32)),stone.getTextureHeight()+(MY+(Y*32)));
                            GL11.glTexCoord2f(0,1);
                            GL11.glVertex2f((MX+(X*32)),stone.getTextureHeight()+(MY+(Y*32)));
                        GL11.glEnd();
                    }

                    if(Tiles[X][Y]=="SOLIDSTONE1"){
                        Color.white.bind();
                        stone1.bind(); // or GL11.glBind(texture.getTextureID());

                        GL11.glBegin(GL11.GL_QUADS);
                            GL11.glTexCoord2f(0,0);
                            GL11.glVertex2f((MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,0);
                            GL11.glVertex2f(stone1.getTextureWidth()+(MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,1);
                            GL11.glVertex2f(stone1.getTextureWidth()+(MX+(X*32)),stone1.getTextureHeight()+(MY+(Y*32)));
                            GL11.glTexCoord2f(0,1);
                            GL11.glVertex2f((MX+(X*32)),stone1.getTextureHeight()+(MY+(Y*32)));
                        GL11.glEnd();
                    }

                    if(Tiles[X][Y]=="WATER"){
                        Color.white.bind();
                        water.bind(); // or GL11.glBind(texture.getTextureID());

                        GL11.glBegin(GL11.GL_QUADS);
                            GL11.glTexCoord2f(0,0);
                            GL11.glVertex2f((MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,0);
                            GL11.glVertex2f(water.getTextureWidth()+(MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,1);
                            GL11.glVertex2f(water.getTextureWidth()+(MX+(X*32)),water.getTextureHeight()+(MY+(Y*32)));
                            GL11.glTexCoord2f(0,1);
                            GL11.glVertex2f((MX+(X*32)),water.getTextureHeight()+(MY+(Y*32)));
                        GL11.glEnd();
                    }

                    if(Tiles[X][Y]=="BUSH"){
                        Color.white.bind();
                        bush.bind(); // or GL11.glBind(texture.getTextureID());

                        GL11.glBegin(GL11.GL_QUADS);
                            GL11.glTexCoord2f(0,0);
                            GL11.glVertex2f((MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,0);
                            GL11.glVertex2f(bush.getTextureWidth()+(MX+(X*32)),(MY+(Y*32)));
                            GL11.glTexCoord2f(1,1);
                            GL11.glVertex2f(bush.getTextureWidth()+(MX+(X*32)),bush.getTextureHeight()+(MY+(Y*32)));
                            GL11.glTexCoord2f(0,1);
                            GL11.glVertex2f((MX+(X*32)),bush.getTextureHeight()+(MY+(Y*32)));
                        GL11.glEnd();
                    }



                }
            }
        }
}

Player code:

package mob;

import java.io.IOException;

import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.Color;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;

public class Player extends game.Map {

    public int SPEED=10;

    public String Colour="WHITE";

    public int mapWidth;

    int DX = (800/2)-16;
    int DY = (600/2)-16;

    public int X;
    public int Y;

     int RX; int RY;

    boolean UP;
    boolean DOWN;
    boolean LEFT;
    boolean RIGHT;


    private Texture texture;

    public void Init()
    {
        try {
            // load texture from PNG file

            if(Colour == "WHITE"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/White.png"));
            }
            if(Colour == "YELLOW"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Yellow.png"));
            }
            if(Colour == "RED"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Red.png"));
            }
            if(Colour == "PURPLE"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Purple.png"));
            }
            if(Colour == "PINK"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Pink.png"));
            }
            if(Colour == "ORRANGE"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Orrange.png"));
            }
            if(Colour == "LIGHT-GREEN"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Lime-Green.png"));
            }
            if(Colour == "LIGHT-BLUE"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Light-Blue.png"));
            }
            if(Colour == "GREY"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Grey.png"));
            }
            if(Colour == "GREEN"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Green.png"));
            }
            if(Colour == "BLUE"){
                texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/Mob/Slime/Blue.png"));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public void Render()
    {

        Color.white.bind();
        texture.bind(); // or GL11.glBind(texture.getTextureID());

        GL11.glBegin(GL11.GL_QUADS);
            GL11.glTexCoord2f(0,0);
            GL11.glVertex2f(DX,DY);
            GL11.glTexCoord2f(1,0);
            GL11.glVertex2f(DX+texture.getTextureWidth(),DY);
            GL11.glTexCoord2f(1,1);
            GL11.glVertex2f(DX+texture.getTextureWidth(),DY+texture.getTextureHeight());
            GL11.glTexCoord2f(0,1);
            GL11.glVertex2f(DX,DY+texture.getTextureHeight());
        GL11.glEnd();

    }

    public void Update()
    {
         UP = Keyboard.isKeyDown(Keyboard.KEY_W);
         DOWN = Keyboard.isKeyDown(Keyboard.KEY_S);
         LEFT = Keyboard.isKeyDown(Keyboard.KEY_A);
         RIGHT   = Keyboard.isKeyDown(Keyboard.KEY_D);

         if(UP){Y=Y+SPEED;}
         if(DOWN){Y=Y-SPEED;}
         if(LEFT){X=X+SPEED;}
         if(RIGHT){X=X-SPEED;}
    }

}

I have heard of RECTANGLE collision checking but I have no idea how to implement it into a tile based game.

Thanks, Griff.

share|improve this question
1  
Griff, remember that comment about posting all your code? It's not required, please clean it up. Show us that you at least understand where the issue is and only post the relevant code. –  Byte56 Mar 8 '13 at 23:57
add comment

2 Answers 2

up vote 2 down vote accepted

Here's the concept. Lets start with a red square representing your player and a green square representing an obstacle:

enter image description here

Now the player presses right on the keyboard. Here's the part of your code that moves them:

public void Update()
    {
         RIGHT   = Keyboard.isKeyDown(Keyboard.KEY_D);
         if(RIGHT){X=X+SPEED;}
    }

Actually your code says X-SPEED, but that would seem to me to be left, not right, unless your coordinate system is pretty unusual, so I changed it. Anyway, they've pressed right, and lets say SPEED is enough that this creates a collision, so we have this:

enter image description here

But that's what we want to prevent! Don't panic though, it hasn't been displayed to the user yet, so there's still time to fix it. First we need to detect that a collision occurred. We'd do that right after moving the square.

public void Update()
    {
         RIGHT   = Keyboard.isKeyDown(Keyboard.KEY_D);
         if(RIGHT){X=X+SPEED;}
         checkIfCollisionHappened()  //  We're going to check right here.
    }

So what goes on in that checkIfCollisionHappened() method? Well you might take a look at the Rect object. That's a simple way to check. In particular it has a few intersect methods you're going to want to use. I.e., you create a Rect for your player (feed the coordinates in the Rect constructor) and create a Rect for the obstacle and check the intersect method of one against the other.

So lets say it returns true, we have a collision, how do we resolve the collision? The answer is we want to move the player back by the amount that the rectangles intersected, so it arrives here:

enter image description here

Our pseudo-code is going to start looking something like this:

public void Update()
    {
         RIGHT   = Keyboard.isKeyDown(Keyboard.KEY_D);
         if(RIGHT){X=X+SPEED;}
         if (checkIfCollisionHappened())  //  Did we collide?
                adjustForCollision();  // If so move the square back.
    }

So now comes the question, how does the adjustForCollision() method know how much to move the sprite back? Look again at those intersect() methods in Rect and you'll see some of them return a Rect that represents the overlap between the two Rects. So that means we can use that return Rect, take its width, and move the player sprite leftwards accordingly.

The key thing here is that we've moved the sprite back to where it isn't overlapping before any of this got rendered to the player, so the player never knows the red square didn't just "stop" when it hit the green square.

share|improve this answer
    
How can I implement your code? Sorry, I am really bad at things like this. –  griffy100 Mar 9 '13 at 7:01
    
I gave you a pretty step-by-step walkthrough there, Griffy. What part are you having difficulty with? Do you want to post your attempt at implementing it? –  Cameron Fredman Mar 9 '13 at 12:50
    
What goes in the adjustForCollision(); function. I have no idea how to use Rects. –  griffy100 Mar 10 '13 at 1:27
    
I linked Rect to the javadoc above. Did you make the code for checking for collisions yet (before you adjust for them)? If so please post it and we can discuss further. –  Cameron Fredman Mar 10 '13 at 1:33
    
No I have not started writing the collision checking yet. Where is the java doc link? –  griffy100 Mar 10 '13 at 10:50
show 1 more comment

Basically you store a 2 dimensional area that is composed of nodes. Each node has the corresponding coordinate of a single tile.

If you have player coordinates that are not discrete (for simplicity: is stored as a float instead of an int) you can check weather or not a position your player wants to stand in by simply rounding the coordinates of the position and getting the corresponding tile from your arrays to check weather or not the entity can stand there "if it would move there".

If you have discrete coordinates for your entities, the problem actually solves itself.

I think the solution you are looking for is to have the logic behind the game and the rendering separate. Have your entity move in coordinates where 1 unit to any direction really means 1 tile in any direction and have it move between these coordinates by giving it a non discrete coordinate description. Standing in position (2.5 , 1.5) means standing "on" Tile (2,1) , collision will be calculated by these coordinates.

Your rendering then iterates across your tiles and draws each with an offset equal to the tile size on screen and it's position (so : tile.getX()*TILE_SIZE ; tile.getY()*TILE_SIZE), with the player coodinates : (int) player.getX()*TILE_SIZE [...]

share|improve this answer
    
Thanks for this but how do I implement it into the game. Sorry if this is a "Write My Code For Me" question but I'm really stuck. :-) –  griffy100 Mar 8 '13 at 23:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.