简体   繁体   English

基于图块的游戏上的重复图块

[英]Duplicated tiles on tile-based game

I'm currently working on a tile-based game in Java with Java2D. 我目前正在使用Java2D用Java开发基于图块的游戏。 However, I think I'm missing something really stupid, or maybe not, the thing is that I checked my code thousands of times and I didn't saw anything weird. 但是,我想我确实缺少了一些愚蠢的东西,或者也许不是,那是因为我检查了我的代码数千次,没有发现任何奇怪的东西。 So this is the print of my game right now: 这是我现在的游戏画面:

But it should look something like this: 但它看起来应该像这样: 在此处输入图片说明

Well, I know, it looks fine but if you take a look at the image of my tile-based level: 好吧,我知道,它看起来不错,但是如果您看一下我基于图块的级别的图像:

(grays tiles are bricks, green tiles are grass and brown tiles are dirt) (灰色砖是砖,绿色砖是草,棕色砖是污垢)

So the bricks tiles are duplicated on some weird way. 因此,以某种奇怪的方式复制了砖块。 So, here is my Level code: 所以,这是我的等级代码:

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import com.wg.MainComponent;
import com.wg.entity.Entity;
import com.wg.entity.Particle;
import com.wg.entity.Projectile;
import com.wg.entity.mob.Mob;
import com.wg.entity.mob.Player;

public abstract class Level {

    public BufferedImage levelImage;
    public BufferedImage[][] tile;
    public Rectangle[][] rect;
    public int tileSize;
    public float xOffset, yOffset;
    public ArrayList<BufferedImage> collision = new ArrayList<BufferedImage>();

    public ArrayList<Player> players = new ArrayList<Player>();
    public ArrayList<Projectile> projectiles = new ArrayList<Projectile>();
    public ArrayList<Particle> particles = new ArrayList<Particle>();
    private List<Entity> entities = new ArrayList<Entity>();

    public BufferedImage[] tilesBufferedImages;
    public int[] xCollisionOffset;
    public int[] yCollisionOffset;

    public Level(BufferedImage levelImage, int tileSize, BufferedImage[] tilesBufferedImages, int[] xCollisionOffset, int[] yCollisionOffset) {
        this.tilesBufferedImages = tilesBufferedImages;
        this.xCollisionOffset = xCollisionOffset;
        this.yCollisionOffset = yCollisionOffset;

        this.levelImage = levelImage;
        this.tileSize = tileSize;

        tile = new BufferedImage[levelImage.getWidth()][levelImage.getHeight()];
        rect = new Rectangle[levelImage.getWidth()][levelImage.getHeight()];

        generateLevel();
    }

    public abstract void generateLevel();

    public void render(float xOffset, float yOffset, int scale, Graphics2D screen) {
        this.xOffset = xOffset;
        this.yOffset = yOffset;

        for (int y = (int) Math.max(yOffset / (tileSize + scale), 0); y < Math.min((MainComponent.height + yOffset) / (tileSize + scale) + 1, levelImage.getHeight()); y++) {
            for (int x = (int) Math.max(xOffset / (tileSize + scale), 0); x < Math.min((MainComponent.width + xOffset) / (tileSize + scale) + 1, levelImage.getWidth()); x++) {
                if (tile[x][y] != null)
                    screen.drawImage(tile[x][y], (int) (x * (tileSize + scale) - xOffset), (int) (y * (tileSize + scale) - yOffset), (tileSize + scale), (tileSize + scale), null);
            }
        }

        for (int i = 0; i < entities.size(); i++) {
            entities.get(i).render(screen);
        }

        for (int i = 0; i < players.size(); i++) {
            players.get(i).render(screen);
        }

        for (int i = 0; i < projectiles.size(); i++) {
            projectiles.get(i).render(screen);
        }

        for (int i = 0; i < particles.size(); i++) {
            particles.get(i).render(screen);
        }
    }

