如何在Java Breakout游戏中绘制砖块?

时间:2015-04-24 19:03:07

标签: java awt

有一个突破性的游戏,部分是为我创造的;目前它只有弹跳球和蝙蝠;球没有砖块可以击中。

我需要添加代码来生成砖块,但我正在努力;我不知道如何解决这个问题,因为我对Java GUI不是很了解。

我已经包含了需要添加代码的类;需要代码的区域写在评论中

Modelbreakout类:

package breakout;

import java.util.Observable;
import static breakout.Global.*;
/**
 * Model of the game of breakout
 *  The active object ActiveModel does the work of moving the ball
 * @author Mike Smith University of Brighton
 */

public class ModelBreakout extends Observable
{
  private GameObject ball;      // The ball
  private GameObject bricks[];  // The bricks
  private GameObject bat;       // The bat

  private ModelActivePart am  = new ModelActivePart( this );
  private Thread activeModel  = new Thread( am );

  private int score = 0;

  public void createGameObjects()
  {
    ball   = new GameObject(W/2, H/2, BALL_SIZE, BALL_SIZE, Colour.RED );
    bat    = new GameObject(W/2, H - BRICK_HEIGHT*4, BRICK_WIDTH*3, 
                            BRICK_HEIGHT, Colour.GRAY);
    bricks = new GameObject[BRICKS];



    // *[1]**********************************************************
    // * Fill in code to place the bricks on the board              *
    // **************************************************************




  }

  public void startGame()             { activeModel.start(); }

  public GameObject getBall()         { return ball; }

  public GameObject[] getBricks()     { return bricks; }

  public GameObject getBat()          { return bat; }

  public void addToScore( int n )     { score += n; }

  public int getScore()               { return score; }

  public void stopGame()              { }


  /**
   * Move the bat dist pixels. (-dist) is left or (+dist) is right
   * @param dist - Distance to move
   */
  public void moveBat( float dist )
  {
    // *[2]**********************************************************
    // * Fill in code to prevent the bat being moved off the screen *
    // **************************************************************
    Debug.trace( "Model: Move bat = %6.2f", dist );
    bat.moveX(dist);
    //modelChanged();
  }

  /**
   * Model has changed so notify observers so that they
   *  can redraw the current state of the game
   */
  public void modelChanged()
  {
    setChanged(); notifyObservers();
  }

}

ViewBreakout类:

package breakout;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFrame;

import static breakout.Global.*;

/**
 * Displays a graphical view of the game of breakout
 *  Uses Garphics2D would need to be re-implemented for Android
 * @author Mike Smith University of Brighton
 */
public class ViewBreakout extends JFrame implements Observer
{ 
    private ControllerBreakout controller;
    private GameObject   ball;             // The ball
    private GameObject[] bricks;           // The bricks
    private GameObject   bat;              // The bat
    private int          score =  0;       // The score
    private long         timeTaken = 0;    // How long
    private int          frames = 0;       // Frames output
    private final static int  RESET_AFTER = 200;

    /**
     * Construct the view of the game
     */

    public ViewBreakout()
    {
        setSize( W, H );                        // Size of window
        addKeyListener( new Transaction() );    // Called when key press
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        Timer.startTimer();
    }

    /**
     *  Code called to draw the current state of the game
     *   Uses draw:       Draw a shape
     *        fill:       Fill the shape
     *        setPaint:   Colour used
     *        drawString: Write string on display
     *  @param g Graphics context to use
     */
    public void drawActualPicture( Graphics2D g )
    {


        frames++;
        // White background

        g.setPaint( Color.white );
        g.fill( new Rectangle2D.Float( 0, 0, W, H ) );

        Font font = new Font("Monospaced",Font.BOLD,24); 
        g.setFont( font ); 

        // Blue playing border

        g.setPaint( Color.blue );              // Paint Colour
        g.draw( new Rectangle2D.Float( B, M, W-B*2, H-M-B ) );

        // Display the ball
        display( g, ball );

        // Display the bricks that make up the game
        // *[3]**********************************************************
        // * Fill in code to display bricks (A brick may not exist)     *
        // **************************************************************

        // Display the bat
        display( g, bat );

        // Display state of game
        g.setPaint( Color.black );
        FontMetrics fm = getFontMetrics( font );
        String fmt = "BreakOut: Score = [%6d] fps=%5.1f";
        String text = String.format(fmt, score, 
                frames/(Timer.timeTaken()/1000.0)
            );
        if ( frames > RESET_AFTER ) 
        { frames = 0; Timer.startTimer(); }
        g.drawString( text, W/2-fm.stringWidth(text)/2, (int)M*2 );
    }

    private void display( Graphics2D g, GameObject go )
    {
        switch( go.getColour() )
        {
            case GRAY: g.setColor( Color.gray );
            break;
            case BLUE: g.setColor( Color.blue );
            break;
            case RED:  g.setColor( Color.red );
            break;
        }
        g.fill( new Rectangle2D.Float( go.getX(),     go.getY(), 
                go.getWidth(), go.getHeight() ) );
    }

    /**
     * Called from the model when its state has changed
     * @param aModel Model to be displayed
     * @param arg    Any arguments
     */
    @Override
    public void update( Observable aModel, Object arg )
    {
        ModelBreakout model = (ModelBreakout) aModel;
        // Get from the model the ball, bat, bricks & score
        ball    = model.getBall();              // Ball
        bricks  = model.getBricks();            // Bricks
        bat     = model.getBat();               // Bat
        score   = model.getScore();             // Score
        //Debug.trace("Update");
        repaint();                              // Re draw game
    }

