Hello guys,
I’m currently working on the AI of my game. I want the NPCs to follow the player within a certain radius. To do that, I attached a (pretty large) GhostControl to my player. Now I wanted to simulate hearing (when the player shoots and a NPC is inside the GhostControl, he moves to the position where the player shot), but the problem is that the framerate is dropping from about 1000 fps to <60 fps. Is there a better way to do this? I somehow need to check the radius but apparently a GhostControl with that size (radius ~50f) is too difficult to calculate. Here’s the code I’m using:
[java]package net.softwarepage.fearkill;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.GhostControl;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
*
-
@author Mathias AppState managing the AI of the small enemies
*/
public class AIState extends AbstractAppState { //TODO: wenn nah, wenn gehörtprivate Main app;
private BulletAppState bulletAppState;
private Map<Spatial, AnimChannel> smallEnemies = new HashMap<>();
private ArrayList<Spatial> followers = new ArrayList<>();public AIState(Main application, BulletAppState bas) {
app = application;
bulletAppState = bas;
}@Override
public void initialize(AppStateManager stateManager, Application application) {
super.initialize(stateManager, application);Spatial t1 = app.getAssetManager().loadModel("Models/skeleton.j3o"); BetterCharacterControl t1Control = new BetterCharacterControl(1f, 4f, 30f); t1.addControl(t1Control); app.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(t1Control); t1Control.warp(new Vector3f(-10f, 0.2f, 5.0f)); t1Control.setGravity(new Vector3f(0f, -30f, 0f)); t1.setUserData("Health", 20f); Spatial t2 = app.getAssetManager().loadModel("Models/skeleton.j3o"); BetterCharacterControl t2Control = new BetterCharacterControl(1f, 4f, 30f); t2.addControl(t2Control); app.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(t2Control); t2Control.warp(new Vector3f(0f, 0.2f, 5.0f)); t2Control.setGravity(new Vector3f(0f, -30f, 0f)); t2.setUserData("Health", 20f); AnimChannel channel = getChannel(t1); AnimChannel c2 = getChannel(t2); app.getEnemies().attachChild(t1); app.getEnemies().attachChild(t2); smallEnemies.put(t1, channel); smallEnemies.put(t2, c2); app.getRootNode().attachChild(app.getEnemies()); GhostControl ghostControl = new GhostControl(new SphereCollisionShape(50f)); app.getPlayer().addControl(ghostControl); bulletAppState.getPhysicsSpace().add(ghostControl); //Without the line I have about 2000 fps; with it about 30
}
private AnimChannel getChannel(Spatial s) {
Node n = (Node) s;
Node metarig = (Node) n.getChild(“metarig”);
Node pelvis = (Node) metarig.getChild(“Pelvis”);
Node polySurface1 = (Node) pelvis.getChild(“polySurface2.006-entity”);
Node polySurface2 = (Node) polySurface1.getChild(“polySurface2.006-ogremesh”);
AnimControl control = polySurface2.getControl(AnimControl.class);
AnimChannel channel = control.createChannel();
return channel;
}public AnimChannel getAnimChannel(Spatial s) {
return smallEnemies.get(s);
}public void remove(Spatial s) {
smallEnemies.remove(s);
followers.remove(s);
bulletAppState.getPhysicsSpace().remove(s.getControl(BetterCharacterControl.class));
}public void setFollower(Spatial s) {
if (!followers.contains(s)) {
smallEnemies.get(s).setAnim(“Walk”);
followers.add(s);
}
}public void shotAt(Vector3f position) {
}@Override
public void update(float tpf) {
for (Spatial s : followers) {
moveToPlayer(s);
}
}private void moveToPlayer(Spatial s) {
BetterCharacterControl b = s.getControl(BetterCharacterControl.class);
Vector3f enemyDirection = app.getPlayer().getLocalTranslation().subtract(s.getLocalTranslation()).normalizeLocal();
enemyDirection.multLocal(4f);
enemyDirection.setY(0);
b.setViewDirection(enemyDirection);
b.setWalkDirection(enemyDirection);
}@Override
public void cleanup() {
super.cleanup();
//TODO: clean up what you initialized in the initialize method,
//e.g. remove all spatials from rootNode
//this is called on the OpenGL thread after the AppState has been detached
}
}
[/java]
Maybe I could somehow just calculate everything that is above the terrain (the collisionshape is also under the terrain) or something like that… But otherwise I really don’t know how to solve this.