Compare commits
6 Commits
v0.0.8-cod
...
trackui
| Author | SHA1 | Date | |
|---|---|---|---|
| 42ee242f0c | |||
| b1b2a6901f | |||
| 68b7eb60a8 | |||
| 31d7f5bc4f | |||
| 0fdd4bbd81 | |||
| 63d8d09fc0 |
@@ -24,7 +24,6 @@ Based on: https://youtu.be/FWSR_7kZuYg?si=ix1dmo76D8AmF25F
|
||||
[](https://github.com/TLINDEN/golsky/blob/main/.github/assets/screenshots/golsky-captured.png)
|
||||
[](https://github.com/TLINDEN/golsky/blob/main/.github/assets/screenshots/golsky-dark-theme.png)
|
||||
|
||||
|
||||
[Youtube video game preview](https://www.youtube.com/watch?v=xEto6Oew16I)
|
||||
|
||||
# Features
|
||||
|
||||
2
go.mod
@@ -13,7 +13,7 @@ require (
|
||||
github.com/ebitengine/gomobile v0.0.0-20240518074828-e86332849895 // indirect
|
||||
github.com/ebitengine/hideconsole v1.0.0 // indirect
|
||||
github.com/ebitengine/purego v0.7.0 // indirect
|
||||
github.com/ebitenui/ebitenui v0.5.8-0.20240608175527-424f62327b21 // indirect
|
||||
github.com/ebitenui/ebitenui v0.5.8-0.20240608230235-27496c28f409 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/jezek/xgb v1.1.1 // indirect
|
||||
github.com/tinne26/etxt v0.0.8 // indirect
|
||||
|
||||
2
go.sum
@@ -10,6 +10,8 @@ github.com/ebitenui/ebitenui v0.5.6 h1:qyJRU5j+lQo1lamxB48IBwMxMfz1xNb5iWUayCtA0
|
||||
github.com/ebitenui/ebitenui v0.5.6/go.mod h1:I0rVbTOUi7gWKTPet2gzbvhOdkHp5pJXMM6c6b3dRoE=
|
||||
github.com/ebitenui/ebitenui v0.5.8-0.20240608175527-424f62327b21 h1:dElhYGyf+FYY+makAndUQNOSDwFSFYyFWziPwQrPObY=
|
||||
github.com/ebitenui/ebitenui v0.5.8-0.20240608175527-424f62327b21/go.mod h1:I0rVbTOUi7gWKTPet2gzbvhOdkHp5pJXMM6c6b3dRoE=
|
||||
github.com/ebitenui/ebitenui v0.5.8-0.20240608230235-27496c28f409 h1:wsPobs+O3ZmZvhtNtmnMkaB1FRM7tuZ60P0/jegRQGg=
|
||||
github.com/ebitenui/ebitenui v0.5.8-0.20240608230235-27496c28f409/go.mod h1:I0rVbTOUi7gWKTPet2gzbvhOdkHp5pJXMM6c6b3dRoE=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.7.4 h1:X+heODRQ3Ie9F9QFjm24gEZqQd5FSfR9XuT2XfHwgf8=
|
||||
|
||||
BIN
src/assets/sprites/backward.png
Normal file
|
After Width: | Height: | Size: 847 B |
BIN
src/assets/sprites/empty.png
Normal file
|
After Width: | Height: | Size: 593 B |
BIN
src/assets/sprites/forward.png
Normal file
|
After Width: | Height: | Size: 833 B |
BIN
src/assets/sprites/grid.png
Normal file
|
After Width: | Height: | Size: 602 B |
BIN
src/assets/sprites/help.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/assets/sprites/insert.png
Normal file
|
After Width: | Height: | Size: 969 B |
BIN
src/assets/sprites/mark.png
Normal file
|
After Width: | Height: | Size: 635 B |
BIN
src/assets/sprites/media-playback-start.png
Normal file
|
After Width: | Height: | Size: 674 B |
BIN
src/assets/sprites/menu.png
Normal file
|
After Width: | Height: | Size: 574 B |
BIN
src/assets/sprites/nogrid.png
Normal file
|
After Width: | Height: | Size: 579 B |
BIN
src/assets/sprites/options.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/assets/sprites/paste-rle.png
Normal file
|
After Width: | Height: | Size: 880 B |
BIN
src/assets/sprites/pause.png
Normal file
|
After Width: | Height: | Size: 580 B |
BIN
src/assets/sprites/save.png
Normal file
|
After Width: | Height: | Size: 728 B |
BIN
src/assets/sprites/zoom-fit-best.png
Normal file
|
After Width: | Height: | Size: 769 B |
BIN
src/assets/sprites/zoom-in.png
Normal file
|
After Width: | Height: | Size: 738 B |
BIN
src/assets/sprites/zoom-original.png
Normal file
|
After Width: | Height: | Size: 630 B |
BIN
src/assets/sprites/zoom-out.png
Normal file
|
After Width: | Height: | Size: 748 B |
27
src/game.go
@@ -10,7 +10,6 @@ type Game struct {
|
||||
CurrentScene SceneName
|
||||
Config *Config
|
||||
Scale float32
|
||||
Screen *ebiten.Image
|
||||
}
|
||||
|
||||
func NewGame(config *Config, startscene SceneName) *Game {
|
||||
@@ -24,6 +23,7 @@ func NewGame(config *Config, startscene SceneName) *Game {
|
||||
// setup scene[s]
|
||||
game.CurrentScene = startscene
|
||||
game.Scenes[Play] = NewPlayScene(game, config)
|
||||
game.Scenes[Toolbar] = NewToolbarScene(game, config)
|
||||
game.Scenes[Menu] = NewMenuScene(game, config)
|
||||
game.Scenes[Options] = NewOptionsScene(game, config)
|
||||
game.Scenes[Keybindings] = NewKeybindingsScene(game, config)
|
||||
@@ -34,7 +34,6 @@ func NewGame(config *Config, startscene SceneName) *Game {
|
||||
ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled)
|
||||
ebiten.SetScreenClearedEveryFrame(true)
|
||||
|
||||
game.Screen = ebiten.NewImage(game.ScreenWidth, game.ScreenHeight)
|
||||
return game
|
||||
}
|
||||
|
||||
@@ -49,16 +48,22 @@ func (game *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
||||
}
|
||||
|
||||
func (game *Game) Update() error {
|
||||
scene := game.GetCurrentScene()
|
||||
currentscene := game.GetCurrentScene()
|
||||
|
||||
if quit := scene.Update(); quit != nil {
|
||||
return quit
|
||||
for _, scene := range game.Scenes {
|
||||
if scene.IsPrimary() || scene == currentscene {
|
||||
if quit := scene.Update(); quit != nil {
|
||||
return quit
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
next := scene.GetNext()
|
||||
next := currentscene.GetNext()
|
||||
|
||||
if next != game.CurrentScene {
|
||||
game.Scenes[next].SetPrevious(game.CurrentScene)
|
||||
scene.ResetNext()
|
||||
currentscene.ResetNext()
|
||||
game.CurrentScene = next
|
||||
}
|
||||
|
||||
@@ -67,6 +72,7 @@ func (game *Game) Update() error {
|
||||
|
||||
func (game *Game) Draw(screen *ebiten.Image) {
|
||||
// first draw primary scene[s], although there are only 1
|
||||
skip := false
|
||||
for current, scene := range game.Scenes {
|
||||
if scene.IsPrimary() {
|
||||
// primary scenes always draw
|
||||
@@ -74,11 +80,16 @@ func (game *Game) Draw(screen *ebiten.Image) {
|
||||
|
||||
if current == game.CurrentScene {
|
||||
// avoid to redraw it in the next step
|
||||
return
|
||||
skip = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if skip {
|
||||
return
|
||||
}
|
||||
|
||||
scene := game.GetCurrentScene()
|
||||
scene.Draw(screen)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"os"
|
||||
|
||||
@@ -101,6 +102,7 @@ func (scene *SceneMenu) Init() {
|
||||
|
||||
options := NewMenuButton("Options",
|
||||
func(args *widget.ButtonClickedEventArgs) {
|
||||
fmt.Println("menu => options")
|
||||
scene.SetNext(Options)
|
||||
})
|
||||
|
||||
|
||||
22
src/play.go
@@ -6,6 +6,7 @@ import (
|
||||
"log"
|
||||
"unsafe"
|
||||
|
||||
uiinput "github.com/ebitenui/ebitenui/input"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||
@@ -18,7 +19,7 @@ type Images struct {
|
||||
}
|
||||
|
||||
const (
|
||||
DEBUG_FORMAT = "FPS: %0.2f, TPG: %d, M: %0.2fMB, Generations: %d\nScale: %.02f, Zoom: %d, Cam: %.02f,%.02f Cursor: %d,%d %s"
|
||||
DEBUG_FORMAT = "FPS: %0.2f, TPG: %d, M: %0.2fMB, Generations: %d\nScale: %.02f, Zoom: %d, Cam: %.02f,%.02f Cursor: %d,%d %s, UI Active: %t"
|
||||
)
|
||||
|
||||
type ScenePlay struct {
|
||||
@@ -424,11 +425,12 @@ func (scene *ScenePlay) Update() error {
|
||||
return quit
|
||||
}
|
||||
|
||||
scene.CheckInput()
|
||||
scene.CheckDrawingInput()
|
||||
scene.CheckDraggingInput()
|
||||
scene.CheckMarkInput()
|
||||
|
||||
if !uiinput.UIActive {
|
||||
scene.CheckInput()
|
||||
scene.CheckDrawingInput()
|
||||
scene.CheckDraggingInput()
|
||||
scene.CheckMarkInput()
|
||||
}
|
||||
if !scene.Config.Paused || scene.RunOneStep {
|
||||
scene.UpdateCells()
|
||||
}
|
||||
@@ -483,10 +485,8 @@ func (scene *ScenePlay) Draw(screen *ebiten.Image) {
|
||||
|
||||
scene.DrawDebug(screen)
|
||||
|
||||
op.GeoM.Reset()
|
||||
op.GeoM.Translate(0, 0)
|
||||
|
||||
scene.Game.Screen.DrawImage(screen, op)
|
||||
// draw the toolbar directly from here, because otherwise it flickers
|
||||
scene.Game.Scenes[Toolbar].Draw(screen)
|
||||
}
|
||||
|
||||
func (scene *ScenePlay) DrawEvolution(screen *ebiten.Image, x, y int, op *ebiten.DrawImageOptions) {
|
||||
@@ -554,7 +554,7 @@ func (scene *ScenePlay) DrawDebug(screen *ebiten.Image) {
|
||||
scene.Game.Scale, scene.Camera.ZoomFactor,
|
||||
scene.Camera.Position[0], scene.Camera.Position[1],
|
||||
x, y,
|
||||
paused)
|
||||
paused, uiinput.UIActive)
|
||||
|
||||
FontRenderer.Renderer.SetSizePx(10 + int(scene.Game.Scale*10))
|
||||
FontRenderer.Renderer.SetTarget(screen)
|
||||
|
||||
@@ -25,4 +25,5 @@ const (
|
||||
Play // actual playing happens here
|
||||
Options
|
||||
Keybindings
|
||||
Toolbar
|
||||
)
|
||||
|
||||
95
src/toolbar.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/ebitenui/ebitenui"
|
||||
"github.com/ebitenui/ebitenui/widget"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
)
|
||||
|
||||
type SceneToolbar struct {
|
||||
Game *Game
|
||||
Config *Config
|
||||
Next SceneName
|
||||
Prev SceneName
|
||||
Whoami SceneName
|
||||
Ui *ebitenui.UI
|
||||
FontColor color.RGBA
|
||||
}
|
||||
|
||||
func NewToolbarScene(game *Game, config *Config) Scene {
|
||||
scene := &SceneToolbar{
|
||||
Whoami: Toolbar,
|
||||
Game: game,
|
||||
Next: Toolbar,
|
||||
Config: config,
|
||||
FontColor: color.RGBA{255, 30, 30, 0xff},
|
||||
}
|
||||
|
||||
scene.Init()
|
||||
|
||||
return scene
|
||||
}
|
||||
|
||||
func (scene *SceneToolbar) GetNext() SceneName {
|
||||
return scene.Next
|
||||
}
|
||||
|
||||
func (scene *SceneToolbar) SetPrevious(prev SceneName) {
|
||||
scene.Prev = prev
|
||||
}
|
||||
|
||||
func (scene *SceneToolbar) ResetNext() {
|
||||
scene.Next = scene.Whoami
|
||||
}
|
||||
|
||||
func (scene *SceneToolbar) SetNext(next SceneName) {
|
||||
scene.Next = next
|
||||
}
|
||||
|
||||
func (scene *SceneToolbar) IsPrimary() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (scene *SceneToolbar) Update() error {
|
||||
scene.Ui.Update()
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) || inpututil.IsKeyJustPressed(ebiten.KeyQ) {
|
||||
scene.SetNext(Play)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (scene *SceneToolbar) Draw(screen *ebiten.Image) {
|
||||
scene.Ui.Draw(screen)
|
||||
}
|
||||
|
||||
func (scene *SceneToolbar) SetInitialValue(w *widget.LabeledCheckbox, value bool) {
|
||||
if value {
|
||||
w.SetState(
|
||||
widget.WidgetChecked,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (scene *SceneToolbar) Init() {
|
||||
rowContainer := NewTopRowContainer("Toolbar")
|
||||
|
||||
options := NewToolbarButton(Assets["options"],
|
||||
func(args *widget.ButtonClickedEventArgs) {
|
||||
fmt.Println("options")
|
||||
scene.SetNext(Options)
|
||||
})
|
||||
|
||||
rowContainer.AddChild(options)
|
||||
|
||||
scene.Ui = &ebitenui.UI{
|
||||
Container: rowContainer.Container(),
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/ebitenui/ebitenui/image"
|
||||
"github.com/ebitenui/ebitenui/widget"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
func NewMenuButton(
|
||||
@@ -40,6 +41,32 @@ func NewMenuButton(
|
||||
)
|
||||
}
|
||||
|
||||
func NewToolbarButton(
|
||||
icon *ebiten.Image,
|
||||
action func(args *widget.ButtonClickedEventArgs)) *widget.Container {
|
||||
|
||||
buttonImage, _ := LoadButtonImage()
|
||||
|
||||
iconContainer := widget.NewContainer(
|
||||
widget.ContainerOpts.Layout(widget.NewStackedLayout()),
|
||||
widget.ContainerOpts.WidgetOpts(widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
|
||||
HorizontalPosition: widget.AnchorLayoutPositionCenter,
|
||||
VerticalPosition: widget.AnchorLayoutPositionCenter,
|
||||
})),
|
||||
)
|
||||
|
||||
button := widget.NewButton(
|
||||
widget.ButtonOpts.Image(buttonImage),
|
||||
widget.ButtonOpts.ClickedHandler(action),
|
||||
)
|
||||
|
||||
iconContainer.AddChild(button)
|
||||
|
||||
iconContainer.AddChild(widget.NewGraphic(widget.GraphicOpts.Image(icon)))
|
||||
|
||||
return iconContainer
|
||||
}
|
||||
|
||||
func NewCheckbox(
|
||||
text string,
|
||||
initialvalue bool,
|
||||
@@ -215,6 +242,37 @@ func (container *RowContainer) Container() *widget.Container {
|
||||
return container.Root
|
||||
}
|
||||
|
||||
// setup a top level toolbar container
|
||||
func NewTopRowContainer(title string) *RowContainer {
|
||||
buttonImageHover := image.NewNineSlice(Assets["button-9slice3"], [3]int{3, 3, 3}, [3]int{3, 3, 3})
|
||||
|
||||
uiContainer := widget.NewContainer(
|
||||
widget.ContainerOpts.Layout(widget.NewAnchorLayout()),
|
||||
)
|
||||
|
||||
rowContainer := widget.NewContainer(
|
||||
widget.ContainerOpts.WidgetOpts(
|
||||
widget.WidgetOpts.LayoutData(widget.AnchorLayoutData{
|
||||
HorizontalPosition: widget.AnchorLayoutPositionStart,
|
||||
VerticalPosition: widget.AnchorLayoutPositionStart,
|
||||
}),
|
||||
),
|
||||
widget.ContainerOpts.Layout(widget.NewRowLayout(
|
||||
widget.RowLayoutOpts.Direction(widget.DirectionVertical),
|
||||
widget.RowLayoutOpts.Padding(widget.NewInsetsSimple(8)),
|
||||
widget.RowLayoutOpts.Spacing(0),
|
||||
)),
|
||||
widget.ContainerOpts.BackgroundImage(buttonImageHover),
|
||||
)
|
||||
|
||||
uiContainer.AddChild(rowContainer)
|
||||
|
||||
return &RowContainer{
|
||||
Root: uiContainer,
|
||||
Row: rowContainer,
|
||||
}
|
||||
}
|
||||
|
||||
// set arg to false if no background needed
|
||||
func NewRowContainer(title string) *RowContainer {
|
||||
buttonImageHover := image.NewNineSlice(Assets["button-9slice3"], [3]int{3, 3, 3}, [3]int{3, 3, 3})
|
||||
|
||||