2011-06-07 36 views
1

我正在製作遊戲(請參閱我以前的主題),並且在途中遇到了很多問題。我所知道的是他編碼編譯,運行,但沒有出現在窗口中,它只是灰色。在Andrew Thompson的建議下,我在這裏發佈整個可編譯版本。對不起,但它是程序中的所有代碼。許多事情可能沒有意義(未使用ActionPerformed來命名),部分原因是因爲我在需要的時候實現了代碼,但主要是因爲我以前從未這樣做過。圖形沒有出現在JFrame中(包含SSCCE)

另外,到目前爲止,我還沒有多線程,因爲我再次對此感到陌生,所以理想情況下我想保持這種狀態,只是爲了我的理智。

編輯:忘了提及我有4 PNG在那裏代表4個不同的對象出現。我的代碼足夠靈活,可供您自己提供。下面是我使用的船舶enter image description here這裏的圖像是一個子彈enter image description here只是製作拷貝,把它們的源文件,並命名爲「敵艦」「SHIP2」「Ebullet」和「PBullet」

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.Timer; 

import javax.swing.JFrame; 


public class GameController extends JFrame implements ActionListener { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -3599196025204169130L; 
    private static GameView window; 
    private static Timer time; 

    public GameController() 
    { 
     setTitle("Space Shooter"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setSize(800, 600); 

     //window = new GameView(800,600); 
     //window.setVisible(true); 

     // 
    } 
    //TODO spawn 
    /*public static void main(String args[]) 
    { 
     //GameController c = new GameController(); 
     window = new GameView(800,600); 
     window.setVisible(true); 

     time = new Timer(40, this); 
     time.schedule(new TimerTask(){ 
      public void run(){GameState.update(); 
      window.paintComponents(null);} 
      },0, 40); 

    }*/ 




    public void display() { 
     add(new GameView(800,600)); 
     pack();   
     setMinimumSize(getSize());// enforces the minimum size of both frame and component 
     setVisible(true); 
    } 

    public static void main(String[] args) { 
     GameController main = new GameController(); 
     main.display(); 
     time = new Timer(40, main); 
    } 


    @Override 
    public void actionPerformed(ActionEvent e) { 
     if(e instanceof EndEvent)//TODO fix this 
     { 

     } 
     else 
     { 
      repaint(); 
     } 

    } 
} 



package Game; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 

public class GameView extends JComponent implements ActionListener{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -2869672245901003704L; 
    private static final Graphics Graphics = null; 
    private boolean liveGame;//used so that buttons cannot be clicked after game is complete 
    private GameState gs; 
    private Player p; 
    private int w, h; 

