user3483494
user3483494

Reputation:

How to fix java keyPressed Lag/Late events

I am sort of a noob at this but have attempted to create my own mario game. It's going well but I need a variable called distanceTraveled to be determined

It isn't reliable at all, when I hold the arrow key numbers go faster than if I was to tap them.

Here are my codes(Everything is commented on the right):

.

frame.java

package EvilMario;                                                                               //Include this class in the EvilMario game package

import javax.swing.JFrame;                                                                       //Import the JFrame

public class frame {                                                                             //Run this class to run the game
    public static void main(String[] args) {                                                     //The first method called by java
        JFrame frame = new JFrame("EvilMario v.1.0.0 by Max Mastalerz");                         //Create JFrame called frame

        frame.getContentPane().add(new board());                                                 //Go to board class
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                                    //Make frame close on X click
        frame.setSize(600,413);                                                                  //Set the frame size to the size of the background
        frame.setVisible(true);                                                                  //Make the frame visible
        frame.setResizable(false);                                                               //Make sure the user can't resize the frame
    }
}

player.java

package EvilMario;                                                                               //Include this class in the EvilMario game package

import java.awt.Image;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;

public class player {
    int x, dx, y, nx, nx2, distanceTraveled;                                                     //x coordinate,change in x coordinate,y coordinate,1st rep bg,2nd rep bg,dist traveled
    Image player;                                                                                //The player variable
    ImageIcon playerFacingLeft = new     ImageIcon("D:/ICS3U1/EvilMario/images/MarioLeft.png");  //Image for player while he is     turning left
    ImageIcon playerFacingRight = new     ImageIcon("D:/ICS3U1/EvilMario/images/MarioRight.png");//Image for player while he is turning right

        public player() {
            player = playerFacingRight.getImage();                                           //Give the player the image
            x = 75;                                                                          //The original x position of the player
            y = 265;                                                                         //The original y position of the player
            nx = -0;                                                                         //Repeating background 1
            nx2 = -575;                                                                      //Repeating background 2
            distanceTraveled = 0;
        }

        public void move() {
            if(x>0 && x<300) {                                                               //If the player is within the moving area
                x = x+dx;                                                                    //The x position is updated to become itself+the amount you moved
                nx = nx+dx;                                                                  //Place the repeating background at regular speed
                nx2 = nx2+dx;                                                                //Place the repeating background at regular speed
            }
            if(x==0) {                                                                       //If the player has reached he very left side of the screen(0px)
                x=1;                                                                         //Move him up a pixel so he can move again

                nx = nx+(dx*(int)0.5);                                                       //Place the background at a slower speed since Mario stops moving
                nx2 = nx2+(dx*(int)0.5);                                                     //Place the background at a slower speed since Mario stops moving

            }
            if(x==300) {                                                                     //If the player has reached the center of the screen(300px)
                x=299;                                                                       //Move him down a pixel so he can move again
                nx = nx+(dx*(int)0.5);                                                       //Place the background at a slower speed since Mario stops moving
                nx2 = nx2+(dx*(int)0.5);                                                     //Place the background at a slower speed since Mario stops moving
            }
            System.out.println(distanceTraveled);
        }

        public int   getX()     { return x;      }                                           //This method will return the x.      Is used by other classes
        public int   getY()     { return y;      }                                           //This method will return the y.      Is used by other classes
        public Image getImage() { return player; }                                           //This method will return the player. Is used by other classes

        public void keyPressed(KeyEvent e) {                                                 //Called from the board class, the argument is whatever key was pressed
            int key = e.getKeyCode();                                                        //The key originally sent from the board class

            if(key == KeyEvent.VK_LEFT) {                                                    //If the key sent was LEFT
                player = playerFacingLeft.getImage();                                        //Make the player face leftwards
                dx = -1;
                distanceTraveled--;
            }

            if(key == KeyEvent.VK_RIGHT) {                                                   //If the key sent was RIGHT
                player = playerFacingRight.getImage();                                       //Make the player face rightwards
                dx = 1;                                                                      //Move right
                distanceTraveled++;
            }
        }

