2010-03-17 164 views
1

HI ..我做了一個小遊戲。但是這個遊戲在不同速度的計算機上運行。我認爲它是關於分辨率的。我在paintcomponent中使用了所有東西。如果我改變屏幕尺寸,遊戲速度會變慢或更快。如果我在另一臺計算機上運行這個遊戲,至少有不同的分辨率,它也有不同的作用。 這是我的比賽
http://rapidshare.com/files/364597095/ShooterGame.2.6.0.jar遊戲速度問題

這裏代碼

public class Shooter extends JFrame implements KeyListener, Runnable { 

JFrame frame = new JFrame(); 
String player; 
Font startFont, startSubFont, timerFont,healthFont; 
Image img; 
Image backGround; 
Graphics dbi; 
URL url1 = this.getClass().getResource("Images/p2.gif"); 
URL url2 = this.getClass().getResource("Images/p3.gif"); 
URL url3 = this.getClass().getResource("Images/p1.gif"); 
URL url4 = this.getClass().getResource("Images/p4.gif"); 
URL urlMap = this.getClass().getResource("Images/zemin.jpg"); 
Player p1 = new Player(5, 150, 10, 40, Color.GREEN, url3); 
Computer p2 = new Computer(750, 150, 10, 40, Color.BLUE, url1); 
Computer p3 = new Computer(0, 0, 10, 40, Color.BLUE, url2); 
Computer p4 = new Computer(0, 0, 10, 40, Color.BLUE, url4); 
ArrayList<Bullets> b = new ArrayList<Bullets>(); 
ArrayList<CBullets> cb = new ArrayList<CBullets>(); 
Thread sheap; 
boolean a, d, w, s; 
boolean toUp, toDown; 
boolean GameOver; 

boolean Level2; 
boolean newGame, resart, pause; 
int S, E; 
int random; 
int cbSpeed = 0; 
long timeStart, timeEnd; 
int timeElapsed; 
long GameStart, GameEnd; 
int GameScore; 
int Timer = 0; 
int timerStart, timerEnd; 

public Shooter() { 


    sheap = new Thread(this); 
    sheap.start(); 
    startFont = new Font("Tiresias PCFont Z", Font.BOLD + Font.ITALIC, 32); 
    startSubFont = new Font("Tiresias PCFont Z", Font.BOLD + Font.ITALIC, 25); 
    timerFont = new Font("Tiresias PCFont Z", Font.BOLD + Font.ITALIC, 16); 
    healthFont = new Font("Tiresias PCFont Z", Font.BOLD + Font.ITALIC, 16); 
    setTitle("Shooter 2.5.1"); 
    setBounds(350, 250, 800, 600); 

    // setResizable(false); 
    setBackground(Color.black); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    addKeyListener(this); 
    a = d = w = s = false; 
    toUp = toDown = true; 
    GameOver = true; 
    newGame = true; 
    Level2 = false; 
    S = E = 0; 

    setVisible(true); 

} 

public void paint(Graphics g) { 

    img = createImage(getWidth(), getHeight()); 
    dbi = img.getGraphics(); 
    paintComponent(dbi); 
    g.drawImage(img, 0, 0, this); 

} 

public void paintComponent(Graphics g) { 
    repaint(); 
    timeStart = System.currentTimeMillis(); 
    backGround = Toolkit.getDefaultToolkit().getImage(urlMap); 
    g.drawImage(backGround, 0, 0, null); 
    g.setColor(Color.red); 
    g.setFont(healthFont); 
    g.drawString("" + player + " Health : " + p1.health, 30, 50); 
    g.setColor(Color.red); 
    g.drawString("Computer Health : " + (p2.health + p3.health + p4.health), 600, 50); 
    g.setColor(Color.BLUE); 
    g.setFont(timerFont); 
    g.drawString("Time : " + Timer, 330, 50); 
    if (newGame) { 

     g.setColor(Color.LIGHT_GRAY); 
     g.setFont(startFont); 
     g.drawString("Well Come To Shoot Game", 200, 190); 
     g.drawString("Press ENTER To Start", 250, 220); 
     g.setColor(Color.LIGHT_GRAY); 
     g.setFont(startSubFont); 
     g.drawString("Use W,A,S,D and Space For Fire", 200, 250); 
     g.drawString("GOOD LUCK", 250, 280); 

     newGame(); 

    } 
    if (!GameOver) { 

     for (Bullets b1 : b) { 

      b1.draw(g); 
     } 
     for (CBullets b2 : cb) { 

      b2.draw(g); 

     } 
     update(); // Here MOvements for Player and For Fires 
    } 
    if (p1.health <= 0) { 
     g.setColor(p2.col); 
     g.setFont(startFont); 
     g.drawString("Computer Wins ", 200, 190); 
     g.drawString("Press Key R to Restart ", 200, 220); 
     GameOver = true; 

    } else if (p2.health <= 0 && p3.health <= 0 && p4.health <= 0) { 

     g.setColor(p1.col); 
     g.setFont(startFont); 
     g.drawString(""+player+" Wins ", 200, 190); 
     g.drawString("Press Key R to Resart ", 200, 220); 
     GameOver = true; 


     g.setColor(Color.MAGENTA); 
     g.drawString(""+player+"`s Score is " + Timer, 200, 120); 


    } 

    if (Level2) { 
     if (p3.health >= 0) { 
      p3.draw(g); 

      for (CBullets b3 : cb) { 
       b3.draw(g); 
      } 
     } else { 
      p3.x = 1000; 
     } 

     if (p4.health >= 0) { 
      p4.draw(g); 

      for (CBullets b4 : cb) { 
       b4.draw(g); 
      } 
     } else { 
      p4.x = 1000; 
     } 
    } 
    if (p1.health >= 0) { 
     p1.draw(g); 

    } 
    if (p2.health >= 0) { 
     p2.draw(g); 
    } else { 
     p2.x = 1000; 
    } 

} 

public void update() { 


    if (w && p1.y > 54) { 
     p1.moveUp(); 
    } 

    if (s && p1.y < 547) { 
     p1.moveDown(); 
    } 
    if (a && p1.x > 0) { 
     p1.moveLeft(); 
    } 

    if (d && p1.x < 200) { 
     p1.moveRight(); 
    } 
    random = 1 * (int) (Math.random() * 100); 

    if (random > 96) { 
     if (p2.health >= 0) { 
      CBullets bo = p2.getCBull(); 

      bo.xVel =-1-cbSpeed; 

      cb.add(bo); 
     } 
     if (Level2) { 
      if (p3.health >= 0) { 
       CBullets bo1 = p3.getCBull(); 
       bo1.xVel = -2-cbSpeed; 
       cb.add(bo1); 
      } 
      if (p4.health >= 0) { 
       CBullets bo2 = p4.getCBull(); 
       bo2.xVel = -4-cbSpeed; 
       cb.add(bo2); 
      } 
     } 

    } 

    if (S == 1) { 

     if (p1.health >= 0) { 
      Bullets bu = p1.getBull(); 
      bu.xVel = 5; 
      b.add(bu); 
      S += 1; 
     } 
    } 

    //Here Also Problem .. When COmputer have More fire then it gaves Array Exeption . Or Player have More Fire 
for (int i = cb.size() -1; i >= 0 ; i--) { 
     boolean bremoved = false; 
    for (int j = b.size() -1 ; j >=0 ; j--) { 
     if (b.get(j).rect.intersects(cb.get(i).rect) || 
      cb.get(i).rect.intersects(b.get(j).rect)) { 
       bremoved = true; 
      b.remove(j); 
     } 
    } 
    if(bremoved) 
     cb.remove(i); 
} 






    for (int i = 0; i < b.size(); i++) { 
     b.get(i).move(); 

     if (b.get(i).rect.intersects(p2.rect)) { 

      if (p2.health >= 0) { 
       p2.health--; 

       b.remove(i); 
      //  System.out.println("Hited P2"); 
       i--; 

       continue; 
      } 
     } 

     if (b.get(i).rect.intersects(p3.rect)) { 
      if (p3.health >= 0) { 
       p3.health--; 

       b.remove(i); 
      // System.out.println("Hited P3"); 
       i--; 

       continue; 
      } 
     } 
     if (b.get(i).rect.intersects(p4.rect)) { 
      if (p4.health >= 0) { 
       p4.health--; 

       b.remove(i); 
      // System.out.println("Hited P4"); 
       i--; 

       continue; 
      } 
     } 
     if (b.get(i).rect.x > 790) { 
      b.remove(i); 

     } 
    } 

    for (int j = 0; j < cb.size(); j++) { 
     cb.get(j).move(); 

     if (cb.get(j).rect.intersects(p1.rect) && cb.get(j).xVel < 0) { 

      p1.health--; 
      cb.remove(j); 
      j--; 
      continue; 
     } 
    } 

    timeEnd = System.currentTimeMillis(); 
    timeElapsed = (int) (timeEnd - timeStart); 
} 

public void level2() { 

    if (p2.health <= 10) { 

     Level2 = true; 
     cbSpeed = 4; 
     p3.x = 750; 
     p4.x = 750; 

     p2.speed = 10; 
     p3.speed = 20; 
     p4.speed = 30; 
    } 
} 

public void keyTyped(KeyEvent e) { 
} 

public void keyPressed(KeyEvent e) { 
    switch (e.getKeyCode()) { 
     case KeyEvent.VK_ENTER: 
      newGame = false; 

      break; 
     case KeyEvent.VK_P: 
      pause = true; 

      break; 
     case KeyEvent.VK_R: 
      resart = true; 

      break; 
     case KeyEvent.VK_A: 
      a = true; 

      break; 

     case KeyEvent.VK_D: 
      d = true; 
      break; 
     case KeyEvent.VK_W: 
      w = true; 
      break; 
     case KeyEvent.VK_S: 
      s = true; 
      break; 

     case KeyEvent.VK_SPACE: 
      S += 1; 

      break; 
    } 
} 

public void keyReleased(KeyEvent e) { 
    switch (e.getKeyCode()) { 

     case KeyEvent.VK_A: 
      a = false; 
      break; 
     case KeyEvent.VK_D: 

      d = false; 
      break; 
     case KeyEvent.VK_W: 
      w = false; 
      break; 
     case KeyEvent.VK_S: 
      s = false; 
      break; 

     case KeyEvent.VK_SPACE: 
      S = 0; 

      break; 

    } 
} 

public void newGame() { 

    p1.health = 20; 
    p2.health = 20; 
    p3.health = 20; 
    p4.health = 20; 
    p3.x = 0; 
    p4.x = 0; 
    p2.x = 750; 

    Level2 = false; 
    cbSpeed = 0; 
    p2.speed = 9; 
    b.removeAll(b); 
    cb.removeAll(cb); 

    timerStart = (int) System.currentTimeMillis(); 

    GameOver = false; 

} 

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 

