1

如何在基于图块的游戏中检查碰撞?我查看了 android SDK 的示例,但我无法理解它们,因为我是 Android 编程新手。

这是我的英雄学习的地图和瓷砖类,所以我可以在世界各地移动他

 class Map{
    int X = 0;
    int Y = 0; 
    int tileSize = 30;

    int [][]map= {
            //0 = empty tile
            //1 = wall
            //2 = player
            {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
            {1,0,0,0,0,0,1,1,2,1,1,0,0,0,0,0,1},
            {1,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1},
            {1,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1},
            {1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1},
            {1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1},
            {1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1},
            {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
            {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
            };



    ArrayList<Tile> tiles = new ArrayList<Tile>();;

    public Map(){
        loadArray();
    }

    public void loadArray(){

        for(int xTiles = 0; xTiles< map.length; xTiles++ ){
            for(int yTiles = 0; yTiles< map[xTiles].length; yTiles++){
                if(map[xTiles][yTiles]==1){//Wall
                tiles.add(new Tile(X, Y, tileSize, map[xTiles][yTiles]));
                tiles.get(tiles.size()-1).setColor(Color.GRAY);
                tiles.get(tiles.size()-1).walkable = false;
                X+=tileSize;
                }else if(map[xTiles][yTiles]==0){//Empty Tile
                    tiles.add(new Tile(X, Y, tileSize, map[xTiles]      [yTiles]));
                X+=tileSize;
                }else if(map[xTiles][yTiles]==2){//Player 
                    tiles.add(new Tile(X, Y, tileSize, map[xTiles][yTiles]));
                X+=tileSize;    
                }
            }
            Y+=tileSize;
            X=0;
            }
        }

    public void drawMap(Canvas canvas){
    for(int index = 0; index < tiles.size(); index++){
        tiles.get(index).drawTile(canvas);
    }
}

}

    class Tile{
    private int type;
    int X;
    int Y;
    int size;
    boolean walkable = true;
    Paint color = new Paint();;
    //rect for the bounds
    Rect bounds = new Rect();

    public Tile(){
        type = 0;
        X = 0;
        Y = 0;
        size = 0;
        color.setColor(Color.TRANSPARENT);
        bounds.set(X, Y, X+size, Y+size);

    }



    public Tile(int X, int Y , int tileSize, int type){
        this.type = type;
        this.X = X;
        this.Y = Y;
        size = tileSize;
        color.setColor(Color.TRANSPARENT);
        bounds.set(X, Y, X+size, Y+size);
    }



    public int getX() {
        return X;
    }



    public int getY() {
        return Y;
    }



    public void setX(int x) {
        X = x;
    }



    public void setY(int y) {
        Y = y;
    }



    public int getType() {
        // TODO Auto-generated method stub
        return type;
    }
    public Paint getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color.setColor(color);
    }

    public void drawTile(Canvas canvas){
        canvas.drawRect(bounds, color);
    }
}

这是我的英雄课

 class Hero{
    private static final int SIZE = 30;
    //Coordinates 
    int X = 60;
    int Y = 60;
    int sx=30, sy=30;
    private Paint paint = new Paint();
    public Rect Bounds = new Rect(X,Y,X+30,Y+30);
    boolean solid = true;

    //Map Things
    Map map;

    public Hero(Map map){
        this.map = map;
        paint.setColor(Color.RED);
        paint.setStyle(Style.FILL_AND_STROKE);

        location();
    }




    private void location() {

        for(int index = 0; index<map.tiles.size(); index++){
            if(map.tiles.get(index).getType() == 2){
                this.X = map.tiles.get(index).getX();
                this.Y = map.tiles.get(index).getY();

            }
        }

    }




    public void move(int KeyCode) {
        switch(KeyCode){

        case KeyEvent.KEYCODE_DPAD_DOWN:
            {if(Collision()){Y+=sy;} break;}
        case KeyEvent.KEYCODE_DPAD_UP:
            {Y-=sy; break;}
        case KeyEvent.KEYCODE_DPAD_LEFT:
            {X-=sx; break;}
        case KeyEvent.KEYCODE_DPAD_RIGHT:
            {X+=sx; break;}
        }

    }







    private boolean Collision() {
        for(int index = 0; index< map.tiles.size(); index++){
            if(Rect.intersects(map.tiles.get(index).bounds, this.Bounds)){
                return map.tiles.get(index).walkable;}  
        }
        return false;
    }




    public int getX() {
        return X;
    }



    public int getY() {
        return Y;
    }



    public void setX(int x) {
        X = x;
    }



    public void setY(int y) {
        Y = y;
    }


    public void position(int x, int y){
        X = x;
        Y = y;

    }

    public void update(){
        Bounds.set(X, Y, (X+SIZE), (Y+SIZE));

    }


    public void Draw(Canvas canvas){
        canvas.drawRect(Bounds, paint);
        canvas.drawText("Player", Bounds.left, Bounds.top-5, paint);
    }
}

如何检查碰撞?我应该循环每一个瓷砖然后检查玩家的新坐标是否会发生碰撞?

这可能不是正确的方法,但它有效。我为每个移动方向向右,向左,向上和向下添加了方法,如下所示

private void moveLeft() {
    for(int index = 0 ; index < map.tiles.size();index++){
        if(yCoord-1 == map.tiles.get(index).yCoord && xCoord == map.tiles.get(index).xCoord){
            if(map.tiles.get(index).walkable){  
            X-=SIZE;
                //My coordinates are flipped for some reason my Xs are Ys and Ys are Xs
                yCoord-=1;
                break;
            }
        }
    }

}
4

2 回答 2

2

您必须记录英雄的最后位置,在每次移动事件中,您可以检查相对于英雄方向的下一个图块。正如您在二维矩阵中实现的那样,因此,如果英雄的位置是地图 [0] [0] 并且玩家一次下降了一个位置,那么地图中的相对位置即地图 [1] [0]。这样你就可以最大限度地减少比较。每个方向都有二维权重,例如up movement can have [CurrentPosition.x-1] [CurrentPosition.y-1], Left can have [CurrentPosition.x] [CurrentPosition.y+1] etc....

于 2012-09-29T01:02:16.150 回答
0

如果您指的是检查您的瓷砖是否“可行走”,那么每次您的玩家决定移动英雄时(因此可能是在移动操纵杆或点击时)您需要确定您的英雄将在哪个瓷砖上,然后检查该图块以查看它是否已将 walkable 设置为 true。您的代码已经很好地实现了这一目标。

如果您指的是与其他实体(例如 NPC)的碰撞,那么当玩家决定移动英雄并确定新位置是​​否与其中一个实体的位置相同时,您将需要获取每个实体的位置可碰撞的实体。

类似于以下内容:

case KeyEvent.KEYCODE_DPAD_DOWN: {
int target = hero.getY() + 1;
if(map.getTile(hero.getX(), target).isWalkable())
   hero.setY(target);
break;
}
于 2012-09-29T00:36:50.750 回答