Esempio n. 1
0
// nextSpot picks where the sentinel will be going to by considering
// all the surrounding spaces and picking from the valid ones.
func (s *sentinel) nextSpot(plan grid.Grid) *gridSpot {
	at := s.next
	was := s.prev
	w, h := plan.Size()

	// using knowledge that the grid starts at 0, 0 and goes to size, -size.
	// and that the outside border is also valid.
	choices := []*gridSpot{}
	if at.x >= -1 && at.y >= -1 && at.x <= w && at.y <= h {
		if s.isValidSpot(plan, w, h, was, at.x+1, at.y) {
			choices = append(choices, &gridSpot{at.x + 1, at.y})
		}
		if s.isValidSpot(plan, w, h, was, at.x-1, at.y) {
			choices = append(choices, &gridSpot{at.x - 1, at.y})
		}
		if s.isValidSpot(plan, w, h, was, at.x, at.y+1) {
			choices = append(choices, &gridSpot{at.x, at.y + 1})
		}
		if s.isValidSpot(plan, w, h, was, at.x, at.y-1) {
			choices = append(choices, &gridSpot{at.x, at.y - 1})
		}
	}
	if len(choices) > 0 {
		way := 0
		if len(choices) > 1 {
			way = rand.Intn(len(choices))
		}
		return choices[way]
	}
	return was // backtrack should never happen.
}
Esempio n. 2
0
// isValidSpot checks that a spot is valid for a sentinel, i.e. not a wall or the
// previous location.
func (s *sentinel) isValidSpot(plan grid.Grid, w, h int, old *gridSpot, x, y int) bool {
	if x == old.x && y == old.y { // can't use previous position.
		return false
	}
	if x >= 0 && y >= 0 && x < w && y < h { // exclude walls.
		return plan.IsOpen(x, y)
	}
	if x >= -1 && y >= -1 && x <= w && y <= h { // outside edge ok.
		return true
	}
	return false // anywhere else is a no-go zone.
}
Esempio n. 3
0
// buildFloorPlan creates the level layout.
func (lvl *level) buildFloorPlan(root vu.Pov, hd *hud, plan grid.Grid) {
	width, height := plan.Size()
	for x := 0; x < width; x++ {
		for y := 0; y < height; y++ {
			xc := float64(x * lvl.units)
			yc := float64(-y * lvl.units)
			band := plan.Band(x, y) / 3
			if x == width/2 && y == height/2 {
				lvl.gcx, lvl.gcy = x, y // remember the maze center location
				lvl.center = root.NewPov().SetLocation(xc, 0, yc)
				m := lvl.center.NewModel("uvra").LoadMesh("tile").AddTex("drop1")
				m.SetAlpha(0.7)
				m.SetUniform("spin", 1.0)
				m.SetUniform("fd", lvl.fade)
			} else if plan.IsOpen(x, y) {

				// the floor tiles.
				tileLabel := lvl.tileLabel(band)
				tile := root.NewPov().SetLocation(xc, 0, yc)
				m := tile.NewModel("uva").LoadMesh("tile").AddTex(tileLabel)
				m.SetAlpha(0.7)
				m.SetUniform("fd", lvl.fade)

				// remember the tile locations for drop spots inside the maze.
				lvl.cc.addDropLocation(x, y)
			} else {

				// draw flat on the y plane with the maze extending into the screen.
				wm := lvl.wallMeshLabel(band)
				wt := lvl.wallTextureLabel(band)
				wall := root.NewPov().SetLocation(xc, 0, yc)
				m := wall.NewModel("uva").LoadMesh(wm).AddTex(wt)
				m.SetUniform("fd", lvl.fade)
				lvl.walls = append(lvl.walls, wall)

				// add the wall to the minimap
				hd.addWall(xc, yc)
			}
		}
	}

	// add core drop locations around the outside of the maze.
	for x := -1; x < width+1; x++ {
		lvl.cc.addDropLocation(x, -1)
		lvl.cc.addDropLocation(x, height)
	}
	for y := 0; y < height; y++ {
		lvl.cc.addDropLocation(-1, y)
		lvl.cc.addDropLocation(width, y)
	}
}