我如何检查基于磁贴的Android游戏中的碰撞?

时间:2012-09-29 00:23:08

标签: java android

如何在基于图块的游戏中检查碰撞?我看过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);
    }
}

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

这可能不是正确的方法,但它有效。我为这个

添加了每个移动方向的方法Right,Left,Up和Down
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;
            }
        }
    }

}

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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;
}