#java #if-statement
Вопрос:
я пытаюсь создать игру, похожую на jetpack joyride, в которой пользователь может удерживать пробел, чтобы подняться, и отпускать, чтобы двигаться вниз. Я использую таймеры для имитации силы тяжести и использования keyPressed
и keyReleased
проверки того, удерживает ли пользователь пробел. Я использую операторы печати, чтобы точно знать, что и нажатие клавиш, и их освобождение работают, но я не знаю, почему физика не работает. Я не знаю, является ли проблема в том, что мои операторы if не обновляются, если это новые таймеры, создаваемые внутри оператора if. В любом случае, гравитация не меняется, и я застрял. Помощь приветствуется.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Calendar;
public class Game implements KeyListener {
JFrame frame;
JLabel player;
public boolean grounded = false;
public int velocity = 0;
public int finalY = 0;
public boolean spaceHeld = false;
Action spaceAction;
Game() {
frame = new JFrame("Nicholas Seow-Xi Crouse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1920, 1080);
frame.setLayout(null);
frame.setFocusable(true);
frame.addKeyListener(this);
player = new JLabel();
player.setBackground(Color.red);
player.setBounds(10, 1800, 50, 50);
player.setOpaque(true);
frame.add(player);
frame.setVisible(true);
Timer flightTime = new Timer();
TimerTask flight = new TimerTask() {
public void run() {
if(velocity > -5) {
velocity -= 1;
}
else{
velocity = -5;
}
if (finalY < -61) {
finalY = finalY velocity;
}
else{
finalY = -61;
}
player.setLocation(player.getX(), player.getY() finalY);
if (player.getY() <= 0){
cancel();
velocity = 0;
finalY = 0;
player.setLocation(player.getX(), 0);
}
}
};
Timer gravityTime = new Timer();
TimerTask gravity = new TimerTask() {
//creates a timer run method that simulates the falling gravity when not grounded
public void run() {
if(velocity < 5){
velocity = 1;
}
else{
velocity = 5;
}
//creates the variable the tells where the player is located
if (finalY < 61) {
finalY = finalY velocity;
}
else{
finalY = 61;
}
player.setLocation(player.getX(), player.getY() finalY);
if (player.getY() >= 1000){
cancel();
velocity = 0;
finalY = 0;
player.setLocation(player.getX(), 990);
}
}
};
if (spaceHeld == false ) {
gravityTime.scheduleAtFixedRate(gravity, 0, 33);
}
if (spaceHeld == true ) {
flightTime.scheduleAtFixedRate(flight, 0 ,33);
}
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
spaceHeld = true;
//debug
System.out.println(spaceHeld);
}
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
spaceHeld = false;
//debug
System.out.println(spaceHeld);
}
}
}
Ответ №1:
Код основан на событиях, и в настоящее время ничто не запускает ваши таймеры для запуска. Для этого вы можете просто переместить расписание таймера/начать действия внутри ключевых событий:
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
//Cancel the other timer here so that they don't overlap
gravity.cancel();
gravityTime.cancel();
//Create a new instance of the timer
flightTime = new Timer();
flight = new TimerTask() {
public void run() {
if(velocity > -5) {
velocity -= 1;
}
else{
velocity = -5;
}
if (finalY < -61) {
finalY = finalY velocity;
}
else{
finalY = -61;
}
player.setLocation(player.getX(), player.getY() finalY);
if (player.getY() <= 0){
cancel();
velocity = 0;
finalY = 0;
player.setLocation(player.getX(), 0);
}
}
};
//Now start the timer
flightTime.scheduleAtFixedRate(flight, 0 ,33);
}
}
//Do the same for the gravity method
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
......
}
}
}
Обратите внимание выше, что вы также должны отменить другую запланированную задачу с противоположными ключевыми событиями, чтобы они не перекрывали друг друга и не приводили к странным результатам.
И чтобы сделать flightTime
gravityTime
их доступными для метода с нажатой клавишей, просто объявите их как переменные класса:
public class Game implements KeyListener {
JFrame frame;
JLabel player;
public boolean grounded = false;
public int velocity = 0;
public int finalY = 0;
public boolean spaceHeld = false;
//Move them here but don't assign a value:
public Timer flightTime;
public TimerTask flight;
public Timer gravityTime;
public TimerTask gravity;
Вы все еще можете создать объект позже в игровом методе:
flightTime = new Timer();
flight = new TimerTask() {
....
};
Комментарии:
1. Здравствуйте, этот метод сработал для меня, хотя я получаю исключение, в котором говорится, что задача гравитации уже запланирована. Есть какие-нибудь идеи?
2. @ZZBowzer Убедитесь, что он сначала отменяется
gravity.cancel();
, прежде чем пытаться запустить его снова, или, если задача уже запущена, нет необходимости запускать ее снова, просто дайте ей запуститься?3. Вы также можете переместить создание таймера в метод нажатия клавиши (см. Мой отредактированный код выше), но это все равно может создать проблемы с перекрытием таймеров, если они неправильно остановлены. Честно говоря, было бы лучше использовать один таймер/задачу для управления анимацией, которую никогда не нужно отменять/запускать, и просто заставить ее прочитать логическое значение, чтобы увидеть, должна ли она двигаться вверх или вниз.