Updating entity position in real-time

I’m in early stages of creating a survival gps game and im trying to create tons of zombies on map that chase the user.

Im using SampledPositionProperty which gets updated every 1 second.

Because everything changes in real-time and i dont know where entity will be next second, thus i decided to use forwardExtrapolationType = Cesium.ExtrapolationType.HOLD;

Now problem arises with large number of entities - FPS goes down the drain.

Performance in mind, what could be other alternatives to update entities position ?

Some code:

function zombieCreate(lon,lat,height){

var position = Cesium.Cartesian3.fromDegrees(lon, lat, height);

var zombiePositions = new Cesium.SampledPositionProperty();

zombiePositions.forwardExtrapolationType = Cesium.ExtrapolationType.HOLD;

zombiePositions.addSample( Cesium.JulianDate.fromDate(new Date()), position);

var walker = viewer.entities.add({

name : 'Green circle at height with outline',

position : zombiePositions,

ellipse : {

    semiMinorAxis : 5.0,

    semiMajorAxis : 5.0,

    outlineWidth : 0,

    material : new Cesium.ImageMaterialProperty({

        image : 'SampleData/pin4.png',

        transparent: true

    }),

    granularity : 0.0523598776,

    numberOfVerticalLines :2,

    height : 1

    }

}); 

return walker;

}

function zombieMove(walker){

for (i in walker){

var dist = 15;

var positionSamples = walker[i].position;

var carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(walker[i].position.getValue(Cesium.JulianDate.fromDate(new Date())));

var zombieLon = Cesium.Math.toDegrees(carto.longitude);

var zombieLat = Cesium.Math.toDegrees(carto.latitude);

//GET DIRECTION WHERE Z MOVES TO V

var zombieBearing = geolib.getBearing(

{latitude: zombieLat, longitude: zombieLon},

{latitude: usrLat, longitude: usrLon}

);

var initialPoint = {lat: zombieLat, lon: zombieLon}

var newPositon = (geolib.computeDestinationPoint(initialPoint, dist, zombieBearing));

//ADD NEW SAMPLES

var time = Cesium.JulianDate.addSeconds( Cesium.JulianDate.fromDate(new Date()), 1, Cesium.JulianDate.fromDate(new Date()));

var position = Cesium.Cartesian3.fromDegrees(newPositon.longitude, newPositon.latitude, 1);

positionSamples.addSample(time, position);

walker[i].position = positionSamples;

walker[i].ellipse.stRotation = Cesium.Math.toRadians(zombieBearing);

}

}

//Gets update from navigator.geolocation
var usrLat;
var usrLon;

var zombies = ;

//GENERATE RANDOM ZOMBIES
for(var i=0;i<250;i++){

if(Math.random()){

zombies.push(zombieCreate(usrLon+(((Math.random() * 0.009) + 0.001)),usrLat+(((Math.random() * 0.009) + 0.001)), 1));

}else{

zombies.push(zombieCreate(usrLon+(((Math.random() * 0.009) - 0.001)),usrLat+(((Math.random() * 0.009) + 0.001)), 1));

}

}

//LOOP
setInterval(function (){ zombieMove(zombies); },1000);

``

Hi Rain,

Sounds like a fun app! :slight_smile:

I would suggest not using setInterval, as it does not always sync updates with Cesium’s update/render cycle. Since you are only updating once per second, I would set the viewer clock to tick only once every second. Then add a listener to the Clock.onTick event to update the positions. You wouldn’t need to use the sampledPositionProperty, just update the positions directly.

The most efficient way to visualize a lot of points in Cesium is to use PointPrimitives, see the blog post on the subject. However that does use the Primitive API which is lower level than the Entity API, and I don’t think that is needed in this case.

Thanks,

Gabby

im using sampledPositionProperty to give smooth transition from point A to B. Updating position directly would teleport the entity.
I imagine that entity would make a decision every second on which direction to go

I see. In any case, you should still avoid the use of getInterval. In your Clock.onTick listener function, check the time since last update, and add a new sampled position.

var clock = viewer.clock;
var lastUpdated = clock.currentTime;
clock.onTick.addEventListener(function() {
var dt = Cesium.JulianDate.secondsDifference(clock.currentTime, lastUpdated);
if (dt >= 1.0) {
// Add a new sample position
lastUpdated = clock.currentTime;

}

});

``

Additionally, instead of calculating the zombieBearing yourself, you can use a VelocityOrientationProperty for the entity’s orientation property.

Thank you so much, that’s what i decided to go with :slight_smile: