Skip to content

Commit b0fb87f

Browse files
committed
Example: Track fire spreading
1 parent 72b4fc4 commit b0fb87f

File tree

6 files changed

+127
-44
lines changed

6 files changed

+127
-44
lines changed

Gopkg.lock

Lines changed: 11 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
version = "1.0.0"
3131

3232
[[constraint]]
33-
branch = "master"
33+
branch = "convex-hull"
3434
name = "github.com/golang/geo"
35+
source = "github.com/markus-wa/geo"
3536

3637
[[constraint]]
3738
name = "github.com/markus-wa/gobitread"

examples/nade-trajectories/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ This example shows how to create a overview of grenade trajectories of a match.
66

77
`go run nade_trajectories.go -demo /path/to/demo > out.jpg`
88

9-
This will create a JPGE with trajectories of the first half's CT-team. The reason it doesn't do all nades is because the image would look quite cluttered otherwise.
9+
This will create a JPGE with grenade trajectories of the first five rounds. The reason it doesn't do more trajectories is because the image would look quite cluttered otherwise.
1010

1111
![Resulting map overview with trajectories](https://raw.githubusercontent.com/markus-wa/demoinfocs-golang/master/examples/nade-trajectories/nade_trajectories.jpg)

examples/nade-trajectories/nade_trajectories.go

Lines changed: 112 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import (
1111
"os"
1212

1313
r3 "github.com/golang/geo/r3"
14+
s2 "github.com/golang/geo/s2"
1415
draw2dimg "github.com/llgcode/draw2d/draw2dimg"
1516

1617
dem "github.com/markus-wa/demoinfocs-golang"
1718
common "github.com/markus-wa/demoinfocs-golang/common"
1819
events "github.com/markus-wa/demoinfocs-golang/events"
1920
ex "github.com/markus-wa/demoinfocs-golang/examples"
21+
st "github.com/markus-wa/demoinfocs-golang/sendtables"
2022
)
2123

2224
type nadePath struct {
@@ -26,13 +28,25 @@ type nadePath struct {
2628
}
2729

2830
var (
29-
colorFire color.Color = color.RGBA{0xff, 0x00, 0x00, 0xff} // Red
30-
colorHE color.Color = color.RGBA{0xff, 0xff, 0x00, 0xff} // Yellow
31-
colorFlash color.Color = color.RGBA{0x00, 0x00, 0xff, 0xff} // Blue, because of the color on the nade
32-
colorSmoke color.Color = color.RGBA{0xbe, 0xbe, 0xbe, 0xff} // Light gray
33-
colorDecoy color.Color = color.RGBA{0x96, 0x4b, 0x00, 0xff} // Brown, because it's shit :)
31+
colorFireNade color.Color = color.RGBA{0xff, 0x00, 0x00, 0xff} // Red
32+
colorInferno color.Color = color.RGBA{0xff, 0xa5, 0x00, 0xff} // Orange
33+
colorInfernoHull color.Color = color.RGBA{0xff, 0xff, 0x00, 0xff} // Yellow
34+
colorHE color.Color = color.RGBA{0x00, 0xff, 0x00, 0xff} // Green
35+
colorFlash color.Color = color.RGBA{0x00, 0x00, 0xff, 0xff} // Blue, because of the color on the nade
36+
colorSmoke color.Color = color.RGBA{0xbe, 0xbe, 0xbe, 0xff} // Light gray
37+
colorDecoy color.Color = color.RGBA{0x96, 0x4b, 0x00, 0xff} // Brown, because it's shit :)
3438
)
3539

40+
type inferno []r3.Vector
41+
42+
func (inf inferno) convexHull() *s2.Loop {
43+
q := s2.NewConvexHullQuery()
44+
for i := range inf {
45+
q.AddPoint(s2.Point{Vector: inf[i]})
46+
}
47+
return q.ConvexHull()
48+
}
49+
3650
// Run like this: go run nade_trajectories.go -demo /path/to/demo.dem > nade_trajectories.jpg
3751
func main() {
3852
f, err := os.Open(ex.DemoPathFromArgs())
@@ -58,19 +72,50 @@ func main() {
5872
nadeTrajectories[id].path = e.Projectile.Trajectory
5973
})
6074

61-
var nadeTrajectoriesFirstHalf []*nadePath
75+
var infernos []*s2.Loop
76+
77+
p.RegisterEventHandler(func(events.DataTablesParsedEvent) {
78+
p.ServerClasses().FindByName("CInferno").OnEntityCreated(func(ent *st.Entity) {
79+
origin := ent.Position()
80+
var fires inferno
81+
var nFires int
82+
ent.FindProperty("m_fireCount").OnUpdate(func(val st.PropertyValue) {
83+
for i := nFires; i < val.IntVal; i++ {
84+
iStr := fmt.Sprintf("%03d", i)
85+
offset := r3.Vector{
86+
X: float64(ent.FindProperty("m_fireXDelta." + iStr).Value().IntVal),
87+
Y: float64(ent.FindProperty("m_fireYDelta." + iStr).Value().IntVal),
88+
Z: float64(ent.FindProperty("m_fireZDelta." + iStr).Value().IntVal),
89+
}
90+
fires = append(fires, origin.Add(offset))
91+
}
92+
nFires = val.IntVal
93+
})
94+
95+
ent.OnDestroy(func() {
96+
infernos = append(infernos, fires.convexHull())
97+
})
98+
})
99+
})
100+
101+
var nadeTrajectoriesFirst5Rounds []*nadePath
102+
var infernosFirst5Rounds []*s2.Loop
62103
round := 0
63104
p.RegisterEventHandler(func(events.RoundEndedEvent) {
64105
round++
65-
// Very cheap first half check
66-
// We only want the first teams CT-side nades in the example so the image is not too cluttered
67-
// Won't work with demos that have match-restarts etc.
68-
if round == 15 {
69-
// Copy all nade paths from the first 15 rounds
106+
// We only want the data from the first 5 rounds so the image is not too cluttered
107+
// This is a very cheap way to do it. Won't work with demos that have match-restarts etc.
108+
if round == 5 {
109+
// Copy all nade paths
70110
for _, np := range nadeTrajectories {
71-
nadeTrajectoriesFirstHalf = append(nadeTrajectoriesFirstHalf, np)
111+
nadeTrajectoriesFirst5Rounds = append(nadeTrajectoriesFirst5Rounds, np)
72112
}
73113
nadeTrajectories = make(map[int64]*nadePath)
114+
115+
// And infernos
116+
for _, hull := range infernos {
117+
infernosFirst5Rounds = append(infernosFirst5Rounds, hull)
118+
}
74119
}
75120
})
76121

@@ -93,21 +138,57 @@ func main() {
93138
// Initialize the graphic context
94139
gc := draw2dimg.NewGraphicContext(dest)
95140

141+
// Draw infernos first so they're in the background
142+
drawInfernos(gc, infernosFirst5Rounds)
143+
144+
// Then trajectories on top of everything
145+
drawTrajectories(gc, nadeTrajectoriesFirst5Rounds)
146+
147+
// Write to standard output
148+
jpeg.Encode(os.Stdout, dest, &jpeg.Options{
149+
Quality: 90,
150+
})
151+
}
152+
153+
func drawInfernos(gc *draw2dimg.GraphicContext, hulls []*s2.Loop) {
154+
// Draw areas first
155+
gc.SetFillColor(colorInferno)
156+
157+
for _, hull := range hulls {
158+
buildInfernoPath(gc, hull)
159+
gc.Fill()
160+
}
161+
162+
// Then the outline
163+
gc.SetStrokeColor(colorInfernoHull)
164+
gc.SetLineWidth(2) // 2 px wide
165+
166+
for _, hull := range hulls {
167+
buildInfernoPath(gc, hull)
168+
gc.FillStroke()
169+
}
170+
}
171+
172+
func buildInfernoPath(gc *draw2dimg.GraphicContext, hull *s2.Loop) {
173+
vertices := hull.Vertices()
174+
gc.MoveTo(translateX(vertices[0].X), translateY(vertices[0].Y))
175+
for _, fire := range vertices[1:] {
176+
gc.LineTo(translateX(fire.X), translateY(fire.Y))
177+
}
178+
gc.LineTo(translateX(vertices[0].X), translateY(vertices[0].Y))
179+
}
180+
181+
func drawTrajectories(gc *draw2dimg.GraphicContext, trajectories []*nadePath) {
96182
gc.SetLineWidth(1) // 1 px lines
97183
gc.SetFillColor(color.RGBA{0, 0, 0, 0}) // No fill, alpha 0
98184

99-
for _, np := range nadeTrajectoriesFirstHalf {
100-
if np.team != common.TeamCounterTerrorists {
101-
// Only draw CT nades
102-
continue
103-
}
104-
185+
for _, np := range trajectories {
105186
// Set colors
106187
switch np.wep {
107188
case common.EqMolotov:
108189
fallthrough
109190
case common.EqIncendiary:
110-
gc.SetStrokeColor(colorFire)
191+
gc.SetStrokeColor(colorFireNade)
111192

112193
case common.EqHE:
113194
gc.SetStrokeColor(colorHE)
@@ -136,31 +217,28 @@ func main() {
136217

137218
gc.FillStroke()
138219
}
139-
140-
// Write to standard output
141-
jpeg.Encode(os.Stdout, dest, &jpeg.Options{
142-
Quality: 90,
143-
})
144220
}
145221

146222
// Rough translations for x & y coordinates from de_cache to 1024x1024 px.
147223
// This could be done nicer by only having to provide the mapping between two source & target coordinates and the max size.
148224
// Then we could calculate the correct stretch & offset automatically.
149225

150-
const (
151-
stretchX = 0.18
152-
offsetX = 414
153-
154-
stretchY = -0.18
155-
offsetY = 630
156-
)
157-
158226
func translateX(x float64) float64 {
159-
return x*stretchX + offsetX
227+
const (
228+
stretch = 0.18
229+
offset = 414
230+
)
231+
232+
return x*stretch + offset
160233
}
161234

162235
func translateY(y float64) float64 {
163-
return y*stretchY + offsetY
236+
const (
237+
stretch = -0.18
238+
offset = 630
239+
)
240+
241+
return y*stretch + offset
164242
}
165243

166244
func checkError(err error) {
-5.3 KB
Loading

vendor

Submodule vendor updated 77 files

0 commit comments

Comments
 (0)