     public void run() { 
      KeyListener k = new Shooter(); 
     } 
    }); 

} 

@Override 
public void run() { 
    player = JOptionPane.showInputDialog(frame, "Enter Player Name", "New Player", JOptionPane.DEFAULT_OPTION); 

    while (true) { 

     timerEnd = (int) System.currentTimeMillis(); 

     if (resart) { 
      newGame(); 
      resart = false; 
     } 
     if (pause) { 
      Thread.currentThread().notify(); 
     } 
     try { 

      if (!GameOver) { 
Timer = timerEnd - timerStart; 
       level2(); 
       if (p1.y < p2.y && p2.y>60) { 
        p2.moveUp(); 
       } 
       if (p1.y < p3.y && p3.y>43) { 
        p3.moveUp(); 
       } 
       if (p1.y < p4.y && p4.y>43) { 
        p4.moveUp(); 

       } 
       if (p1.y > p2.y && p2.y<535) { 
        p2.moveDown(); 
       } 
       if (p1.y > p3.y && p3.y<535) { 
        p3.moveDown(); 
       } 
       if (p1.y > p4.y && p4.y<530) { 
        p4.moveDown(); 
       } 

      } 
      if (timeElapsed < 125) { 
       Thread.currentThread().sleep(125); 
      } 
     } catch (InterruptedException ex) { 
      System.out.print("FInished"); 

     } 

    } 

} 

}

