tins2020/research.go

228 lines
4.7 KiB
Go
Raw Normal View History

package tins2020
import (
"fmt"
"math"
"math/rand"
"strconv"
"strings"
"time"
"github.com/veandco/go-sdl2/sdl"
)
type Research struct {
Container
game *Game
botanist Specialist
farmer Specialist
typing string
digitCount int
close func()
description Paragraph
specialists Paragraph
input Label
digits []Digit
animate Animation
}
func NewResearch(game *Game) Control {
research := &Research{
game: game,
animate: NewAnimation(20 * time.Millisecond),
}
dialog := &LargeDialog{}
dialog.SetCaption("Research")
dialog.SetContent(research)
dialog.OnShow().RegisterItf(func(state interface{}) {
research.onShow(state.(*Context))
})
research.close = func() { dialog.CloseDialog() }
return dialog
}
type Digit struct {
ControlBase
Value string
highlight int
}
func (d *Digit) Render(ctx *Context) {
font := ctx.Fonts.Font("title")
color := White
if d.highlight > 0 {
color = MustHexColor("#15569F")
}
font.RenderCopyAlign(ctx.Renderer, d.Value, Pt(d.Bounds.X+d.Bounds.W/2, d.Bounds.Y+int32(font.Height())), color, TextAlignmentCenter)
}
func (d *Digit) Blink() {
d.highlight = 4
}
func (d *Digit) Tick() {
if d.highlight > 0 {
d.highlight--
}
}
type Specialist struct {
Cost int
Number string
}
func (r *Research) Init(ctx *Context) error {
r.AddChild(&r.description)
r.AddChild(&r.specialists)
r.AddChild(&r.input)
r.description.Text = "Call a specialist to conduct research with."
r.digits = make([]Digit, 10)
for i := range r.digits {
r.digits[i].Value = strconv.Itoa(i)
r.AddChild(&r.digits[i])
}
return nil
}
func (r *Research) Arrange(ctx *Context, bounds Rectangle) {
r.Container.Arrange(ctx, bounds)
r.specialists.Arrange(ctx, RectSize(r.Bounds.X, r.Bounds.Y+40, r.Bounds.W, r.Bounds.H-40))
r.input.Arrange(ctx, RectSize(r.Bounds.X, r.Bounds.X+r.Bounds.H-48, r.Bounds.W, 24))
r.input.Alignment = TextAlignmentCenter
center := Pt(r.Bounds.X+r.Bounds.W/2, r.Bounds.Y+r.Bounds.H/2)
distance := float64(bounds.H) * .3
for i := range r.digits {
angle := (float64((10-i)%10)*0.16 + .2) * math.Pi
pos := Pt(int32(distance*math.Cos(angle)), int32(.8*distance*math.Sin(angle)))
digitCenter := center.Add(pos)
r.digits[i].Arrange(ctx, RectSize(digitCenter.X-24, digitCenter.Y-24, 48, 48))
}
}
func (r *Research) userTyped(i int) {
r.digits[i].Blink()
digit := strconv.Itoa(i)
if len(r.typing) == 0 || digit != r.typing {
r.typing = digit
r.digitCount = 1
} else {
r.digitCount++
}
if !strings.HasPrefix(r.botanist.Number, r.input.Text+r.typing) {
r.input.Text = ""
r.typing = ""
r.digitCount = 0
} else if r.digitCount == i || r.digitCount == 10 {
r.input.Text += digit
r.typing = ""
r.digitCount = 0
if r.input.Text == r.botanist.Number {
r.game.UnlockNextFlower()
r.close()
r.input.Text = ""
}
}
}
func (r *Research) Handle(ctx *Context, event sdl.Event) bool {
switch e := event.(type) {
case *sdl.KeyboardEvent:
if e.Type == sdl.KEYDOWN {
switch e.Keysym.Sym {
case sdl.K_0:
r.userTyped(0)
case sdl.K_KP_0:
r.userTyped(0)
case sdl.K_1:
r.userTyped(1)
case sdl.K_KP_1:
r.userTyped(1)
case sdl.K_2:
r.userTyped(2)
case sdl.K_KP_2:
r.userTyped(2)
case sdl.K_3:
r.userTyped(3)
case sdl.K_KP_3:
r.userTyped(3)
case sdl.K_4:
r.userTyped(4)
case sdl.K_KP_4:
r.userTyped(4)
case sdl.K_5:
r.userTyped(5)
case sdl.K_KP_5:
r.userTyped(5)
case sdl.K_6:
r.userTyped(6)
case sdl.K_KP_6:
r.userTyped(6)
case sdl.K_7:
r.userTyped(7)
case sdl.K_KP_7:
r.userTyped(7)
case sdl.K_8:
r.userTyped(8)
case sdl.K_KP_8:
r.userTyped(8)
case sdl.K_9:
r.userTyped(9)
case sdl.K_KP_9:
r.userTyped(9)
}
}
}
return false
}
func (r *Research) Render(ctx *Context) {
for i := range r.digits {
r.digits[i].Tick()
}
r.Container.Render(ctx)
}
func (r *Research) onShow(ctx *Context) {
generateNumber := func() string {
var number string
for i := 0; i < 3; i++ {
number += strconv.Itoa(rand.Intn(9) + 1)
}
return number
}
r.digitCount = 0
r.input.Text = ""
var specialists string
defer func() {
r.specialists.Text = specialists
}()
_, _, price := r.game.Herbarium.NextFlowerToUnlock()
if price == 0 {
specialists += "Botanist (unlocks next flower; unavailable)\n"
specialists += "Farmer (fertilizes land; unavailable)\n"
return
}
r.botanist.Cost = price
if r.game.Balance < r.botanist.Cost {
r.botanist.Number = "**unavailable**"
} else {
r.botanist.Number = generateNumber()
}
specialists += fmt.Sprintf("Botanist: no. %s (unlocks next flower; $ %d)\n", r.botanist.Number, r.botanist.Cost)
specialists += "Farmer: no. **unavailable** (fertilizes land; $ ---)\n"
}