Browse Source

Add tutorial

main
Trevor Slocum 5 months ago
parent
commit
c16dec2e65
  1. 2
      game/game.go
  2. 53
      system/input_move.go
  3. 7
      system/renderhud.go
  4. 51
      system/tax.go
  5. 73
      world/help.go
  6. 17
      world/world.go

2
game/game.go

@ -192,7 +192,6 @@ func (g *game) Update() error { @@ -192,7 +192,6 @@ func (g *game) Update() error {
nil,
nil,
nil,
nil,
{
StructureType: world.StructureToggleHelp,
Sprite: asset.ImgHelp,
@ -347,6 +346,7 @@ func (g *game) addSystems() { @@ -347,6 +346,7 @@ func (g *game) addSystems() {
ecs.AddSystem(system.NewTickSystem())
ecs.AddSystem(system.NewPowerScanSystem())
ecs.AddSystem(system.NewPopulateSystem())
ecs.AddSystem(system.NewTaxSystem())
// Input systems.
g.movementSystem = system.NewMovementSystem()

53
system/input_move.go

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
package system
import (
"errors"
"math/rand"
"os"
"strings"
@ -50,8 +51,16 @@ func (_ *playerMoveSystem) Uses() []gohan.ComponentID { @@ -50,8 +51,16 @@ func (_ *playerMoveSystem) Uses() []gohan.ComponentID {
}
func (s *playerMoveSystem) buildStructure(structureType int, tileX int, tileY int, playSound bool) (*world.Structure, error) {
cost := world.StructureCosts[structureType]
if world.World.Funds < cost {
world.ShowMessage("Insufficient funds", 3)
return nil, errors.New("insufficient funds")
}
structure, err := world.BuildStructure(world.World.HoverStructure, false, tileX, tileY)
if err == nil {
world.World.LastBuildX, world.World.LastBuildY = tileX, tileY
if world.IsPowerPlant(world.World.HoverStructure) {
plant := &world.PowerPlant{
Type: world.World.HoverStructure,
@ -351,8 +360,8 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { @@ -351,8 +360,8 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
if tileX >= 0 && tileY >= 0 && tileX < 256 && tileY < 256 {
multiUseStructure := world.World.HoverStructure == world.StructureBulldozer || world.World.HoverStructure == world.StructureRoad || world.IsZone(world.World.HoverStructure)
dragStarted := world.World.BuildDragX != -1 || world.World.BuildDragY != -1
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) || (multiUseStructure && ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft)) || dragStarted {
if !dragStarted {
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) || (multiUseStructure && ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft)) || (multiUseStructure && dragStarted) {
if !dragStarted && world.World.Funds >= world.StructureCosts[world.World.HoverStructure] {
world.World.BuildDragX, world.World.BuildDragY = int(tileX), int(tileY)
if world.World.HoverStructure == world.StructureBulldozer {
@ -366,17 +375,22 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { @@ -366,17 +375,22 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
if dragStarted && !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
// TODO build all tiles
world.World.Level.ClearHoverSprites()
var cost int
var builtRoad bool
for _, tile := range tiles {
_, err := s.buildStructure(world.World.HoverStructure, tile[0], tile[1], !builtRoad)
if err == nil {
cost += world.StructureCosts[world.World.HoverStructure]
builtRoad = true
cost := world.StructureCosts[world.World.HoverStructure] * len(tiles) / 2
if cost <= world.World.Funds {
cost = 0
for _, tile := range tiles {
_, err := s.buildStructure(world.World.HoverStructure, tile[0], tile[1], !builtRoad)
if err == nil {
cost += world.StructureCosts[world.World.HoverStructure]
builtRoad = true
}
}
}
if cost > 0 {
world.ShowBuildCost(world.World.HoverStructure, cost)
if cost > 0 {
world.ShowBuildCost(world.World.HoverStructure, cost)
}
} else {
world.ShowMessage("Insufficient funds", 3)
}
world.World.BuildDragX, world.World.BuildDragY = -1, -1
@ -385,9 +399,13 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { @@ -385,9 +399,13 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
// TODO draw hover sprites
// TODO move below into shared func
world.World.Level.ClearHoverSprites()
world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY))
var cost int
for _, tile := range tiles {
world.BuildStructure(world.World.HoverStructure, true, tile[0], tile[1])
cost += world.StructureCosts[world.World.HoverStructure]
}
world.World.HoverValid = cost <= world.World.Funds
}
return nil
} else if dragStarted && !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
@ -406,15 +424,18 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { @@ -406,15 +424,18 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
if err == nil {
tileX, tileY = float64(structure.X), float64(structure.Y)
world.ShowBuildCost(world.World.HoverStructure, cost)
if !multiUseStructure {
world.World.HoverStructure = 0
world.World.BuildDragX, world.World.BuildDragY = -1, -1
world.World.LastBuildX, world.World.LastBuildY = -1, -1
}
}
world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY))
if world.World.HoverStructure > 0 {
world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY))
}
}
} else {
if world.World.LastBuildX != -1 || world.World.LastBuildY != -1 {
world.World.LastBuildX, world.World.LastBuildY = -1, -1
}
world.World.Level.ClearHoverSprites()
world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY))

7
system/renderhud.go

@ -16,7 +16,7 @@ import ( @@ -16,7 +16,7 @@ import (
const (
helpW = 480
helpH = 185
helpH = 225
)
type RenderHudSystem struct {
@ -114,8 +114,13 @@ func (s *RenderHudSystem) drawSidebar() { @@ -114,8 +114,13 @@ func (s *RenderHudSystem) drawSidebar() {
s.drawButtonBackground(s.tmpImg, r, selected)
// Draw sprite.
colorScale := 1.0
if selected {
colorScale = 0.9
}
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64(x+paddingSize)+button.SpriteOffsetX, float64(y+paddingSize)+button.SpriteOffsetY)
op.ColorM.Scale(colorScale, colorScale, colorScale, 1)
s.tmpImg.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Max.X, r.Max.Y)).(*ebiten.Image).DrawImage(button.Sprite, op)
s.drawButtonBorder(s.tmpImg, r, selected)

51
system/tax.go

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
package system
import (
"code.rocketnine.space/tslocum/citylimits/component"
"code.rocketnine.space/tslocum/citylimits/world"
"code.rocketnine.space/tslocum/gohan"
"github.com/hajimehoshi/ebiten/v2"
)
type TaxSystem struct {
}
func NewTaxSystem() *TaxSystem {
s := &TaxSystem{}
return s
}
func (s *TaxSystem) Needs() []gohan.ComponentID {
return []gohan.ComponentID{
component.PositionComponentID,
component.VelocityComponentID,
component.WeaponComponentID,
}
}
func (s *TaxSystem) Uses() []gohan.ComponentID {
return nil
}
func (s *TaxSystem) Update(_ *gohan.Context) error {
if world.World.Paused {
return nil
}
if world.World.Ticks%world.YearTicks != 0 {
return nil
}
for _, zone := range world.World.Zones {
if !zone.Powered {
continue
}
_ = zone
}
return nil
}
func (s *TaxSystem) Draw(ctx *gohan.Context, screen *ebiten.Image) error {
return gohan.ErrSystemWithoutDraw
}

73
world/help.go

@ -2,19 +2,64 @@ package world @@ -2,19 +2,64 @@ package world
// HelpText lines must be 39 characters or less.
var HelpText = []string{`
Welcome to City Limits! (1/3)
Blah blah blah...1231231231231231231234
Testing, testing... Testing, testing...
How does this much text per page seem?
`, `
Yadda yadda yadda (2/3)
Do you like the game?
I hoped you would.
I spent a lot of time making it.
`, `
Oh no... More text?!? (3/3)
If I wanted to read, I would have
grabbed a book, not a game! I'm outta
here! *Door slam*... *Engine starting*
Welcome to City Limits! (1/10)
As the new mayor, it's time to run
things YOUR way. For better or worse...
Will you lead the clean energy front,
or will you put profits before people?
`, `
Moving via mouse (2/10)
To move around, place your cursor at
the edge of the screen, or press and
hold your middle mouse button while
moving your cursor.
`, `
Moving via keyboard (3/10)
You can also use your keyboard to move
by pressing any of the arrow keys or
W/A/S/D. Try using your mouse and/or
keyboard to move the camera around now.
`, `
Zoning areas (4/10)
Structures are built according to the
zoning category of an area. Demand for
each category (Residential, Commercial,
Industrial) is shown in the sidebar.
`, `
Did you know? (5/10)
Powering an area requires more input
energy than the resulting electricity.
In in fact, only a third of the energy
is transmitted as usable electricity.
`, `
Building blocks of a city (6/10)
Structures require power, sewer and
transportation in order to function.
This is all facilitated via roads and
underground wiring and piping.
`, `
Did you know? (7/10)
Meat-based diets require much more
energy, land and water resources than
vegetarian and especially vegan diets.
Animal farms are a source of pollution.
`, `
Power to the people (8/10)
Build a power plant, then zone a few
areas for residential development.
Connect the power plant to the newly
zoned areas with a road.
`, `
Did you know? (9/10)
It takes large amounts of water to
convert fossil fuels into electricity.
Converting solar and wind energy uses
negligible amounts of water.
`, `
Collecting taxes (10/10)
Each year, taxes are collected from the
residents of the city. The tax rate you
set determines how appealing your city
is, and whether or not it can survive.
`,
}

17
world/world.go

@ -63,6 +63,12 @@ var HUDButtons []*HUDButton @@ -63,6 +63,12 @@ var HUDButtons []*HUDButton
var CameraMinZoom = 0.1
var CameraMaxZoom = 1.0
const (
startingTaxR = 0.12
startingTaxC = 0.12
startingTaxI = 0.12
)
var World = &GameWorld{
CamScale: startingZoom,
CamScaleTarget: startingZoom,
@ -190,6 +196,10 @@ type GameWorld struct { @@ -190,6 +196,10 @@ type GameWorld struct {
LastBuildX int
LastBuildY int
TaxR float64
TaxC float64
TaxI float64
resetTipShown bool
}
@ -604,7 +614,12 @@ func SetHoverStructure(structureType int) { @@ -604,7 +614,12 @@ func SetHoverStructure(structureType int) {
}
func Satisfaction() (r, c, i float64) {
return 0.01, 0.0, 0.02
popR, _, _ := Population()
c = float64(popR) / (maxPopulation / 2)
if c > 0.02 {
c = 0.02
}
return 0.02, c, 0.02
}
func TargetPopulation() (r, c, i int) {

Loading…
Cancel
Save