    public void add(Entity e) {
        if (e instanceof Particle) {
            particles.add((Particle) e);
        } else if (e instanceof Player) {
            players.add((Player) e);
        } else if (e instanceof Projectile) {
            projectiles.add((Projectile) e);
        } else {
            entities.add(e);
        }
    }

    public void update(int scale) {
        for (int y = 0; y < levelImage.getHeight(); y++) {
            for (int x = 0; x < levelImage.getWidth(); x++) {
                if (tile[x][y] != null && rect[x][y] == null) {
                    for (int i = 0; i < tilesBufferedImages.length; i++) {
                        if (tilesBufferedImages[i] == tile[x][y])
                            rect[x][y] = new Rectangle(x * (tileSize + scale) - Math.round(xOffset) + xCollisionOffset[i], y * (tileSize + scale) - Math.round(yOffset) + yCollisionOffset[i], (tileSize + scale) + xCollisionOffset[i], (tileSize + scale) + yCollisionOffset[i]);
                    }
                } else if (tile[x][y] != null && rect[x][y] != null) {
                    for (int i = 0; i < tilesBufferedImages.length; i++) {
                        if (tilesBufferedImages[i] == tile[x][y])
                            rect[x][y].setBounds(x * (tileSize + scale) - Math.round(xOffset) + xCollisionOffset[i], y * (tileSize + scale) - Math.round(yOffset) + xCollisionOffset[i], (tileSize + scale) + xCollisionOffset[i], (tileSize + scale) + yCollisionOffset[i]);
                    }
                }
            }
        }

        for (int i = 0; i < entities.size(); i++) {
            entities.get(i).update();
        }

        for (int i = 0; i < players.size(); i++) {
            players.get(i).update();
        }

        for (int i = 0; i < projectiles.size(); i++) {
            projectiles.get(i).update();
        }
        for (int i = 0; i < particles.size(); i++) {
            particles.get(i).update();
        }

        remove();
    }

    public List<Player> getPlayers() {
        return players;
    }

    public Player getPlayerAt(int index) {
        return players.get(index);
    }

    public Player getClientPlayer() {
        return players.get(0);
    }

    private void remove() {
        for (int i = 0; i < entities.size(); i++) {
            if (entities.get(i).isRemoved())
                entities.remove(i);
        }
        for (int i = 0; i < projectiles.size(); i++) {
            if (projectiles.get(i).isRemoved())
                projectiles.remove(i);
        }
        for (int i = 0; i < players.size(); i++) {
            if (players.get(i).isRemoved())
                players.remove(i);
        }
        for (int i = 0; i < particles.size(); i++) {
            if (particles.get(i).isRemoved())
                particles.remove(i);
        }
    }

