diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2025-06-06 16:42:46 -0500 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2025-08-20 15:57:18 +0200 |
| commit | bcffeac4c5086eba59448d4fe5d79bb786b05de2 (patch) | |
| tree | cc0b3648f2b070c731225e88b42fb3f4adcb65da /go | |
| parent | c15142c3bcae4316c8580adb7a9f0b223e586ae9 (diff) | |
| download | muhqs-game-bcffeac4c5086eba59448d4fe5d79bb786b05de2.tar.gz muhqs-game-bcffeac4c5086eba59448d4fe5d79bb786b05de2.zip | |
refactor client activities
Make the activity stack explicit and move reusable activities to the
activity package.
Diffstat (limited to 'go')
| -rw-r--r-- | go/activities/activity.go | 41 | ||||
| -rw-r--r-- | go/activities/draft.go (renamed from go/client/draft.go) | 95 | ||||
| -rw-r--r-- | go/activities/sealed.go (renamed from go/client/sealed.go) | 68 | ||||
| -rw-r--r-- | go/client/main.go | 17 | ||||
| -rw-r--r-- | go/client/startMenu.go | 40 | ||||
| -rw-r--r-- | go/ui/openUrl.go | 25 |
6 files changed, 186 insertions, 100 deletions
diff --git a/go/activities/activity.go b/go/activities/activity.go new file mode 100644 index 00000000..c082b8c6 --- /dev/null +++ b/go/activities/activity.go @@ -0,0 +1,41 @@ +package activities + +import ( + "github.com/hajimehoshi/ebiten/v2" +) + +type ActivityStack struct { + activityStack []ebiten.Game +} + +var Activities ActivityStack + +type Activity = ebiten.Game + +func (s *ActivityStack) PushActivity(a Activity) { + s.activityStack = append(s.activityStack, a) +} + +func (s *ActivityStack) PopActivity() Activity { + n := len(s.activityStack) + a := s.activityStack[n-1] + s.activityStack = s.activityStack[:n-1] + return a +} + +func (s *ActivityStack) Last() Activity { + n := len(s.activityStack) + return s.activityStack[n-1] +} + +func PushActivity(a Activity) { + Activities.PushActivity(a) +} + +func PopActivity() Activity { + return Activities.PopActivity() +} + +func CurActivity() Activity { + return Activities.Last() +} diff --git a/go/client/draft.go b/go/activities/draft.go index 3950094f..10ce9671 100644 --- a/go/client/draft.go +++ b/go/activities/draft.go @@ -1,4 +1,4 @@ -package main +package activities import ( "log" @@ -10,9 +10,13 @@ import ( "muhq.space/muhqs-game/go/ui" ) +const ( + DRAFT_BUTTON_WIDTH = 150 + DRAFT_BUTTON_HEIGHT = 40 +) + type Draft struct { ui.Collection - app *app player *game.Player ctrl *game.ChanPlayerControl draft *game.Draft @@ -22,74 +26,81 @@ type Draft struct { deckList *ui.PocList } -func NewDraft(width, height int, app *app) *Draft { +func NewDraft(width, height int, playerName string) *Draft { d := &Draft{ - app: app, Collection: ui.Collection{Width: width, Height: height}, } d.AddWidget(ui.NewFixedTextBox( - (d.Width-START_BUTTON_WIDTH)/2-START_BUTTON_WIDTH, - (d.Height-START_BUTTON_HEIGHT)/2-3*START_BUTTON_HEIGHT, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + (d.Width-DRAFT_BUTTON_WIDTH)/2-DRAFT_BUTTON_WIDTH, + (d.Height-DRAFT_BUTTON_HEIGHT)/2-3*DRAFT_BUTTON_HEIGHT, + DRAFT_BUTTON_WIDTH, + DRAFT_BUTTON_HEIGHT, "sets:", ).Centering(true)) d.setInput = ui.NewTextInput( - (d.Width-START_BUTTON_WIDTH)/2, - (d.Height-START_BUTTON_HEIGHT)/2-3*START_BUTTON_HEIGHT, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + (d.Width-DRAFT_BUTTON_WIDTH)/2, + (d.Height-DRAFT_BUTTON_HEIGHT)/2-3*DRAFT_BUTTON_HEIGHT, + DRAFT_BUTTON_WIDTH, + DRAFT_BUTTON_HEIGHT, "base,magic,equipments", ) d.AddWidget(d.setInput) d.AddWidget(ui.NewFixedTextBox( - (d.Width-START_BUTTON_WIDTH)/2-START_BUTTON_WIDTH, - (d.Height-START_BUTTON_HEIGHT)/2-2*START_BUTTON_HEIGHT, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + (d.Width-DRAFT_BUTTON_WIDTH)/2-DRAFT_BUTTON_WIDTH, + (d.Height-DRAFT_BUTTON_HEIGHT)/2-2*DRAFT_BUTTON_HEIGHT, + DRAFT_BUTTON_WIDTH, + DRAFT_BUTTON_HEIGHT, "draft:", ).Centering(true)) d.descInput = ui.NewTextInput( - (d.Width-START_BUTTON_WIDTH)/2, - (d.Height-START_BUTTON_HEIGHT)/2-2*START_BUTTON_HEIGHT, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + (d.Width-DRAFT_BUTTON_WIDTH)/2, + (d.Height-DRAFT_BUTTON_HEIGHT)/2-2*DRAFT_BUTTON_HEIGHT, + DRAFT_BUTTON_WIDTH, + DRAFT_BUTTON_HEIGHT, "3x[2;8]", ) d.AddWidget(d.descInput) + d.AddWidget(ui.NewRoundSimpleButton( + (d.Width-DRAFT_BUTTON_WIDTH)/2+DRAFT_BUTTON_WIDTH+20, + (d.Height-DRAFT_BUTTON_HEIGHT)/2-2*DRAFT_BUTTON_HEIGHT, + DRAFT_BUTTON_WIDTH, + "?", + func(*ui.SimpleButton) { + ui.OpenUrl("https://muhq.space/muhqs-game/build/en/rules.html#draft-notation") + })) + d.AddWidget(ui.NewFixedTextBox( - (d.Width-START_BUTTON_WIDTH)/2-START_BUTTON_WIDTH, - (d.Height-START_BUTTON_HEIGHT)/2-START_BUTTON_HEIGHT, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + (d.Width-DRAFT_BUTTON_WIDTH)/2-DRAFT_BUTTON_WIDTH, + (d.Height-DRAFT_BUTTON_HEIGHT)/2-DRAFT_BUTTON_HEIGHT, + DRAFT_BUTTON_WIDTH, + DRAFT_BUTTON_HEIGHT, "AI:", ).Centering(true)) aiNInput := ui.NewNumberChoice( - (d.Width-START_BUTTON_WIDTH)/2, - (d.Height-START_BUTTON_HEIGHT)/2-START_BUTTON_HEIGHT, + (d.Width-DRAFT_BUTTON_WIDTH)/2, + (d.Height-DRAFT_BUTTON_HEIGHT)/2-DRAFT_BUTTON_HEIGHT, 1, nil, ) d.AddWidget(aiNInput) d.AddWidget(ui.NewSimpleButton( - (d.Width-START_BUTTON_WIDTH)/2, - (d.Height-START_BUTTON_HEIGHT)/2, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + (d.Width-DRAFT_BUTTON_WIDTH)/2, + (d.Height-DRAFT_BUTTON_HEIGHT)/2, + DRAFT_BUTTON_WIDTH, + DRAFT_BUTTON_HEIGHT, "Start", func(*ui.SimpleButton) { d.startDraft(d.descInput.TextOrLabel(), d.setInput.TextOrLabel(), aiNInput.GetChoosen()) })) - startMenu := d.app.activities[len(d.app.activities)-1].(*StartMenu) - d.player = game.NewDraftPlayer(startMenu.playerName) + d.player = game.NewDraftPlayer(playerName) d.ctrl = game.NewChanPlayerControl(d.player) d.player.Ctrl = d.ctrl @@ -111,7 +122,7 @@ func (d *Draft) Update() error { } if inpututil.IsKeyJustPressed(ebiten.KeyEscape) { - d.app.popActivity() + PopActivity() } return nil @@ -165,7 +176,7 @@ func (d *Draft) startDraft(desc string, setList string, aiN int) { } d.Clear() - d.deckList = ui.NewPocList(d.Width-SEALED_DECK_STRIP_WIDTH/2, d.Height-START_BUTTON_HEIGHT-20, d.player.Deck) + d.deckList = ui.NewPocList(d.Width-SEALED_DECK_STRIP_WIDTH/2, d.Height-DRAFT_BUTTON_HEIGHT-20, d.player.Deck) d.deckList.Bg(ui.Gray) { cardsInDeck := 0 @@ -180,10 +191,10 @@ func (d *Draft) startDraft(desc string, setList string, aiN int) { d.AddWidget(d.deckList) d.AddWidget(ui.NewSimpleButton( - d.Width-SEALED_DECK_STRIP_WIDTH/2-START_BUTTON_WIDTH/2, - d.Height-START_BUTTON_HEIGHT, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + d.Width-SEALED_DECK_STRIP_WIDTH/2-DRAFT_BUTTON_WIDTH/2, + d.Height-DRAFT_BUTTON_HEIGHT, + DRAFT_BUTTON_WIDTH, + DRAFT_BUTTON_HEIGHT, "Done", func(*ui.SimpleButton) { d.done() @@ -193,7 +204,9 @@ func (d *Draft) startDraft(desc string, setList string, aiN int) { } func (d *Draft) done() { - startMenu := d.app.activities[len(d.app.activities)-2].(*StartMenu) - startMenu.deckInput.SetInput(d.player.Deck.ToList()) - d.app.popActivity() + PopActivity() +} + +func (d *Draft) GetDeckList() string { + return d.player.Deck.ToList() } diff --git a/go/client/sealed.go b/go/activities/sealed.go index efe1006e..7438e89d 100644 --- a/go/client/sealed.go +++ b/go/activities/sealed.go @@ -1,4 +1,4 @@ -package main +package activities import ( "github.com/hajimehoshi/ebiten/v2" @@ -10,46 +10,46 @@ import ( const ( SEALED_DECK_STRIP_WIDTH = 200 + SEALED_BUTTON_WIDTH = 150 + SEALED_BUTTON_HEIGHT = 40 ) -type sealed struct { +type Sealed struct { ui.Collection - app *app setInput *ui.TextInput pool game.PileOfCards - deck game.PileOfCards + Deck game.PileOfCards } -func NewSealed(width, height int, app *app) *sealed { - s := &sealed{ - app: app, +func NewSealed(width, height int) *Sealed { + s := &Sealed{ Collection: ui.Collection{Width: width, Height: height}, } s.AddWidget(ui.NewFixedTextBox( - (s.Width-START_BUTTON_WIDTH)/2-START_BUTTON_WIDTH, - (s.Height-START_BUTTON_HEIGHT)/2-START_BUTTON_HEIGHT, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + (s.Width-SEALED_BUTTON_WIDTH)/2-SEALED_BUTTON_WIDTH, + (s.Height-SEALED_BUTTON_HEIGHT)/2-SEALED_BUTTON_HEIGHT, + SEALED_BUTTON_WIDTH, + SEALED_BUTTON_HEIGHT, "sets:", ).Centering(true)) s.setInput = ui.NewTextInput( - (s.Width-START_BUTTON_WIDTH)/2, - (s.Height-START_BUTTON_HEIGHT)/2-START_BUTTON_HEIGHT, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + (s.Width-SEALED_BUTTON_WIDTH)/2, + (s.Height-SEALED_BUTTON_HEIGHT)/2-SEALED_BUTTON_HEIGHT, + SEALED_BUTTON_WIDTH, + SEALED_BUTTON_HEIGHT, "base,equipments,magic", ) s.AddWidget(s.setInput) s.AddWidget(ui.NewSimpleButton( - (s.Width-START_BUTTON_WIDTH)/2, - (s.Height-START_BUTTON_HEIGHT)/2, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + (s.Width-SEALED_BUTTON_WIDTH)/2, + (s.Height-SEALED_BUTTON_HEIGHT)/2, + SEALED_BUTTON_WIDTH, + SEALED_BUTTON_HEIGHT, "Start", func(*ui.SimpleButton) { s.startSealed(s.setInput.TextOrLabel()) @@ -58,7 +58,7 @@ func NewSealed(width, height int, app *app) *sealed { return s } -func (s *sealed) Update() error { +func (s *Sealed) Update() error { if err := ui.TouchManager.Update(); err != nil { return err } @@ -68,17 +68,17 @@ func (s *sealed) Update() error { } if inpututil.IsKeyJustPressed(ebiten.KeyEscape) { - s.app.popActivity() + Activities.PopActivity() } return nil } -func (s *sealed) Layout(width, height int) (int, int) { +func (s *Sealed) Layout(width, height int) (int, int) { return s.Width, s.Height } -func (s *sealed) startSealed(setList string) { +func (s *Sealed) startSealed(setList string) { sets, err := game.SetListToSets(setList) if err != nil { s.setInput.Bg(ui.WarningBg) @@ -87,7 +87,7 @@ func (s *sealed) startSealed(setList string) { } s.pool = game.NewPileOfCards() - s.deck = game.NewPileOfCards() + s.Deck = game.NewPileOfCards() s.Clear() @@ -101,7 +101,7 @@ func (s *sealed) startSealed(setList string) { setDeck.MoveInto(s.pool) } - deckList := ui.NewPocList(s.Width-SEALED_DECK_STRIP_WIDTH/2, s.Height-START_BUTTON_HEIGHT-20, s.deck) + deckList := ui.NewPocList(s.Width-SEALED_DECK_STRIP_WIDTH/2, s.Height-SEALED_BUTTON_HEIGHT-20, s.Deck) deckList.Bg(ui.Gray) s.AddWidget(deckList) @@ -113,7 +113,7 @@ func (s *sealed) startSealed(setList string) { } card := _card.(*game.Card) - s.pool.MoveCard(card, s.deck) + s.pool.MoveCard(card, s.Deck) grid.ForceRedraw() deckList.ForceRedraw() } @@ -121,18 +121,18 @@ func (s *sealed) startSealed(setList string) { s.AddWidget(grid) s.AddWidget(ui.NewSimpleButton( - s.Width-SEALED_DECK_STRIP_WIDTH/2-START_BUTTON_WIDTH/2, - s.Height-START_BUTTON_HEIGHT, - START_BUTTON_WIDTH, - START_BUTTON_HEIGHT, + s.Width-SEALED_DECK_STRIP_WIDTH/2-SEALED_BUTTON_WIDTH/2, + s.Height-SEALED_BUTTON_HEIGHT, + SEALED_BUTTON_WIDTH, + SEALED_BUTTON_HEIGHT, "Done", func(*ui.SimpleButton) { s.done() })) } -func (s *sealed) done() { - startMenu := s.app.activities[len(s.app.activities)-2].(*StartMenu) - startMenu.deckInput.SetInput(s.deck.ToList()) - s.app.popActivity() +func (s *Sealed) done() { + Activities.PopActivity() + // startMenu := CurActivity().(*StartMenu) + // startMenu.deckInput.SetInput(s.deck.ToList()) } diff --git a/go/client/main.go b/go/client/main.go index 4d46ed9a..b631269e 100644 --- a/go/client/main.go +++ b/go/client/main.go @@ -8,6 +8,7 @@ import ( "github.com/hajimehoshi/ebiten/v2" + "muhq.space/muhqs-game/go/activities" "muhq.space/muhqs-game/go/font" ) @@ -21,24 +22,14 @@ var startDeckPath string type app struct { windowWidth int windowHeight int - - activities []ebiten.Game -} - -func (a *app) pushActivity(activity ebiten.Game) { - a.activities = append(a.activities, activity) -} - -func (a *app) popActivity() { - a.activities = a.activities[:len(a.activities)-1] } func (a *app) Update() error { - return a.activities[len(a.activities)-1].Update() + return activities.CurActivity().Update() } func (a *app) Draw(screen *ebiten.Image) { - a.activities[len(a.activities)-1].Draw(screen) + activities.CurActivity().Draw(screen) } func (a *app) Layout(outsideWidth, outsideHeight int) (int, int) { @@ -86,7 +77,7 @@ func main() { 1 nautics/galley` } - app.pushActivity(startMenu) + activities.PushActivity(startMenu) if err := ebiten.RunGame(app); err != nil { if err != ebiten.Termination { log.Fatal(err) diff --git a/go/client/startMenu.go b/go/client/startMenu.go index 10fa8e1f..10b9e23d 100644 --- a/go/client/startMenu.go +++ b/go/client/startMenu.go @@ -3,6 +3,7 @@ package main import ( "log" + "muhq.space/muhqs-game/go/activities" "muhq.space/muhqs-game/go/game" "muhq.space/muhqs-game/go/ui" ) @@ -15,25 +16,28 @@ const ( DECK_LIST_HEIGHT = 500 ) -type StartMenu struct { +type startMenu struct { ui.Collection app *app deckInput *ui.TextInput + draft *activities.Draft + sealed *activities.Sealed + playerName string startDeck string remote string mapPath string } -func NewStartMenu(app *app) *StartMenu { - m := &StartMenu{app: app} +func NewStartMenu(app *app) *startMenu { + m := &startMenu{app: app} return m } -func (m *StartMenu) build() { +func (m *startMenu) build() { deckInput := ui.NewTextInput( (m.Width-DECK_LIST_WIDTH)/2, (m.Height-DECK_LIST_HEIGHT)/2, @@ -101,8 +105,8 @@ func (m *StartMenu) build() { START_BUTTON_HEIGHT, "Sealed", func(*ui.SimpleButton) { - sealed := NewSealed(m.Width, m.Height, m.app) - m.app.pushActivity(sealed) + sealed := activities.NewSealed(m.Width, m.Height) + activities.PushActivity(sealed) })) m.AddWidget(ui.NewSimpleButton( @@ -112,8 +116,8 @@ func (m *StartMenu) build() { START_BUTTON_HEIGHT, "Draft", func(*ui.SimpleButton) { - draft := NewDraft(m.Width, m.Height, m.app) - m.app.pushActivity(draft) + m.draft = activities.NewDraft(m.Width, m.Height, playerInput.Text()) + activities.PushActivity(m.draft) })) m.AddWidget(ui.NewSimpleButton( @@ -130,11 +134,23 @@ func (m *StartMenu) build() { })) } -func (m *StartMenu) Update() error { +func (m *startMenu) Update() error { if m.Widgets() == nil { m.build() } + // Get the drafted deck + if m.draft != nil { + m.deckInput.SetInput(m.draft.GetDeckList()) + m.draft = nil + } + + // Get the sealed deck + if m.sealed != nil { + m.deckInput.SetInput(m.sealed.Deck.ToList()) + m.sealed = nil + } + if err := ui.TouchManager.Update(); err != nil { return err } @@ -142,11 +158,11 @@ func (m *StartMenu) Update() error { return m.Collection.Update() } -func (m *StartMenu) Layout(width, height int) (int, int) { +func (m *startMenu) Layout(width, height int) (int, int) { return m.Width, m.Height } -func (m *StartMenu) startGame() { +func (m *startMenu) startGame() { var state game.State if m.remote != "" { log.Fatal("Remote games are currently not implemented") @@ -162,5 +178,5 @@ func (m *StartMenu) startGame() { g.gameState.AddNewAiPlayer("kraken", color) } - m.app.pushActivity(g.Start()) + activities.PushActivity(g.Start()) } diff --git a/go/ui/openUrl.go b/go/ui/openUrl.go new file mode 100644 index 00000000..7e227ba8 --- /dev/null +++ b/go/ui/openUrl.go @@ -0,0 +1,25 @@ +package ui + +import ( + "os/exec" + "runtime" +) + +// https://stackoverflow.com/questions/39320371/how-start-web-server-to-open-page-in-browser-in-golang +// open opens the specified URL in the default browser of the user. +func OpenUrl(url string) error { + var cmd string + var args []string + + switch runtime.GOOS { + case "windows": + cmd = "cmd" + args = []string{"/c", "start"} + case "darwin": + cmd = "open" + default: // "linux", "freebsd", "openbsd", "netbsd" + cmd = "xdg-open" + } + args = append(args, url) + return exec.Command(cmd, args...).Start() +} |
