为什么我尝试更改 Mario 克隆游戏精灵时会被截断?

Why is my Mario clone game sprite getting cut off when I try to change it?

大编辑:我现在有一个 MCVE

在我的超级马里奥 3 克隆中,我的精灵在实例化 JFrame 时正确绘制,但是当我按下我设置为跳跃的按钮之一时,它被部分切断。屏幕上的所有内容都是 JLabel。

代码如下:

//for all
import java.nio.file.*;
import javax.imageio.ImageIO;
import java.io.IOException;
import java.awt.image.*;
import java.net.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.invoke.MethodHandles.*;
import java.awt.event.*;

//my Mario class (cut down a lot)
class Mario {
    // all numbers multiplied by 2 from OG game

    protected Direction dir;
    protected int x, y;
    protected BufferedImage sprite;

    public Mario() {

        this.x = 54;
        this.y = 808;
        dir = Direction.RIGHT;
        setSprite(MVCE.SMALLSTANDFACERIGHT);

    }

    public void moveRight() {
        if (this.dir == Direction.LEFT) {
            this.dir = Direction.RIGHT;
        } else if (this.dir == Direction.RIGHT) {
            this.x += 2;
        }
    }

    public void jump() {
        this.y -= 46;
    }

    public void setSprite(String spriteName) {
        URL spriteAtLoc = MVCE.urlGenerator(spriteName);
        this.sprite = MVCE.generateAndFilter(sprite, spriteAtLoc);
    }

    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.drawImage(sprite, 0, 0, null); // DO NOT SET x and y TO ANYTHING,
                                          // this sets 0,0 to top left!!
    }

}

// my MarioRender class:
class MarioRender extends JLabel {

    protected Mario marioSprite;

    public MarioRender() {
        marioSprite = new Mario();
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        marioSprite.paint(g2);
    }

    public void moveMarioRight() {
        marioSprite.moveRight();
        setLocation(this.marioSprite.x, this.marioSprite.y);
        repaint();
    }

    public void jumpMario() {
        marioSprite.jump();
        setLocation(this.marioSprite.x, this.marioSprite.y);
        repaint();

    }

}

// direction class, solely for moving
enum Direction {
    LEFT, RIGHT
}

// my calling class, which I called MVCE where I make the frame
public class MVCE extends JFrame {

    MarioRender m = new MarioRender();
    JLabel bg;

    public MVCE() {
        bg = new JLabel();
        this.setSize(868, 915);
        this.setVisible(true);
        this.add(bg, BorderLayout.CENTER);
        bg.setLayout(null);

        bg.add(m);
        m.setBounds(m.marioSprite.x, m.marioSprite.y, m.marioSprite.sprite.getWidth(),
                m.marioSprite.sprite.getHeight());
        KeyListener kl = new MoveListener();
        this.addKeyListener(kl);
        this.setFocusable(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    public static final String SMALLSTANDFACERIGHT = "SmallStandFaceRight.bmp"; // 30
                                                                                // x
                                                                                // 32
    public static final String SMALLJUMPFACERIGHT = "SmallJumpFaceRight.bmp"; // 32
                                                                              // x
                                                                              // 32

    // generate URL
    public static URL urlGenerator(String name) {
        URL u = lookup().lookupClass().getResource(name);
        return u;
    }

    // return image with filtered color
    public static BufferedImage generateAndFilter(BufferedImage b, URL u) {

        try {
            b = ImageIO.read(u);
            int width = b.getWidth();
            int height = b.getHeight();
            int[] pixels = new int[width * height];
            b.getRGB(0, 0, width, height, pixels, 0, width);
            for (int i = 0; i < pixels.length; i++) {
                // System.out.println(pixels[i]);
                if (pixels[i] == 0xFFff00fe) {
                    pixels[i] = 0x00ff00fe;
                }
            }
            BufferedImage newSprite = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            newSprite.setRGB(0, 0, width, height, pixels, 0, width);
            b = newSprite;
        } catch (IOException e) {
            System.out.println("sprite not found");
            e.printStackTrace();
        }
        return b;
    }

    // key listener
    class MoveListener implements KeyListener {
        public void keyPressed(KeyEvent k) {

            if ((k.getKeyCode() == 39)) {
                m.marioSprite.setSprite(SMALLSTANDFACERIGHT);
                m.moveMarioRight();

            }

            if (k.getKeyCode() == 83) { // S key

                m.marioSprite.setSprite(SMALLJUMPFACERIGHT);
                m.jumpMario();
            }

        }

        public void keyReleased(KeyEvent k) {
        }

        public void keyTyped(KeyEvent k) {
        }
    }

    public static void main(String[] args) {
        MVCE m = new MVCE();
    }

}

可以找到 sprites here and here 虽然下载的格式是 .jpg,而在我的代码中,它们是 .bmp,但您可以直接下载,在另一个应用程序中打开,另存为 bmp,或更改代码

这很可能是 JLabel 对象的水平和垂直约束的结果。从图片上看,跳跃的马里奥横向比站在地上的马里奥略宽。