我正在创建一个 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,如果大脑被触摸过,则删除特定的大脑。