Hello, have a nice day!
I am new at JME yet and so sorry for my bad English. I used Unity Engine before -not professionaly- actually, i am not very good on Java but, i really liked JME and i wanna be an advanced user.
I wanted a basic floor, 3 box npc and a simply crosshair. After build that scene, i wanted modular abilities which is attachable on this npc boxes, What are these abilities? -Flammeable -Corruptible -Rotatable. They should have been remotable on one common BoxControler. I hope, i made myself clear.
Here is simple video of my work;
So, here is the my component system based on only custom controls.
i have a basic GameAppState and this is only appState on this work so Main class runs this appState directly.
package mycomponentsystem;
// for make shorter i cut the imports and empty @override methods if you want see i can add that stuffs.
public class GameAppState extends BaseAppState{
protected SimpleApplication app;
protected Node rootNode;
protected Node guiNode;
protected Node shootable;
protected AssetManager assetManager;
protected AppStateManager stateManager;
protected InputManager inputManager;
protected ViewPort viewPort;
protected Node shootables;
protected Camera cam;
protected BitmapFont guiFont;
protected AppSettings settings;
@Override
protected void initialize(Application app) {
this.app = (SimpleApplication)app;
this.rootNode = this.app.getRootNode();
this.guiNode = this.app.getGuiNode();
this.assetManager = this.app.getAssetManager();
this.stateManager = this.app.getStateManager();
this.inputManager = this.app.getInputManager();
this.viewPort = this.app.getViewPort();
this.cam = this.app.getCamera();
this.settings = this.app.getContext().getSettings();
initScene();
initKeys();
}
private void initScene(){
app.setDisplayStatView(false);
Geometry floor = makeBox(10f,.5f,10f,"Floor");
Geometry box1g = makeBox(.3f,.3f,.3f,"Box1");
Node box1 = new Node("Box1");
box1g.addControl(new BoxControl(this,box1));
box1.setLocalTranslation(-2f,1.5f,-4f);
Geometry box2g = makeBox(.3f,.3f,.3f,"Box2");
Node box2 = new Node("Box2");
box2g.addControl(new BoxControl(this,box2));
box2.setLocalTranslation(0f,1.5f,-4f);
Node box3 = new Node("Box3");
Geometry box3g = makeBox(.3f,.3f,.3f,"Box3");
box3g.addControl(new BoxControl(this,box3));
box3.setLocalTranslation(2f,1.5f,-4f);
BitmapText crosshair = makeCrosshair();
cam.setLocation(new Vector3f(0f,2f,0f));
rootNode.attachChild(floor);
box1.attachChild(box1g);
box2.attachChild(box2g);
box3.attachChild(box3g);
shootable = new Node("Shootable");
shootable.attachChild(box1);
shootable.attachChild(box2);
shootable.attachChild(box3);
rootNode.attachChild(shootable);
guiNode.attachChild(crosshair);
}
private void initKeys(){
inputManager.addMapping("Shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(actionListener, "Shoot");
}
public ActionListener actionListener = new ActionListener(){
@Override
public void onAction(String name, boolean isPressed, float tpf) {
if(name.equals("Shoot")&&!isPressed){
CollisionResults results = new CollisionResults();
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
shootable.collideWith(ray, results);
if(results.size()>0){
CollisionResult result = results.getClosestCollision();
result.getGeometry().getControl(BoxControl.class).onShoot();
}
}
}
};
private Geometry makeBox(float x, float y, float z, String name){
Box box = new Box(x,y,z);
Geometry boxGeo = new Geometry(name,box);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.LightGray);
boxGeo.setMaterial(mat);
CollisionShape shape = CollisionShapeFactory.createBoxShape(boxGeo);
return boxGeo;
}
private BitmapText makeCrosshair(){
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText bt = new BitmapText(guiFont,false);
bt.setText(">o<");
bt.setSize(25f);
bt.setLocalTranslation(settings.getWidth() / 2 - bt.getLineWidth()/2, settings.getHeight() / 2 + bt.getLineHeight()/2, 0);
return bt;
}
}
and here my common BoxController for all npc in my scene;
package mycomponentsystem;
//again sorry for imports :)
public class BoxControl extends AbstractControl{
protected GameAppState appState;
protected Node node;
public BoxControl(AppState appState, Node node){
this.appState = (GameAppState)appState;
this.node = node;
}
@Override
public void setSpatial(Spatial spatial) {
super.setSpatial(spatial);
if (spatial != null){ // initialize
switch (spatial.getName()) {
case "Box1":
spatial.addControl(new FlammableComponent(appState,node));
break;
case "Box2":
spatial.addControl(new CorruptibleComponent(appState,node));
break;
case "Box3":
spatial.addControl(new FlammableComponent(appState,node));
spatial.addControl(new RotatableComponent(appState,node));
break;
default:
break;
}
}else{ // cleanup
}
}
public void onShoot(){
Geometry geo = (Geometry)spatial;
geo.getMaterial().setColor("Color", ColorRGBA.randomColor());
switch (spatial.getName()) {
case "Box1":
spatial.getControl(FlammableComponent.class).onShoot();
break;
case "Box2":
spatial.getControl(CorruptibleComponent.class).onShoot();
break;
case "Box3":
spatial.getControl(FlammableComponent.class).onShoot();
spatial.getControl(RotatableComponent.class).onShoot();
break;
default:
break;
}
}
}
and now i will show only one component for make this topic shorter here is flammeable;
public class FlammableComponent extends AbstractControl{
protected GameAppState appState;
protected Node node;
protected Boolean isInfected = false;
public FlammableComponent(AppState appState, Node node){
this.appState = (GameAppState)appState;
this.node = node;
}
protected void onShoot(){
if(!isInfected)
node.attachChild(makeParticle());
}
protected ParticleEmitter makeParticle(){
ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 5);
Material mat = new Material(appState.getApplication().getAssetManager(), "Common/MatDefs/Misc/Particle.j3md");
mat.setTexture("Texture", appState.getApplication().getAssetManager().loadTexture("Effects/Explosion/flame.png"));
fire.setMaterial(mat);
fire.setImagesX(2);
fire.setImagesY(2);
fire.setEndColor( new ColorRGBA(1f, 0f, 0f, 1f));
fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f));
fire.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 1, 0));
fire.setStartSize(1f);
fire.setEndSize(0.1f);
fire.setGravity(0, 0, 0);
fire.setLowLife(1f);
fire.setHighLife(2f);
fire.getParticleInfluencer().setVelocityVariation(0.3f);
isInfected = true;
return fire;
}
@Override
protected void controlUpdate(float tpf) {
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
}
}
The FlammeableComponent and the RotatableComponent effects together the third npc (as you can see -Box3 Node- rotates and burns when shooted) this system fells like Plug and Play for me and i like it
here is the final questions and purpose of this topic;
1-How is affected performance when i work with that system, -imagine- I have tousand NPCs in my scene?
2-Is this system logical for JME code basement? so i mean, if i dont want use the ES system (i see that system too complex for me) can i use this system?
----Update----
i tested the system i use with 10.000 object.