Add initial tutorial

This commit is contained in:
Trevor Slocum 2023-02-17 14:38:59 -08:00
parent 46c9a1e300
commit 5dd5219b5a
6 changed files with 195 additions and 34 deletions

View File

@ -12,12 +12,18 @@ import (
func parseFlags() {
var (
skipIntro bool
skipName bool
)
flag.BoolVar(&world.Fullscreen, "fullscreen", true, "run in fullscreen mode")
flag.BoolVar(&skipIntro, "skip-intro", false, "skip intro screen")
flag.BoolVar(&skipName, "skip-name", false, "skip name input screen")
flag.Parse()
if skipIntro {
if skipIntro || skipName {
world.StartGame()
if skipName {
world.Name = world.NameInput
world.NameInput = ""
}
}
}

View File

@ -61,6 +61,8 @@ func NewGame() *Game {
entity.NewOnceEntity()
gohan.AddSystem(&system.NewEmployee{})
gohan.AddSystem(&system.RenderBackground{})
gohan.AddSystem(&system.Customer{})
gohan.AddSystem(&system.Tutorial{})
gohan.AddSystem(&system.RenderUI{})
s, err := ebiten.NewShader([]byte(shaderSrc))
@ -128,7 +130,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
log.Fatal(err)
}
// NewEmployee target on screen using dither shader.
// Customer target on screen using dither shader.
op := &ebiten.DrawRectShaderOptions{}
op.Images[0] = g.target
screen.DrawRectShader(world.ScreenWidth, world.ScreenHeight, g.shader, op)

34
system/customer.go Normal file
View File

@ -0,0 +1,34 @@
package system
import (
"code.rocketnine.space/tslocum/gas-station-sim/asset"
"code.rocketnine.space/tslocum/gas-station-sim/world"
"code.rocketnine.space/tslocum/gohan"
"github.com/hajimehoshi/ebiten/v2"
)
type Customer struct {
}
func (r *Customer) Update(_ gohan.Entity) error {
if !world.TutorialIntroFinished {
return nil
}
if world.CustomerTicks == 0 {
world.CustomerGenderMale = world.Rand.Intn(2) == 0
asset.SoundChime.Rewind()
asset.SoundChime.Play()
}
world.CustomerTicks++
return nil
}
func (r *Customer) Draw(_ gohan.Entity, screen *ebiten.Image) error {
if !world.TutorialIntroFinished {
return nil
}
return nil
}

View File

@ -2,24 +2,16 @@ package system
import (
"fmt"
"image"
"image/color"
"code.rocketnine.space/tslocum/gas-station-sim/world"
"code.rocketnine.space/tslocum/gohan"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)
type RenderUI struct {
img *ebiten.Image
}
func (r *RenderUI) Update(_ gohan.Entity) error {
if r.img == nil {
r.img = ebiten.NewImage(world.ScreenWidth, world.ScreenHeight)
}
if !world.GameStarted {
return nil
}
@ -37,33 +29,11 @@ func (r *RenderUI) Draw(_ gohan.Entity, screen *ebiten.Image) error {
if world.Name == "" {
if world.Ticks > 6 {
r.drawText(screen, 2, 32, 64, true, "What is your name?")
world.DrawText(screen, 2, 32, 64, true, "What is your name?")
if world.Ticks > 8 {
r.drawText(screen, 2, 64, 128, true, fmt.Sprintf("%s_", world.NameInput))
world.DrawText(screen, 2, 64, 128, true, fmt.Sprintf("%s_", world.NameInput))
}
}
}
return nil
}
func (r *RenderUI) drawText(screen *ebiten.Image, scale int, x int, y int, fill bool, text string) {
const (
paddingW = 6
paddingH = 4
)
l := len(text)
textW, textH := 6*l+paddingW, 12+paddingH
rect := image.Rect(x, y, x+textW*scale, y+textH*scale)
screen.SubImage(rect).(*ebiten.Image).Fill(color.White)
screen.SubImage(rect.Inset(1)).(*ebiten.Image).Fill(color.Black)
r.img.Clear()
ebitenutil.DebugPrintAt(r.img, text, 2+x/scale, y/scale)
op := &ebiten.DrawImageOptions{}
op.GeoM.Scale(float64(scale), float64(scale))
//op.ColorM.ChangeHSV(0, 0, 0.8)
screen.DrawImage(r.img, op)
}

105
system/tutorial.go Normal file
View File

@ -0,0 +1,105 @@
package system
import (
"fmt"
"code.rocketnine.space/tslocum/gas-station-sim/world"
"code.rocketnine.space/tslocum/gohan"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/inpututil"
)
var hireReasons = []string{
"brought a pen",
"didn't bring a pen",
"laughed at our jokes",
"didn't laugh at our jokes",
"wore a plain, boring tie",
"wore an oversized tie",
"have the same uncle as me",
"got married to my sister",
"still have most of your fingers",
"played the harmonica",
}
const tutorialText1 = `Welcome, %s! We are glad to have you here.
We care deeply about our valued customers.
And we know what our customers need.
They need gas. Gallons and gallons and gallons...
And snacks. And sometimes... the restroom.
(Click to continue)`
const tutorialText2 = `We know you will serve our customers with a smile.
While interviewing you, we saw something special.
We loved the way you %s.
That's when we knew our search was over.`
const tutorialText3 = `Oh, here comes your first customer now!
We know you will do great. Break a leg.
Actually, don't break a leg.
We don't want to have to pay for that.`
type Tutorial struct {
ticks int
page int
hireReason string
}
func (r *Tutorial) Update(_ gohan.Entity) error {
if !world.GameStarted || world.Name == "" || world.TutorialIntroFinished {
return nil
}
r.ticks++
if r.page == 3 {
if r.ticks == world.TPS {
world.TutorialIntroFinished = true
}
return nil
}
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
r.page++
r.ticks = 0
if r.page == 1 {
r.hireReason = hireReasons[world.Rand.Intn(len(hireReasons))]
} else if r.page == 3 {
r.ticks = 7
}
}
if r.page == 1 && inpututil.IsKeyJustPressed(ebiten.KeySpace) {
r.hireReason = hireReasons[world.Rand.Intn(len(hireReasons))]
}
return nil
}
func (r *Tutorial) Draw(_ gohan.Entity, screen *ebiten.Image) error {
if !world.GameStarted || world.Name == "" || world.TutorialIntroFinished {
return nil
}
if r.ticks > 6 {
var text string
switch r.page {
case 0:
text = fmt.Sprintf(tutorialText1, world.Name)
case 1:
text = fmt.Sprintf(tutorialText2, r.hireReason)
case 2:
text = tutorialText3
default:
return nil
}
world.DrawText(screen, 1, 16, 48, true, text)
}
return nil
}

View File

@ -1,8 +1,14 @@
package world
import (
"image"
"image/color"
"math/rand"
"strings"
"time"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)
const (
@ -22,9 +28,16 @@ var (
Fullscreen = true
TutorialIntroFinished bool
DisableEsc bool
)
var (
CustomerTicks int
CustomerGenderMale bool
)
var Rand = rand.New(rand.NewSource(time.Now().UnixNano()))
func RandomName() string {
@ -36,3 +49,34 @@ func StartGame() {
NameInput = RandomName()
GameStarted = true
}
var img = ebiten.NewImage(ScreenWidth, ScreenHeight)
func DrawText(screen *ebiten.Image, scale int, x int, y int, fill bool, text string) {
const (
paddingW = 6
paddingH = 2
)
var maxLen int
lines := strings.Split(text, "\n")
for _, line := range lines {
l := len(line)
if l > maxLen {
maxLen = l
}
}
textW, textH := maxLen*6+paddingW, len(lines)*16+paddingH
rect := image.Rect(x, y, x+textW*scale, y+textH*scale)
screen.SubImage(rect).(*ebiten.Image).Fill(color.White)
screen.SubImage(rect.Inset(1)).(*ebiten.Image).Fill(color.Black)
img.Clear()
ebitenutil.DebugPrintAt(img, text, 2+x/scale, y/scale)
op := &ebiten.DrawImageOptions{}
op.GeoM.Scale(float64(scale), float64(scale))
//op.ColorM.ChangeHSV(0, 0, 0.8)
screen.DrawImage(img, op)
}