-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstarscape.go
More file actions
141 lines (125 loc) · 3.61 KB
/
starscape.go
File metadata and controls
141 lines (125 loc) · 3.61 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package spacegame
import (
"log"
"math/rand"
"github.com/faiface/pixel"
)
type Background interface {
Displace(float64)
Render()
}
type star struct {
resource *Resource
position pixel.Vec
layer float64
}
type Starscape struct {
renderer Renderer
camera Camera
stars []star
resources []Resource
scaleFactor float64
}
func NewStarscape(renderer Renderer, camera Camera, density float64) Starscape {
const layerLow, layerHigh = 0.1, 2.35
var (
stars []star
resourceManager ResourceManager
bounds = renderer.Bounds()
w = bounds.W()
h = bounds.H()
numStars = int(w*h*density) / 1000
numDust = numStars / 10
scaleFactor = 1.17 // TODO param like density
extraW = w*scaleFactor - w
extraH = w*scaleFactor - w
)
log.Println(extraW, extraH)
resourceManager = renderer.ResourceManager()
starResources := resourceManager.FindInCollection("star")
dustResources := resourceManager.FindInCollection("dust")
if len(starResources) == 0 {
log.Println("Could not create a starscape: No stars found")
return Starscape{}
}
if len(dustResources) == 0 {
log.Println("Error creating a starscape: No dust found -- using stars instead")
dustResources = starResources
}
for i := 0; i < numStars+numDust; i++ {
var (
x, y float64
topLow float64 = 0.0
topMult float64 = 1.00
)
resource := &starResources[rand.Intn(len(starResources))]
x = -extraW/2 + float64(rand.Intn(int(w*scaleFactor)))
y = -extraH/2 + float64(rand.Intn(int(h*scaleFactor)))
// create dust
if i > numStars {
topLow = 3.7
topMult = 16.76
resource = &dustResources[rand.Intn(len(dustResources))]
}
star := star{
resource: resource,
position: pixel.V(x, y),
layer: topLow + layerLow + rand.Float64()*(layerHigh*topMult),
}
stars = append(stars, star)
}
return Starscape{
renderer: renderer,
camera: camera,
stars: stars,
resources: starResources,
scaleFactor: scaleFactor,
}
}
func (sc Starscape) Displace(dt float64) {
vector := sc.camera.Motion().Scaled(dt)
if vector.Len() == 0 {
return
}
for i, star := range sc.stars {
displacement := vector.Scaled(star.layer)
sc.stars[i].position = star.position.Sub(displacement)
// if position is out of bounds, reset the image and the coordinate component that was out of bounds
// find the missing component
starBox := sc.renderer.Bounds()
starBox = starBox.Resized(starBox.Center(), pixel.V(starBox.W()*sc.scaleFactor, starBox.H()*sc.scaleFactor))
if !starBox.Contains(sc.stars[i].position) {
sc.recreate(i)
}
}
}
func (sc Starscape) Render() {
// TODO: Sort by layer!
for _, star := range sc.stars {
sc.renderer.Render(star.resource.entity, star.position)
}
}
func (sc Starscape) recreate(starIndex int) {
candidatePosition := sc.stars[starIndex].position
bounds := sc.renderer.Bounds()
h := bounds.H()
w := bounds.W()
extraH := h*sc.scaleFactor - h
extraW := w*sc.scaleFactor - w
sc.stars[starIndex].resource = &sc.resources[rand.Intn(len(sc.resources))]
if candidatePosition.X > w+extraW {
candidatePosition.X = 0-extraW
candidatePosition.Y = float64(rand.Intn(int(h)))
} else if candidatePosition.X < 0-extraW {
candidatePosition.X = w+extraW
candidatePosition.Y = float64(rand.Intn(int(h)))
}
if candidatePosition.Y > h+extraH {
candidatePosition.X = float64(rand.Intn(int(w)))
candidatePosition.Y = 0-extraH
} else if candidatePosition.Y < 0-extraH {
candidatePosition.X = float64(rand.Intn(int(w)))
candidatePosition.Y = h+extraH
}
sc.stars[starIndex].position = candidatePosition
}