// newTrooper creates a trooper for the given level. // level 0: 1x1x1 : 0 edge cubes 0 panels, (only 1 cube) // level 1: 2x2x2 : 8 edge cubes + 6 panels of 0x0 cubes + 0x0x0 center. // level 2: 3x3x3 : 20 edge cubes + 6 panels of 1x1 cubes + 1x1x1 center. // level 3: 4x4x4 : 32 edge cubes + 6 panels of 2x2 cubes + 2x2x2 center. // ... func newTrooper(part vu.Pov, level int) *trooper { tr := &trooper{} tr.lvl = level tr.part = part tr.bits = []box{} tr.ipos = []int{} tr.mid = tr.lvl*tr.lvl*tr.lvl*8 - (tr.lvl-1)*(tr.lvl-1)*(tr.lvl-1)*8 // set max energies. tr.cemax, tr.temax = 1000, 1000 // special case for a level 0 (start screen) trooper. if tr.lvl == 0 { cube := newCube(tr.part, 0, 0, 0, 1) cube.edgeSort(1) tr.bits = append(tr.bits, cube) return tr } // create the panels. These are used in each level after level 1. cubeSize := 1.0 / float64(tr.lvl+1) centerOffset := cubeSize * 0.5 panelCenter := float64(tr.lvl) * centerOffset tr.bits = append(tr.bits, newPanel(tr.part, panelCenter, 0.0, 0.0, tr.lvl)) tr.bits = append(tr.bits, newPanel(tr.part, -panelCenter, 0.0, 0.0, tr.lvl)) tr.bits = append(tr.bits, newPanel(tr.part, 0.0, panelCenter, 0.0, tr.lvl)) tr.bits = append(tr.bits, newPanel(tr.part, 0.0, -panelCenter, 0.0, tr.lvl)) tr.bits = append(tr.bits, newPanel(tr.part, 0.0, 0.0, panelCenter, tr.lvl)) tr.bits = append(tr.bits, newPanel(tr.part, 0.0, 0.0, -panelCenter, tr.lvl)) // troopers are made out of cubes and panels. mx := float64(-tr.lvl) for cx := 0; cx <= tr.lvl; cx++ { my := float64(-tr.lvl) for cy := 0; cy <= tr.lvl; cy++ { mz := float64(-tr.lvl) for cz := 0; cz <= tr.lvl; cz++ { // create the outer edges. newCells := 0 if (cx == 0 || cx == tr.lvl) && (cy == 0 || cy == tr.lvl) && (cz == 0 || cz == tr.lvl) { // corner cube newCells = 1 } else if (cx == 0 || cx == tr.lvl) && (cy == 0 || cy == tr.lvl) || (cx == 0 || cx == tr.lvl) && (cz == 0 || cz == tr.lvl) || (cy == 0 || cy == tr.lvl) && (cz == 0 || cz == tr.lvl) { // edge cube newCells = 2 } else if cx == 0 || cx == tr.lvl || cy == 0 || cy == tr.lvl || cz == 0 || cz == tr.lvl { // side cubes are added to a panel. x, y, z := mx*centerOffset, my*centerOffset, mz*centerOffset if cx == tr.lvl && x > y && x > z { tr.bits[0].(*panel).addCube(x, y, z, float64(cubeSize)) } else if cx == 0 && x < y && x < z { tr.bits[1].(*panel).addCube(x, y, z, float64(cubeSize)) } else if cy == tr.lvl && y > x && y > z { tr.bits[2].(*panel).addCube(x, y, z, float64(cubeSize)) } else if cy == 0 && y < x && y < z { tr.bits[3].(*panel).addCube(x, y, z, float64(cubeSize)) } else if cz == tr.lvl && z > x && z > y { tr.bits[4].(*panel).addCube(x, y, z, float64(cubeSize)) } else if cz == 0 && z < x && z < y { tr.bits[5].(*panel).addCube(x, y, z, float64(cubeSize)) } } if newCells > 0 { x, y, z := mx*centerOffset, my*centerOffset, mz*centerOffset cube := newCube(tr.part, x, y, z, float64(cubeSize)) cube.edgeSort(newCells) tr.bits = append(tr.bits, cube) } mz += 2 } my += 2 } mx += 2 } tr.addCenter() // its easier to remember the initial positions than recalculate them. tr.ipos = make([]int, len(tr.bits)) for cnt, b := range tr.bits { tr.ipos[cnt] = b.box().ccnt } // create the noises the trooper can make. tr.noise = part.NewNoise() tr.noise.Add("teleport") // teleportSound tr.noise.Add("fetch") // fetchSound tr.noise.Add("cloak") // cloakSound tr.noise.Add("decloak") // decloakSound tr.noise.Add("collide") // collideSound return tr }