How to create a spawner the control way?

Use Case : Box Spawner
Create a GameObject that spawns other gameobjects

If I have a GameObject say a Spatial Cube and I want it to use a Controller that will create other game objects.
Inside the Control that extends AbstractControl how do I get access to the rootNode to attach the new objects and how do I get to the AssetManager to load textures.

Am I off on trying to use a Control or is there a good test that shows me how to do this.

Thanks,
Greg

The rootNode is probably one of the parents of your spatial, right? :wink: You can also make an AppState that gets a Node passed and maintains the Spatials, theres no wrong or right, its depending on your usecase. The advantage of a Control is that you can save it in a j3o.

As hinted, controls are for spatial-specific things. The fact that you need to modify the root of the tree implies that an app state might be a better idiom. Hard to say when dealing with hypothetical vagueness.

Thanks @normen and @pspeed

Sorry for the hypothetical. I am just trying to understand the concept.

I want a box that spawns smaller boxes.

This is a test. I cant figure out how to get the AssetManager inside the controller.
for cases where I want to get new Materials or other Models from my assets.
Am I not using Controller correctly?

Thanks for the info.

[java]
package com.scriptblocks.flappymonkey.controller;

import com.jme3.asset.AssetManager;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.material.Material;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import com.jme3.scene.shape.Box;
import java.io.IOException;

public class SpawnerControl extends AbstractControl {

private static final Box box;
public float speed = 3;
private float timeSenceLastCreation = 0;
Material childMat;

static {
    box = new Box(.5f, .5f, .5f);
    box.scaleTextureCoordinates(new Vector2f(1f, .5f));
}

@Override
protected void controlUpdate(float tpf) {
    timeSenceLastCreation = timeSenceLastCreation + tpf;
    if (timeSenceLastCreation > speed) {
        System.out.println("Create");
        makeBlock(new Vector3f(0, 0, 0));
        timeSenceLastCreation = 0;
    }
}

protected Node getRootNode() {
    //assuming parent is roodNode
    return spatial.getParent();
}

protected AssetManager getAssetManager() {
    return null;  //How to get this
}

 protected Material getMaterial() {
    return ((Geometry)spatial).getMaterial();  
}


public Control cloneForSpatial(Spatial spatial) {
    SpawnerControl control = new SpawnerControl();
    return control;
}

public void makeBlock(Vector3f loc) {
    Geometry block = new Geometry("brick", box);
    block.setMaterial(getMaterial());
    block.setLocalTranslation(loc);
    block.addControl(new BlockControl());
    getRootNode().attachChild(block);
}

}
[/java]

[java]
package com.scriptblocks.flappymonkey;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.scriptblocks.flappymonkey.controller.SpawnerControl;

public class Main extends SimpleApplication {
public static void main(String[] args) {
Main app = new Main();
app.start();
}

@Override
public void simpleInitApp() {
    Box b = new Box(1, 1, 1);
    Geometry geom = new Geometry("Box", b);
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.setColor("Color", ColorRGBA.Blue);
    geom.setMaterial(mat);
    geom.addControl(new SpawnerControl());
    rootNode.attachChild(geom);
}

@Override
public void simpleUpdate(float tpf) {       
}

@Override
public void simpleRender(RenderManager rm) {
    //TODO: add render code
}   

}

[/java]

new MyControl(assetManager)

…not sure what’s hard. Can you explain?

@pspeed
I was thinking that I should not override the Constructor.
Wouldn’t that make it not usable in the SDK Scene Viewer?

I know I could do this one just one Main class but I am trying to understand how to split up my code and also make it reusable.

I was hoping to extend the Controller so say I have one Spawner Spawn Blue boxes and on Spawner Spawn Red.

What if I make the cubeToBeSpawned Geometry a variable on the controller and defined a public getter and setter. I could assign the cubeToBeSpawned with the setter and then clone it when I want to make the boxes.

Would that be a correct usage?

Well, yes, if you add the SDK requirement then there is no clean way to do what you want to do. Controls are spatial-specific and so don’t have access to global things like app states do. A clear sign that an app state is really what you want as the app state has access to everything… including being able to find your spawning spatials.

You can easily grab the assetManager in the read() method and also pass one when you create the control, but you will need a custom “add control” command for the SDK or use an AppState that you run on your scene to add them with AssetManager (also in the SDK).

I also faced this problem. I also wanted to add spawn points in my game world. What I did was make a Separate Node in the Stage and named it “ModelNodes” where I have linked all the other enemies spatial there (they are all Invisible). So now the spawn spatial with spawn control had to do is grab the link models from that Node and attach it in the Stage Node(could be anywhere you want it to be attached).