Пример #1
0
// Update state of live aliens
func updateLive(dt float32) {
	x0, y0 := Zoo[0].Sx, Zoo[0].Sy
	for k := 1; k < len(Zoo); k++ {
		c := &Zoo[k]
		// Update S and v
		bounce(&c.Sx, &c.vx, xSize-1, dt)
		bounce(&c.Sy, &c.vy, ySize-1, dt)
		// Update Progress
		c.Progress += c.fallRate * dt
		// Update health
		if c.health > 0 {
			// Healthy alien
			if c.Progress >= 1 {
				// Alien reached full power!
				if !isPractice {
					gameState = GameLose
				}
				// Mark alien for culling
				c.health = deathThreshold
				continue
			}
			dx := c.Sx - x0
			dy := c.Sy - y0
			if dx*dx+dy*dy <= killRadius2 {
				const killTime = 0.1
				c.health -= healthType(dt * (float32(initialHealth) / killTime))
				if c.health <= 0 {
					c.health = -1 // Transition to death sequence
					sound.Play(sound.Twang, alienPitch[c.Id])
				}
				c.Show = true
			} else {
				c.Show = showAlways
			}
		} else {
			// Dying alien
			c.health -= 1
			c.Show = true
		}
		// Update amplitude
		if c.health > 0 {
			c.Amplitude = math32.Sqrt(c.Progress)
		} else {
			c.Amplitude -= dt * (1 / amplitudeDieTime)
			if c.Amplitude < 0 {
				// Alien croaked.  Mark as dead
				c.health = deathThreshold
				if !isPractice {
					TallyKill()
				}
			}
		}
	}
}
Пример #2
0
func tryBirth(dt float32) {
	j := len(Zoo)
	if nLiveMax > len(zooStorage)-1 {
		panic(fmt.Sprintf("tryBirth: nLiveMax=%v > len(zooStorage)-1=%v\n", nLiveMax, len(zooStorage)-1))
	}
	if nLive := j - 1; nLive >= nLiveMax {
		// Already reached population limit
		return
	}
	if rand.Float32() > dt*birthRate {
		return
	}

	// Swap in random id
	avail := len(zooStorage) - len(Zoo)
	k := rand.Intn(avail) + j
	zooStorage[j].Id, zooStorage[k].Id = zooStorage[k].Id, zooStorage[j].Id
	Zoo = zooStorage[:j+1]

	// Initialize the alien
	Zoo[j].initAlien()
	sound.Play(sound.AntiTwang, alienPitch[Zoo[j].Id])
}
Пример #3
0
/* The "boot sequence" was created in the 1990's to create eye candy while
   the program was slowly computing lookup tables.  By the mid-2000s machines
   were so fast that it has no practical purpose anymore.  But to retain
   the original look of Frequon Invaders, it's done nonethless, with the
   teletype techno-babble.  It like the flutes on concrete columnes. */
func advanceBootSequence(dt float32) {
	if bootSequenceIndex < 0 || bootSequenceIndex >= 10 {
		return
	}
	bootSequenceFrac += dt
	if bootSequenceFrac < bootSequencePeriod {
		return
	}
	bootSequenceFrac = 0
	n := bootSequenceIndex
	bootSequenceIndex = n + 1
	if 1 <= n && n <= 8 {
		teletype.PrintUpper(grammar.Generate(rune('0' + n)))
		teletype.PrintChar('\n')
	}
	if 0 < n && n <= 8 {
		sound.Play(sound.Wobble, float32(n+1)*0.25)
	}
	switch n {
	case 1:
		break
	case 2, 3, 4:
		dividerCount = n - 1
	case 5:
		fallIsVisible = true
	case 6:
		radarIsVisible = true
		radarIsRunning = true
	case 7:
		scoreIsVisible = true
	case 9:
		// C++ original does following actions for n==8, but that hides the 8th techobabble.
		fourierIsVisible = true
		setZoom(zoomGrow)
		teletype.Reset()
	}
}
Пример #4
0
// At certain scores, certain kinds of damages become possible.
// Here are the thresholds:
//
//		0:  1 stationary alien
//		1:  half-speed alien
//		2:  full-speed alien
//		4:  2 stationary aliens
//		8:  phase, real, or imaginary lost, 1 stationary alien
//		12: 3 aliens
//		16: lose 1 color bit
//		20: 4 aliens
// 		24: lose 2 color bits
//		32: compress x or y
//
// n is score
func setDifficulty(n int) {
	const simpleScheme = coloring.AllBits

	if n == 0 {
		nLiveMax = 1
		velocityMax = 0
		compressX = 1
		compressY = 1
		scheme = simpleScheme
		return
	}

	if n >= 64 {
		gameState = GameWin
		return
	}

	// Set nLiveMax, which is the max number of aliens simultaneously running.
	var liveLimit int
	if n < 4 {
		liveLimit = 1
	} else {
		liveLimit = (n-4)/7 + 2
	}
	if nLiveMax < liveLimit {
		if rand.Intn(2) == 1 {
			nLiveMax++
			// The game is now harder.  Simplify other things that make the game not quite so hard.
			if n < 8 {
				velocityMax = 0
			} else {
				velocityMax /= 2
			}
			if scheme != simpleScheme {
				scheme = simpleScheme
				sound.Play(sound.Bell, 1.5)
			}
			return
		}
	}

	// See if velocityMax should be increased
	// FIXME - should be scaled to screen size
	var velocityLimit float32
	if n <= 4 {
		velocityLimit = float32(n * 15)
	} else {
		velocityLimit = 60
	}
	if velocityMax < velocityLimit {
		if rand.Intn(2) == 1 {
			velocityMax += velocityLimit * 0.5
			if velocityMax > velocityLimit {
				velocityMax = velocityLimit
			}
			if nLiveMax > 1 {
				// Ease up on live limit
				nLiveMax--
			}
			// The game is now harder.
			return
		}
	}

	// Now consider a change in the radar scheme.
	if n >= 8 {
		if rand.Intn(2) == 1 {
			s := scheme
			if s&coloring.CoordinateBits == coloring.CoordinateBits {
				// Break the radar by removing phase, real, or imaginary information.
				switch rand.Intn(3) {
				case 0:
					s &= ^coloring.PhaseBit
				case 1:
					s &= ^coloring.RealBit
				case 2:
					s &= ^coloring.ImagBit
				}
				// Play sound announcing damage.
				sound.Play(sound.Broken, 0.5)
			} else {
				// Fix the radar by restoring all coordinate information (but not color)
				s |= coloring.CoordinateBits
				sound.Play(sound.Bell, 1)
			}
			// Commit the new scheme
			scheme = s
			if s&coloring.CoordinateBits != coloring.CoordinateBits {
				// Game is harder.
				return
			}
		}
	}

	// Consider changing color failures.
	if n >= 16 {
		r := rand.Intn(6)
		if r&1 == 0 {
			var minOnes int
			if n >= 24 {
				minOnes = 1
			} else {
				minOnes = 2
			}
			s := scheme ^ coloring.RedBit<<uint(r%3)
			if bitCount(s&coloring.ColorBits) >= minOnes {
				scheme = s
				// Game is harder
				sound.Play(sound.Broken, 1)
				return
			}
		}
	}

	// Consider compression
	if n >= 32 {
		compressed := false
		switch rand.Intn(2) {
		case 0:
			if compressX > 1./16. {
				compressX *= 0.5
				compressed = true
			}
		case 1:
			if compressY > 1./16. {
				compressY *= 0.5
				compressed = true
			}
		}
		if compressed {
			// Ease up on lost colors
			// FIXME - consider restoring only one color bit
			scheme |= coloring.ColorBits
			if nLiveMax > 1 {
				// Ease up on live limit
				nLiveMax--
			}
			sound.Play(sound.Broken, 0.75)
			return
		}
	}
}