Updating entity position in real-time

2,120 views
Skip to first unread message

rain ungert

unread,
Feb 3, 2018, 2:20:07 PM2/3/18
to cesium-dev
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);


Gabby Getz

unread,
Feb 6, 2018, 10:13:00 AM2/6/18
to cesium-dev
Hi Rain,

Sounds like a fun app! :)

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

rain ungert

unread,
Feb 11, 2018, 10:39:20 AM2/11/18
to cesium-dev
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

Gabby Getz

unread,
Feb 13, 2018, 5:20:10 PM2/13/18
to cesium-dev
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.

rain ungert

unread,
Feb 13, 2018, 6:13:11 PM2/13/18
to cesium-dev
Thank you so much, that's what i decided to go with :)
Reply all
Reply to author
Forward
0 new messages