2013-11-04 93 views
2

我是計算機課程(高中新生)中三個成員組中的三分之一。對於我們的項目,我們決定用Java製作一款Pac-Man風格的遊戲。我們都沒有太多經驗,所以我們基本上一直在教導自己。我們已經取得了一些進展,但在這一點上我們似乎已經陷入停滯。以下是我們的主要問題:Java遊戲編程第1部分:平滑運動

  1. 我們如何讓我們的Pacman(Fatman)在瓷磚上平穩移動?他通過平鋪移動平鋪,但看起來不專業。另外,當你按住箭頭鍵時,他在屏幕上拉動。我們如何防止這種情況發生?

(我還有其他的事情,我需要幫助的,但他們在不同的問題)

謝謝您的幫助!

這裏是我們到目前爲止的代碼:

迷宮類:

package Fatman; 

import javax.swing.*; 

public class Maze { 
    public static void main(String[] args){ 
     new Maze(); 
    } 

    public Maze(){ 
     JFrame f = new JFrame(); 
     f.setTitle("Fatman!"); 
     f.add(new Board()); 
     f.setSize(816, 838); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 
} 

地圖類

package Fatman; 

import java.awt.*; 
import java.io.*; 
import java.util.*; 
import javax.swing.*; 

public class Map { 

    private Scanner m; 
    private String Map[] = new String[25]; 

    private Image spaceregcandy, 
        srcb, 
        safehouse, 
        spacebigcandy, 
        blackspace, 
        space, 
        portal1, 
        portal2, 
        wall; 

    public Map(){ 

     ImageIcon img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\spaceregcandy.png"); 
     spaceregcandy = img.getImage(); 
     //image icon has already been initiated, so it doesn't have to be written again 
     img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\spaceregcandyblue.png"); 
     srcb = img.getImage(); 
     img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\safehouse.png"); 
     safehouse = img.getImage(); 
     img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\wall232x.png"); 
     wall = img.getImage(); 
     img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\spacebigcandy.png"); 
     spacebigcandy = img.getImage(); 
     img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\blackspace.png"); 
     blackspace = img.getImage(); 
     img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\space.png"); 
     space = img.getImage(); 
     img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\portal1.png"); 
     portal1 = img.getImage(); 
     img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\portal2.png"); 
     portal2 = img.getImage(); 

     openFile(); 
     readFile(); 
     closeFile(); 
     } 

    public Image getSpaceregcandy(){ 
     return spaceregcandy; 
    } 
    public Image getSrcb(){ 
     return srcb; 
    } 
    public Image getSafehouse(){ 
     return safehouse; 
    } 
    public Image getWall(){ 
     return wall; 
    } 
    public Image getSpacebigcandy(){ 
     return spacebigcandy; 
    } 
    public Image getBlackspace(){ 
     return blackspace; 
    } 
    public Image getSpace(){ 
     return space; 
    } 
    public Image getPortal1(){ 
     return portal1; 
    } 
    public Image getPortal2(){ 
     return portal2; 
    } 

    public String getMap(int x, int y){ 
     String index = Map[y].substring(x, x + 1); 
     return index; 
     //in y position, if y = 2, goes to second row (substring gets x position) 
    } 

    public void openFile(){ 

     try{ 
     m = new Scanner(new File("C:\\Users\\Martin\\Desktop\\Fatman Project\\map3.txt")); 
     }catch(Exception e){ 
      System.out.println("error loading map"); 
     } 
    } 

    public void readFile(){ 
     while(m.hasNext()){ 
      for(int i = 0; i < 25; i++){ 
       Map[i] = m.next(); 
      } 
     } 

    } 

    public void closeFile(){ 
     m.close(); 
    } 
} 

package Fatman; 

import java.awt.*; 
import java.awt.event.*; 
import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileReader; 
import java.io.FileWriter; 
import java.io.IOException; 

import javax.swing.*; 

public class Board extends JPanel implements ActionListener{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 

    private Timer timer; 

    private Image player; 

    private Map m; 
    private Player p; 

    public Board(){ 

     m = new Map(); 
     p = new Player(); 
     addKeyListener(new Al()); 
     setFocusable(true); 
     timer = new Timer(1, this); 
     timer.start(); 
    } 

    public void actionPerformed(ActionEvent e){ 
     repaint(); 

    } 

    public void paint(Graphics g){ 
     super.paint(g); 

     for(int y = 0; y < 25; y++){ 
      for(int x = 0; x <25; x++){ 
       if(m.getMap(x, y).equals("o")){ 
        g.drawImage(m.getSpaceregcandy(), x *32, y *32, null); 
       } 
       if(m.getMap(x, y).equals("O")){ 
        g.drawImage(m.getSrcb(), x *32, y *32, null); 
       } 
       if(m.getMap(x, y).equals("x")){ 
        g.drawImage(m.getWall(), x *32, y *32, null); 
       } 
       if(m.getMap(x, y).equals("H")){ 
        g.drawImage(m.getSafehouse(), x *32, y *32, null); 
       } 
       if(m.getMap(x, y).equals("C")){ 
        g.drawImage(m.getSpacebigcandy(), x *32, y *32, null); 
       } 
       if(m.getMap(x, y).equals("b")){ 
        g.drawImage(m.getBlackspace(), x *32, y *32, null); 
       } 
       if(m.getMap(x, y).equals("s")){ 
        g.drawImage(m.getSpace(), x *32, y *32, null); 
       } 
       if(m.getMap(x, y).equals("p")){ 
        g.drawImage(m.getPortal1(), x *32, y *32, null); 
       } 
       if(m.getMap(x, y).equals("P")){ 
        g.drawImage(m.getPortal2(), x *32, y *32, null); 
       } 
     } 


    } 


     g.drawImage(p.getPlayer(), p.getTileX() * 32, p.getTileY() * 32, null); 

} 

    public class Al extends KeyAdapter{ 

     public void keyPressed(KeyEvent e){ 
      int keycode = e.getKeyCode(); 

      if(keycode == KeyEvent.VK_UP){ 
       if(!m.getMap(p.getTileX(), p.getTileY() -1).equals("x")){ 
        if(!m.getMap(p.getTileX(), p.getTileY() -1).equals("b")){      
         } 
         p.move(0, -1);     

         System.out.println(m.getMap(p.getTileX(), p.getTileY())); 

      } 
       } 

      if(keycode == KeyEvent.VK_DOWN){ 
       if(!m.getMap(p.getTileX(), p.getTileY() +1).equals("x")){ 
        if(!m.getMap(p.getTileX(), p.getTileY() +1).equals("b")){ 
         p.move(0, 1); 
         System.out.println(m.getMap(p.getTileX(), p.getTileY())); 
      } 
       } 
      } 
      if(keycode == KeyEvent.VK_LEFT){ 
       if(!m.getMap(p.getTileX() - 1, p.getTileY()).equals("x")){ 
        if(!m.getMap(p.getTileX() - 1, p.getTileY()).equals("b")){ 
         p.move(-1, 0); 
         System.out.println(m.getMap(p.getTileX(), p.getTileY())); 
      } 
       } 
      } 
      if(keycode == KeyEvent.VK_RIGHT){ 
       if(!m.getMap(p.getTileX() + 1, p.getTileY()).equals("x")){ 
        if(!m.getMap(p.getTileX() + 1, p.getTileY()).equals("b")){ 
         p.move(1, 0); 
         System.out.println(m.getMap(p.getTileX(), p.getTileY())); 
      } 
      } 
      } 
      } 


     public void keyReleased(KeyEvent e){ 

     } 

     public void keyTyped(KeyEvent e){ 

} 
} 
} 

Player類

package Fatman; 

import java.awt.Image; 

import javax.swing.ImageIcon; 

public class Player { 

    private int tileX, tileY; 
    private int dx, dy; 

    private Image player; 

    public Player(){ 

     ImageIcon img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\FATMANsimplified32xbrown.png"); 
     player = img.getImage(); 

     tileX = 12; 
     tileY = 18; 
    } 

    public Image getPlayer(){ 
     return player; 
    } 
    public int getTileX(){ 
     return tileX; 
    } 
    public int getTileY(){ 
     return tileY; 
    } 

    public void move(int dx, int dy){ 

     tileX += dx; 
     tileY += dy; 
    } 

} 

任何想法?

+1

使用[主題](http://www.codeproject.com/Articles/616109/Java-Thread-Tutorial)。 – elyashiv

+0

這是一個廣泛的問題。你應該嘗試把它分解成更具體的問題。 –

+1

不要在keylistener中移動你的pacman。設置一個標誌,以便您知道該鍵已關閉,並在線程中相應移動,同時檢查這些標誌。還有一種叫做KeyBinding的東西,我看到很多人在談論,但我對它們的瞭解不多。這應該會更好,儘管 – Cruncher

回答

1

對於你的第一個問題,認識到你只是在你的移動方法中增加瓦片數字,然後在那個位置重新繪製播放器(增量爲32像素)。您需要更精細的粒度級別,即不是按瓷磚本身遞增,而是按瓷磚的一部分(例如2像素)遞增。所以FatMan的形象將需要更多的步驟從1瓦移動到另一個。很顯然,如果FatMan的圖像播放器在這段時間內是一個步行/跑步動畫,看起來會更好,讓動作看起來更自然。

所以......在無恥的自我推銷我請你看看我的老教程在這裏: https://sites.google.com/site/javagamescorner/home/animated-sprites

+0

我知道你可能比幫助一個十五歲的孩子做更好的事情,但考慮到我對Java的知識是非常基本的事實,你會介意進一步解釋嗎?我將如何製作它,以便我們的角色逐個像素地移動,而不是按瓦片平鋪?我能想到的唯一的事情就是提出一個變量,它代表圖像的中心,並且只要沒有按下另一個按鈕,就會每y毫秒添加一個x ......我不確定這是怎麼工作的,儘管(如果有的話)。非常感謝你的幫助!非常感謝! – leo882

0

有兩個問題:

首先你需要某種形式的睡眠的/在每次更新之間暫停以模擬時間,否則如果您按住鍵,玩家會立即跳到地圖的盡頭。既然你想在玩家每走一步之後花一些時間。

一種可能性是在每次調用後添加Thread.sleep。

其次,您需要從您的圖塊座標系中分離玩家移動。如果你想讓玩家能夠「在瓷磚之間移動」。他應該使用自己的座標系統,讓他移動更小的步幅。

0

我看了你的代碼,我建議你這些修改:

  • 當你按下一個鍵設置方向可以是向上,向下,向左或向右未來方向(因爲方向必須保持直到移動完成)。你可以用兩個類變量實現:direction和nextDirection。您還可以使用tile的邊緣大小的值設置另一個類變量(例如32)。這個變量被稱爲animationFrame。
  • 在這個例子中,您將定時器頻率或多或少設置爲32 Hz(1000/32毫秒)。你可以玩定時器來適應動畫。
  • 每次調用計時器時,都會沿方向移動1個像素的Fatman圖像(讀取方向變量),並減少animationFrame。當你達到0時,胖人被放置在下一個瓷磚中。您可以通過設置direction = nextDirection來重複操作。現在你必須在這個時候應用遊戲的邏輯(碰撞等)。

這只是一個粗略的方法,但我認爲你可以從這個想法開始。這讓我想起我16歲時在java中編程的蛇遊戲。