Example #1
0
func renderMenu(g *game.Game, fudge float32) {
	ease := func(start, change float32) float32 {
		return easeOutCubic(g.StateProgress(fudge), start, change)
	}

	alpha := float32(1)
	switch g.State {
	case game.GameInitial, game.GamePaused:
		alpha = ease(0, 1)

	case game.GamePlaying, game.GameExiting:
		alpha = ease(1, -1)
	}

	// Don't render the menu if it is invisible.
	if alpha == 0 {
		return
	}

	gl.UniformMatrix4fv(projectionViewMatrixUniform, 1, false, &orthoProjectionViewMatrix[0])
	gl.Uniform1f(grayscaleUniform, 0)
	gl.Uniform1f(brightnessUniform, 0)
	gl.Uniform1f(alphaUniform, alpha)
	gl.Uniform1f(mixAmountUniform, 0)

	menu := g.Menu
	titleText := menuTitleText[menu.ID]
	totalHeight := titleText.height * 2
	for _, item := range menu.Items {
		totalHeight += float32(menuItemFontSize) * 2
		if !item.SingleChoice() {
			totalHeight += float32(menuItemFontSize) * 2
		}
	}

	currentY := (float32(winHeight) + totalHeight) / 2

	centerX := func(txt *renderableText) float32 {
		return (float32(winWidth) - txt.width) / 2
	}

	renderText := func(text *renderableText) {
		currentY -= text.height
		text.render(centerX(text), currentY)
		currentY -= text.height // add spacing for next item
	}

	// TODO(btmura): split these out into separate functions

	renderSlider := func(item *game.MenuItem) {
		val := strconv.Itoa(item.Slider.Value)

		var valWidth, valHeight float32
		for _, rune := range val {
			text := menuRuneText[rune]
			valWidth += text.width
			if text.height > valHeight {
				valHeight = text.height
			}
		}

		currentY -= valHeight
		x := (float32(winWidth) - valWidth) / 2
		for _, rune := range val {
			text := menuRuneText[rune]
			text.render(x, currentY)
			x += text.width
		}
		currentY -= valHeight
	}

	renderMenuItem := func(index int, item *game.MenuItem) {
		var brightness float32
		if menu.FocusedIndex == index {
			switch {
			case menu.Selected:
				brightness = pulse(g.GlobalPulse+fudge, 1, 1, 1)

			case item.SingleChoice():
				brightness = pulse(g.GlobalPulse+fudge, 1, 0.3, 0.06)

			default:
				brightness = 1
			}
		}
		gl.Uniform1f(brightnessUniform, brightness)
		renderText(menuItemText[item.ID])
		switch {
		case item.Selector != nil:
			renderText(menuChoiceText[item.Selector.Value()])

		case item.Slider != nil:
			renderSlider(item)
		}
	}

	renderText(titleText)
	for i, item := range menu.Items {
		renderMenuItem(i, item)
	}
}
Example #2
0
func renderBoard(g *game.Game, fudge float32) bool {
	if g.Board == nil {
		return false
	}

	b := g.Board

	metrics := newMetrics(g, fudge)

	gl.UniformMatrix4fv(projectionViewMatrixUniform, 1, false, &perspectiveProjectionViewMatrix[0])
	gl.Uniform3fv(mixColorUniform, 1, &blackColor[0])

	globalGrayscale := float32(1)
	globalDarkness := float32(0.8)
	var boardDarkness float32

	gameEase := func(start, change float32) float32 {
		return easeOutCubic(g.StateProgress(fudge), start, change)
	}
	boardEase := func(start, change float32) float32 {
		return easeOutCubic(b.StateProgress(fudge), start, change)
	}

	switch g.State {
	case game.GamePlaying:
		globalGrayscale = gameEase(1, -1)
		globalDarkness = gameEase(0.8, -0.8)

	case game.GamePaused:
		globalGrayscale = gameEase(0, 1)
		globalDarkness = gameEase(0, 0.8)

	case game.GameExiting:
		globalGrayscale = 1
		globalDarkness = gameEase(0.8, 1)
	}

	switch b.State {
	case game.BoardEntering:
		boardDarkness = boardEase(1, -1)

	case game.BoardExiting:
		boardDarkness = boardEase(0, 1)
	}

	finalDarkness := globalDarkness
	if finalDarkness < boardDarkness {
		finalDarkness = boardDarkness
	}
	gl.Uniform1f(mixAmountUniform, finalDarkness)

	gl.Uniform1i(textureUniform, int32(boardTexture)-1)

	for i := 0; i <= 2; i++ {
		gl.Uniform1f(grayscaleUniform, globalGrayscale)
		gl.Uniform1f(brightnessUniform, 0)
		gl.Uniform1f(alphaUniform, 1)

		if i == 0 {
			renderSelector(metrics)
		}

		for y, r := range b.Rings {
			for x, c := range r.Cells {
				switch i {
				case 0: // draw opaque objects
					switch c.Block.State {
					case game.BlockStatic,
						game.BlockSwappingFromLeft,
						game.BlockSwappingFromRight,
						game.BlockDroppingFromAbove,
						game.BlockFlashing:
						renderCellBlock(metrics, c, x, y)

					case game.BlockCracking, game.BlockCracked:
						renderCellFragments(metrics, c, x, y)
					}

				case 1: // draw transparent objects
					switch c.Block.State {
					case game.BlockExploding:
						renderCellFragments(metrics, c, x, y)
					}
					renderMarker(metrics, c.Marker, x, y)
				}
			}
		}
	}

	// Render the spare rings.

	// Set brightness to zero for all spare rings.
	gl.Uniform1f(brightnessUniform, 0)

	for y, r := range b.SpareRings {
		// Set grayscale value. First spare rings becomes colored. Rest are gray.
		grayscale := float32(1)
		if y == 0 {
			grayscale = easeInExpo(b.RiseProgress(fudge), 1, -1)
		}
		if grayscale < globalGrayscale {
			grayscale = globalGrayscale
		}
		gl.Uniform1f(grayscaleUniform, grayscale)

		// Set alpha value. Last spare ring fades in. Rest are opaque.
		alpha := float32(1)
		if y == len(b.SpareRings)-1 {
			alpha = easeInExpo(b.RiseProgress(fudge), 0, 1)
		}
		gl.Uniform1f(alphaUniform, alpha)

		// Render the spare rings below the normal rings.
		for x, c := range r.Cells {
			renderCellBlock(metrics, c, x, y+b.RingCount)
		}
	}

	return true
}