您好,欢迎访问一九零五行业门户网

jMonkeyEngine译文 FlagRush8(2)增加随机的Flag

8.6 、为旗杆增加布 我想要让 flag 看起来像 很好,像 flag 。为了这么做,我们需要模拟一个布的 flag , attach 到旗杆。有什么更好的方式完成这件事,还是使用 jme 的 clothpatch 功能。这将允许我们去创建一个弹簧( spring )点的 matrix ,它们由不同方
8.6、为旗杆增加布    我想要让flag看起来像…很好,像flag。为了这么做,我们需要模拟一个布的flag,attach到旗杆。有什么更好的方式完成这件事,还是使用jme的clothpatch功能。这将允许我们去创建一个弹簧(spring)点的matrix,它们由不同方向的外力(force)调整(引力和风力)。我已经为这个向导创建了我自己的风力,而我们将在下面讨论。
首先,增加对象到flag类。
//用于制作flag的cloth
    private clothpatch cloth;
    //风的参数
    privatefloatwindstrength = 15f;
    private vector3f winddirection = new vector3f(0.8f, 0, 0.2f);
    private springpointforce gravity,wind;
在flag的构造参数中,我们将创建一个clothpatch。这个cloth将是25*25的matrix,给它一个相当详细的cloth。cloth上的点越多,它运行得越慢,所以你应该在flag的视觉外观和它对游戏的影响之间选个平衡点。25*25给我一个可接受的性能和外观的比例。在创建cloth之后,我们将增加我们的force。我们增加的第一个force是我们为这个向导创建的自定义的force,叫做randomflagwindforce。我们也将增加一个默认的重力它是由clothutils创建的,这将在风减小的时候把flag拉下来。
//创建一个cloth patch 将处理我们flag
       cloth = new clothpatch(cloth, 25, 25, 1f, 10);
       //将我们自定义的风力增加到cloth
        wind = new randomflagwindforce(windstrength, winddirection);
        cloth.addforce(wind);
        //增加一个简单的重力
        gravity = clothutils.createbasicgravity();
        cloth.addforce(gravity);
由于cloth是标准的jme spatial,我们和平常一样应用renderstate。我们将为flag增加texture,使用jme monkey的logo。这个是一个让monkey的头在你脑海留下烙印的企图。
//创建一个将flag显示的texture,一起推进jme发展!
        texturestate ts = displaysystem.getdisplaysystem()
        .getrenderer().createtexturestate();
        ts.settexture(
             texturemanager.loadtexture(
                    flag.class.getclassloader()
                       .getresource(res/logo.png),
                    texture.minificationfilter.trilinear,
                    texture.magnificationfilter.bilinear
             )
        );
        cloth.setrenderstate(ts);
当我开始增加一个flag到场景时,我对light非常不满意,因为flag大部分时间都是阴影。因此,我决定增加一个light,它只影响flag。这个light应该跟着flag移动,并且根据flag定位自己。因此,使用一个lightnode是最好的解决方案。lightnode允许你对待一个light就像scene中的其它元素一样,通过移动light的父亲node移动它。
//我们将使用一个lightnode去给flag增加light,使用node
        //是因为它允许light随着flag移动
        //首先创建light
        pointlight dr = new pointlight();
        dr.setenabled(true);
        dr.setdiffuse(new colorrgba(1.0f, 1.0f, 1.0f, 1.0f));
        dr.setambient(new colorrgba(0.5f, 0.5f, 0.5f, 1.0f));
        dr.setlocation(new vector3f(0.5f, -0.5f, 0));
        //接下来是state
        lightstate lightstate = displaysystem.getdisplaysystem()
        .getrenderer().createlightstate();
        lightstate.setenabled(true);
        lightstate.settwosidedlighting(true);
        lightstate.attach(dr);
        setrenderstate(lightstate);
        //最后是结点
        lightnode lightnode = new lightnode(light);
        lightnode.setlight(dr);
        lightnode.setlocaltranslation(new vector3f(15,0,0));
        attachchild(lightnode);
        cloth.setrenderstate(lightstate);
flag有一点和前面不同,那就是我们想看到它所有面的三角形。前面,我们设置了scene的cullstate去剔除所有背后的三角形。因此,我们将增加另一个cullstate给cloth,让它不要剔除任何三角形。它将看到所有的三角形。
//我们想看flag所有的面,所以我们将关闭cull
        cullstate cs = displaysystem.getdisplaysystem()
            .getrenderer().createcullstate();
        cs.setcullface(cullstate.face.none);
        cloth.setrenderstate(cs);
        this.attachchild(cloth);
