mirror of
https://github.com/cbeimers113/strands.git
synced 2025-12-23 23:27:42 -05:00
Optimize chem quantities tracker and highlighting
This commit is contained in:
9
TODO.md
9
TODO.md
@@ -1,11 +1,10 @@
|
||||
### v0.2.2:
|
||||
|
||||
- [ ] Fix bug with conservation of mass (water)
|
||||
- [ ] Fix mouse jittering bug when going in and out of menus
|
||||
- [ ] Revisit tile highlighting
|
||||
- [ ] Pipeline improvements / build & release binaries / auto-tagging
|
||||
- [ ] Skybox
|
||||
- [ ] Shadows
|
||||
- [ ] Skybox
|
||||
- [ ] Pipeline improvements / build & release binaries / auto-tagging
|
||||
- [x] Real object highlighting instead of wireframe
|
||||
- [x] Optimize chemical quantities tracker
|
||||
|
||||
### v0.3.0 - Plants Upgrade:
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"cbeimers113/strands/internal/graphics"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
@@ -42,6 +43,12 @@ func RemoveEntity(entity Entity, entities map[int]Entity, scene *core.Node) {
|
||||
// Highlight or unhighlight an entity
|
||||
func Highlight(entity Entity, highlight bool) {
|
||||
if mat := entity.Material(); mat != nil {
|
||||
mat.SetWireframe(highlight)
|
||||
tex := graphics.Textures[graphics.TexHighlight]
|
||||
|
||||
if highlight && !mat.HasTexture(tex) {
|
||||
mat.AddTexture(tex)
|
||||
} else if !highlight && mat.HasTexture(tex) {
|
||||
mat.RemoveTexture(tex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,11 +123,6 @@ func (t *Tile) doWaterSpread() {
|
||||
}
|
||||
}
|
||||
|
||||
// Shuffle the lower neighbours to give some randomness to flow direction
|
||||
t.Rand.Shuffle(len(lowerNeighbours), func(i, j int) {
|
||||
lowerNeighbours[i], lowerNeighbours[j] = lowerNeighbours[j], lowerNeighbours[i]
|
||||
})
|
||||
|
||||
// Distribute water to lower neighbours
|
||||
for len(lowerNeighbours) > 0 {
|
||||
var neighbour *Tile
|
||||
@@ -144,12 +139,9 @@ func (t *Tile) doWaterSpread() {
|
||||
break
|
||||
}
|
||||
|
||||
// Add d/n litres of water to the neighbour, where d is the elevation difference and n is the number of lower neighbours
|
||||
delta := chem.CubicMetresToLitres(t.getElevation().Value-neighbour.getElevation().Value) / float32(len(lowerNeighbours))
|
||||
|
||||
if δ := neighbour.AddWater(delta - t.AddWater(-delta)); δ != 0 {
|
||||
// TODO: This shouldn't ever be 0, but do something if it is
|
||||
println(δ)
|
||||
}
|
||||
neighbour.AddWater(delta - t.AddWater(-delta))
|
||||
|
||||
// Remove neighbour from lowerNeighbours
|
||||
for i, nb := range lowerNeighbours {
|
||||
|
||||
@@ -202,7 +202,7 @@ func (g *Game) Start() {
|
||||
g.gui.Refresh()
|
||||
|
||||
// Spin camera in main menu and any sub-views in the main menu
|
||||
if g.State.InMainMenu() {
|
||||
if g.State.InSpinMenu() {
|
||||
if !g.camSpin {
|
||||
p := g.Cam.Position()
|
||||
g.camSpin = true
|
||||
|
||||
@@ -17,13 +17,14 @@ const (
|
||||
TexCursor = "cursor"
|
||||
|
||||
// World
|
||||
TexDirt = "dirt"
|
||||
TexGrass = "grass"
|
||||
TexSand = "sand"
|
||||
TexSeed = "seed"
|
||||
TexStalk = "stalk"
|
||||
TexStone = "stone"
|
||||
TexWater = "water"
|
||||
TexHighlight = "highlight"
|
||||
TexDirt = "dirt"
|
||||
TexGrass = "grass"
|
||||
TexSand = "sand"
|
||||
TexSeed = "seed"
|
||||
TexStalk = "stalk"
|
||||
TexStone = "stone"
|
||||
TexWater = "water"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -32,6 +33,8 @@ var (
|
||||
//go:embed textures/gui/cursor.png
|
||||
bytesCursor []byte
|
||||
|
||||
//go:embed textures/world/highlight.png
|
||||
bytesHighlight []byte
|
||||
//go:embed textures/world/dirt.png
|
||||
bytesDirt []byte
|
||||
//go:embed textures/world/grass.png
|
||||
@@ -60,6 +63,7 @@ func LoadTextures() {
|
||||
{id: TexMenuLogo, data: bytesMenuLogo},
|
||||
{id: TexCursor, data: bytesCursor},
|
||||
|
||||
{id: TexHighlight, data: bytesHighlight},
|
||||
{id: TexDirt, data: bytesDirt},
|
||||
{id: TexGrass, data: bytesGrass},
|
||||
{id: TexSand, data: bytesSand},
|
||||
|
||||
BIN
internal/graphics/textures/world/highlight.png
Normal file
BIN
internal/graphics/textures/world/highlight.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -171,7 +171,7 @@ func (g *Gui) registerConfigMenu() {
|
||||
})
|
||||
g.Scene.Add(g.exitButton)
|
||||
|
||||
g.State.SetInMainMenu(true)
|
||||
g.State.SetInSpinMenu(true)
|
||||
},
|
||||
|
||||
close: func() {
|
||||
|
||||
@@ -159,7 +159,7 @@ func (g *Gui) registerMainMenu() {
|
||||
})
|
||||
g.Scene.Add(g.exitButton)
|
||||
|
||||
g.State.SetInMainMenu(true)
|
||||
g.State.SetInSpinMenu(true)
|
||||
},
|
||||
|
||||
close: func() {
|
||||
@@ -177,7 +177,7 @@ func (g *Gui) registerMainMenu() {
|
||||
g.Scene.Remove(g.exitButton)
|
||||
g.Scene.Remove(g.popup)
|
||||
|
||||
g.State.SetInMainMenu(false)
|
||||
g.State.SetInSpinMenu(false)
|
||||
},
|
||||
|
||||
refresh: func() {
|
||||
|
||||
@@ -149,6 +149,7 @@ func (i *InputManager) MouseDown(evname string, ev interface{}) {
|
||||
switch me.Button {
|
||||
case window.MouseButton1:
|
||||
tile.AddWater(chem.CubicMetresToLitres(1))
|
||||
i.State.Quantities[chem.Water].Value += 1
|
||||
case window.MouseButton2:
|
||||
gui.Open(gui.TileContextMenu, false)
|
||||
}
|
||||
|
||||
@@ -15,18 +15,18 @@ import (
|
||||
type State struct {
|
||||
tps int // Record the number of world ticks per second
|
||||
inMenu bool // Whether the player is in a menu and everything in the simulation is frozen, including the player
|
||||
inMainMenu bool // Whether the main menu is open
|
||||
inSpinMenu bool // Whether we're in a menu where we want the camera to spin
|
||||
paused bool // Whether the simulation physics are paused, but the player can still interact with the simulation
|
||||
moving bool // Whether the player is moving
|
||||
fastMove bool // Whether the player is using fast movement
|
||||
showChems bool // Whether to show the levels of each chemical in the simulation
|
||||
|
||||
Seed int64 // The world's random seed value
|
||||
Rand *rand.Rand // The simulation's psuedo random number generator
|
||||
Clock *Clock // Keep track of in-game time
|
||||
LookingAt entity.Entity // What the camera/player is looking at
|
||||
Entities map[int]entity.Entity // List of entities in the game world
|
||||
Quantities map[chem.ElementType]chem.Quantity // Map of quantities for tracking various substances in the simulation
|
||||
Seed int64 // The world's random seed value
|
||||
Rand *rand.Rand // The simulation's psuedo random number generator
|
||||
Clock *Clock // Keep track of in-game time
|
||||
LookingAt entity.Entity // What the camera/player is looking at
|
||||
Entities map[int]entity.Entity // List of entities in the game world
|
||||
Quantities map[chem.ElementType]*chem.Quantity // Map of quantities for tracking various substances in the simulation
|
||||
}
|
||||
|
||||
func New(cfg *config.Config, seed int64) *State {
|
||||
@@ -37,7 +37,7 @@ func New(cfg *config.Config, seed int64) *State {
|
||||
Rand: rand.New(rand.NewSource(seed)),
|
||||
Clock: NewClock(cfg, 9, 00, true),
|
||||
Entities: make(map[int]entity.Entity),
|
||||
Quantities: make(map[string]chem.Quantity),
|
||||
Quantities: make(map[string]*chem.Quantity),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,10 +53,10 @@ func (s *State) SetInMenu(inMenu bool) {
|
||||
s.inMenu = inMenu
|
||||
}
|
||||
|
||||
// Set the inMainMenu state
|
||||
func (s *State) SetInMainMenu(inMainMenu bool) {
|
||||
s.inMainMenu = inMainMenu
|
||||
s.SetInMenu(inMainMenu)
|
||||
// Set the inSpinMenu state
|
||||
func (s *State) SetInSpinMenu(inSpinMenu bool) {
|
||||
s.inSpinMenu = inSpinMenu
|
||||
s.SetInMenu(inSpinMenu)
|
||||
}
|
||||
|
||||
// Set the paused state
|
||||
@@ -91,9 +91,9 @@ func (s State) InMenu() bool {
|
||||
return s.inMenu
|
||||
}
|
||||
|
||||
// Get the inMainMenu state
|
||||
func (s State) InMainMenu() bool {
|
||||
return s.inMainMenu
|
||||
// Get the inSpinMenu state
|
||||
func (s State) InSpinMenu() bool {
|
||||
return s.inSpinMenu
|
||||
}
|
||||
|
||||
// Get the paused state
|
||||
|
||||
@@ -67,11 +67,13 @@ func Load(ctx *context.Context, tiles []*entity.Tile, cells []*state.Cell) *Worl
|
||||
|
||||
w.Scene.Add(w.light)
|
||||
w.Scene.Add(w.sun)
|
||||
|
||||
|
||||
width := w.Cfg.Simulation.Width
|
||||
depth := w.Cfg.Simulation.Depth
|
||||
|
||||
w.State.Quantities[chem.Water] = &chem.Quantity{Units: chem.Litre}
|
||||
w.tilemap = make([][]*entity.Tile, width)
|
||||
|
||||
for x := 0; x < width; x++ {
|
||||
w.tilemap[x] = make([]*entity.Tile, depth)
|
||||
|
||||
@@ -80,10 +82,12 @@ func Load(ctx *context.Context, tiles []*entity.Tile, cells []*state.Cell) *Worl
|
||||
tile.Rand = w.State.Rand
|
||||
w.tilemap[x][z] = tile
|
||||
tile.Refresh(w.State.Entities, w.Scene)
|
||||
|
||||
w.State.Quantities[chem.Water].Value += tile.WaterLevel.Value
|
||||
}
|
||||
}
|
||||
|
||||
w.AssignTileNeighbourhoods()
|
||||
w.assignTileNeighbourhoods()
|
||||
return w
|
||||
}
|
||||
|
||||
@@ -91,7 +95,7 @@ func Load(ctx *context.Context, tiles []*entity.Tile, cells []*state.Cell) *Worl
|
||||
func (w *World) createMap() {
|
||||
heightmap, min, max := w.makeHeightmap()
|
||||
w.makeTilemap(heightmap, min, max)
|
||||
w.AssignTileNeighbourhoods()
|
||||
w.assignTileNeighbourhoods()
|
||||
}
|
||||
|
||||
// Check if a given coordinate is within the tilemap boundaries
|
||||
@@ -132,7 +136,9 @@ func (w *World) makeTilemap(heightmap [][]float32, min, max float32) {
|
||||
width := w.Cfg.Simulation.Width
|
||||
depth := w.Cfg.Simulation.Depth
|
||||
|
||||
w.State.Quantities[chem.Water] = &chem.Quantity{Units: chem.Litre}
|
||||
w.tilemap = make([][]*entity.Tile, width)
|
||||
|
||||
for x := 0; x < width; x++ {
|
||||
|
||||
w.tilemap[x] = make([]*entity.Tile, depth)
|
||||
@@ -151,12 +157,14 @@ func (w *World) makeTilemap(heightmap [][]float32, min, max float32) {
|
||||
tile := entity.NewTile(x, z, height, 22.0, 10, tType, w.State.Rand)
|
||||
tile.Refresh(w.State.Entities, w.Scene)
|
||||
w.tilemap[x][z] = tile
|
||||
|
||||
w.State.Quantities[chem.Water].Value += tile.WaterLevel.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Give each tile in a tilemap a list of pointers to its neighbours
|
||||
func (w *World) AssignTileNeighbourhoods() {
|
||||
func (w *World) assignTileNeighbourhoods() {
|
||||
// Base hexmap neighbourhood offsets
|
||||
nbOffsets := [][]int{
|
||||
{1, 0}, // Right
|
||||
@@ -254,21 +262,22 @@ func (w *World) updateSun() {
|
||||
|
||||
// Update the game world, deltaTime is time since last update in ms
|
||||
func (w *World) Update(deltaTime float32) {
|
||||
// Track quantities of various substances in the world
|
||||
waterLevel := chem.Quantity{Units: chem.Litre}
|
||||
|
||||
if !w.State.Paused() {
|
||||
w.updateSun()
|
||||
w.atmosphere.Update(deltaTime)
|
||||
|
||||
// Update plants and creatures
|
||||
for _, e := range w.State.Entities {
|
||||
if _, isTile := e.(*entity.Tile); isTile {
|
||||
continue
|
||||
}
|
||||
|
||||
e.Update()
|
||||
entity.Highlight(e, w.State.LookingAt == e)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the tilemap independant of paused state so that things like tile highlighting will still work when physics paused
|
||||
// Update the tilemap
|
||||
for x := 0; x < w.Cfg.Simulation.Width; x++ {
|
||||
for z := 0; z < w.Cfg.Simulation.Depth; z++ {
|
||||
tile := w.tilemap[x][z]
|
||||
@@ -277,16 +286,6 @@ func (w *World) Update(deltaTime float32) {
|
||||
entity.Highlight(tile, w.State.LookingAt == tile)
|
||||
}
|
||||
}
|
||||
|
||||
// Update water level count after updating tiles and atmosphere
|
||||
for x := 0; x < w.Cfg.Simulation.Width; x++ {
|
||||
for z := 0; z < w.Cfg.Simulation.Depth; z++ {
|
||||
tile := w.tilemap[x][z]
|
||||
waterLevel.Value += tile.WaterLevel.Value
|
||||
}
|
||||
}
|
||||
|
||||
w.State.Quantities[chem.Water] = waterLevel
|
||||
}
|
||||
|
||||
// GetAtmosphere returns a linear slice of Cells representing the atmosphere
|
||||
|
||||
Reference in New Issue
Block a user