无法让精灵与地图图像发生冲突 (java)



我正在创建一个 2D 游戏,僵尸使用 WASD 键移动,应该与墙壁碰撞而不是进入它们,以及与大脑碰撞并移除它们。我使用的每种类型的代码都不会产生冲突。我正在使用我在谷歌上找到的僵尸精灵表以及 2 张用于墙壁和大脑的无背景图像。

在我弄清楚碰撞之后,我然后实现一个自动运行序列,让它像屏幕保护程序一样弹跳,并自动做同样的事情,直到收集到所有的大脑。

EZ只是UH Manoa使用的一个库,可以在这里找到:EZ Graphics

主要

import java.awt.Color;
import java.io.FileReader;
import java.util.Scanner;
public class ZombieMain {
    static EZImage[] walls = new EZImage[500];
    static EZImage[] sideWalls = new EZImage[500];
    static EZImage[] brains = new EZImage[50];
    static int wallsCount = 0;
    static int sideWallsCount = 0;
    static int brainsCount = 0;
    /*public static void addWall(EZImage wall) {
        walls[wallsCount] = wall;
        wallsCount++;
    }
    public static void addCoin(EZImage brain) {
        brains[brainsCount] = brain;
        brainsCount++;
    }*/
    /*public static void CollisingCoin(EZImage me) {
        int x = me.getXCenter();
        int y = me.getYCenter();
        for (int i = 0; i < brainsCount; i++) {
            if ((brains[i].isPointInElement(me.getXCenter() - 30, me.getYCenter() - 30))
                    || (brains[i].isPointInElement(me.getXCenter() + 30, me.getYCenter() - 30))
                    || (brains[i].isPointInElement(me.getXCenter() - 30, me.getYCenter() + 30))
                    || (brains[i].isPointInElement(me.getXCenter() + 30, me.getYCenter() + 30))) {
                brains[i].translateTo(-20, -20);
                System.out.println("You ate a brain!");
            }
        }
    }*/
    public static void main(String[] args) throws java.io.IOException {
        //initialize scanner
        Scanner fScanner = new Scanner(new FileReader("boundaries.txt"));
        int w = fScanner.nextInt();
        int h = fScanner.nextInt();
        String inputText = fScanner.nextLine();
        //create backdrop
        EZ.initialize(w*33,h*32);
        EZ.setBackgroundColor(new Color(0, 0,0));
        Zombie me = new Zombie("zombieSheet.png", 650, 450, 65, 63, 10);

        //set reading parameters and establish results of case readings
        int row = 0;
        while(fScanner.hasNext()) {
            inputText = fScanner.nextLine();
            for (int column = 0; column < inputText.length(); column++){
                char ch = inputText.charAt(column);
                switch(ch){
                case 'W':
                    walls[wallsCount] = EZ.addImage("barbwire.jpg", column*32, row*32);
                    wallsCount++;
                    break;      
                case 'M':
                    sideWalls[wallsCount] = EZ.addImage("barb.jpg", column*32, row*32);
                    wallsCount++;
                    break;
                case 'B':
                    brains[brainsCount] = EZ.addImage("brains.png", column*32, row*32);
                    brainsCount++;
                    break;
                default:
                    // Do nothing
                    break;
                }
                //printed count of walls, side walls, and brains
                System.out.println("W = " + wallsCount);
                System.out.println("M = " + sideWallsCount);
                System.out.println("B = " + brainsCount);
            }
            row++;
        }
        fScanner.close();
        while (true) {
            // check if going to collide with wall
            // we want to check this before we actually move
            // otherwise, we get "stuck" in a situation where we can't move
            // if no collision, we can move
            /*if (EZInteraction.isKeyDown('a')) {
                if (!isCollisingWall(me, -2, 0)) {
                    me.translateBy(-2, 0);
                }
            } else if (EZInteraction.isKeyDown('d')) {
                if (!isCollisingWall(me, 2, 0)) {
                    me.translateBy(2, 0);
                }
            } else if (EZInteraction.isKeyDown('w')) {
                if (!isCollisingWall(me, 0, -2)) {
                    me.translateBy(0, -2);
                }
            } else if (EZInteraction.isKeyDown('s')) {
                if (!isCollisingWall(me, 0, 2)) {
                    me.translateBy(0, 2);
                }
            }*/
            me.go();
            EZ.refreshScreen();
        }
    }
}

