Changes from the deadline until the 1.0.0 release/tag.
This commit is contained in:
parent
e4ca42165d
commit
5f2537120d
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
||||
.vscode/launch.json
|
||||
|
||||
cmd/tins2020/*rice-box.*
|
||||
|
@ -49,6 +49,7 @@ func (a *Animation) Run() {
|
||||
}
|
||||
a.active = true
|
||||
a.start = time.Now()
|
||||
a.lastUpdate = 0
|
||||
}
|
||||
|
||||
func (a *Animation) SetInterval(interval time.Duration) {
|
||||
|
@ -9,6 +9,9 @@ import (
|
||||
"opslag.de/schobers/tins2020"
|
||||
)
|
||||
|
||||
//go:generate go get -u github.com/GeertJohan/go.rice/rice
|
||||
//go:generate rice embed
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
if err != nil {
|
||||
|
8
color.go
8
color.go
@ -11,6 +11,14 @@ var Transparent = sdl.Color{R: 0, G: 0, B: 0, A: 0}
|
||||
var TransparentWhite = sdl.Color{R: 255, G: 255, B: 255, A: 31}
|
||||
var White = sdl.Color{R: 255, G: 255, B: 255, A: 255}
|
||||
|
||||
func HexColor(s string) (sdl.Color, error) {
|
||||
c, err := img.HexColor(s)
|
||||
if err != nil {
|
||||
return sdl.Color{}, err
|
||||
}
|
||||
return sdl.Color(c), nil
|
||||
}
|
||||
|
||||
func MustHexColor(s string) sdl.Color { return sdl.Color(img.MustHexColor(s)) }
|
||||
|
||||
func SetDrawColor(renderer *sdl.Renderer, color sdl.Color) {
|
||||
|
@ -22,6 +22,7 @@ func EmptyEvent(fn EventFn) EventContextFn {
|
||||
type ControlBase struct {
|
||||
Bounds Rectangle
|
||||
|
||||
IsDisabled bool
|
||||
IsMouseOver bool
|
||||
|
||||
OnLeftMouseButtonClick EventContextFn
|
||||
@ -36,7 +37,7 @@ func (b *ControlBase) Handle(ctx *Context, event sdl.Event) bool {
|
||||
case *sdl.MouseMotionEvent:
|
||||
b.IsMouseOver = b.Bounds.IsPointInside(e.X, e.Y)
|
||||
case *sdl.MouseButtonEvent:
|
||||
if b.IsMouseOver && e.Button == sdl.BUTTON_LEFT && e.Type == sdl.MOUSEBUTTONDOWN {
|
||||
if !b.IsDisabled && b.IsMouseOver && e.Button == sdl.BUTTON_LEFT && e.Type == sdl.MOUSEBUTTONDOWN {
|
||||
return b.Invoke(ctx, b.OnLeftMouseButtonClick)
|
||||
}
|
||||
case *sdl.WindowEvent:
|
||||
|
8
game.go
8
game.go
@ -163,6 +163,11 @@ func (g *Game) Load() {
|
||||
func (g *Game) Pause() { g.setSpeed(GameSpeedPaused) }
|
||||
|
||||
func (g *Game) PlantFlower(id string, tile Point) {
|
||||
if g.Terrain.HasFlower(tile) {
|
||||
// TODO: notify user it tried to plant on tile with flower?
|
||||
return
|
||||
}
|
||||
|
||||
flower, ok := g.Herbarium.Find(id)
|
||||
if !ok {
|
||||
log.Println("user was able to plant a flower that doesn't exist")
|
||||
@ -255,7 +260,8 @@ func (g *Game) Tool() Tool { return g.tool }
|
||||
func (g *Game) ToolChanged() EventHandler { return g.toolChanged }
|
||||
|
||||
func (g *Game) UnlockNextFlower() {
|
||||
g.Herbarium.UnlockNext()
|
||||
price := g.Herbarium.UnlockNext()
|
||||
g.Balance -= price
|
||||
g.selectTool(nil)
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,10 @@ func (c *GameControls) Init(ctx *Context) error {
|
||||
c.game.SpeedChanged().RegisterItf(c.speedChanged)
|
||||
c.game.ToolChanged().RegisterItf(c.toolChanged)
|
||||
c.dialogs.DialogOpened().Register(func() { c.game.Pause() })
|
||||
c.dialogs.DialogClosed().Register(func() { c.game.Resume() })
|
||||
c.dialogs.DialogClosed().Register(func() {
|
||||
c.updateFlowerControls(ctx)
|
||||
c.game.Resume()
|
||||
})
|
||||
|
||||
c.flowers.Background = MustHexColor("#356dad")
|
||||
c.flowers.ButtonLength = 64
|
||||
@ -117,7 +120,10 @@ func (c *GameControls) Init(ctx *Context) error {
|
||||
|
||||
c.menu.Background = MustHexColor("#356dad")
|
||||
c.menu.Buttons = []Control{
|
||||
NewIconButton("control-settings", c.dialogs.ShowSettings),
|
||||
NewIconButtonConfig("control-settings", c.dialogs.ShowSettings, func(b *IconButton) {
|
||||
b.IsDisabled = true
|
||||
b.IconDisabled = "#afafaf"
|
||||
}),
|
||||
NewIconButton("control-save", func(*Context) { c.game.Save() }),
|
||||
NewIconButton("control-load", func(ctx *Context) {
|
||||
c.game.Load()
|
||||
|
16
herbarium.go
16
herbarium.go
@ -130,12 +130,12 @@ func (h *Herbarium) NextFlowerToUnlock() (string, FlowerDescriptor, int) {
|
||||
return "", FlowerDescriptor{}, 0
|
||||
}
|
||||
|
||||
func (h *Herbarium) UnlockNext() {
|
||||
// id, flower, _ := h.NextFlowerToUnlock()
|
||||
// if flower == nil {
|
||||
// return
|
||||
// }
|
||||
|
||||
// flower.Unlocked = true
|
||||
// h.flowers[flower]
|
||||
func (h *Herbarium) UnlockNext() int {
|
||||
id, flower, price := h.NextFlowerToUnlock()
|
||||
if len(id) == 0 {
|
||||
return 0
|
||||
}
|
||||
flower.Unlocked = true
|
||||
h.flowers[id] = flower
|
||||
return price
|
||||
}
|
||||
|
@ -19,8 +19,7 @@ type IconButton struct {
|
||||
IconActive HoverEffect
|
||||
IconHover HoverEffect
|
||||
|
||||
IsActive bool
|
||||
IsDisabled bool
|
||||
IsActive bool
|
||||
}
|
||||
|
||||
func NewIconButton(icon string, onClick EventContextFn) *IconButton {
|
||||
@ -44,6 +43,16 @@ func (b *IconButton) activeTexture(ctx *Context) *Texture {
|
||||
if texture != nil {
|
||||
return texture
|
||||
}
|
||||
|
||||
texture = ctx.Textures.Texture(b.Icon)
|
||||
if len(b.IconDisabled) == 0 {
|
||||
return texture
|
||||
}
|
||||
color, err := HexColor(b.IconDisabled)
|
||||
if err == nil {
|
||||
texture.SetColor(color)
|
||||
}
|
||||
return texture
|
||||
}
|
||||
return ctx.Textures.Texture(b.Icon)
|
||||
}
|
||||
|
5
map.go
5
map.go
@ -24,6 +24,11 @@ func (m *Map) DigFlower(pos Point) string {
|
||||
return flower.ID
|
||||
}
|
||||
|
||||
func (m *Map) HasFlower(pos Point) bool {
|
||||
_, ok := m.Flowers[pos]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (m *Map) NewFlower(pos Point, id string, traits FlowerTraits) Flower {
|
||||
flower := Flower{
|
||||
ID: id,
|
||||
|
140
research.go
140
research.go
@ -56,13 +56,13 @@ func (d *Digit) Render(ctx *Context) {
|
||||
font := ctx.Fonts.Font("title")
|
||||
color := White
|
||||
if d.highlight > 0 {
|
||||
color = MustHexColor("#356DAD")
|
||||
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 = 10
|
||||
d.highlight = 4
|
||||
}
|
||||
|
||||
func (d *Digit) Tick() {
|
||||
@ -90,33 +90,10 @@ func (r *Research) Init(ctx *Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Research) lastAvailableFlower() *FlowerDescriptor {
|
||||
var desc *FlowerDescriptor
|
||||
for _, id := range r.game.Herbarium.Flowers() {
|
||||
flower, _ := r.game.Herbarium.Find(id)
|
||||
if !flower.Unlocked {
|
||||
return desc
|
||||
}
|
||||
desc = &flower
|
||||
}
|
||||
return desc
|
||||
|
||||
}
|
||||
|
||||
func (r *Research) firstLockedFlower() *FlowerDescriptor {
|
||||
for _, id := range r.game.Herbarium.Flowers() {
|
||||
flower, _ := r.game.Herbarium.Find(id)
|
||||
if !flower.Unlocked {
|
||||
return &flower
|
||||
}
|
||||
}
|
||||
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-24, r.Bounds.W, 24))
|
||||
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)
|
||||
@ -133,25 +110,26 @@ func (r *Research) Arrange(ctx *Context, bounds Rectangle) {
|
||||
func (r *Research) userTyped(i int) {
|
||||
r.digits[i].Blink()
|
||||
digit := strconv.Itoa(i)
|
||||
if len(r.typing) == 0 {
|
||||
if len(r.typing) == 0 || digit != r.typing {
|
||||
r.typing = digit
|
||||
r.digitCount = 1
|
||||
} else if digit != r.typing {
|
||||
r.typing = ""
|
||||
r.digitCount = 0
|
||||
} else {
|
||||
r.digitCount++
|
||||
}
|
||||
if r.digitCount == i || r.digitCount == 10 {
|
||||
|
||||
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 !strings.HasPrefix(r.input.Text, r.botanist.Number) {
|
||||
r.input.Text = ""
|
||||
} else if r.input.Text == r.botanist.Number {
|
||||
if r.input.Text == r.botanist.Number {
|
||||
r.game.UnlockNextFlower()
|
||||
r.close()
|
||||
r.input.Text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,47 +137,49 @@ func (r *Research) userTyped(i int) {
|
||||
func (r *Research) Handle(ctx *Context, event sdl.Event) bool {
|
||||
switch e := event.(type) {
|
||||
case *sdl.KeyboardEvent:
|
||||
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)
|
||||
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
|
||||
@ -227,21 +207,21 @@ func (r *Research) onShow(ctx *Context) {
|
||||
defer func() {
|
||||
r.specialists.Text = specialists
|
||||
}()
|
||||
available := r.lastAvailableFlower()
|
||||
locked := r.firstLockedFlower()
|
||||
if locked == nil {
|
||||
|
||||
_, _, 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 = 2 * available.BuyPrice
|
||||
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 += fmt.Sprintf("Botanist: no. %s (unlocks next flower; $ %d)\n", r.botanist.Number, r.botanist.Cost)
|
||||
specialists += "Farmer: no. **unavailable** (fertilizes land; $ ---)\n"
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ func (r *terrainRenderer) Init(ctx *Context) error {
|
||||
|
||||
func isControlKeyDown() bool {
|
||||
state := sdl.GetKeyboardState()
|
||||
return state[sdl.SCANCODE_LCTRL] == 1 || state[sdl.SCANCODE_RCTRL] == 1
|
||||
return state[sdl.SCANCODE_LCTRL] == 1 || state[sdl.SCANCODE_RCTRL] == 1 || state[sdl.SCANCODE_LGUI] == 1 || state[sdl.SCANCODE_RGUI] == 1
|
||||
}
|
||||
|
||||
func (r *terrainRenderer) Handle(ctx *Context, event sdl.Event) bool {
|
||||
@ -42,12 +42,13 @@ func (r *terrainRenderer) Handle(ctx *Context, event sdl.Event) bool {
|
||||
case *sdl.MouseButtonEvent:
|
||||
if r.project.windowInteractRect.IsPointInside(e.X, e.Y) {
|
||||
if e.Type == sdl.MOUSEBUTTONDOWN {
|
||||
if e.Button == sdl.BUTTON_MIDDLE || (e.Button == sdl.BUTTON_LEFT && isControlKeyDown()) {
|
||||
controlKeyDown := isControlKeyDown()
|
||||
if e.Button == sdl.BUTTON_MIDDLE || (e.Button == sdl.BUTTON_LEFT && controlKeyDown) {
|
||||
if !r.drag.IsDragging() {
|
||||
r.drag.Start(Pt(e.X, e.Y))
|
||||
}
|
||||
}
|
||||
if e.Button == sdl.BUTTON_LEFT {
|
||||
if e.Button == sdl.BUTTON_LEFT && !controlKeyDown {
|
||||
pos := r.project.screenToMapInt(e.X, e.Y)
|
||||
r.game.UserClickedTile(pos)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user