-1

I am trying to make a simple game with Java swing/awt. I am have issue with lagging while printing and moving images on the screen.

Here is my code below:

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) {
    }

}

When you compile the code, the first few stationary images appear fine.

After moving images(Drones) appear nicely, but when you summon the next stationary image(Building), heavy lag starts to appear and the speed of the moving drones decrease visibly.

The building is about 300*150 pixels and the drones are 40*30 pixels.

What is the cause of this problem? Is this because of the code(the way of summoning the image), or the picture's size, or the computer(I am using a notebook(LG Gram 14in)).?

Pavel
  • 1,519
  • 21
  • 29
David
  • 1
  • 1) One way to get image(s) for a self contained example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). 2) See [Detection/fix for the hanging close bracket of a code block](http://meta.stackexchange.com/q/251795/155831) for a problem I could no longer be bothered fixing. – Andrew Thompson Dec 09 '17 at 18:09

2 Answers2

1

Start by not using Graphics ge = this.getGraphics();.

Because you're also using your own Thread, you're running the risk of thread race conditions which could result in dirty reads/ paints.

Start by understanding how Swing painting actually works and work within the API functionality.

Start by having a look at Performing Custom Painting, Painting in AWT and Swing and Concurrency in Swing

KeyListener is also a poor choice for monitor key input and you should be using the Key Bindings API - see How to use key bindings for more details.

Adding content to the ArrayList can cause the ArrayList to go through a growth cycle, which can consume time and force a longer GC cycle. Consider seeding the ArrayList with initial capacity, it will help reduce the interval between growth cycles.

Focus on separating the "update" logic from the "paint" logic, it can help you find performance issues

You could also have a look at

Which demonstrate a verity of techniques for improving performance of rendering in Swing.

If these still are't getting your to the level you want, then you will want to explore using a BufferStrategy

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Better draw in JPanel and use repaint() method to update your JPanel