天天看點

《Java 2D遊戲程式設計入門》—— 8.7 編寫原型遊戲

本節書摘來異步社群《java 2d遊戲程式設計入門》一書中的第8章,第8.7節,作者:【美】timothy wright(萊特),更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

原型遊戲如圖8.12所示,位于javagames.prototype包中,它使用了我們目前為止所見過的所有技術。盡管這隻是一個原型,并且目前還沒有成為一款完整的遊戲,但我已經展示了足夠的工具來讓一些功能奏效。如果要等到最後再制作一款遊戲,可能需要等太長的時間。

《Java 2D遊戲程式設計入門》—— 8.7 編寫原型遊戲

該原型遊戲使用了我們在本章前面所介紹的如下的類。

polygonwrapper

prototypeship

prototypeasteroid

prototypeasteroidfactory

prototypebullet

當你在本章末尾嘗試編譯和運作代碼之前,確定已經建立了這些類。

initialize()方法為原型建立了所有這些對象,包括建立了一些星星作為背景。如下的代碼建立了星星,并且建立了顔色的一個數組。color類接受3個值:red、blue和green,這3個值在0到1之間。将每種顔色值設定為相同的值,将會産生灰色的陰影。本書稍後會詳細介紹顔色,但現在,隻要使用java語言所提供的java.awt.color類就行了。

// prototypegame.java

