I'm starting an object orientated game engine in Java. My plans for the engine is to be able to split things easily into multi-core loads. My idea is that a Unique (interface with a GetUID()
method) gets passed in. The Unique can also implement any number of other interfaces. In this case, the unique can also implement an Entity (having the Compute()
and Render()
methods) or MouseInputter (having the UpdateMouse()
method). In the future, any number of other interfaces can also be added and handled if needed. Then Tick()
moves everything forward one step. So far I've not implemented the multi-core parts, but want early feedback to ensure I'm not going astray.
I'd like to know the common weaknesses or pitfalls of my approach. I'm also concerned about the performance impact of running instanceof X times on N objects per loop. Is there a benefit to caching the interfaces? I think I'd use a long with bitmasks, so the overhead is about 16 bytes per object. It's harder to compare the CPU load (fetching from cache vs instanceof). Is caching this value worth the tradeoff, generally? So what I'm getting at is; is my approach scalable or is a different one required?
package com.mygdx.engine;
import java.util.ArrayList;
import java.util.HashMap;
import com.badlogic.gdx.Gdx;
import com.mygdx.game.entity.Entity;
import com.mygdx.game.entity.Unique;
import com.mygdx.game.utils.MouseInputter;
public class Engine {
private HashMap<String,Unique> things = new HashMap<String,Unique>();
private long lastComputeMillis;
private long lastMouseMillis;
// TODO: implement multicore.
public Engine(int cores) {
}
public void Tick() {
this.UpdateMouse();
this.Compute();
this.Render();
}
public void AddObject(Unique o) {
things.put(o.GetUID(), o);
}
public boolean Remove(String o) {
if( this.things.containsKey(o) ) {
things.remove(o);
return true;
}
return false;
}
private void render() {
Entity transientEntity;
for (Object o : things.values()) {
if (o instanceof Entity) {
transientEntity = (Entity) o;
transientEntity.Render();
}
}
this.lastComputeMillis = System.currentTimeMillis();
}
private void compute() {
Entity transientEntity;
for (Object o : things.values()) {
if (o instanceof Entity) {
transientEntity = (Entity) o;
transientEntity.Compute(System.currentTimeMillis() - this.lastComputeMillis);
}
}
this.lastComputeMillis = System.currentTimeMillis();
}
private void updateMouse() {
int mousex = Gdx.input.getX();
int mousey = Gdx.input.getY();
MouseInputter transientEntity;
for (Object o : things.values()) {
if (o instanceof MouseInputter) {
transientEntity = (MouseInputter) o;
transientEntity.UpdateMouse(mousex, mousey, System.currentTimeMillis() - this.lastMouseMillis);
}
}
this.lastMouseMillis = System.currentTimeMillis();
}
}