Hello,
I am a bit new to JMonkey. My plan is a simple capture the flag game. I got most of the character control and map generation done already but now I’m running into the problem with detecting if a character is touching a flag.
My first idea was to check for location collision but that didn’t work out since I can’t get the physics position of the BetterCharacterControl. So I tried to use the getLocalTranslation()
method on the actual spatial but that returned a number which was way off even though the spatial was attached to the rootNode.
After this I came to ghostControl. So I started by setting up PhysicsTickListener in my class and inside the physicsTick()
method I check all the overlapping objects of the ghostControl. This for some reason is empty even when my BetterCharacterControl player passes right through the flag.
What is causing the ghostControl not to detect the player?
Code for base/flag:
/*
- To change this template, choose Tools | Templates
- and open the template in the editor.
*/
package org.ctf.control;
import com.jme3.bullet.PhysicsTickListener;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.control.GhostControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Cylinder;
import java.util.Observable;
import java.util.Observer;
import org.ctf.models.Character;
import org.ctf.models.Team;
import org.ctf.util.GlobalStorage;
import org.ctf.util.PhysicsSpace;
/**
*
@author thomv
*/
public class BaseControl implements Observer, PhysicsTickListener {private Vector3f location;
private Team team;
private Geometry flag;
private GhostControl control;//
/**
- Get the value of location
- @return The value of location
*/
public Vector3f getLocation() {
return location;
}/**
- Get the value of flag
- @return The value of flag
*/
public Geometry getFlag() {
return flag;
}/**
- Get the value of flag
- @return The value of flag
*/
public Team getTeam() {
return team;
}/**
- Get the value of control
- @return The value of control
*/
public GhostControl getControl(){
return control;
}
///**
Creates a physical base on the field
@param location The location of the flat base object. Not the pole, not the flag
@param team The team the base will be assigned to
*/
public BaseControl(Vector3f location, Team team){
this.location = location;
this.team = team;// Generate the physical base
generateBase();// Setup the flag
resetFlag();
}/**
- This method will attach the flag of the base to the character
- @param character The character who touched the flag
*/
public void stealFlag(Character character){
System.out.println(team.getName() + “'s flag got stolen.”);
}/**
This method will generate the baseplate and pole
*/
private void generateBase(){
Geometry base = new Geometry(“Base”, new Cylinder(8, 8, 5, 1, true));
base.setLocalTranslation(location);
base.lookAt(new Vector3f(location.x, -1, location.z), new Vector3f(location.x, 1, location.z));Material mat = new Material(GlobalStorage.getAssetManager(), “Common/MatDefs/Misc/Unshaded.j3md”);
mat.setColor(“Color”, ColorRGBA.DarkGray);
base.setMaterial(mat);GlobalStorage.getRootNode().attachChild(base);
RigidBodyControl baseC = new RigidBodyControl(0);
baseC.setKinematicSpatial(false);
base.addControl(baseC);
PhysicsSpace.add(baseC);Geometry pole = new Geometry(“Box”, new Box(0.1F, 3, 0.1F));
pole.setLocalTranslation(new Vector3f(location.x, location.y + 3, location.z));Material mat1 = new Material(GlobalStorage.getAssetManager(), “Common/MatDefs/Misc/Unshaded.j3md”);
mat1.setColor(“Color”, ColorRGBA.Brown);
pole.setMaterial(mat1);GlobalStorage.getRootNode().attachChild(pole);
}/**
This method will reset the flag to the base. Can only be called from inside
*/
private void resetFlag(){
this.flag = new Geometry(“Box”, new Box(0.075F, 1, 1));
this.flag.setLocalTranslation(new Vector3f(location.x, location.y + 4.75F, location.z + 1));this.control = new GhostControl(new BoxCollisionShape(new Vector3f(0.075F, 1, 1)));
this.flag.addControl(this.control);Material mat = new Material(GlobalStorage.getAssetManager(), “Common/MatDefs/Misc/Unshaded.j3md”);
mat.setColor(“Color”, this.team.getColor());
this.flag.setMaterial(mat);GlobalStorage.getRootNode().attachChild(this.flag);
PhysicsSpace.add(control);
}/**
- This method is automatically invoked if a character touches a flag
- @param o The observable object which this method was called from
- @param arg The additional argument
*/
@Override
public void update(Observable o, java.lang.Object arg) {
Character character = (Character) arg;
stealFlag(character);
}
/** * * @param space * @param tpf */ @Override public void prePhysicsTick(com.jme3.bullet.PhysicsSpace space, float tpf) { }
/** * * @param space * @param tpf */ @Override public void physicsTick(com.jme3.bullet.PhysicsSpace space, float tpf) { for (PhysicsCollisionObject obj : this.control.getOverlappingObjects()){ System.out.println(obj.getUserObject()); } }
}
Code for character:
/*
- To change this template, choose Tools | Templates
- and open the template in the editor.
*/
package org.ctf.models;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import org.ctf.util.GlobalStorage;
import org.ctf.util.PhysicsSpace;
/**
*
- @author thomv
*/
public abstract class Character extends Entity {
protected Spatial model; protected Geometry camTarget; protected BetterCharacterControl control; protected Team team; protected int flagsCaptured; protected int kills; protected int deaths; //<editor-fold defaultstate="collapsed" desc="Properties"> /** * Get the value of model * @return The value of model */ public Spatial getModel(){ return model; } /** * Get the value of control * @return The value of control */ public BetterCharacterControl getControl(){ return control; } /** * Get the value of team * @return The value of team */ public Team getTeam(){ return team; } /** * Get the value of camTarget * @return The value of camTarget */ public Geometry getCamTarget(){ return camTarget; } /** * Get the value of flagsCaptured * @return The value of flagsCaptured */ public int getFlagsCaptured(){ return flagsCaptured; } /** * Get the value of kills * @return The value of kills */ public int getKills(){ return kills; } /** * Get the value of deaths * @return The value of deaths */ public int getDeaths(){ return deaths; } /** * Set the value of team * @param team The new value for team */ public void setTeam(Team team){ this.team = team; Material mat = new Material(GlobalStorage.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); mat.setColor("Color", this.team.getColor()); this.model.setMaterial(mat); } //</editor-fold> public Character(String name, Vector3f location) { super(name, location); this.flagsCaptured = 0; this.kills = 0; this.deaths = 0; this.model = GlobalStorage.getAssetManager().loadModel("Models/character/character.j3o"); this.model.setLocalTranslation(location); this.control = new BetterCharacterControl(2F, 6F, 10F); this.control.setJumpForce(new Vector3f(0, 75, 0)); this.control.setGravity(new Vector3f(0, 10, 0)); this.model.addControl(this.control); this.camTarget = new Geometry("Box", new Box(0.1F, 0.1F, 0.1F)); this.camTarget.setMaterial(new Material(GlobalStorage.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md")); this.camTarget.setLocalTranslation(0, 3.5F, 0); Node modelNode = (Node) this.model; modelNode.attachChild(this.camTarget); GlobalStorage.getRootNode().attachChild(this.model); PhysicsSpace.add(this.control); }
}