public void shootSpell(){
final BlueSpell b = new BlueSpell(GoodGuy.getx(), GoodGuy.gety() +1, BlueSpellWizard());
int delay = 60;
ActionListener timeListen = new ActionListener(){
public void actionPerformed(ActionEvent e){
if(b.gety() != 19){
WizardCells[b.getx()][b.gety()].setIcon(null);
WizardCells[b.getx()][b.changey(b.gety()+1)].setIcon(b.getIcon());
}
else{
WizardCells[b.getx()][b.gety()].setIcon(null);
b.changex(GoodGuy.getx());
b.changey(GoodGuy.gety() +1);
timer.stop();
}
}
};
timer = new Timer(delay, timeListen);
if(timer.isRunning()){
return;
}
else{
timer.start();
}
}
密钥处理程序:
public class WizardKeyHandeler extends WizardBattleGrid implements KeyListener {
GoodGuy Player = new GoodGuy(10, 0, GoodGuyWizardIcon());
BlueSpell GoodSpell = new BlueSpell(10, 1, BlueSpellWizard());
WizardPause pause = new WizardPause();
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_W){
if(Player.getx() != 0){
Player.moveUp();
}
}
else if(key == KeyEvent.VK_S){
if(Player.getx() != 19){
Player.moveDown();
}
}
else if(key == KeyEvent.VK_D){
if(Player.gety() != 9){
Player.moveRight();
}
}
else if(key == KeyEvent.VK_A){
if(Player.gety() != 0){
Player.moveLeft();
}
}
else if(key == KeyEvent.VK_SPACE){
}
else if(key == KeyEvent.VK_ESCAPE){
pause.createPause();
}
}
@Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_W){
if(Player.getx() != 0){
Player.remainAtPosition();
}
}
else if(key == KeyEvent.VK_S){
if(Player.getx() != 19){
Player.remainAtPosition();
}
}
else if(key == KeyEvent.VK_D){
if(Player.gety() != 9){
Player.remainAtPosition();
}
}
else if(key == KeyEvent.VK_A){
if(Player.gety() != 0){
Player.remainAtPosition();
}
}
else if(key == KeyEvent.VK_SPACE){
GoodSpell.shootSpell();
}
else if(key == KeyEvent.VK_ESCAPE){
pause.createPause();
}
}
@Override
public void keyTyped(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_W){
if(Player.getx() != 0){
Player.moveUp();
}
}
else if(key == KeyEvent.VK_S){
if(Player.getx() != 19){
Player.moveDown();
}
}
else if(key == KeyEvent.VK_D){
if(Player.gety() != 9){
Player.moveRight();
}
}
else if(key == KeyEvent.VK_A){
if(Player.gety() != 0){
Player.moveLeft();
}
}
else if(key == KeyEvent.VK_SPACE){
}
else if(key == KeyEvent.VK_ESCAPE){
pause.createPause();
}
}
答案 0 :(得分:1)
MadPrgrammer和camickr两个好点。我想说明这些观点。
MapPrgogrammer:你应该有一个计时器,它负责更新游戏/模型的状态并安排重绘,不要使用多个计时器
您应该做的是List
Spell
或BlueSpell
(无论如何)。你想要做的是遍历Timer
和你的绘画方法中的列表。像
public class GamePanel extends JPanel {
List<BlueSpell> spells;
Timer timer = null;
public GamePanel() {
spells = new ArrayList<>();
timer = new Timer(40, new ActionListener(){
public void actionPerformed(ActionEvent e) {
If (spells.size() > 0) {
Iterator spellIt = spells.iterator();
while (spellIt.hasNext()) {
BlueSpell spell = (BlueSpell)spellIt.next();
if (spell.collidesWithSomthing()) {
// do something, then remove from list
spellIt.remove();
} else if (spell.isOffScreen()) {
spellIt.remove(); // remove the spell from list
} else {
spell.animate(); // animate for each tick of timer
}
}
}
repaint(); // just repaint once in each timer tick after all
} // state id update.
});
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
If (spells.size() > 0) {
for (BlueSpell spell: spells) {
spell.drawSpell(g);
}
}
}
}
您可以在spells
回调中看到Timer
列表的基本概念。它遍历计时器,如果列表有BlueSpells
,那么它将继续检查法术是否与某些东西发生碰撞(如果你需要),它会检查法术是否在屏幕外。使用其中之一,您将要从列表中删除它。 (不要试图在每个循环中使用a。在这种情况下,你应该使用迭代器)。如果它仍然在屏幕上并且没有击中任何东西,那么该法术会动画(可能会移动它x位置或其他东西),然后最后为每个刻度,面板重新绘制。请注意if
和paintComponent
中的Timer
次检查。如果列表为空,则无需绘制或遍历列表。
你想要在单个计时器中保持所有游戏的状态,而不仅仅是法术。如果法术是动画的唯一内容,如果列表为空,您可能需要在计时器中添加else { timer.stop() }
。
camickr:不要使用KeyListener来控制玩家的移动。有关更多信息和替代方法using Key Bindings
,请参阅使用键盘进行运动
你可以做的是当按下空间时,将new BlueSpell
添加到列表中(并启动计时器[仅在必要时])。像
public GamePanel() {
...
InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke("SPACE"), "shootSpell");
getActionMap().put("shootSpell", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
spells.add(new BlueSpell(...));
}
});
}
一旦将法术添加到列表中,该法术将开始动画,直到它与某些东西发生碰撞或离开屏幕。
您可以在this answer中看到两个点的实际示例。
此外,您还可以看到其他一些&#34;动画多个对象&#34; 答案here和here以及here和{{3 }}和here以及here。
<强>更新强>
&#34;唯一的问题是在我的重绘方法中,我只是调用我创建的ImageIcon还是必须创建一个新的?&#34;
public class BlueSpell {
BufferedImage bi;
int x, y;
int width = someWidth;
int height = someHeight;
JPanel panel;
public BlueSpell(BufferedImage bi, int x, int y, panel) {
this.bi = bi;
this.x = x;
this.y = y;
this.panel = panel;
}
public void drawSpell(Graphics g) {
g.drawImage(bi, x, y, width, height, panel);
}
public void animate() {
x += 5;
}
}
您应该只在BufferedImage
中创建一个GamePanel
,当您在键绑定中创建new BlueSpell
时,只需将图像与其他参数一起传递给它