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.
Related
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
i'm teaching myself to program in java, and i have decided to make an space invader game. i got my ship moving in any direction, but i have a problem with my bullet being fired. now i know that my y-coordinate of the bullet are being updated every time my ship moves, but it is not firing. I need someone to help me get it to fire if possible. any help is welcome.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Panel extends JPanel implements KeyListener, ActionListener{
private int x;
private int y;
private int dx;
private int dy;
int bx;
int by;
Rectangle bullet;
Timer timer;
private Image image;
public Panel() {
timer = new Timer(30, this);
setBackground(Color.black);
addKeyListener(this);
setFocusable(true);
timer.start();
x=130;
y=430;
bx=xPost()+55;
by=yPost();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
ImageIcon ii= new ImageIcon("C:\\Users\\TriZam\\workspace\\LearningSprite\\ship.png");
image=ii.getImage();
g.drawImage(image, x, y, this);
doDrawing(g);
}
public void move(){
// thhis method will be placed inside the interferance ActionPerformed in order to move the ship and bullet
x += dx;
y += dy;
bx += dx;
by += dy;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = -3;
if (x<=-25){
dx=0;
}
}
if (key == KeyEvent.VK_RIGHT) {
dx = 3;
if (x>=380 ){
dx=0;
}
}
if (key == KeyEvent.VK_UP) {
dy = -3;
if (y<=0 ){
dy=0;
}
}
if (key == KeyEvent.VK_DOWN) {
dy = 3;
if (y>=430 ){
dy=0;
}
}
if(key ==KeyEvent.VK_SPACE){
// bullet shooting and as you can see the y coordinate updates but bullet not moving.
bullet.y--;
System.out.println(bullet.y--);
}
}
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;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent arg0) {
move();
repaint();
}
int yPost(){
return y;
}
int xPost(){
return x;
}
void doDrawing(Graphics g) {
bullet = new Rectangle(bx, by, 10, 10);
g.setColor(Color.white);
g.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
}
}
This is the main class
import javax.swing.JFrame;
public class MainClass extends JFrame {
private int FrameWidth;
private int FrameHeigh;
private Panel panel;
public MainClass(int width, int height ) {
panel= new Panel();
this.FrameWidth=width;
this.FrameHeigh=height;
setSize(FrameWidth,FrameHeigh);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(panel);
setVisible(true);
}
public static void main(String[] args) {
MainClass m= new MainClass(500, 600);
}
}
create the bullet once ; not inside paint and drawing - inside the constructor;
move this out of
void doDrawing(Graphics g) {
--> remove this from here and into the constructor --> bullet = new Rectangle(bx, by, 10, 10);
also when you update the location of the bullet dont use bx, by and separate variables; just do
bullet.x=....new location
bullet.y=....new location
Inside your key pressed space event, you should create an instance of a bullet. As of right now, you have a member variable Bullet; however it is null since it's never been initialized. That being said, you'll also want to move your bullet--this should be done in your move function.
I see that you have a bx, by, which I'm assuming is suppose to be the bullet's x and y position. However, the rectangle's coordinates never update. Instead of incrementing bx and by, update the rectangle (You'll also want to repaint the rectangle).
Hi I am new to making games, and I am working on one for a project. My code however does not make the Ship image move. Can someone help with a reasonable and simple explanation? Maybe even explain how to do this a bit simpler?
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
import java.awt.geom.*;
import java.util.Random;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class SpaceJam extends JPanel implements ActionListener
{
private Timer time;
private ImageIcon Ship = new ImageIcon("Spaceship.PNG");
private ImageIcon Back = new ImageIcon("background.PNG");
private ImageIcon Test = new ImageIcon("test.PNG");
private int x, y, dx, dy;
private Image CurrentImage = Ship.getImage();
public SpaceJam()
{
addKeyListener(new AL());
setFocusable(true);
x = 100;
y = 100;
dx = 0;
dy = 0;
time = new Timer(100, this);
time.start();
}
public void actionPerformed(ActionEvent e)
{
repaint();
move();
}
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(Back.getImage() ,0,0,null);
g2d.drawImage(CurrentImage, x, y, null);
}
public void move()
{
x += dx;
y += dy;
}
public class AL extends KeyAdapter
{
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT)
{
dx = 5;
move();
}
if (key == KeyEvent.VK_LEFT)
{
dx = -5;
move();
}
}
}
}
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
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.