~bigbes/game-prototype-ftl

ref: c3461b001847b1677f79a3876fde63902df8726e game-prototype-ftl/render.go -rw-r--r-- 2.6 KiB
c3461b00 — Eugene Blikh docs(crew-movement): record review conclusion 30 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package main

import (
	"image/color"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"github.com/hajimehoshi/ebiten/v2/vector"
)

// Rendering constants. All coordinate math goes through TilePx;
// no code should reason about window pixels directly.
const (
	TilePx   = 16
	VirtualW = 640
	VirtualH = 360
)

// roleColor maps a RoomRole to its tint. The mapping lives here so
// that ship data stays free of any rendering concerns.
func roleColor(role RoomRole) color.RGBA {
	switch role {
	case RolePilot:
		return color.RGBA{90, 130, 180, 255} // steel blue
	case RoleWeapons:
		return color.RGBA{170, 80, 70, 255} // dusty red
	case RoleShields:
		return color.RGBA{80, 140, 120, 255} // teal green
	case RoleMedBay:
		return color.RGBA{190, 160, 90, 255} // warm ochre
	case RoleEngines:
		return color.RGBA{140, 95, 160, 255} // muted violet
	default:
		return color.RGBA{120, 120, 120, 255}
	}
}

// drawShip draws every room of the ship. Rendering delegates to
// drawRoom so per-room logic lives in one place.
func drawShip(screen *ebiten.Image, s Ship) {
	for _, r := range s.Rooms {
		drawRoom(screen, r)
	}
}

// drawRoom draws a single room: a role-tinted fill, a 1-px border,
// and the role name printed inside.
func drawRoom(screen *ebiten.Image, r Room) {
	x := float32(r.GridX * TilePx)
	y := float32(r.GridY * TilePx)
	w := float32(r.GridW * TilePx)
	h := float32(r.GridH * TilePx)

	fill := roleColor(r.Role)
	vector.DrawFilledRect(screen, x, y, w, h, fill, false)

	border := color.RGBA{230, 230, 230, 255}
	// Four 1-px edges.
	vector.DrawFilledRect(screen, x, y, w, 1, border, false)
	vector.DrawFilledRect(screen, x, y+h-1, w, 1, border, false)
	vector.DrawFilledRect(screen, x, y, 1, h, border, false)
	vector.DrawFilledRect(screen, x+w-1, y, 1, h, border, false)

	// Label: a few pixels inside the top-left corner.
	ebitenutil.DebugPrintAt(screen, r.Name, int(x)+3, int(y)+2)
}

const CrewRadius = 6

var white = color.RGBA{255, 255, 255, 255}

func drawCrew(screen *ebiten.Image, c Crew, selected bool) {
	var fx, fy float64
	if len(c.Path) > 0 {
		fx = float64(c.TileX) + (float64(c.Path[0][0])-float64(c.TileX))*c.MoveT
		fy = float64(c.TileY) + (float64(c.Path[0][1])-float64(c.TileY))*c.MoveT
	} else {
		fx = float64(c.TileX)
		fy = float64(c.TileY)
	}
	px := float32(fx*TilePx + TilePx/2)
	py := float32(fy*TilePx + TilePx/2)

	vector.DrawFilledCircle(screen, px, py, CrewRadius, c.Color, true)
	if selected {
		vector.StrokeCircle(screen, px, py, CrewRadius+1, 1, white, true)
	}
	ebitenutil.DebugPrintAt(screen, string(c.Initial), int(px)-2, int(py)-5)
}