我正在制作一个简单的基于平铺的游戏。谈到碰撞检测,我倾向于失败。这是第三次尝试正确地进行像素精确运动。我仍然面临着瓷砖的一些问题。(http://prntscr.com/2evl5c)例如 - > http://prntscr.com/2evl92,http://prntscr.com/2evlg6,http://prntscr.com/2evll1
这是我上课的。 //包 //进口 公共类LevelOne扩展BasicGameState { // state是这个类的id,objLayer是检查碰撞的图层的id,tileX,Y = tile上的位置 public int state,objLayer,tileX,tileY; 布尔esc; 输入输入;
public int[][] obj; //store each tile's id of the object layer here
private TiledMap map;
private float x,y,vel, TILE_SIZE;//x position , y position ,velocity, tile size in pixels
private Sound jump;//nevermind
public boolean cLeft,cRight,cUp,cDown;//c(anMove)Left/Right/Down etc
public LevelOne(int state){
this.state = state;//constructor to pass the
}
@Override
public void init(GameContainer arg0, StateBasedGame arg1)
throws SlickException {
TILE_SIZE = 32;//initialization
esc = false;
map = new TiledMap("res/map/map.tmx");
cUp = false;
cDown = false;
cLeft = false;
cRight = false;
x = 2 * TILE_SIZE;//see the map
y = 1 * TILE_SIZE;
vel = .1f;
objLayer = map.getLayerIndex("Objects");//get the layer
jump = new Sound("res/sound/jump.wav");
obj = new int[10][10];//initialize the 2d array to store the blocked tiles
for(int col = 0; col < 10;col++){
for(int row = 0;row < 10;row++){
obj[col][row] = map.getTileId(col, row, objLayer);
}
}
}
@Override
public void render(GameContainer arg0, StateBasedGame arg1, Graphics g)
throws SlickException {
map.render(0, 0);//render only the map and a white rectangle (player)
g.fillRect(x, y, TILE_SIZE, TILE_SIZE);
}
@Override
public void update(GameContainer gc, StateBasedGame sbg, int delta)
throws SlickException {
input = gc.getInput();//get input
if(esc){//somehting about the menu , ignore it!
Mouse.setGrabbed(false);
}else{
Mouse.setGrabbed(true);
}
if(input.isKeyPressed(Input.KEY_ESCAPE)){
esc = true;
}
if(esc){
Mouse.setGrabbed(false);
if(input.isKeyPressed(Input.KEY_R)){
esc = false;
}else if(input.isKeyPressed(Keyboard.KEY_Q)){
System.exit(0);
}else if(input.isKeyPressed(Keyboard.KEY_M)){
esc = false;
sbg.enterState(0);
Mouse.setGrabbed(false);
}
}
//calculate collisions
AABB();
//TODO -- FIX COLLISIONS , thats what we need to do :/
if(input.isKeyDown(Input.KEY_RIGHT)){//arrow keys, check if player can move and decide, see AABB() method!
if(cRight){
x += vel * delta;
}
}
if(input.isKeyDown(Input.KEY_LEFT)){
if(cLeft){
x -= vel * delta;
}
}
if(input.isKeyDown(Input.KEY_UP)){
if(cUp){
y -= vel * delta;
}
}
if(input.isKeyDown(Input.KEY_DOWN)){
if(cDown){
y += vel * delta;
}
}
}
@Override
public int getID() {//get the id of the class
return state;
}
private void AABB(){
cLeft = false;//re-initialize
cRight = false;
cUp = false;
cDown = false;
tileX = (int) Math.round(Math.ceil(x / TILE_SIZE));//get the tile of the player
tileY = (int) Math.round(Math.ceil(y / TILE_SIZE));
int diffX = (int) Math.round(Math.ceil(x % TILE_SIZE));//get the remainder , sorry for the name
int diffY = (int) Math.round(Math.ceil(y % TILE_SIZE));
int HALF_TILE_SIZE = 32 / 2;//get half the tile size
//Start handling collisions
if(diffX == HALF_TILE_SIZE){//if the player is actually on a number that can be divided by 32 without remainder , do a simple up/down check
if(obj[tileX][tileY - 1] == 0){
cUp = true;
}
if(obj[tileX][tileY + 1] == 0){
cDown = true;
}
}else{
if(diffX > HALF_TILE_SIZE){//if it is not , check the other nearby squares.Here because diffX > HALF_TILE_SIZE , I get the one near these tiles. its obj[numberoftilex][numberoftiley] to get the tile's id. it returns 0 if it is empty.
if(obj[tileX][tileY - 1] == 0 && obj[tileX + 1][tileY - 1] == 0){
cUp = true;
}
if(obj[tileX][tileY + 1] == 0 && obj[tileX + 1][tileY + 1] == 0){
cDown = true;
}
}else if(diffX < HALF_TILE_SIZE){
if(obj[tileX][tileY - 1] == 0 && obj[tileX - 1][tileY - 1] == 0){
cUp = true;
}
if(obj[tileX][tileY + 1] == 0 && obj[tileX - 1][tileY + 1] == 0){
cDown = true;
}
}
}
//same things done with X are done with Y
if(diffY == HALF_TILE_SIZE){
if(obj[tileX - 1][tileY] == 0){
cLeft = true;
}
if(obj[tileX + 1][tileY] == 0){
cRight = true;
}
}else{
if(diffY > HALF_TILE_SIZE){
if(obj[tileX - 1][tileY] == 0 && obj[tileX - 1][tileY - 1] == 0){
cLeft = true;
}
if(obj[tileX + 1][tileY] == 0 && obj[tileX + 1][tileY - 1] == 0){
cRight = true;
}
}else if(diffY < HALF_TILE_SIZE){
if(obj[tileX - 1][tileY] == 0 && obj[tileX - 1][tileY + 1] == 0){
cLeft = true;
}
if(obj[tileX + 1][tileY] == 0 && obj[tileX + 1][tileY + 1] == 0){
cRight = true;
}
}
}
}
} //有帮助吗?
答案 0 :(得分:0)
我做出以下假设:
TILE_SIZE
,因此它跨越0到TILE_SIZE - 1
(TILE_SIZE/2 ,TILE_SIZE/2 )
相对于其左上角的像素的位置
我相信在AABB()
末尾添加以下代码块应该可以修复它:
if(diffX>HALF_TILE_SIZE){
cRight=true;
}else if(diffX<HALF_TILE_SIZE){
cLeft=true;
}
if(diffY>HALF_TILE_SIZE){
cDown=true;
}else if(diffY<HALF_TILE_SIZE){
cUp=true;
}
你忘了考虑如果玩家在右边,那么他们可以向左走。在上面的图片中,玩家应该能够向上,向左和向右移动;但是,您的代码不会考虑当前正方形中有可用空间来移动。