Slick Forums

Discuss the Slick 2D Library
It is currently Thu Jun 20, 2013 1:04 am

All times are UTC




Post new topic Reply to topic  [ 2 posts ] 
Author Message
PostPosted: Tue Apr 24, 2012 4:49 pm 
Offline

Joined: Tue Apr 24, 2012 4:39 pm
Posts: 1
Hey all,
I am very new to Slick2D and have so far really been enjoying it however I have found that there is little documentation on colllisions with Slick2D. Anyways, after reading a couple of tutorials and messing around for a bit, I began on my first game but I am now stuck with how to get my collision Detection to work.

I believe that the way I have done the collision detection takes into account all 4 sides of the player and both directions but I am now stuck. The player stops moving when he hits a blocked obstacle hence I do believe the collision detection is working as it detects that the player hits the obstacle but it does not allow the player to move any further. Any ideas?

I first grab the Tile Data from the Tiled (.tmx) map:
Code:
      // build a collision map based on tile properties in the TileD map
      blocked = new boolean[map.getWidth()][map.getHeight()];

      for (int xAxis = 0; xAxis < map.getWidth(); xAxis++) {
         for (int yAxis = 0; yAxis < map.getHeight(); yAxis++) {
            int tileID = map.getTileId(xAxis, yAxis, 0);
            String value = map.getTileProperty(tileID, "blocked", "false");
            if (value.equals("true")) {
               blocked[xAxis][yAxis] = true;
            }
         }
      }
   }


checks if the new position is blocked against the generated 2d boolean array
Code:
private boolean isBlocked(float x, float y) {
      int xBlock = (int) x / SIZE;
      int yBlock = (int) y / SIZE;
      return blocked[xBlock][yBlock];
   }


And this is my movement + collision code:

Code:
   @Override
   public void update(GameContainer container, int delta)
         throws SlickException {
      Input input = container.getInput();
      float rotation = player.getRotation();
      float speed = 0.1f * delta;
      float newX = 0;
      float newY = 0;

      newX += speed * Math.sin(Math.toRadians(rotation));

      newY -= speed * Math.cos(Math.toRadians(rotation));

      if (input.isKeyDown(Input.KEY_UP)) {
         // Check all directions
         if (!(isBlocked(playerX, playerY - newY)
               || isBlocked(playerX + SIZE - 1, playerY - newY)
               || isBlocked(playerX, playerY + SIZE + newY)
               || isBlocked(playerX + SIZE - 1, playerY + SIZE + newY)
               || isBlocked(playerX - newX, playerY)
               || isBlocked(playerX - newX, playerY + SIZE - 1)
               || isBlocked(playerX + SIZE + newX, playerY) || isBlocked(
                  playerX + SIZE + newX, playerY + SIZE - 1))) {

            // The lower the delta the slowest the sprite will animate.

            blockedStr = "Free";

            playerX += newX;
            playerY += newY;

         } else {
            blockedStr = "Blocked"; // if collision, change string (for
                              // debug purposes)
         }
      }

      if (input.isKeyDown(Input.KEY_LEFT)) {

         player.rotate(-0.2f * delta);
      }
      if (input.isKeyDown(Input.KEY_RIGHT)) {

         player.rotate(0.2f * delta);
      }
   }


Here is a full listing

SimpleGame.java
Code:
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.tiled.TiledMap;

public class SimpleGame extends BasicGame {
   Image land = null;
   Image player = null;

   float playerX = 400f;
   float playerY = 300f;
   float scale = 1.0f;
   private TiledMap map;
   private Camera cam;
   private String blockedStr = "free";

   int currentBullet = 0;
   /**
    * The collision map indicating which tiles block movement - generated based
    * on tile properties
    */
   private boolean[][] blocked;
   private static final int SIZE = 32;

   public SimpleGame() {
      super("Window");
   }

   // overriden methods are the 3 methods that we will add code later to, they
   // make up our game loop
   @Override
   public void init(GameContainer gc) throws SlickException {

      map = new TiledMap("res/map1.tmx");
      player = new Image("res/player.png"); // Note that this is Slick2D's
                                    // Image class not AWT's Image
                                    // class.

      cam = new Camera(gc, map);
      // build a collision map based on tile properties in the TileD map
      blocked = new boolean[map.getWidth()][map.getHeight()];

      for (int xAxis = 0; xAxis < map.getWidth(); xAxis++) {
         for (int yAxis = 0; yAxis < map.getHeight(); yAxis++) {
            int tileID = map.getTileId(xAxis, yAxis, 0);
            String value = map.getTileProperty(tileID, "blocked", "false");
            if (value.equals("true")) {
               blocked[xAxis][yAxis] = true;
            }
         }
      }
   }

   @Override
   public void update(GameContainer container, int delta)
         throws SlickException {
      Input input = container.getInput();
      float rotation = player.getRotation();
      float speed = 0.1f * delta;
      float newX = 0;
      float newY = 0;

      newX += speed * Math.sin(Math.toRadians(rotation));

      newY -= speed * Math.cos(Math.toRadians(rotation));

      if (input.isKeyDown(Input.KEY_UP)) {
         // Check all directions
         if (!(isBlocked(playerX, playerY - newY)
               || isBlocked(playerX + SIZE - 1, playerY - newY)
               || isBlocked(playerX, playerY + SIZE + newY)
               || isBlocked(playerX + SIZE - 1, playerY + SIZE + newY)
               || isBlocked(playerX - newX, playerY)
               || isBlocked(playerX - newX, playerY + SIZE - 1)
               || isBlocked(playerX + SIZE + newX, playerY) || isBlocked(
                  playerX + SIZE + newX, playerY + SIZE - 1))) {

            // The lower the delta the slowest the sprite will animate.

            blockedStr = "Free";

            playerX += newX;
            playerY += newY;

         } else {
            blockedStr = "Blocked"; // if collision, change string (for
                              // debug purposes)
         }
      }

      if (input.isKeyDown(Input.KEY_LEFT)) {

         player.rotate(-0.2f * delta);
      }
      if (input.isKeyDown(Input.KEY_RIGHT)) {

         player.rotate(0.2f * delta);
      }
   }

   private boolean isBlocked(float x, float y) {
      int xBlock = (int) x / SIZE;
      int yBlock = (int) y / SIZE;
      return blocked[xBlock][yBlock];
   }

   @Override
   public void render(GameContainer gc, Graphics g) throws SlickException {

      // after calculating the positions of all entities
      cam.centerOn(playerX, playerY);

      // in the render()-method
      cam.drawMap();
      cam.translateGraphics();

      // no depth in slick, images are rendered as the code executes so if we
      // render the player before the land, it will be underneath (no
      // transparency)
      player.draw(playerX, playerY);
      g.drawString("blocked:" + blockedStr, playerX - 10, playerY - 10);
   }

   public static void main(String[] args) throws SlickException {
      AppGameContainer app = new AppGameContainer(new SimpleGame());

      app.setDisplayMode(800, 600, false);
      app.start();

   }

}


Camera.java

Code:
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.tiled.TiledMap;
//Example Camera Class
public class Camera {

   protected TiledMap map;
   protected int numTilesX;
   protected int numTilesY;
   protected int mapHeight;
   protected int mapWidth;
   protected int tileWidth;
   protected int tileHeight;
   protected GameContainer gc;
   protected float cameraX;
   protected float cameraY;
   
   public Camera(GameContainer gc, TiledMap map) {
      this.map = map;
     
      this.numTilesX = map.getWidth();
      this.numTilesY = map.getHeight();
     
      this.tileWidth = map.getTileWidth();
      this.tileHeight = map.getTileHeight();
     
      this.mapHeight = this.numTilesX * this.tileWidth;
      this.mapWidth = this.numTilesY * this.tileHeight;
     
      this.gc = gc;
   }
   
   public void centerOn(float x, float y) {
      //try to set the given position as center of the camera by default
      cameraX = x - gc.getWidth()  / 2;
      cameraY = y - gc.getHeight() / 2;
     
      //if the camera is at the right or left edge lock it to prevent a black bar
      if(cameraX < 0) cameraX = 0;
      if(cameraX + gc.getWidth() > mapWidth) cameraX = mapWidth - gc.getWidth();
     
      //if the camera is at the top or bottom edge lock it to prevent a black bar
      if(cameraY < 0) cameraY = 0;
      if(cameraY + gc.getHeight() > mapHeight) cameraY = mapHeight - gc.getHeight();
   }

   public void centerOn(float x, float y, float height, float width) {
      this.centerOn(x + width / 2, y + height / 2);
   }


   public void centerOn(Shape shape) {
      this.centerOn(shape.getCenterX(), shape.getCenterY());
   }
   
 
   public void drawMap() {
      this.drawMap(0, 0);
   }
   

   
   public void drawMap(int offsetX, int offsetY) {
       //calculate the offset to the next tile (needed by TiledMap.render())
       int tileOffsetX = (int) - (cameraX % tileWidth);
       int tileOffsetY = (int) - (cameraY % tileHeight);
       
       //calculate the index of the leftmost tile that is being displayed
       int tileIndexX = (int) (cameraX / tileWidth);
       int tileIndexY = (int) (cameraY / tileHeight);
       
       //finally draw the section of the map on the screen
       map.render(   
             tileOffsetX + offsetX,
             tileOffsetY + offsetY,
             tileIndexX, 
             tileIndexY,
                (gc.getWidth()  - tileOffsetX) / tileWidth  + 1,
                (gc.getHeight() - tileOffsetY) / tileHeight + 1);
   }
   
   /**
    * Translates the Graphics-context to the coordinates of the map - now everything
    * can be drawn with it's NATURAL coordinates.
    */
   public void translateGraphics() {
      gc.getGraphics().translate(-cameraX, -cameraY);
   }
   /**
    * Reverses the Graphics-translation of Camera.translatesGraphics().
    * Call this before drawing HUD-elements or the like
    */
   public void untranslateGraphics() {
      gc.getGraphics().translate(cameraX, cameraY);
   }
   
}



Any help is appreciated,
v0rtex


Top
 Profile  
 
PostPosted: Fri May 04, 2012 3:28 pm 
Offline

Joined: Fri May 04, 2012 3:24 pm
Posts: 3
I guess the easiest way for doing collision detection is using slick's Shape class and the intersects() and contains() methods.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group