    public GameView(int width, int height) 
    { 
     liveGame = true; 
     gs = new GameState(); 
     GameState.init(width, height); 
     p = new Player(width/2,(height*7)/8); 
     this.setBackground(Color.BLACK); 
     paintComponents(Graphics); 
     w = width; 
     h = height; 
    } 
     @Override 
     public Dimension getMinimumSize() { 
      return new Dimension(w, h); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(w, h); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      int margin = 10; 
      Dimension dim = getSize(); 
      super.paintComponent(g); 
      g.setColor(Color.black); 
      GameState.update(); 

      for(Bullet j : GameState.getEnBullets()){ 
       g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
      for(Enemy j : GameState.getEnemies()){ 
       g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
      for(Bullet j : GameState.getPlayBullets()){ 
       g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
      g.fillRect(margin, margin, dim.width - margin * 2, dim.height - margin * 2); 
     } 

    public void paintComponents (Graphics g) 
    { 

     for(Bullet j : GameState.getEnBullets()){ 
      g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
     for(Enemy j : GameState.getEnemies()){ 
      g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
     for(Bullet j : GameState.getPlayBullets()){ 
      g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
     this.paint(g); 
    } 



    public void refreshImage() 
    { 
     this.removeAll(); 
     paintComponents(Graphics); 
    } 


    public void actionPerformed(ActionEvent e) { 


    } 


} 


package Game; 
import java.awt.event.ActionEvent; 
import java.util.ArrayList; 

import javax.swing.JFrame; 
public class GameState { 

    private static ArrayList<Bullet> playBullets; 
    public static ArrayList<Bullet> getPlayBullets() { 
     return playBullets; 
    } 

    public static ArrayList<Bullet> getEnBullets() { 
     return enBullets; 
    } 

    public static ArrayList<Enemy> getEnemies() { 
     return enemies; 
    } 

    public static Player getP() { 
     return p; 
    } 

    private static ArrayList<Bullet> enBullets; 
    private static ArrayList<Enemy> enemies; 
    private static int X, Y;//for limit of screen so nothing can go outside of screen 
    private static Player p; 
    private static int score; 

    public GameState(){ 

    } 

    public static void init(int x, int y) 
    { 
     playBullets = new ArrayList<Bullet>(); 
     enBullets = new ArrayList<Bullet>(); 
     enemies = new ArrayList<Enemy>(); 
     X=x; 
     Y=y; 
     p = null; 
     score =0; 
    } 

    public static int xLimit(){return X;} 
    public static int yLimit(){return Y;} 

    public static int getScore(){return score;} 

    public static void add (Location e) 
    { 
     if(e instanceof Bullet) 
     { 
      if(((Bullet) e).getOwner() instanceof Enemy){ 
       enBullets.add((Bullet) e); 
      } 
      else 
       playBullets.add((Bullet) e); 
     } 
     else if(e instanceof Enemy){enemies.add((Enemy)e);} 
     else 
      p=(Player)e; 
    } 

    public static void spawn() 
    { 
     Enemy e = new Enemy(((int)(Math.random()*(X-56))+28), 0, 1); 
    } 


    public static void playerCD()//detects if player has collided with anything, removes whatever collided with it, and causes the player to take damage 
    { 
     if(enemies.size()>0){ 
     for(int i =0; i < enemies.size(); i++) 
     { 
      if (p.getLocation().intersects(enemies.get(i).getLocation())) 
      { 
       p.takeDamage(enemies.get(i).getDamage()); 
       enemies.get(i).takeDamage(p.getDamage()); 

      } 
     } 
     if(enBullets.size()>0) 
     for(int i =0; i < enBullets.size(); i++) 
     { 
      if (p.getLocation().intersects(enBullets.get(i).getLocation())) 
      { 
       p.takeDamage(enBullets.get(i).getDamage()); 
       enBullets.remove(i); 
       i--; 

      } 
     } 
     } 
    } 

    public static void enemyCD() 
    { 
     for(int i =0; i < enemies.size(); i++) 
     { 
      for(int n =0; n < playBullets.size(); n++) 
      { 
       if (playBullets.get(n).getLocation().intersects(enemies.get(i).getLocation())) 
        { 
         enemies.get(i).takeDamage(playBullets.get(i).getDamage()); 
         playBullets.remove(n); 
         n--; 
         score+=50; 
        } 
       } 
      } 

     } 

    public static void checkForDead()//clears away dead and things gone offscreen 
    { 

     for(int i =0; i < enemies.size(); i++) 
     { 
      if(enemies.get(i).getY()>Y) 
      { 
       enemies.remove(i); 
       i--; 
      } 
     } 


     for(int i =0; i < enBullets.size(); i++) 
     { 
      if(enBullets.get(i).getY()>Y) 
      { 
       enBullets.remove(i); 
       i--; 
      } 
     } 

     for(int i =0; i < enemies.size(); i++) 
     { 
      if(enemies.get(i).getHealth()>0) 
      { 
       enemies.remove(i); 
       i--; 
       score+=200; 
      } 
     } 

     if(p.getHealth()<=0) 
     { 
      ActionEvent e = new EndEvent(null, 0, "end"); 
     } 
    } 

    public static void update() 
    { 
     move(); 
     playerCD(); 
     enemyCD(); 
     checkForDead(); 
    } 

    public static void move() 
    { 
     p.move(); 
     for(int i =0; i < enemies.size(); i++){enemies.get(i).move();} 
     for(int i =0; i < enBullets.size(); i++){enBullets.get(i).move();} 
     for(int i =0; i < playBullets.size(); i++){playBullets.get(i).move();} 
    } 





} 


package Game; 

import java.awt.Rectangle; 
import java.awt.event.ActionListener; 

public abstract class Fights extends Location implements ActionListener { 

    public Fights(Rectangle location) { 
     super(location); 
     // TODO Auto-generated constructor stub 
    } 

    public Fights(){} 
    protected int health; 
    protected int maxHealth;//in the event that I want to have healing items 
    protected int shotCooldown;//in milliseconds 
    protected int shotDmg; 
    protected long currentCool; //cooldown tracker, represents time that shot will be cooled down by (System time @ last shot + shotCooldown 
    protected int xVel, yVel; 
    public abstract boolean shoot(); 
    public abstract int takeDamage(int damage);//returns remaining health 
    protected boolean shoots;//determines whether thing can shoot. possible implementation in some enemy class 
    public boolean move; 
    public int getHealth(){return health;} 
    public abstract boolean move(); 
    public int getDamage(){return shotDmg;} 
    public boolean isDead() 
    { 
     return health<=0; 
    } 


} 



package Game; 

import java.awt.Image; 
import java.awt.Rectangle; 
import java.awt.image.BufferedImage; 



public class Location { 
    protected Rectangle loc; 
    protected Image image; 

    public Location(){}; 

    public Location (Rectangle location) 
    { 
     loc = location; 
    } 

    public Rectangle getLocation() 
    { 
     return loc; 
    } 

    public void setLocation(Rectangle l) 
    { 
     loc = l; 
    } 

    public void updateLocation(int x, int y) 
    { 
     loc.setLocation(x, y); 
    } 

    public Image getImage() 
    { 
     return image; 
    } 

    public int getX() 
    { 
     return (int)loc.getX(); 
    } 

    public int getY() 
    { 
     return (int)loc.getY(); 
    } 
     } 

package Game; 

import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.awt.Rectangle; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 

public class Player extends Fights implements KeyListener{ 

    int speed = 4; 

    public Player(Rectangle location) { 
     super(location); 
     GameState.add(this); 
     image = null; 
     try{ 
      image = ImageIO.read(new File("ship2.png")); 
     }catch(IOException e){} 
    } 

    public Player(int x, int y) { 

     maxHealth = 1; 
     health = maxHealth; 
     image = null; 
     try{ 
      image = ImageIO.read(new File("ship2.png")); 
     }catch(IOException e){} 


     this.setLocation(new Rectangle(x, y, image.getWidth(null), image.getHeight(null))); 
     GameState.add(this); 
    } 

    public void resetVelocity() 
    { 
     xVel = 0; 
     yVel = 0; 
    } 


    @Override 
    public boolean shoot() { 
     if(currentCool - System.currentTimeMillis() >0){return false;} 
     else 
     { 
      new Bullet(this); 
      currentCool = System.currentTimeMillis() + shotCooldown; 
     }//spawns bullet in the center and slightly in front of player 
     return true; 
    } 

    @Override 
    public int takeDamage(int damage) { 

     return health-=damage; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public boolean move() {//moves in a direction only if it won't exceed screen boundary, boolean just in case i need it later 
     int newX = this.getX(), newY=this.getY(); 
     if((xVel+ this.getX()+this.getLocation().width)<GameState.xLimit()&& this.getX()+xVel>=0) 
     { 
      newX +=xVel; 
     } 
     if((yVel+ this.getY()+this.getLocation().height)<GameState.yLimit()&& this.getY()+yVel>=0) 
     { 
      newY +=yVel; 
     } 
     this.updateLocation(newX, newY); 
     this.resetVelocity(); 

     return true; 
    } 

    @Override 
    public void keyPressed(KeyEvent arg0) { 

     if (arg0.getKeyCode()== KeyEvent.VK_LEFT) 
     { 
      xVel -= speed; 
     } 


     if (arg0.getKeyCode()== KeyEvent.VK_RIGHT) 
     { 
      xVel += speed; 
     } 

     if (arg0.getKeyCode()== KeyEvent.VK_UP) 
     { 
      yVel -= speed; 
     } 


     if (arg0.getKeyCode()== KeyEvent.VK_DOWN) 
     { 
      yVel += speed; 
     } 

     if(arg0.getKeyCode()==KeyEvent.VK_SPACE) 
     { 
      this.shoot(); 
     } 


    } 

    @Override 
    public void keyReleased(KeyEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void keyTyped(KeyEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

} 


package Game; 

import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 

public class Enemy extends Fights { 

    public Enemy(Rectangle location) { 
     super(location); 
     GameState.add(this); 
     image = null; 
     try{ 
      image = ImageIO.read(new File("Enemy-Ship.png")); 
     }catch(IOException e){} 
    } 
    public Enemy(int x, int y, int d) { 
     image = null; 
     try{ 
      image = ImageIO.read(new File("Enemy-Ship.png")); 
     }catch(IOException e){} 


     this.setLocation(new Rectangle(x, y, image.getWidth(null), image.getHeight(null))); 
     GameState.add(this); 

     shotCooldown =(int)(Math.random()*2000); 

     xVel = (int)((Math.pow(-1, (int)(Math.random())))*((int)(Math.random()*6))+2); 
     yVel = (int)(Math.random()*3+1); 
     shotDmg =d; 
    } 


    public void actionPerformed(ActionEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public boolean shoot() { 
     if(currentCool - System.currentTimeMillis() >0){return false;} 
     else 
     { 
      new Bullet(this); 
      currentCool = System.currentTimeMillis() + shotCooldown; 
     }//spawns bullet in the center and slightly in front of player 
     return true; 
    } 

    @Override 
    public int takeDamage(int damage)//returns remaining health 
    { 
     health = health-damage; 
     return health; 
    } 
    @Override 
    public boolean move() { 
     int newX = this.getX(), newY=this.getY(); 
     if((xVel+ this.getX()+this.getLocation().width)<GameState.xLimit()&& this.getX()+xVel>=0) 
     { 
      xVel=-xVel; 
      newX +=xVel; 
     } 
     if(this.getY()+yVel>=0) 
     { 
      newY +=yVel; 
     } 
     this.updateLocation(newX, newY); 

     return true; 
    } 

} 

package Game; 

import java.awt.Rectangle; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 

public class Bullet extends Location{ 
    private Fights bulletOwner; 
    private int damage; 
    private int velocity; 

    public Bullet(Fights owner)//eventually change to singleton pattern for efficiency 
    { 
     bulletOwner = owner; 
     damage = owner.getDamage(); 
     image = null; 
     if(owner instanceof Enemy) 
     { 
      try{ 
       image = ImageIO.read(new File("Ebullet.png")); 
      }catch(IOException e){} 
      this.setLocation(new Rectangle(owner.getX(), owner.getY()+((int)(owner.getLocation().getHeight()/2)), image.getWidth(null), image.getHeight(null))); 
      velocity = 5; 

     } 

     else 
     { 
      try{ 
       image = ImageIO.read(new File("Pbullet.png")); 
      }catch(IOException e){} 
      this.setLocation(new Rectangle(owner.getX(), owner.getY()-((int)(owner.getLocation().getHeight()/2)), image.getWidth(null), image.getHeight(null))); 
      velocity = -15; 

     } 
     GameState.add(this); 


    } 

    public Fights getOwner(){return bulletOwner;} 
    public int getDamage(){return damage;} 
    public int getVelocity(){return velocity;} 
    public boolean move() 
    { 
     this.updateLocation(this.getX(), this.getY()+velocity); 
     return true; 
    } 


} 
+0

意味着http://stackoverflow.com/questions/6263409/error-with-timer-and-jframe和http://stackoverflow.com/questions/6271909/graphics-not-appearing-in-jframe – mKorbel 2011-06-07 21:41:09

+0

Andrew did不建議你發佈整個代碼。在發佈不正確的內容之前,請至少*閱讀*創建[sscce](http://sscce.org)的鏈接。 – 2011-06-07 21:53:12

+0

我讀過了。我發佈了我的代碼的工作版本,這個代碼的長度並不短,但根據定義,代碼長度很短(低於20 KB)。該代碼是自包含的,並顯示了在GameController類中調用主方法時的示例。 – Will 2011-06-07 21:59:55

回答

2

好的,所以我想我已經把它的大部分都弄清楚了。

你有幾個問題。

首先,你應該只看到一個灰色的屏幕,中間有一個黑色的矩形,因爲你的子彈和敵人陣列中沒有任何東西。這是我在運行你的代碼時所得到的(在刪除對endEvent的引用之後,它無法找到它)。所以要解決這個問題,只需要給它一些東西來繪製

第二個問題很明顯,一旦你給它繪製一些東西。我手動輸入一行代碼來繪製播放器,爲此我使用了我自己的一個png。當你這樣做時,它將無法編譯一個空指針異常。原因是因爲在您的GameView類中,您將名爲「graphics」的Graphics對象設置爲null,但是您繼續調用paintComponents(graphics)。如前所述,這只是以前編譯,因爲你從來沒有真正畫過任何東西。爲了解決這個問題,你可以刪除

public void paintComponents (Graphics g) 
{ 

    for(Bullet j : GameState.getEnBullets()){ 
     g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
    for(Enemy j : GameState.getEnemies()){ 
     g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
    for(Bullet j : GameState.getPlayBullets()){ 
     g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
    this.paint(g); 

} 

並且讓重載的paintComponent(Graphics g)方法完成所有的工作。此外,而不是paintComponents(圖形)調用,使用repaint()。你也可以在構造函數中第一次調用paintComponents(graphics),因爲它默認會第一次繪製。如果你真的想使用自己的方法,那麼你必須創建一個圖形對象並將其傳入。

最後,在重寫的paintComponents(Graphics g)方法中,最後一行是繪製巨大的黑色框。這會掩蓋你之前繪製的任何東西。所以你應該把它作爲第一行,並且按順序繪製其他所有東西,這樣你想要在最前面的東西應該被繪製到最後。我能夠讓我的測試圖像顯示出該類的以下代碼。我不認爲我改變了其他任何東西。

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 

public class GameView extends JComponent implements ActionListener{ 

/** 
* 
*/ 
private static final long serialVersionUID = -2869672245901003704L; 
private boolean liveGame;//used so that buttons cannot be clicked after game is complete 
private GameState gs; 
private Player p; 
private int w, h; 

public GameView(int width, int height) 
{ 
    liveGame = true; 
    gs = new GameState(); 
    GameState.init(width, height); 
    p = new Player(width/2,(height*7)/8); 
    this.setBackground(Color.BLACK); 
    w = width; 
    h = height; 
} 
    @Override 
    public Dimension getMinimumSize() { 
     return new Dimension(w, h); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(w, h); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     int margin = 10; 
     Dimension dim = getSize(); 
     super.paintComponent(g); 
     g.setColor(Color.black); 
     GameState.update(); 

     g.fillRect(margin, margin, dim.width - margin * 2, dim.height - margin * 2); 

     for(Bullet j : GameState.getEnBullets()){ 
      g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
     for(Enemy j : GameState.getEnemies()){ 
      g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 
     for(Bullet j : GameState.getPlayBullets()){ 
      g.drawImage(j.getImage(),j.getX(), j.getY(), null);} 

     g.drawImage(p.getImage(),p.getX(),p.getY(),null); 
    } 




public void refreshImage() 
{ 
    this.removeAll(); 
    repaint(); 
} 


public void actionPerformed(ActionEvent e) { 


} 


} 

另一件事是在你的一些其他類中你有@Override的actionPerformed方法。我的IDE不喜歡,雖然它編譯。它說「在實現接口方法時不允許使用@Override」。

希望這對你的作品。

+0

解決了許多問題中的第一個問題。謝謝! – Will 2011-06-08 00:28:41

0

嘗試添加repaint();在對內容窗格進行更改之後。除非你堵塞​​了EDT,否則我不認爲併發會成爲一個問題。

5

我不敢相信你在編寫700行代碼時沒有做任何測試。它的時間你回到開始,並從簡單的事情開始。這是一個SSCCE的重點。首先繪製幾個組件。一旦你得到這個工作,你會添加一些動作。一旦這是工作,你添加衝突邏輯。

我注意到快速瀏覽器的唯一的事情就是您重寫paintComponents()。不需要在pantComponent()方法中完成自定義繪畫。

如果你不能生產更小尺寸的SSCCE,那麼我所能做的就是祝你好運。

+0

阿門說得好。 – 2011-06-08 03:01:11