import "./templates.ecal" as tmpl import "./const.ecal" as const import "./helper.ecal" as hlp import "./engine.ecal" as engine /* Get details of a game world. Endpoint: /db/ecal/game */ sink GetGameWorld kindmatch ["db.web.ecal"] statematch {"path" : "game", "method" : "GET"} priority 10 { let gameWorld try { gameName := event.state.query.gameName[0] if gameName != "main" { raise(const.Errors.EntityNotFound, "Game world {{gameName}} not found") } gameWorld := tmpl.newGameWorld(gameName) if db.fetchNode(gameName, gameName, const.NodeKinds.ConfigurationObject) == null { db.storeNode(gameName, gameWorld) sprite := tmpl.newSpriteNode("asteroid", 300, 300, 40, 20, 0.01) db.storeNode(gameName, sprite) } } except e { error(e) db.raiseWebEventHandled({"code" : const.ErrorCodes[e.type], "body" : {"error" : e.type}}) } otherwise { db.raiseWebEventHandled({"code" : 200, "body" : {"result" : "success", "gameworld" : gameWorld}}) } } /* Register a new player. Endpoint: /db/ecal/player */ sink RegisterNewPlayer kindmatch ["db.web.ecal"] statematch {"path" : "player", "method" : "POST"} priority 10 { let sprite let gameWorld try { let playerName := event.state.bodyJSON.player let gameName := event.state.bodyJSON.gameName gameWorld := tmpl.DefaultGameWorld if db.fetchNode(gameName, playerName, const.NodeKinds.GameWorldObject) == null { sprite := tmpl.newSpriteNode(event.state.bodyJSON.player, 21, 21) db.storeNode(gameName, sprite) } log("Registered player: ", playerName, " for game:", gameName) } except e { error(e) db.raiseWebEventHandled({"code" : const.ErrorCodes["InternalError"], "body" : {"error" : const.Errors.InternalError}}) } otherwise { db.raiseWebEventHandled({"code" : 200, "body" : { "result" : "success", "sprite" : sprite, "gameworld" : gameWorld }}) } } /* Process player input. Endpoint: /db/ecal/input */ sink PlayerInput kindmatch ["db.web.ecal"] statematch {"path" : "input", "method" : "POST"} priority 10 { let sprite let gameWorld try { let playerName := event.state.bodyJSON.player let gameName := event.state.bodyJSON.gameName let state := event.state.bodyJSON.state state["key"] := playerName state["kind"] := const.NodeKinds.GameWorldObject db.updateNode(gameName, state) log("Updated player: ", playerName, " for game:", gameName, " with state:", state) } except e { error(e) db.raiseWebEventHandled({"code" : const.ErrorCodes["InternalError"], "body" : {"error" : const.Errors.InternalError}}) } otherwise { db.raiseWebEventHandled({"code" : 200, "body" : { "result" : "success", "sprite" : sprite, "gameworld" : gameWorld }}) } } /* Object for main game engine. */ MainGameEngine := new(engine.GameEngine, "main", tmpl.DefaultGameWorld) /* GameLoop sink. */ sink MainGameLoop kindmatch ["main.gameloop"] priority 100 { try { MainGameEngine.moveLoop() } except e { error("Gameloop:", e) } } /* Trigger the main game loop in a set interval (microseconds). The interval here must always be greater than the total time of the move loop (see the time_total_move stat recorded in engine.ecal). 55000 - 55 milli seconds - smooth animation calculated in the backend, frontend only needs to display */ setPulseTrigger(55000, "Main Game Loop", "main.gameloop")