Key Pressed wont work - java

Im having trouble getting the key pressed event to work, it doesn't recognize key input, can someone please help?
I have three classes player, exe, and board
Here is the board class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Board extends JPanel implements ActionListener{
private Timer timer;
private Player player;
//private Floor
public Board() {
addKeyListener( new TAdapter() );
setFocusable(true);
setBackground(Color.WHITE);
setDoubleBuffered(true);
player = new Player();
//floor = new Floor();
timer = new Timer(5, this);
timer.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(player.getImage(), player.getX(), player.getY(), this);
// g2d.drawImage(floor.getImage(), floor.getX(), floor.getY(), this);
//System.out.println(player.getX() + ", " + player.getY());
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void actionPerformed(ActionEvent e) {
// checkPlayerOnGround();
player.move();
repaint();
}
private class TAdapter extends KeyAdapter implements KeyListener{
public void keyTyped(KeyEvent e) {
player.keyReleased(e);
System.out.println("Released");
}
public void keyPressed(KeyEvent e) {
player.keyPressed(e);
System.out.println("Pressed");
}
}
}
here is the player class
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.Timer;
import java.util.TimerTask;
public class Player{
private String player = "player.jpg";
private int moveX;
private int moveY;
private int x;
private int y;
private Image image;
private boolean canFall = false;
//private Timer jumpTimer = new Timer();
boolean canJump = true;
public Player() {
ImageIcon playeriImage = new ImageIcon(this.getClass().getResource(player));
image = playeriImage.getImage();
x = 40;
y = 60;
}
public void checkFall() {
if(canFall) {
moveY = -4;
}
}
public void move() {
//checkFall();
x = moveX + x;
y = moveY + y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Image getImage() {
return image;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_A) {
moveX = -4;
}
if (key == KeyEvent.VK_D) {
moveX = 4;
}
if (key == KeyEvent.VK_W) {
if(canJump)
this.jump();
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_A) {
moveX = 0;
}
if (key == KeyEvent.VK_D) {
moveX = 0;
}
}
here is the exe class
import javax.swing.JFrame;
public class Exe extends JFrame {
public Exe() {
add(new Board());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
setLocationRelativeTo(null);
setTitle("TSA Video Game");
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
new Exe();
}
}
thanks in advance

KeyListener will only respond to key events IF the component is focusable AND has focus.
It would be better to use the Key Bindings API which will allow you to overcome this limitation (if you want to)
I would also recommend that you override paintComponent instead of paint. You should also not be calling Graphics#dispose, as you did not create the Graphics context, this could actually prevent anything from being painted on some systems
I would also suggest that a delay of 5 milliseconds (on your Timer) might be a little excessive (5 milliseconds = 200fps!).
A value of 16 (60fps) or 40 (25fps) may be more suitable and reduce the overhead on the system...IMHO

Related

Java TSM AdjustCapsLockLEDForKeyTransitionHandling

I am trying to capture up,down,right,left keys from KeyEvent, and I am getting following message when I press a key:
2021-06-05 00:46:11.176 java[47646:1823153] TSM AdjustCapsLockLEDForKeyTransitionHandling - _ISSetPhysicalKeyboardCapsLockLED Inhibit
This is my code:
Character.java
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class Character {
private int dx;
private int dy;
private int x;
private int y;
private String imageLocation;
private Image image;
private boolean moveable;
public Character(int x, int y, String imgLoc, boolean m){
this.x = x;
this.y = y;
imageLocation = imgLoc;
ImageIcon ii = new ImageIcon(this.getClass().getResource(imageLocation));
image = ii.getImage();
moveable = m;
}
public void move() {
if(moveable){
x += dx;
y += dy;
}
}
public boolean moveable(){
return moveable;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Image getImage() {
return image;
}
public void keyPresed(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
System.out.println("left key pressed");
dx = -1;
}
if(key == KeyEvent.VK_RIGHT){
dx = 1;
}
if(key == KeyEvent.VK_UP){
dy = -1;
}
if(key == KeyEvent.VK_DOWN){
dy = 1;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 0;
}
if (key == KeyEvent.VK_UP) {
dy = 0;
}
if (key == KeyEvent.VK_DOWN) {
dy = 0;
}
}
}
** ADDED: **
Lounge.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Lounge extends JPanel implements ActionListener{
private Timer timer;
private Player player;
public Lounge(){
//addKeyListener(new TAdapter());
setFocusable(true);
setBackground(Color.BLACK);
setDoubleBuffered(true);
player = new Player(1000, 40);
timer = new Timer(5, this);
timer.start();
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(player.getImage(), player.getX(), player.getY(), this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
player.move();
repaint();
}
private class TAdapter extends KeyAdapter{
public void keyReleased(KeyEvent e){
player.keyReleased(e);
}
public void keyPressed(KeyEvent e){
player.keyReleased(e);
}
}
}
Main.java
import javax.swing.JFrame;
public class Main extends JFrame{
public Main(){
add(new Lounge());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1280,720);
setLocationRelativeTo(null);
setTitle("Be My Guest");
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
I am using Visual Studio Code on MacBook pro 2017
Please help me!
I think the problem is with the Caps-Lock key being pressed initially, I found a similar question over here
Another problem I found is that The method keyPressed is spelt wrongly as keyPresed that may cause some issues also

My keybinding didn't do its actionPerformed in JPanel

I've added keybinding on one of my JPanels. The problem is this keybinding didn't do its "actionPerformed". Even though I put a sysout in the actionPerformed, nothing was outputted on the console. Can someone help me with this problem? I've already tried to disable my buttons, but still my keybinding doesn't work.
package project.fin;
import java.awt.*;
import java.io.*;
import java.util.List;
import java.awt.event.*;
import javax.swing.*;
//Panel for my game
public class GamePlayPanel extends JPanel{
private Image current;
private Baby bayi;
public GamePlayPanel(String img) {
Dimension size = new Dimension(1200, 500);
this.setPreferredSize(size);
this.setMaximumSize(size);
this.setMinimumSize(size);
this.setSize(size);
this.setLayout(null);
//An baby object
bayi = new Baby(100, 410, 5);
//this is where my keyBinding initialized
bayi.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0), "moveRight");
bayi.getActionMap().put("moveRight", new Move_it(1));
}
//this is the action class that i want to put in my keybinding
private class Move_it extends AbstractAction{
int code;
public Move_it(int code) {
this.code=code;
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("test\n");
if (this.code==1) {
bayi.MoveRight();
}
repaint();
}
}
//To draw my baby
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
bayi.draw(g);
}
}
This is my baby class:
package project.fin;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import java.awt.event.*;
public class Baby extends JComponent{
float x, y;
float speed;
Image current;
private List <Image> ImgPool;
private int Current;
public Baby(float x, float y, float speed) {
// TODO Auto-generated constructor stub
this.x = x;
this.y = y;
this.speed = speed;
ImgPool = new ArrayList<Image>();
//These are just some images that i use to build my moving baby
ImgPool.add(new ImageIcon("baby1_50.png").getImage());
ImgPool.add(new ImageIcon("baby2_50.png").getImage());
ImgPool.add(new ImageIcon("baby1_50.png").getImage());
ImgPool.add(new ImageIcon("baby3_50.png").getImage());
this.current = ImgPool.get(0);
this.Current = 0;
}
//The action that i want my baby to do when a key is pressed
public void MoveRight() {
if (x>600) return;
this.x+=speed;
if (this.Current==3)this.Current=0;
else
this.Current++;
this.current = this.ImgPool.get(Current);
}
public void draw(Graphics g) {
g.drawImage(this.current, (int)this.x, (int)this.y, null);
}
}
Baby isn't attached to the component hierarchy and therefore won't receive any key events. In fact, the design doesn't make sense. There's no need for Bady to extend from JPanel at all.
Instead, make use of the GamePlayPanel directly
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.*;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new GamePlayPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GamePlayPanel extends JPanel {
private Baby bayi;
public GamePlayPanel() {
//An baby object
bayi = new Baby(100, 410, 5);
//this is where my keyBinding initialized
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "moveRight");
getActionMap().put("moveRight", new Move_it(1));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1200, 500);
}
//this is the action class that i want to put in my keybinding
private class Move_it extends AbstractAction {
int code;
public Move_it(int code) {
this.code = code;
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("test\n");
if (this.code == 1) {
bayi.moveRight();
}
repaint();
}
}
//To draw my baby
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
bayi.draw(g);
}
}
public class Baby {
float x, y;
float speed;
Image current;
private List<Image> ImgPool;
private int Current;
public Baby(float x, float y, float speed) {
// TODO Auto-generated constructor stub
this.x = x;
this.y = y;
this.speed = speed;
ImgPool = new ArrayList<Image>();
//These are just some images that i use to build my moving baby
ImgPool.add(new ImageIcon("baby1_50.png").getImage());
ImgPool.add(new ImageIcon("baby2_50.png").getImage());
ImgPool.add(new ImageIcon("baby1_50.png").getImage());
ImgPool.add(new ImageIcon("baby3_50.png").getImage());
this.current = ImgPool.get(0);
this.Current = 0;
}
//The action that i want my baby to do when a key is pressed
public void moveRight() {
if (x > 600) {
return;
}
this.x += speed;
if (this.Current == 3) {
this.Current = 0;
} else {
this.Current++;
}
this.current = this.ImgPool.get(Current);
}
public void draw(Graphics g) {
g.drawImage(this.current, (int) this.x, (int) this.y, null);
}
}
}

