mirror of
https://codeberg.org/scip/golsky.git
synced 2025-12-16 20:20:57 +01:00
added+fixed game state loader, using NewGrid() to allocate new grids
This commit is contained in:
@@ -37,12 +37,13 @@ While it runs, there are a couple of commands you can use:
|
||||
* right mouse click: set a cell to dead
|
||||
* space: pause or resume the game
|
||||
* while game is paused: press n to forward one step
|
||||
* q: quit
|
||||
* page up: speed up
|
||||
* page down: slow down
|
||||
* Mouse wheel: zoom in or out
|
||||
* move mouse while middle mouse button pressed: move canvas
|
||||
* escape: reset to 1:1 zoom
|
||||
* s: save game state to file (can be loaded with -l)
|
||||
* q: quit
|
||||
|
||||
# Report bugs
|
||||
|
||||
|
||||
2
TODO.md
2
TODO.md
@@ -7,3 +7,5 @@ https://github.com/sachaos/go-life/tree/master/format/rle
|
||||
rle files:
|
||||
https://catagolue.hatsya.com/object/xq2_32mmgozg0igke72z1n2q1z0qgm1z31i2bsogzggqq261z1/b3s23
|
||||
https://copy.sh/life/examples/
|
||||
|
||||
- Translate mouse click co-ordinates to world co-ordinates
|
||||
|
||||
66
game.go
66
game.go
@@ -38,7 +38,8 @@ type Game struct {
|
||||
World *ebiten.Image // actual image we render to
|
||||
WheelTurned bool // when user turns wheel multiple times, zoom faster
|
||||
Dragging bool // middle mouse is pressed, move canvas
|
||||
LastCursorPos []int
|
||||
LastCursorPos []int // used to check if the user is dragging
|
||||
Statefile string // load game state from it if non-nil
|
||||
}
|
||||
|
||||
func (game *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
||||
@@ -325,13 +326,50 @@ func (game *Game) InitPattern() {
|
||||
}
|
||||
|
||||
// initialize playing field/grid
|
||||
func (game *Game) InitGrid() {
|
||||
grid := &Grid{Data: make([][]int, game.Height)}
|
||||
func (game *Game) InitGrid(grid *Grid) {
|
||||
if grid != nil {
|
||||
// use pre-loaded grid
|
||||
game.Grids = []*Grid{
|
||||
grid,
|
||||
NewGrid(grid.Width, grid.Height),
|
||||
}
|
||||
|
||||
game.History = NewGrid(grid.Width, grid.Height)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
grida := NewGrid(game.Width, game.Height)
|
||||
gridb := NewGrid(game.Width, game.Height)
|
||||
history := NewGrid(game.Width, game.Height)
|
||||
|
||||
for y := 0; y < game.Height; y++ {
|
||||
if !game.Empty {
|
||||
for x := 0; x < game.Width; x++ {
|
||||
if rand.Intn(game.Density) == 1 {
|
||||
history.Data[y][x] = 1
|
||||
grida.Data[y][x] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
game.Grids = []*Grid{
|
||||
grida,
|
||||
gridb,
|
||||
}
|
||||
|
||||
game.History = history
|
||||
}
|
||||
|
||||
func (game *Game) _InitGrid(grid *Grid) {
|
||||
|
||||
grida := &Grid{Data: make([][]int, game.Height)}
|
||||
gridb := &Grid{Data: make([][]int, game.Height)}
|
||||
history := &Grid{Data: make([][]int, game.Height)}
|
||||
|
||||
for y := 0; y < game.Height; y++ {
|
||||
grid.Data[y] = make([]int, game.Width)
|
||||
grida.Data[y] = make([]int, game.Width)
|
||||
gridb.Data[y] = make([]int, game.Width)
|
||||
history.Data[y] = make([]int, game.Width)
|
||||
|
||||
@@ -339,14 +377,14 @@ func (game *Game) InitGrid() {
|
||||
for x := 0; x < game.Width; x++ {
|
||||
if rand.Intn(game.Density) == 1 {
|
||||
history.Data[y][x] = 1
|
||||
grid.Data[y][x] = 1
|
||||
grida.Data[y][x] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
game.Grids = []*Grid{
|
||||
grid,
|
||||
grida,
|
||||
gridb,
|
||||
}
|
||||
|
||||
@@ -378,6 +416,20 @@ func (game *Game) InitTiles() {
|
||||
|
||||
func (game *Game) Init() {
|
||||
// setup the game
|
||||
var grid *Grid
|
||||
|
||||
if game.Statefile != "" {
|
||||
g, err := LoadState(game.Statefile)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to load game state: %s", err)
|
||||
}
|
||||
|
||||
grid = g
|
||||
|
||||
game.Width = grid.Width
|
||||
game.Height = grid.Height
|
||||
}
|
||||
|
||||
game.ScreenWidth = game.Cellsize * game.Width
|
||||
game.ScreenHeight = game.Cellsize * game.Height
|
||||
|
||||
@@ -390,7 +442,7 @@ func (game *Game) Init() {
|
||||
|
||||
game.World = ebiten.NewImage(game.ScreenWidth, game.ScreenHeight)
|
||||
|
||||
game.InitGrid()
|
||||
game.InitGrid(grid)
|
||||
game.InitPattern()
|
||||
game.InitTiles()
|
||||
|
||||
|
||||
1
go.mod
1
go.mod
@@ -9,6 +9,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alecthomas/repr v0.4.0 // indirect
|
||||
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
|
||||
|
||||
2
go.sum
2
go.sum
@@ -1,3 +1,5 @@
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/ebitengine/gomobile v0.0.0-20240518074828-e86332849895 h1:48bCqKTuD7Z0UovDfvpCn7wZ0GUZ+yosIteNDthn3FU=
|
||||
github.com/ebitengine/gomobile v0.0.0-20240518074828-e86332849895/go.mod h1:XZdLv05c5hOZm3fM2NlJ92FyEZjnslcMcNRrhxs8+8M=
|
||||
github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
|
||||
|
||||
31
grid.go
31
grid.go
@@ -15,6 +15,31 @@ type Grid struct {
|
||||
Width, Height int
|
||||
}
|
||||
|
||||
// Create new empty grid and allocate Data according to provided dimensions
|
||||
func NewGrid(width, height int) *Grid {
|
||||
grid := &Grid{
|
||||
Height: height,
|
||||
Width: width,
|
||||
Data: make([][]int, height),
|
||||
}
|
||||
|
||||
for y := 0; y < height; y++ {
|
||||
grid.Data[y] = make([]int, width)
|
||||
}
|
||||
|
||||
return grid
|
||||
}
|
||||
|
||||
func (grid *Grid) Clone() *Grid {
|
||||
newgrid := &Grid{}
|
||||
|
||||
newgrid.Width = grid.Width
|
||||
newgrid.Height = grid.Height
|
||||
newgrid.Data = grid.Data
|
||||
|
||||
return newgrid
|
||||
}
|
||||
|
||||
func GetFilename(generations int64) string {
|
||||
now := time.Now()
|
||||
return fmt.Sprintf("dump-%s-%d.gol", now.Format("20060102150405"), generations)
|
||||
@@ -75,16 +100,18 @@ func LoadState(filename string) (*Grid, error) {
|
||||
// sanity check the grid
|
||||
explen := 0
|
||||
rows := 0
|
||||
first := false
|
||||
first := true
|
||||
for _, row := range grid.Data {
|
||||
length := len(row)
|
||||
|
||||
if first {
|
||||
explen = length
|
||||
first = false
|
||||
}
|
||||
|
||||
if explen != length {
|
||||
return nil, errors.New("all rows must be in the same length")
|
||||
return nil, fmt.Errorf(fmt.Sprintf("all rows must be in the same length, got: %d, expected: %d",
|
||||
length, explen))
|
||||
}
|
||||
|
||||
rows++
|
||||
|
||||
5
main.go
5
main.go
@@ -50,7 +50,8 @@ func main() {
|
||||
"game speed: the higher the slower (default: 10)")
|
||||
|
||||
pflag.StringVarP(&rule, "rule", "r", "B3/S23", "game rule")
|
||||
pflag.StringVarP(&rlefile, "rlefile", "f", "", "RLE pattern file")
|
||||
pflag.StringVarP(&rlefile, "rle-file", "f", "", "RLE pattern file")
|
||||
pflag.StringVarP(&game.Statefile, "load-state-file", "l", "", "game state file")
|
||||
|
||||
pflag.BoolVarP(&showversion, "version", "v", false, "show version")
|
||||
pflag.BoolVarP(&game.Paused, "paused", "p", false, "do not start simulation (use space to start)")
|
||||
@@ -73,6 +74,8 @@ func main() {
|
||||
if game.RLE.Width > game.Width || game.RLE.Height > game.Height {
|
||||
game.Width = game.RLE.Width * 2
|
||||
game.Height = game.RLE.Height * 2
|
||||
fmt.Printf("rlew: %d, rleh: %d, w: %d, h: %d\n",
|
||||
game.RLE.Width, game.RLE.Height, game.Width, game.Height)
|
||||
}
|
||||
|
||||
// RLE needs an empty grid
|
||||
|
||||
Reference in New Issue
Block a user