《Java 2D游戏编程入门》—— 8.3 创建一个原型编辑器

8.3 创建一个原型编辑器

现在是时候创建一些多边形了。尽管有可能可以猜到每个点,但要创建9个小行星形状,手动进行的话,工作量还是很大的。就像大多数程序一样,我也很懒。编写一个编辑器来创建多边形,这样会容易很多。位于javagames.prototype包中的PrototypeEditor,如图8.9所示。

如果模型存储为文件,它们将在运行时加载。然而,做这些事情所需的代码还没有介绍过,因此,编辑器将会作弊。当按下空格键的时候,编辑器会产生出能够粘贴到其他源文件中的代码。本书的第二部分将会介绍使用真正的文件,因此,你不必为此而担心。

polygon列表保存了模型的点。mousePos是鼠标的当前位置,布尔变量closed所保存的值,确定了在绘制时多边形的最后一个点是否和第一个点相连。

processInput()方法处理编辑器的交互。当按下鼠标左键时,会给多边形添加一个点。鼠标中键用于切换closed变量。鼠标右键从多边形删除点。C键清除整个多边形,空格键打印出多边形代码。printPolygon()方法向控制台打印出当前的多边形,以便可以将其粘贴到一个文本文件中或复制到其他的代码文件中。打印到调试控制台的输出如下所示:

Vector2f[] v = new Vector2f[] {
  new Vector2f(-0.2895149f, 0.3865415f),
  new Vector2f(-0.47104853f, -0.28012514f),
  new Vector2f(-0.14241004f, 0.15805948f),
  new Vector2f(-0.13615024f, -0.30516434f),
  new Vector2f(0.28012514f, -0.2832551f),
  new Vector2f(0.17370892f, 0.21752739f),
  new Vector2f(-0.19248825f, 0.40219092f),
  new Vector2f(-0.18622851f, 0.25195616f),
  };```
render()方法显示常用的指令,并且绘制多边形以及轴线。drawAxisLines()方法在编辑器中绘制两条线,表示x轴和y轴。

drawPolygon()方法负责渲染当前模型。如果多边形只是一个点,那么,绘制单个的点。接下来,如果多边形有多个点,那么所有的点(除了最后一个点以外)都绘制。如果多边形是闭合的,那么,最后一个点连接到第一个点。如果多边形不是闭合的,那么,从最后一个点到当前鼠标位置绘制一条线。drawPoint()和drawLine()方法都是标准版本。

package javagames.prototype;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javagames.util.*;

public class PrototypeEditor extends SimpleFramework {
  private ArrayList polygon;
  private Vector2f mousePos;
  private boolean closed;
  public PrototypeEditor() {
    appTitle = "Prototype Editor 1.0";
    appWidth = 640;
    appHeight = 640;
    appBackground = Color.WHITE;
    appFPSColor = Color.BLACK;
  }
  protected void initialize() {
    super.initialize();
    polygon = new ArrayList();
  }
  protected void processInput( float delta ) {
    super.processInput( delta );
    mousePos = getWorldMousePosition();
    if( mouse.buttonDownOnce( MouseEvent.BUTTON1 ) ) {
      polygon.add( mousePos );
    }
    if( mouse.buttonDownOnce( MouseEvent.BUTTON2 ) ) {
      closed = !closed;
    }
    if( mouse.buttonDownOnce( MouseEvent.BUTTON3 ) ) {
      if( !polygon.isEmpty() ) {
        polygon.remove( polygon.size() - 1 );
      }
    }
    if( keyboard.keyDownOnce( KeyEvent.VK_C ) ) {
      polygon.clear();
    }
    if( keyboard.keyDownOnce( KeyEvent.VK_SPACE ) ) {
      printPolygon();
    }
  }
  private void printPolygon() {
    System.out.println( "Vector2f[] v = new Vector2f[] { " };
    for( Vector2f v : polygon ) {
      System.out.print( " new Vector2f(" );
      System.out.print( v.x + "f, " );
      System.out.print( v.y + "f)" );
      System.out.println( "," );
    }
    System.out.println( ");" );
  }
  protected void render( Graphics g ) {
    super.render( g );
    g.drawString( "Close Polygon: " + closed, 20, 35 );
    g.drawString( "Left Mouse: Add point", 20, 50 );
    g.drawString( "Right Mouse: Remove point", 20, 65 );
    g.drawString( "Center Mouse: Toggle Close", 20, 80 );
    g.drawString( "C: Clear Polygon", 20, 95 );
    g.drawString( "Space Bar: Print Polygon", 20, 110 );
    drawAxisLines( g );
    drawPolygon( g );
  }
  private void drawAxisLines( Graphics g ) {
    g.setColor( Color. BLUE );
    Vector2f left = new Vector2f( appWorldWidth / 2.0f, 0.0f );
    Vector2f right = new Vector2f( -left.x, 0.0f );
    drawLine( g, left, right );
    Vector2f top = new Vector2f( 0.0f, appWorldHeight / 2.0f );
    Vector2f bottom = new Vector2f( 0.0f, -top.y );
    drawLine( g, top, bottom );
  }
  private void drawPolygon( Graphics g ) {
    g.setColor( Color.BLACK );
    if( polygon.size() == 1 ) {
      drawPoint( g, polygon.get( 0 ) );
    }
    for( int i = 0; i < polygon.size() - 1; ++i ) {
      drawLine( g, polygon.get(i), polygon.get( i+1 ) );
    }
    if( closed && polygon.size() > 1 ) {
      Vector2f P = polygon.get( polygon.size() - 1 );
      Vector2f S = polygon.get( 0 );
      drawLine( g, S, P );
    }
    if( !(polygon.isEmpty() || closed) ) {
      Vector2f P = polygon.get( polygon.size() - 1 );
      Vector2f S = mousePos;
      drawLine( g, S, P );
    }
  }
  private void drawPoint( Graphics g, Vector2f v ) {
    Matrix3x3f view = getViewportTransform();
    Vector2f s = view.mul( v );
    g.drawRect( (int)s.x, (int)s.y, 1, 1 );
  }
  private void drawLine( Graphics g, Vector2f v0, Vector2f v1 ) {
    Matrix3x3f view = getViewportTransform();
    Vector2f S = view.mul( v0 );
    Vector2f P = view.mul( v1 );
    g.drawLine( (int)S.x, (int)S.y, (int)P.x, (int)P.y );
  }
  public static void main( String[] args ) {
    launchApp( new PrototypeEditor() );
  }
}`

