I'm trying to make a small shooter game, where you can only see a small portion of the map around you. The map will also be much larger then the actual JPanel (The panel is 1000 by 1000, the map currently is 5000 by 5000).
When I added movement, the game seemed to lag slightly, mainly noticeable in the graphics flickering, however the game was still playable
Adding in a few walls drawn on the map significantly dropped performance, however, and now the game is entirely unplayable.
I'm looking for some tips to help optimize my code to lower this lag.
The other major problem I've been having is in regards to how I draw the map. When I move the area of the map I'm able to see down and to the left, the actual image moves up and to the right. This means that the Maps coordinates (and therefore the players coordinates), are negative. This isn't entirely game breaking, but is an annoyance nonetheless.
I've only included classes associated with movement below, but if the JPanel and JFrame classes are necessary, I can add them
Edit Removing the line
image.getGraphics().draw3DRect(10, 10, 10, 10, true);
seemed to speed up the game considerably, to the point of near to no lag However, I'm still almost certain my code is far from efficient - are there any other tweaks I could use to speed it up?
GameManager (Holds the gamethread, and runs the majority of the logic)
package Logic;
import java.util.ArrayList;
import Runner.Panel;
import Entities.*;
import java.awt.Graphics;
import Movement.*;
public class GameManager {
private final Panel gamepanel;
private boolean game_is_running = true;
private final Map map = new Map();
private Player player = new Player(100, 100);
private Movement movement = new Movement(0);
ArrayList<Wall> walls = new ArrayList<Wall>();
public GameManager(Panel p) {
gamepanel = p;
initializeWalls();
gamethread.start();
}
private void initializeWalls() {
//adds walls on the map image
walls.add(new Wall(2000, 2000, 100, 50));
walls.add(new Wall(500,500,1000,500));
walls.add(new Wall(0,500,100,1000));
map.addWalls(walls);
}
private final Thread gamethread = new Thread() {
public void run() {
final byte UPDATES_PER_SECOND = 45;
final double ups = 1000 / UPDATES_PER_SECOND;
long iTime = System.currentTimeMillis();
while (game_is_running) {
final long ftime = System.currentTimeMillis();
final long eTime = ftime - iTime;
if (eTime >= ups) {
iTime = System.currentTimeMillis();
//updates logic 60 times a second
update();
}
//repaints the game as fast as it can
gamepanel.repaint();
}
}
};
private void update() {
//Updates the position of the player
movement.Update(gamepanel, player, map);
}
public void Draw(Graphics g) {
//Calls the drawing of the map and player
map.Draw(g);
player.Draw(g, map);
}
}
Movement (Updates positions of the objects on screen)
package Movement;
import Entities.*;
import Runner.Panel;
public class Movement {
private float angle = 0;
private int speed = 20;
public Movement(float a) {
angle = a;
}
private void addangle(float a) {
angle += a;
}
private void moveForward(Player p) {
float xpos = (float) (speed * Math.sin(Math.toRadians(angle)));
float ypos = (float) (speed * Math.cos(Math.toRadians(angle)));
p.setX(p.getX() - xpos);
p.setY(p.getY() - ypos);
}
public void Update(Panel panel, Player p, Map m) {
if (panel.isUp()) {
moveForward(p);
}
if (panel.isDown()) {
moveBack(p);
}
if (panel.isLeft()) {
addangle(5);
}
if (panel.isRight()) {
addangle(-5);
}
m.setX(p.getX() - 450);
m.setY(p.getY() - 450);
}
private void moveBack(Player p) {
float xpos = (float) (speed * Math.sin(Math.toRadians(angle)));
float ypos = (float) (speed * Math.cos(Math.toRadians(angle)));
p.setX(p.getX() + xpos);
p.setY(p.getY() + ypos);
}
}
Entity (Abstract class for all objects on screen)
package Entities;
import java.awt.image.BufferedImage;
public abstract class Entity {
float x, y;
int width, height;
BufferedImage image;
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public BufferedImage getImage() {
return image;
}
}
Map (Holds the map image)
package Entities;
import java.awt.Graphics;
import java.io.File;
import javax.imageio.ImageIO;
import java.util.ArrayList;
public class Map extends Entity {
public Map() {
try {
image = ImageIO.read(new File("resources/Maps/TestMap.jpg"));
} catch (Exception ex) {
System.out.println("WARNING: MAP NOT FOUND" + "\n" + "ERROR CODE 1");
System.exit(-1);
}
}
public void addWalls(ArrayList<Wall> walls){
for(Wall w:walls){
image.getGraphics().drawRect((int)w.getX(),(int)w.getY(),w.getWidth(),w.getHeight());
}
}
public void Draw(Graphics g) {
image.getGraphics().draw3DRect(10, 10, 10, 10, true);
g.drawImage(image, (int) x, (int) y, null);
}
}
Player (Holds position of the player)
package Entities;
import java.awt.Graphics;
public class Player extends Entity {
public Player(float x, float y) {
this.x=x;
this.y=y;
}
public void Draw(Graphics g, Map m) {
g.drawRect((int)(m.getX()*-1-x*-1), (int)(m.getY()*-1-y*-1), 100, 100);
}
}
Wall (holds position of walls (I've not added collision in yet)
package Entities;
import java.awt.Rectangle;
public class Wall extends Entity{
public Wall(int x, int y, int width, int height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public Rectangle getBounds(){
Rectangle ret = new Rectangle((int)x,(int)y,width,height);
return ret;
}
}