arielsan wrote:
Hi appel, I have some questions:
1) could you share all the scene graph stuff?

2) I have some special case I dunno the best way to handle it:
In my current game I have arrows which have a physics component. Once they hit a target I want them to become stuck.
Right now, I am creating a new entity with similar information to the other one but without physics component and remove the old one. One problem with this solution is that I am creating a new entity and destroying another each time the arrows hit. Another problem is the arrows become invisible for one frame (because there is no arrow for one frame), this one could be a problem with the systems ordering (in my code).
I was thinking about only removing the physics component from the first one instead creating a new entity, but I have a problem: I need to handle the component removal to do extra logic (remove the body from the physics engine, etc). Dunno how to achieve that with Artemis, and if it should be in that way or my current solution is better.
Thanks for the answer.
I have already posted about the game in other forum thread, but if you didn't see it,
here is the link of the game.
Removing a component is simple: Entity.removeComponent(ComponentType type)
Then invoke Entity.refresh()
Systems will be notified if a Entity it is currently holding no longer is relevant for the system aspect:
EntitySystem.removed(Entity e)
Just override it in your system.
My early scene-graph system:
Code:
package com.gamadu.modulus.systems;
import com.artemis.ComponentMapper;
import com.artemis.Entity;
import com.artemis.EntitySystem;
import com.artemis.utils.Bag;
import com.artemis.utils.ImmutableBag;
import com.artemis.utils.Utils;
import com.gamadu.modulus.components.LocalTransform;
import com.gamadu.modulus.components.Node;
import com.gamadu.modulus.components.Transform;
public class SceneGraphSystem extends EntitySystem {
private ComponentMapper<Node> nodeMapper;
private ComponentMapper<Transform> transformMapper;
private ComponentMapper<LocalTransform> localTransformMapper;
private Bag<Entity> rootNode;
public SceneGraphSystem() {
super(Node.class);
rootNode = new Bag<Entity>();
}
@Override
public void initialize() {
nodeMapper = new ComponentMapper<Node>(Node.class, world.getEntityManager());
transformMapper = new ComponentMapper<Transform>(Transform.class, world.getEntityManager());
localTransformMapper = new ComponentMapper<LocalTransform>(LocalTransform.class, world.getEntityManager());
}
@Override
protected void processEntities(ImmutableBag<Entity> entities) {
for(int i = 0, s = rootNode.size(); s > i; i++) {
processEntity(rootNode.get(i));
}
}
private void processEntity(Entity entity) {
Node node = nodeMapper.get(entity);
Bag<Entity> children = node.getChildren();
for(int i = 0, s = children.size(); s > i; i++) {
Entity e = children.get(i);
updateWorldTransformation(e);
processEntity(e);
}
}
private void updateWorldTransformation(Entity e) {
Node node = nodeMapper.get(e);
Entity parent = node.getParent();
Transform parentTransform = transformMapper.get(parent);
Transform transform = transformMapper.get(e);
LocalTransform localTransform = localTransformMapper.get(e);
float currentX = parentTransform.getX()+localTransform.getX();
float currentY = parentTransform.getY()+localTransform.getY();
float x = Utils.getRotatedX(currentX, currentY, parentTransform.getX(), parentTransform.getY(), parentTransform.getRotation());
float y = Utils.getRotatedY(currentX, currentY, parentTransform.getX(), parentTransform.getY(), parentTransform.getRotation());
transform.setLocation(x, y);
transform.setRotation(parentTransform.getRotation());
}
@Override
protected boolean checkProcessing() {
return true;
}
@Override
protected void added(Entity e) {
Node node = nodeMapper.get(e);
Entity parent = node.getParent();
if(parent == null) {
rootNode.add(e);
} else {
Node parentNode = nodeMapper.get(parent);
parentNode.addChild(e);
}
}
@Override
protected void removed(Entity e) {
}
}
Code:
package com.gamadu.modulus.components;
import com.artemis.Component;
import com.artemis.Entity;
import com.artemis.utils.Bag;
public class Node extends Component {
private Entity parent;
private Bag<Entity> children;
public Node() {
children = new Bag<Entity>();
}
public Node(Entity parent) {
this();
this.parent = parent;
}
public Entity getParent() {
return parent;
}
public Bag<Entity> getChildren() {
return children;
}
public void addChild(Entity child) {
children.add(child);
}
public void removeChild(Entity child) {
children.remove(child);
}
}
Code:
package com.gamadu.modulus.components;
import com.artemis.Component;
import com.artemis.utils.Utils;
public class LocalTransform extends Component {
private float x;
private float y;
private float rotation;
public LocalTransform() {
}
public LocalTransform(float x, float y) {
this.x = x;
this.y = y;
}
public LocalTransform(float x, float y, float rotation) {
this(x, y);
this.rotation = rotation;
}
public void addX(float x) {
this.x += x;
}
public void addY(float y) {
this.y += y;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public void setLocation(float x, float y) {
this.x = x;
this.y = y;
}
public float getRotation() {
return rotation;
}
public void setRotation(float rotation) {
this.rotation = rotation;
}
public void addRotation(float angle) {
rotation = (rotation + angle) % 360;
}
public float getRotationAsRadians() {
return (float) Math.toRadians(rotation);
}
public float getDistanceTo(LocalTransform t) {
return Utils.distance(t.getX(), t.getY(), x, y);
}
}