0

タイル マップを作成していて、この問題に遭遇しました。キャラクターを移動すると、マップから外れて落下します (重力により)。このマップを無限にするにはどうすればよいですか? また、どのブロックが破壊され、どのブロックが破壊されていないかをどのように保存しますか? 同じマップで画面を再描画できるように、出発点に戻るとブロッケン ブロックがまだそこにあります。

コードを提供する必要があるかどうか教えてください。

私のworld.javaをあげます

package game.test.src;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;

import javax.swing.ImageIcon;

public class World {

    public Rectangle[] blocks;
    public boolean[] isSolid;
    public Image[] blockImg;
    public final int arrayNum = 500;

    //Block Images
    public Image BLOCK_GRASS, BLOCK_DIRT, BLOCK_STONE, BLOCK_SKY;

    private int x, y, xDirection, yDirection;;

    //map navigation
    static final int PAN_UP = 0, PAN_DOWN = 1, PAN_LEFT= 2, PAN_RIGHT = 3;

    public World(){
        BLOCK_GRASS = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_grass.png").getImage();
        BLOCK_DIRT = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_dirt.png").getImage();
        BLOCK_STONE = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_stone.png").getImage();
        BLOCK_SKY = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_sky.png").getImage();
        blocks = new Rectangle[500];
        blockImg = new Image[500];
        isSolid = new boolean[arrayNum];
        loadArrays();
    }

    private void loadArrays(){
        for(int i = 0; i < arrayNum; i++){
            if(x >= 500){
                x = 0;
                y += 20;
            }
            if(i >= 0 && i < 100){
                blockImg[i] = BLOCK_SKY;
                isSolid[i] = false;
                blocks[i] = new Rectangle(x, y, 20, 20);
            }
            if(i >= 100 && i < 125){
                blockImg[i] = BLOCK_GRASS;
                isSolid[i] = true;
                blocks[i] = new Rectangle(x, y, 20, 20);
            }
            if(i >= 125 && i < 225){
                blockImg[i] = BLOCK_DIRT;
                isSolid[i] = true;
                blocks[i] = new Rectangle(x, y, 20, 20);
            }
            if(i >= 225 && i < 500){
                blockImg[i] = BLOCK_STONE;
                isSolid[i] = true;
                blocks[i] = new Rectangle(x, y, 20, 20);
            }
            x += 20;
        }
    }

    public void draw(Graphics g){
        for(int i = 0; i < arrayNum; i++){
            g.drawImage(blockImg[i], blocks[i].x, blocks[i].y, null);
        }
    }

    public void moveMap(){
        for(Rectangle r : blocks){
            r.x += xDirection;
            r.y += yDirection;
        }
    }
    public void stopMoveMap(){
        setXDirection(0);
        setYDirection(0);
    }
    private void setXDirection(int dir){
        xDirection = dir;
    }
    private void setYDirection(int dir){
        yDirection = dir;
    }
    public void navigateMap(int nav){
        switch(nav){
            default:
                System.out.println("default case entered... Doing nothing.");
                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;
        }
    }
}

ここに私の Player.java があります

package game.test.src;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;

import javax.swing.ImageIcon;

public class Player {

    static final int MOVE_UP = 0, MOVE_DOWN = 1, MOVE_LEFT= 2, MOVE_RIGHT = 3;
    private World world;

    private Rectangle playerRect;
    private Image playerImg;

    //Block Variables
    private int hoverX, hoverY;
    private boolean hovering = false;

    protected static int xDirection;
    protected static int yDirection;
    private Weapon weapon;

    public Player(World world){
        this.world = world;
        playerImg = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/Character.png").getImage();
        playerRect = new Rectangle(50, 0, 10, 36);
        weapon = new Weapon(weapon.PICKAXE);
    }
    private static void setXDirection(int d){
        xDirection = d;

    }
    private static void setYDirection(int d){
        yDirection = d;

    }
    public void update()
    {
        move();
        checkForCollision();

    }
    private void checkForCollision() {



    }
    private void move()
    {
        playerRect.x += xDirection;
        playerRect.y += yDirection;
        gravity();
    }
    private void gravity()
    {
        for(int i=0;i<world.arrayNum; i++)
        {
            if(!world.isSolid[i])
            {
                setYDirection(1);

            }
            else if(world.isSolid[i] && playerRect.intersects(world.blocks[i]))
            {
                setYDirection(0);
            }
        }
    }
    //MotionEvents

    public void mousePressed(MouseEvent e)
    {

    }

    public void mouseReleased(MouseEvent e)
    {

    }

    public void mouseClicked(MouseEvent e)
    {

    }