精灵

public class Zombie {
    EZImage zombieSheet;
    int x = 0;              // Position of Sprite
    int y = 0;
    int zombieWidth;        // Width of each sprite
    int zombieHeight;       // Height of each sprite
    int direction = 0;      // Direction character is walking in
    int walkSequence = 0;   // Walk sequence counter
    int cycleSteps;         // Number of steps before cycling to next animation step
    int counter = 0;        // Cycle counter

    Zombie(String imgFile, int startX, int startY, int width, int height, int steps) {
        x = startX;                 // position of the sprite character on the screen
        y = startY;
        zombieWidth = width;        // Width of the sprite character
        zombieHeight = height;      // Height of the sprite character
        cycleSteps = steps;         // How many pixel movement steps to move before changing the sprite graphic
        zombieSheet = EZ.addImage(imgFile, x, y);
        setImagePosition();
    }
    private void setImagePosition() {
        // Move the entire sprite sheet
        zombieSheet.translateTo(x, y);
        // Show only a portion of the sprite sheet.
        // Portion is determined by setFocus which takes 4 parameters:
        // The 1st two numbers is the top left hand corner of the focus region.
        // The 2nd two numbers is the bottom right hand corner of the focus region.
        zombieSheet.setFocus(walkSequence * zombieWidth, direction, walkSequence * zombieWidth + zombieWidth, direction + zombieHeight);
    }
    public void moveDown(int stepSize) {
        y = y + stepSize;
        direction = 0;
        if ((counter % cycleSteps) == 0) {
            walkSequence++;
            if (walkSequence > 6)
                walkSequence = 0;
        }
        counter++;
        setImagePosition();
    }
    public void moveLeft(int stepSize) {
        x = x - stepSize;
        direction = zombieHeight * 2;
        if ((counter % cycleSteps) == 0) {
            walkSequence--;
            if (walkSequence < 0)
                walkSequence = 6;
        }
        counter++;
        setImagePosition();
    }
    public void moveRight(int stepSize) {
        x = x + stepSize;
        direction = zombieHeight;
        if ((counter % cycleSteps) == 0) {
            walkSequence++;
            if (walkSequence > 6)
                walkSequence = 0;
        }
        counter++;
        setImagePosition();
    }
    public void moveUp(int stepSize) {
        y = y - stepSize;
        direction = zombieHeight * 3;
        if ((counter % cycleSteps) == 0) {
            walkSequence--;
            if (walkSequence < 0)
                walkSequence = 6;
        }
        setImagePosition();
        counter++;
    }

    // Keyboard controls for moving the character.
    public void go() {
        if (EZInteraction.isKeyDown('w')) {
            moveUp(2);
        } else if (EZInteraction.isKeyDown('a')) {
            moveLeft(2);
        } else if (EZInteraction.isKeyDown('s')) {
            moveDown(2);
        } else if (EZInteraction.isKeyDown('d')) {
            moveRight(2);
        }
    }
    public void translateBy(int i, int j) {
        // TODO Auto-generated method stub
    }
    public int getXCenter() {
        // TODO Auto-generated method stub
        return x;
    }
    public int getYCenter() {
        // TODO Auto-generated method stub
        return y;
    }
    public int getWidth() {
        // TODO Auto-generated method stub
        return 0;
    }
    public int getHeight() {
        // TODO Auto-generated method stub
        return 0;
    }

}

EZElement提供了一个getBounds属性,该属性返回一个java.awt.Shape对象;为什么这很重要?因为Java 2D Graphics API已经提供了一些命中检测。

由此,我们需要确定玩家形状与任何其他形状的交集。为此,我们需要将两个形状包裹在Area中,并使用它来做出最终决定。

Area meArea = new Area(me.getBounds());
Area checkArea = new Area(elementToCheck.getBounds());
checkArea(meArea);
if (!checkArea.isEmpty()) {
    //... We have collision
}