下一步,我们需要为cloth创建一些点去固定它。如果我们不这么做,整个cloth将在force应用于它身上时被“吹走”。我们需要在旗杆上attach一些点去保住cloth。我们通过设置点的质量为无穷大来这么做。因此,没有任何force能移走它。为了模拟这个方法,一个flag被attach到一个旗杆,flag上边缘的一些和旗杆接触的点将被attach,下面的也是。这些点被设置在一个基础的二维matrix中,所以我们将attach点(0,1,2,3,4)到旗杆,点(500,525,550,575,600)也一样。我们也调整这些点在y的位置让它们偏移,从而让cloth形成一点褶皱。
//我们需要attach一些点到旗杆,这些点不应该被移动。
        //因此,我们将attach顶部和底部的5个点去让它们足够高而
        //且没有任何forece能移动它。我也稍微移动这些点的位置去
        //形成褶皱让它更真实。
        for(int i=0; i
            cloth.getsystem().getnode(i*25).position.y *= .8f;
             cloth.getsystem().getnode(i*25)
                 .setmass(float.positive_infinity);
        }
        for(int i=24; i>19; i--){
             cloth.getsystem().getnode(i*25).position.y *= .8f;
            cloth.getsystem().getnode(i*25)
                 .setmass(float.positive_infinity);
        }
最后,我创建自定义风力。为了模仿旗杆上flag的效果,我们也随机化风向。风向将基于它之前的位置
/**
         * 在每次update cloth时调用。将轻微调整风向和强度、
         */
       publicvoid apply(float dt, springpoint node) {
           winddirection.x += dt * (fastmath.nextrandomfloat() - .5f);
           winddirection.z += dt * (fastmath.nextrandomfloat() - .5f);
           winddirection.normalize();
           float tstr = fastmath.nextrandomfloat() * strength;
               node.acceleration.addlocal(
                  winddirection.x * tstr,
                  winddirection.y * tstr,
                  winddirection.z * tstr
               );
       }