Key Listener not working while using Image and Image Icon

So, I am using ImageIcon and Image to animate a character. So far my code makes it look like the character is running however for a reason that I can't figure out KeyListener is not working. I have been at this for a while and I am wondering what I am doing wrong. This is my code:
*Right now I took out moving up and down because I couldn't get side to side to work. velyY was going to be the change in y.
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.MediaTracker;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.*;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Image;
public class Main extends JPanel implements ActionListener,KeyListener{
ImageIcon images[];
int x = 100;
int y = 5;
int velX;
int velY;
int totalImages =3, currentImage = 0, animationDelay = 160;
Timer animationTimer;
public Main() {
images = new ImageIcon[totalImages];
images[0] = new ImageIcon("standing.png");
images[1] = new ImageIcon("ready.png");
images[2] = new ImageIcon("running.png");
startAnimation();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics g2 = (Graphics) g;
if (images[currentImage].getImageLoadStatus() == MediaTracker.COMPLETE){
Image img = images[currentImage].getImage();
g2.drawImage(img, x, 407, null);
currentImage = (currentImage + 1) % totalImages;
}
}
public void actionPerformed(ActionEvent e) {
repaint();
x+=velX;
}
public void right(){
velX = 8;
}
public void left(){
velX = -8;
}
public void keyPressed(KeyEvent arg0) {
int code = arg0.getKeyCode();
if (code == KeyEvent.VK_A){
left();
}
if(code == KeyEvent.VK_D){
right();
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){
velX = 0;
velY = 0;
}
public void startAnimation() {
if (animationTimer == null) {
currentImage = 0;
animationTimer = new Timer(animationDelay, this);
animationTimer.start();
} else if (!animationTimer.isRunning())
animationTimer.restart();
}
public void stopAnimation() {
animationTimer.stop();
}
}//end class
You have to register your KeyListener to your panel, if you want it to manage key events.
The second thing is that a JPanel is not focusable by default, so you have to make it focusable to receive key events.
In your Main constructor, just add :
setFocusable(true); // make your panel focusable
addKeyListener(this); // register the key listener

Java 2D Game dev: Multiple key input

I'm trying to get the controls working for a 2D game written in Java. However, I'm encountering an odd bug in movement. Whenever I'm trying to use the up and left controls while firing (space bar), or down and right while firing, the game is unable to detect the pressing of the space bar. Below are the relevant code excerpts:
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.ImageIcon;
public class Player {
private String playerPath = "images/craft.png";
private int x, y, dx, dy;
private Image image;
private ArrayList missiles;
private final int CRAFT_SIZE = 20;
public Player() {
ImageIcon ii = new ImageIcon(playerPath);
image = ii.getImage();
missiles = new ArrayList();
x = 20;
y = 20;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
fire();
}
if (key == KeyEvent.VK_LEFT) {
dx = -1;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 1;
}
if (key == KeyEvent.VK_UP) {
dy = -1;
}
if (key == KeyEvent.VK_DOWN) {
dy = 1;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 0;
}
if (key == KeyEvent.VK_UP) {
dy = 0;
}
if (key == KeyEvent.VK_DOWN) {
dy = 0;
}
}
public void fire() {
missiles.add(new Projectile(x + CRAFT_SIZE, y + CRAFT_SIZE/2));
}
}//end class Player
And
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Game extends JPanel implements ActionListener {
private Player player;
private Timer timer;
private int winHeight;
private int winWidth;
private final int UP = KeyEvent.VK_UP;
private final int DOWN = KeyEvent.VK_DOWN;
private final int LEFT = KeyEvent.VK_LEFT;
private final int RIGHT = KeyEvent.VK_RIGHT;
private final int SPACE = KeyEvent.VK_SPACE;
public Game(int w, int h) {
addKeyListener(new TAdapter());
setBackground(Color.BLACK);
addKeyListener(new TAdapter());
setFocusable(true);
setDoubleBuffered(true);
player = new Player();
winHeight = h;
winWidth = w;
timer = new Timer(5, this);
timer.start();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(player.getImage(), player.getX(), player.getY(), this);
ArrayList proj = player.getMissiles();
for (Object p : proj) {
Projectile b = (Projectile) p;
g2d.drawImage(b.getImage(), b.getX(), b.getY(), this);
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
// Update projectile locations
ArrayList ms = player.getMissiles();
for (int i = 0; i < ms.size(); i++) {
Projectile p = (Projectile) ms.get(i);
if (p.getX() <= winWidth) {
p.move();
} else {
ms.remove(p);
}
}
player.move();
repaint();
}
private class TAdapter extends KeyAdapter {
#Override
public void keyReleased(KeyEvent e) {
player.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
player.keyPressed(e);
}
}// end class TAdapter
}// end class Game
Whenever I'm trying to use the up and left controls while firing (space bar), or down and right while firing, the game is unable to detect the pressing of the space bar.
KeyEvents are only generated for the last key pressed. If you want to handle multiple keys being pressed at the same time then you need to:
keep track of a key that has been pressed/released
use a Swing Timer to schedule the animation.
Then whenever the timer fires you check which keys are currently pressed and the do the action for that key.

Lag in simple side scrolling game in Java

I recently built my first simple side scrolling game in java, but I'm experiencing some lag and I don't know why. When I move my character sideways it seems to be changing speed, most of the time going fast but sometimes slowing down. It makes the feel of the game very odd. I hope someone can point me in the right direction here, I'll post my classes below:
Main Class:
public class MainGame {
public static void main(String[] args) {
Frame frame = new Frame();
}
}
Frame Class:
import javax.swing.JFrame;
public class Frame extends JFrame{
public Frame(){
add(new Board());
setTitle("2-D Test Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800,325);
this.setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
}
}
Board Class:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Board extends JPanel implements ActionListener{
private Player p;
private Timer timer;
private Image background;
public Board(){
super();
p = new Player();
addKeyListener(new ActionListener());
setFocusable(true);
ImageIcon i = new ImageIcon("C:/test.png");
background = i.getImage();
timer = new Timer(5,this);
timer.start();
}
public void actionPerformed(ActionEvent arg0) {
p.move();
repaint();
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(background,p.nx,0,null);
g2d.drawImage(p.getImage(), 350, p.getY(), null);
}
private class ActionListener extends KeyAdapter{
public void keyReleased(KeyEvent e){
p.keyReleased(e);
}
public void keyPressed(KeyEvent e){
p.keyPressed(e);
}
}
}
Player Class:
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Player {
private Image img;
int x,y,dx,dy,nx;
long time;
private final int SPEED = 2;
private final int GRAV = 1;
boolean left,right,isJumping;
public Player(){
ImageIcon i = new ImageIcon("C:/plager.png");
img = i.getImage();
x = 350;
y = 160;
dx = 0;
dy = 0;
nx = 0;
left = false;
right = false;
isJumping = false;
}
public void move(){
x += dx;
nx = (nx-dx);
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public Image getImage(){
return img;
}
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_LEFT){
left = false;
if(right){
dx = SPEED;
}else{
dx = 0;
}
}else if(code == KeyEvent.VK_RIGHT){
right = false;
if(left){
dx = -SPEED;
}else{
dx = 0;
}
}
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_LEFT){
left = true;
dx = -SPEED;
}else if(code == KeyEvent.VK_RIGHT){
right = true;
dx = SPEED;
}
}
}
Timer does not have a real time guarantee. So, you should calculate the time difference from the last time move was called and multiply that by the amount you are moving. It will make the numbers smaller so I would add another const to make it larger. It's actually better get the time delta in actionPerformed (or another process method) and pass it to all of the process or move methods so everything moves using the same time delta.

Categories