Merge branch 'master' of lab.zaar.be:thefish/alchemyst-go
This commit is contained in:
commit
32c598f9e0
5
engine/ecs/entity.go
Normal file
5
engine/ecs/entity.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package ecs
|
||||||
|
|
||||||
|
type Entity struct {
|
||||||
|
ID int
|
||||||
|
}
|
88
engine/fov/fov.go
Normal file
88
engine/fov/fov.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package fov
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jcerise/gogue/gamemap"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FieldOfVision struct {
|
||||||
|
cosTable map[int]float64
|
||||||
|
sinTable map[int]float64
|
||||||
|
torchRadius int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FieldOfVision) Initialize() {
|
||||||
|
|
||||||
|
f.cosTable = make(map[int]float64)
|
||||||
|
f.sinTable = make(map[int]float64)
|
||||||
|
|
||||||
|
for i := 0; i < 360; i++ {
|
||||||
|
ax := math.Sin(float64(i) / (float64(180) / math.Pi))
|
||||||
|
ay := math.Cos(float64(i) / (float64(180) / math.Pi))
|
||||||
|
|
||||||
|
f.sinTable[i] = ax
|
||||||
|
f.cosTable[i] = ay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FieldOfVision) SetTorchRadius(radius int) {
|
||||||
|
if radius > 1 {
|
||||||
|
f.torchRadius = radius
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FieldOfVision) SetAllInvisible(gameMap *gamemap.Map) {
|
||||||
|
for x := 0; x < gameMap.Width; x++ {
|
||||||
|
for y := 0; y < gameMap.Height; y++ {
|
||||||
|
gameMap.Tiles[x][y].Visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FieldOfVision) RayCast(playerX, playerY int, gameMap *gamemap.Map) {
|
||||||
|
// Cast out rays each degree in a 360 circle from the player. If a ray passes over a floor (does not block sight)
|
||||||
|
// tile, keep going, up to the maximum torch radius (view radius) of the player. If the ray intersects a wall
|
||||||
|
// (blocks sight), stop, as the player will not be able to see past that. Every visible tile will get the Visible
|
||||||
|
// and Explored properties set to true.
|
||||||
|
|
||||||
|
for i := 0; i < 360; i++ {
|
||||||
|
|
||||||
|
ax := f.sinTable[i]
|
||||||
|
ay := f.cosTable[i]
|
||||||
|
|
||||||
|
x := float64(playerX)
|
||||||
|
y := float64(playerY)
|
||||||
|
|
||||||
|
// Mark the players current position as explored
|
||||||
|
tile := gameMap.Tiles[playerX][playerY]
|
||||||
|
tile.Explored = true
|
||||||
|
tile.Visible = true
|
||||||
|
|
||||||
|
for j := 0; j < f.torchRadius; j++ {
|
||||||
|
x -= ax
|
||||||
|
y -= ay
|
||||||
|
|
||||||
|
roundedX := int(Round(x))
|
||||||
|
roundedY := int(Round(y))
|
||||||
|
|
||||||
|
if x < 0 || x > float64(gameMap.Width-1) || y < 0 || y > float64(gameMap.Height-1) {
|
||||||
|
// If the ray is cast outside of the gamemap, stop
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
tile := gameMap.Tiles[roundedX][roundedY]
|
||||||
|
|
||||||
|
tile.Explored = true
|
||||||
|
tile.Visible = true
|
||||||
|
|
||||||
|
if gameMap.Tiles[roundedX][roundedY].BlocksSight == true {
|
||||||
|
// The ray hit a wall, go no further
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Round(f float64) float64 {
|
||||||
|
return math.Floor(f + .5)
|
||||||
|
}
|
14
engine/gamemap/level.go
Normal file
14
engine/gamemap/level.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package gamemap
|
||||||
|
|
||||||
|
import "lab.zaar.be/thefish/alchemyst-go/engine/ecs"
|
||||||
|
|
||||||
|
type Level struct {
|
||||||
|
Name string
|
||||||
|
Branch string
|
||||||
|
Depth int
|
||||||
|
MaxRooms int
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
Objects []ecs.Entity
|
||||||
|
Tiles [][]*Tile
|
||||||
|
}
|
20
engine/gamemap/mapgen.go
Normal file
20
engine/gamemap/mapgen.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package gamemap
|
||||||
|
|
||||||
|
type mapGen interface {
|
||||||
|
generate(l *Level) *Level
|
||||||
|
}
|
||||||
|
|
||||||
|
type defaultGen struct {}
|
||||||
|
|
||||||
|
func (d defaultGen) generate(l *Level) *Level {
|
||||||
|
|
||||||
|
l.Tiles, rooms = addRooms(l)
|
||||||
|
l. Tiles = connectRooms(rooms)
|
||||||
|
l.Objects = populate(rooms)
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func addRooms(l *Level) {
|
||||||
|
|
||||||
|
}
|
143
engine/gamemap/tile.go
Normal file
143
engine/gamemap/tile.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package gamemap
|
||||||
|
|
||||||
|
import "lab.zaar.be/thefish/alchemyst-go/util"
|
||||||
|
import blt "lab.zaar.be/thefish/bearlibterminal"
|
||||||
|
|
||||||
|
type ColorHolder struct {
|
||||||
|
R uint8
|
||||||
|
G uint8
|
||||||
|
B uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type TileColorSet struct {
|
||||||
|
Fg func() uint32
|
||||||
|
Bg func() uint32
|
||||||
|
DarkFg func() uint32
|
||||||
|
DarkBg func() uint32
|
||||||
|
current *ColorHolder
|
||||||
|
}
|
||||||
|
|
||||||
|
type Appearance struct {
|
||||||
|
Char string
|
||||||
|
ColorSet *TileColorSet
|
||||||
|
}
|
||||||
|
|
||||||
|
var crng = util.NewRNG()
|
||||||
|
|
||||||
|
func colordance(colorValue uint8, minGlow, maxGlow, step int) uint8 {
|
||||||
|
color := crng.Range(0, step) + int(colorValue)
|
||||||
|
if color > maxGlow {
|
||||||
|
color = crng.Range(0, step) + minGlow
|
||||||
|
}
|
||||||
|
return uint8(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tile struct {
|
||||||
|
*Appearance
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
BlocksPass bool
|
||||||
|
BlocksSight bool
|
||||||
|
Explored bool
|
||||||
|
MustDraw bool
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func NewWall() *Tile {
|
||||||
|
return &Tile{
|
||||||
|
Name: "Wall",
|
||||||
|
Description: "A dull rock wall",
|
||||||
|
BlocksPass: true,
|
||||||
|
BlocksSight: true,
|
||||||
|
Explored: false,
|
||||||
|
MustDraw: false,
|
||||||
|
Appearance: &Appearance{
|
||||||
|
Char: "#",
|
||||||
|
ColorSet: &TileColorSet{
|
||||||
|
Fg: func() uint32 {return blt.ColorFromARGB(255, 130,110,150)},
|
||||||
|
Bg: func() uint32 {return blt.ColorFromARGB(255, 172,170,173)},
|
||||||
|
DarkFg: func() uint32 {return blt.ColorFromARGB(255, 20,20,68)},
|
||||||
|
DarkBg: func() uint32 {return blt.ColorFromARGB(255, 7,7,30)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFloor() *Tile {
|
||||||
|
return &Tile{
|
||||||
|
Name: "Floor",
|
||||||
|
Description: "Dusty rock floor",
|
||||||
|
BlocksPass: false,
|
||||||
|
BlocksSight: false,
|
||||||
|
Explored: false,
|
||||||
|
MustDraw: false,
|
||||||
|
Appearance: &Appearance{
|
||||||
|
Char: ".",
|
||||||
|
ColorSet: &TileColorSet{
|
||||||
|
Fg: func() uint32 {return blt.ColorFromARGB(255, 220,220,250)},
|
||||||
|
Bg: func() uint32 {return blt.ColorFromARGB(255, 19,19,70)},
|
||||||
|
DarkFg: func() uint32 {return blt.ColorFromARGB(255, 30,20,50)},
|
||||||
|
DarkBg: func() uint32 {return blt.ColorFromARGB(255, 7,7,30)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWaterTile() *Tile {
|
||||||
|
ch := &ColorHolder{19,19,70}
|
||||||
|
return &Tile {
|
||||||
|
Name: "Water",
|
||||||
|
Description: "Murky water",
|
||||||
|
BlocksPass: false,
|
||||||
|
BlocksSight: false,
|
||||||
|
Explored: false,
|
||||||
|
MustDraw: true, //fixme debug
|
||||||
|
Appearance: &Appearance{
|
||||||
|
Char: ".",
|
||||||
|
ColorSet: &TileColorSet{
|
||||||
|
current: ch,
|
||||||
|
Fg: func() uint32 {return blt.ColorFromARGB(255, 220,220,250)},
|
||||||
|
Bg: func() uint32 {
|
||||||
|
return blt.ColorFromARGB(
|
||||||
|
255,
|
||||||
|
ch.R,
|
||||||
|
colordance(ch.G, 2, 42, 4 ),
|
||||||
|
colordance(ch.B, 180,229,12),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
DarkFg: func() uint32 {return blt.ColorFromARGB(255, 30,20,50)},
|
||||||
|
DarkBg: func() uint32 {return blt.ColorFromARGB(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{
|
||||||
|
Char: " ",
|
||||||
|
ColorSet: &TileColorSet{
|
||||||
|
current: ch,
|
||||||
|
Fg: func() uint32 {return blt.ColorFromARGB(255, 220,220,250)},
|
||||||
|
Bg: func() uint32 {
|
||||||
|
return blt.ColorFromARGB(
|
||||||
|
255,
|
||||||
|
ch.R,
|
||||||
|
colordance(ch.G, 0, 15, 2 ),
|
||||||
|
colordance(ch.B, 120,180,5),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
DarkFg: func() uint32 {return blt.ColorFromARGB(255, 30,20,50)},
|
||||||
|
DarkBg: func() uint32 {return blt.ColorFromARGB(255, 7,7,30)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
5
engine/gamemap/types.go
Normal file
5
engine/gamemap/types.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package gamemap
|
||||||
|
|
||||||
|
type Coords struct {
|
||||||
|
x,y int
|
||||||
|
}
|
1
main.go
1
main.go
@ -59,7 +59,6 @@ func main() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
mainCtx.Logger().Info().Msg("pre-shutdown sequence")
|
mainCtx.Logger().Info().Msg("pre-shutdown sequence")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// do runs f on the main thread.
|
// do runs f on the main thread.
|
||||||
|
43
ui/mainwindow/camera.go
Normal file
43
ui/mainwindow/camera.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package mainwindow
|
||||||
|
|
||||||
|
type GameCamera struct {
|
||||||
|
X int
|
||||||
|
Y int
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *GameCamera) MoveCamera(targetX int, targetY int, mapWidth int, mapHeight int) {
|
||||||
|
// Update the camera coordinates to the target coordinates
|
||||||
|
x := targetX - c.Width/2
|
||||||
|
y := targetY - c.Height/2
|
||||||
|
|
||||||
|
if x < 0 {
|
||||||
|
x = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if y < 0 {
|
||||||
|
y = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if x > mapWidth - c.Width {
|
||||||
|
x = mapWidth - c.Width
|
||||||
|
}
|
||||||
|
|
||||||
|
if y > mapHeight - c.Height {
|
||||||
|
y = mapHeight - c.Height
|
||||||
|
}
|
||||||
|
|
||||||
|
c.X, c.Y = x, y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *GameCamera) ToCameraCoordinates(mapX int, mapY int) (cameraX int, cameraY int) {
|
||||||
|
// Convert coordinates on the gamemap, to coordinates on the viewport
|
||||||
|
x, y := mapX-c.X, mapY-c.Y
|
||||||
|
|
||||||
|
if x < 0 || y < 0 || x >= c.Width || y >= c.Height {
|
||||||
|
return -1, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return x, y
|
||||||
|
}
|
@ -2,160 +2,64 @@ package mainwindow
|
|||||||
|
|
||||||
import blt "lab.zaar.be/thefish/bearlibterminal"
|
import blt "lab.zaar.be/thefish/bearlibterminal"
|
||||||
|
|
||||||
var emptyCorners = [4]uint32{0,0,0,0}
|
|
||||||
|
|
||||||
type LayerInterface interface {
|
type LayerInterface interface {
|
||||||
Render()
|
Render()
|
||||||
Put(x, y int, symbol rune, color string)
|
Put(x, y int, symbol rune, color string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type LayerInterfaceImpl struct {
|
type Layer struct {
|
||||||
idx int
|
idx int
|
||||||
defaultColor uint32
|
defaultColor uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddLayer(idx int, colorName string) LayerInterfaceImpl {
|
func AddLayer(idx int, colorName string) Layer {
|
||||||
c := blt.ColorFromName(colorName)
|
c := blt.ColorFromName(colorName)
|
||||||
return LayerInterfaceImpl{idx: idx, defaultColor: c}
|
return Layer{idx: idx, defaultColor: c}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lii *LayerInterfaceImpl) before() *LayerInterfaceImpl {
|
func (layer *Layer) before() *Layer {
|
||||||
blt.Layer(lii.idx)
|
blt.Layer(layer.idx)
|
||||||
return lii
|
return layer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lii *LayerInterfaceImpl) WithColor(colorName string) *LayerInterfaceImpl {
|
func (layer *Layer) WithColor(colorName string) *Layer {
|
||||||
lii.before()
|
layer.before()
|
||||||
c := blt.ColorFromName(colorName)
|
c := blt.ColorFromName(colorName)
|
||||||
blt.Color(c)
|
blt.Color(c)
|
||||||
return lii
|
return layer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lii *LayerInterfaceImpl) after() *LayerInterfaceImpl {
|
func (layer *Layer) after() *Layer {
|
||||||
blt.Color(lii.defaultColor)
|
blt.Color(layer.defaultColor)
|
||||||
blt.Layer(0)
|
blt.Layer(0)
|
||||||
return lii
|
return layer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lii LayerInterfaceImpl) Put(x,y int, symbol string) {
|
func (layer Layer) Put(x,y int, symbol string) {
|
||||||
rnes := []rune(symbol)
|
rnes := []rune(symbol)
|
||||||
if (len(rnes)) > 0 {
|
if (len(rnes)) > 0 {
|
||||||
blt.Put(x, y, int(rnes[0]))
|
blt.Put(x, y, int(rnes[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lii LayerInterfaceImpl) Print(x,y int, txt string) (w,h int) {
|
func (layer Layer) Print(x,y int, txt string) (w,h int) {
|
||||||
return blt.Print(x,y, txt)
|
return blt.Print(x,y, txt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type Rect struct {
|
func (layer Layer) DrawWindow (title string, x, y, w, h int) {
|
||||||
x,y,w,h int
|
|
||||||
layer *LayerInterfaceImpl
|
|
||||||
}
|
|
||||||
|
|
||||||
type rectFill struct {
|
|
||||||
top, bottom, left, right, topLeft, topRight, bottomLeft, bottomRight, body string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lii *LayerInterfaceImpl) NewRect(x,y,w,h int) *Rect {
|
|
||||||
return &Rect{x,y,w,h, lii}
|
|
||||||
}
|
|
||||||
|
|
||||||
var noborder = rectFill{
|
|
||||||
top: "▄",
|
|
||||||
bottom: "▀",
|
|
||||||
left: "▐",
|
|
||||||
right: "▌",
|
|
||||||
topLeft: "▗",
|
|
||||||
topRight: "▖",
|
|
||||||
bottomLeft: "▝",
|
|
||||||
bottomRight: "▘",
|
|
||||||
body: "█",
|
|
||||||
}
|
|
||||||
|
|
||||||
var splash = rectFill{
|
|
||||||
top: "█",
|
|
||||||
bottom: "█",
|
|
||||||
left: "█",
|
|
||||||
right: "█",
|
|
||||||
topLeft: "█",
|
|
||||||
topRight: "█",
|
|
||||||
bottomLeft: "█",
|
|
||||||
bottomRight: "█",
|
|
||||||
body: "█",
|
|
||||||
}
|
|
||||||
|
|
||||||
var doubleBorder = rectFill {
|
|
||||||
top: "═",
|
|
||||||
bottom: "═",
|
|
||||||
left: "║",
|
|
||||||
right: "║",
|
|
||||||
topLeft: "╔",
|
|
||||||
topRight: "╗",
|
|
||||||
bottomLeft: "╚",
|
|
||||||
bottomRight: "╝",
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Rect) Fill() {
|
|
||||||
r.render(noborder)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Rect) Splash() {
|
|
||||||
r.render(splash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Rect) DrawBorder() {
|
|
||||||
r.render(doubleBorder)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Rect) render (fillage rectFill) {
|
|
||||||
|
|
||||||
if fillage.body != "" {
|
|
||||||
for i := r.x + 1; i < r.x+r.w; i++ {
|
|
||||||
for j := r.y + 1; j < r.y+r.h; j++ {
|
|
||||||
r.layer.Put(i, j, fillage.body);
|
|
||||||
//lii.Put(i, j, "X");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := r.x + 1; i < r.x+r.w; i++ {
|
|
||||||
r.layer.Put(i, r.y, fillage.top);
|
|
||||||
//lii.Put(i, y-1, "Q");
|
|
||||||
r.layer.Put(i, r.y+r.h, fillage.bottom);
|
|
||||||
//lii.Put(i, y+h, "H");
|
|
||||||
}
|
|
||||||
|
|
||||||
for j := r.y + 1; j < r.y+r.h; j++ {
|
|
||||||
r.layer.Put(r.x, j, fillage.left);
|
|
||||||
//lii.Put(x-1, j, "U");
|
|
||||||
r.layer.Put(r.x+r.w, j, fillage.right);
|
|
||||||
//lii.Put(x+w, j, "M");
|
|
||||||
}
|
|
||||||
|
|
||||||
r.layer.Put(r.x, r.y, fillage.topLeft);
|
|
||||||
//lii.Put(x-1, y-1, "T");
|
|
||||||
r.layer.Put(r.x, r.y+r.h, fillage.bottomLeft);
|
|
||||||
//lii.Put(x-1, y+h, "q");
|
|
||||||
r.layer.Put(r.x+r.w, r.y, fillage.topRight);
|
|
||||||
//lii.Put(x+w, y-1, "L");
|
|
||||||
r.layer.Put(r.x+r.w, r.y+r.h, fillage.bottomRight);
|
|
||||||
};
|
|
||||||
|
|
||||||
func (lii LayerInterfaceImpl) DrawWindow (title string, x, y, w, h int) {
|
|
||||||
if len(title) > (w -2) {
|
if len(title) > (w -2) {
|
||||||
title = title[:(w-2)]
|
title = title[:(w-2)]
|
||||||
}
|
}
|
||||||
lii.NewRect(x,y,w,h).DrawBorder()
|
layer.NewRect(x,y,w,h).DrawBorder()
|
||||||
centerX := x + (w / 2)
|
centerX := x + (w / 2)
|
||||||
lii.Print(centerX - (len(title) / 2) - 1, y, "╡" + title + "╞")
|
layer.Print(centerX - (len(title) / 2) - 1, y, "╡" + title + "╞")
|
||||||
};
|
};
|
||||||
|
|
||||||
func (lii *LayerInterfaceImpl) Decorate (f func (args ...interface{})) func (args ...interface{}) {
|
func (layer *Layer) Decorate (f func (args ...interface{})) func (args ...interface{}) {
|
||||||
return func (args ...interface{}) {
|
return func (args ...interface{}) {
|
||||||
lii.before()
|
layer.before()
|
||||||
f(args)
|
f(args)
|
||||||
lii.after()
|
layer.after()
|
||||||
}
|
}
|
||||||
}
|
}
|
97
ui/mainwindow/primitives.go
Normal file
97
ui/mainwindow/primitives.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package mainwindow
|
||||||
|
|
||||||
|
type Rect struct {
|
||||||
|
x,y,w,h int
|
||||||
|
layer *Layer
|
||||||
|
}
|
||||||
|
|
||||||
|
type rectFill struct {
|
||||||
|
top, bottom, left, right, topLeft, topRight, bottomLeft, bottomRight, body string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (layer *Layer) NewRect(x,y,w,h int) *Rect {
|
||||||
|
return &Rect{x,y,w,h, layer}
|
||||||
|
}
|
||||||
|
|
||||||
|
var noborder = rectFill{
|
||||||
|
top: "▄",
|
||||||
|
bottom: "▀",
|
||||||
|
left: "▐",
|
||||||
|
right: "▌",
|
||||||
|
topLeft: "▗",
|
||||||
|
topRight: "▖",
|
||||||
|
bottomLeft: "▝",
|
||||||
|
bottomRight: "▘",
|
||||||
|
body: "█",
|
||||||
|
}
|
||||||
|
|
||||||
|
var splash = rectFill{
|
||||||
|
top: "█",
|
||||||
|
bottom: "█",
|
||||||
|
left: "█",
|
||||||
|
right: "█",
|
||||||
|
topLeft: "█",
|
||||||
|
topRight: "█",
|
||||||
|
bottomLeft: "█",
|
||||||
|
bottomRight: "█",
|
||||||
|
body: "█",
|
||||||
|
}
|
||||||
|
|
||||||
|
var doubleBorder = rectFill {
|
||||||
|
top: "═",
|
||||||
|
bottom: "═",
|
||||||
|
left: "║",
|
||||||
|
right: "║",
|
||||||
|
topLeft: "╔",
|
||||||
|
topRight: "╗",
|
||||||
|
bottomLeft: "╚",
|
||||||
|
bottomRight: "╝",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) Fill() {
|
||||||
|
r.render(noborder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) Splash() {
|
||||||
|
r.render(splash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) DrawBorder() {
|
||||||
|
r.render(doubleBorder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rect) render (fillage rectFill) {
|
||||||
|
|
||||||
|
if fillage.body != "" {
|
||||||
|
for i := r.x + 1; i < r.x+r.w; i++ {
|
||||||
|
for j := r.y + 1; j < r.y+r.h; j++ {
|
||||||
|
r.layer.Put(i, j, fillage.body);
|
||||||
|
//lii.Put(i, j, "X");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := r.x + 1; i < r.x+r.w; i++ {
|
||||||
|
r.layer.Put(i, r.y, fillage.top);
|
||||||
|
//lii.Put(i, y-1, "Q");
|
||||||
|
r.layer.Put(i, r.y+r.h, fillage.bottom);
|
||||||
|
//lii.Put(i, y+h, "H");
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := r.y + 1; j < r.y+r.h; j++ {
|
||||||
|
r.layer.Put(r.x, j, fillage.left);
|
||||||
|
//lii.Put(x-1, j, "U");
|
||||||
|
r.layer.Put(r.x+r.w, j, fillage.right);
|
||||||
|
//lii.Put(x+w, j, "M");
|
||||||
|
}
|
||||||
|
|
||||||
|
r.layer.Put(r.x, r.y, fillage.topLeft);
|
||||||
|
//lii.Put(x-1, y-1, "T");
|
||||||
|
r.layer.Put(r.x, r.y+r.h, fillage.bottomLeft);
|
||||||
|
//lii.Put(x-1, y+h, "q");
|
||||||
|
r.layer.Put(r.x+r.w, r.y, fillage.topRight);
|
||||||
|
//lii.Put(x+w, y-1, "L");
|
||||||
|
r.layer.Put(r.x+r.w, r.y+r.h, fillage.bottomRight);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -26,6 +26,7 @@ func (mw *MainWindow) Open() {
|
|||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
//"window: size=%dx%d, title='%s v%s'; font: ./resources/fonts-bitmap/ibmnew8x12.png, size=8x12;",
|
//"window: size=%dx%d, title='%s v%s'; font: ./resources/fonts-bitmap/ibmnew8x12.png, size=8x12;",
|
||||||
"window: size=%dx%d, title='%s v%s'; font: %s, size=8x16;",
|
"window: size=%dx%d, title='%s v%s'; font: %s, size=8x16;",
|
||||||
|
//"window: size=%dx%d, title='%s v%s'",
|
||||||
config.MainWindowSizeX,
|
config.MainWindowSizeX,
|
||||||
config.MainWindowSizeY,
|
config.MainWindowSizeY,
|
||||||
config.Title,
|
config.Title,
|
||||||
|
94
util/rng.go
Normal file
94
util/rng.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RNG struct {
|
||||||
|
seed int64
|
||||||
|
rand *rand.Rand
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRNG() *RNG {
|
||||||
|
rng := RNG{}
|
||||||
|
|
||||||
|
// Set the seed to the current time. This can be updated later by the user.
|
||||||
|
rng.seed = time.Now().UTC().UnixNano()
|
||||||
|
rng.rand = rand.New(rand.NewSource(rng.seed))
|
||||||
|
|
||||||
|
return &rng
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rng *RNG) GetSeed() int64 {
|
||||||
|
return rng.seed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rng *RNG) SetSeed(seed int64) {
|
||||||
|
rng.seed = seed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rng *RNG) Uniform() float64 {
|
||||||
|
return rng.rand.Float64()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rng *RNG) UniformRange(a, b float64) float64 {
|
||||||
|
return a + rng.Uniform() * (b - a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rng *RNG) Normal(mean, stddev float64) float64 {
|
||||||
|
|
||||||
|
var r, x float64
|
||||||
|
|
||||||
|
for r >= 1 || r == 0 {
|
||||||
|
x = rng.UniformRange(-1.0, 1.0)
|
||||||
|
y := rng.UniformRange(-1.0, 1.0)
|
||||||
|
r = x*x + y*y
|
||||||
|
}
|
||||||
|
|
||||||
|
result := x * math.Sqrt(-2 * math.Log(r) / r)
|
||||||
|
|
||||||
|
return mean + stddev * result
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rng *RNG) Percentage() int {
|
||||||
|
return rng.rand.Intn(100)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rng *RNG) Range(min, max int) int {
|
||||||
|
if min == max {
|
||||||
|
return min
|
||||||
|
} else {
|
||||||
|
return rng.rand.Intn(max - min) + min
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rng *RNG) RangeNegative(min, max int) int {
|
||||||
|
if min == max {
|
||||||
|
return min
|
||||||
|
} else {
|
||||||
|
return rng.rand.Intn(max - min + 1) + min
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rng *RNG) GetWeightedEntity(values map[int]int) int {
|
||||||
|
// First up, get the total weight value from the gamemap
|
||||||
|
totalWeight := 0
|
||||||
|
for weight := range values {
|
||||||
|
totalWeight += weight
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, get a random integer in the range of the total weight
|
||||||
|
r := rng.Range(0, totalWeight)
|
||||||
|
|
||||||
|
for weight, value := range values {
|
||||||
|
r -= value
|
||||||
|
if r <= 0 {
|
||||||
|
return weight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user