        public void keyReleased(KeyEvent e) {                                                //Called from the board class, the argument is whatever key was released
             int key = e.getKeyCode();                                                        //The key originally sent from the board class

            if(key == KeyEvent.VK_LEFT || key == KeyEvent.VK_RIGHT)                          //If the left or right key was released
                dx = 0;                                                                      //Stop moving
        }
}

board.java

package EvilMario;                                                                           //Include this class in the EvilMario game package

import java.awt.*;                                                                           //Imported to allow use of Image
import java.awt.event.*;                                                                     //Imported to allow use of ActionListener

import javax.swing.*;

public class board extends JPanel implements ActionListener {
player p;                                                                                        //Instance of player class
Image background;                                                                            //The background variable
Timer time;                                                                                  //A timer

    public board() {
        p = new player();                                                                    //Start running player class
        addKeyListener(new AL());                                                            //Listen for keys
        setFocusable(true);                                                                  //Allows movement                      
        ImageIcon i = new ImageIcon("D:/ICS3U1/EvilMario/images/EvilMario_Background.png");  //Image for background
        background = i.getImage();                                                           //Give the background the image
        time = new Timer(7,this);                                                            //Timer set to update "this" class every 5 milliseconds
        time.start();                                                                        //Actually start the timer
    }

    public void actionPerformed(ActionEvent e) {
        p.move();                                                                            //Call the move method from the player class
        repaint();                                                                           //Repaint
    }

    public void paint(Graphics g) {                                                          //Graphics method
        super.paint(g);
            Graphics2D g2d = (Graphics2D) g;                                                 //casts 2d graphics(or however you would explain it)

            g2d.drawImage(background, -p.nx, 0, null);                                       //Draw the background image
            g2d.drawImage(background, -p.nx2, 0, null);                                      //Draw the background image

            if(-p.nx<-575)                                                                   //If going forwards
                p.nx=-575;                                                                   //Start placing forwards every 575px in front on the last one
            else if(-p.nx>575)                                                               //If going backwards
                p.nx=575;                                                                    //Start placing backwards every 575px behind the last one

             if(-p.nx2<-575)                                                                  //If going forwards
                p.nx2=-575;                                                                  //Start placing forwards every 575px in front on the last one
            else if(-p.nx2>575)                                                              //If going backwards
                p.nx2=575;                                                                   //Start placing backgrounds every 575px behind the last one

            g2d.drawImage(p.getImage(), p.getX(), p.getY(), null);                           //Draw the player at the position he is currently(Coordinate values taken from player class)
        }

    private class AL extends KeyAdapter {                                                    //Action Listener extends key adapter
        public void keyPressed(KeyEvent e) {                                                 //On key press
            p.keyPressed(e);                                                                 //Send whatever key was pressed  TO the keyPressed  method in the player class
        }
        public void keyReleased(KeyEvent e) {                                                //On key release
            p.keyReleased(e);                                                                //Send whatever key was released TO the keyReleased method in the player class
        }
    }
}

If you wish to test this game yourself, you will need these three images

EvilMario_Background.png

EvilMario_Background.png

MarioLeft.png

MarioLeft.png

MarioRight.png

MarioRight.png

Also change the directories I've been trying too many things with this and have not come up with anything, If you figure this out I will be forever grateful :)

Upvotes: 1

Views: 1177

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347194

Rather then trying to calculate the distance in the key event handlers, calculate it within the move method. This would be based on the value of dx been either greater or less then 0

  • You really should be using paintComponent by convention, rather the paint
  • You should consider using the key bindings API as it solves many of the problems associated with the KeyListener
  • I would rely more on the actual width and height properties of the JPanel rather then "magic" numbers. The problem here is different platforms and look and feels have different frame border sizes, which will effect these values. Consider overriding getPreferredSize in the board to return the preferred size of the gaming canvas. Then you can use pack on the frame instead.
  • Call setResizable before trying to size or show the window, this will change the size of the frame border and change the size of the viewable area...
  • A 7 millisecond delay is something like 143fps...I seriously doubt you really need that kind of refresh rate. 40 milliseconds is 25fps and I dare you do tell the difference, event 60fps is only 16 milliseconds. Don't change the speed of your refresh rate, change the speed of your delta values to alter the speed of the game...just saying ;)

Upvotes: 2

Related Questions