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

本节书摘来异步社区《Java 2D游戏编程入门》一书中的第8章,第8.4节,作者:【美】Timothy Wright(莱特),更多章节内容可以访问云栖社区“异步社区”公众号查看。

8.4 用原型小行星工厂生产小行星

位于javagames.prototype包中的PrototypeAsteroidFactory,包含了3个大的、3个中型的和3个小的小行星,它们都是使用编辑器并粘贴到代码中设计的。给定一个位置,这3个方法生成一个随机数来选择所返回的小行星:

createLargeAsteroid( Vector2f position )

createMediumAsteroid( Vector2f position )

createSmallAsteroid( Vector2f position )```

第一个方法mirror(),用来沿着x轴和y轴翻转模型,以便模型有多个独特的版本。

// PrototypeAsteroidFactory.java

private Vector2f[] mirror( Vector2f[] polygon ) {

Vector2f[] mirror = new Vector2f[ polygon.length ];

float x = rand.nextBoolean() ? 1.0f : -1.0f;

float y = rand.nextBoolean() ? 1.0f : -1.0f;

Matrix3x3f mat = Matrix3x3f.scale( x, y );

for( int i = 0; i < polygon.length; ++i ) {

mirror[i] = mat.mul( polygon[i] );

}

return mirror;

}`

就像在执行视口矩阵乘法的时候使用矩阵来翻转y轴一样,通过乘以-1来翻转x或y轴的值,以缩放模型。

package javagames.prototype;

import java.util.Random;

import javagames.prototype.PrototypeAsteroid.Size;

import javagames.util.Matrix3x3f;

import javagames.util.Vector2f;

