diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..4a23794 --- /dev/null +++ b/TODO.md @@ -0,0 +1,59 @@ +# TODO List + +## Planned + +- [ ] Player HUD +- [ ] Magic/Weapon/Melee attacks +- [ ] Action interface to extract logic from system +- [ ] Action trees to build complex branching behaviour +- [ ] Add player detection to trigger actions +- [ ] Extend ActionComponent to support multiple schedules +- [ ] Wander action +- [ ] WanderTo action +- [ ] WalkShape action? +- [ ] Skill training system +- [ ] Interaction system for talking and looting +- [ ] Inventory system +- [ ] Shops +- [ ] Weather +- [ ] Generate new areas / NPCs +- [ ] Multiverse +- [ ] Time dilation? +- [ ] Multiplayer? + +## v0.5.0 Dev QoL (WIP) + +- [x] Scale speed system with global scale +- [x] Split character utils and action system +- [x] Move spawn points to map +- [x] Move NPC path to map +- [x] Fix NPC movement animations +- [x] Add character shadows + +## v0.4.0 NPC + +- [x] Add an NPC +- [x] Add character system + +## v0.3.0 Gotta go fast + +- [x] Add sprint to character controls +- [x] Fix window resizing with scaling + +## v0.2.0 + +- [x] Add collision system + +## v0.1.0 + +- [x] Bundle assets in binary + +## v0.0.0 + +- [x] Add map +- [x] Add camera +- [x] Add player character +- [x] Add movement for player character +- [x] Animate player character +- [x] Follow player character with camera +- [x] Animate tiles using tilemap data diff --git a/assets/spritesheets/LightShadow_pipo.png b/assets/spritesheets/LightShadow_pipo.png new file mode 100644 index 0000000..8e9af70 Binary files /dev/null and b/assets/spritesheets/LightShadow_pipo.png differ diff --git a/assets/tilemaps/fantasy1-min.tmx b/assets/tilemaps/fantasy1-min.tmx index 2435dd5..cdc5157 100644 --- a/assets/tilemaps/fantasy1-min.tmx +++ b/assets/tilemaps/fantasy1-min.tmx @@ -1 +1 @@ -eJztzzEOQEAQRuHZBhUq3P8QqKwKxzKJK2yy/8grXv3yNWbWBq/zem8I3ohDKhxa4dAKh1Y4tMKhFY6vNZlthdpTPcfh71yoEwcOHDhw4MCBAwcOHDhwhHFc/r4L9VR0qIRDKxxa4dAKh1Y4tMKh1Z8ckzcHb/FespqnHA==eJzt00EOQDAQheHpoZST4WS4WK1NQ0MaFrVphv9LXsTuTV4qAgAAAAAAvs5rWk1Xu8hLqb93IoN+G2fznl72/nnGmqUKxS3SDnniLlY2edrC2iaTZpX7G4JmqVet2BfeRxQ3meXcJRz/lra4SvdY7Q8AAAAAAP5nA6d3HVQ=eJztxUENADAIBLDDv9qhABmMpP004Uddyat7AwAAAAAAAAAAbBngCSuUeJzt0TEKgDAUBNFs7n9R7fQEamETsRACzocZkLX84aW31s8vxZdww4y9/6s2eqz5+6LvLXl67AXfsUUPUnqw0oOVHqz0YKUHKz1Y6cFKD1Z6sNKDlR6s9GClBys9WOnBSg9WerDSg5UerPRg9eZxva/ajh7Vl3DDjD0ALV+BYA== +eJztzzEOQEAQRuHZBhUq3P8QqKwKxzKJK2yy/8grXv3yNWbWBq/zem8I3ohDKhxa4dAKh1Y4tMKhFY6vNZlthdpTPcfh71yoEwcOHDhw4MCBAwcOHDhwhHFc/r4L9VR0qIRDKxxa4dAKh1Y4tMKh1Z8ckzcHb/FespqnHA==eJzt00EKgCAUhOHnobJOVp2sulitU1IyocA28uT/YDau5jEoAgAAAAAAWmZd+pChcpc/Yn9rRCa50hl994xy988zV+xVwm+R7pDH76Jhk68tNG3Syh2LyyHvN+wuW7V2ZVr4557fZJXnLnt407JFKt6jtT8AAAAAAChzAloGJik=eJztxUENADAIBLDDv9qhABmMpP004Uddyat7AwAAAAAAAAAAbBngCSuUeJzt0TEKgDAUBNFs7n9R7fQEamETsRACzocZkLX84aW31s8vxZdww4y9/6s2eqz5+6LvLXl67AXfsUUPUnqw0oOVHqz0YKUHKz1Y6cFKD1Z6sNKDlR6s9GClBys9WOnBSg9WerDSg5UerPRg9eZxva/ajh7Vl3DDjD0ALV+BYA== diff --git a/assets/tilemaps/fantasy1.tmx b/assets/tilemaps/fantasy1.tmx index a8c3d62..738cc1d 100644 --- a/assets/tilemaps/fantasy1.tmx +++ b/assets/tilemaps/fantasy1.tmx @@ -1,5 +1,5 @@ - + @@ -14,7 +14,7 @@ - eJzt00EOQDAQheHpoZST4WS4WK1NQ0MaFrVphv9LXsTuTV4qAgAAAAAAvs5rWk1Xu8hLqb93IoN+G2fznl72/nnGmqUKxS3SDnniLlY2edrC2iaTZpX7G4JmqVet2BfeRxQ3meXcJRz/lra4SvdY7Q8AAAAAAP5nA6d3HVQ= + eJzt00EKgCAUhOHnobJOVp2sulitU1IyocA28uT/YDau5jEoAgAAAAAAWmZd+pChcpc/Yn9rRCa50hl994xy988zV+xVwm+R7pDH76Jhk68tNG3Syh2LyyHvN+wuW7V2ZVr4557fZJXnLnt407JFKt6jtT8AAAAAAChzAloGJik= @@ -27,30 +27,96 @@ eJzt0TEKgDAUBNFs7n9R7fQEamETsRACzocZkLX84aW31s8vxZdww4y9/6s2eqz5+6LvLXl67AXfsUUPUnqw0oOVHqz0YKUHKz1Y6cFKD1Z6sNKDlR6s9GClBys9WOnBSg9WerDSg5UerPRg9eZxva/ajh7Vl3DDjD0ALV+BYA== - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/tilesets/BaseChip.tsx b/assets/tilesets/BaseChip.tsx index ed0f019..e882d23 100644 --- a/assets/tilesets/BaseChip.tsx +++ b/assets/tilesets/BaseChip.tsx @@ -1,53 +1,4 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/tilesets/Water1.tsx b/assets/tilesets/Water1.tsx index 0247ccc..bb5336e 100644 --- a/assets/tilesets/Water1.tsx +++ b/assets/tilesets/Water1.tsx @@ -1,591 +1,4567 @@ - + - - - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scenes/game/constants.go b/scenes/game/constants.go index 516145e..e296c5f 100644 --- a/scenes/game/constants.go +++ b/scenes/game/constants.go @@ -5,5 +5,10 @@ const ( tilemapURL string = "tilemaps/fantasy1-min.tmx" ) +const ( + PlayerSpawnName = "PlayerSpawn" + NPCSpawnName = "NPCSpawn" +) + // SceneType is the unique type identifier for Scene. const SceneType string = "GameScene" diff --git a/scenes/game/scene.go b/scenes/game/scene.go index 149e082..30455f8 100644 --- a/scenes/game/scene.go +++ b/scenes/game/scene.go @@ -23,6 +23,7 @@ func (g *Scene) Preload() { files := []string{ "spritesheets/Male 18-1.png", "spritesheets/Female 24-1.png", + "spritesheets/LightShadow_pipo.png", "tilesets/BaseChip.png", "tilesets/Dirt1.png", "tilesets/Grass1-Dirt1.png", @@ -53,41 +54,72 @@ func (g *Scene) Setup(u engo.Updater) { } speedSystem.Level = tilemap.Level + playerSpawn, ok := tilemap.Spawns[PlayerSpawnName] + if !ok { + log.Println("no player spawn found in tilemap") + } + player, err := util.NewCharacter(util.NewCharacterOptions{ - Position: engo.Point{X: 800, Y: 600}, + Position: playerSpawn.Position, SpritesheetURL: spritesheetURL, CellWidth: 32, CellHeight: 32, + CollisionGroup: util.CollisionPlayer, AnimationRate: 0.1, StartZIndex: 3, }) if err != nil { - log.Printf("Failed to create Player entity, error: %s\n", err) + log.Printf("failed to create Player entity, error: %s\n", err) } - player.CollisionComponent.Main = 1 player.ControlComponent.Enabled = true + playerShadow, err := util.NewCharacterShadow(player) + if err != nil { + log.Printf("failed to create Shadow entity, error: %s\n", err) + } + player.BasicEntity.AppendChild(playerShadow.GetBasicEntity()) + + npcSpawn, ok := tilemap.Spawns[NPCSpawnName] + if !ok { + log.Println("no npc spawn found in tilemap") + } + npc, err := util.NewCharacter(util.NewCharacterOptions{ - Position: engo.Point{X: 800, Y: 568}, + Position: npcSpawn.Position, SpritesheetURL: "spritesheets/Female 24-1.png", CellWidth: 32, CellHeight: 32, + CollisionGroup: util.CollisionEntity, AnimationRate: 0.1, StartZIndex: 3, }) if err != nil { log.Printf("Failed to create NPC entity, error: %s\n", err) } - npc.CollisionComponent.Main = 1 - npc.CollisionComponent.Group = 1 npc.ActionComponent.Schedule = action.Schedule{ Actions: []action.Action{ - {Type: action.ActWalkTo, Point: engo.Point{X: 900, Y: 600}}, - {Type: action.ActWalkTo, Point: engo.Point{X: 700, Y: 600}}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint1"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint2"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint3"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint4"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint5"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint6"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint7"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint8"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint9"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint10"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint11"].Position}, + {Type: action.ActWalkTo, Point: tilemap.Points["NPCPoint12"].Position}, }, Loop: true, } + npcShadow, err := util.NewCharacterShadow(npc) + if err != nil { + log.Printf("failed to create Shadow entity, error: %s\n", err) + } + npc.BasicEntity.AppendChild(npcShadow.GetBasicEntity()) + entityScroller := &common.EntityScroller{ SpaceComponent: &player.SpaceComponent, TrackingBounds: tilemap.Level.Bounds(), @@ -105,7 +137,9 @@ func (g *Scene) Setup(u engo.Updater) { tilemap.AddTilesToWorld(g.World) g.World.AddEntity(player) + g.World.AddEntity(playerShadow) g.World.AddEntity(npc) + g.World.AddEntity(npcShadow) engo.Mailbox.Listen("WindowResizeMessage", func(msg engo.Message) { offsetX, offsetY := engo.GameWidth()/2, engo.GameHeight()/2 diff --git a/scenes/game/variables.go b/scenes/game/variables.go index 5828e14..2663b63 100644 --- a/scenes/game/variables.go +++ b/scenes/game/variables.go @@ -5,12 +5,13 @@ import ( "github.com/eth0net/magicgame/systems/action" "github.com/eth0net/magicgame/systems/control" "github.com/eth0net/magicgame/systems/speed" + "github.com/eth0net/magicgame/util" ) // Systems for scene. var ( animationSystem = &common.AnimationSystem{} - collisionSystem = &common.CollisionSystem{Solids: 1} + collisionSystem = &common.CollisionSystem{Solids: util.CollisionWorld | util.CollisionPlayer | util.CollisionEntity} renderSystem = &common.RenderSystem{} actionSystem = &action.ActionSystem{} controlSystem = &control.ControlSystem{} diff --git a/systems/action/action.go b/systems/action/action.go index 3837dc2..e998c05 100644 --- a/systems/action/action.go +++ b/systems/action/action.go @@ -45,12 +45,14 @@ const ( // FollowPath // FollowEntity // FollowSpaceComponent + // Wander/WanderTo + // Roll + // Jump // Interact // Attack // Defend // Magic - // Jump - // Anything else + // Anything else? ) // An Action defines a single act for a Entity. diff --git a/systems/action/entity.go b/systems/action/entity.go index 91125e8..0f123fc 100644 --- a/systems/action/entity.go +++ b/systems/action/entity.go @@ -1,6 +1,8 @@ package action import ( + "math" + "github.com/EngoEngine/ecs" "github.com/EngoEngine/engo" "github.com/EngoEngine/engo/common" @@ -26,35 +28,37 @@ func (ce *actionEntity) setAnimation() { newAnimationName := currentAnimation.Name var ( - xIsNegative bool = point.X < 0 - xIsPositive bool = point.X > 0 - xIsZero bool = point.X == 0 + xIsNegative bool = math.Round((float64(point.X)*100)/100) < 0 + xIsPositive bool = math.Round((float64(point.X)*100)/100) > 0 + xIsZero bool = !xIsNegative && !xIsPositive + + yIsNegative bool = math.Round((float64(point.Y)*100)/100) < 0 + yIsPositive bool = math.Round((float64(point.Y)*100)/100) > 0 + yIsZero bool = !yIsNegative && !yIsPositive - yIsNegative bool = point.Y < 0 - yIsPositive bool = point.Y > 0 - yIsZero bool = point.Y == 0 + yIsBigger bool = math.Abs(float64(point.Y)) > math.Abs(float64(point.X)) ) switch { + case xIsNegative: + newAnimationName = AnimationMoveLeft + case xIsPositive: + newAnimationName = AnimationMoveRight + case yIsBigger && yIsNegative: + newAnimationName = AnimationMoveUp + case yIsBigger && yIsPositive: + newAnimationName = AnimationMoveDown case xIsZero && yIsZero: switch currentAnimation.Name { - case AnimationMoveUp: - newAnimationName = AnimationStopUp - case AnimationMoveDown: - newAnimationName = AnimationStopDown case AnimationMoveLeft: newAnimationName = AnimationStopLeft case AnimationMoveRight: newAnimationName = AnimationStopRight + case AnimationMoveUp: + newAnimationName = AnimationStopUp + case AnimationMoveDown: + newAnimationName = AnimationStopDown } - case xIsZero && yIsNegative: - newAnimationName = AnimationMoveUp - case xIsZero && yIsPositive: - newAnimationName = AnimationMoveDown - case xIsNegative: - newAnimationName = AnimationMoveLeft - case xIsPositive: - newAnimationName = AnimationMoveRight } if currentAnimation.Name != newAnimationName { diff --git a/util/character.go b/util/character.go index 32fcf90..34c4e0a 100644 --- a/util/character.go +++ b/util/character.go @@ -29,6 +29,7 @@ type NewCharacterOptions struct { Position engo.Point SpritesheetURL string CellWidth, CellHeight int + CollisionGroup common.CollisionGroup AnimationRate float32 StartZIndex float32 } @@ -57,7 +58,8 @@ func NewCharacter(o NewCharacterOptions) (p *Character, err error) { p.AnimationComponent.AddDefaultAnimation(CharacterAnimations[5]) } - p.CollisionComponent.Group = 1 + p.CollisionComponent.Main = CollisionWorld | CollisionPlayer | CollisionEntity + p.CollisionComponent.Group = o.CollisionGroup p.SpaceComponent = common.SpaceComponent{ Position: o.Position, Width: float32(o.CellWidth), diff --git a/util/character_shadow.go b/util/character_shadow.go new file mode 100644 index 0000000..0a5b8d3 --- /dev/null +++ b/util/character_shadow.go @@ -0,0 +1,37 @@ +package util + +import ( + "fmt" + + "github.com/EngoEngine/ecs" + "github.com/EngoEngine/engo/common" +) + +const shadowSpritesheetURL = "spritesheets/LightShadow_pipo.png" + +// Shadow entity is an entity shadow. +type Shadow struct { + ecs.BasicEntity + common.RenderComponent + common.SpaceFace +} + +func NewCharacterShadow(character *Character) (*Shadow, error) { + shadowSpritesheet := common.NewSpritesheetFromFile( + shadowSpritesheetURL, 32, 32, + ) + if shadowSpritesheet == nil { + return nil, fmt.Errorf("failed to load shadow spritesheet with url %v", shadowSpritesheetURL) + } + + shadow := &Shadow{ + BasicEntity: ecs.NewBasic(), + RenderComponent: common.RenderComponent{ + Drawable: shadowSpritesheet.Drawable(3), + StartZIndex: 2, + }, + SpaceFace: character, + } + + return shadow, nil +} diff --git a/util/character_test.go b/util/character_test.go index e39039f..6a5aca8 100644 --- a/util/character_test.go +++ b/util/character_test.go @@ -18,7 +18,7 @@ func TestNewCharacter(t *testing.T) { Name: "DefaultOptions", Options: NewCharacterOptions{}, Expected: &Character{ - CollisionComponent: common.CollisionComponent{Group: 1}, + CollisionComponent: common.CollisionComponent{Main: CollisionWorld | CollisionPlayer | CollisionEntity}, ControlComponent: control.ControlComponent{ Vertical: control.AxisVertical, Horizontal: control.AxisHorizontal, diff --git a/util/collisions.go b/util/collisions.go new file mode 100644 index 0000000..b0a8f3f --- /dev/null +++ b/util/collisions.go @@ -0,0 +1,9 @@ +package util + +import "github.com/EngoEngine/engo/common" + +const ( + CollisionWorld common.CollisionGroup = 1 << iota + CollisionPlayer + CollisionEntity +) diff --git a/util/tilemap.go b/util/tilemap.go index ac81e89..a7b450c 100644 --- a/util/tilemap.go +++ b/util/tilemap.go @@ -1,8 +1,8 @@ package util import ( + "fmt" "log" - "strconv" "github.com/EngoEngine/ecs" "github.com/EngoEngine/engo" @@ -28,21 +28,32 @@ type Object struct { // A Tilemap entity stores the // data for a single Tiled map. type Tilemap struct { - Level *common.Level - Tiles []*Tile + Level *common.Level + + // Tiles contains all tiles from the map. + Tiles []*Tile + + // Objects contains all objects from the map. Objects []*Object + + // Points contains objects of type Point. + Points map[string]*Object + + // Spawns contains objects of type Spawn. + Spawns map[string]*Object } // NewTilemap constructs a new Tilemap from the provided file url. func NewTilemap(url string) (tm *Tilemap, err error) { resource, err := engo.Files.Resource(url) if err != nil { - return nil, err + return nil, fmt.Errorf("error getting resource: %w", err) } tm = &Tilemap{ - Level: resource.(common.TMXResource).Level, - Tiles: []*Tile{}, + Level: resource.(common.TMXResource).Level, + Points: map[string]*Object{}, + Spawns: map[string]*Object{}, } for idx, layer := range tm.Level.TileLayers { @@ -57,11 +68,13 @@ func NewTilemap(url string) (tm *Tilemap, err error) { } t.RenderComponent = common.RenderComponent{ Drawable: tile.Image, - Scale: engo.Point{X: 1, Y: 1}, StartZIndex: float32(idx), } t.SpaceComponent = common.SpaceComponent{ Position: tile.Point, + Width: float32(tm.Level.TileWidth), + Height: float32(tm.Level.TileHeight), + Rotation: tile.Rotation, } tm.Tiles = append(tm.Tiles, t) } @@ -72,43 +85,42 @@ func NewTilemap(url string) (tm *Tilemap, err error) { o := &Object{BasicEntity: ecs.NewBasic()} o.SpaceComponent = common.SpaceComponent{ Position: engo.Point{X: object.X, Y: object.Y}, - Width: 32, - Height: 32, + Width: object.Width, + Height: object.Height, } - var collision bool - for _, property := range layer.Properties { - if property.Name != "Collision" { - continue - } - collision, _ = strconv.ParseBool(property.Value) - } - if collision { - s := common.Shape{} - for _, tmxLine := range object.Lines { - for _, line := range tmxLine.Lines { - l := engo.Line{ - P1: engo.Point{ - X: line.P1.X - object.X, - Y: line.P1.Y - object.Y, - }, - P2: engo.Point{ - X: line.P2.X - object.X, - Y: line.P2.Y - object.Y, - }, - } - s.Lines = append(s.Lines, l) + shape := common.Shape{} + for _, tmxLine := range object.Lines { + for _, line := range tmxLine.Lines { + l := engo.Line{ + P1: engo.Point{ + X: line.P1.X - object.X, + Y: line.P1.Y - object.Y, + }, + P2: engo.Point{ + X: line.P2.X - object.X, + Y: line.P2.Y - object.Y, + }, } + shape.Lines = append(shape.Lines, l) } - o.AddShape(s) - o.CollisionComponent.Group = 1 + } + o.SpaceComponent.AddShape(shape) + + switch object.Type { + case "Collision": + o.CollisionComponent.Group = CollisionWorld + case "Point": + tm.Points[object.Name] = o + case "Spawn": + tm.Spawns[object.Name] = o } tm.Objects = append(tm.Objects, o) } } - return tm, err + return tm, nil } // AddTilesToWorld adds each Tile entity to the given world.