main.ecal 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import "./templates.ecal" as tmpl
  2. import "./const.ecal" as const
  3. import "./helper.ecal" as hlp
  4. import "./engine.ecal" as engine
  5. /*
  6. Get details of a game world.
  7. Endpoint: /db/ecal/game
  8. */
  9. sink GetGameWorld
  10. kindmatch ["db.web.ecal"]
  11. statematch {"path" : "game", "method" : "GET"}
  12. priority 10
  13. {
  14. let gameWorld
  15. try {
  16. gameName := event.state.query.gameName[0]
  17. if gameName != "main" {
  18. raise(const.Errors.EntityNotFound, "Game world {{gameName}} not found")
  19. }
  20. gameWorld := tmpl.newGameWorld(gameName)
  21. if db.fetchNode(gameName, gameName, const.NodeKinds.ConfigurationObject) == null {
  22. db.storeNode(gameName, gameWorld)
  23. sprite := tmpl.newSpriteNode("asteroid", 300, 300, 40, 20, 0.01)
  24. db.storeNode(gameName, sprite)
  25. }
  26. } except e {
  27. error(e)
  28. db.raiseWebEventHandled({"code" : const.ErrorCodes[e.type], "body" : {"error" : e.type}})
  29. } otherwise {
  30. db.raiseWebEventHandled({"code" : 200, "body" : {"result" : "success", "gameworld" : gameWorld}})
  31. }
  32. }
  33. /*
  34. Register a new player.
  35. Endpoint: /db/ecal/player
  36. */
  37. sink RegisterNewPlayer
  38. kindmatch ["db.web.ecal"]
  39. statematch {"path" : "player", "method" : "POST"}
  40. priority 10
  41. {
  42. let sprite
  43. let gameWorld
  44. try {
  45. let playerName := event.state.bodyJSON.player
  46. let gameName := event.state.bodyJSON.gameName
  47. gameWorld := tmpl.DefaultGameWorld
  48. if db.fetchNode(gameName, playerName, const.NodeKinds.GameWorldObject) == null {
  49. sprite := tmpl.newSpriteNode(event.state.bodyJSON.player, 21, 21)
  50. db.storeNode(gameName, sprite)
  51. }
  52. log("Registered player: ", playerName, " for game:", gameName)
  53. } except e {
  54. error(e)
  55. db.raiseWebEventHandled({"code" : const.ErrorCodes["InternalError"], "body" : {"error" : const.Errors.InternalError}})
  56. } otherwise {
  57. db.raiseWebEventHandled({"code" : 200, "body" : {
  58. "result" : "success",
  59. "sprite" : sprite,
  60. "gameworld" : gameWorld
  61. }})
  62. }
  63. }
  64. /*
  65. Process player input.
  66. Endpoint: /db/ecal/input
  67. */
  68. sink PlayerInput
  69. kindmatch ["db.web.ecal"]
  70. statematch {"path" : "input", "method" : "POST"}
  71. priority 10
  72. {
  73. let sprite
  74. let gameWorld
  75. try {
  76. let playerName := event.state.bodyJSON.player
  77. let gameName := event.state.bodyJSON.gameName
  78. let state := event.state.bodyJSON.state
  79. state["key"] := playerName
  80. state["kind"] := const.NodeKinds.GameWorldObject
  81. db.updateNode(gameName, state)
  82. log("Updated player: ", playerName, " for game:", gameName, " with state:", state)
  83. } except e {
  84. error(e)
  85. db.raiseWebEventHandled({"code" : const.ErrorCodes["InternalError"], "body" : {"error" : const.Errors.InternalError}})
  86. } otherwise {
  87. db.raiseWebEventHandled({"code" : 200, "body" : {
  88. "result" : "success",
  89. "sprite" : sprite,
  90. "gameworld" : gameWorld
  91. }})
  92. }
  93. }
  94. /*
  95. Object for main game engine.
  96. */
  97. MainGameEngine := new(engine.GameEngine, "main", tmpl.DefaultGameWorld)
  98. /*
  99. GameLoop sink.
  100. */
  101. sink MainGameLoop
  102. kindmatch ["main.gameloop"]
  103. priority 100
  104. {
  105. try {
  106. MainGameEngine.moveLoop()
  107. } except e {
  108. error("Gameloop:", e)
  109. }
  110. }
  111. /*
  112. Trigger the main game loop in a set interval (microseconds). The interval here
  113. must always be greater than the total time of the move loop (see the time_total_move
  114. stat recorded in engine.ecal).
  115. 55000 - 55 milli seconds - smooth animation calculated in the backend, frontend only needs to display
  116. */
  117. setPulseTrigger(55000, "Main Game Loop", "main.gameloop")