123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- import "./const.ecal" as const
- import "./helper.ecal" as hlp
- /*
- newGameWorld creates a new game world datastructure.
- */
- func newGameWorld(name) {
- let ret := hlp.copyMap(DefaultGameWorld)
- ret["key"] := name
- ret["kind"] := const.ObjectKinds.ConfigurationObject
- return ret
- }
- DefaultGameWorld := {
- "screenWidth" : 1280,
- "screenHeight" : 1024,
- "screenElementWidth" : 1280,
- "screenElementHeight" : 1024,
- "backdrop" : "background_nebular"
- }
- /*
- newSpriteNode creates a new general sprite datastructure.
- */
- func newSpriteNode(id, kind, x, y, dim=20, rot=0, speed=0) {
- let ret := hlp.copyMap(DefaultSpriteState)
- ret["key"] := id
- ret["kind"] := kind
- ret["id"] := id
- ret["x"] := x
- ret["y"] := y
- ret["dim"] := dim
- ret["rot"] := rot
- ret["speed"] := speed
- return ret
- }
- DefaultSpriteState := {
- /* A unique ID */
- "id" : "",
- /* Sprite x position */
- "x" : 20,
- /* Sprite y position */
- "y" : 20,
- /* Dimensions of the sprite (box) */
- "dim" : 20,
- /* Flag if the sprite is moving or static */
- "isMoving" : true,
- /*
- Flag if the sprite is kept in the display or if it should be
- destroyed once it is outside of the visible area
- */
- "displayLoop" : true,
- /* Turning direction (-1 for left, 1 for right, 0 no turning) */
- "dir" : 0,
- /* Angle of rotation */
- "rot" : 0,
- /* Rotation speed for each step (in radians) */
- "rotSpeed" : math.Pi / 180,
- /* Moving direction (1 forward, -1 backwards, 0 no movement) */
- "speed" : 0,
- /* Strafing direction of sprite (-1 left, 1 right, 0 no movement) */
- "strafe" : 0,
- /* Move speed for each step */
- "moveSpeed" : 0.21,
- /* Action handler funcion */
- "doAction" : func (entity, action, engine) {
- },
- /* Collision handler funcion */
- "collision" : func (entity, otherEntity) {
- return []
- }
- }
- PlayerState := {
- "lastBounce" : 0,
- /* Collision handler funcion */
- "collision" : func (entity, otherEntity, engine) {
- return [entity]
- },
- /* Action handler funcion */
- "doAction" : func (entity, action, engine) {
- if action == "fire" {
- let sx := entity.x + math.cos(entity.rot) * 20
- let sy := entity.y + math.sin(entity.rot) * 20
- let sprites := engine.gameState[engine.part].sprites
- let sprite := newShot("shot-{{entity.id}}-{{math.floor(rand() * 1000)}}", sx, sy, entity.rot)
- sprite.displayLoop := false
- sprite.owner := entity.id
- mutex GameStateMutex {
- engine.gameState[engine.part].sprites := add(sprites, sprite)
- }
- sendAudioEvent({"audioEvent" : "shot", "player" : entity.id}, engine)
- }
- }
- }
- /*
- newPlayer creates a new player datastructure.
- */
- func newPlayer(id, x, y) {
- base := newSpriteNode(id, const.ObjectKinds.Player, x, y)
- return hlp.copyMap(PlayerState, base)
- }
- ShotState := {
- /* Collision handler funcion */
- "collision" : func (entity, otherEntity, engine) {
- if otherEntity.kind == const.ObjectKinds.Asteroid {
- addEvent("changescore", "main.gamescore", {
- "id" : entity.owner,
- "part" : engine.part,
- "changeFunc" : func (s) {
- s.score := s.score + 100
- }
- })
- }
- /* A shot colliding with anything removes the shot */
- return [entity]
- }}
- /*
- newShot creates a new shot datastructure.
- */
- func newShot(id, x, y, rot) {
- base := newSpriteNode(id, const.ObjectKinds.Shot, x, y, 10, rot, 0.05)
- return hlp.copyMap(ShotState, base)
- }
- AsteroidState := {
- "lastBounce" : 0,
- /* Collision handler funcion */
- "collision" : func (entity, otherEntity, engine) {
- let ret := []
- if otherEntity.kind == const.ObjectKinds.Asteroid {
- /*
- Asteroids bounce off each other
- */
- if now() - entity.lastBounce > 1000000 {
- entity.rot := entity.rot + math.Pi
- if otherEntity.kind == const.ObjectKinds.Asteroid {
- otherEntity.rot := otherEntity.rot + math.Pi
- }
- /* Prevent further bouncing for some time on both objects */
- entity.lastBounce := now()
- if otherEntity.kind == const.ObjectKinds.Asteroid {
- otherEntity.lastBounce := now()
- }
- }
- } elif otherEntity.kind == const.ObjectKinds.Shot {
- let sprites := engine.gameState[engine.part].sprites
- let newParticleAsteroid := func (counter) {
- /*
- Create a particle asteroid after a bigger asteroid has been shot
- */
- let rot := counter % 3 * 45 + math.floor(rand() * 45)
- let dim := math.floor(entity.dim * 0.5)
- let radius := 10 + math.floor(rand() * 10)
- let speed := entity.speed + math.floor(2 + rand() * 3) / 1000
- let newX := math.floor(entity.x + math.cos(rot) * radius)
- let newY := math.floor(entity.y + math.sin(rot) * radius)
- return newAsteroid("{{entity.id}}-{{counter}}", newX, newY, 5 + dim, rot, speed)
- }
- if entity.dim > 35 {
- for i in range(1, 4) {
- let sprite := newParticleAsteroid(i)
- sprite.lastBounce := now()
- sprites := add(sprites, sprite)
- }
- mutex GameStateMutex {
- engine.gameState[engine.part].sprites := sprites
- }
- sendAudioEvent({"audioEvent" : "explosion"}, engine)
- } else {
- sendAudioEvent({"audioEvent" : "vanish"}, engine)
- }
- ret := [entity]
- }
- return ret
- },
- /* Action handler funcion */
- "doAction" : func (entity, action, engine) {
- }
- }
- /*
- newAsteroid creates a new asteroid datastructure.
- */
- func newAsteroid(id, x, y, dim=20, rot=0, speed=0) {
- base := newSpriteNode(id, const.ObjectKinds.Asteroid, x, y, dim, rot, speed)
- return hlp.copyMap(AsteroidState, base)
- }
- /*
- sendAudioEvent sends an audio event to the frontend.
- */
- func sendAudioEvent(payload, engine) {
- for [commID, data] in engine.websocket {
- if data.gamename == engine.part {
- addEvent("AudioEvent", "db.web.sock.msg", {"commID" : commID, "payload" : payload})
- }
- }
- }
|