Add tutorial
This commit is contained in:
parent
049006fab0
commit
c16dec2e65
|
@ -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() {
|
|||
ecs.AddSystem(system.NewTickSystem())
|
||||
ecs.AddSystem(system.NewPowerScanSystem())
|
||||
ecs.AddSystem(system.NewPopulateSystem())
|
||||
ecs.AddSystem(system.NewTaxSystem())
|
||||
|
||||
// Input systems.
|
||||
g.movementSystem = system.NewMovementSystem()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -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 {
|
|||
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 {
|
|||
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 {
|
|||
// 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 {
|
|||
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))
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
|
||||
const (
|
||||
helpW = 480
|
||||
helpH = 185
|
||||
helpH = 225
|
||||
)
|
||||
|
||||
type RenderHudSystem struct {
|
||||
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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?
|
||||
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?
|
||||
`, `
|
||||
Yadda yadda yadda (2/3)
|
||||
Do you like the game?
|
||||
I hoped you would.
|
||||
I spent a lot of time making it.
|
||||
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.
|
||||
`, `
|
||||
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*
|
||||
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.
|
||||
`,
|
||||
}
|
||||
|
|
|
@ -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 {
|
|||
LastBuildX int
|
||||
LastBuildY int
|
||||
|
||||
TaxR float64
|
||||
TaxC float64
|
||||
TaxI float64
|
||||
|
||||
resetTipShown bool
|
||||
}
|
||||
|
||||
|
@ -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…
Reference in New Issue