public class PrototypeAsteroidFactory {

private static final Vector2f[][] LARGE = {

{ // Large 0

new Vector2f(-0.029733956f, 0.283255100f),

new Vector2f(-0.183098610f, 0.111111104f),

new Vector2f(-0.230046930f,-0.057902932f),

new Vector2f(-0.092331770f,-0.139280080f),

new Vector2f( 0.117370844f,-0.142410040f),

new Vector2f( 0.161189320f,-0.048513293f),

new Vector2f( 0.151799680f, 0.067292630f),

new Vector2f( 0.195618150f, 0.129890440f),

new Vector2f( 0.017214417f, 0.158059480f),

}, { // Large 1

new Vector2f(-0.001763641f, 0.325800420f),

new Vector2f(-0.082892360f, 0.220339000f),

new Vector2f(-0.227513200f, 0.065913380f),

new Vector2f(-0.206349200f,-0.141242860f),

new Vector2f(-0.061728360f,-0.080979230f),

new Vector2f( 0.061728418f,-0.167608260f),

new Vector2f( 0.192239940f,-0.092278720f),

new Vector2f( 0.167548480f, 0.126177010f),

new Vector2f( 0.107583820f, 0.269303200f),

}, { // Large 2

new Vector2f( 0.176838760f,-0.107981205f),

new Vector2f(-0.070422530f,-0.076682330f),

new Vector2f(-0.220657290f,-0.123630640f),

new Vector2f(-0.273865400f, 0.048513293f),

new Vector2f(-0.186228510f, 0.086071970f),

new Vector2f(-0.214397490f, 0.223787190f),

new Vector2f(-0.026604056f, 0.148669780f),

new Vector2f( 0.104851365f, 0.220657290f),

new Vector2f( 0.211267590f, 0.032863855f),

},

};

private static final Vector2f[][] MEDIUM = {

{ // Medium 0

new Vector2f(-0.045383394f, 0.186228510f),

new Vector2f(-0.167449180f, 0.123630700f),

new Vector2f(-0.067292630f, 0.039123654f),

new Vector2f(-0.107981205f,-0.073552370f),

new Vector2f( 0.057902932f,-0.073552370f),

new Vector2f( 0.133020280f, 0.098591566f),

}, { // Medium 1

new Vector2f(-0.023474216f, 0.189358350f),

new Vector2f(-0.107981205f, 0.107981205f),

new Vector2f(-0.129890440f,-0.098591566f),

new Vector2f( 0.020344257f,-0.120500800f),

new Vector2f( 0.139280080f,-0.001564979f),

new Vector2f( 0.076682330f, 0.092331770f),

new Vector2f(-0.007824719f, 0.095461670f),

}, { // Medium 2

new Vector2f(-0.064162790f, 0.158059480f),

new Vector2f(-0.173708920f, 0.126760600f),

new Vector2f(-0.142410040f, 0.023474216f),

new Vector2f(-0.039123654f, 0.029733956f),

new Vector2f( 0.010954618f,-0.035993695f),

new Vector2f( 0.117370844f, 0.023474216f),

new Vector2f( 0.117370844f, 0.120500800f),

new Vector2f(-0.001564979f, 0.092331770f),

},

};

private static final Vector2f[][] SMALL = {

{ // Small 0

new Vector2f(-0.048513293f, 0.057902990f),

new Vector2f(-0.073552430f,-0.042253494f),

new Vector2f( 0.004694819f,-0.035993695f),

new Vector2f( 0.042253494f, 0.026604056f),

new Vector2f(-0.001564979f, 0.082942130f),

}, { // Small 1

new Vector2f( 0.067292690f, 0.007824719f),

new Vector2f(-0.029733956f,-0.076682330f),

new Vector2f(-0.067292630f,-0.042253494f),

new Vector2f(-0.061032890f, 0.082942130f),

new Vector2f( 0.032863855f, 0.111111104f),

}, { // Small 2

new Vector2f(-0.007824719f, 0.089201870f),

new Vector2f(-0.114241004f, 0.001564979f),

new Vector2f(-0.004694819f,-0.067292690f),

new Vector2f( 0.039123654f,-0.039123654f),

new Vector2f(-0.014084518f, 0.020344317f),

},

};

private PolygonWrapper wrapper;

private Random rand;

public PrototypeAsteroidFactory( PolygonWrapper wrapper ) {

this.wrapper = wrapper;

this.rand = new Random();

}

public PrototypeAsteroid createLargeAsteroid( Vector2f position ) {

PrototypeAsteroid asteroid = new PrototypeAsteroid( wrapper );

asteroid.setPosition( position );

asteroid.setPolygon( getRandomAsteroid( LARGE ) );

asteroid.setSize( Size.Large );

return asteroid;

}

public PrototypeAsteroid createMediumAsteroid( Vector2f position ) {

PrototypeAsteroid asteroid = new PrototypeAsteroid( wrapper );

asteroid.setPosition( position );

asteroid.setPolygon( getRandomAsteroid( MEDIUM ) );

asteroid.setSize( Size.Medium );

return asteroid;

}

public PrototypeAsteroid createSmallAsteroid( Vector2f position ) {

PrototypeAsteroid asteroid = new PrototypeAsteroid( wrapper );

asteroid.setPosition( position );

asteroid.setPolygon( getRandomAsteroid( SMALL ) );

asteroid.setSize( Size.Small );

return asteroid;

}

private Vector2f[] getRandomAsteroid( Vector2f[][] asteroids ) {

return mirror( asteroids[ rand.nextInt( asteroids.length ) ] );

}

private Vector2f[] mirror( Vector2f[] polygon ) {

Vector2f[] mirror = new Vector2f[ polygon.length ];

float x = rand.nextBoolean() ? 1.0f : -1.0f;

float y = rand.nextBoolean() ? 1.0f : -1.0f;

Matrix3x3f mat = Matrix3x3f.scale( x, y );

for( int i = 0; i < polygon.length; ++i ) {

mirror[i] = mat.mul( polygon[i] );

}

return mirror;

}

}```

RandomAsteroidExample位于javagames.prototype包中,如图8.10所示,它使用PolygonWrapper、PrototypeAsteroid和PrototypeAsteroid Factory,来生成在屏幕上随机飞来飞去的陨石。

5089ec5e7f268f2e2dac10f7ef0f3c0a.png

getRandomAsteroid()方法创建了一个随机的位置,然后选择一个随机的大小:small、medium或large。记住,工厂的每一个方法都从3种不同的多边形模型中针对每个大小选取一个模型,并且为每个模型生成4个镜像的版本。每个多边形有4个镜像,每个大小有3个形状,共有3种不同的大小,因此,共有36种不同的模型。

还应该注意,由于PrototypeAsteroid使用了新的Utility.fillPolygon()方法,Graphics对象强制转型为一个Graphics2D对象。

// RandomAsteroidExample.java

protected void render( Graphics g ) {

super.render( g );

g.drawString( "Press ESC to respawn", 20, 35 );

Matrix3x3f view = getViewportTransform();

for( PrototypeAsteroid asteroid : asteroids ) {

asteroid.draw( (Graphics2D)g, view );

}

}

RandomAsteroidExample代码如下所示:

package javagames.prototype;

import java.awt.*;

import java.awt.event.KeyEvent;

import java.util.*;

import javagames.prototype.PrototypeAsteroid.Size;

import javagames.util.*;

public class RandomAsteroidExample extends SimpleFramework {

private PrototypeAsteroidFactory factory;

private ArrayList asteroids;

private Random rand;

public RandomAsteroidExample() {

appBorderScale = 0.9f;

appWidth = 640;

appHeight = 640;

appMaintainRatio = true;

appSleep = 1L;

appTitle = "Random Asteroids";

appBackground = Color.WHITE;

appFPSColor = Color.BLACK;

}

@Override

protected void initialize() {

super.initialize();

rand = new Random();

asteroids = new ArrayList();

PolygonWrapper wrapper =

new PolygonWrapper( appWorldWidth, appWorldHeight );

factory = new PrototypeAsteroidFactory( wrapper );

createAsteroids();

}

private void createAsteroids() {

asteroids.clear();

for( int i = 0; i < 42; ++i ) {

asteroids.add( getRandomAsteroid() );

}

}

private PrototypeAsteroid getRandomAsteroid() {

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

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

Vector2f position = new Vector2f( x, y );

Size[] sizes = Size.values();

Size randomSize = sizes[ rand.nextInt( sizes.length ) ];

switch( randomSize ) {

case Small: return factory.createSmallAsteroid( position );

case Medium: return factory.createMediumAsteroid( position );

case Large:

default: return factory.createLargeAsteroid( position );

}

}

@Override

protected void processInput( float delta ) {

super.processInput( delta );

if( keyboard.keyDownOnce( KeyEvent.VK_ESCAPE ) ) {

createAsteroids();

}

}

@Override

protected void updateObjects( float delta ) {

super.updateObjects( delta );

for( PrototypeAsteroid asteroid : asteroids ) {

asteroid.update( delta );

}

}

@Override

protected void render( Graphics g ) {

super.render( g );

g.drawString( "Press ESC to respawn", 20, 35 );

Matrix3x3f view = getViewportTransform();

for( PrototypeAsteroid asteroid : asteroids ) {

asteroid.draw( (Graphics2D)g, view );

}

}

public static void main( String[] args ) {

launchApp( new RandomAsteroidExample() );

}

}`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值