【问题标题】:Sprite Drawing Issue精灵绘图问题
【发布时间】:2015-06-04 18:36:34
【问题描述】:

当我使用此代码时,图像会绘制(来自我定义的 spritesheet 部分),但它会在前一个实例上重新绘制它。我需要“图像”来“移动”。我使用paint 方法,使用Graphics 来重绘在init() 方法中定义的精灵。我只是想创建一个“奴才”,一旦它被添加到程序中,它就会开始从屏幕左下角到右侧“行走”,它本身(没有用户操作移动它)。我目前可以让它只拍摄图像并将其“涂抹”在屏幕底部(它会不断地将其绘制在自身上)

(为简单起见删除了导入)

 public class Main extends JFrame {

    BufferedImage sprite;
    int War_x = 10, War_y = 640, War_dx = 1;

    public Main()
    {
        //(X,Y) ---- (LEFT,UP)
        //Window theGUI = new Window();
        //JFrame theGUI = new JFrame();
        setSize(870,720);
        setTitle("Game");
        setBackground(Color.red);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);

        init();

    }
    public void init()
    {
        BufferedImageLoader loader = new BufferedImageLoader();
        BufferedImage spriteSheet = null;
        System.out.println("bruh");
        try {
            spriteSheet = loader.loadImage("warrior.png");
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
        SpriteSheet ss = new SpriteSheet(spriteSheet);

        sprite = ss.grabSprite(0,130,32,36);


    } 
@Override
public void paint(Graphics g){

    g.drawImage(sprite, War_x, War_y,64, 64, null);
    warrior start = new warrior();
    start.start();
    repaint();
}

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


public class warrior implements ActionListener{
    public Timer T = new Timer(100, this);

    public void start(){
        T.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        War_x += War_dx;
    }

}

}

【问题讨论】:

    标签: java sprite


    【解决方案1】:

    为了让精灵“移动”,您需要将他从原来所在的画布中移除,然后将他绘制到新位置。

    为了真正做到这一点,你可能需要做这样的事情:

    1. 清屏
    2. 重绘更新的背景
    3. 重绘更新的实体

    因此,对于实际情况,假设您的背景只是一个纯白色矩形,其中canvasWidthcanvasHeight 是您的画布的宽度和高度,您的绘制方法将如下所示:

    @Override
    public void paint(Graphics g){
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, canvasWidth, canvasHeight);
    
        g.drawImage(sprite, War_x, War_y,64, 64, null);
        repaint();
    }
    

    【讨论】:

    • 谢谢,这看起来很麻烦,但如果那是最好的方法,那就好吧。如何准确清屏?
    • 如果您使用的是Graphics 对象,那么g.clearRect 可能是您最好的选择。这只会清除矩形中的所有内容,然后您可以重绘背景、字符、对象等。
    • 更新:当我这样做时,它会发送垃圾邮件“清除”并且它不显示精灵。我有时会瞥见清除之间的精灵,但似乎精灵被粘贴在我创建的画布下面
    【解决方案2】:

    首先,不建议直接在 JFrame 上绘图。这就是您遇到“污迹/等”问题的原因之一。使用画布或类似的东西,用于绘图。也可能更好地绘制到 BufferedImage 之类的东西上,然后将其绘制到屏幕上,而不是直接绘制到屏幕上。

    其次,如果你想让它不断移动,我会把它放在外面的一个循环中,然后让画布从一个单独的线程自动更新。

    这是一个链接,可让您开始使用 Threads https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

    【讨论】:

    • 我还是新手,所以请不要使用您的建议来使用画布。但是,循环的问题是,我需要有延迟或 FPS 速率,以便用户真正看到精灵在移动。我尝试为此使用计时器,但我对计时器并不是那么好。
    • 如果你把绘图放到一个线程中,你可以让它变得非常简单,只需要沿着 thead.sleep() 的行做一些事情。我不确定你想用这个有多复杂,但它可能是你最好的选择。
    • 如何设置话题?目前,我相信使用 thread.sleep() 会导致整个框架进入睡眠状态。我计划让屏幕上的多个精灵彼此独立移动,那么这种方法仍然是这种情况下的最佳选择吗?
    • 一个快速的谷歌搜索应该给你很多实现线程的方法。要专门回答您的问题 - 您需要一个线程来处理对不断更新的画布所做的更改(例如,如果绘图发生更改,它会尽可能频繁地更新)。
    猜你喜欢
    • 1970-01-01
    • 2012-08-07
    • 2013-06-12
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    相关资源
    最近更新 更多