    public boolean tileDownCollision(Mob en, boolean fixed) {
        Point p = null;
        if (fixed)
            p = new Point(Math.round(en.x), Math.round(en.y + en.height));
        else if (!fixed)
            p = new Point(Math.round(en.x - xOffset), Math.round(en.y + en.height - yOffset));
        try {
            for (int y = 0; y < levelImage.getHeight(); y++) {
                for (int x = 0; x < levelImage.getWidth(); x++) {
                    if (tile[x][y] != null) {
                        if (rect[x][y] != null && rect[x][y].contains(p)) {
                            if (collision.contains(tile[x][y]))
                                return true;
                        }
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
        }
        return false;
    }

    public boolean tileUpCollision(Mob en, boolean fixed) {
        Point p = null;
        if (fixed)
            p = new Point(Math.round(en.x), Math.round(en.y - 1));
        else if (!fixed)
            p = new Point(Math.round(en.x - xOffset), Math.round(en.y - 1 - yOffset));
        try {
            for (int y = 0; y < levelImage.getHeight(); y++) {
                for (int x = 0; x < levelImage.getWidth(); x++) {
                    if (tile[x][y] != null) {
                        if (rect[x][y] != null && rect[x][y].contains(p)) {
                            if (collision.contains(tile[x][y]))
                                return true;
                        }
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
        }
        return false;
    }

    public boolean tileLeftCollision(Mob en, boolean fixed) {
        Point p = null;
        if (fixed)
            p = new Point(Math.round(en.x - 1), Math.round(en.y));
        else if (!fixed)
            p = new Point(Math.round(en.x - 1 - xOffset), Math.round(en.y - yOffset));
        try {
            for (int y = 0; y < levelImage.getHeight(); y++) {
                for (int x = 0; x < levelImage.getWidth(); x++) {
                    if (tile[x][y] != null) {
                        if (rect[x][y] != null && rect[x][y].contains(p)) {
                            if (collision.contains(tile[x][y]))
                                return true;
                        }
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
        }
        return false;
    }

    public boolean tileRightCollision(Mob en, boolean fixed) {
        Point p = null;
        if (fixed)
            p = new Point(Math.round(en.x + en.width), Math.round(en.y));
        else if (!fixed)
            p = new Point(Math.round(en.x + en.width - xOffset), Math.round(en.y - yOffset));
        try {
            for (int y = 0; y < levelImage.getHeight(); y++) {
                for (int x = 0; x < levelImage.getWidth(); x++) {
                    if (tile[x][y] != null) {
                        if (rect[x][y] != null && rect[x][y].contains(p)) {
                            if (collision.contains(tile[x][y]))
                                return true;
                        }
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
        }
        return false;
    }

    public boolean projectileDownCollision(Projectile en, boolean fixed) {
        Point p = null;
        if (fixed)
            p = new Point(Math.round(en.x), Math.round(en.y + en.height));
        else if (!fixed)
            p = new Point(Math.round(en.x - xOffset), Math.round(en.y + en.height - yOffset));
        try {
            for (int y = 0; y < levelImage.getHeight(); y++) {
                for (int x = 0; x < levelImage.getWidth(); x++) {
                    if (tile[x][y] != null) {
                        if (rect[x][y] != null && rect[x][y].contains(p)) {
                            if (collision.contains(tile[x][y]))
                                return true;
                        }
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
        }
        return false;
    }

    public boolean projectileUpCollision(Projectile en, boolean fixed) {
        Point p = null;
        if (fixed)
            p = new Point(Math.round(en.x), Math.round(en.y - 1));
        else if (!fixed)
            p = new Point(Math.round(en.x - xOffset), Math.round(en.y - 1 - yOffset));
        try {
            for (int y = 0; y < levelImage.getHeight(); y++) {
                for (int x = 0; x < levelImage.getWidth(); x++) {
                    if (tile[x][y] != null) {
                        if (rect[x][y] != null && rect[x][y].contains(p)) {
                            if (collision.contains(tile[x][y]))
                                return true;
                        }
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
        }
        return false;
    }

    public boolean projectileLeftCollision(Projectile en, boolean fixed) {
        Point p = null;
        if (fixed)
            p = new Point(Math.round(en.x - 1), Math.round(en.y));
        else if (!fixed)
            p = new Point(Math.round(en.x - 1 - xOffset), Math.round(en.y - yOffset));
        try {
            for (int y = 0; y < levelImage.getHeight(); y++) {
                for (int x = 0; x < levelImage.getWidth(); x++) {
                    if (tile[x][y] != null) {
                        if (rect[x][y] != null && rect[x][y].contains(p)) {
                            if (collision.contains(tile[x][y]))
                                return true;
                        }
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
        }
        return false;
    }

    public boolean projectileRightCollision(Projectile en, boolean fixed) {
        Point p = null;
        if (fixed)
            p = new Point(Math.round(en.x + en.width), Math.round(en.y));
        else if (!fixed)
            p = new Point(Math.round(en.x + en.width - xOffset), Math.round(en.y - yOffset));
        try {
            for (int y = 0; y < levelImage.getHeight(); y++) {
                for (int x = 0; x < levelImage.getWidth(); x++) {
                    if (tile[x][y] != null) {
                        if (rect[x][y] != null && rect[x][y].contains(p)) {
                            if (collision.contains(tile[x][y]))
                                return true;
                        }
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
        }
        return false;
    }

    public boolean mobProjectileCollision(Mob en, Projectile pr, boolean fixed) {
        Rectangle p1 = null;
        if (fixed)
            p1 = new Rectangle(Math.round(en.x), Math.round(en.y), en.width, en.height);
        else if (!fixed)
            p1 = new Rectangle(Math.round(en.x - xOffset), Math.round(en.y - yOffset), en.width, en.height);

        Rectangle p2 = null;
        if (fixed)
            p2 = new Rectangle(Math.round(pr.x), Math.round(pr.y), pr.width, pr.height);
        else if (!fixed)
            p2 = new Rectangle(Math.round(pr.x - xOffset), Math.round(pr.y - yOffset), pr.width, pr.height);

        if (p1.intersects(p2))
            return true;

        return false;
    }

    public double calcDistance(Entity e1, Entity e2) {
        return Math.sqrt(((e1.x - e2.x) * (e1.x - e2.x)) + ((e1.y - e2.y) * (e1.y - e2.y)));
    }
}

The Level is rendered into the render(Graphics2D) method. 将关卡渲染到render(Graphics2D)方法中。 It is an abstract class so I have a subclass of it, Level1, in the case it is the one in the image. 它是一个抽象类,因此在它是图像中的一个的情况下,我有一个子类Level1。

import static com.wg.MainComponent.spritesheet;

import java.awt.Color;
import java.awt.image.BufferedImage;

import com.wg.BufferedImageLoader;
import com.wg.entity.mob.Player;

public class Level1 extends Level {

    public static final BufferedImage bricks = crop(0, 2);
    public static final BufferedImage dirt = crop(1, 2);
    public static final BufferedImage grass = crop(2, 2);
    public static final BufferedImage[] tilesList = { bricks, dirt, grass };
    public static final int[] defaultxCollisionOffset = { 0, 0, 0 };
    public static final int[] defaultyCollisionOffset = { 0, 0, 0 };
    private static BufferedImage level = BufferedImageLoader.load("/level1.png");

    private static BufferedImage crop(int x, int y) {
        return spritesheet.getSubimage(x * 16, y * 16, 16, 16);
    }

    public void generateLevel() {
        for (int y = 0; y < levelImage.getHeight(); y++) {
            for (int x = 0; x < levelImage.getWidth(); x++) {
                Color c = new Color(level.getRGB(x, y));
                String data = String.format("%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue());
                if (data.equals("838383"))
                    tile[x][y] = bricks;
                else if (data.equals("bea100"))
                    tile[x][y] = dirt;
                else if (data.equals("23d200"))
                    tile[x][y] = grass;
            }
        }
    }

    public Level1(float xOffset, float yOffset) {
        super(level, 16, tilesList, defaultxCollisionOffset, defaultyCollisionOffset);
        collision.add(grass);
        collision.add(dirt);
        collision.add(bricks);
        add(new Player(50, 20, 1, 2, 32 + 32, 32 + 32, this));
        this.xOffset = xOffset;
        this.yOffset = yOffset;
    }
}

Well, I know that would be really hard to find the error just with two classes, so I made a MCVE :). 好吧,我知道仅使用两个类就很难找到错误,所以我制作了一个MCVE :)。 (To run it create a folder called image in your C: with this (要运行它,请在C:中创建一个名为image的文件夹 inside called level1.png and this 里面叫做level1.png而这个 image called tiles.png) 名为tiles.png的图片)

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class MCVE extends JFrame {

    public static final int WIDTH = 800;
    public static final int HEIGHT = 600;
    private MCVELevel1 level1 = new MCVELevel1(0, 0);

    public static void main(String[] args) {
        MCVE mcve = new MCVE();
        mcve.setVisible(true);
        mcve.setSize(WIDTH, HEIGHT);
        mcve.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public void paint(Graphics g) {
        level1.render(50, 400, 32, (Graphics2D) g);
    }

    private static class MCVELevel1 extends MCVELevel {

        private static BufferedImage spritesheet = BufferedImageLoader.load("C://image//tiles.png");
        public static final BufferedImage bricks = crop(0, 0);
        public static final BufferedImage dirt = crop(1, 0);
        public static final BufferedImage grass = crop(2, 0);
        public static final BufferedImage[] tilesList = { bricks, dirt, grass };
        public static final int[] defaultxCollisionOffset = { 0, 0, 0 };
        public static final int[] defaultyCollisionOffset = { 0, 0, 0 };
        private static BufferedImage level = BufferedImageLoader.load("C://image//level1.png");

        private static BufferedImage crop(int x, int y) {
            return spritesheet.getSubimage(x * 16, y * 16, 16, 16);
        }

        public void generateLevel() {
            for (int y = 0; y < levelImage.getHeight(); y++) {
                for (int x = 0; x < levelImage.getWidth(); x++) {
                    Color c = new Color(level.getRGB(x, y));
                    String data = String.format("%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue());
                    if (data.equals("838383"))
                        tile[x][y] = bricks;
                    else if (data.equals("bea100"))
                        tile[x][y] = dirt;
                    else if (data.equals("23d200"))
                        tile[x][y] = grass;
                }
            }
        }

        public MCVELevel1(float xOffset, float yOffset) {
            super(level, 16, tilesList, defaultxCollisionOffset, defaultyCollisionOffset);
            this.xOffset = xOffset;
            this.yOffset = yOffset;
        }
    }

    public static class BufferedImageLoader {
        public static BufferedImage load(String path) {
            try {
                return ImageIO.read(new File(path));
            } catch (IOException e) {
                e.printStackTrace();
            }
            throw new NullPointerException("No file found at: " + path);
        }

        public static BufferedImage load(URL url) {
            try {
                return ImageIO.read(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
            throw new NullPointerException("No file found at: " + url.getPath());
        }
    }
}

The MCVELevel class: MCVELevel类:

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;

public abstract class MCVELevel {

    public BufferedImage levelImage;
    public BufferedImage[][] tile;
    public Rectangle[][] rect;
    public int tileSize;
    public float xOffset, yOffset;

    public BufferedImage[] tilesBufferedImages;
    public int[] xCollisionOffset;
    public int[] yCollisionOffset;

    public MCVELevel(BufferedImage levelImage, int tileSize, BufferedImage[] tilesBufferedImages, int[] xCollisionOffset, int[] yCollisionOffset) {
        this.tilesBufferedImages = tilesBufferedImages;
        this.xCollisionOffset = xCollisionOffset;
        this.yCollisionOffset = yCollisionOffset;

        this.levelImage = levelImage;
        this.tileSize = tileSize;

        tile = new BufferedImage[levelImage.getWidth()][levelImage.getHeight()];
        rect = new Rectangle[levelImage.getWidth()][levelImage.getHeight()];

        generateLevel();
    }

    public abstract void generateLevel();

    public void render(float xOffset, float yOffset, int scale, Graphics2D screen) {
        this.xOffset = xOffset;
        this.yOffset = yOffset;

        for (int y = (int) Math.max(yOffset / (tileSize + scale), 0); y < Math.min((MCVE.HEIGHT + yOffset) / (tileSize + scale) + 1, levelImage.getHeight()); y++) {
            for (int x = (int) Math.max(xOffset / (tileSize + scale), 0); x < Math.min((MCVE.WIDTH + xOffset) / (tileSize + scale) + 1, levelImage.getWidth()); x++) {
                if (tile[x][y] != null)
                    screen.drawImage(tile[x][y], (int) (x * (tileSize + scale) - xOffset), (int) (y * (tileSize + scale) - yOffset), (tileSize + scale), (tileSize + scale), null);
            }
        }
    }

    public void update(int scale) {
        for (int y = 0; y < levelImage.getHeight(); y++) {
            for (int x = 0; x < levelImage.getWidth(); x++) {
                if (tile[x][y] != null && rect[x][y] == null) {
                    for (int i = 0; i < tilesBufferedImages.length; i++) {
                        if (tilesBufferedImages[i] == tile[x][y])
                            rect[x][y] = new Rectangle(x * (tileSize + scale) - Math.round(xOffset) + xCollisionOffset[i], y * (tileSize + scale) - Math.round(yOffset) + yCollisionOffset[i], (tileSize + scale) + xCollisionOffset[i], (tileSize + scale) + yCollisionOffset[i]);
                    }
                } else if (tile[x][y] != null && rect[x][y] != null) {
                    for (int i = 0; i < tilesBufferedImages.length; i++) {
                        if (tilesBufferedImages[i] == tile[x][y])
                            rect[x][y].setBounds(x * (tileSize + scale) - Math.round(xOffset) + xCollisionOffset[i], y * (tileSize + scale) - Math.round(yOffset) + xCollisionOffset[i], (tileSize + scale) + xCollisionOffset[i], (tileSize + scale) + yCollisionOffset[i]);
                    }
                }
            }
        }
    }
}

Many thanks. 非常感谢。

EDIT: updated code at MCVELevel: 编辑:在MCVELevel更新的代码:

public void render(float xOffset, float yOffset, int scale, Graphics2D screen) {
        this.xOffset = xOffset;
        this.yOffset = yOffset;

        for (int y = 0; y < levelImage.getHeight(); y++) {
            for (int x = 0; x < levelImage.getWidth(); x++) {
                if (tile[x][y] != null)
                    screen.drawImage(tile[x][y], (int) (x * (tileSize + scale) - xOffset), (int) (y * (tileSize + scale) - yOffset), (tileSize + scale), (tileSize + scale), null);
            }
        }
    }

The problem is in this chunk inside the render method: 问题出在render方法中的以下代码块中:

for (int y = (int) Math.max(yOffset / (tileSize + scale), 0); y < Math.min((MCVE.HEIGHT + yOffset) / (tileSize + scale) + 1, levelImage.getHeight()); y++) {
    for (int x = (int) Math.max(xOffset / (tileSize + scale), 0); x < Math.min((MCVE.WIDTH + xOffset) / (tileSize + scale) + 1, levelImage.getWidth()); x++) {
        if (tile[x][y] != null)
            screen.drawImage(tile[x][y], (int) (x * (tileSize + scale) - xOffset), (int) (y * (tileSize + scale) - yOffset), (tileSize + scale), (tileSize + scale), null);
    }
}

This seems to be saying: "for pixels that I want to draw to, draw tiles" (though I could be wrong about that.. I get a different explanation every time I read that for-loop guard). 这似乎是在说:“对于我要绘制的像素,请绘制图块”(尽管我可能会犯错。每次阅读该for循环后卫时,我都会得到不同的解释)。 The problem is that you're calculating x and y in terms of drawing area, but you're using them in terms of indices into the tiles[] array. 问题在于您是根据绘图区域来计算x和y,但是却是根据tiles[]数组中的索引来使用它们。 You want "for tiles I want to draw, draw tiles". 您想要“对于我要绘制的瓷砖,绘制瓷砖”。

The loop in generateLevel() is doing the right thing. generateLevel()的循环正在做正确的事情。 Use that sort of loop ( for (y = 0 y < levelImage.getHeight(); ++y) ). 使用这种循环( for (y = 0 y < levelImage.getHeight(); ++y) )。 The only bit of code that needs to worry about yOffset , tileSize and scale is the code that actually draws a tile . 唯一需要担心yOffsettileSizescale的代码是实际绘制图块的代码。

This reminds me again why code should be written to be testable, and why tests should be written :) 这再次让我想起了为什么应该将代码编写为可测试的,以及为什么应该编写测试:)

(My other answer is not wrong (I think) but it doesn't answer the specific problem; it fixes a problem that would have become apparent later.) (我的其他答案没有错(我认为),但是它没有回答特定的问题;它解决了以后会变得很明显的问题。)

Your level1.png has some unusual pixels which have RGB values that match bricks, but which look to the eye to be blank. 您的level1.png包含一些不寻常的像素,这些像素的RGB值与砖块匹配,但是在眼睛看来是空白的。 I guess there's a transparency thing happening, but I don't know anything about pngs. 我猜发生了透明事件,但是我对png一无所知。 Anyway, this level1.png is clean and works as expected: 无论如何,这个level1.png是干净的并且可以按预期工作: level1.png

It took a while to figure this out. 花了一段时间才弄清楚这一点。 I created a more minimal MCVE from your one. 我从您的产品中创建了一个最小的MCVE。 This version may help future readers debug the problem with the original png (in the question). 此版本可能会帮助将来的读者用原始的png(问题中)调试问题。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class MCVE extends JFrame {
    private static final long serialVersionUID = 1L;
    public static final int WIDTH = 800;
    public static final int HEIGHT = 600;

    public static void main(String[] args) {
        MCVE mcve = new MCVE();
        mcve.setVisible(true);
        mcve.setSize(WIDTH, HEIGHT);
        mcve.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public void paint(Graphics g) {
        render((Graphics2D) g);
    }

    public BufferedImage[][] tile;
    public static final int TILE_SIZE = 16;
    private static BufferedImage spritesheet = BufferedImageLoader
            .load("tiles.png");
    private static final BufferedImage bricks = crop(0, 0);
    private static final BufferedImage dirt = crop(1, 0);
    private static final BufferedImage grass = crop(2, 0);
    private static final BufferedImage levelImage = BufferedImageLoader.load("level1.png");
    int widthInTiles;
    int heightInTiles;

    private static BufferedImage crop(int x, int y) {
        return spritesheet.getSubimage(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE,
                TILE_SIZE);
    }

    public MCVE() {
        widthInTiles = levelImage.getWidth();
        heightInTiles = levelImage.getHeight();

        generateLevel();
    }

    public void generateLevel() {
        tile = new BufferedImage[widthInTiles][heightInTiles];
        for (int y = 0; y < heightInTiles; y++) {
            for (int x = 0; x < widthInTiles; x++) {
                Color c = new Color(levelImage.getRGB(x, y));
                switch (c.getRGB()) {
                case -8158333:
                    tile[x][y] = bricks;
                    break;
                case -14429696:
                    tile[x][y] = grass;
                    break;
                case -4284160:
                    tile[x][y] = dirt;
                }
            }
        }
    }

    public void render(Graphics2D screen) {
        int scale = 16;
        int yes = 0, no = 0;
        for (int y = 0; y < heightInTiles; y++) {
            for (int x = 0; x < widthInTiles; x++) {
                if (tile[x][y] != null) {
                    screen.drawImage(tile[x][y], (int) (x * (TILE_SIZE + scale)),
                            (int) (y * (TILE_SIZE + scale)),
                            (TILE_SIZE + scale), (TILE_SIZE + scale),
                            Color.BLACK, null);
                }
            }
        }
    }

    public static class BufferedImageLoader {
        public static BufferedImage load(String path) {
            try {
                return ImageIO.read(new File(path));
            } catch (IOException e) {
                e.printStackTrace();
            }
            throw new NullPointerException("No file found at: " + path);
        }

        public static BufferedImage load(URL url) {
            try {
                return ImageIO.read(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
            throw new NullPointerException("No file found at: " + url.getPath());
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM