Smooth tile scrolling with Slick

game1

This is my first attempt for smooth tile scrolling in Slick. The offx/offy coordinates are not entirely correct for hero, smaller than the tile image but it’s a good start the “smooth” part comes from shx/shy variables which offset the rendering position. The code is after the break:

Update: Check the project source code page at Google Code: http://code.google.com/p/jmuonline/

package scroller;

import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.tiled.TiledMap;

/**
 *
 * @author aquilax
 */
public class Scroller2 extends BasicGame{

  private TiledMap map = null;
  private Hero hero = null;

  final static int screenw = 432;
  final static int screenh = 336;
  final static int centerx = screenw/2;
  final static int centery = screenh/2;
  final static int visx = 9;
  final static int visy = 7;
  final static float halfvisx = visx/2;
  final static float halfvisy = visy/2;

  private int tileW;
  private int tileH;
  private int mapW;
  private int mapH;
  private boolean[][] blocked;
  private int offx;
  private int offy;

  public Scroller2(){
    super("Scroller2");
  }

  @Override
  public void init(GameContainer container) throws SlickException {
    map = new TiledMap("data/testone.tmx");
    tileW = map.getTileWidth();
    tileH = map.getTileHeight();
    mapW = map.getWidth();
    mapH = map.getHeight();
    fillBlocked(map);
    hero = new Hero("data/hero.png");
    hero.speed = 1;
    hero.xtile = Integer.parseInt(map.getMapProperty("herox", "16"));
    hero.ytile = Integer.parseInt(map.getMapProperty("heroy", "8"));

    hero.xpos = centerx - hero.awidth/2;
    hero.ypos = centery - hero.aheight/2;

    offx = hero.xtile*tileW;
    offy = hero.ytile*tileH;
  }

  @Override
  public void update(GameContainer container, int delta) throws SlickException {
    Input input = container.getInput();
    if (input.isKeyDown(Input.KEY_LEFT)) {
      moveChar(hero, -1, 0);
    }
    if (input.isKeyDown(Input.KEY_RIGHT)) {
      moveChar(hero, +1, 0);
    }
    if (input.isKeyDown(Input.KEY_UP)) {
      moveChar(hero, 0, -1);
    }
    if (input.isKeyDown(Input.KEY_DOWN)) {
      moveChar(hero, 0, +1);
    }
  }

  public void render(GameContainer container, Graphics g) throws SlickException {
    int shx = (int)(offx/tileW)*tileW - offx;
    int shy = (int)(offy/tileH)*tileH - offy;
    map.render(shx, shy, (int)(offx/tileW-halfvisx), (int)(offy/tileH-halfvisy), visx+1, visy+1);
    hero.draw(hero.xpos, hero.ypos);
    g.setColor(Color.red);
    g.drawString("offx "+offx, 300, 10);
    g.drawString("offy "+offy, 300, 30);
  }

  public static void main(String[] args) throws SlickException {
    AppGameContainer app = new AppGameContainer(new Scroller2());
    app.setDisplayMode(screenw, screenh, false);
    app.start();
  }

  private void fillBlocked(TiledMap map) {
    blocked = new boolean[mapW][mapH];
    for(int x = 0; x < mapW; x++){
      for (int y = 0; y < mapH; y++){
        blocked[x][y]  = "true".equals(map.getTileProperty(map.getTileId(x, y, 0), "blocked", "false"));
      }
    }
  }

  private void moveChar(Hero ob, int dirx, int diry) {
    offx += (int)(dirx*ob.speed);
    offy += (int)(diry*ob.speed);
  }
}

Comments

comments powered by Disqus