2017-08-07 47 views
0

我試圖在按下按鈕時在我的遊戲中設置精靈的動畫,但是當我按下按鈕時,它會跳過動畫。它應該去一個像素,改變精靈,然後再去一個像素,然後改回來。下面是代碼爲什麼這會嘗試對我的移動精靈進行動畫製作?

//for all 
import java.nio.file.*; 
import javax.imageio.ImageIO; 
import java.io.IOException; 
import java.awt.image.*; 
import java.net.*; 
import java.awt.*; 
import javax.swing.*; 
import static java.lang.invoke.MethodHandles.*; 
import java.awt.event.*; 

//my Mario class (cut down a lot) 
class Mario { 
    // all numbers multiplied by 2 from OG game 

    protected Direction dir; 
    protected int x, y; 
    protected BufferedImage sprite; 
    protected String currentSpriteName; 

    public Mario() { 

     this.x = 54; 
     this.y = 808; 
     dir = Direction.RIGHT; 
     setSprite(MVCE.SMALLSTANDFACERIGHT); 
     currentSpriteName = MVCE.SMALLSTANDFACERIGHT; 
    } 

     public void moveRight(){ 
     if(this.dir == Direction.LEFT){ 
     this.dir = Direction.RIGHT; 
     } 
     else if(this.dir == Direction.RIGHT){ 
     this.x+=1; 
     } 
    } 

    public void animateMoveRight(){ 
     if (currentSpriteName.equals(MVCE.SMALLSTANDFACERIGHT)){ 
     setSprite(MVCE.SMALLWALKFACERIGHT); 
     } 
     else if (currentSpriteName.equals(MVCE.SMALLWALKFACERIGHT)){ 
     setSprite(MVCE.SMALLSTANDFACERIGHT); 
     } 
    } 

    public void jump() { 
     this.y -= 46; 
    } 

    public void setSprite(String spriteName) { 
     URL spriteAtLoc = MVCE.urlGenerator(spriteName); 
     this.sprite = MVCE.generateAndFilter(sprite, spriteAtLoc); 
    } 

     public void getSprite(){ 
     System.out.println(this.currentSpriteName); 
    } 

    public void paint(Graphics g) { 
     Graphics2D g2 = (Graphics2D) g; 
     g2.drawImage(sprite, 0, 0, null); // DO NOT SET x and y TO ANYTHING, 
              // this sets 0,0 to top left!! 
    } 

} 

// my MarioRender class: 
class MarioRender extends JLabel { 

    protected Mario marioSprite; 

    public MarioRender() { 
     marioSprite = new Mario(); 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     marioSprite.paint(g2); 
     setBounds(marioSprite.x, marioSprite.y, marioSprite.sprite.getWidth(), marioSprite.sprite.getHeight()); 
    } 

     public void moveMarioRight(){ 
     marioSprite.moveRight(); 
     marioSprite.animateMoveRight(); 
     setLocation(this.marioSprite.getX(), this.marioSprite.getY()); 
     repaint(); 
     //this is my attempt to make it animate 
     marioSprite.moveRight(); 
     marioSprite.animateMoveRight(); 
     setLocation(this.marioSprite.getX(), this.marioSprite.getY()); 
     repaint(); 
     } 

    public void jumpMario() { 
     marioSprite.jump(); 
     setLocation(this.marioSprite.x, this.marioSprite.y); 
     repaint(); 

    } 

} 

// direction class, solely for moving 
enum Direction { 
    LEFT, RIGHT 
} 

// my calling class, which I called MVCE where I make the frame 
public class MVCE extends JFrame { 

    MarioRender m = new MarioRender(); 
    JLabel bg; 

    public MVCE() { 
     bg = new JLabel(); 
     this.setSize(868, 915); 
     this.setVisible(true); 
     this.add(bg, BorderLayout.CENTER); 
     bg.setLayout(null); 

     bg.add(m); 
     m.setBounds(m.marioSprite.x, m.marioSprite.y, m.marioSprite.sprite.getWidth(), 
       m.marioSprite.sprite.getHeight()); 
     KeyListener kl = new MoveListener(); 
     this.addKeyListener(kl); 
     this.setFocusable(true); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    } 

    public static final String SMALLSTANDFACERIGHT = "SmallStandFaceRight.bmp"; // 30 
                       // x 
                       // 32 
    public static final String SMALLJUMPFACERIGHT = "SmallJumpFaceRight.bmp"; // 32 
                       // x 
                       // 32 

    // generate URL 
    public static URL urlGenerator(String name) { 
     URL u = lookup().lookupClass().getResource(name); 
     return u; 
    } 

