Skip to content

Commit

Permalink
add production animation
Browse files Browse the repository at this point in the history
  • Loading branch information
mlange-42 committed Feb 24, 2024
1 parent 128d52d commit feef10e
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 19 deletions.
Binary file added artwork/sprites/flat_48x24/food/food.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added artwork/sprites/flat_48x24/food/food.xcf
Binary file not shown.
Binary file added artwork/sprites/flat_48x24/stones/stones.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added artwork/sprites/flat_48x24/stones/stones.xcf
Binary file not shown.
Binary file added artwork/sprites/flat_48x24/wood/wood.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added artwork/sprites/flat_48x24/wood/wood.xcf
Binary file not shown.
53 changes: 37 additions & 16 deletions assets/sprites/flat_48x24.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,113 +3,134 @@
"SpriteHeight": 24,
"Sprites": [
{
"Name": "path",
"Name": "food",
"Index": 0,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path",
"Index": 1,
"Height": 0,
"YOffset": 0,
"MultiTile": true
},
{
"Name": "path_1",
"Index": 1,
"Index": 2,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_2",
"Index": 2,
"Index": 3,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_3",
"Index": 3,
"Index": 4,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_4",
"Index": 4,
"Index": 5,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_5",
"Index": 5,
"Index": 6,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_6",
"Index": 6,
"Index": 7,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_7",
"Index": 7,
"Index": 8,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_8",
"Index": 8,
"Index": 9,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_9",
"Index": 9,
"Index": 10,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_10",
"Index": 10,
"Index": 11,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_11",
"Index": 11,
"Index": 12,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_12",
"Index": 12,
"Index": 13,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_13",
"Index": 13,
"Index": 14,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_14",
"Index": 14,
"Index": 15,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "path_15",
"Index": 15,
"Index": 16,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "stones",
"Index": 17,
"Height": 0,
"YOffset": 0,
"MultiTile": false
},
{
"Name": "wood",
"Index": 18,
"Height": 0,
"YOffset": 0,
"MultiTile": false
Expand Down
Binary file modified assets/sprites/flat_48x24.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions game/comp/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ type Consumption struct {
Amount int
Countdown int
}

type ProductionMarker struct {
StartTick int64
Resource resource.Resource
}
96 changes: 96 additions & 0 deletions game/render/markers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package render

import (
"image"

"github.com/hajimehoshi/ebiten/v2"
ares "github.com/mlange-42/arche-model/resource"
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
"github.com/mlange-42/tiny-world/game/comp"
"github.com/mlange-42/tiny-world/game/res"
"github.com/mlange-42/tiny-world/game/resource"
)

// Markers is a system to render production markers.
type Markers struct {
MinOffset int
MaxOffset int
Duration int

time generic.Resource[ares.Tick]
screen generic.Resource[res.EbitenImage]
sprites generic.Resource[res.Sprites]
view generic.Resource[res.View]

filter generic.Filter2[comp.Tile, comp.ProductionMarker]

resources [resource.EndResources]int
}

// InitializeUI the system
func (s *Markers) InitializeUI(world *ecs.World) {
s.time = generic.NewResource[ares.Tick](world)
s.screen = generic.NewResource[res.EbitenImage](world)
s.sprites = generic.NewResource[res.Sprites](world)
s.view = generic.NewResource[res.View](world)

s.filter = *generic.NewFilter2[comp.Tile, comp.ProductionMarker]()

sprites := s.sprites.Get()
for i := resource.Resource(0); i < resource.EndResources; i++ {
s.resources[i] = sprites.GetIndex(resource.Properties[i].Name)
}
}

// UpdateUI the system
func (s *Markers) UpdateUI(world *ecs.World) {
tick := s.time.Get().Tick
sprites := s.sprites.Get()
view := s.view.Get()
canvas := s.screen.Get()
img := canvas.Image

off := view.Offset()
bounds := view.Bounds(canvas.Width, canvas.Height)

op := ebiten.DrawImageOptions{}
op.Blend = ebiten.BlendSourceOver
if view.Zoom < 1 {
op.Filter = ebiten.FilterLinear
}

halfWidth := view.TileWidth / 2

drawCursor := func(point *image.Point, cursor int) {
sp, info := sprites.Get(cursor)
h := sp.Bounds().Dy() - view.TileHeight

op.GeoM.Reset()
op.GeoM.Scale(view.Zoom, view.Zoom)
op.GeoM.Translate(
float64(point.X-halfWidth)*view.Zoom-float64(off.X),
float64(point.Y-h-info.YOffset)*view.Zoom-float64(off.Y),
)
img.DrawImage(sp, &op)
}

query := s.filter.Query(world)
for query.Next() {
tile, mark := query.Get()
point := view.TileToGlobal(tile.X, tile.Y)
if !point.In(bounds) {
continue
}
passed := tick - mark.StartTick
off := s.MinOffset + (s.MaxOffset-s.MinOffset)*int(passed)/s.Duration
point.Y -= off
drawCursor(&point, s.resources[mark.Resource])
}
}

// PostUpdateUI the system
func (s *Markers) PostUpdateUI(world *ecs.World) {}

// FinalizeUI the system
func (s *Markers) FinalizeUI(world *ecs.World) {}
24 changes: 21 additions & 3 deletions game/sys/do_production.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/mlange-42/arche/generic"
"github.com/mlange-42/tiny-world/game/comp"
"github.com/mlange-42/tiny-world/game/res"
"github.com/mlange-42/tiny-world/game/resource"
)

// DoProduction system.
Expand All @@ -14,7 +15,9 @@ type DoProduction struct {
update generic.Resource[res.UpdateInterval]
stock generic.Resource[res.Stock]

filter generic.Filter2[comp.UpdateTick, comp.Production]
filter generic.Filter3[comp.Tile, comp.UpdateTick, comp.Production]
markerBuilder generic.Map2[comp.Tile, comp.ProductionMarker]
toCreate []markerEntry
}

// Initialize the system
Expand All @@ -23,7 +26,8 @@ func (s *DoProduction) Initialize(world *ecs.World) {
s.update = generic.NewResource[res.UpdateInterval](world)
s.stock = generic.NewResource[res.Stock](world)

s.filter = *generic.NewFilter2[comp.UpdateTick, comp.Production]()
s.filter = *generic.NewFilter3[comp.Tile, comp.UpdateTick, comp.Production]()
s.markerBuilder = generic.NewMap2[comp.Tile, comp.ProductionMarker](world)
}

// Update the system
Expand All @@ -35,7 +39,7 @@ func (s *DoProduction) Update(world *ecs.World) {

query := s.filter.Query(world)
for query.Next() {
up, pr := query.Get()
tile, up, pr := query.Get()

if up.Tick != tickMod {
continue
Expand All @@ -44,9 +48,23 @@ func (s *DoProduction) Update(world *ecs.World) {
if pr.Countdown < 0 {
pr.Countdown += update.Countdown
stock.Res[pr.Type]++
s.toCreate = append(s.toCreate, markerEntry{Tile: *tile, Resource: pr.Type})
}
}

for _, entry := range s.toCreate {
s.markerBuilder.NewWith(
&entry.Tile,
&comp.ProductionMarker{StartTick: tick, Resource: entry.Resource},
)
}
s.toCreate = s.toCreate[:0]
}

// Finalize the system
func (s *DoProduction) Finalize(world *ecs.World) {}

type markerEntry struct {
Tile comp.Tile
Resource resource.Resource
}
46 changes: 46 additions & 0 deletions game/sys/remove_markers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package sys

import (
ares "github.com/mlange-42/arche-model/resource"
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
"github.com/mlange-42/tiny-world/game/comp"
)

// RemoveMarkers system.
type RemoveMarkers struct {
MaxTime int64

time generic.Resource[ares.Tick]
filter generic.Filter1[comp.ProductionMarker]

toRemove []ecs.Entity
}

// Initialize the system
func (s *RemoveMarkers) Initialize(world *ecs.World) {
s.time = generic.NewResource[ares.Tick](world)

s.filter = *generic.NewFilter1[comp.ProductionMarker]()
}

// Update the system
func (s *RemoveMarkers) Update(world *ecs.World) {
tick := s.time.Get().Tick

query := s.filter.Query(world)
for query.Next() {
mark := query.Get()
if tick > mark.StartTick+s.MaxTime {
s.toRemove = append(s.toRemove, query.Entity())
}
}

for _, e := range s.toRemove {
world.RemoveEntity(e)
}
s.toRemove = s.toRemove[:0]
}

// Finalize the system
func (s *RemoveMarkers) Finalize(world *ecs.World) {}
8 changes: 8 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ func main() {
g.Model.AddSystem(&sys.DoProduction{})
g.Model.AddSystem(&sys.DoConsumption{})
g.Model.AddSystem(&sys.UpdateStats{})
g.Model.AddSystem(&sys.RemoveMarkers{
MaxTime: 180,
})

g.Model.AddSystem(&sys.Build{
AllowStroke: true,
Expand All @@ -85,6 +88,11 @@ func main() {

g.Model.AddUISystem(&render.CenterView{})
g.Model.AddUISystem(&render.Terrain{})
g.Model.AddUISystem(&render.Markers{
MinOffset: view.TileHeight * 2,
MaxOffset: 250,
Duration: 180,
})
g.Model.AddUISystem(&render.UI{})

// =========== Run ===========
Expand Down

0 comments on commit feef10e

Please sign in to comment.