go-sdl2-examples/examples/render_goroutines/render_goroutines.go

123 lines
2.4 KiB
Go
Raw Normal View History

package main
import (
"fmt"
"math/rand"
"os"
"sync"
"github.com/veandco/go-sdl2/sdl"
)
const (
WindowTitle = "Go-SDL2 Render"
WindowWidth = 800
WindowHeight = 600
FrameRate = 60
RectWidth = 20
RectHeight = 20
NumRects = WindowHeight / RectHeight
)
var rects [NumRects]sdl.Rect
var runningMutex sync.Mutex
func run() int {
var window *sdl.Window
var renderer *sdl.Renderer
var err error
sdl.Do(func() {
window, err = sdl.CreateWindow(WindowTitle, sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, WindowWidth, WindowHeight, sdl.WINDOW_OPENGL)
})
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", err)
return 1
}
defer func() {
sdl.Do(func() {
window.Destroy()
})
}()
sdl.Do(func() {
renderer, err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
})
if err != nil {
fmt.Fprint(os.Stderr, "Failed to create renderer: %s\n", err)
return 2
}
defer func() {
sdl.Do(func() {
renderer.Destroy()
})
}()
sdl.Do(func() {
renderer.Clear()
})
for i := range rects {
rects[i] = sdl.Rect{
X: int32(rand.Int() % WindowWidth),
Y: int32(i * WindowHeight / len(rects)),
W: RectWidth,
H: RectHeight,
}
}
running := true
for running {
sdl.Do(func() {
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
switch event.(type) {
case *sdl.QuitEvent:
runningMutex.Lock()
running = false
runningMutex.Unlock()
}
}
renderer.Clear()
renderer.SetDrawColor(0, 0, 0, 0x20)
renderer.FillRect(&sdl.Rect{0, 0, WindowWidth, WindowHeight})
})
// Do expensive stuff using goroutines
wg := sync.WaitGroup{}
for i := range rects {
wg.Add(1)
go func(i int) {
rects[i].X = (rects[i].X + 10) % WindowWidth
sdl.Do(func() {
renderer.SetDrawColor(0xff, 0xff, 0xff, 0xff)
renderer.DrawRect(&rects[i])
})
wg.Done()
}(i)
}
wg.Wait()
sdl.Do(func() {
renderer.Present()
sdl.Delay(1000 / FrameRate)
})
}
return 0
}
func main() {
// os.Exit(..) must run AFTER sdl.Main(..) below; so keep track of exit
// status manually outside the closure passed into sdl.Main(..) below
var exitcode int
sdl.Main(func() {
exitcode = run()
})
// os.Exit(..) must run here! If run in sdl.Main(..) above, it will cause
// premature quitting of sdl.Main(..) function; resource cleaning deferred
// calls/closing of channels may never run
os.Exit(exitcode)
}