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.
Related
i am trying to take keyboard inputs to change the boolean's value but keylisteners are not working
those bolleans values will be used later in other class
heres the method i am having issues with
public boolean upPressed, downPressed, leftPressed, rightPressed;
#Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_W){
upPressed = true;}
else if(code == KeyEvent.VK_S){
downPressed = true;}
else if(code == KeyEvent.VK_A){
leftPressed = true;}
else if(code == KeyEvent.VK_D){
rightPressed = true;}
}
i am using a different class which extends JPanel, frame is in a different class and key listener is in a different class and i have this.setFocusable(true);this.addKeyListener(keyH);
and if u want, here's the full code : https://github.com/PROMAN8625/2dGAME
Your code snippet looks fine. Maybe you didn't add KeyListener to the frame.
Here is a working example:
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Label;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyListenerExample implements KeyListener
{
public boolean upPressed, downPressed, leftPressed, rightPressed;
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if (code == KeyEvent.VK_W) {
upPressed = true;
}
else if(code == KeyEvent.VK_S){
downPressed = true;}
else if(code == KeyEvent.VK_A){
leftPressed = true;}
else if(code == KeyEvent.VK_D){
rightPressed = true;}
System.out.println("The key Pressed was: " + e.getKeyChar());
System.out.println("upPressed: " + upPressed);
System.out.println("downPressed: " + downPressed);
System.out.println("leftPressed: " + leftPressed);
System.out.println("rightPressed: " + rightPressed);
System.out.println("\n");
}
#Override
public void keyReleased(KeyEvent e) {
}
public static void main(String[] args)
{
//Setting the Frame and Labels
Frame f = new Frame("Demo");
f.setLayout(new FlowLayout());
f.setSize(500, 500);
Label l = new Label();
l.setText("This is a demonstration");
f.add(l);
f.setVisible(true);
//Creating and adding the key listener
KeyListenerExample k = new KeyListenerExample();
f.addKeyListener(k);
}
}
I will only supply the relevant parts of the code as it is quite large. Help me figure out why I never get keyboard events to the GameBoard JPanel. The game code runs just fine until I added the new feature where I wanted it to have a welcome screen.
Edit: If you would like to view the entire project (it's an eclipse project), here is the link to download it Eclipse project, I honestly can't format almost 1000 lines of code here on StackOverflow, that'll be painful even for you.
Main.java
private void initUI() throws IOException {
cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);
welcomeMenu = new Welcome(cardLayout, mainPanel);
mainPanel.add(welcomeMenu, "welcome");
game = new GameBoard();
mainPanel.add(game, "game");
add(mainPanel);
setTitle("Pacman");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(380, 420);
setLocationRelativeTo(null);
}
This is the welcome/menu panel (some section of it).
Welcome.java (servers as a menu)
#Override
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand() == Actions.EXIT.name()) {
System.exit(0);
} else if (evt.getActionCommand() == Actions.CONFIG.name()) {
JOptionPane.showMessageDialog(null, "Not yet implemented");
} else if (evt.getActionCommand() == Actions.PLAY.name()) {
// The part that switches to game, works as expected.
cl.show(mp, "game");
}
}
GameBoard class has a KeyAdapter class within it that is used to listen to key events, however, in the addition of the new feature using CardLayout, I could not get the key events to the panel so my PacMan is just stuck in one place opening and closing its mouth like a fish.
GameBoard.java
private void initBoard() {
addKeyListener(new TAdapter());
setFocusable(true);
setBackground(Color.black);
initGame();
}
...
class TAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (inGame) {
if (key == KeyEvent.VK_LEFT) {
req_dx = -1;
req_dy = 0;
} else if (key == KeyEvent.VK_RIGHT) {
req_dx = 1;
req_dy = 0;
} else if (key == KeyEvent.VK_UP) {
req_dx = 0;
req_dy = -1;
} else if (key == KeyEvent.VK_DOWN) {
req_dx = 0;
req_dy = 1;
} else if (key == KeyEvent.VK_ESCAPE && timer.isRunning()) {
inGame = false;
} else if (key == KeyEvent.VK_PAUSE) {
if (timer.isRunning()) {
timer.stop();
} else {
timer.start();
}
}
} /*
* else { if (key == 's' || key == 'S') { inGame = true; initGame(); } }
*/
}
#Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == Event.LEFT || key == Event.RIGHT || key == Event.UP || key == Event.DOWN) {
req_dx = 0;
req_dy = 0;
}
}
}
The issue was using Key Listener when I should have been using Key Binding in the GameBoard JPanel. So instead of this,
class TAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (inGame) {
...
} else if (key == KeyEvent.VK_UP) {
req_dx = 0;
req_dy = -1;
} else if (key == KeyEvent.VK_DOWN) {
...
}
}
}
I replaced it with this approach (I will only demonstrate Arrow Up scenario),
private class UpAction extends AbstractAction {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
if (!inGame)
return;
req_dx = 0;
req_dy = -1;
}
}
...
private void setupKeyListeners() {
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "doUp");
...
getActionMap().put("doUp", new UpAction());
...
}
And later on,
private void initBoard() {
setupListeners();
setFocusable(true);
setBackground(Color.black);
initGame();
}
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 have managed to pause the game using *running = !running
But it's unable to unpause if this is used
And thread.resume() or thread.wait() doesn't work either to unpause it when 'P' is pressed
private volatile boolean running;
private Thread thread;
public static enum STATE {
MENU,
GAME,
};
public static STATE State = STATE.MENU;
public void init(){
requestFocus();
}
private synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
private synchronized void stop(){
if(!running)
return;
running = false;
try{
thread.join();
}catch(InterruptedException e){
e.printStackTrace();
}
}
public void run() {
init();
while(running){
/some codes
}
stop();
}
private void render(){
if(State == STATE.GAME){
p.render(g);
c.render(g);
}else if(State == STATE.MENU){
menu.render(g);
}
g.dispose();
bs.show();
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(State == STATE.GAME){
if(key == KeyEvent.VK_RIGHT){
p.setVelX(5);
}else if(key == KeyEvent.VK_LEFT){
p.setVelX(-5);
}else if(key == KeyEvent.VK_DOWN){
p.setVelY(5);
}else if(key == KeyEvent.VK_UP){
p.setVelY(-5);
}else if(key == KeyEvent.VK_SPACE && !is_shooting){
c.addEntity(new Bullet(p.getX(), p.getY(), tex, this));
is_shooting = true;
}else if(key == KeyEvent.VK_P){
This line is to pause.
running = !running;
}
}
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT){
p.setVelX(0);
}else if(key == KeyEvent.VK_LEFT){
p.setVelX(0);
}else if(key == KeyEvent.VK_DOWN){
p.setVelY(0);
}else if(key == KeyEvent.VK_UP){
p.setVelY(0);
}else if(key == KeyEvent.VK_SPACE){
is_shooting = false;
}else if(key == KeyEvent.VK_P){
// This line doesn't work.
running = true;
}
}
At the moment, as soon as running is set to false, your game thread exits (run() method returns).
public void run() {
init();
while(running){
/some codes
}
stop();
}
Should be changed to something more like this:
public void run() {
init();
while(true){
if(!running) {
Thread.sleep(1000); //1 second or something else
continue;
}
//Game logic here
}
stop();
}
You will of course need to differentiate between running and paused, to be able to break out of this loop.
Setting running = !runnning will just change the variable, you're not actually stopping anything unless you're using the variable in the game loop.
To pause the method, use Thread.sleep()or simply stop the thread, then start it again if you don't know how long you want to pause it for.
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)