| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- import "./const.ecal" as const
- import "./helper.ecal" as hlp
- /*
- Constant rate for moving. The higher the less movement we do in a given time.
- */
- moveRate := 30
- /*
- Time the move loop was executed last (used for time correction)
- */
- lastMoveCycleTime := 0
- /*
- Game engine object which moves objects in a game world.
- */
- GameEngine := {
- /*
- Partition to manage
- */
- "part" : null,
- /*
- Game world
- */
- "world" : null,
- /*
- Constructor
- */
- "init" : func (part, world) {
- this.part := part
- this.world := world
- },
- /*
- updateStats updates the statistic node in the DB.*/
- "updateStats" : func (state) {
- state["key"] := "stats"
- state["kind"] := "stats"
- db.updateNode(this.part, state)
- },
- /*
- moveLoop handles object movement in the game world.
- */
- "moveLoop" : func () {
- let moveLoopTime := now()
- let timeDelta := moveLoopTime - lastMoveCycleTime # Do the move
- /*
- Do a single move step with compensation for the time delta
- */
- time := now()
- this.move(timeDelta)
- this.updateStats({"time_total_move" : now() - time})
- lastMoveCycleTime := moveLoopTime
- },
- /*
- move calculates one move step
- */
- "move" : func (timeDelta) {
- /*
- Calculate a correction multiplier for the time lag
- */
- let timeCorrection := timeDelta / moveRate
- if math.isNaN(timeCorrection) or math.isInf(timeCorrection, 0) {
- timeCorrection := 1
- }
- /*
- Store the latest time correction
- */
- this.updateStats({"time_move_correction" : timeCorrection})
- gq := "{ obj { key, kind, x, y, dim, displayLoop, dir, rot, rotSpeed, speed, strafe, moveSpeed } }"
- time := now()
- res := db.graphQL(this.part, gq)
- this.updateStats({"time_move_graphql" : now() - time})
- if len(res.data.obj) > 0 {
- trans := db.newTrans()
- time := now()
- for obj in res.data.obj {
- if not this.moveObject(timeCorrection, obj, trans) {
- 0 # TODO Decide if the entity should be removed
- }
- }
- this.updateStats({"time_move_update" : now() - time})
- time := now()
- db.commit(trans)
- this.updateStats({"time_move_commit" : now() - time})
- }
- },
- /*
- Move a specific object in the game world. Return false if the object
- should be removed from the world.
- */
- "moveObject" : func (timeCorrection, obj, trans) {
- let keepObj := true
- /*
- Calculate new entity coordinates
- */
- let moveStep := timeCorrection * obj.speed * obj.moveSpeed
- let strafeStep := timeCorrection * obj.strafe * obj.moveSpeed * 20
- /*
- Forward / backward movement
- */
- let newX := obj.x + math.cos(obj.rot) * moveStep
- let newY := obj.y + math.sin(obj.rot) * moveStep
- /*
- Left / right strafe movement
- */
- newX := newX - math.sin(obj.rot) * strafeStep
- newY := newY + math.cos(obj.rot) * strafeStep
- /*
- Rotate the entity
- */
- obj.rot := obj.rot + timeCorrection * obj.dir * obj.rotSpeed
- obj.x := math.floor(newX)
- obj.y := math.floor(newY)
- /*
- Ensure the entity does not move outside the boundaries
- */
- if obj.displayLoop {
- hmin := 0 - obj.dim - 20
- hmax := this.world.screenWidth + obj.dim + 20
- if obj.x > hmax {
- obj.x := 0 - obj.dim - 10
- } elif obj.x < hmin {
- obj.x := this.world.screenWidth + obj.dim + 10
- }
- vmin := 0 - obj.dim - 20
- vmax := this.world.screenHeight + obj.dim + 20
- if obj.y > vmax {
- obj.y := 0 - obj.dim - 10
- } elif obj.y < vmin {
- obj.y := this.world.screenHeight + obj.dim + 10
- }
- } elif obj.x > this.world.screenWidth or obj.x < 0 or obj.y > this.world.screenHeight or obj.y < 0 {
- keepObj := false
- }
- db.updateNode(this.part, {
- "key" : obj.key,
- "kind" : obj.kind,
- "x" : obj.x,
- "y" : obj.y,
- "rot" : obj.rot
- }, trans)
- return keepObj
- }
- }
|