Help creating a scrolling level like Legend of Zelda

Hello all, I am very new to game programming. I am currently using the
Slick2D Library to assist me in making a game. I am trying to create a scrolling level like you would have in Zelda where the player reaches the edge of the screen and goes onto the next. I am using a Tile Map to load the level and have defined tiles within the map editor where the collision is to take place (walls, trees). Anyway, when I compile the code and run, the map loads and I can move the sprite around. Currently I cannot get the map to “scroll” in any direction. In addition each direction gives me different results. When heading North, or West I crash (array index out of bounds)
When I head south, I get “blocked” (collision point) from reaching the edge. Sorry for the long post. Any help in figuring out why the scrolling does not work is greatly appreciated. Here is the code.


* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package GameWorld;

/**
*
* @author Matt
*/

import org.newdawn.slick.*;
import org.newdawn.slick.tiled.TiledMap;
import org.newdawn.slick.state.*;
import org.newdawn.slick.gui.TextField;



public class GamePlayState extends BasicGameState{
   
    private int stateID = 0;
    private TiledMap level1;
    private Animation sprite,up,down,left,right;
    private float x = 34f, y = 34f;
    //is the current tile of the tile map "blocked"
    private boolean[][] blocked;
    //
    private boolean[][] collidable;
    private static final int SIZE = 32;
    private static final int TILE_SIZE = 32;
    private static final float SPEED = 0.003f;
    private TextField text1;
    /** The width of the display in tiles */
    private int widthInTiles;
   /** The height of the display in tiles */
    private int heightInTiles;
   
    /** The offset from the centre of the screen to the top edge in tiles */
    private int topOffsetInTiles;
   /** The offset from the centre of the screen to the left edge in tiles */
    private int leftOffsetInTiles;
    /** The angle the player is facing */
    private float ang;
   /** The x component of the movement vector */
    private float dirX;
   /** The y component of themovement vector */
    private float dirY;
   
    /** The player's x position in tiles */
    private float playerX =20;
   /** The player's y position in tiles */
    private float playerY = 20;
       
    private enum STATES{START_GAME_STATE,PAUSE_GAME_STATE,GAME_OVER_STATE};
    private STATES currentState = null;
   

    public GamePlayState(int stateID)
    {
        this.stateID = stateID;
    }

   
    @Override
    public int getID() {
        return stateID;
    }
   
