Gdzieś wyczytałem, że wykrywanie kolizji w przypadku tilemap można bazować na tileset mapy. do poszczególnych tilesets można przypisać wartości blocked.
np. mamy tileset o nazwie trawa gdzie wartość właściwości blocked jest false, czyli postać chodząca po trawie nie będzie blokowana i będzie mogła się swobodnie poruszać.
i tileset o nazwie Skały w którego skład będą wchodzić różnego rodzaju duże skały. Dla właściwości "blocked" tego tileseta będzie przypisana wartość true, co w programie będzie oznaczało że nasza postać nie będzie mogła poruszać się po tego rodzaju tilesach.
Jak to zrealizować?
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package slicktest;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.util.Rectangle;
import org.newdawn.slick.Animation;
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.tiled.TiledMap;
/**
*
* @author jarek
*/
public class SlickTest extends BasicGame{
private TiledMap grassMap;
private Animation sprite, up, down, left, right;
private float x = 34f, y = 34f;
// This will keep a list of Tiles that are blocked
private boolean [][] blocked;
// For collision detection, we have a list of Rectangles you can use to test against
private ArrayList<Rectangle> blocks;
private static final int SIZE = 34;
/**
* @param args the command line arguments
* @throws org.newdawn.slick.SlickException
*/
public static void main(String[] args) {
// app.setDisplayMode(500, 400, false);
try {
AppGameContainer app = new AppGameContainer(new SlickTest());
app.setDisplayMode(500, 400, false);
app.start();
} catch (SlickException ex) {
Logger.getLogger(SlickTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
public SlickTest() {
}
@Override //tutaj ładujemy zdjecia mapy itp
public void init(GameContainer gc) throws SlickException {
grassMap = new TiledMap("data/map/grassmap.tmx");
Image[] movementUp = {new Image("data/player/up1.png"), new Image("data/player/up2.png")};
Image[] movementDown = {new Image("data/player/down1.png"), new Image("data/player/down2.png")};
Image[] movementLeft = {new Image("data/player/left1.png"), new Image("data/player/left2.png")};
Image[] movementRight = {new Image("data/player/right1.png"), new Image("data/player/right2.png")};
int[] duration = {300, 300}; // Ustawiamy jak często ma być rysowana animacja podczas Sprite
/*
* false variable means do not auto update the animation.
* By setting it to false animation will update only when
* the user presses a 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);
// Oryginalna orientacja postaci (w którą stronę jest obrócona postać standardowo)
sprite = down;
// buduje mape kolizji opierającej się na mapie
blocked = new boolean[grassMap.getWidth()][grassMap.getHeight()];
int layer = 1;
for (int xAxis=0;xAxis<grassMap.getWidth(); xAxis++)
{
for (int yAxis=0;yAxis<grassMap.getHeight(); yAxis++)
{
int tileID = grassMap.getTileId(xAxis, yAxis, layer);
String value = grassMap.getTileProperty(tileID, "blocked", "false");
if (value.equals("true"))
{
blocked[xAxis][yAxis] = true;
// And create the collision Rectangle
// blocks.add(new Rectangle((float)xAxis * SIZE, (float)yAxis * SIZE, SIZE, SIZE));
}
}
}
}
@Override
public void update(GameContainer gc, int deltaTime) throws SlickException {
Input input = gc.getInput();
float fdelta= deltaTime *0.1f;
if (input.isKeyDown(Input.KEY_UP))
{
sprite = up;
if (!(isBlocked(x, y - fdelta) || isBlocked(x + SIZE -1, y - fdelta))){
sprite.update(deltaTime);
// The lower the delta the slowest the sprite will animate.
y -= fdelta;
}
}
else if (input.isKeyDown(Input.KEY_DOWN))
{
sprite = down;
if (!(isBlocked(x, y + SIZE + fdelta) || isBlocked(x+SIZE-1, y + SIZE + fdelta)))
{
sprite.update(deltaTime);
y += fdelta;
}
}
else if (input.isKeyDown(Input.KEY_LEFT))
{
sprite = left;
if (!(isBlocked(x - fdelta, y) || isBlocked(x - fdelta, y+SIZE-1)))
{
sprite.update(deltaTime);
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(deltaTime);
x += fdelta;
}
}
}
@Override
public void render(GameContainer gc, Graphics grphcs) throws SlickException {
grassMap.render(0, 0);
sprite.draw(x, y);
}
private boolean isBlocked(float x, float y) {
int xBlock = (int) ((int)x / SIZE);
int yBlock = (int) ((int)y / SIZE);
return blocked[xBlock][yBlock];
}
}
blocks.add(new Rectangle((float)xAxis * SIZE, (float)yAxis * SIZE, SIZE, SIZE)); dla tej linii dostaje "incompatible types: possible lossy conversion from float to int" dlaczego?