Reputation: 1
I'm working on a game in java, based on the Atari game adventure. I got the basic KeyListener part working fine, but then I added another if statement, using another class, to test if if the player was going to hit a wall, and stopping movement if that was the case. The method I used also used if statements, and when I ran the code, it had MAJOR lag. I tried a while loop first, but that made it lag even worse. Anyway to make this not lag so much? It doesn't seem that complex a program to run, and I still have to add yet another if statement to make be able to move into another room, so I have to do something to massively cut down on the lag.
Here is the class:
class Player extends JPanel implements KeyListener{
private char c = 'e';
int x = 400;
int y = 400;
int mapX = 0;
int mapY = 0;
public Player() {
this.setPreferredSize(new Dimension(800, 500));
addKeyListener(this);
}
public void addNotify() {
super.addNotify();
requestFocus();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Environment Layout = new Environment();
Layout.drawRoom(mapX,mapY,g);
g.fillRect(x , y , 20, 20);
}
public void keyPressed(KeyEvent e) { }
public void keyReleased(KeyEvent e) { }
public void keyTyped(KeyEvent e) {
c = e.getKeyChar();
repaint();
Environment Layout = new Environment();
if(Layout.isWall(x,y,c)){}
else{
if (c == 'a'){
x = x - 3;
}
else if (c == 'w'){
y = y - 3;
}
else if (c == 's'){
y = y + 3;
}
else if (c == 'd'){
x = x + 3;
}
}
}
public static void main(String[] s) throws IOException{
JFrame f = new JFrame();
f.getContentPane().add(new Player());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
The draw room method I used in this was just to put the background of the room into place.
Here is the isWall method from the Environment class:
public boolean isWall(int moveX, int moveY, char let){
BufferedImage room = null;
try {
room = ImageIO.read(new File(xNum + "," + yNum + ".png"));
}
catch (IOException e) {
}
int[][] walls = convertImage(room);
boolean blocked = false;
if(let == 'w') {
if(walls[moveY-8][moveX] == -3584){blocked = true;}
}
else if(let == 's') {
if(walls[moveY+20][moveX] == -3584){blocked = true;}
}
else if(let == 'a') {
if(walls[moveY][moveX-5] == -3584){blocked = true;}
}
else if(let == 'd') {
if(walls[moveY][moveX+20] == -3584){blocked = true;}
}
return blocked;
}
the convertImage method just converts the image of the room into an int array, for the value of the colors. -3584 is the color of the walls. It's possible this is what's lagging it, but this seemed like the best way for each room to have the walls done automatically.
I also tried a timer, but either I did that wrong, or it just didn't help.
I can give more of my code if that's needed, but help with this would be much appreciated. I'm relatively new to this kind of stuff, so it's likely I'm missing something big. Thanks.
Upvotes: 0
Views: 247
Reputation: 19268
This is an extension to @templatetypedef's answer.
Instead of loading the image files upon calling the isWall method, you might want to consider caching all of the walls on game start.
So I am thinking;
<String, Integer>
. Where String is your coordinates. E.g. coordinate string = "100,238" This should drastically reduce the I/O disk contention.
In future, if you would like to extend the solution to incorporate APIs like isTreasureChest() or isMonster(). It can be extended by building a immutable class call "Room
" or "Tile
" to represent the object. Then modify the HashMap to take in <String, Room>
.
Upvotes: 0
Reputation: 767
You appear to be moving your walls further than you are moving your player.
Is it possible that your player object is getting stuck in a wall there by producing "blocked = true" continuously?
Your character gets +- 3 in every direction, however your walls seem inconsistent and range from 8 up to 20 down to 5 left to 20 right.
Upvotes: 0
Reputation: 372814
The lag here is almost certainly not from the if
statements. Those are really fast. I think the bigger issue is in isWall
. Notice that any time you want to check for whether a wall is present, you
Reading files from disk is extremely slow compared to looking at values in memory. For example, a regular magnetic hard drive works at around 7200 RPM, so the seek time is measured in milliseconds. On the other hand, your processor can do about a billion operations per second, so other operations take nanoseconds. That means that a disk read is roughly a million times slower than other operations, which is almost certainly where you're getting the lag from!
To fix this, consider rewriting your isWall
code so that you only read the file and do the conversion once and, having done that, then just look up the part of the image you need. This converts doing tons of (glacially slow) file reads to one single (slow but inevitable) file read followed by tons of fast memory reads.
Upvotes: 4