我目前正在开发Java rpg 游戏。我处于早期阶段,试图弄清楚游戏引擎,特别是平铺机制。游戏确实是由平铺组成的,玩家是静止的,而背景是移动的。我遇到了一个关于用于碰撞检测的二维数组的大问题。这是代码(请原谅长度):
package java4k;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
/**
*
* @author Christophe
*/
public class Main extends JFrame implements Runnable{
public Image dbImage;
public Graphics dbGraphics;
//Move Variables
int x = 320,y = 240, xDirection, yDirection;
//Sprites
BufferedImage spriteSheet;
//Lists for sprite sheet: 1 = STILL; 2 = MOVING_1; 3 = MOVING_2
BufferedImage[] ARCHER_NORTH = new BufferedImage[4];
BufferedImage[] ARCHER_SOUTH = new BufferedImage[4];
BufferedImage[] ARCHER_EAST = new BufferedImage[4];
BufferedImage[] ARCHER_WEST = new BufferedImage[4];
Image[] TILE = new Image[4];
//Animation Variables
int currentFrame = 0, framePeriod = 150;
long frameTicker = 0l;
Boolean still = true;
Boolean MOVING_NORTH = false, MOVING_SOUTH = false, MOVING_EAST = false, MOVING_WEST = false;
BufferedImage player = ARCHER_SOUTH[0];
//World Tile Variables
//20 X 15 = 300 tiles
Rectangle[][] blocks = new Rectangle[20][15];
Image[][] blockImg = new Image[20][15];
int tileX = 0, tileY = 0;
Random r = new Random();
Rectangle playerRect = new Rectangle(x+4,y+20,32,20);
Rectangle checkRect;
//Map Navigation
static final byte PAN_UP = 0, PAN_DOWN = 1, PAN_LEFT = 2, PAN_RIGHT = 3;
public Main(){
this.setTitle("JAVA4K");
this.setSize(640,505);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
addKeyListener(new AL());
TILE[0] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_GRASS_1.png").getImage();
TILE[1] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_GRASS_2.png").getImage();
TILE[2] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_GRASS_3.png").getImage();
TILE[3] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_WATER_1.png").getImage();
loadTiles();
init();
}
//First called to store image tiles in blockImg[][] and tile rectangles in blocks[][]
private void loadTiles(){
tileX = tileY = 0;
for(int i = 0; i < 20; i++){
for(int j = 0; j < 15; j++){
if(tileX>=640){
tileX = 0;
tileY += 32;
}
blockImg[i][j] = TILE[r.nextInt(4)];
blocks[i][j] = new Rectangle(tileX, tileY, 32, 32);
tileX += 32;
}
}
System.out.println(blocks[2][0]);
}
//collision detection
public boolean collide(Rectangle in)
{
for (int y = (int)((in.y) / 32)-1; y <= (int)((in.y+in.height) / 32)+1; y++){
for (int x = (int)((in.x) / 32)-1; x <= (int)((in.x+in.width) / 32)+1; x++){
if (x >= 0 && y >= 0 && x < 32 && y < 32){
if (blockImg[x][y] != null)
{
checkRect.setBounds(x*32,y*32, 32, 32);
if (in.intersects(checkRect))
{
return true;
}
}
}
}
}
return false;
}
//Key Listener
public class AL extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keyInput = e.getKeyCode();
still = false;
if(keyInput == e.VK_LEFT){
navigateMap(PAN_RIGHT);
MOVING_WEST = true;
}if(keyInput == e.VK_RIGHT){
navigateMap(PAN_LEFT);
MOVING_EAST = true;
}if(keyInput == e.VK_UP){
navigateMap(PAN_DOWN);
MOVING_NORTH = true;
}if(keyInput == e.VK_DOWN){
navigateMap(PAN_UP);
MOVING_SOUTH = true;
}
}
public void keyReleased(KeyEvent e){
int keyInput = e.getKeyCode();
setXDirection(0);
setYDirection(0);
still = true;
MOVING_SOUTH = false;
MOVING_NORTH = MOVING_SOUTH = MOVING_EAST = MOVING_WEST = false;
if(keyInput == e.VK_LEFT){
player = ARCHER_WEST[0];
}if(keyInput == e.VK_RIGHT){
player = ARCHER_EAST[0];
}if(keyInput == e.VK_UP){
player = ARCHER_NORTH[0];
}if(keyInput == e.VK_DOWN){
player = ARCHER_SOUTH[0];
}
}
}
public void moveMap(){
for(Rectangle[] r : blocks){
for(Rectangle r2 : r){
r2.x += xDirection;
r2.y += yDirection;
}
}
}
public void navigateMap(byte pan){
switch(pan){
default:
System.out.println("Unrecognized pan!");
break;
case PAN_UP:
setYDirection(-1);
break;
case PAN_DOWN:
setYDirection(+1);
break;
case PAN_LEFT:
setXDirection(-1);
break;
case PAN_RIGHT:
setXDirection(+1);
break;
}
}
//Animation Update
public void update(long gameTime) {
if (gameTime > frameTicker + framePeriod) {
frameTicker = gameTime;
currentFrame++;
if (currentFrame >= 4) {
currentFrame = 0;
}
}
if(MOVING_NORTH) player = ARCHER_NORTH[currentFrame];
if(MOVING_SOUTH) player = ARCHER_SOUTH[currentFrame];
if(MOVING_EAST) player = ARCHER_EAST[currentFrame];
if(MOVING_WEST) player = ARCHER_WEST[currentFrame];
}
public void setXDirection(int xdir){
xDirection = xdir;
}
public void setYDirection(int ydir){
yDirection = ydir;
}
//Method to get sprites
public BufferedImage grabSprite(int x, int y, int width, int height){
BufferedImage sprite = spriteSheet.getSubimage(x, y, width, height);
return sprite;
}
private void init(){
spriteSheet = null;
try {
spriteSheet = loadImage("ARCHER_SPRITESHEET.png");
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
for(int i = 0; i <= 3; i++){
ARCHER_NORTH[i] = grabSprite(i*16, 16, 16,16);
ARCHER_SOUTH[i] = grabSprite(i*16, 0, 16, 16);
ARCHER_EAST[i] = grabSprite(i*16, 32, 16, 16);
ARCHER_WEST[i] = grabSprite(i*16, 48, 16, 16);
}
}
public BufferedImage loadImage(String pathRelativeToThis) throws IOException{
URL url = this.getClass().getResource(pathRelativeToThis);
BufferedImage img = ImageIO.read(url);
return img;
}
public void paint(Graphics g){
dbImage = createImage(getWidth(), getHeight());
dbGraphics = dbImage.getGraphics();
paintComponent(dbGraphics);
g.drawImage(dbImage, 0, 25, this);
}
public void paintComponent(Graphics g){
requestFocus();
//Draws tiles and rectangular boundaries for debugging
for(int a = 0; a < 20; a++){
for(int b = 0; b < 15; b++){
if(blockImg[a][b] != null && blocks[a][b] != null){
g.drawImage(blockImg[a][b], blocks[a][b].x, blocks[a][b].y, 32, 32, null);
g.drawRect(blocks[a][b].x, blocks[a][b].y, 32, 32);
}
}
}
//Draw player and rectangular boundary for collision detection
g.drawRect(playerRect.x, playerRect.y, playerRect.width, playerRect.height);
g.drawImage(player, x, y, 40, 40, null);
repaint();
}
public void run(){
try{
while(true){
moveMap();
if(!still) update(System.currentTimeMillis());
Thread.sleep(13);
}
}catch(Exception e){
System.out.println("RUNTIME ERROR: " + e);
}
}
public static void main(String[] args) {
Main main = new Main();
//Threads
Thread thread1 = new Thread(main);
thread1.start();
}
}
我的错误如下:如果我要从 blocks[][] (一个存储用于碰撞检测的矩形的二维数组)中调用一个对象,它会给我带来完全不同的东西。例如,我取blocks[0][0]
(注意每个图块是一个 32 像素的正方形)。这个矩形的坐标是0,0
。但是,如果我要绘制块 [1][0],这在逻辑上会给我(32;0)
,它会返回(480;0)
。我几乎把头发拉出来试图找到造成这种情况的原因,我猜这是由于blocks[].x
在某个地方被改变了,但我找不到在哪里。我试过打印出每个值blocks[][]
在 draw 方法中查看问题在哪里,出于某种原因,在 loadTiles() 中一切都很好,突然间一切都搞砸了。提前感谢您的帮助,我希望我提供了足够的信息:)!