显然,这一切都应该包含在某种处理核心功能的方法中,但是您可以有一个辅助方法,该方法只需两个EZElement,如果发生冲突,则返回true/false

为了简洁和测试,我删除了您的示例,但基本思想应该继续有效

import java.awt.Color;
import java.awt.Shape;
import java.awt.geom.Area;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test {
    private List<EZImage> brains = new ArrayList<>(25);
    private Zombie me;
    public static void main(String[] args) throws java.io.IOException {
        new Test();
    }
    public Test() {
        int w = 10;
        int h = 10;
        //create backdrop
        EZ.initialize(w * 33, h * 32);
        EZ.setBackgroundColor(new Color(0, 0, 0));
        me = new Zombie("Zombie.png", 0, 0);
        brains.add(EZ.addImage("Brains.png", (w * 33) / 2, (h * 32 / 2)));
        while (true) {
            detectCollision();
            // check if going to collide with wall
            // we want to check this before we actually move
            // otherwise, we get "stuck" in a situation where we can't move
            // if no collision, we can move
            /*if (EZInteraction.isKeyDown('a')) {
                        if (!isCollisingWall(me, -2, 0)) {
                            me.translateBy(-2, 0);
                        }
                    } else if (EZInteraction.isKeyDown('d')) {
                        if (!isCollisingWall(me, 2, 0)) {
                            me.translateBy(2, 0);
                        }
                    } else if (EZInteraction.isKeyDown('w')) {
                        if (!isCollisingWall(me, 0, -2)) {
                            me.translateBy(0, -2);
                        }
                    } else if (EZInteraction.isKeyDown('s')) {
                        if (!isCollisingWall(me, 0, 2)) {
                            me.translateBy(0, 2);
                        }
                    }*/
            me.go();
            EZ.refreshScreen();
        }
    }
    public boolean doesCollide(EZElement element, EZElement with) {
        Area a = new Area(element.getBounds());
        Area b = new Area(with.getBounds());
        a.intersect(b);
        return !a.isEmpty();
    }
    public void detectCollision() {
        Iterator<EZImage> obstacles = brains.iterator();
        while (obstacles.hasNext()) {
            EZElement next = obstacles.next();
            if (doesCollide(me.zombieSheet, next)) {
                System.out.println("Me = " + me.getBounds().getBounds());
                System.out.println("next = " + next.getBounds().getBounds());
                EZ.removeEZElement(next);
                obstacles.remove();
            }
        }
    }
    public class Zombie {
        EZImage zombieSheet;
        int x = 0;              // Position of Sprite
        int y = 0;
        Zombie(String imgFile, int startX, int startY) {
            x = startX;                 // position of the sprite character on the screen
            y = startY;
            zombieSheet = EZ.addImage(imgFile, x, y);
            setImagePosition();
        }
        public Shape getBounds() {
            return zombieSheet.getBounds();
        }
        private void setImagePosition() {
            // Move the entire sprite sheet
            zombieSheet.translateTo(x, y);
        }
        public void moveDown(int stepSize) {
            y = y + stepSize;
            setImagePosition();
        }
        public void moveLeft(int stepSize) {
            x = x - stepSize;
            setImagePosition();
        }
        public void moveRight(int stepSize) {
            x = x + stepSize;
            setImagePosition();
        }
        public void moveUp(int stepSize) {
            y = y - stepSize;
            setImagePosition();
        }
        // Keyboard controls for moving the character.
        public void go() {
            if (EZInteraction.isKeyDown('w')) {
                moveUp(2);
            } else if (EZInteraction.isKeyDown('a')) {
                moveLeft(2);
            } else if (EZInteraction.isKeyDown('s')) {
                moveDown(2);
            } else if (EZInteraction.isKeyDown('d')) {
                moveRight(2);
            }
        }
    }
}

我建议您给每个实体(和块/瓦片)一个碰撞框,然后测试特定实体的边界框是否与另一个实体的边界框发生冲突,然后使实体无法向该方向移动,直到某个方向上没有边界框,如果此后有任何边界框。
对大脑进行测试也做同样的事情,尽管我建议制作一个大脑的ArrayList,如果大脑被触摸过,则删除特定的大脑。

最新更新