Skip to content

Commit

Permalink
implement game logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Steinke committed Feb 9, 2024
1 parent b801737 commit 9934bd9
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 20 deletions.
32 changes: 29 additions & 3 deletions button.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package main

import "github.com/maxence-charriere/go-app/v9/pkg/app"
import (
"fmt"
"time"

"github.com/maxence-charriere/go-app/v9/pkg/app"
)

type button struct {
app.Compo

id int64
id int64
Active bool
}

func NewButton(id int64) *button {
Expand All @@ -14,12 +20,32 @@ func NewButton(id int64) *button {
}
}

func (b *button) OnMount(ctx app.Context) {
ctx.Handle(fmt.Sprintf(playButton, b.id), b.handleActivate)
}

func (b *button) Render() app.UI {
return app.Button().
e := app.Button().
Class("simon-button").
Body(app.Span().Text("")).
ID("button%d", b.id).
OnClick(func(ctx app.Context, _ app.Event) {
ctx.NewActionWithValue(click, b.id)
})
if b.Active {
e.Class("active")
}
return e
}

func (b *button) handleActivate(ctx app.Context, a app.Action) {
fmt.Println("playing", b.id)
ctx.Dispatch(func(_ app.Context) {
b.Active = true
})
ctx.After(900*time.Millisecond, func(_ app.Context) {
ctx.Dispatch(func(_ app.Context) {
b.Active = false
})
})
}
3 changes: 0 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ func main() {
g := NewGame()
app.Route("/", g)

app.Handle(click, g.handleClick)
app.Handle(newGame, g.handleNewGame)

// When executed on the client-side, the RunWhenOnBrowser() function
// launches the app, starting a loop that listens for app events and
// executes client instructions. Since it is a blocking call, the code below
Expand Down
4 changes: 2 additions & 2 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ html, body {
transition: 300ms;
}

.simon-button.current span {
background-color: #D0D0D0;
.simon-button.active span {
background: none;
}

@media (min-width: 768px) {
Expand Down
56 changes: 44 additions & 12 deletions ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/rand"
"fmt"
"math/big"
"time"

"github.com/maxence-charriere/go-app/v9/pkg/app"
)
Expand All @@ -13,9 +14,18 @@ type events = string
const (
click events = "click"
playSequence events = "playSequence"
playButton events = "play%d"
newGame events = "newGame"
)

type gameState int

const (
gameStateNoGame gameState = iota
gameStateSimonSays
gameStatePlayerSays
)

func NewGame() *game {
return &game{
sequence: []int64{},
Expand All @@ -27,10 +37,14 @@ type game struct {

sequence []int64
clicks int
stage int
state gameState
}

func (g *game) OnMount(ctx app.Context) {
ctx.Handle(playSequence, g.playSequence)
ctx.Handle(click, g.handleClick)
ctx.Handle(newGame, g.handleNewGame)
}

func (g *game) Render() app.UI {
Expand All @@ -57,47 +71,65 @@ func (g *game) Render() app.UI {
}

func (g *game) playSequence(ctx app.Context, a app.Action) {
g.state = gameStateSimonSays
sequence, ok := a.Value.([]int64)
if !ok {
fmt.Println("wrong type")
return
}
fmt.Println("sequence:", sequence)
for _, btnIndex := range sequence {
btn := app.Window().GetElementByID(fmt.Sprintf("button%d", btnIndex))
fmt.Println("found button:", btn.Truthy())
}

ctx.Async(func() {
// TODO: This is so weird. I somehow need to wait before I can do the next
// action, otherwise it just won't update the DOM.
<-time.After(200 * time.Millisecond)
for _, btnIndex := range sequence {
fmt.Println("sending", btnIndex)
ctx.NewAction(fmt.Sprintf(playButton, btnIndex))
<-time.After(time.Second)
}
g.state = gameStatePlayerSays
})
}

func (g *game) handleNewGame(ctx app.Context, a app.Action) {
fmt.Println("New Game")
g.clicks = 0
seq := GenerateSequence(4)
g.sequence = seq
ctx.NewActionWithValue(playSequence, seq)
g.sequence = GenerateSequence(4)
g.stage = 1
ctx.NewActionWithValue(playSequence, g.sequence[:1])
}

func (g *game) handleClick(ctx app.Context, a app.Action) {
if g.state != gameStatePlayerSays {
return
}
click, ok := a.Value.(int64)
if !ok {
fmt.Println("wrong type")
return
}
if len(g.sequence) <= g.clicks {
fmt.Println("game is over")
return
}

fmt.Println("received click:", click)
if g.sequence[g.clicks] != click {
fmt.Println("YOU LOSE!")
g.clicks = 0
g.sequence = GenerateSequence(4)
ctx.NewActionWithValue(playSequence, g.sequence)
return
}
g.clicks++
if len(g.sequence) == g.clicks {
fmt.Println("YOU WIN!")
return
}
if g.clicks == g.stage {
g.clicks = 0
g.sequence = GenerateSequence(4)
ctx.NewActionWithValue(playSequence, g.sequence)
g.stage++
ctx.After(300*time.Millisecond, func(ctx app.Context) {
ctx.NewActionWithValue(playSequence, g.sequence[:g.stage])
})
}
}

Expand Down

0 comments on commit 9934bd9

Please sign in to comment.