回答

0

嗨再次..我做了一些modıfıcation我的遊戲像繪製和移動對象的線程..現在它工作在每個сomputer相同speed.Also,如果我改變size.But問題是我用J3DTimer.getValue()。對於這個庫,我已經下載了Java3d。問題是如果在機器上沒有這個庫或安裝,我的遊戲無法正常工作。我該如何解決這個問題?我應該說每一個設置Java#d? :))我也使用了standart System.currentTimeMillis();但現在我的遊戲工作非常緩慢......任何想法?

+1

您可以將此帖轉爲原始問題,也可以開始新帖。每個線程的「答案」部分僅用於答案。答案不是在寫作時安排的,所以像這樣的討論實際上並不奏效。 – Ponkadoodle 2010-03-19 21:17:52

+0

@Wallacoloo感謝您的建議。 – Ercan 2010-03-19 23:38:46

4

很難從你的揮霍說,但我會正前方去,反正回答:問題似乎是你不會丟幀;只有拖延他們。基本上,您需要將您的遊戲邏輯與繪圖邏輯分開,然後繪製儘可能多的框架。這兩者可能應該在不同的線程上,但是再一次,線程是邪惡的。

+0

只要您使用適當的包裝器或庫,線程就很好。像SwingWorker,Future's等 – extraneon 2010-03-17 16:04:10

+0

+1雖然分離的擔憂,你可以想象大家應該知道,現在:) – extraneon 2010-03-17 16:05:26

+0

@ Williham你的意思是我必須創建另一個油漆方法,並在線程中使用它? – Ercan 2010-03-17 16:54:27

3

您正在尋找的主題是「基於時間的動作」。我沒有閱讀你的源代碼,但你描述的行爲看起來像基於幀的移動是問題。

這裏是一個簡短的教程,涵蓋了基於時間的運動: http://jerome.jouvie.free.fr/OpenGl/Tutorials/Tutorial10.php

這篇文章也涵蓋了更詳細的問題,重點在物理,但也適用於比較簡單的遊戲: http://gafferongames.com/game-physics/fix-your-timestep/

編輯:正如其他答案所述,分離渲染和遊戲邏輯非常有幫助。

0

您需要跟蹤自上次「打勾」(屏幕重新繪製)以來的毫秒數,並且只有在經過了一定的時間後才更新您的世界狀態(例如位置)。否則,您的遊戲將以不一致的屏幕重繪速度運行。假設你想以25fps的速度運行,那意味着你應該每秒更新遊戲狀態25次,即每40秒更新一次。