Как переместить видимое изображение по диагонали?

Я пытался выяснить, как заставить видимое изображение двигаться по диагонали в окне апплета.

Если вы нажимаете вверх, вниз, влево или вправо, изображение (рисунок) перемещается соответствующим образом, однако, если вы пытаетесь нажать две клавиши одновременно (например, вверх и вправо одновременно), изображение перемещается только в направлении, которое вы нажали второе (даже если вы нажмете клавиши одновременно, микроскопическая задержка все еще сохраняется).

Возможно, есть простой способ исправить это, о котором я просто не знаю, или, возможно, кто-то нашел обходной путь... Я ценю любую помощь или совет, который можно дать.

Спасибо

Класс героя (этот класс определяет, что такое "герой"; в данном случае это простой пиксельный человек и что он может делать)

import objectdraw.*;
import java.awt.*;

public class Hero extends ActiveObject {

private DrawingCanvas canvas;
private VisibleImage player;

public Hero(Location initLocation, Image playerPic, DrawingCanvas aCanvas) {
canvas = aCanvas;

player = new VisibleImage(playerPic, canvas.getWidth()/3,
         canvas.getWidth()/3, canvas);
start();

}
public void run() 
{

}

public void move(double dx, double dy) 
{
player.move(dx, dy);
}
}

Класс HeroGame (этот класс создает "Героя" и указывает местоположение, а также какие ключи используются для его перемещения)

import objectdraw.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class HeroGame extends WindowController implements KeyListener {
private Hero theHero;
private Image playerPic;
private Location initLocation;
public void begin() {
    playerPic = getImage("player.gif");
    canvas.addKeyListener ( this );
    this.addKeyListener ( this );
    requestFocusInWindow();
    theHero = new Hero(initLocation, playerPic, canvas);
    }
public void keyTyped( KeyEvent e ) { }
public void keyReleased( KeyEvent e ) { }
public void keyPressed( KeyEvent e ) {

    if ( e.getKeyCode() == KeyEvent.VK_UP ) {
        theHero.move(0,-5);
    }
    else if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
        theHero.move(0,5);
    }
    else if ( e.getKeyCode() == KeyEvent.VK_LEFT ) {
        theHero.move(-5,0);
    }
    else if ( e.getKeyCode() == KeyEvent.VK_RIGHT ) {
        theHero.move(5,0);
    }
  }
}

Спасибо еще раз, что нашли время, чтобы прочитать это и, надеюсь, помочь.

5 ответов

Решение

Это довольно обычная ситуация в играх, которые принимают ввод с клавиатуры. Проблема в том, что ваша игра должна воздействовать на все клавиши, которые в данный момент нажаты, насколько это касается игры (то есть все клавиши, для которых еще не было инициировано событие KEY_RELEASE).

KeyListener будет уведомлять вас только о последней нажатой клавише (и будет продолжать уведомлять вас о той же клавише, если вы удерживаете ее нажатой), поэтому вам нужно самостоятельно отслеживать состояние остальных клавиш.

Чтобы получить представление о том, как это сделать, выполните поиск опроса клавиатуры ( здесь пример), популярного метода, при котором вы не реагируете сразу на вход игрока, а скорее сохраняете нажатия клавиш в очереди, а затем опрашиваете эту очередь через равные промежутки времени. (т.е. в вашем игровом цикле), чтобы решить, какие клавиши нажаты или нет, и действовать соответственно.

надеюсь, это поможет

Я бы посоветовал вам использовать Swing (JApplet) и привязки клавиш. См. Раздел " Движение с помощью клавиатуры", где описаны проблемы с использованием KeyListener, а также решение для одновременного нажатия нескольких клавиш.

Менять

if ( e.getKeyCode() == KeyEvent.VK_UP ) {
    theHero.move(0,-5);
}
else if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
    theHero.move(0,5);
}
else if ( e.getKeyCode() == KeyEvent.VK_LEFT ) {
    theHero.move(-5,0);
}
else if ( e.getKeyCode() == KeyEvent.VK_RIGHT ) {
    theHero.move(5,0);
}

в

if ( e.getKeyCode() == KeyEvent.VK_UP ) {
    theHero.move(0,-5);
}
if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
    theHero.move(0,5);
}
if ( e.getKeyCode() == KeyEvent.VK_LEFT ) {
    theHero.move(-5,0);
}
if ( e.getKeyCode() == KeyEvent.VK_RIGHT ) {
    theHero.move(5,0);
}

И это должно реагировать на оба ключа.

Вместо вашего if-else Заявление для ключа, вы должны использовать серию if заявления.

Вместо установки heroНаправление для обоих x а также y движение в этих if заявления, вы должны только обновлять соответствующие delta

Для (очень упрощенного) примера...

if (up) yDelta = -5;
if (down) yDelta = 5;
if (left) xDelta = -5;
if (right) xDelta = 5;

hero.move(xDelta, yDelta);

Я тоже согласен с camickr

Что вам нужно сделать, это получить доступ к базовому классу AffineTransform изображения и установить правильные методы перевода. Это позволит вам в любом случае переместить изображение (на любое количество градусов в любом направлении) одним нажатием клавиши (которую вы связываете с этим вызовом).

Читайте об этом: http://docs.oracle.com/javase/7/docs/api/java/awt/geom/AffineTransform.html

Другие вопросы по тегам