时间: 2024-11-10 07:11:51

《Java 2D游戏编程入门》—— 8.3 创建一个原型编辑器的相关文章

《Java 2D游戏编程入门》—— 8.7 编写原型游戏

8.7 编写原型游戏 原型游戏如图8.12所示,位于javagames.prototype包中,它使用了我们目前为止所见过的所有技术.尽管这只是一个原型,并且目前还没有成为一款完整的游戏,但我已经展示了足够的工具来让一些功能奏效.如果要等到最后再制作一款游戏,可能需要等太长的时间. 该原型游戏使用了我们在本章前面所介绍的如下的类. PolygonWrapper PrototypeShip PrototypeAsteroid PrototypeAsteroidFactory PrototypeBu

《Java 2D游戏编程入门》—— 8.4 用原型小行星工厂生产小行星

8.4 用原型小行星工厂生产小行星 位于javagames.prototype包中的PrototypeAsteroidFactory,包含了3个大的.3个中型的和3个小的小行星,它们都是使用编辑器并粘贴到代码中设计的.给定一个位置,这3个方法生成一个随机数来选择所返回的小行星: createLargeAsteroid( Vector2f position ) createMediumAsteroid( Vector2f position ) createSmallAsteroid( Vector

《Java 2D游戏编程入门》—— 导读

前言 多年前,当我第一次将软件开发作为专业工作的时候,有人请我编写一个applet.那时候,我对于Java语言知道得并不多.在整个上学期间,我很广泛地使用C++.我确实用Java编写过一些代码,但认为它太慢并且是C++的没落版. 同时,我购买和阅读了很多可以接触到的游戏编程图书.我通读了一本关于人工智能的书,其中包含很多不错的示例,但它们都是用C++和DirectX编写的.由于忙着学习Java以便在工作中使用,我认为将示例转换为由Java编写可能是学习这门语言的一种好办法. 毕竟,Java游戏编

《Java 2D游戏编程入门》—— 8.2 创建一个原型小行星

8.2 创建一个原型小行星 PrototypeAsteroid类位于javagames.prototype包中,它表示一个穿越太空的陨石.在创建的时候,使用了一个随机的速率和旋转.Java的随机数生成器只能返回0到1之间的浮点数,因此,要创建在任意范围内分布的随机数,需要一些额外的步骤.例如,要返回-3到7之间的随机数,应按照如下步骤进行. 1.用最大值减去最小值,计算随机数之间的差距. 2.生成从0到1的一个随机浮点数. 3.将随机数乘以差距值. 4.通过加上最小值来迁移范围. 这些步骤听起来

《Java 2D游戏编程入门》—— 第8章 游戏原型

第8章 游戏原型 本章基于你在前面各章中已经学到的所有内容,介绍如何创建一个原型太空游戏.尽管它还有很多元素缺失,因而不能称之为一款完整的游戏,但我们已经有了足够的可用工具来创建一个可以工作的原型. 在初次学习编程的时候,我遇到的一个问题是,有众多的示例使用各种编程概念,如循环.变量.集成和多态,但是,并没有太多的示例真正做某件事情.这些示例要么太简单了,只是无用的代码片段,要么是极其复杂.编写糟糕的程序,其中还掺入了所有的计算机科学理论,而不是只用到完成任务所需的那些知识.本章的这款原型游戏并

《Java 2D游戏编程入门》—— 8.1 创建一个多边形包装类

8.1 创建一个多边形包装类 制作一款2D太空飞船游戏时,首先要解决的大问题是,当飞船到达屏幕边缘时,会发生什么事情.一个解决方案是,将飞船保持在屏幕的中央,而移动其周围的环境.没有对加载文件的任何支持,也没有关卡编辑器的话,要做到这点似乎有点难.另一个选择是,当飞船到达屏幕边界的时候,将其弹回.这样做似乎显得很奇怪.第三种选择是,让飞船从一端到另一端折返.让我们采用第三种方法. 还有很多方法可以解决这一问题.一种方法是,让飞船完全离开屏幕,然后让其在另一端返回,如图8.1所示. 尝试这一想法似

《Java 2D游戏编程入门》—— 1.6 修改显示模式

1.6 修改显示模式 要创建全屏的应用程序,需要修改显示模式.DisplayModeTest如图1.4所示,它使用了Swing组件.这个示例也位于javagames.render包中.如果你还没有编写过任何的Swing程序,一些代码可能会看上去很陌生.有很多相关的图书和教程可供参考,并且如果要详细介绍Swing所提供的所有功能,需要比这本书更大的篇幅. 这个示例应用程序列出了所有可用的屏幕分辨率,这允许用户在全屏模式之间来回切换,以使用任何可用的显示模式.这个示例不仅展示了使用Swing组件编程

《Java 2D游戏编程入门》—— 1.3 使用主动渲染

1.3 使用主动渲染 前面的示例使用了一种叫做被动渲染(passive rendering)的技术.该应用程序在paint()方法中重新绘制自身,但是,由Swing库来决定什么时候调用该方法.事件分派线程处理Swing组件的渲染,而这并不由你来控制.尽管这对于常规应用程序来说很好,但对于游戏不推荐这么做. 要处理渲染,可以使用BufferStrategy类,但这需要对应用程序的结构做一些修改.这将允许应用程序把渲染代码放在一个单独的线程中,并且由整个进程来控制. 把游戏代码放在paint()方法

《Java 2D游戏编程入门》—— 1.4 创建定制的渲染线程

1.4 创建定制的渲染线程 除了使用前面的代码来执行定制的渲染外,还需要一个定制的渲染线程.为了只是关注线程问题,位于javagames.render包中的RenderThreadExample实际上不会在屏幕上绘制任何内容,它只是在渲染代码应该出现的地方打印出"Game Loop".下面的示例将RenderThreadExample和前面的代码组合起来,创建了一个主动渲染的应用程序. 在RenderThreadExample中,首先需要注意的是,它实现了一个可运行的接口.这个可运行的