make context great again

This commit is contained in:
thefish 2019-11-14 22:28:58 +03:00
parent 3560be99a1
commit 6a37870bd2
12 changed files with 160 additions and 84 deletions

4
TODO
View File

@ -15,6 +15,9 @@ Basics:
advanced:
- ai
- dijkstra maps
Tech:
- make context great again
Assets and i18n:
- move tile settings to json, generate from there (part of prefabs)
@ -54,3 +57,4 @@ Combat:
Quest engine:
- look at parsers like URQL etc
- distorted Aschenputtel story / partisans / rapist prince / Grey Mountains

View File

@ -71,7 +71,8 @@ func main() {
//fixme set up (load / generate) level - move to game / enter or title / exit
//level, rooms := _default.DefaultGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1))
level, rooms := mapgens.DelaunayMstGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1))
//level, rooms := mapgens.DelaunayMstGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1))
level, rooms := mapgens.DelaunayMstExtGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1))
State.Level = level
sidebarWidth := 0

View File

@ -1,6 +1,7 @@
package gamemap
import (
"context"
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/util/appctx"
@ -13,7 +14,7 @@ var mapHeight = 90
type Level struct {
types.Rect
ctx appctx.ClientCtx
ctx context.Context
Name string
Branch string
Depth int
@ -53,17 +54,26 @@ func (l *Level) SetTileByXY (x,y int, tile *Tile) {
l.Tiles[y*l.W+x] = tile
}
//only replaces tile if original is not passable
func (l *Level) MakePassByXY (x,y int, tile *Tile) {
t := l.Tiles[y*l.W+x]
if t.BlocksPass {
l.Tiles[y*l.W+x] = tile
}
}
func (l *Level) Put (x, y int, tileFunc interface{}) {
tile := tileFunc.(func() *Tile)()
if tile == nil {
l.ctx.Logger().Fatal().Msgf("Got non-tile type to put into level: %v", tile)
appctx.Logger(l.ctx).Fatal().Msgf("Got non-tile type to put into level: %v", tile)
}
if l.InBounds(types.Coords{x, y}) {
l.Tiles[y*l.W+x] = tile
}
}
func NewLevel(ctx appctx.ClientCtx, branch string, depth int) *Level {
func NewLevel(ctx context.Context, branch string, depth int) *Level {
l := &Level{
ctx: ctx,
Name: branch + string(depth),
@ -72,7 +82,7 @@ func NewLevel(ctx appctx.ClientCtx, branch string, depth int) *Level {
}
l.Tiles = make([]*Tile, l.W*l.H)
ctx.Logger().Debug().Msgf("Generating level of branch %s depth %d", branch, depth)
appctx.Logger(ctx).Debug().Msgf("Generating level of branch %s depth %d", branch, depth)
return l
}

View File

@ -1,6 +1,7 @@
package mapgens
import (
"context"
"lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/util"
@ -9,7 +10,7 @@ import (
//fixme move to config
var minRoomSize = 5
var maxRoomSize = 25
var maxRoomSize = 15
var maxrooms = 200
var fges = map[int]types.RectFill{
@ -38,7 +39,7 @@ var fges = map[int]types.RectFill{
},
}
func GetRandomRoomList(ctx appctx.ClientCtx, rng *util.RNG, l *gamemap.Level, maxRooms, minRoomSize, maxRoomSize int, ) []gamemap.Room{
func GetRandomRoomList(ctx context.Context, rng *util.RNG, l *gamemap.Level, maxRooms, minRoomSize, maxRoomSize int, ) []gamemap.Room{
rooms := make([]gamemap.Room, 0)
pfLoader := gamemap.NewPrefabLoader(ctx)
pfRooms := pfLoader.PrefabRoomsList()
@ -102,6 +103,28 @@ func GetRandomRoomList(ctx appctx.ClientCtx, rng *util.RNG, l *gamemap.Level, ma
}
//delaunay helper funcs
func MedianStraight(rng *util.RNG, l *gamemap.Level, rooms []gamemap.Room, centers []types.Coords, edge types.Edge) {
//find connected rooms
var fromRoom, toRoom gamemap.Room
for _, room := range rooms {
if room.Center == edge.From {
fromRoom = room
continue
}
if room.Center == edge.To {
toRoom = room
continue
}
if len(fromRoom.Connectors) > 0 && len(toRoom.Connectors) > 0 {
break
}
}
midpoint := edge.Midpoint()
fromConnector := FindNearestConnector(midpoint, fromRoom)
toConnector := FindNearestConnector(midpoint, toRoom)
ConnectStraight(rng, l, fromConnector, toConnector, midpoint)
}
func FindNearestConnector(midpoint types.Coords, room gamemap.Room) types.Coords {
var nearest types.Coords
@ -118,8 +141,8 @@ func FindNearestConnector(midpoint types.Coords, room gamemap.Room) types.Coords
}
func ConnectStraight(rng *util.RNG, l *gamemap.Level, from, to, midpoint types.Coords) {
toss := rng.Range(0, 1)
if toss == 0 {
toss := rng.Range(1, 2)
if toss > 1 {
DigHTunnel(l, from.X, midpoint.X, from.Y)
DigVTunnel(l, from.Y, to.Y, midpoint.X)
DigHTunnel(l, midpoint.X, to.X, to.Y)
@ -141,7 +164,7 @@ func DigHTunnel(l *gamemap.Level, x1, x2, y int) {
}
for i := start; i <= finish; i++ {
if l.InBounds(types.Coords{i, y}) {
l.SetTileByXY(i, y, gamemap.NewFloor())
l.MakePassByXY(i, y, gamemap.NewFloor())
//l.Tiles[i][y] = gamemap.NewFloor()
}
}
@ -158,7 +181,7 @@ func DigVTunnel(l *gamemap.Level, y1, y2, x int) {
}
for i := start; i <= finish; i++ {
if l.InBounds(types.Coords{x, i}) {
l.SetTileByXY(x, i, gamemap.NewFloor())
l.MakePassByXY(x, i, gamemap.NewFloor())
}
}
}

View File

@ -1,15 +1,15 @@
package mapgens
import (
"context"
"fmt"
"lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/util"
"lab.zaar.be/thefish/alchemyst-go/util/appctx"
"lab.zaar.be/thefish/alchemyst-go/util/delaunay"
)
func DelaunayMstGen(ctx appctx.ClientCtx, l *gamemap.Level) (*gamemap.Level, []gamemap.Room) {
func DelaunayMstGen(ctx context.Context, l *gamemap.Level) (*gamemap.Level, []gamemap.Room) {
rng := util.NewRNG()
@ -33,7 +33,7 @@ func DelaunayMstGen(ctx appctx.ClientCtx, l *gamemap.Level) (*gamemap.Level, []g
for _, room := range rooms {
centers = append(centers, room.Center)
}
edges := delaunay.GetMst(centers, l.W, l.H)
edges := delaunay.GetMst(centers, l.W, l.H, 0)
for _, edge := range edges {
MedianStraight(rng, l, rooms, centers, edge)
}
@ -41,27 +41,5 @@ func DelaunayMstGen(ctx appctx.ClientCtx, l *gamemap.Level) (*gamemap.Level, []g
return l, rooms
}
func MedianStraight(rng *util.RNG, l *gamemap.Level, rooms []gamemap.Room, centers []types.Coords, edge types.Edge) {
//find connected rooms
var fromRoom, toRoom gamemap.Room
for _, room := range rooms {
if room.Center == edge.From {
fromRoom = room
continue
}
if room.Center == edge.To {
toRoom = room
continue
}
if len(fromRoom.Connectors) > 0 && len(toRoom.Connectors) > 0 {
break
}
}
midpoint := edge.Midpoint()
fromConnector := FindNearestConnector(midpoint, fromRoom)
toConnector := FindNearestConnector(midpoint, toRoom)
ConnectStraight(rng, l, fromConnector, toConnector, midpoint)
}

View File

@ -0,0 +1,55 @@
package mapgens
import (
"fmt"
"lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/util"
"lab.zaar.be/thefish/alchemyst-go/util/appctx"
"lab.zaar.be/thefish/alchemyst-go/util/delaunay"
)
func DelaunayMstExtGen(ctx appctx.ClientCtx, l *gamemap.Level) (*gamemap.Level, []gamemap.Room) {
rng := util.NewRNG()
//fill with walls
for i := 0; i < l.W; i ++ {
for j := 0; j < l.H; j++ {
l.SetTileByXY(i, j, gamemap.NewWall())
}
}
rooms := GetRandomRoomList(ctx, rng, l, maxrooms, minRoomSize, maxRoomSize)
for _, room := range rooms {
err := room.BlitToLevel(l)
if err != nil {
fmt.Printf("err: %v", err)
}
}
centers := make([]types.Coords, 0)
for _, room := range rooms {
centers = append(centers, room.Center)
}
edges := delaunay.GetMst(centers, l.W, l.H, l.W) //get negative Weights
outlyingCorridors := make([]types.Edge, 0)
outlyingCorrCount := 0
for _, edge := range edges {
MedianStraight(rng, l, rooms, centers, edge)
outlyingCorridors = append(outlyingCorridors, edge)
outlyingCorrCount++
if outlyingCorrCount > 5 {
break
}
}
edges = delaunay.GetMst(centers, l.W, l.H, 0) //get negative Weights
for _, edge := range edges {
MedianStraight(rng, l, rooms, centers, edge)
}
return l, rooms
}

View File

@ -1,6 +1,7 @@
package gamemap
import (
"context"
"encoding/json"
"io/ioutil"
"lab.zaar.be/thefish/alchemyst-go/engine/items"
@ -42,10 +43,10 @@ func LoadPrefabFile(filename string) (*PrefabFile, error) {
}
type PrefabLoader struct {
ctx appctx.ClientCtx
ctx context.Context
}
func NewPrefabLoader(ctx appctx.ClientCtx) PrefabLoader {
func NewPrefabLoader(ctx context.Context) PrefabLoader {
return PrefabLoader{ctx: ctx}
}
@ -105,7 +106,7 @@ func (pfbl PrefabLoader) PrefabRoomsList() []Room {
} else {
f, ok = TileTypeMap[shortName]
if (!ok) {
pfbl.ctx.Logger().Warn().Msgf("Unknown tile: %s", shortName)
appctx.Logger(pfbl.ctx).Warn().Msgf("Unknown tile: %s", shortName)
}
}
room.Geometry[i+ j*room.W] = f

View File

@ -110,6 +110,33 @@ func NewWaterTile() *Tile {
BlocksSight: false,
Explored: false,
MustDraw: true, //fixme debug
Appearance: &Appearance{
Glyph: &PlainGlyphHolder{" "},
ColorSet: TileColorSet{
Fg: &PlainColorHolder{255, 220, 220, 250},
Bg: &DanceColorHolder{
255,
SingleColorRing(5),
FillColorRing(2, 2, 42, 4),
FillColorRing(154, 150, 229, 12),
},
DarkFg: &PlainColorHolder{255, 30, 20, 50},
DarkBg: &PlainColorHolder{255, 7, 7, 30},
},
},
}
}
func NewDeepWaterTile() *Tile {
//ch := &ColorHolder{5, 2, 154}
return &Tile{
Name: "Deep Water",
Description: "Deep water",
BlocksPass: false,
BlocksSight: false,
Explored: false,
MustDraw: true, //fixme debug
Appearance: &Appearance{
Glyph: &PlainGlyphHolder{" "},
@ -125,31 +152,6 @@ func NewWaterTile() *Tile {
DarkBg: &PlainColorHolder{255, 7, 7, 30},
},
},
}
}
func NewDeepWaterTile() *Tile {
//ch := &ColorHolder{5, 2, 154}
return &Tile{
Name: "Deep Water",
Description: "Deep water",
BlocksPass: false,
BlocksSight: false,
Explored: false,
MustDraw: true, //fixme debug
Appearance: &Appearance{
Glyph: &PlainGlyphHolder{" "},
ColorSet: TileColorSet{
Fg: &PlainColorHolder{255, 220, 220, 250},
Bg: &DanceColorHolder{
255,
SingleColorRing(5),
FillColorRing(2, 2, 42, 4),
FillColorRing(154, 150, 229, 12),
},
DarkFg: &PlainColorHolder{255, 30, 20, 50},
DarkBg: &PlainColorHolder{255, 7, 7, 30},
},
},
}
}

View File

@ -1,6 +1,7 @@
package types
import (
"context"
"lab.zaar.be/thefish/alchemyst-go/util/appctx"
)
@ -13,14 +14,14 @@ type Screen interface {
}
type ScreenManager struct {
ctx appctx.ClientCtx
ctx context.Context
Screens map[string]Screen
CurrentScreen Screen
PreviousScreen Screen
}
// NewScreenManager is a convenience/constructor method to properly initialize a new ScreenManager
func NewScreenManager(ctx appctx.ClientCtx) *ScreenManager {
func NewScreenManager(ctx context.Context) *ScreenManager {
manager := ScreenManager{
ctx:ctx,
Screens: make(map[string]Screen),
@ -35,7 +36,7 @@ func (sm *ScreenManager) AddScreen(screenName string, screen Screen) {
// A screen with the given name does not yet exist on the ScreenManager, go ahead and add it
sm.Screens[screenName] = screen
} else {
sm.ctx.Logger().Warn().Msgf("A screen with name %v was already added to the ScreenManager %v!", screenName, sm)
appctx.Logger(sm.ctx).Warn().Msgf("A screen with name %v was already added to the ScreenManager %v!", screenName, sm)
}
}
@ -48,7 +49,7 @@ func (sm *ScreenManager) RemoveScreen(screenName string, screen Screen) {
delete(sm.Screens, screenName)
} else {
// A screen with the given name does not exist
sm.ctx.Logger().Warn().Msgf("A screen with name %v was not found on ScreenManager %v!", screenName, sm)
appctx.Logger(sm.ctx).Warn().Msgf("A screen with name %v was not found on ScreenManager %v!", screenName, sm)
}
}
@ -83,6 +84,6 @@ func (sm *ScreenManager) SetScreenByName(screenName string) {
sm.CurrentScreen.Enter()
} else {
// A screen with the given name does not exist
sm.ctx.Logger().Warn().Msgf("A screen with name %v was not found on ScreenManager %v!", screenName, sm)
appctx.Logger(sm.ctx).Warn().Msgf("A screen with name %v was not found on ScreenManager %v!", screenName, sm)
}
}

View File

@ -1,6 +1,7 @@
package mainwindow
import (
"context"
"fmt"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"lab.zaar.be/thefish/alchemyst-go/util/appctx"
@ -9,12 +10,12 @@ import (
type MainWindow struct {
types.Rect
ctx appctx.ClientCtx
ctx context.Context
layers map[string]types.Renderable
}
func Init(ctx appctx.ClientCtx) *MainWindow {
ctx.Logger().Info().Msgf("Opening main window...")
func Init(ctx context.Context) *MainWindow {
appctx.Logger(ctx).Info().Msgf("Opening main window...")
mw := MainWindow{ctx: ctx, layers: make(map[string]types.Renderable, 0)}
mw.Open()
return &mw
@ -32,12 +33,12 @@ func (mw *MainWindow) GetLayer(name string) *Layer {
if layer, ok := mw.layers[name]; ok {
return layer.(*Layer)
}
mw.ctx.Logger().Fatal().Msgf("No layer with such name %s", name)
appctx.Logger(mw.ctx).Fatal().Msgf("No layer with such name %s", name)
return nil
}
func (mw *MainWindow) Open() {
config := mw.ctx.Config()
config := appctx.Config(mw.ctx)
blt.Open()
//blt.Set("window: size=80x25, title="+config.Title+" v"+string(version)+"; font: ./fonts/Monaco-Linux.ttf, size=10")
blt.Set(
@ -57,7 +58,7 @@ func (mw *MainWindow) Open() {
}
func (mw *MainWindow) Close() {
mw.ctx.Logger().Info().Msg("Closing main window...")
appctx.Logger(mw.ctx).Info().Msg("Closing main window...")
blt.Close()
}

View File

@ -13,26 +13,26 @@ const (
)
type ClientCtx struct {
ctx context.Context
context.Context
}
func NewClientContext(config *util.Config, logger *zerolog.Logger) ClientCtx {
ctx := context.Context(context.TODO())
ctx = context.WithValue(ctx, configKey, config)
ctx = context.WithValue(ctx, loggerKey, logger)
return ClientCtx{ctx: ctx}
return ClientCtx{ ctx}
}
func (c *ClientCtx) Config() *util.Config {
cfg, ok := c.ctx.Value(configKey).(*util.Config)
func Config(c context.Context) *util.Config {
cfg, ok := c.Value(configKey).(*util.Config)
if !ok {
panic(fmt.Errorf("no access to config from context"))
}
return cfg
}
func (c *ClientCtx) Logger() *zerolog.Logger {
logger, ok := c.ctx.Value(loggerKey).(*zerolog.Logger)
func Logger(c context.Context) *zerolog.Logger {
logger, ok := c.Value(loggerKey).(*zerolog.Logger)
if !ok {
panic(fmt.Errorf("no access to logger from context"))
}

View File

@ -16,7 +16,7 @@ func GetTriangles(coords []types.Coords, w, h int) []types.Edge {
return output
}
func GetMst(coords []types.Coords, w, h int) []types.Edge {
func GetMst(coords []types.Coords, w, h, negativeWeight int) []types.Edge {
d := &Delaunay{}
@ -48,7 +48,7 @@ func GetMst(coords []types.Coords, w, h int) []types.Edge {
kruskals.SimpleWeightedEdge{
nodeMap[e.Nodes[0].Id],
nodeMap[e.Nodes[1].Id],
int(e.Nodes[0].Coords.DistanceTo(e.Nodes[1].Coords))},
negativeWeight - int(e.Nodes[0].Coords.DistanceTo(e.Nodes[1].Coords))},
)
}