Fat Old Yeti

Fat Old Yeti

Being a blog of thoughts and tutorials from a hobby game developer.

08 Feb 2021

Roguelike Tutorial 9

Roguelike in Go - Part 9 (Better Field of View)

All of the code for this tutorial can be found here.

So, we now have a good field of view going, but it looks kind of bleak. Normal implementations of Fog of War show the player what they have already uncovered, at least from a terrain perspective. We may want to hide the movements of any monsters in areas that the player cannot currently see, but we can still show them the territory they have uncovered.

This type of behavior is expected, so let’s give our players that. I broke this up in two parts because if you wish to not give them this (like for a horror based game), you could just skip this part entirely and have what you want.

All of the changes take place in level.go.

Add this to our MapTile type:

IsRevealed bool

This will simply indicate to us that the tile has, at one time, been revealed to us. Fairly simple.

In the function createTiles, we need to edit where the tile is first generated by changing the code to this:

tile := MapTile{
	PixelX: x * gd.TileWidth,
	PixelY: y * gd.TileHeight,
	Blocked: true,
	Image: wall,
	IsRevealed: false,
}

Note that the only change here is that we now set IsRevealed to false.

Lastly we change DrawLevel so that it also draws revealed tiles. If a tile is revealed but not currently visible, we want to shade it out a bit. We do this with the DrawImageOptions.

//DrawLevel draws the level onto the screen.
func (level *Level) DrawLevel(screen *ebiten.Image) {
	gd := NewGameData()

	for x := 0; x < gd.ScreenWidth; x++ {
		for y := 0; y < gd.ScreenHeight; y++ {
			idx := level.GetIndexFromXY(x, y)
			tile := level.Tiles[idx]
			isVis := level.PlayerVisible.IsVisible(x, y)
			if isVis {
				op := &ebiten.DrawImageOptions{}
				op.GeoM.Translate(float64(tile.PixelX), float64(tile.PixelY))
				screen.DrawImage(tile.Image, op)
				level.Tiles[idx].IsRevealed = true
			} else  if tile.IsRevealed == true {
				op := &ebiten.DrawImageOptions{}
				op.GeoM.Translate(float64(tile.PixelX), float64(tile.PixelY))
				op.ColorM.Translate(100, 100, 100, 0.35)
				screen.DrawImage(tile.Image, op)
			}
		}
	}
}

I know there is some repeated code here. I’m not sure how I want to handle this function later so if we decide we are keeping this as it, we will fix it later.

And that, as it stands, should work perfectly.

better

As always, if you have any questions, feel free to contact me at fatoldyeti@gmail.com or @idiotcoder on the gophers slack.