繁体   English   中英

您如何解决Java awt / swing图像打印的滞后问题?

[英]How do you solve lagging in Java awt/swing image printing?

我试图用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))造成的?

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

因为您还使用自己的Thread ,所以冒着线程竞争情况的风险,这可能会导致读取/绘制不干净。

首先了解Swing绘画在API功能中的实际工作方式和工作方式。

首先看一下执行自定义绘画AWT中的绘画以及Swing中的Swing并发

对于监听器的键盘输入, KeyListener也是一个糟糕的选择,您应该使用Key Bindings API-有关更多详细信息,请参见如何使用键绑定

将内容添加到ArrayList可能会导致ArrayList经历一个增长周期,这可能会消耗时间并迫使更长的GC周期。 考虑使用初始容量为ArrayList种子,这将有助于缩短增长周期之间的间隔。

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

您也可以看看

这证明了提高Swing渲染性能的技术的真实性。

如果这些仍然不能使您达到所需的水平,那么您将需要使用BufferStrategy探索

暂无
暂无

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

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