I'm trying to code a game similar to Mario in Java and am having problems with making the dude jump while he is running. What the below code ends up doing is, as the user is holding down right and presses the jump button, Mario basically stops running and jumps, so its like the user has let go of right and pressed jump.
public void keyPressed(KeyEvent e) {
// here I keep track of what buttons the user pressed
int keyCode = e.getKeyCode();
if(keyCode == 37)
pressedKeys[0] = true;
else if(keyCode == 39)
pressedKeys[1] = true;
else if(keyCode == 68)
pressedKeys[2] = true;
// after I see what the user has pressed an action is carried out
Thread t = new Thread(this);
t.start();
}
public void performAction()
{
// depending on what the user has pressed a certain action is performed
if(pressedKeys[2]==true)
{
// changes the coordinates of the character itself
// done in another thread so the background can continue
// moving as the user holds down a direction
Thread t = new Thread(mcControl);
t.start();
}
if(pressedKeys[0]==true)
{
changeSprite();
bg.moveImageForward();
}
if(pressedKeys[1]==true)
{
changeSprite();
bg.moveImageBackward();
}
}
public void run() {
performAction();
}
if(keyCode == 37)
Not related to your problem, but NEVER use code like that. Most people don't know what that magic number means.
The better way to do this is to use:
if(keyCode == KeyEvent.VK_???)
Now your code is self documenting.
You want to take a look at How to Write a Key Listener. The KeyEvent object has several methods for learning what modifier keys and mouse buttons were pressed at the time the event was generated.
Related
Wasn't sure how to word the title.
I have some code for my "space invaders" type game. I made the entire thing just making adjustments. To shoot, i use spacebar. The problem is im able to hold spacebar and it continually shoots. I would rather have to press it multiple times (if i hold it down.. for it not to continually fire) How would i change it?
*here is the code i believe is the source of the problem. If the source is located elsewhere please say so.
private class KeyInputHandler extends KeyAdapter {
private int pressCount = 1;
/**
* key pressed
*/
public void keyPressed(KeyEvent e) {
if (waitingForKeyPress) {
return;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
leftPressed = true;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
rightPressed = true;
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
firePressed = true;
}
}
/**
* Key Released
*/
public void keyReleased(KeyEvent e) {
if (waitingForKeyPress) {
return;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
leftPressed = false;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
rightPressed = false;
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
firePressed = false;
}
}
added code
public class ShotEntity extends Entity {
//vertical speed
private double moveSpeed = -300;
private Game game;
private boolean used = false;
/**
* Create a new shot from the player
*/
public ShotEntity(Game game,String sprite,int x,int y) {
super(sprite,x,y);
this.game = game;
dy = moveSpeed;
}
/**
* Request that this shot moved based on time
*/
public void move(long delta) {
super.move(delta);
if (y < -100) {
game.removeEntity(this);
}
}
//collision
public void collidedWith(Entity other) {
// prevents double kills.
if (used) {
return;
}
// alien killed
if (other instanceof AlienEntity) {
game.removeEntity(this);
game.removeEntity(other);
game.notifyAlienKilled();
used = true;
}
}
}
Listen for two seperate key events. One when the key is pressed, and one when it is released. Now, you make a boolean.
public boolean myBoolean;
When the key is pressed, set the boolean to true (myBoolean==true)and if it is released, set it to false (myBoolean==false).
Now, create a simple if statement:
if(myBoolean==true){ //Key is being held down
//execute this code
//Have nothing be done
}
Thats it!
P.S. If you want, you can have one separate method to clean up the code. This method could just change the value of the boolean:
public void changeValueOfBoolean(Boolean b){
if(b = true){
return false;
}
if(b==false){
return true;
}
}
It's very simple. Let me know if you need any help, and if this was helpful, please mark it as best answer. Feel free to ask me any questions, I am always happy to help!
Clarifications:
Okay, so we have this boolean, right? Now, this boolean essencialy decides whether the key is pressed or not.
Say we press the button:
Because the key is being held down, we make the boolean myBoolean as true. Now, because the user is holding the key down, we want to do nothing, right? That's why we created that if statement:
if(myBoolean==true){ //Key is being held down
//execute this code
//Have nothing be done
}
It says, if the boolean is true, then we won't do anything. Recall, the boolean is true when the key is being held down, remember? So, when the key is held down, the boolean is true, and nothing will be done.
Now, when the user releases the key:
Now, say the user has pressed the key. This will call two listeners. One listener for when the key is pressed and another for when it is released. If the user just presses the key, myBoolean will end as false, since they have let go of the key. Therefore, we can execute some code when myBoolean is false (shooting).
**In summary:
myBoolean is true when when the key is being held down. So, when it is true, we do nothing. myBoolean is false when the user lets go of the key, and there, we shoot the space invaders.**
Simple, just have a Boolean variable which causes the ship to shoot only when it is true. Then set it to true in the space bar is pressed and set it to false when the ship shoots. I can't show you how to implement it in your program as I don't know how your shoot method works. However, if you were to post the method which causes the ship to shoot then, I could show you how to implement it or, you could try your self.
Hi I'm new to stackoverflow so bear with me if I make mistakes.
I'm making this Java Simon Says Game for a class project. It works by a random number generator for each sequence#. I show the sequence through doClick() but remove the actionlisteners beforehand and add it afterwards.
The problem is the buttons won't unpress or unarm until all other buttons have been pressed. I've tried using thread.sleep to put a delay between each if...else statements yet it only stays pressed for longer. I've tried updating the gui through repaint(), revalidate(), updateUI() within the try... catch of the thread.sleep but that didn't work either.
I've realized this issue is mainly cosmetic because when I tried implementing setPressed or setArmed it said it wasn't being pressed but it looked pressed.
Here is the code snippet in it's most simplest form without thread.sleep or my previous attempts in comments.
public void sequence2() //This is where the issue happens. The buttons won't unpress until every button has been pressed.
{
level.setText(" Level 2"); //Level indicator
Green.removeActionListener(Listener);
Red.removeActionListener(Listener);
Yellow.removeActionListener(Listener);
Blue.removeActionListener(Listener);
if(sequence1 == 1)
{
Green.doClick(300); //Programmatically clicks the button
}
else if(sequence1 == 2)
{
Red.doClick(300);
}
else if(sequence1 == 3)
{
Yellow.doClick(300);
}
else if(sequence1 == 4)
{
Blue.doClick(300);
}
if(sequence2 == 1)
{
Green.doClick(300);
}
else if(sequence2 == 2)
{
Red.doClick(300);
}
else if(sequence2 == 3)
{
Yellow.doClick(300);
}
else if(sequence2 == 4)
{
Blue.doClick(300);
}
Green.addActionListener(Listener);
Red.addActionListener(Listener);
Yellow.addActionListener(Listener);
Blue.addActionListener(Listener);
}
I'm very new to java so I'm not skilled in multithreading or working on the Event Dispatch Thread for that manner. But if that's the only solution I'll need some more help with that.
I have the full code in a zip file with previous attempts commented out if that will help.
https://drive.google.com/file/d/0Bxg4WleC9jD2VFhoZmZBNjV6Vkk/view?usp=sharing
Invoking doClick() may be an awkward choice for this, as it uses a Timer internally. Instead, use a JToggleButton, which will allow you to control each button's appearance based on its selected state using setSelected(). A complete example is shown in the game Buttons. In the ActionListener of your Swing Timer, select the current button, play its note and increment the sequence index. When all notes have been played, unselect all the buttons.
Addendum: Can you show how you implement the timer?
In outline, given a suitable list of toggle buttons:
private static final int MAX = 4;
List<JToggleButton> buttons = new ArrayList<JToggleButton>(MAX);
private int i;
The timer's listener might look like this:
#Override
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
JToggleButton b = buttons.get(i);
if (i > MAX) { // reset i and all the buttons
for (JToggleButton b : buttons) {
b.setSelected(false);
}
timer.stop();
i = 0;
} else {
b.setSelected(true);
// play tone i
i++;
}
}
A toggle button's item listener should update the button's appearance as indicated by its state:
#Override
public void itemStateChanged(ItemEvent e) {
JToggleButton b = (JToggleButton) e.getItem();
if (b.isSelected()) {
// change icon, color etc.
} else {
// restore icon, color etc.
}
}
I'm developing a little 2D game like Mario Bros, in this game when the user press the jump button depends of the milliseconds the jump button is pressed, Mario performs a small jump or a larger jump.
I tried to declare a counter that increments into my keyPressed event but not working...
contadorSalto = 0;
contadorTiempoSalto = 0;
public void keyPressed(KeyEvent arg0) {
int codigo = arg0.getKeyCode();
if(codigo == KeyEvent.VK_SPACE)
{
System.out.println(contadorTiempoSalto);
contadorTiempoSalto++;
map.put("espacio", true);
}
}
public void moverPersonaje(){
if(map.get("espacio")&&(contadorSalto < 1)){
if(contadorTiempoSalto == 0){//less tant 1 second
pj[0].setVelocidadY(-15);
}
if(contadorTiempoSalto > 0){
pj[0].setVelocidadY(-25);
}
contadorSalto++;
}
}
I can paste the rest of code if you want! Thanks
Instead of just recording that a key has been pressed in your map, record when the key has been pressed. Also add a keyReleased() handler that clears the key from the map.
You can then easily find out for how long the key has been pressed:
public Map<Integer, Long> keyPressMap = new HashMap<>();
public void keyPressed(KeyEvent arg0) {
keyPressMap.put(arg0.getKeyCode(), System.currentTimeMillis());
}
public void keyReleased(KeyEvent arg0) {
keyPressMap.remove(arg0.getKeyCode());
}
// find out if key is pressed and how long it was
Long t = keyPressMap.get(KeyEvent.VK_SPACE);
if (t == null) {
// not pressed
} else {
// pressed for X milliseconds
long millis = t - System.currentTimeMillis();
}
You can then decide what to do on how long the key has been down.
Generally, you shouldn't rely on the keyPressed() and keyReleased() functions. Instead, use booleans that keep track of whether each key you care about is pressed, and set those booleans in the keyPressed() and keyReleased() functions.
Then in your game loop, check those booleans to determine which keys are currently pressed. Then either keep track of the number of frames a boolean is true, or record the system time when the boolean changes to get the elapsed time.
So basicaly what im trying to do is using LWJGL now making my player move in the game. The player is currently moving but he doesnt keep mooving while you are holding the button..
public void update(){
while(Keyboard.next()){
if(Keyboard.getEventKey() == Keyboard.KEY_RIGHT) {
if(Keyboard.getEventKeyState()){
System.out.println("KEY DOWN!");
player.playerMovingRight();
}
else{
System.out.println("KEY RELEASED!");
}
}
}
I tried using a while(Keyboard.getEventKeyState()) but it just made the game crash and it wouldnt recognise if i release the key.
So how can i make my player keep moving if you hold the button instead of having to rapidly press the key to move. And how would i make it work if the player is holding 2 buttons at the same time?
Updated code:
public void update(){
while(Keyboard.next()){
//If key escape is down we shut the application down
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
System.exit(0);
}
//If key up was pressed move up
else if(Keyboard.getEventKey() == Keyboard.KEY_UP) {
if(Keyboard.getEventKeyState()){
System.out.println("KEY DOWN!");
moveUp = true;
}
else{
System.out.println("KEY RELEASED!");
moveUp = false;
}
}
//If key down was pressed move down
else if(Keyboard.getEventKey() == Keyboard.KEY_DOWN) {
if(Keyboard.getEventKeyState()){
System.out.println("KEY DOWN!");
moveDown = true;
}
else{
System.out.println("KEY RELEASED!");
moveDown = false;
}
}
if(moveUp == true){
player.playerMovingUp();
}
if(moveDown == true){
player.playerMovingDown();
}
}
Im still having the same problem with the code, Im starting to think its they Keyboard.next() that is preventing me from holding the button and the player still moves.
What you need is a boolean flag which triggers when the button is pressed down, and is untriggered when the button is released. The flag would then be added to an if statement before the movement code. Like so:
if(Keyboard.getEventKey() == Keyboard.KEY_RIGHT) {
if(Keyboard.getEventKeyState()){
System.out.println("KEY DOWN!");
flag = true;
}
else{
System.out.println("KEY RELEASED!");
flag = false;
}
}
}
//player movement code
if(flag) {
player.playerMovingRight();
}
The way to do it with multiple keys is to use an array of boolean triggers and repeating the checks for each key.
While the above answer will work, LWJGL has the capability to detect if a key is being held down. It is not enabled by default though, so you need to enable it. To do this just set this flag to true somewhere in your input initialization.
Keyboard.enableRepeatEvents(true);
Now in your event loop, just do this check on your keys to see if it is a repeat (held down key).
if(Keyboard.isRepeatEvent())
Here is a small sample to see how to check a key for different key states.
while(Keyboard.next())
{
if(Keyboard.getEventKey() == Keyboard.KEY_A)
if(Keyboard.getEventKeyState())
{
if(Keyboard.isRepeatEvent())
// Key held down
else
// Key pressed
}
else
// Key released
}
while(Keyboard.next()) is supposed to be used with events.
In your case, you don't want to only do something, when an event gets triggered. But you want to determine many times per second, whether a key is pressed or not. If it is, you want to do something (e.g. move).
So it's the best solution to use the Keyboard.isKeyDown() function.
A little example:
if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
System.out.println("pressing KEY_UP");
}
if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
System.out.println("pressing KEY_DOWN");
}
if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
System.out.println("pressing KEY_LEFT");
}
if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
System.out.println("pressing KEY_RIGHT");
}
Also, a good tutorial can be found here.
I found a very good tutorial about how to create games with Java2D. In this tutorial there is a section called 'Moving sprites' that shows how to move a little spacecraft image on the screen. I was playing with the craft and realized that it was "blocking" on screen sometimes. After some tests and thinking about the problem I found out that the blocking problem was happening because when you use the arrows of the keyboard sometimes you press Left and Right at same time for example, and this blocks the movement.
So my question is: how do I handle this kind of keyboard event - when you are pressing LEFT button keep pressing it and then press RIGHT button - so the character movement is not blocked?
I think this is very common to happen because when you are playing you switch from left to right but for an instant you are pressing left and right at the same time.
You can do this in multiple ways. One way is to use booleans in your program.
You can set booleans to true when you press a certain key and to false when you release them. ie:
int x,xSpeed;
boolean movingLeft = false;
boolean movingRight = false;
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
movingLeft = true;
}
if(key == KeyEvent.VK_RIGHT){
movingRight = true;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
movingLeft = false;
}
if(key == KeyEvent.VK_RIGHT){
movingRight = false;
}
}
public void moving(){
if(movingLeft){
x -= xSpeed;
}
if(movingRight){
x += xSpeed;
}
}
Ok let's look at this code. Because we're using the 'else if' you either move right, or you move left. I haven't test this code so not quite sure if this will work :)
Let me know what you think and good luck!