private vector2f getasteroidstartposition() {

  float angle = (float)math.toradians( rand.nextint( 360 ) );

  float minimum = appworldwidth / 4.0f;

  float extra = rand.nextfloat() * minimum;

  float radius = minimum + extra;

  return vector2f.polar( angle, radius );

}<code>`</code>

前面的代碼在圓圈中放置了新的多邊形,該圓圈是螢幕的四分之一大,如圖8.13所示。

《Java 2D遊戲程式設計入門》—— 8.7 編寫原型遊戲

這會防止這種現象發生:新産生的小行星出現于飛船的頂部,玩家還沒來得及開火,就碰到它并爆炸了。這是遊戲程式員所面對的各種挑戰的一個很好的例子。隻有在原型遊戲開始運作時,這個問題才會變得明顯。不管遊戲多麼簡單,總是會有奇怪的問題需要解決。

processinput()方法使用向左鍵和向右鍵來旋轉飛船,向上鍵會激活加速動作,空格鍵會發射子彈,escape鍵會重新産生小行星。

當子彈擊中小行星時,不僅小行星會從渲染清單中删除,而且如果小行星不是太小的話,它會分裂成兩塊更小的小行星。

updateship()方法檢查碰撞。如果飛船被擊中,會設定毀滅标志。盡管在真實的遊戲中,當飛船被擊中時,遊戲會重新啟動,但我們還沒有介紹玩家生命或遊戲結束狀态的概念,是以,目前當飛船被擊中時,将其繪制為紅色。

render()方法繪制星星、所有的小行星、子彈、飛船以及常用的幀速率和指令。還有一些新的代碼,它們會開啟抗鋸齒功能,以使線條繪制得更為平滑。第10章将會介紹抗鋸齒。

package javagames.prototype;

import java.awt.*;

import java.awt.event.keyevent;

import java.util.*;

import javagames.prototype.prototypeasteroid.size;

import javagames.util.*;

public class prototypegame extends simpleframework {

  private static final int star_count = 1500;

  private prototypeship ship;

  private polygonwrapper wrapper;

  private prototypeasteroidfactory factory;

  private arraylist bullets;

  private arraylist asteroids;

  private random rand;

  private vector2f[] stars;

  private color[] colors;

  public prototypegame() {

    appborderscale = 0.9f;

    appwidth = 640;

    appheight = 640;

    appmaintainratio = true;

    appsleep = 1l;

    apptitle = "prototype game";

  }

  @override

  protected void initialize() {

    super.initialize();

    // create game objects

    rand = new random();

    bullets = new arraylist();

    asteroids = new arraylist();

    wrapper = new polygonwrapper( appworldwidth, appworldheight );

    ship = new prototypeship( wrapper );

    factory = new prototypeasteroidfactory( wrapper );

    createstars();

    createasteroids();

  // this creates the random stars for the background

  private void createstars() {

    stars = new vector2f[ star_count ];

    colors = new color[ star_count ];

    for( int i = 0; i &lt; stars.length; ++i ) {

      float x = rand.nextfloat() * 2.0f - 1.0f;

      float y = rand.nextfloat() * 2.0f - 1.0f;

      stars[i] = new vector2f( x, y );

      float color = rand.nextfloat();

      colors[i] = new color( color, color, color );

    }

  // create the random asteroids

  private void createasteroids() {

    asteroids.clear();

    for( int i = 0; i &lt; 4; ++i ) {

      vector2f position = getasteroidstartposition();

      asteroids.add( factory.createlargeasteroid( position ) );

  // create random position for an asteroid

  private vector2f getasteroidstartposition() {

    float angle = (float)math.toradians( rand.nextint( 360 ) );

    float minimum = appworldwidth / 4.0f;

    float extra = rand.nextfloat() * minimum;

    float radius = minimum + extra;

    return vector2f.polar( angle, radius );

  protected void processinput( float delta ) {

    super.processinput( delta );

    // fly the ship

    if( keyboard.keydown( keyevent.vk_left ) ) {

      ship.rotateleft( delta );

    if( keyboard.keydown( keyevent.vk_right ) ) {

      ship.rotateright( delta );

    if( keyboard.keydownonce( keyevent.vk_space ) ) {

      bullets.add( ship.launchbullet() );

    if( keyboard.keydownonce( keyevent.vk_escape ) ) {

      createasteroids();

    ship.setthrusting( keyboard.keydown( keyevent.vk_up ) );

  protected void updateobjects( float delta ) {

    super.updateobjects( delta );

    updateasteroids( delta );

    updatebullets( delta );

    updateship( delta );

  private void updateasteroids( float delta ) {

    for( prototypeasteroid asteroid : asteroids ) {

      asteroid.update( delta );

  private void updatebullets( float delta ) {

    arraylist copy =

      new arraylist( bullets );

    for( prototypebullet bullet : copy ) {

      updatebullet( delta, bullet );

  // check for bullet collisions

  private void updatebullet( float delta, prototypebullet bullet ) {

    bullet.update( delta );

    if( wrapper.hasleftworld( bullet.getposition() ) ) {

      bullets.remove( bullet );

    } else {

      arraylist ast =

        new arraylist( asteroids );

      for( prototypeasteroid asteroid : ast ) {

        if( asteroid.contains( bullet.getposition() ) ) {

          bullets.remove( bullet );

          asteroids.remove( asteroid );

          spawnbabies( asteroid );

        }

      }

  // create smaller asteroids when one is broken apart

  private void spawnbabies( prototypeasteroid asteroid ) {

    if( asteroid.getsize() == size.large ) {

      asteroids.add(

        factory.createmediumasteroid( asteroid.getposition() ) );

    if( asteroid.getsize() == size.medium ) {

        factory.createsmallasteroid( asteroid.getposition() ) );

  // update the ship object

  private void updateship( float delta ) {

    ship.update( delta );

    boolean ishit = false;

      if( ship.istouching( asteroid ) ) {

        ishit = true;

    ship.setdamaged( ishit );

  protected void render( graphics g ) {

    // render instructions

    super.render( g );

    g.drawstring( "rotate: left/right arrow", 20, 35 );

    g.drawstring( "thrust: up arrow", 20, 50 );

    g.drawstring( "fire: space bar", 20, 65 );

    g.drawstring( "press esc to respawn", 20, 80 );

    graphics2d g2d = (graphics2d)g;

    g2d.setrenderinghint(

      renderinghints.key_antialiasing,

      renderinghints.value_antialias_on

    );

    // draw game objects

    matrix3x3f view = getviewporttransform();

    drawstars( g2d, view );

    drawasteroids( g2d, view );

    drawbullets( g2d, view );

    drawship( g2d, view );

  private void drawstars( graphics2d g, matrix3x3f view ) {

      g.setcolor( colors[i] );

      vector2f screen = view.mul( stars[i] );

      g.fillrect( (int)screen.x, (int)screen.y, 1, 1 );

  private void drawship( graphics2d g, matrix3x3f view ) {

    ship.draw( g, view );

  private void drawasteroids( graphics2d g, matrix3x3f view ) {

      asteroid.draw( g, view );

  private void drawbullets( graphics2d g, matrix3x3f view ) {

    for( prototypebullet b : bullets ) {

      b.draw( g, view );

  public static void main( string[] args ) {

    launchapp( new prototypegame() );