colordance

This commit is contained in:
thefish 2019-10-31 00:55:51 +03:00
parent ffe658e90e
commit 8dd242b242
9 changed files with 185 additions and 86 deletions

View File

@ -77,7 +77,7 @@ func (*GameState) Do(f func()) {
func mainLoop(ctx util.ClientCtx) { func mainLoop(ctx util.ClientCtx) {
baseLayer := mainwindow.AddLayer(0, "white") baseLayer := mainwindow.AddLayer(0, "white")
bgLayer := mainwindow.AddLayer(1, "white") //bgLayer := mainwindow.AddLayer(1, "white")
menuLayer := mainwindow.AddLayer(2, "white") menuLayer := mainwindow.AddLayer(2, "white")
initRender := func() { initRender := func() {
@ -106,14 +106,14 @@ Sed euismod nisi porta lorem mollis aliquam ut porttitor leo. Ut tellus elementu
menuLayer.WithColor("white").PutWithBackground(40, 1, "Щ", "#cd31ed12") menuLayer.WithColor("white").PutWithBackground(40, 1, "Щ", "#cd31ed12")
menuLayer.WithColor("yellow").PutWithBackground(41, 1, "Ц", "#efcccccc") menuLayer.WithColor("yellow").PutWithBackground(41, 1, "Ц", "#efcccccc")
bgLayer.WithColor("#77cfcfcf").NewWindow(45, 5, 40, 40).Splash() //bgLayer.WithColor("#cc242424").NewWindow(45, 5, 40, 40).Splash()
menuLayer.WithColor("#aaed26ca").NewWindow(45, 5, 40, 40).DoubleBordered("Transparent BG window test") //menuLayer.WithColor("#ffdede89").NewWindow(45, 5, 40, 40).DoubleBordered("Transparent BG window test")
blt.PrintExt(46, 6, 40, 39, 1, `Lorem mollis aliquam ut porttitor leo a diam sollicitudin tempor. Convallis tellus id interdum velit. Enim nunc faucibus a pellentesque. Tincidunt augue interdum velit euismod in pellentesque massa placerat duis. Leo duis ut diam quam nulla porttitor massa id. Eu feugiat pretium nibh ipsum consequat nisl. Eget est lorem ipsum dolor sit amet. Et sollicitudin ac orci phasellus egestas. Donec adipiscing tristique risus nec. Et molestie ac feugiat sed. Ante in nibh mauris cursus mattis molestie a iaculis at. Neque laoreet suspendisse interdum consectetur. Vitae et leo duis ut diam quam nulla. Sed ullamcorper morbi tincidunt ornare massa eget egestas purus viverra. Ornare lectus sit amet est placerat in egestas erat. //blt.PrintExt(46, 6, 40, 39, 1, `Lorem mollis aliquam ut porttitor leo a diam sollicitudin tempor. Convallis tellus id interdum velit. Enim nunc faucibus a pellentesque. Tincidunt augue interdum velit euismod in pellentesque massa placerat duis. Leo duis ut diam quam nulla porttitor massa id. Eu feugiat pretium nibh ipsum consequat nisl. Eget est lorem ipsum dolor sit amet. Et sollicitudin ac orci phasellus egestas. Donec adipiscing tristique risus nec. Et molestie ac feugiat sed. Ante in nibh mauris cursus mattis molestie a iaculis at. Neque laoreet suspendisse interdum consectetur. Vitae et leo duis ut diam quam nulla. Sed ullamcorper morbi tincidunt ornare massa eget egestas purus viverra. Ornare lectus sit amet est placerat in egestas erat.
//
Cursus in hac habitasse platea. Aliquet risus feugiat in ante metus dictum. Maecenas sed enim ut sem viverra aliquet eget sit. [color=orange]Vitae[/color] aliquet nec ullamcorper sit amet risus nullam. Scelerisque fermentum dui faucibus in ornare quam viverra orci sagittis. Sed tempus urna et pharetra pharetra massa massa ultricies. Est ultricies integer quis auctor. Volutpat est velit egestas dui id ornare arcu. Eget nunc lobortis mattis aliquam faucibus purus. Erat nam at lectus urna duis. //Cursus in hac habitasse platea. Aliquet risus feugiat in ante metus dictum. Maecenas sed enim ut sem viverra aliquet eget sit. [color=orange]Vitae[/color] aliquet nec ullamcorper sit amet risus nullam. Scelerisque fermentum dui faucibus in ornare quam viverra orci sagittis. Sed tempus urna et pharetra pharetra massa massa ultricies. Est ultricies integer quis auctor. Volutpat est velit egestas dui id ornare arcu. Eget nunc lobortis mattis aliquam faucibus purus. Erat nam at lectus urna duis.
//
Sed euismod nisi porta lorem mollis aliquam ut porttitor leo. Ut tellus elementum sagittis vitae et leo duis ut diam. Elementum curabitur vitae nunc sed velit dignissim. Auctor elit sed vulputate mi sit. Consectetur adipiscing elit ut aliquam purus. Feugiat vivamus at augue eget arcu. Duis ut diam quam nulla porttitor massa id neque. Pharetra magna ac placerat vestibulum lectus mauris ultrices. Non sodales neque sodales ut etiam. Massa ultricies mi quis hendrerit dolor. Est sit amet facilisis magna etiam. Ornare suspendisse sed nisi lacus sed viverra tellus in. //Sed euismod nisi porta lorem mollis aliquam ut porttitor leo. Ut tellus elementum sagittis vitae et leo duis ut diam. Elementum curabitur vitae nunc sed velit dignissim. Auctor elit sed vulputate mi sit. Consectetur adipiscing elit ut aliquam purus. Feugiat vivamus at augue eget arcu. Duis ut diam quam nulla porttitor massa id neque. Pharetra magna ac placerat vestibulum lectus mauris ultrices. Non sodales neque sodales ut etiam. Massa ultricies mi quis hendrerit dolor. Est sit amet facilisis magna etiam. Ornare suspendisse sed nisi lacus sed viverra tellus in.
`) //`)
baseLayer.Print(1, 1, "Hello, [font=bold]world[/font]!") baseLayer.Print(1, 1, "Hello, [font=bold]world[/font]!")
baseLayer.Print(1, 4, "Testing line-[color=orange]spacing[/color]") baseLayer.Print(1, 4, "Testing line-[color=orange]spacing[/color]")
@ -130,18 +130,14 @@ Sed euismod nisi porta lorem mollis aliquam ut porttitor leo. Ut tellus elementu
vp.Render() vp.Render()
}) })
d, _ := time.ParseDuration("166ms") // ~6 fps for terrain d2, _ := time.ParseDuration("16ms")
d2, _ := time.ParseDuration("1ms")
terrainAnimationTicker := time.NewTicker(d) fpsTicker := time.NewTicker(d2)
//fpsTicker := time.NewTicker(d2) fpsCount := 0
//main loop! //main loop!
for { for {
// не оставляйте default в бесконесчном select {} - сожрет всё CPU
select { select {
case <-terrainAnimationTicker.C:
//ctx.Logger().Debug().Msg("hb!")
State.Do(func() {
vp.Render()
})
case key := <-State.input: case key := <-State.input:
switch key { switch key {
case "F10": case "F10":
@ -158,14 +154,14 @@ Sed euismod nisi porta lorem mollis aliquam ut porttitor leo. Ut tellus elementu
return return
default: default:
State.Do(func(){ State.Do(func(){
baseLayer.ClearArea(0, 3, 80, 1) baseLayer.ClearArea(0, 3, 40, 1)
baseLayer.Print(1, 3, "Key: "+key) baseLayer.Print(1, 3, "Key: "+key)
baseLayer.Print(1, 4, "█") baseLayer.Print(1, 4, "█")
return return
}) })
} }
case <- fpsTicker.C:
default: fpsCount++
State.Do(func() { State.Do(func() {
var key, keycode = ui.ReadKey(ctx) var key, keycode = ui.ReadKey(ctx)
if keycode == blt.TK_NONE { if keycode == blt.TK_NONE {
@ -177,16 +173,24 @@ Sed euismod nisi porta lorem mollis aliquam ut porttitor leo. Ut tellus elementu
ctx.Logger().Warn().Msg("...done") ctx.Logger().Warn().Msg("...done")
return return
} }
_ = key
State.input <- key State.input <- key
//time.Sleep(d2) //time.Sleep(d2)
}) })
//animate terrain 5 times slower than fps
if (fpsCount % 10) == 0 {
State.Do(func() {
vp.Render()
})
fpsCount = 0
}
//update screen //update screen
State.Do(func() { State.Do(func() {
blt.Refresh() blt.Refresh()
time.Sleep(d2) //Костыль для убирания 100% CPU time.Sleep(d2) //Костыль для убирания 100% CPU
}) })
} }
} }
ctx.Logger().Warn().Msg("and it continues") ctx.Logger().Warn().Msg("and it continues")

View File

@ -1,10 +1,13 @@
package basic package basic
import ( import (
"github.com/jcerise/gogue/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
"math" "math"
) )
//fixme store separate FovMap, add method IsInMap to it
type FieldOfVision struct { type FieldOfVision struct {
cosTable map[int]float64 cosTable map[int]float64
sinTable map[int]float64 sinTable map[int]float64
@ -31,15 +34,15 @@ func (f *FieldOfVision) SetTorchRadius(radius int) {
} }
} }
func (f *FieldOfVision) SetAllInvisible(gameMap *gamemap.Map) { func (f *FieldOfVision) SetAllInvisible(level *gamemap.Level) {
for x := 0; x < gameMap.Width; x++ { for x := 0; x < level.W; x++ {
for y := 0; y < gameMap.Height; y++ { for y := 0; y < level.H; y++ {
gameMap.Tiles[x][y].Visible = false level.Tiles[x][y].Visible = false
} }
} }
} }
func (f *FieldOfVision) RayCast(playerX, playerY int, gameMap *gamemap.Map) { func (f *FieldOfVision) RayCast(playerCoords types.Coords, level *gamemap.Level) {
// Cast out rays each degree in a 360 circle from the player. If a ray passes over a floor (does not block sight) // 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 // 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 // (blocks sight), stop, as the player will not be able to see past that. Every visible tile will get the Visible
@ -50,11 +53,11 @@ func (f *FieldOfVision) RayCast(playerX, playerY int, gameMap *gamemap.Map) {
ax := f.sinTable[i] ax := f.sinTable[i]
ay := f.cosTable[i] ay := f.cosTable[i]
x := float64(playerX) x := float64(playerCoords.X)
y := float64(playerY) y := float64(playerCoords.Y)
// Mark the players current position as explored // Mark the players current position as explored
tile := gameMap.Tiles[playerX][playerY] tile := level.Tiles[playerCoords.X][playerCoords.Y]
tile.Explored = true tile.Explored = true
tile.Visible = true tile.Visible = true
@ -65,17 +68,17 @@ func (f *FieldOfVision) RayCast(playerX, playerY int, gameMap *gamemap.Map) {
roundedX := int(Round(x)) roundedX := int(Round(x))
roundedY := int(Round(y)) roundedY := int(Round(y))
if x < 0 || x > float64(gameMap.Width-1) || y < 0 || y > float64(gameMap.Height-1) { if x < 0 || x > float64(level.W -1) || y < 0 || y > float64(level.H -1) {
// If the ray is cast outside of the gamemap, stop // If the ray is cast outside of the gamemap, stop
break break
} }
tile := gameMap.Tiles[roundedX][roundedY] tile := level.Tiles[roundedX][roundedY]
tile.Explored = true tile.Explored = true
tile.Visible = true tile.Visible = true
if gameMap.Tiles[roundedX][roundedY].BlocksSight == true { if level.Tiles[roundedX][roundedY].BlocksSight == true {
// The ray hit a wall, go no further // The ray hit a wall, go no further
break break
} }

View File

@ -37,7 +37,7 @@ CurrentShade variable with the contents of the NextShade variable.
If the tested cell is opaque for each angle in the range occludedAngles by the cell, place a 1 at the position If the tested cell is opaque for each angle in the range occludedAngles by the cell, place a 1 at the position
determined by angle%360 in the NextShade string. determined by angle%360 in the NextShade string.
For each angle in the range occludedAngles by the cell, add 1 to the shade value for that cell for each 0 encountered For each angle in the range occludedAngles by the cell, add 1 to the lit value for that cell for each 0 encountered
at the position determined by angle%360 in the CurrentShade string. at the position determined by angle%360 in the CurrentShade string.
Notes Notes
@ -75,7 +75,8 @@ type Cell struct {
types.Coords types.Coords
distance float64 distance float64
occludedAngles []int //indexes of cells in CellList occludedAngles []int //indexes of cells in CellList
shade int //shade value lit int //lit value
wasOccluded bool
} }
type CellList []*Cell type CellList []*Cell
@ -116,7 +117,7 @@ func (ps *precomputedShade) IsInFov(coords types.Coords) bool {
if err != nil { if err != nil {
return false return false
} }
return cell.shade > 0 return cell.lit > 0
} }
func (ps *precomputedShade) SetLightWalls(value bool) { func (ps *precomputedShade) SetLightWalls(value bool) {
@ -141,7 +142,7 @@ func (ps *precomputedShade) PrecomputeFovMap() {
iterCoords := types.Coords{x, y} iterCoords := types.Coords{x, y}
distance := zeroCoords.DistanceTo(iterCoords) distance := zeroCoords.DistanceTo(iterCoords)
if distance <= float64(max) { if distance <= float64(max) {
ps.CellList = append(ps.CellList, &Cell{iterCoords, distance, nil, 0}) ps.CellList = append(ps.CellList, &Cell{iterCoords, distance, nil, 0, false})
} }
} }
} }
@ -223,19 +224,22 @@ func (ps *precomputedShade) recalc(level *gamemap.Level, initCoords types.Coords
} }
//fmt.Printf("\n level coords: %v", lc) //fmt.Printf("\n level coords: %v", lc)
if level.Tiles[lc.X][lc.Y].BlocksSight { for _, angle := range cell.occludedAngles {
level.Tiles[lc.X][lc.Y].Visible = true
for _, angle := range cell.occludedAngles { if level.Tiles[lc.X][lc.Y].BlocksSight {
nextShade[angle] = 1 nextShade[angle] = 1
} }
}
for _, angle := range cell.occludedAngles {
if currentShade[angle] == 0 { if currentShade[angle] == 0 {
cell.shade = cell.shade + 1 cell.lit = cell.lit + 1
} }
} }
if level.Tiles[lc.X][lc.Y].BlocksSight {
level.Tiles[lc.X][lc.Y].Visible = true
}
} }
} }
@ -244,8 +248,8 @@ func (ps *precomputedShade) ComputeFov(level *gamemap.Level, initCoords types.Co
ps.recalc(level, initCoords, radius) ps.recalc(level, initCoords, radius)
for _, cell := range ps.CellList { for _, cell := range ps.CellList {
//fmt.Printf("\n coords: %v, distance: %f, shade: %d", cell.Coords, cell.distance, cell.shade) //fmt.Printf("\n coords: %v, distance: %f, lit: %d", cell.Coords, cell.distance, cell.lit)
if cell.shade > 0 { if cell.lit > 0 {
cs, err := ps.toLevelCoords(level, initCoords, cell.Coords) cs, err := ps.toLevelCoords(level, initCoords, cell.Coords)
if err != nil { if err != nil {
continue continue

View File

@ -59,7 +59,7 @@ func TestPrecompShade(t *testing.T) {
level.Tiles[10][11] = gamemap.NewWall() level.Tiles[10][11] = gamemap.NewWall()
level.Tiles[11][10] = gamemap.NewWall() level.Tiles[11][10] = gamemap.NewWall()
ppFov.ComputeFov(level, playerCoords, 15) ppFov.ComputeFov(level, playerCoords, 12)
fmt.Printf("\n\n") fmt.Printf("\n\n")

View File

@ -7,8 +7,8 @@ import (
) )
//fixme move to config //fixme move to config
var minRoomSize = 3 var minRoomSize = 3
var maxRoomSize = 11 var maxRoomSize = 22
var maxrooms = 100 var maxrooms = 30
//fixme make closure to stack them //fixme make closure to stack them
func DefaultGen(l *gamemap.Level) *gamemap.Level { func DefaultGen(l *gamemap.Level) *gamemap.Level {
@ -35,27 +35,51 @@ func DefaultGen(l *gamemap.Level) *gamemap.Level {
newRoom.Center = types.Coords{newRoom.X + newRoom.W / 2, newRoom.Y + newRoom.H / 2} newRoom.Center = types.Coords{newRoom.X + newRoom.W / 2, newRoom.Y + newRoom.H / 2}
failed := false failed := false
for _, otherRoom := range rooms {
if otherRoom.Intersects(newRoom.Rect) { if !l.InBounds(types.Coords{newRoom.X, newRoom.Y}) {
failed = true failed = true
break }
if !failed && !l.InBounds(types.Coords{newRoom.X + newRoom.W, newRoom.Y + newRoom.H}) {
failed = true
}
if !failed {
for _, otherRoom := range rooms {
if otherRoom.Intersects(newRoom.Rect) {
failed = true
break
}
} }
} }
if !failed { if !failed {
rooms = append(rooms, newRoom) rooms = append(rooms, newRoom)
} }
} }
//fillage := types.RectFill{
// Top: func() *gamemap.Tile {return gamemap.NewWall()},
// Bottom: func() *gamemap.Tile {return gamemap.NewWall()},
// Left: func() *gamemap.Tile {return gamemap.NewWall()},
// Right: func() *gamemap.Tile {return gamemap.NewWall()},
// BottomLeft: func() *gamemap.Tile {return gamemap.NewWall()},
// BottomRight: func() *gamemap.Tile {return gamemap.NewWall()},
// TopLeft: func() *gamemap.Tile {return gamemap.NewWall()},
// TopRight: func() *gamemap.Tile {return gamemap.NewWall()},
// Body: func() *gamemap.Tile {return gamemap.NewFloor()},
//}
fillage := types.RectFill{ fillage := types.RectFill{
Top: func() *gamemap.Tile {return gamemap.NewWall()}, Top: func() *gamemap.Tile {return gamemap.NewWaterTile()},
Bottom: func() *gamemap.Tile {return gamemap.NewWall()}, Bottom: func() *gamemap.Tile {return gamemap.NewWaterTile()},
Left: func() *gamemap.Tile {return gamemap.NewWall()}, Left: func() *gamemap.Tile {return gamemap.NewWaterTile()},
Right: func() *gamemap.Tile {return gamemap.NewWall()}, Right: func() *gamemap.Tile {return gamemap.NewWaterTile()},
BottomLeft: func() *gamemap.Tile {return gamemap.NewWall()}, BottomLeft: func() *gamemap.Tile {return gamemap.NewWaterTile()},
BottomRight: func() *gamemap.Tile {return gamemap.NewWall()}, BottomRight: func() *gamemap.Tile {return gamemap.NewWaterTile()},
TopLeft: func() *gamemap.Tile {return gamemap.NewWall()}, TopLeft: func() *gamemap.Tile {return gamemap.NewWaterTile()},
TopRight: func() *gamemap.Tile {return gamemap.NewWall()}, TopRight: func() *gamemap.Tile {return gamemap.NewWaterTile()},
Body: func() *gamemap.Tile {return gamemap.NewFloor()}, Body: func() *gamemap.Tile {return gamemap.NewDeepWaterTile()},
} }
for idx, room := range rooms { for idx, room := range rooms {
@ -80,28 +104,33 @@ func connectRooms (l *gamemap.Level, room, otherRoom *gamemap.Room, fillage type
func digHTunnel(l *gamemap.Level, x1,x2,y int, fillage types.RectFill) { func digHTunnel(l *gamemap.Level, x1,x2,y int, fillage types.RectFill) {
var start, finish int var start, finish int
if x1 > x2 { if x1 < x2 {
start = x1 start = x1
finish = x2 finish = x2
} else { } else {
start = x2 start = x2
finish = x1 finish = x1
} }
for i := start; i <= finish - 1; i++ { for i := start; i <= finish; i++ {
l.Tiles[i][y] = fillage.Body.(func() *gamemap.Tile)() if l.InBounds(types.Coords{i, y}) {
l.Tiles[i][y] = fillage.Body.(func() *gamemap.Tile)()
//l.Tiles[i][y] = gamemap.NewFloor()
}
} }
} }
func digVTunnel(l *gamemap.Level, y1,y2,x int, fillage types.RectFill) { func digVTunnel(l *gamemap.Level, y1,y2,x int, fillage types.RectFill) {
var start, finish int var start, finish int
if y1 > y2 { if y1 < y2 {
start = y1 start = y1
finish = y2 finish = y2
} else { } else {
start = y2 start = y2
finish = y1 finish = y1
} }
for i := start; i <= finish - 1; i++ { for i := start; i <= finish; i++ {
l.Tiles[x][i] = fillage.Body.(func() *gamemap.Tile)() if l.InBounds(types.Coords{x, i}) {
l.Tiles[x][i] = fillage.Body.(func() *gamemap.Tile)()
}
} }
} }

View File

@ -39,8 +39,8 @@ type Tile struct {
BlocksPass bool BlocksPass bool
BlocksSight bool BlocksSight bool
Explored bool Explored bool
Visible bool
MustDraw bool MustDraw bool
Visible bool
Colordance bool Colordance bool
} }
@ -94,8 +94,9 @@ func NewWaterTile() *Tile {
Explored: false, Explored: false,
MustDraw: true, //fixme debug MustDraw: true, //fixme debug
Colordance: true, Colordance: true,
Appearance: &Appearance{ Appearance: &Appearance{
Char: ".", Char: " ",
ColorSet: &TileColorSet{ ColorSet: &TileColorSet{
current: ch, current: ch,
Fg: func() uint32 { return blt.ColorFromARGB(255, 220, 220, 250) }, Fg: func() uint32 { return blt.ColorFromARGB(255, 220, 220, 250) },
@ -103,19 +104,20 @@ func NewWaterTile() *Tile {
return blt.ColorFromARGB( return blt.ColorFromARGB(
255, 255,
ch.R, ch.R,
colordance(ch.G, 2, 42, 4), colordance(ch.G, 0, 15, 2),
colordance(ch.B, 180, 229, 12), colordance(ch.B, 120, 220, 12),
) )
}, },
DarkFg: func() uint32 { return blt.ColorFromARGB(255, 30, 20, 50) }, DarkFg: func() uint32 { return blt.ColorFromARGB(255, 30, 20, 50) },
DarkBg: func() uint32 { return blt.ColorFromARGB(255, 7, 7, 30) }, DarkBg: func() uint32 { return blt.ColorFromARGB(255, 7, 7, 30) },
}, },
}, },
} }
} }
func NewDeepWaterTile() *Tile { func NewDeepWaterTile() *Tile {
ch := &ColorHolder{5, 2, 154} ch := &ColorHolder{5, 2, 122}
return &Tile{ return &Tile{
Name: "Deep Water", Name: "Deep Water",
Description: "Deep water", Description: "Deep water",
@ -133,8 +135,8 @@ func NewDeepWaterTile() *Tile {
return blt.ColorFromARGB( return blt.ColorFromARGB(
255, 255,
ch.R, ch.R,
colordance(ch.G, 0, 15, 2), colordance(ch.G, 2, 42, 4),
colordance(ch.B, 120, 180, 5), colordance(ch.B, 180, 229, 12),
) )
}, },
DarkFg: func() uint32 { return blt.ColorFromARGB(255, 30, 20, 50) }, DarkFg: func() uint32 { return blt.ColorFromARGB(255, 30, 20, 50) },

25
engine/mob/mob.go Normal file
View File

@ -0,0 +1,25 @@
package mob
import (
"lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
"lab.zaar.be/thefish/alchemyst-go/engine/types"
)
type Mob struct {
*gamemap.Appearance
*types.Coords
BlocksPass bool
}
func (m *Mob) Walk(dx, dy int) {
}
func (m *Mob) Render() {
}
func (m *Mob) MoveToCoords(c types.Coords) {
}

5
engine/mob/player.go Normal file
View File

@ -0,0 +1,5 @@
package mob
type Player struct {
*Mob
}

View File

@ -14,10 +14,10 @@ const FPS_LIMIT = 60
type ViewPort struct { type ViewPort struct {
*types.Rect *types.Rect
level *gamemap.Level level *gamemap.Level
layer *Layer layer *Layer
Fov fov.Fov Fov fov.Fov
playerCoords types.Coords playerCoords types.Coords
playerTorchRadius int playerTorchRadius int
} }
@ -32,7 +32,7 @@ func NewViewPort(x, y, w, h int, level *gamemap.Level, layer *Layer) *ViewPort {
Fov: fov, Fov: fov,
} }
vp.playerCoords = types.Coords{10,10} vp.playerCoords = types.Coords{10, 10}
vp.playerTorchRadius = 10 vp.playerTorchRadius = 10
return &vp return &vp
@ -116,16 +116,43 @@ func (vp *ViewPort) ToVPCoords(c *types.Coords) (newCoords *types.Coords, err er
// } // }
//} //}
var redraw = true
var fovRecompute = true
func (vp *ViewPort) Render() { func (vp *ViewPort) Render() {
if fovRecompute {
vp.layer.Clear(vp.Rect)
fovRecompute = false
redraw = true
//fixme
vp.Fov.ComputeFov(vp.level, vp.playerCoords, vp.playerTorchRadius)
}
for y := 0; y < vp.H; y++ { for y := 0; y < vp.H; y++ {
for x := 0; x < vp.W; x++ { for x := 0; x < vp.W; x++ {
mapCoords := types.Coords{vp.X + x, vp.Y + y} mapCoords := types.Coords{vp.X + x, vp.Y + y}
tile := vp.level.Tiles[mapCoords.X][mapCoords.Y] tile := vp.level.Tiles[mapCoords.X][mapCoords.Y]
fg := tile.ColorSet.Fg()
bg := tile.ColorSet.Bg() if tile.Visible {
vp.layer.WithRawColor(fg). if tile.MustDraw {
PutWithRawBackground(mapCoords.X, mapCoords.Y, tile.Char, bg) //darkened version of landscape
vp.layer.WithRawColor(tile.ColorSet.DarkFg()).
PutWithRawBackground(mapCoords.X, mapCoords.Y, tile.Char, tile.ColorSet.DarkBg())
}
} else {
if redraw == true || tile.Colordance {
vp.layer.WithRawColor(tile.ColorSet.Fg()).
PutWithRawBackground(mapCoords.X, mapCoords.Y, tile.Char, tile.ColorSet.Bg())
tile.Explored = true
tile.MustDraw = true
}
}
//fg := tile.ColorSet.Fg()
//bg := tile.ColorSet.Bg()
//vp.layer.WithRawColor(fg).
// PutWithRawBackground(mapCoords.X, mapCoords.Y, tile.Char, bg)
} }
} }