Example #1
0
// Draw the "fall" view onto the given PixMap.
func Draw(pm nimble.PixMap, invaders []Invader) {
	if pm.Width() != background.Width() || pm.Height() != background.Height() {
		panic("fall.Draw: pm and background differ in size")
	}

	drawDot := false
	time := nimble.Now()
	if time-lastDotTime >= dotTimeInterval {
		lastDotTime = time
		drawDot = true
	}

	pm.Copy(0, 0, &background)
	xScale := float32(pm.Width() - tickHalfWidth)   // Avoid clipping tic on right side
	yScale := float32(pm.Height() - tickHalfHeight) // Avoid clippling tic on bottom
	xOffset := float32(0)
	yOffset := float32(0)
	for _, inv := range invaders {
		x := int32(inv.Amplitude*xScale + xOffset)
		y := int32(inv.Progress*yScale + yOffset)
		r := nimble.Rect{
			Left:   x - tickHalfWidth,
			Top:    y - tickHalfHeight,
			Right:  x + tickHalfWidth,
			Bottom: y + tickHalfHeight,
		}
		pm.DrawRect(r, inv.Color)
		background.DrawRect(r, nimble.Black)
		if drawDot {
			if doty := r.Top - 1; background.Contains(x, doty) {
				background.SetPixel(x, doty, inv.Color)
			}
		}
	}
}
Example #2
0
func DrawMenuBar(pm nimble.PixMap, menuBar []*Menu) {
	// Draw menu
	x := int32(0)
	for _, m := range menuBar {
		m.Draw(pm, x, 0)
		w, _ := m.TabSize()
		x += w
	}
	h := menuFont.Height()
	pm.DrawRect(nimble.Rect{Top: 0, Left: x, Bottom: h, Right: pm.Width()}, backgroundColor)
	pm.DrawRect(nimble.Rect{Top: h, Left: x, Bottom: h + 1, Right: pm.Width()}, separatorColor)
}
// drawFrequonsFourier draws the frequency-domain representation of Frequons.
func drawFrequonsFourier(pm nimble.PixMap) {
	c := universe.Zoo
	h := harmonicStorage[:len(c)]

	var ampScale float32
	if autoGain.Value {
		// Compute L1 norm of amplitudes
		norm := float32(0)
		for i := range c {
			norm += math32.Abs(c[i].Amplitude)
		}
		ampScale = 1 / norm
	} else {
		ampScale = 1 / float32(len(c))
	}
	fracX, fracY := universe.BoxFraction()
	fracX *= zoomCompression
	fracY *= zoomCompression
	sizeX, sizeY := pm.Size()

	// Set up harmonics
	// (cx,cy) is center of fourier view
	cx, cy := 0.5*float32(sizeX)*fracX, 0.5*float32(sizeY)*fracY
	α, β := -0.5*cx, -0.5*cy
	ωScale := 200. / float32(sizeX*sizeY)
	for i := range h {
		ωx := (c[i].Sx - cx) * ωScale
		ωy := (c[i].Sy - cy) * ωScale
		h[i].Ωx = ωx
		h[i].Ωy = ωy
		h[i].Phase = α*ωx + β*ωy + phaseRoll
		// Scale amplitude so that DFT values fit within domain of color lookup table.
		h[i].Amplitude = c[i].Amplitude * ampScale
	}

	marginX := int32(math32.Round(0.5 * float32(sizeX) * (1 - fracX)))
	marginY := int32(math32.Round(0.5 * float32(sizeY) * (1 - fracY)))
	fourier.Draw(pm.Intersect(nimble.Rect{
		Left:   marginX,
		Right:  sizeX - marginX,
		Top:    marginY,
		Bottom: sizeY - marginY,
	}), h, universe.Scheme())
	if marginX != 0 || marginY != 0 {
		pm.DrawRect(nimble.Rect{Left: 0, Right: sizeX, Top: 0, Bottom: marginY}, nimble.Black)
		pm.DrawRect(nimble.Rect{Left: 0, Right: sizeX, Top: sizeY - marginY, Bottom: sizeY}, nimble.Black)
		pm.DrawRect(nimble.Rect{Left: 0, Right: marginX, Top: marginY, Bottom: sizeY - marginY}, nimble.Black)
		pm.DrawRect(nimble.Rect{Left: sizeX - marginX, Right: sizeX, Top: marginY, Bottom: sizeY - marginY}, nimble.Black)
	}
}
Example #4
0
func (context) Render(pm nimble.PixMap) {
	dt := updateClock()

	// Advance the boot sequence
	advanceBootSequence(dt)

	// Draw dividers
	for i, r := range divider {
		if i < dividerCount {
			pm.DrawRect(r, nimble.White)
		} else {
			pm.DrawRect(r, nimble.Black)
		}
	}

	if fourierIsVisible {
		// Update universe
		xf, yf := fourierPort.RelativeToLeftTop(mouseX, mouseY)
		switch universe.Update(dt, xf, yf) {
		case universe.GameWin:
			youWin()
		case universe.GameLose:
			youLose()
		}
		updateZoom(dt)

		// Fourier view
		if rollPhase.Value {
			updatePhaseRoll(dt)
		}
		drawFrequonsFourier(pm.Intersect(fourierPort))
		drawFrequonsSpatial(pm.Intersect(fourierPort), xf, yf)
		tallyFourierFrame()
	} else {
		// Teletype view
		teletype.Draw(pm.Intersect(fourierPort))
	}

	// Fall view
	if fallIsVisible {
		inv := invStorage[:len(universe.Zoo)-1]
		for k := range inv {
			c := &universe.Zoo[k+1]
			inv[k] = fall.Invader{
				Progress:  c.Progress,
				Amplitude: c.Amplitude,
				Color:     pastels.Pixel(0, int32(c.Id)),
			}
		}
		fall.Draw(pm.Intersect(fallPort), inv)
	} else {
		pm.DrawRect(fallPort, nimble.Black)
	}

	// Radar view
	if radarIsVisible {
		radar.Draw(pm.Intersect(radarPort), universe.Scheme(), radarIsRunning)
	} else {
		pm.DrawRect(radarPort, nimble.Black)
	}

	// Score
	if scoreIsVisible {
		score.Draw(pm.Intersect(scorePort), universe.NKill())
	} else {
		pm.DrawRect(scorePort, nimble.Black)
	}

	// Menu bar
	if len(menuBar) > 0 {
		menu.DrawMenuBar(pm, menuBar)
	}

	// Cursor
	showCursor := true
	switch currentMode {
	case modeGame:
		showCursor = false
	case modeTraining:
		showCursor = !fourierPort.Contains(mouseX, mouseY)
	}
	if showCursor != cursorIsVisible {
		nimble.ShowCursor(showCursor)
		cursorIsVisible = showCursor
	}
}
Example #5
0
// Draw draws the menu with its upper left corner at (x,y)
func (m *Menu) Draw(pm nimble.PixMap, x, y int32) {
	// Draw the tab
	if m.tabWidth == 0 {
		// Lazily compute tabWidth and itemHeight
		m.computeTabSize()
	}
	var back, fore nimble.Pixel
	if m.hilightRow != showNone {
		back = tabHilightColor
		fore = backgroundColor
	} else {
		back = backgroundColor
		fore = foregroundColor
	}
	m.tabRect = nimble.MakeRect(x, y, 2*marginWidth+int32(m.tabWidth), int32(m.itemHeight))
	pm.DrawRect(m.tabRect, back)
	pm.DrawText(x+marginWidth, y, m.Label, fore, menuFont)
	pm.DrawRect(nimble.Rect{Left: m.tabRect.Left, Top: m.tabRect.Bottom, Right: m.tabRect.Right, Bottom: m.tabRect.Bottom + 1}, separatorColor)

	if m.hilightRow != showNone {
		if m.itemWidth == 0 {
			// Lazily compute itemsWidth
			w := int32(m.tabWidth)
			for i := range m.Items {
				p := m.Items[i].GetItem()
				w0, _ := menuFont.Size(p.Label)
				if w0 > w {
					w = w0
				}
			}
			m.itemWidth = uint16(checkWidth + w + 3 + 4*marginWidth)
		}
		w := int32(m.itemWidth)
		h := int32(m.itemHeight)
		m.itemsRect = nimble.MakeRect(x, m.tabRect.Bottom, w, h*int32(len(m.Items)))

		r := m.itemsRect
		r.Left += 1
		r.Right -= 1
		pm.DrawRect(r, backgroundColor)

		// Draw left border
		r.Left -= 1
		r.Right = r.Left + 1
		pm.DrawRect(r, separatorColor)

		// Draw middle border
		r.Left += 1 + checkWidth + 2*marginWidth
		r.Right = r.Left + 1
		pm.DrawRect(r, separatorColor)

		// Draw right border
		r.Left = m.itemsRect.Right - 1
		r.Right = r.Left + 1
		pm.DrawRect(r, separatorColor)

		// Draw the items
		checkX := x + 1 + marginWidth
		labelX := x + 2 + 3*marginWidth + checkWidth
		for i := range m.Items {
			mi := m.Items[i].GetItem()
			yi := m.itemsRect.Top + h*int32(i)
			if i == int(m.hilightRow-hilightBase) {
				pm.DrawRect(nimble.MakeRect(x, yi, int32(m.itemWidth), h), itemHilightColor)
			}
			if i == 0 {
				pm.DrawRect(nimble.Rect{x, yi, m.itemsRect.Right - 1, yi + 1}, separatorColor)
			} else if mi.Flags&Separator != 0 || i == 0 {
				pm.DrawRect(nimble.Rect{labelX - marginWidth, yi, m.itemsRect.Right - 1, yi + 1}, separatorColor)
			}
			fore := choose(mi.Flags&Disabled != 0, disabledForegroundColor, foregroundColor)
			if mi.Check != 0 {
				pm.DrawText(checkX, yi, string(mi.Check), fore, checkFont)
			}
			pm.DrawText(labelX, yi, mi.Label, fore, menuFont)
		}
	}
}