【问题标题】:How do you solve lagging in Java awt/swing image printing?如何解决 Java awt/swing 图像打印的滞后问题?
【发布时间】:2018-05-23 13:09:52
【问题描述】:

我正在尝试使用 Java swing/awt 制作一个简单的游戏。 在屏幕上打印和移动图像时出现滞后问题。

下面是我的代码:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.File;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;




public class StarDef extends JFrame implements Runnable, KeyListener{
    private BufferedImage back;
    private boolean start = false, end = false;
    public int w = 1500, h = 800, commandx = 200, commandy = 100, ground = 500,  mineral = 100;
    private int mineralx = 0, mineraly = commandy + 104;
    private int dronecnt = 0;
    private ArrayList<Drone> DrList = null;
    private ArrayList<Enemy> EnList = null;
    private ArrayList<Building> BuildList = null;
    private ArrayList<Allies> AlyList= null;
    public Image imagearr[] = new Image[10];
    private boolean makedrone = false, NeedMinerals = false;
    public int picnum = 1;
    private int OrderBuild = 0;

    public static void main(String[] args){
        Thread t = new Thread(new StarDef());
        t.start();
    }

    public StarDef(){
        back = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        DrList = new ArrayList<>();
        BuildList = new ArrayList<>();
        EnList = new ArrayList<>();
        AlyList = new ArrayList<>();
        this.addKeyListener(this);
        this.setSize(w,h);
        this.setTitle("Starcraft");
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        try {
            imagearr[0] = ImageIO.read(new File("Char/Command.png"));
            imagearr[1] = ImageIO.read(new File("Char/droneleft.png"));
            imagearr[2] = ImageIO.read(new File("Char/droneright.png"));
            imagearr[3] = ImageIO.read(new File("Char/Mineral.png"));
            imagearr[4] = ImageIO.read(new File("Char/barracks.png"));
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    public void initGame(){
        DrList.clear();
        mineral = 100;

    }
    public void draw(){
        Graphics gs = back.getGraphics();
        gs.setColor(Color.white);
        gs.fillRect(0,0,w,h);
        gs.setColor(Color.DARK_GRAY);
        gs.fillRect(0,ground,w,200);

        if (!end) {
            gs.drawImage(imagearr[0], commandx, commandy, null); // First Image-Command Center
            gs.drawImage(imagearr[3], mineralx,mineraly,null); // Second Image-Mineral

            for (int i = 0; i < DrList.size(); i++) { //Printing Drones
                Drone m = DrList.get(i);
                gs.drawImage(imagearr[m.state], m.x, m.y, null); //Drawing Drones
                m.moveDr(); // Moving the Drone
            }

            for (int i = 0; i < BuildList.size(); i++){ //Printing Building
                Building bd = BuildList.get(i);
                if(bd.buildingtype == 'R'){
                    gs.drawImage(imagearr[4], bd.x, bd.y, null); // Drawing Building-Problem starts..?
                }
            }
            gs.drawImage(imagearr[0], commandx, commandy, null);
        }

        gs.setColor(Color.black);
        gs.drawString("mineral : " + mineral, 10,50);
        gs.drawString("Drones : " + DrList.size(), 10, 70);

        Graphics ge = this.getGraphics();
        ge.drawImage(back, 0,0,w,h,this);
    }

    public void run(){

        try{
            int timer = 10;

            while (true){
                Thread.sleep(timer);
                if(start){
                    if (makedrone) {
                        makedrone();
                    }
                    if (OrderBuild>0){
                        makeBuilding(OrderBuild);
                    }
                }
                draw();
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    public void makeBuilding(int buildingnumber){
        int bdx, bdy;
        char BuildingType;
        if(buildingnumber == 1){
            bdx = 500;
            bdy = 100;
            BuildingType = 'R';
            Building barracks = new Building(this, bdx, bdy, BuildingType);
            BuildList.add(barracks);
        }
    }
    public void makedrone() {

        if (mineral >= 50) {
            int dronex = commandx;
            int droney = commandy+129;
            Drone dr = new Drone(this ,dronex, droney);
            DrList.add(dr);
            dronecnt++;
            mineral -= 50;
            makedrone = false;

        } else if (mineral < 50) {
            NeedMinerals = true;
            makedrone = false;
        }

    }

    public void keyPressed(KeyEvent ke){
        switch (ke.getKeyCode()){
            case KeyEvent.VK_ENTER:
                start = true;
                end = false;
                break;
            case KeyEvent.VK_D:
                makedrone = true;
                break;
            case KeyEvent.VK_R:
                OrderBuild = 1;
                break;
        }
    }

    public void keyReleased(KeyEvent ke){
        switch ((ke.getKeyCode())){

        }
    }
    public void keyTyped(KeyEvent ke) {
    }

}

编译代码时,前几张静止图像看起来不错。

在移动图像(无人机)很好地出现后,但当你召唤下一个静止图像(建筑物)时,开始出现严重滞后,移动无人机的速度明显降低。

建筑大约300*150像素,无人机40*30像素。

这个问题的原因是什么?是因为代码(调用图片的方式),还是图片的大小,还是电脑(我用的是笔记本(LG Gram 14in))?

【问题讨论】:

标签: java image swing awt javax.imageio


【解决方案1】:

首先不要使用Graphics ge = this.getGraphics();

因为您还使用自己的Thread,所以您面临线程竞争条件的风险,这可能导致脏读/绘制。

首先了解 Swing 绘画的实际工作原理以及在 API 功能中的工作原理。

首先查看Performing Custom PaintingPainting in AWT and SwingConcurrency in Swing

KeyListener 也是监控键输入的糟糕选择,您应该使用 Key Bindings API - 有关详细信息,请参阅How to use key bindings

ArrayList 添加内容会导致ArrayList 经历一个增长周期,这会消耗时间并强制延长GC 周期。考虑用初始容量播种ArrayList,这将有助于减少生长周期之间的间隔。

专注于将“更新”逻辑与“绘制”逻辑分开,它可以帮助您发现性能问题

你也可以看看

这展示了在 Swing 中提高渲染性能的大量技术。

如果这些仍然无法让您达到您想要的水平,那么您将需要使用 BufferStrategy 进行探索

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-14
    • 2011-01-18
    • 1970-01-01
    • 2021-03-11
    • 2017-03-01
    • 2022-01-02
    • 2012-01-19
    • 2022-11-28
    相关资源
    最近更新 更多