本文我们通过介绍SimpleGame、Box和rootNode,来学习如何创建jME程序。好,我们开门见山。这里有一段创建好的最简单的程序:
import com.jme.app.SimpleGame; import com.jme.scene.shape.Box; import com.jme.math.Vector3f; public class HelloWorld extends SimpleGame{ public static void main(String[] args) { HelloWorld game = new HelloWorld(); // 创建对象 // 设置属性对话框的显示方式 game.setDialogBehaviour(ConfigShowMode.AlwaysShow); game.start(); // 启动 } protected void simpleInitGame() { // 创建一个Box Box b = new Box("Mybox", new Vector3f(0,0,0), new Vector3f(1,1,1)); rootNode.attachChild(b); // 将它放入场景中 } }
确实很短,对不对?实质上我们的程序从这句话开始:
public class HelloWorld extends SimpleGame{
SimpleGame为我们做了很多隐藏在背后的初始化工作。如果你愿意,可以看看它的源代码。但是现在我们只需要知道,它为我们创造了所有用来渲染的最基本的条件。在自己的程序中你是要扩展它的。
game.setDialogBehaviour(ConfigShowMode.AlwaysShow);
在你第一次运行的时候,会有一个带猴子图片的对话框出现——提示你选择运行时分辨率。
嗯,就是这句代码使它出现。就像代码所表示的,每次运行时属性对话框都出现。如果改成下面的代码,那么那个对话框就永远不会出现。
game.setDialogBehaviour(ConfigShowMode.NeverShow);
一点都不难吧。
app.start(); // 启动
start()这个函数从本质上来说是一个无限循环。最开始它初始化jME系统,然后在while循环的每次迭代中做这么两件事:首先,它告诉游戏中所有的物体,需要要移动了(就是告诉所有物体,你们可以挪挪位置了);然后,重新渲染所有物体。这样,让游戏不断运行。
protected void simpleInitGame() { // 创建一个Box Boxb = new Box("Mybox", new Vector3f(0,0,0), new Vector3f(1,1,1)); rootNode.attachChild(b); // 将它放入场景中 }
在SimpleGame的simpleInitGame()是个虚函数,所以每次继承SimpleGame你都必须实现它。让我们来看看代码,很明显发生了两件事。第一,我创建了一个Box对象(就是你在屏幕上看到的长方体);然后,我把这个长方体附加(attach)在了场景的根节点下。对象的rootNode是SimpleGame为你创建好的。所有东西都放在它或者它的子节点下。
注意这里我给了b三个参数:1个字符串和2个Vector3f对象。场景中所有的Node、Box、Circle、Person或者所有的东西都有名字。一般来说你会给不同的对象不同的名字。在这里叫"MyBox",但是你可以随便给它名字。接下来的两个参数规定了Box的顶点。一个顶点在原点,另一个在点(1,1,1)。恩,一个单位立方体。
好了,我创建了这个Box,但我还必须告诉它我想要将它渲染出来。这也就是我为什么把它附加在rootNode对象下。场景图(scene graph)看起来大概是这样:
rootNode | MyBox
最上面是rootNode对象,下面是"MyBox"。所以,当SimpleGame试着把rootNode画出来的时候,它也会试着画出"MyBox"。
这就是本文的内容,接下来我们将接触一些更复杂的东西。