    // return image with filtered color 
    public static BufferedImage generateAndFilter(BufferedImage b, URL u) { 

     try { 
      b = ImageIO.read(u); 
      int width = b.getWidth(); 
      int height = b.getHeight(); 
      int[] pixels = new int[width * height]; 
      b.getRGB(0, 0, width, height, pixels, 0, width); 
      for (int i = 0; i < pixels.length; i++) { 
       // System.out.println(pixels[i]); 
       if (pixels[i] == 0xFFff00fe) { 
        pixels[i] = 0x00ff00fe; 
       } 
      } 
      BufferedImage newSprite = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 
      newSprite.setRGB(0, 0, width, height, pixels, 0, width); 
      b = newSprite; 
     } catch (IOException e) { 
      System.out.println("sprite not found"); 
      e.printStackTrace(); 
     } 
     return b; 
    } 

    // key listener 
    class MoveListener implements KeyListener { 
     public void keyPressed(KeyEvent k) { 

      if ((k.getKeyCode() == 39)) { 

       m.moveMarioRight(); 
       ///THIS IS SUPPOSED TO MOVE HIM 1, change sprite, and automatically move him back, it moves 2 pixels but no animation 


      } 

      if (k.getKeyCode() == 83) { // S key 

       m.marioSprite.setSprite(SMALLJUMPFACERIGHT); 
       m.jumpMario(); 
      } 

     } 

     public void keyReleased(KeyEvent k) { 
     } 

     public void keyTyped(KeyEvent k) { 
     } 
    } 

    public static void main(String[] args) { 
     MVCE m = new MVCE(); 
    } 

} 

我試圖把這個調用之間marioMoveRight():

try { 
     Thread.sleep(200);     
    } catch(InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
    } 

但它只是拖延整個事情。我也嘗試過使用ActionListener,但我不知道如何僅在按下按鍵時才做出反應。因爲我有它,

我有這個類MVCE內:

class TickListener implements ActionListener{ 
    public void actionPerformed(ActionEvent a){ 
    m.marioSprite.setSprite(Constants.SMALLWALKFACERIGHT); 
    repaint(); 
    } 
} 

,這在MVCE構造函數的末尾:

ActionListener ac = new TickListener(); 
final int DELAY = 1000; 
Timer t = new Timer(DELAY, ac); 
t.start(); 

但隨後,馬里奧只是自動移動。我不想爲這個項目使用一個精靈表,我想爲SMB1做this guy did

回答

0

你永遠不會真的調用方法animateMoveRight(),如果我理解正確,那是什麼改變了精靈。另外,我懷疑你在連續兩次調用同一個方法時沒有任何延遲就會看到精靈的變化。
嘗試將animateMoveRight()方法放入moveRight()moveMarioRight()方法中,如果因爲動畫太快而需要,請將您的延遲代碼添加回原來的位置。要小心,不要讓主線程睡眠,因爲這會導致一切凍結,所以開始另一個或使用定時器等

編輯:好定時器
我不是太熟悉的Timer類,所以我最終使用了Thread變體。有很多教程,只需搜索「java線程」或「java多線程」即可。 This是國際海事組織一個堅實的教程,你可以檢查出來。

+0

即使當我這樣做,並把它放在marioMoveRight(),它仍然沒有動畫它。 – Derry

+0

什麼是一些很好的延遲代碼? – Derry

1

許多問題,不知道是哪一個,或者如果任何將解決這個問題:

  1. 不要使用KeyListener的。如果組件沒有焦點,組件將不會收到事件。請改用Key Bindings

  2. 不要使用「==」來比較對象。相反,您應該使用equals(...)方法。

  3. 請勿重寫paintComponent。繪畫方法僅用於繪畫。您不應該改變繪畫方法中組件的邊界。

  4. 在提問前做基本調試(解決問題)。一個簡單的System.out.println(...)添加到各種方法將確定代碼是否按照您的預期執行。然後,當你問一個問題時,你可以問一個具體的問題,告訴我們哪個代碼塊不會像你期望的那樣執行。

+0

我在兩次調用keyListener中的marioMoveRight()之間有一個System.out.println,並且它打印出不同的精靈名稱,但沒有視覺上的變化。另外,如果我不更改paintComponent中的邊界,則如果更改了精靈,它將被切斷。我曾嘗試使用equals(),沒有區別 – Derry

+0

@Derry,「如果我不更改paintComponent中的邊界,精靈會被截斷」 - 再次,您不應該在繪畫方法中更改組件邊界! !如果事實你不應該做任何自定義繪畫。您所做的只是將圖標添加到標籤並將標籤添加到面板。然後,您可以更改面板上標籤的位置。查看[使用鍵盤移動](https://tips4java.wordpress.com/2013/06/09/motion-using-the-keyboard/)獲取一個基本示例,幫助您開始。 – camickr

+0

重新提出問題[這裏](https://stackoverflow.com/questions/45603451/how-can-i-animate-this-sprite-so-when-a-function-is-called-it-switches-精靈?) –