    @Override
    public void init(GameContainer container, StateBasedGame sb) throws SlickException
    {
        //assigning instance variable of object TileMap to the level1 Map Location
        level1 = new TiledMap("C:/Users/Matt/Downloads/desert.tmx");
        /*storing the image files for movement in an array so that different images can be loaded when player has new weapons. 
        and more importantly to help animate the sprite 
        */
        Image []  movementUp = {new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_bk1.gif")
                               ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_bk2.gif")};
        Image []  movementDown = {new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_fr1.gif")
                               ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_fr2.gif")};
        Image []  movementLeft = { new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_lf1.gif")
                               ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_lf2.gif")};
        Image []  movementRight ={ new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_rt1.gif")
                                ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_rt2.gif")};
       
        //determine how often the images are to be redrawn
        int [] duration = {300,300};
       
        //animate the sprite as the user presses the key
        up = new Animation(movementUp,duration,false);
        down = new Animation(movementDown,duration,false);
        left = new Animation(movementLeft,duration,false);
        right = new Animation(movementRight,duration,false);
       
        //set default orientation of the sprite
        sprite = right;
        sprite.setAutoUpdate(false);
       
               
        //add collision detection to the walls that have the blocked Map property
        blocked = new boolean[level1.getWidth()][level1.getHeight()];
        collidable =  new boolean[level1.getWidth()][level1.getHeight()];
        for (int a=0;a<level1.getWidth();a++) {
         for (int b=0;b<level1.getHeight();b++) {
            int tileID = level1.getTileId(a, b, 0);
            String value = level1.getTileProperty(tileID, "blocked", "false");
            if ("true".equals(value)) {
               blocked[a][b] = true;
            }
         }
   }
       
        // caculate some layout values for rendering the tilemap. How many tiles
      // do we need to render to fill the screen in each dimension and how far is
      // it from the centre of the screen
      widthInTiles = container.getWidth() / TILE_SIZE;
      heightInTiles = container.getHeight() / TILE_SIZE;
      topOffsetInTiles = heightInTiles / 2;
      leftOffsetInTiles = widthInTiles / 2;
    } 
   
   
    @Override
    public void update(GameContainer container, StateBasedGame sb, int delta) throws SlickException
    {
         
        //update the sprite movement as the keys are pressed
        Input input = container.getInput();
        float fdelta = delta*0.1f;
       
            if (input.isKeyDown(Input.KEY_UP))
            {
                sprite = up;
                if (!(isBlocked(x, y - fdelta) || isBlocked(x+SIZE-1, y - fdelta)))
                     {
                    sprite.update(delta);
                    // The lower the delta the slowest the sprite will animate.
                    y -= delta * 0.1f;
                     }
            }
            else if (input.isKeyDown(Input.KEY_DOWN))
                 {
                    sprite = down;
                    if (!(isBlocked(x, y + SIZE + fdelta) || isBlocked(x+SIZE-1, y + SIZE + fdelta)))
                    {
                         sprite.update(delta);
                         y += fdelta;
                    }
                 }
                 else if (input.isKeyDown(Input.KEY_LEFT))
                 {
                    sprite = left;
                    if(!(isBlocked(x-fdelta,y) || isBlocked(x-fdelta,y+SIZE-1)))
                    {
                        sprite.update(delta);
                        x -= fdelta;
                    }
                 }
                 else if (input.isKeyDown(Input.KEY_RIGHT))
                 {
                    sprite = right;
                    if (!(isBlocked(x + SIZE + fdelta, y) || isBlocked(x + SIZE + fdelta, y+SIZE-1)))
                    {   
                        sprite.update(delta);
                        x += fdelta;
                    }
                 }

     
    }
   

   
   
    @Override
    public void render(GameContainer container, StateBasedGame sb, Graphics g) throws SlickException
    {
       // draw the appropriate section of the tilemap based on the centre (hence the -(SIZE/2)) of
      // the player
      int playerTileX = (int) playerX;
      int playerTileY = (int) playerY;
      
      // caculate the offset of the player from the edge of the tile. As the player moves around this
      // varies and this tells us how far to offset the tile based rendering to give the smooth
      // motion of scrolling
      int playerTileOffsetX = (int) ((playerTileX - playerX) * TILE_SIZE);
      int playerTileOffsetY = (int) ((playerTileY - playerY) * TILE_SIZE);
      
      // render the section of the map that should be visible. Notice the -1 and +3 which renders
      // a little extra map around the edge of the screen to cope with tiles scrolling on and off
      // the screen
      level1.render(playerTileOffsetX - (SIZE / 2), playerTileOffsetY - (SIZE / 2),
               playerTileX - leftOffsetInTiles - 1,
               playerTileY - topOffsetInTiles - 1,
               widthInTiles + 3, heightInTiles + 3);
      
      // draw entities relative to the player that must appear in the centre of the screen
      g.translate(400 - (int) (playerX * 32), 300 - (int) (playerY * 32));
      
      //drawTank(g, playerX, playerY, ang);
      // draw other entities here if there were any
      
      g.resetTransform();
       // TextField field = new TextField();
        //render the map onto the screen
      //  level1.render(0,0);
                sprite.draw((int)x,(int)y);
       // fontTest.drawString(20.0f, 20.0f, "Slick displaying True Type Fonts", Color.green)
           
       
       
    }
   
   
    private boolean isBlocked(float aBlock, float bBlock)
    {
        int a = (int)aBlock/SIZE;
        int b = (int)bBlock/SIZE;
        return blocked[a][b];
    }
   
   /* private boolean isCollectable(float x,float y)
    {
        int xBlock = (int)x / SIZE;
        int yBlock = (int)y / SIZE;
        return collidable[xBlock][yBlock];
    }  */       
   
}

OK, I got the scrolling to work. Now I have a bigger problem. The collision detection no longer works. I think this is because the map is scrolling underneath the sprite. I have no idea how to fix so that the collision detection works. Can someone please help me?


/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package GameWorld;

/**
*
* @author Matt
*/

import org.newdawn.slick.*;
import org.newdawn.slick.tiled.TiledMap;
import org.newdawn.slick.state.*;
import org.newdawn.slick.gui.TextField;



public class GamePlayState extends BasicGameState{
   
    private int stateID = 0;
    private TiledMap level1;
    private Animation sprite,up,down,left,right,spin;
    private float x = 34f, y = 34f;
    private boolean[][] blocked;
    private boolean[][] collidable;
    private static final int SIZE = 32;
    private static final int TILE_SIZE = 32;
    private static final float SPEED = 0.003f;
    private int scrollOffset;
    private TextField text1;
    private int widthInTiles;
    private int heightInTiles;
    private int topOffsetInTiles;
    private int leftOffsetInTiles;
    private float ang;
    private float dirX;
    private float dirY;
   // private float playerX =20;
   //private float playerY = 20;
    private enum STATES{START_GAME_STATE,PAUSE_GAME_STATE,GAME_OVER_STATE};
    private STATES currentState = null;
   

    public GamePlayState(int stateID)
    {
        this.stateID = stateID;
    }

   
    @Override
    public int getID() {
        return stateID;
    }
   
    @Override
    public void init(GameContainer container, StateBasedGame sb) throws SlickException
    {
        Image []  movementUp = {new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_bk1.gif")
                               ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_bk2.gif")};
        Image []  movementDown = {new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_fr1.gif")
                               ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_fr2.gif")};
        Image []  movementLeft = { new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_lf1.gif")
                               ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_lf2.gif")};
        Image []  movementRight ={ new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_rt1.gif")
                                ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_rt2.gif")};
       
        int [] duration = {300,300};
       
        //animate the sprite as the user presses the key
        up = new Animation(movementUp,duration,false);
        down = new Animation(movementDown,duration,false);
        left = new Animation(movementLeft,duration,false);
        right = new Animation(movementRight,duration,false);
       
        widthInTiles = container.getWidth() / TILE_SIZE;
   heightInTiles = container.getHeight() / TILE_SIZE;
   topOffsetInTiles = heightInTiles / 2;
   leftOffsetInTiles = widthInTiles / 2;
       
        sprite = right;
        //sprite.setAutoUpdate(false);
               
        //assigning instance variable of object TileMap to the level1 Map Location
        level1 = new TiledMap("C:/Users/Matt/Downloads/desert.tmx");
                     
        //add collision detection to the walls that have the blocked Map property
        blocked = new boolean[level1.getWidth()][level1.getHeight()];
        //collidable =  new boolean[level1.getWidth()][level1.getHeight()];
        for (int xAxis=0;xAxis<level1.getWidth();xAxis++) {
      for (int yAxis=0;yAxis<level1.getHeight();yAxis++) {
         int tileID = level1.getTileId(xAxis, yAxis,0);
         String value = level1.getTileProperty(tileID, "blocked", "false");
         if ("true".equals(value)) {
            blocked[xAxis][yAxis] = true;
         }
      }
   }
    }
   
    private boolean isBlocked(float x, float y)
    {
        int xBlock = (int)x/SIZE;
        int yBlock = (int)y/SIZE;
        return blocked[xBlock][yBlock];
    }
   
       
        // caculate some layout values for rendering the tilemap. How many tiles
      // do we need to render to fill the screen in each dimension and how far is
      // it from the centre of the screen

    @Override
    public void update(GameContainer container, StateBasedGame sb, int delta) throws SlickException
    {
         
        //update the sprite movement as the keys are pressed
        Input input = container.getInput();
        float fdelta = delta*0.1f;
       
            if (input.isKeyDown(Input.KEY_UP))
            {
                sprite = up;
                if (!(isBlocked(x, y - fdelta) || isBlocked(x+SIZE-1, y - fdelta)))
                     {
                    sprite.update(delta);
                    // The lower the delta the slowest the sprite will animate.
                    y -= delta * 0.1f;
                         
                     }
            }
            else if (input.isKeyDown(Input.KEY_DOWN))
                 {
                    sprite = down;
                    if (!(isBlocked(x, y + SIZE + fdelta) || isBlocked(x+SIZE-1, y + SIZE + fdelta)))
                    {
                         sprite.update(delta);
                         y += fdelta;
                         
                    }
                 }
                 else if (input.isKeyDown(Input.KEY_LEFT))
                 {
                    sprite = left;
                    if(!(isBlocked(x-fdelta,y) || isBlocked(x-fdelta,y+SIZE-1)))
                    {
                        sprite.update(delta);
                        x -= fdelta;
                    }
                 }
                 else if (input.isKeyDown(Input.KEY_RIGHT))
                 {
                    sprite = right;
                    if (!(isBlocked(x + SIZE + fdelta, y) || isBlocked(x + SIZE + fdelta, y+SIZE-1)))
                    {   
                        sprite.update(delta);
                        x += fdelta;
                    }
                 }

     
    }


    @Override
    public void render(GameContainer container, StateBasedGame sb, Graphics g) throws SlickException
    {
       // draw the appropriate section of the tilemap based on the centre (hence the -(SIZE/2)) of
      // the player
        float fpx = x;
        float fpy = y;
       
   int playerTileX = (int)fpx;
   int playerTileY = (int)fpy;
        // caculate the offset of the player from the edge of the tile. As the player moves around this
   // varies and this tells us how far to offset the tile based rendering to give the smooth
   // motion of scrolling
   int playerTileOffsetX = (int) ((playerTileX - fpx) * TILE_SIZE);
   int playerTileOffsetY = (int) ((playerTileY - fpy) * TILE_SIZE);
      
   // render the section of the map that should be visible. Notice the -1 and +3 which renders
   // a little extra map around the edge of the screen to cope with tiles scrolling on and off
   // the screen
        level1.render(playerTileOffsetX,
                      playerTileOffsetY,
                      playerTileX - leftOffsetInTiles - 1,
                      playerTileY - topOffsetInTiles - 1,
                 widthInTiles + 3,
                      heightInTiles + 3);
       
       
         
        // scrollOffset += 20*0.1f/1000f;     
   // draw entities relative to the player that must appear in the centre of the screen
   g.translate(400 - (int) (fpx * SIZE), 300 - (int) (fpy * SIZE));
   //drawTank(g, playerX, playerY, ang);
   // draw other entities here if there were any
       
        sprite.draw((int)(x* SIZE),(int)(y* SIZE));
        g.resetTransform();
   
          
       // TextField field = new TextField();
        //render the map onto the screen
      //  level1.render(0,0);
               
       // fontTest.drawString(20.0f, 20.0f, "Slick displaying True Type Fonts", Color.green)
           
       
       
    }
   
   
   
   /* private boolean isCollectable(float x,float y)
    {
        int xBlock = (int)x / SIZE;
        int yBlock = (int)y / SIZE;
        return collidable[xBlock][yBlock];
    }  */       
   
}

does the collision detection not work at all? or is just wierd (stops at spots it should, or you can go halfway into blocks). because if its just wierd, it porbably means you messed something up in the rendering portion. have you had a looksee at cokeandcode’s tutorial?

I assume hwen u say collision detection, you’re talkinga bout the blocked[][]?

Yes I have looked at coke and code tutorial, that is what I based my collision detection from. Yes I am talking about blocked[][] and no, the collision does not work at all. Thanks again for any help you can provide.

it may be a good idea to add system.out.println() to some key spots, and to print variables, so you can know whats going on.

another question, did it work before you fixed scrolling?

Yes it worked perfect before I fixed the scrolling. The sprite needed to “butt” directly up against the block before the collision was detected.

OK. I finally managed to get the collision working, well, somewhat. When walking UP, the collision is perfect. When walking down, the collision does not occur until half way through the tile. Also when trying to pass through a blocked tile at the end of a row or corner block, I can pass straight through. I think the problem is in either my update or trymove method. I would really appreciate if someone could help me because it is really hard to move forward with my project until I get the collision down. I should let you know that math was never my best subject and I am pretty sure I am not calculating something correctly. Thanks again in advance.


/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package GameWorld;

/**
*
* @author Matt
*/

import org.newdawn.slick.*;
import org.newdawn.slick.tiled.TiledMap;
import org.newdawn.slick.state.*;
import org.newdawn.slick.gui.TextField;



public class GamePlayState extends BasicGameState{
   
    private int stateID = 0;
    private TiledMap level1;
    private Animation sprite,up,down,left,right,spin;
    private float x = 34f, y = 34f;
    private boolean[][] blocked;
    private boolean[][] collidable;
    private static final int SIZE = 32;
    private static final int TILE_SIZE = 32;
    private static final float SPEED = 0.003f;
    private int scrollOffset;
    private TextField text1;
    private int widthInTiles;
    private int heightInTiles;
    private int topOffsetInTiles;
    private int leftOffsetInTiles;
    private float ang;
    private float dirX;
    private float dirY;
    private float playerX =20;
    private float playerY = 20;
    private enum STATES{START_GAME_STATE,PAUSE_GAME_STATE,GAME_OVER_STATE};
    private STATES currentState = null;
   

    public GamePlayState(int stateID)
    {
        this.stateID = stateID;
    }

   
    @Override
    public int getID() {
        return stateID;
    }
   
    @Override
    public void init(GameContainer container, StateBasedGame sb) throws SlickException
    {
        Image []  movementUp = {new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_bk1.gif")
                               ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_bk2.gif")};
        Image []  movementDown = {new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_fr1.gif")
                               ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_fr2.gif")};
        Image []  movementLeft = { new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_lf1.gif")
                               ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_lf2.gif")};
        Image []  movementRight ={ new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_rt1.gif")
                                ,new Image("C:/Users/Matt/Downloads/last-guardian-sprites/last-guardian-sprites/amg1_rt2.gif")};
       
        int [] duration = {300,300};
       
        //animate the sprite as the user presses the key
        up = new Animation(movementUp,duration,false);
        down = new Animation(movementDown,duration,false);
        left = new Animation(movementLeft,duration,false);
        right = new Animation(movementRight,duration,false);
       
        widthInTiles = container.getWidth() / TILE_SIZE;
        heightInTiles = container.getHeight() / TILE_SIZE;
        topOffsetInTiles = heightInTiles / 2;
        leftOffsetInTiles = widthInTiles / 2;
       
        sprite = right;
        //sprite.setAutoUpdate(false);
               
        //assigning instance variable of object TileMap to the level1 Map Location
        level1 = new TiledMap("C:/Users/Matt/Downloads/desert.tmx");
        System.out.println(container.getWidth());             
        //add collision detection to the walls that have the blocked Map property
        blocked = new boolean[level1.getWidth()][level1.getHeight()];
        //collidable =  new boolean[level1.getWidth()][level1.getHeight()];
        for (int xAxis=0;xAxis<level1.getWidth();xAxis++) {
      for (int yAxis=0;yAxis<level1.getHeight();yAxis++) {
         int tileID = level1.getTileId(xAxis, yAxis,0);
         String value = level1.getTileProperty(tileID, "blocked", "false");
         if ("true".equalsIgnoreCase(value)) {
            System.out.println("tileID" + tileID + "Blocked"); 
            blocked[xAxis][yAxis] = true;
            
         }
      }
   }
}
   
    private boolean isBlocked(float x, float y)
    {
       return blocked[(int)x][(int)y];
    } 
    
   
   
       
        // caculate some layout values for rendering the tilemap. How many tiles
      // do we need to render to fill the screen in each dimension and how far is
      // it from the centre of the screen

    @Override
    public void update(GameContainer container, StateBasedGame sb, int delta) throws SlickException
    {
         
        //update the sprite movement as the keys are pressed
        Input input = container.getInput();
        float fdelta = delta*0.0051f;
       
            if (input.isKeyDown(Input.KEY_UP))
            {
                sprite = up;
                if ((tryMove(dirX, dirY - fdelta)) || (tryMove(dirX-1, -dirY - fdelta)))
               // if (tryMove(dirX * delta , dirY * delta))
                     {
                    sprite.update(delta);
                    // The lower the delta the slowest the sprite will animate.
                    y -= fdelta * 0.0051f;
                         
                     }
            }
            else if (input.isKeyDown(Input.KEY_DOWN))
                 {
                    sprite = down;
                    if (tryMove(dirX, -dirY + fdelta) || tryMove(dirX-1, +dirY + fdelta))
                  //  if (tryMove(-dirX * fdelta * SPEED, -dirY * delta * SPEED))
                    {
                         sprite.update(delta);
                         y += fdelta;
                         
                    }
                 }
                 else if (input.isKeyDown(Input.KEY_LEFT))
                 {
                    sprite = left;
                    if(tryMove(-dirX-fdelta,dirY) || tryMove(dirX-fdelta,dirY-1))
                    {
                        sprite.update(delta);
                        x -= fdelta;
                    }
                 }
                 else if (input.isKeyDown(Input.KEY_RIGHT))
                 {
                    sprite = right;
                    if (tryMove(dirX + fdelta, dirY) || tryMove(dirX +  fdelta, dirY-1))
                    {   
                        sprite.update(delta);
                        x += fdelta;
                    }
                 }

     
    }

   private boolean tryMove(float x, float y) {
		float newx = playerX + x;
		float newy = playerY + y;
		
		// first we try the real move, if that doesn't work
		// we try moving on just one of the axis (X and then Y) 
		// this allows us to slide against edges
		if (isBlocked(newx,newy)) {
			if (isBlocked(newx, playerY)) {
				if (isBlocked(playerX, newy)) {
					// can't move at all!
					return false;
				} else {
					playerY = newy;
					return false;
				}
			} else {
				playerX = newx;
				return true;
			}
		}
                else{
                    playerX = newx;
                    playerY = newy;
                    return true;
                }
   }

    @Override
    public void render(GameContainer container, StateBasedGame sb, Graphics g) throws SlickException
    {
       // draw the appropriate section of the tilemap based on the centre (hence the -(SIZE/2)) of
      // the player
      //  float fpx = x;
      //  float fpy = y;
       
   int playerTileX = (int)playerX;
   int playerTileY = (int)playerY;
          int mapOffsetX = 13;
          int mapOffsetY = 10;
          
        // caculate the offset of the player from the edge of the tile. As the player moves around this
   // varies and this tells us how far to offset the tile based rendering to give the smooth
   // motion of scrolling
   int playerTileOffsetX = (int) ((playerTileX - playerX) * TILE_SIZE);
   int playerTileOffsetY = (int) ((playerTileY - playerY) * TILE_SIZE);
      
   // render the section of the map that should be visible. Notice the -1 and +3 which renders
   // a little extra map around the edge of the screen to cope with tiles scrolling on and off
   // the screen
        level1.render(playerTileOffsetX - (SIZE / 2), playerTileOffsetY - (SIZE / 2), 
				   playerTileX - leftOffsetInTiles - 1, 
				   playerTileY - topOffsetInTiles - 1,
				   widthInTiles + 3, heightInTiles + 3);
       
       
         
        // scrollOffset += 20*0.1f/1000f;     
   // draw entities relative to the player that must appear in the centre of the screen
  g.translate(400 - (int) (playerX * 32), 300 - (int) (playerY * 32));
   //drawTank(g, playerX, playerY, ang);
   // draw other entities here if there were any
   //   sprite.draw((int)x,(int)y); 
      sprite.draw((int)(playerX* SIZE),(int)(playerY* SIZE));
    //sprite.draw(playerX,playerY);
        g.resetTransform();
   
          
       // TextField field = new TextField();
        //render the map onto the screen
      //  level1.render(0,0);
               
       // fontTest.drawString(20.0f, 20.0f, "Slick displaying True Type Fonts", Color.green)
           
       
       
    }
   
   
   
   /* private boolean isCollectable(float x,float y)
    {
        int xBlock = (int)x / SIZE;
        int yBlock = (int)y / SIZE;
        return collidable[xBlock][yBlock];
    }  */       
   
}