通过那样,我们现在有一个看起来真实的flag,而且我们以自己的方式去为我们游戏中添加元素。下一课,我们只需能获取flag。
8.7、源码 
import java.io.ioexception;
import java.net.url;
import java.util.hashmap;
import javax.swing.imageicon;
import com.jme.app.basegame;
import com.jme.bounding.boundingbox;
import com.jme.image.texture;
import com.jme.input.chasecamera;
import com.jme.input.inputhandler;
import com.jme.input.keybindingmanager;
import com.jme.input.keyinput;
import com.jme.input.thirdperson.thirdpersonmouselook;
import com.jme.light.directionallight;
import com.jme.math.fastmath;
import com.jme.math.vector3f;
import com.jme.renderer.camera;
import com.jme.renderer.colorrgba;
import com.jme.renderer.renderer;
import com.jme.scene.node;
import com.jme.scene.skybox;
import com.jme.scene.shape.box;
import com.jme.scene.state.cullstate;
import com.jme.scene.state.lightstate;
import com.jme.scene.state.texturestate;
import com.jme.scene.state.zbufferstate;
import com.jme.system.displaysystem;
import com.jme.system.jmeexception;
import com.jme.util.texturemanager;
import com.jme.util.timer;
import com.jme.util.export.binary.binaryimporter;
import com.jmex.model.converters.maxtojme;
import com.jmex.terrain.terrainblock;
import com.jmex.terrain.util.midpointheightmap;
import com.jmex.terrain.util.proceduraltexturegenerator;
publicclass lesson8 extends basegame{
privateintwidth,height;
    privateintfreq,depth;
    privatebooleanfullscreen;
//我们的camera对象,用于观看scene
    private camera cam;
protected timer timer;
    private node scene;
    private texturestate ts;
private terrainblock tb;
private forcefieldfence fence;
    private skybox skybox;
private vehicle player;
    private chasecamera chaser;
private inputhandler input;
//保存terrain的任何一个给出点的法向
    private vector3f normal = new vector3f();
    privatefloatagl;
    private flag flag;
publicstaticvoid main(string[] args) {
       lesson8 app = new lesson8();
       java.net.url url = app.getclass().getclassloader().getresource(res/logo.png);
       app.setconfigshowmode(configshowmode.alwaysshow,url);
       app.start();
    }
/*
     * 清除texture
     */
    protectedvoid cleanup() {
       ts.deleteall();
    }
protectedvoid initgame() {
       display.settitle(flag rush);
       scene = new node(scene graph node);
zbufferstate buf = display.getrenderer().createzbufferstate();
       buf.setenabled(true);
       buf.setfunction(zbufferstate.testfunction.lessthanorequalto);
       scene.setrenderstate(buf);
buildterrain();
       buildflag();
       buildlighting();
       buildenvironment();
       createskybox();
       buildplayer();
       buildchasecamera();
       buildinput();
cullstate cs = display.getrenderer().createcullstate();
       cs.setcullface(cullstate.face.back);
       scene.setrenderstate(cs);
//更新scene用于渲染
       scene.updategeometricstate(0.0f, true);
       scene.updaterenderstate();
    }
privatevoid buildflag() {
       flag = new flag(tb);
       scene.attachchild(flag);
       flag.placeflag();
    }
privatevoid buildinput() {
       input = new flagrushinputhandler(
              player,
              settings.getrenderer()
       );
    }
privatevoid buildchasecamera() {
       hashmap props = new hashmap();
       props.put(thirdpersonmouselook.prop_maxrollout, 6);
       props.put(thirdpersonmouselook.prop_minrollout, 3);
       props.put(
              thirdpersonmouselook.prop_maxascent,
              +45*fastmath.deg_to_rad
       );
       props.put(
              chasecamera.prop_initialspherecoords,
              new vector3f(5,0,30*fastmath.deg_to_rad)
       );
       chaser = new chasecamera(cam, player, props);
       chaser.setmaxdistance(8);
       chaser.setmindistance(2);
    }
privatevoid buildplayer() {
       node model = null;
       url maxfile = lesson8.class.getclassloader()
        .getresource(res/bike.jme);
       try {
           model = (node)binaryimporter.getinstance().load(
                  maxfile.openstream()
           );
           model.setmodelbound(new boundingbox());
           model.updatemodelbound();
           model.setlocalscale(0.0025f);
       } catch (ioexception e1) {
           e1.printstacktrace();
       }
//设置vehicle的属性(这些数字能被认为是单元/秒 unit/s)
        player = new vehicle(player node,model);
        player.setacceleration(15);
        player.setbraking(25);
        player.setturnspeed(2.5f);
        player.setweight(25);
        player.setmaxspeed(25);
        player.setminspeed(15);
player.setlocaltranslation(new vector3f(100,0, 100));
        player.updateworldbound();
        player.setrenderqueuemode(renderer.queue_opaque);
scene.attachchild(player);
        scene.updategeometricstate(0, true);
agl = ((boundingbox)(player.getworldbound())).yextent;
    }
privatevoid createskybox() {
       skybox = new skybox(skybox,10,10,10);
       texture north = texturemanager.loadtexture(
              lesson8.class.getclassloader()
                  .getresource(res/texture/north.jpg),
              texture.minificationfilter.bilinearnearestmipmap,
              texture.magnificationfilter.bilinear
       );
       texture south = texturemanager.loadtexture(
              lesson8.class.getclassloader()
                  .getresource(res/texture/south.jpg),
              texture.minificationfilter.bilinearnearestmipmap,
               texture.magnificationfilter.bilinear
       );
       texture east = texturemanager.loadtexture(
              lesson8.class.getclassloader()
                  .getresource(res/texture/east.jpg),
              texture.minificationfilter.bilinearnearestmipmap,
              texture.magnificationfilter.bilinear
       );
       texture west = texturemanager.loadtexture(
              lesson8.class.getclassloader()
                  .getresource(res/texture/west.jpg),
              texture.minificationfilter.bilinearnearestmipmap,
              texture.magnificationfilter.bilinear
       );
       texture up = texturemanager.loadtexture(
              lesson8.class.getclassloader()
                  .getresource(res/texture/top.jpg),
              texture.minificationfilter.bilinearnearestmipmap,
              texture.magnificationfilter.bilinear
       );
       texture down = texturemanager.loadtexture(
              lesson8.class.getclassloader()
                  .getresource(res/texture/bottom.jpg),
              texture.minificationfilter.bilinearnearestmipmap,
              texture.magnificationfilter.bilinear
       );
skybox.settexture(skybox.face.north, north);
       skybox.settexture(skybox.face.west, west);
       skybox.settexture(skybox.face.south, south);
       skybox.settexture(skybox.face.east, east);
       skybox.settexture(skybox.face.up, up);
       skybox.settexture(skybox.face.down, down);
       skybox.preloadtextures();
scene.attachchild(skybox);
    }
privatevoid buildenvironment() {
       fence = new forcefieldfence(forcefieldfence);
//我们将手工做一些调整去让它更好适应terrain
       //首先我们将实体“模型”放大
       fence.setlocalscale(5);
       //现在,让我们移动fence到terrain的高度并有一点陷入它里面
       fence.setlocaltranslation(
           new vector3f(25,tb.getheight(25,25)+10,25)   
       );
scene.attachchild(fence);
    }
privatevoid buildlighting() {
       /* 设置一个基础、默认灯光 */
       directionallight light = new directionallight();
       light.setdiffuse(new colorrgba(1.0f, 1.0f, 1.0f, 1.0f));
       light.setambient(new colorrgba(0.5f, 0.5f, 0.5f, 1.0f));
       light.setdirection(new vector3f(1, -1, 0));
       light.setenabled(true);
lightstate lightstate = display.getrenderer().createlightstate();
       lightstate.setenabled(true);
       lightstate.attach(light);
scene.setrenderstate(lightstate);
    }
/**
     * 创建heightmap和terrainblock
     */
    privatevoid buildterrain() {
       //生成随机地形数据
       midpointheightmap heightmap = new midpointheightmap(64,1f);
//缩放数据
       vector3f terrainscale = new vector3f(4, .0575f, 4);
//创建一个terrain block
       tb = new terrainblock(
              terrain,
              heightmap.getsize(),
              terrainscale,
              heightmap.getheightmap(),
              new vector3f(0, 0, 0)
       );
       tb.setmodelbound(new boundingbox());
       tb.updatemodelbound();
//通过三个纹理生成地形纹理
       proceduraltexturegenerator pt =
           new proceduraltexturegenerator(heightmap);
pt.addtexture(
              new imageicon(
                     getclass().getclassloader()
                         .getresource(res/grassb.png)
              ),
              -128, 0, 128
       );
       pt.addtexture(
              new imageicon(
                     getclass().getclassloader()
                         .getresource(res/dirt.jpg)
              ),
              0, 128, 256
       );
       pt.addtexture(
              new imageicon(
                     getclass().getclassloader()
                         .getresource(res/highest.jpg)
              ),
              128, 256, 384
       );
       pt.createtexture(32);
//将纹理赋予地形
       ts = display.getrenderer().createtexturestate();
       texture t1 = texturemanager.loadtexture(
              pt.getimageicon().getimage(),
              texture.minificationfilter.trilinear,
              texture.magnificationfilter.bilinear,
              true
       );
       ts.settexture(t1, 0);
//加载细节纹理并为2个terrain的texture设置组合模型
        texture t2 = texturemanager.loadtexture(
                lesson8.class.getclassloader()
                  .getresource(res/detail.jpg),
                texture.minificationfilter.trilinear,
                texture.magnificationfilter.bilinear
        );
        ts.settexture(t2, 1);
t2.setwrap(texture.wrapmode.repeat);
t1.setapply(texture.applymode.combine);
        t1.setcombinefuncrgb(texture.combinerfunctionrgb.modulate);
        t1.setcombinesrc0rgb(texture.combinersource.currenttexture);
        t1.setcombineop0rgb(texture.combineroperandrgb.sourcecolor);
        t1.setcombinesrc1rgb(texture.combinersource.primarycolor);
        t1.setcombineop1rgb(texture.combineroperandrgb.sourcecolor);
t2.setapply(texture.applymode.combine);
        t2.setcombinefuncrgb(texture.combinerfunctionrgb.addsigned);
        t2.setcombinesrc0rgb(texture.combinersource.currenttexture);
        t2.setcombineop0rgb(texture.combineroperandrgb.sourcecolor);
        t2.setcombinesrc1rgb(texture.combinersource.previous);
        t2.setcombineop1rgb(texture.combineroperandrgb.sourcecolor);
tb.setrenderstate(ts);
       tb.setdetailtexture(1, 16);
tb.setrenderqueuemode(renderer.queue_opaque);
       scene.attachchild(tb
其它类似信息

推荐信息