Compare commits
3 Commits
46e3ac060a
...
cdb581d0f6
Author | SHA1 | Date | |
---|---|---|---|
cdb581d0f6 | |||
0203539201 | |||
fd92207400 |
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
"opslag.de/schobers/geom"
|
"opslag.de/schobers/geom"
|
||||||
"opslag.de/schobers/krampus19/alui"
|
"opslag.de/schobers/krampus19/alui"
|
||||||
|
|
||||||
@ -23,9 +24,10 @@ func newTexture(bmp *allg5.Bitmap) texture {
|
|||||||
type Context struct {
|
type Context struct {
|
||||||
DisplaySize geom.Point
|
DisplaySize geom.Point
|
||||||
Resources vfs.CopyDir
|
Resources vfs.CopyDir
|
||||||
|
ResourcesFs afero.Fs
|
||||||
Textures map[string]texture
|
Textures map[string]texture
|
||||||
Sprites map[string]sprite
|
Sprites map[string]sprite
|
||||||
Levels map[string]levelPack
|
Levels *levelPacks
|
||||||
Progress progress
|
Progress progress
|
||||||
SpriteDrawer SpriteDrawer
|
SpriteDrawer SpriteDrawer
|
||||||
Settings settings
|
Settings settings
|
||||||
|
@ -6,7 +6,11 @@ import (
|
|||||||
"image/png"
|
"image/png"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
"opslag.de/schobers/allg5"
|
"opslag.de/schobers/allg5"
|
||||||
"opslag.de/schobers/fs/vfs"
|
"opslag.de/schobers/fs/vfs"
|
||||||
"opslag.de/schobers/geom"
|
"opslag.de/schobers/geom"
|
||||||
@ -98,24 +102,57 @@ func (g *game) loadTextures(pathToName map[string]string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *game) loadLevelPack(ids ...string) error {
|
func (g *game) loadLevelPacks() error {
|
||||||
g.ctx.Levels = map[string]levelPack{}
|
g.ctx.Levels = newLevelPacks()
|
||||||
for _, id := range ids {
|
|
||||||
fileName := fmt.Sprintf("levels/pack%s.txt", id)
|
var ids []string
|
||||||
f, err := g.ctx.Resources.Open(fileName)
|
const root = "levels"
|
||||||
|
err := afero.Walk(g.ctx.ResourcesFs, root, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
if !info.IsDir() {
|
||||||
pack, err := parseLevelPackAsset(f, func(levelID string) (io.ReadCloser, error) {
|
return nil
|
||||||
fileName := fmt.Sprintf("levels/pack%s_level%s.txt", id, levelID)
|
|
||||||
return g.ctx.Resources.Open(fileName)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
g.ctx.Levels[id] = pack
|
name := filepath.Base(path)
|
||||||
|
if name == root {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(name, "pack") {
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
ids = append(ids, name[4:])
|
||||||
|
return filepath.SkipDir
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, id := range ids {
|
||||||
|
err := g.loadLevelPack(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *game) loadLevelPack(id string) error {
|
||||||
|
fileName := fmt.Sprintf("levels/pack%s/info.txt", id)
|
||||||
|
f, err := g.ctx.Resources.Open(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
pack, err := parseLevelPackAsset(f, func(levelID string) (io.ReadCloser, error) {
|
||||||
|
fileName := fmt.Sprintf("levels/pack%s/level%s.txt", id, levelID)
|
||||||
|
return g.ctx.Resources.Open(fileName)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
g.ctx.Levels.Add(id, pack)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,12 +201,12 @@ func (g *game) loadAssets() error {
|
|||||||
}
|
}
|
||||||
log.Printf("Loaded %d textures.\n", len(g.ctx.Textures))
|
log.Printf("Loaded %d textures.\n", len(g.ctx.Textures))
|
||||||
|
|
||||||
log.Println("Loading levels...")
|
log.Println("Loading level packs...")
|
||||||
err = g.loadLevelPack("1")
|
err = g.loadLevelPacks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Printf("Loaded %d levels.\n", len(g.ctx.Levels))
|
log.Printf("Loaded %d levels packs (%d levels).\n", g.ctx.Levels.Len(), g.ctx.Levels.LenLevels())
|
||||||
|
|
||||||
log.Println("Loading fonts...")
|
log.Println("Loading fonts...")
|
||||||
err = g.loadFonts()
|
err = g.loadFonts()
|
||||||
@ -192,9 +229,9 @@ func (g *game) Destroy() {
|
|||||||
g.ctx.Destroy()
|
g.ctx.Destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *game) Init(disp *allg5.Display, settings settings, res vfs.CopyDir, cons *gut.Console, fps *gut.FPS) error {
|
func (g *game) Init(disp *allg5.Display, settings settings, res vfs.CopyDir, resFs afero.Fs, cons *gut.Console, fps *gut.FPS) error {
|
||||||
log.Print("Initializing game...")
|
log.Print("Initializing game...")
|
||||||
g.ctx = &Context{Resources: res, Textures: map[string]texture{}, Settings: settings, Navigation: navigation{game: g}}
|
g.ctx = &Context{Resources: res, ResourcesFs: resFs, Textures: map[string]texture{}, Settings: settings, Navigation: navigation{game: g}}
|
||||||
g.ctx.DisplaySize = geom.Pt(disp.Width(), disp.Height())
|
g.ctx.DisplaySize = geom.Pt(disp.Width(), disp.Height())
|
||||||
g.ctx.SpriteDrawer.ctx = g.ctx
|
g.ctx.SpriteDrawer.ctx = g.ctx
|
||||||
err := g.ctx.Progress.load()
|
err := g.ctx.Progress.load()
|
||||||
|
@ -24,10 +24,15 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resources() (vfs.CopyDir, error) {
|
func resources() (vfs.CopyDir, afero.Fs, error) {
|
||||||
var embeddedFs = ricefs.NewFs(rice.MustFindBox("res"))
|
var embeddedFs = ricefs.NewFs(rice.MustFindBox("res"))
|
||||||
var osFs = afero.NewBasePathFs(afero.NewOsFs(), "./res")
|
var osFs = afero.NewBasePathFs(afero.NewOsFs(), "./res")
|
||||||
return vfs.NewCopyDir(vfs.NewFallbackFs(osFs, embeddedFs))
|
var fs = vfs.NewFallbackFs(osFs, embeddedFs)
|
||||||
|
copy, err := vfs.NewCopyDir(fs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return copy, fs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func run() error {
|
func run() error {
|
||||||
@ -35,7 +40,7 @@ func run() error {
|
|||||||
cons := &gut.Console{}
|
cons := &gut.Console{}
|
||||||
log.SetOutput(io.MultiWriter(log.Writer(), cons))
|
log.SetOutput(io.MultiWriter(log.Writer(), cons))
|
||||||
|
|
||||||
res, err := resources()
|
res, resFs, err := resources()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -107,7 +112,7 @@ func run() error {
|
|||||||
defer fps.Destroy()
|
defer fps.Destroy()
|
||||||
|
|
||||||
game := &game{}
|
game := &game{}
|
||||||
err = game.Init(disp, settings, res, cons, fps)
|
err = game.Init(disp, settings, res, resFs, cons, fps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,8 @@ func (p levelPack) FindNext(level string) (string, bool) {
|
|||||||
return p.order[idx+1], true
|
return p.order[idx+1], true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p levelPack) Len() int { return len(p.order) }
|
||||||
|
|
||||||
type parseLevelPackContext struct {
|
type parseLevelPackContext struct {
|
||||||
name string
|
name string
|
||||||
levels []string
|
levels []string
|
||||||
|
36
cmd/krampus19/levelpacks.go
Normal file
36
cmd/krampus19/levelpacks.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type levelPacks struct {
|
||||||
|
packs map[string]levelPack
|
||||||
|
order []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLevelPacks() *levelPacks {
|
||||||
|
return &levelPacks{map[string]levelPack{}, nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *levelPacks) Add(id string, pack levelPack) {
|
||||||
|
p.order = append(p.order, id)
|
||||||
|
p.packs[id] = pack
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *levelPacks) ByID(id string) levelPack { return p.packs[id] }
|
||||||
|
|
||||||
|
func (p *levelPacks) FirstPackID() string {
|
||||||
|
if p.Len() == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p.order[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *levelPacks) Len() int { return len(p.order) }
|
||||||
|
|
||||||
|
func (p *levelPacks) LenLevels() int {
|
||||||
|
var cnt int
|
||||||
|
for _, pack := range p.packs {
|
||||||
|
cnt += pack.Len()
|
||||||
|
}
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *levelPacks) MustSelect() bool { return p.Len() != 1 }
|
40
cmd/krampus19/levelpackselect.go
Normal file
40
cmd/krampus19/levelpackselect.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"opslag.de/schobers/allg5"
|
||||||
|
|
||||||
|
"opslag.de/schobers/krampus19/alui"
|
||||||
|
)
|
||||||
|
|
||||||
|
type levelPackSelect struct {
|
||||||
|
alui.Menu
|
||||||
|
|
||||||
|
ctx *Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *levelPackSelect) Enter(ctx *Context) error {
|
||||||
|
s.ctx = ctx
|
||||||
|
s.Init()
|
||||||
|
s.AddChild(newHeader("Select a level pack"))
|
||||||
|
for _, id := range s.ctx.Levels.order {
|
||||||
|
var copy = id
|
||||||
|
s.Add(s.ctx.Levels.ByID(id).name, func() {
|
||||||
|
s.ctx.Navigation.SelectLevel(copy)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
s.Add("Back to main menu", func() { s.ctx.Navigation.ShowMainMenu() })
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *levelPackSelect) Handle(e allg5.Event) {
|
||||||
|
switch e := e.(type) {
|
||||||
|
case *allg5.KeyDownEvent:
|
||||||
|
switch e.KeyCode {
|
||||||
|
case allg5.KeyEscape:
|
||||||
|
s.ctx.Navigation.ShowMainMenu()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.Menu.Handle(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *levelPackSelect) Leave() {}
|
@ -19,7 +19,7 @@ type levelSelect struct {
|
|||||||
|
|
||||||
func (s *levelSelect) Enter(ctx *Context) error {
|
func (s *levelSelect) Enter(ctx *Context) error {
|
||||||
s.ctx = ctx
|
s.ctx = ctx
|
||||||
s.pack = s.ctx.Levels[s.packID]
|
s.pack = s.ctx.Levels.ByID(s.packID)
|
||||||
s.Init()
|
s.Init()
|
||||||
name := func(i int, steps int) string {
|
name := func(i int, steps int) string {
|
||||||
if steps == 0 {
|
if steps == 0 {
|
||||||
@ -27,12 +27,20 @@ func (s *levelSelect) Enter(ctx *Context) error {
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("Level %d (%d)", i, steps)
|
return fmt.Sprintf("Level %d (%d)", i, steps)
|
||||||
}
|
}
|
||||||
|
if s.ctx.Levels.MustSelect() {
|
||||||
|
s.AddChild(newHeader(fmt.Sprintf("Select a '%s' level", s.pack.name)))
|
||||||
|
} else {
|
||||||
|
s.AddChild(newHeader("Select a level"))
|
||||||
|
}
|
||||||
for i, id := range s.pack.order {
|
for i, id := range s.pack.order {
|
||||||
levelID := id
|
levelID := id
|
||||||
s.Add(name(i+1, s.ctx.Progress.Level(s.packID, levelID).Steps), func() {
|
s.Add(name(i+1, s.ctx.Progress.Level(s.packID, levelID).Steps), func() {
|
||||||
s.ctx.Navigation.PlayLevel(s.packID, levelID)
|
s.ctx.Navigation.PlayLevel(s.packID, levelID)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if s.ctx.Levels.MustSelect() {
|
||||||
|
s.Add("Select level pack", func() { s.ctx.Navigation.SelectPack() })
|
||||||
|
}
|
||||||
s.Add("Back to main menu", func() { s.ctx.Navigation.ShowMainMenu() })
|
s.Add("Back to main menu", func() { s.ctx.Navigation.ShowMainMenu() })
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,15 @@ type mainMenu struct {
|
|||||||
ctx *Context
|
ctx *Context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newHeader(label string) alui.Control {
|
||||||
|
return alui.NewMargins(&alui.Label{ControlBase: alui.ControlBase{Font: "header"}, Text: label, TextAlign: allg5.AlignCenter}, 3*margin)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *mainMenu) Enter(ctx *Context) error {
|
func (m *mainMenu) Enter(ctx *Context) error {
|
||||||
m.ctx = ctx
|
m.ctx = ctx
|
||||||
m.Init()
|
m.Init()
|
||||||
m.AddChild(alui.NewMargins(&alui.Label{ControlBase: alui.ControlBase{Font: "header"}, Text: "Sokodragon", TextAlign: allg5.AlignCenter}, 3*margin))
|
m.AddChild(newHeader("Sokodragon"))
|
||||||
m.Add("Play", func() { m.ctx.Navigation.SelectLevel("1") })
|
m.Add("Play", func() { m.ctx.Navigation.SelectPack() })
|
||||||
m.Add("Settings", func() { m.ctx.Navigation.ChangeSettings() })
|
m.Add("Settings", func() { m.ctx.Navigation.ChangeSettings() })
|
||||||
m.Add("Quit", func() { m.ctx.Navigation.Quit() })
|
m.Add("Quit", func() { m.ctx.Navigation.Quit() })
|
||||||
return nil
|
return nil
|
||||||
|
@ -28,6 +28,15 @@ func (n *navigation) SelectLevel(packID string) {
|
|||||||
n.switchTo(&levelSelect{packID: packID})
|
n.switchTo(&levelSelect{packID: packID})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *navigation) SelectPack() {
|
||||||
|
if n.game.ctx.Levels.MustSelect() {
|
||||||
|
n.switchTo(&levelPackSelect{})
|
||||||
|
} else {
|
||||||
|
packID := n.game.ctx.Levels.FirstPackID()
|
||||||
|
n.SelectLevel(packID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (n *navigation) ShowMainMenu() {
|
func (n *navigation) ShowMainMenu() {
|
||||||
n.switchTo(&mainMenu{})
|
n.switchTo(&mainMenu{})
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,9 @@ func (l *playLevel) onComplete() {
|
|||||||
if ok {
|
if ok {
|
||||||
menu.Add("Continue with next", func() { l.ctx.Navigation.PlayLevel(l.packID, nextID) })
|
menu.Add("Continue with next", func() { l.ctx.Navigation.PlayLevel(l.packID, nextID) })
|
||||||
}
|
}
|
||||||
|
if l.ctx.Levels.MustSelect() {
|
||||||
|
menu.Add("Select level pack", func() { l.ctx.Navigation.SelectPack() })
|
||||||
|
}
|
||||||
menu.Add("Select level", func() { l.ctx.Navigation.SelectLevel(l.packID) })
|
menu.Add("Select level", func() { l.ctx.Navigation.SelectLevel(l.packID) })
|
||||||
menu.Add("Go to main menu", func() { l.ctx.Navigation.ShowMainMenu() })
|
menu.Add("Go to main menu", func() { l.ctx.Navigation.ShowMainMenu() })
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ func (s *playLevelState) IsNextToMagma(pos geom.Point) bool {
|
|||||||
|
|
||||||
func (s *playLevelState) Init(ctx *Context, pack, level string, onComplete func()) {
|
func (s *playLevelState) Init(ctx *Context, pack, level string, onComplete func()) {
|
||||||
s.ctx = ctx
|
s.ctx = ctx
|
||||||
s.pack = ctx.Levels[pack]
|
s.pack = ctx.Levels.ByID(pack)
|
||||||
s.level = s.pack.levels[level]
|
s.level = s.pack.levels[level]
|
||||||
s.bricks = nil
|
s.bricks = nil
|
||||||
s.sunken = nil
|
s.sunken = nil
|
||||||
|
Loading…
Reference in New Issue
Block a user