2011-06-07 49 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