2017-02-04 23 views
0

Я начал процесс обучения самому java-дизайну игры, и я столкнулся с первым препятствием: у меня есть объект KeyListener, который вызывается прямо сейчас, когда пользователь щелкает правой или левой клавишами. Когда он называется, у меня есть консольная печать «это работает», и я обновляю vel до 1 или -1. Однако, пока консоль печатает vel, не будет обновляться. Почему это?Обновление переменных с помощью EventListener

public class Paddle{ 

private int width = 100; 
private int height = 15; 
private int winWidth; 
private int posX; 
private int posY; 
int vel = 0; 
Game game; 

public Paddle(){ 

} 
public Paddle(int winWidth, int winHeight, Game game){ 
    posX = winWidth/2; 
    posY = winHeight - 70; 
    this.winWidth = winWidth; 
    this.game = game; 
} 
**public void move(){ 
    if((posX + vel < winWidth) && (posX + vel > 0)){ 
     posX += vel; 
    } 
}** 
public void paint(Graphics2D g){ 
    g.setColor(Color.BLACK); 
    g.fillRect(posX, posY, width, height); 
} 
**public void keyPressed(KeyEvent e) { 
    if(e.getKeyCode() == KeyEvent.VK_RIGHT){ 
     System.out.println("This works"); 
     this.vel = 1; 
    } 
    if(e.getKeyCode() == KeyEvent.VK_LEFT){ 
     vel = -1; 
    } 
} 
public void keyReleased(KeyEvent e) { 
    vel = 0; 
}** 
} 

.

public class Keyboard implements KeyListener{ 

Paddle paddle = new Paddle(); 

@Override 
public void keyPressed(KeyEvent e) { 
    paddle.keyPressed(e); 
} 
@Override 
public void keyReleased(KeyEvent e) {  
    paddle.keyReleased(e); 
} 
@Override 
public void keyTyped(KeyEvent e) { 
    //Not using it 
} 
} 

.

public class Game extends JPanel{ 

public int width = 900; 
public int height = width/16 * 9; 
private static boolean running = true; 

Ball ball = new Ball(width, height, this); 
Paddle paddle = new Paddle(width, height, this); 
Keyboard keyboard = new Keyboard(); 

public Game(){ 
    JFrame frame = new JFrame("Mini Tennis"); 

    this.addKeyListener(keyboard); 
    this.setFocusable(true); 

    frame.add(this); 
    frame.setVisible(true); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(width, height);; 
    frame.setLocationRelativeTo(null); 
    System.out.println(frame.getHeight()); 
} 
public void move(){ 
    ball.move(); 
    paddle.move(); 
} 
public void paint(Graphics g){ 
    super.paint(g); 
    Graphics2D g2d = (Graphics2D) g; 
    ball.paint(g2d); 
    paddle.paint(g2d); 
} 
public void gameOver(){ 
    running = false; 
    System.out.println("Game Over"); 
} 
public static void main(String[] args) throws InterruptedException{ 
    Game game = new Game(); 

    while(running){ 
     game.move(); 
     game.repaint(); 

     Thread.sleep(10); 
    } 
} 
} 
+2

Пока мы находимся в режиме обучения, давайте рассмотрим некоторые неотложные проблемы/улучшения. Как общая рекомендация, вы должны переопределить paintComponent вместо краски, возможно, не имеют большого значения для вас, вы знаете, но может взорваться на вашем лице позже. Я бы избегал использовать поток (или ваш цикл while) в качестве механизма обновления до тех пор, пока у вас не будет лучшего представления о том, что вы делаете, Swing не является потокобезопасным, вместо этого рассмотрите использование таймера Swing. Вы должны избегать KeyListener и предпочитаете API привязки ключей, он исправляет проблемы, связанные с фокусом, и обеспечивает более многократно используемую структуру. – MadProgrammer

+2

Проблема, с которой вы сталкиваетесь, - это экземпляр Paddle, который меняется KeyListener, это не тот, который вы рисуете , Как идея, ваш KeyListener должен устанавливать какую-то переменную состояния (состояния), которая затем передается игровым элементам при выполнении цикла обновления, это отделяет механизм ввода от игровых элементов, что облегчает изменение – MadProgrammer

+0

@MadProgrammer Большое вам спасибо за отзывы! Я обязательно рассмотрю все эти рекомендации. Однако у меня есть два очень глупых вопроса. Что вы имеете в виду, когда говорите игровые элементы, и можете ли вы дать мне пример KeyListener, передающего переменную состояния. Мне жаль, что я некоторое время работал с основами Java, но я только что перешел к разработке игр. –

ответ

0

Вы заявили следующее Клавиатура Calss,

Paddle paddle = new Paddle(); 

что означает V, который вы увеличивающиеся отличается от V, которая есть в классе Game.java

вы должны либо передать объект paddle в Calss клавиатуры.

Ваш класс Paddle должен быть как,

public class Keyboard implements KeyListener { 

Paddle paddle; 

public Keyboard(Paddle paddel) { 
    this.paddle = paddel; 
} 

@Override 
public void keyPressed(KeyEvent e) { 
    paddle.keyPressed(e); 
} 

@Override 
public void keyReleased(KeyEvent e) { 
    paddle.keyReleased(e); 
} 

@Override 
public void keyTyped(KeyEvent e) { 
    // Not using it 
} 
} 

И в игре классе вместо

Keyboard keyboard = new Keyboard(); 

Это должно быть добавлено,

Keyboard keyboard = new Keyboard(paddle); 

Позвольте мне знать, если у вас есть какие-либо сомнения.

+0

Лучшим решением было бы отделить ввод от цикла обновления, вместо того чтобы проходить paddle в 'KeyListener',' KeyListener' должен менять состояние игровой модели, из которой весло обновляется с – MadProgrammer

+0

@MadProgrammer, с которой вы находитесь прямо с точки зрения дизайна. Благодарю. – NewToJava

0

Когда ключ используется, он затем отжимается и отпускается. Затем ваша переменная vel будет изменена на 1 или -1 во время нажатия клавиши, а затем будет сброшена на 0 при ее освобождении.

+0

Которая не будет иметь большого значения для текущего состояния весла. – MadProgrammer