    public void mouseMoved(MouseEvent e)
    {
        int x = e.getX();
        int y = e.getY();
        int px = playerRect.x;
        int py = playerRect.y;
        for(int i = 0; i < world.arrayNum; i++)
        {
            if(weapon.isEquipped(Weapon.PICKAXE) &&
                    x > world.blocks[i].x && x < world.blocks[i].x + world.blocks[i].width && 
                    y > world.blocks[i].x && y < world.blocks[i].y + world.blocks[i].height && world.isSolid[i] && 
                    (world.blocks[i].x + (world.blocks[i].width / 2) ) <= (px + playerRect.width/2) + weapon.WEAPON_RADIUS &&
                    (world.blocks[i].x + (world.blocks[i].width / 2) ) >= (px + playerRect.width/2) - weapon.WEAPON_RADIUS &&
                    (world.blocks[i].y + (world.blocks[i].height / 2) ) <= (py + playerRect.height/2) + weapon.WEAPON_RADIUS &&
                    (world.blocks[i].y + (world.blocks[i].height / 2) ) >= (py + playerRect.height/2) - weapon.WEAPON_RADIUS)

            {
                hovering = true;
                hoverX = world.blocks[i].x;
                hoverY = world.blocks[i].y;
                break;
            }
            else
                hovering = false;
        }
    }
    public void mouseDragged(MouseEvent e)
    {

    }
    public void mouseEntered(MouseEvent e)
    {

    }
    public void mouseExited(MouseEvent e)
    {

    }

    //Drawing Methods
    public void draw(Graphics g)
    {
        g.drawImage(playerImg, playerRect.x, playerRect.y, null);
        if(hovering)
            drawBlockOutline(g);

    }

    private void drawBlockOutline(Graphics g)
    {
        g.setColor(Color.black);
        g.drawRect(hoverX, hoverY, world.blocks[0].width,world.blocks[0].height);
    }



    private class Weapon
    {
        public static final int UNARMED = 0;
        public static final int PICKAXE = 1; 
        public static final int GUN = 2;

        public int CURRENT_WEAPON;

        public int WEAPON_RADIUS;

        public Weapon(int w)

        {
            switch(w)
            {
                default:
                    System.out.println("No weapon selected");
                    break;
                case UNARMED:
                    CURRENT_WEAPON = UNARMED;
                    WEAPON_RADIUS = 100;
                    break;

                case PICKAXE:
                    CURRENT_WEAPON = PICKAXE;
                    WEAPON_RADIUS = 100;
                    break;

                case GUN:
                    CURRENT_WEAPON = GUN;
                    WEAPON_RADIUS = 100;
                    break;

            }

        }

        public void selectWeapon(int w)
        {
            switch(w)
            {
                default:
                    System.out.println("No weapon selected");
                    break;
                case UNARMED:
                    CURRENT_WEAPON = UNARMED;
                    WEAPON_RADIUS = 100;
                    break;

                case PICKAXE:
                    CURRENT_WEAPON = PICKAXE;
                    WEAPON_RADIUS = 100;
                    break;

                case GUN:
                    CURRENT_WEAPON = GUN;
                    WEAPON_RADIUS = 100;
                    break;

            }

        }

        public boolean isEquipped(int w)

        {
            if(w == CURRENT_WEAPON)
            {
                return true;
            }
            else
                return false;



        }


    }
    public void moveMap(){
        for(Rectangle r : world.blocks){
            r.x += xDirection;
            r.y += yDirection;
        }
    }
    public static void stopMoveMap(){
        setXDirection(0);
        setYDirection(0);
    }
    private static void setXDirection1(int dir){
        xDirection = dir;
    }
    private static void setYDirection1(int dir){
        yDirection = dir;
    }

    public static void navigatePlayer(int nav){
        switch(nav){
            default:
                System.out.println("default case entered... Doing nothing.");
                break;
            case MOVE_UP:
                setYDirection1(-1);
                break;
            case MOVE_DOWN:
                setYDirection1(1);
                break;
            case MOVE_LEFT:
                setXDirection1(-1);
                break;
            case MOVE_RIGHT:
                setXDirection1(1);
                break;
        }
    }
}

助けてくれてありがとう!

4

2 に答える 2

0

基本的なレベルでは、すべてのブロックを格納するために3次元配列が必要です。問題は、それはあなたに「無限の」世界をもたらさないということです、それはあなたに記憶に制限された世界をあなたに与えるでしょう。

Notchは、必要に応じてディスクに交換できる固定サイズの3D配列である「チャンク」を使用して問題を解決しました。

また、ビットを使用してストレージをパックする方法についても学ぶ必要があります。たとえば、各ブロックは3ビットで保持でき、2つはブロック用、もう1つは「壊れた」ものです。バイト配列の代わりにこれを使用した場合、ストレージの使用量は1/2未満になります。つまり、ディスクから別のチャンクを読み取る必要が生じる前に、世界の2倍の距離に移動する可能性があります。

この種のアプリの作成をより簡単に紹介したい場合は、Bukkitを使用してMinecraft Modを作成することを検討してください。詳細な作業の多くは自動的に処理され、実際に作業を行う前に、作業がどのように行われるかについて多くの知識を得ることができます。 Minecraftのクローンを最初から作成します。

于 2012-09-03T19:54:31.923 に答える
0

したがって、必要なのは本質的に、無期限に (またはメモリがなくなるまで) 両方の次元に拡張できる 2 次元のデータ構造です。

この問題を解決する方法は無数にあります。

1 つの方法は、各マップ タイルが隣接する 4 つのタイルへの参照を持つ 2 次元の二重リンク リスト (二重リンク ネット?) です。つまり、ビューポートの中央にあるタイルを追跡し、画面を離れるまで 4 つの方向すべてに繰り返してシーンをレンダリングします。初期化されていないタイルにヒットしたら、それを生成します。

于 2012-09-03T20:00:24.057 に答える