簡體   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