I'm trying to make a game in java, just a simple platformer, but I'm having difficulty when running the code. I can't seem to get any response from key presses. The only thing I can think hasn't been working properly is the keyPressed and keyReleased functions. Below is the relevant code.
public ReflexPanel() {
initBoard();
setFocusable(true);
addKeyListener(this);
Timer timer = new Timer(1000/120, this);
timer.start();
}
private void initBoard() {
loadMenu();
int w = menu.getWidth(this);
int h = menu.getHeight(this);
setPreferredSize(new Dimension(w, h));
}
private void step() {
if(mainMenu){
if(ePressed) {
System.exit(0);
}
if(hPressed) {
loadScores();
repaint();
}
}
}
public void keyTyped(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 'e') {
ePressed = true;
}
if (e.getKeyCode() == 'h') {
hPressed = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == 'e') {
ePressed = false;
}
if (e.getKeyCode() == 'h') {
hPressed = false;
}
}
#Override
public void actionPerformed(ActionEvent e) {
step();
}
The ePressed and hPressed variables are just booleans set to false by default, and loadScores calls a png file.
You can't do this:
if(e.getKeyCode() == 'e'){
// code logic
}
KeyEvent::getKeyCode doesn't return the char you press on the keyboard. It "returns the integer keyCode associated with the key in this event". When using KeyEvent::getKeyCode you have to use the KeyEvent key constants values predefined in the class. So for example:
if(e.getKeyCode() == KeyEvent.VK_E){
// code logic
}
Or you can use KeyEvent::getKeyChar which "returns the character associated with the key in this event".
You're using getKeyCode() which returns an int value with constants given in KeyEvent class, such as KeyEvent.VK_E.
You're looking to use getKeyChar() which returns 'e' directly.
if (e.getKeyChar() == 'e') { // Now it has an actual chance of working
If I move my player1 and player2 up, and let's say I push the down key for player1, my player stops moving up. I can't find the problem. Can someone please help me and explain what I did wrong?
package game;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class KeyInput extends KeyAdapter{
private Handler handler;
private boolean [] keyPressed = new boolean [4];
public KeyInput(Handler handler){
this.handler = handler;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
keyPressed[0]= false;
keyPressed[1]= false;
keyPressed[2]= false;
keyPressed[3]= false;
for(int i = 0; i <handler.object.size(); i++){
GameObject tempobject= handler.object.get(i);
if (tempobject.getId()== ID.Player1){
if (key == KeyEvent.VK_UP){tempobject.setSpeedy(-7); keyPressed[0] = true;}
if (key == KeyEvent.VK_DOWN){tempobject.setSpeedy(7); keyPressed[1] = true;}
}
if(tempobject.getId()== ID.player2)
if (key == KeyEvent.VK_W){tempobject.setSpeedy2(-7); keyPressed[2] = true;}
if (key == KeyEvent.VK_S){tempobject.setSpeedy2(7); keyPressed[3] = true;}
}
if(key == KeyEvent.VK_ESCAPE)System.exit(1);
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
for(int i = 0; i <handler.object.size(); i++){
GameObject tempobject= handler.object.get(i);
if (tempobject.getId()== ID.Player1){
if (key == KeyEvent.VK_UP) keyPressed[0] = false;
if (key == KeyEvent.VK_DOWN) keyPressed[1] = false;
if(!keyPressed[0] && !keyPressed[1])tempobject.setSpeedy(0);
}
if (tempobject.getId()== ID.player2){
if (key == KeyEvent.VK_W) keyPressed[2] = false;
if (key == KeyEvent.VK_S) keyPressed[3] = false;
if(!keyPressed[2] && !keyPressed[3])tempobject.setSpeedy2(0);
}
}
}
}
It probably has to do with this:
keyPressed[0]= false;
keyPressed[1]= false;
keyPressed[2]= false;
keyPressed[3]= false;
This would make it so that whenever any key is pressed, the other keys are set to false, even if they may still be being held down.
I am trying to make a game in Java and this is my first time dealing with multithreading (well, asides from playing music concurrently via the Clip class.) I have a Canvas class which extends JPanel, but within the Canvas class I also have a KeyListener to take input, shown here:
private class myKeyListener implements KeyListener
{
public void keyPressed(KeyEvent keyEvent)
{
if(keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE){System.exit (0);}
Thread thread3 = new Thread()
{
public void run() {
if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT){moveX(5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT){moveX(-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_UP){moveY(-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN){moveY (5, player1);}
}
};
Thread thread4 = new Thread()
{
public void run() {
if(keyEvent.getKeyCode() == KeyEvent.VK_D){moveX(5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_A){moveX(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_W){moveY(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_S){ moveY(5, player2);}
}
};
Thread thread5 = new Thread()
{
public void run() {
repaint();
}
};
thread3.start();
thread4.start();
thread5.start();
try{
thread3.join();
thread4.join();
thread5.join();
}
catch (Exception e){System.out.println(e);}
repaint();
}
public void keyReleased(KeyEvent keyEvent)
{
}
public void keyTyped(KeyEvent keyEvent)
{
}
}
My goal is to have it so that one can move both players (which are Rectangles) at the same time on the canvas. Currently, one can only move them one at a time, but never both at the same time. This is my first time dealing with multithreading so I apologize in advance if I am making a rookie mistake.
Here is the code.
You need just one thread, to do the "game loop".
import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.util.ArrayList;
public class Canvas2 extends JPanel {
// attributes
private Rectangle player1;
private Rectangle player2;
private ArrayList<KeyEvent> log;
private boolean player1left = false;
private boolean player1right = false;
private boolean player1up = false;
private boolean player1down = false;
private boolean player2left = false;
private boolean player2right = false;
private boolean player2up = false;
private boolean player2down = false;
// constructor
public Canvas2() {
// initialize object
player1 = new Rectangle(50, 50, 50, 50);
player2 = new Rectangle(50, 50, 50, 50);
log = new ArrayList<KeyEvent>();
// set canavs background colour
setBackground(Color.white);
// add the key listener in the constructor of your canavas/panel
addKeyListener(new myKeyListener());
// ensure focus is on this canavas/panel for key operations.
setFocusable(true);
Thread gameLoop = new Thread() {
public void run() {
while (true) {
updatePlayers();
repaint();
pause(10);
}
}
};
gameLoop.start();
}
private void updatePlayers() {
if (player1left) {
moveX(-5, player1);
}
if (player1right) {
moveX(5, player1);
}
if (player1up) {
moveY(-5, player1);
}
if (player1down) {
moveY(5, player1);
}
if (player2left) {
moveX(-5, player2);
}
if (player2right) {
moveX(5, player2);
}
if (player2up) {
moveY(-5, player2);
}
if (player2down) {
moveY(5, player2);
}
}
// painting
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D graphics2d = (Graphics2D) graphics;
graphics.setColor(Color.blue);
graphics2d.fill(player1);
graphics2d.fill(player2);
}
// function which essentially re-creates rectangle with varying x
// orientations. (x-movement)
public void moveX(int mutationDistance, Rectangle sampleObject) {
sampleObject.setBounds(sampleObject.x + mutationDistance,
sampleObject.y, sampleObject.width, sampleObject.height);
}
// function which essentially re-creates rectangle with varying y
// orientations. (y-movement)
public void moveY(int mutationDistance, Rectangle sampleObject) {
sampleObject.setBounds(sampleObject.x, sampleObject.y
+ mutationDistance, sampleObject.width, sampleObject.height);
}
// listener
private class myKeyListener implements KeyListener {
// implement all the possible actions on keys
public void keyPressed(final KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE) {
System.exit(0);
}
if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
player1right = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
player1left = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
player1up = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
player1down = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_D) {
player2right = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_A) {
player2left = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_W) {
player2up = true;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_S) {
player2down = true;
}
}
public void keyReleased(KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
player1right = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
player1left = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_UP) {
player1up = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
player1down = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_D) {
player2right = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_A) {
player2left = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_W) {
player2up = false;
}
if (keyEvent.getKeyCode() == KeyEvent.VK_S) {
player2down = false;
}
}
public void keyTyped(KeyEvent keyEvent) {
}
}
public static void pause(int secs) {
try {
Thread.sleep(secs);
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.util.ArrayList;
/**
* This code was originally by the user "UniBrain" from the website:
* http://forum.codecall.net/topic/74377-moving-graphics-across-up-and-down-a-jpanel/?p=652384
*
* but has been modified by me for my own purposes
*/
public class Canvas2 extends JPanel
{
//attributes
private Rectangle player1;
private Rectangle player2;
private ArrayList<KeyEvent> log;
//constructor
public Canvas2()
{
//initialize object
player1 = new Rectangle (50, 50, 50, 50);
player2 = new Rectangle (50, 50, 50, 50);
log = new ArrayList<KeyEvent>();
//set canavs background colour
setBackground (Color.white);
//add the key listener in the constructor of your canavas/panel
addKeyListener(new myKeyListener());
//ensure focus is on this canavas/panel for key operations.
setFocusable(true);
}
//painting
public void paintComponent(Graphics graphics)
{
super.paintComponent(graphics);
Graphics2D graphics2d =(Graphics2D)graphics;
graphics.setColor(Color.blue);
graphics2d.fill(player1);
graphics2d.fill(player2);
}
//function which essentially re-creates rectangle with varying x orientations. (x-movement)
public void moveX(int mutationDistance, Rectangle sampleObject)
{
sampleObject.setBounds(sampleObject.x + mutationDistance, sampleObject.y, sampleObject.width, sampleObject.height);
}
//function which essentially re-creates rectangle with varying y orientations. (y-movement)
public void moveY(int mutationDistance, Rectangle sampleObject)
{
sampleObject.setBounds(sampleObject.x, sampleObject.y + mutationDistance, sampleObject.width, sampleObject.height);
}
public void move(){
/*
* This method of keeping track of key events and using a loop is taken from the user Michael Meyers at
* http://stackoverflow.com/questions/752999/how-do-i-handle-multiple-key-presses-in-java
*/
Thread thread1 = new Thread()
{
public void run() {
for(KeyEvent keyEvent: log){
if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT){moveX(5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT){moveX (-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_UP){moveY (-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN){moveY (5, player1);}
}
}
};
Thread thread2 = new Thread()
{
public void run() {
for(KeyEvent keyEvent: log){
if(keyEvent.getKeyCode() == KeyEvent.VK_D){moveX(5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_A){moveX(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_W){moveY(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_S){moveY(5, player2);}
}
}
};
//Starts the threads
thread1.start();
thread2.start();
//Waits for them to finish
try{
thread1.join();
thread2.join();
log = new ArrayList<KeyEvent>();
}
catch (Exception e){System.out.println(e);}
}
//listener
private class myKeyListener implements KeyListener
{
//implement all the possible actions on keys
public void keyPressed(KeyEvent keyEvent)
{
if(keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE){System.exit (0);}
Thread thread3 = new Thread()
{
public void run() {
if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT){moveX(5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT){moveX(-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_UP){moveY(-5, player1);}
if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN){moveY (5, player1);}
}
};
Thread thread4 = new Thread()
{
public void run() {
if(keyEvent.getKeyCode() == KeyEvent.VK_D){moveX(5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_A){moveX(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_W){moveY(-5, player2);}
if(keyEvent.getKeyCode() == KeyEvent.VK_S){ moveY(5, player2);}
}
};
Thread thread5 = new Thread()
{
public void run() {
repaint();
}
};
thread3.start();
thread4.start();
thread5.start();
try{
thread3.join();
thread4.join();
thread5.join();
}
catch (Exception e){System.out.println(e);}
repaint();
}
public void keyReleased(KeyEvent keyEvent)
{
}
public void keyTyped(KeyEvent keyEvent)
{
}
}
public static void pause(int secs){
try{Thread.sleep(secs*0);} catch(Exception e){}
}
}
which is then executed by this class
import javax.swing.JFrame;
import java.awt.Dimension;
/**
* This code was taken from the user "UniBrain" from the website:
* http://forum.codecall.net/topic/74377-moving-graphics-across-up-and-down-a-jpanel/?p=652384
*/
public class Display
{
public static void main ( String [ ] arguments )
{
JFrame frame = new JFrame("key listener demo");
Canvas2 panel = new Canvas2();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setContentPane(panel);
frame.setPreferredSize(new Dimension(800, 600));
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.pack();
}
}
I am trying to shoot a missile at a certain rate but currently you can simple hold down the fire button (Space) and it will make a continuous line of missiles.
I believe this is because the KeyEvent is being triggered when you hold it down when what I need it to do is only trigger once when you hold it down.
How would I make it detect the holding down of a button as only pressing it once?
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
fire();
}
if (key == KeyEvent.VK_A) {
dx = -1;
}
if (key == KeyEvent.VK_D) {
dx = 1;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
}
if (key == KeyEvent.VK_A) {
dx = 0;
}
if (key == KeyEvent.VK_D) {
dx = 0;
}
}
Just add a check to make sure you've released the key before allowing yourself to fire again. I use AtomicBoolean to ensure there are no multithreading issues by the different events getting fired.
private final AtomicBoolean canShoot = new AtomicBoolean(true);
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
if (canShoot.compareAndSet(true, false)) {
fire();
}
}
// snip
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
canShoot.set(true);
}
// snip
}
I'm having problems with wall collision. Basically I want my player to stop whenever it collides with a block.
Here's what I did so far:
Keylistener set up:
addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_A){
pressL = true;
}
if(e.getKeyCode() == KeyEvent.VK_D){
pressR = true;
}
if(e.getKeyCode() == KeyEvent.VK_W){
pressU = true;
}
if(e.getKeyCode() == KeyEvent.VK_S){
pressD = true;
}
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_A){
pressL = false;
}
if(e.getKeyCode() == KeyEvent.VK_D){
pressR = false;
}
if(e.getKeyCode() == KeyEvent.VK_W){
pressU = false;
}
if(e.getKeyCode() == KeyEvent.VK_S){
pressD = false;
}
}
public void keyTyped(KeyEvent e){
}
});
Player's movement:
public void playerMovement(){
player.horizontalMovement(0);
player.verticalMovement(0)
map.horizontalMovement(0);
map.verticalMovement(0);
if(pressR && !pressL && !pressU && !pressD){
if(!east){
toggleRight();
}
if(collision("east"))
east = true;
}
if(pressL && !pressR && !pressD && !pressU){
if(!west)
toggleLeft();
if(collision("west"))
west = true;
}
if(pressD && !pressU && !pressR && !pressL){
if(!south)
toggleDown();
if(collision("south"))
south = true;
}
if(pressU && !pressD && !pressL && !pressR){
if(!north)
toggleUp();
if(collision("north"))
north = true;
}
}
Here's where the collision test is:
public boolean collision(String loc){
Rectangle pR = player.getBound();
Rectangle pM = map.getBound(0, 0);
if(loc.equals("east")){
if(pR.equals(pM)){
if(west)
return false;
if(!west)
return true;
} west = false; south = false;north = false;
}
if(loc.equals("west"))
if(pR.intersects(pM)){
if(east)
return false;
if(!east)
return true;
} east = false; south = false;north = false;
}
if(loc.equals("south")){
if(pR.intersects(pM)){
if(north)
return false;
if(!north)
return true;
} north = false; west = false;east = false;
}
if(loc.equals("north")){
if(pR.intersects(pM)){
if(south)
return false;
if(!south)
return true;
} south = false; west = false;east = false;
}
return false;
}
I set up my code likes this to avoid being stuck whenever I collide with a block I'm testing with. It works but there are a lot of bugs I'm encountering. One example is sometimes I get stuck, or the player can pass through the block with pressing the vertical with the horizontal keys. I'm having problems figuring out the proper algorithm for this. And by the way the direction is based on the viewer's direction not the player's.
Can someone share with me a descent way of do it? Thanks.
For player and walls (blocks) create Shapes (e.g. Polygon can be used). The use Shape's methods
public boolean intersects(double x, double y, double w, double h);
public boolean intersects(Rectangle2D r);
Or you can create Areas from the Shapes and use
public void intersect(Area rhs)