1

私は現在 Java RPG ゲームを開発しています。私は初期段階にあり、ゲーム エンジン、特にタイリング メカニズムを理解しようとしています。ゲームは確かにタイリングで構成されており、背景が動いている間、プレイヤーは静止しています。衝突検出用の 2 次元配列に関する大きな問題に遭遇しました。コードは次のとおりです (長さはご容赦ください)。

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();
    }
}

私のエラーは次のとおりです。ブロック[] [](衝突検出のために長方形を格納する2次元配列)からオブジェクトを呼び出すと、まったく異なる結果が得られます。たとえば、blocks[0][0](各タイルは 32 ピクセルの正方形であることに注意してください)。この長方形の座標は になります0,0。ただし、ブロック[1][0]を描画すると、論理的(32;0)に が返され、 が返され(480;0)ます。どこかで変更されたことが原因だと推測してblocks[].xいますが、どこかを見つけることができません。のすべての値を出力してみましたblocks[][]draw メソッドで問題の場所を確認し、何らかの理由で loadTiles() ですべて問題なく、突然すべてが台無しになります。事前にご協力いただきありがとうございます。十分な情報を提供できたことを願っています :)!

4

1 に答える 1