如何制作无限平铺地图? (Java)的

时间:2012-09-03 19:44:05

标签: java image swing awt

我正在制作平铺地图,我遇到了这个问题: 当我移动我的角色时,它会离开地图然后掉落(由于重力) 如何使这张地图无限? 而且,我如何存储哪些块被销毁,哪些块不被销毁?所以我可以使用相同的地图重新绘制屏幕,​​当你走回起点时,brocken块仍然存在。

告诉我是否需要提供代码。

我会给你我的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;
        }
    }
}

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

在基本级别,您需要一个3维数组来存储每个块。问题是,这不会让你成为一个“无限”的世界,它会让你受限于记忆。

Notch通过使用“Chunks”来解决它 - 这是一个固定大小的3D数组,可以在必要时交换到磁盘。

您还应该了解如何使用位来打包存储,对于任何需要它的大型存储 - 例如,每个块可以保存为3位,2个用于块,另外一个用于“已损坏” 。如果你使用这个而不是一个字节数组,你将使用少于1/2的存储空间,这意味着你可能需要从磁盘中读取另一个块之前在你的世界中走两倍。

如果你想更简单地介绍编写这种应用程序,那么请看一下使用Bukkit编写一个minecraft mod - 大部分细节工作都是为你处理的,你实际上可以掌握很多关于如何完成工作的知识在尝试从头开始编写Minecraft克隆之前。

答案 1 :(得分:0)

所以你需要的本质上是一个二维数据结构,它可以无限期地扩展(或直到内存耗尽)到两个维度。

有很多方法可以解决这个问题。

一种方法是二维双链表(双链网?),其中每个地图图块都有对四个相邻图块的引用。这意味着您可以跟踪视口中心的图块,并通过迭代到所有四个方向来渲染场景,直到您离开屏幕。当您点击未初始化的磁贴时,就可以生成它了。