package mainwindow import ( "errors" "lab.zaar.be/thefish/alchemyst-go/engine/fov" "lab.zaar.be/thefish/alchemyst-go/engine/fov/precomputed_shade" "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" "lab.zaar.be/thefish/alchemyst-go/engine/types" ) var NotInViewError = errors.New("not in ViewPort") const FPS_LIMIT = 60 type ViewPort struct { *types.Rect level *gamemap.Level layer *Layer Fov fov.Fov playerCoords types.Coords playerTorchRadius int } func NewViewPort(x, y, w, h int, level *gamemap.Level, layer *Layer) *ViewPort { //fixme fov := precomputed_shade.NewPrecomputedShade(15) fov.Init() vp := ViewPort{ Rect: &types.Rect{x, y, w, h}, level: level, layer: layer, Fov: fov, } vp.playerCoords = types.Coords{10, 10} vp.playerTorchRadius = 10 return &vp } func (vp *ViewPort) Move(c *types.Coords) { x := c.X - vp.Rect.W/2 y := c.Y - vp.Rect.H/2 if x < 0 { x = 0 } if y < 0 { y = 0 } if x > vp.level.W-vp.W { x = vp.level.W - vp.W } if y > vp.level.H-vp.H { x = vp.level.H - vp.H } //if x != vp.X || y != vp.Y { State.FovRecompute <- struct{}{}} vp.X, vp.Y = x, y } func (vp *ViewPort) ToVPCoords(c *types.Coords) (newCoords *types.Coords, err error) { //coords on map to coords on vp x, y := c.X-vp.X, c.Y-vp.Y if x < 0 || y < 0 || x >= vp.W || y >= vp.H { return &types.Coords{-1, -1}, NotInViewError } return &types.Coords{x, y}, nil } ////call only from main thread //func (vp *ViewPort) Render() { // //fixme get these from state chan(s) // var fpsTicker int // var fovRecompute bool = true // redraw := false // //fixme get player instance // // vp.Move(&vp.playerCoords) // //fixme detect fovRecompute // if fovRecompute { // vp.layer.Clear(vp.Rect) // fovRecompute = false // redraw = true // //fixme // // vp.Fov.ComputeFov(vp.level, vp.playerCoords, vp.playerTorchRadius) // } // //increase ticker // fpsTicker++ // // if redraw || fpsTicker%(FPS_LIMIT/10) == 0 { // fpsTicker = 0 // // for y := 0; y < vp.H; y++ { // for x := 0; x < vp.W; x++ { // mapCoords := types.Coords{vp.X + x, vp.Y + y} // tile := vp.level.Tiles[mapCoords.X][mapCoords.Y] // visible := vp.Fov.IsInFov(mapCoords) // if !visible { // if tile.MustDraw { // //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 // } // } // } // } // // } //} var redraw = true var fovRecompute = true func (vp *ViewPort) Render() { if fovRecompute { vp.layer.Clear(vp.Rect) fovRecompute = false redraw = true vp.Fov.ComputeFov(vp.level, vp.playerCoords, vp.playerTorchRadius) } if redraw { for y := 0; y < vp.H; y++ { for x := 0; x < vp.W; x++ { mapCoords := types.Coords{vp.X + x, vp.Y + y} tile := vp.level.GetTile(mapCoords) if tile.Explored || tile.MustDraw || tile.Visible { vp.layer.PutToBase(mapCoords.X, mapCoords.Y, tile.GetChar(), tile.GetRawColor(), tile.GetRawBgColor()) } } } //redraw = false } }