    /**
     * Called by repaint to redraw the Model
     * @param g    Graphics context
     */
    @Override
    public void update( Graphics g )          // Called by repaint
    {
        drawPicture( (Graphics2D) g );          // Draw Picture
    }

    /**
     * Called when window is first shown or damaged
     * @param g    Graphics context
     */
    @Override
    public void paint( Graphics g )           // When 'Window' is first
    {                                         //  shown or damaged
        drawPicture( (Graphics2D) g );          // Draw Picture
    }

    private BufferedImage theAI;              // Alternate Image
    private Graphics2D    theAG;              // Alternate Graphics

    public void drawPicture( Graphics2D g )   // Double buffer
    {                                         //  to avoid flicker
        if (  theAG == null )
        {
            Dimension d = getSize();              // Size of curr. image
            theAI = (BufferedImage) createImage( d.width, d.height );
            theAG = theAI.createGraphics();
        }
        drawActualPicture( theAG );             // Draw Actual Picture
        g.drawImage( theAI, 0, 0, this );       //  Display on screen
    }

    /**
     * Need to be told where the controller is
     * @param aPongController The controller used
     */
    public void setController(ControllerBreakout aPongController)
    {
        controller = aPongController;
    }

    /**
     * Methods Called on a key press 
     *  calls the controller to process
     */
    class Transaction implements KeyListener  // When character typed
    {
        @Override
        public void keyPressed(KeyEvent e)      // Obey this method
        {
            // Make -ve so not confused with normal characters
            controller.userKeyInteraction( -e.getKeyCode() );
        }

        @Override
        public void keyReleased(KeyEvent e)
        {
            // Called on key release including specials
        }

        @Override
        public void keyTyped(KeyEvent e)
        {
            // Send internal code for key
            controller.userKeyInteraction( e.getKeyChar() );
        }
    }
}

ModelActivePart类:

package breakout;

import static breakout.Global.*;

/**
 * A class used by the model to give it an active part.
 *  Which moves the ball every n millesconds and implements
 *  an appropirate action on a collision involving the ball.
 * @author Mike Smith University of Brighton
 */
public class ModelActivePart implements Runnable
{
  private ModelBreakout model;
  private boolean runGame = true;           // Assume write to is atomic

  public ModelActivePart(ModelBreakout aBreakOutModel)
  {
    model = aBreakOutModel;
  }

  /**
   * Stop game, thread will finish
   */
  public void stopGame() { runGame = false; }

  /**
   * Code to position the ball after time interval
   *  and work out what happens next
   */

  @Override
  public void run()
  {
    final float S = 6; // Units to move the ball
    try
    {
      GameObject ball     = model.getBall();     // Ball in game
      GameObject bricks[] = model.getBricks();   // Bricks
      GameObject bat      = model.getBat();      // Bat

      while (runGame)
      {
        double x = ball.getX();
        double y = ball.getY();
        // Deal with possible edge of board hit
        if (x >= W - B - BALL_SIZE)  ball.changeDirectionX();
        if (x <= 0 + B            )  ball.changeDirectionX();
        if (y >= H - B - BALL_SIZE) 
        { 
          ball.changeDirectionY(); model.addToScore( HIT_BOTTOM ); 
        }
        if (y <= 0 + M            )  ball.changeDirectionY();

        ball.moveX(S);  ball.moveY(S);

        // As only a hit on the bat/ball is detected it is assumed to be
        // on the top or bottom of the object
        // A hit on the left or right of the object
        //  has an interesting affect

        boolean hit = false;
        // *[4]**********************************************************
        // * Fill in code to check if a brick has been hit              *
        // *  Remember to remove a brick in the array  (if hit)         *
        // *    [remove] - set the array element to null                *
        // **************************************************************
        if (hit)
          ball.changeDirectionY();

        if (bat.hitBy(ball) == GameObject.Collision.HIT)
          ball.changeDirectionY();

        model.modelChanged(); // Model changed refresh screen

        Thread.sleep(20);     // About 50 Hz
      }
    } catch (Exception e) 
    { 
      Debug.error("ModelActivePart - stopped\n%s", e.getMessage() );
    }
  }

}

现在我不希望你为我做任何事情,我只是想知道如何在屏幕上画一块砖;从那以后我可以自己做其余的事。

如果你想要整个包装;我项目的下载链接是here

感谢任何帮助:)

1 个答案:

答案 0 :(得分:2)

对于位置0的蓝砖,0修改createGameObjects类的ModelBreakout方法:

public void createGameObjects() 
{
    ball = new GameObject(W / 2, H / 2, BALL_SIZE, BALL_SIZE, Colour.RED);
    bat = new GameObject(W / 2, H - BRICK_HEIGHT * 4, BRICK_WIDTH * 3,
            BRICK_HEIGHT, Colour.GRAY);
    bricks = new GameObject[BRICKS];

    // *[1]**********************************************************
    // * Fill in code to place the bricks on the board *
    // **************************************************************

    bricks[0] = new GameObject(0, 0, BRICK_HEIGHT, BRICK_WIDTH, Colour.BLUE);
}

然后在drawActualPicture类的ViewBreakout方法中绘制砖块:

// Display the bricks that make up the game
// *[3]**********************************************************
// * Fill in code to display bricks (A brick may not exist)     *
// **************************************************************

for (GameObject brick : bricks) 
{
    if (null != brick)
    {
        display ( g, brick );
    }
}

如果是课程作业,这是一项很棒的作业。