运行 并在 Go 中的 Goroutine 中使用 SDL
Run and use SDL in a Goroutine in go
我有一个包含多个循环的程序,每个循环 运行 在一个 Goroutine 中。我需要在我的程序 运行s 时插入或拔出显示器,所以我必须重新启动 sdl 让它找到我的新显示器,我通过 sdl.quit() 退出最后一个 sdl 和 sdl.init(sdl.InitEverything) 再次初始化它。
我的问题是我必须在一个循环中处理 sdl 事件,如果我不这样做,它将变得无响应,但这个循环将阻止我的主代码。我不需要处理鼠标点击之类的任何事件,我只想显示一些简单的图片并对其进行操作,有什么方法可以停止事件或 运行 goroutine 中的整个 sdl 吗?我试过了,但得到了奇怪的结果。这是我的结构:
type SDLstruct{
window *sdl.Window
renderer *sdl.Renderer
texture *sdl.Texture
src, dst sdl.Rect
event sdl.Event
Close bool
winWidth, winHeight int32
}
此函数启动一个 window 和一个渲染器:
func (sdlVars *SDLstruct)StartWindow() (err error) {
sdlVars.winWidth, sdlVars.winHeight = 1920,1080
sdl.Init(sdl.INIT_VIDEO)
Num,err :=sdl.GetNumVideoDisplays()
if err!=nil {
return err
}
var rect sdl.Rect
rect,err = sdl.GetDisplayBounds(0)
if err!=nil {
return err
}
for i:=Num-1;i>=0;i--{
Mod , _:=sdl.GetDisplayMode(i,0)
if Mod.W ==info.winWidth && Mod.H==info.winHeight{
rect,err = sdl.GetDisplayBounds(i)
if err!=nil {
return err
}
break
}
}
sdlVars.window, err = sdl.CreateWindow(winTitle, rect.X, rect.Y,
rect.W, rect.H, sdl.WINDOW_SHOWN)
sdlVars.window.SetBordered(false)
sdlVars.window.SetFullscreen(1)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", err)
return err
}
sdlVars.renderer, err = sdl.CreateRenderer(sdlVars.window, -1, sdl.RENDERER_ACCELERATED)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create renderer: %s\n", err)
return err
}
sdlVars.renderer.Clear()
sdlVars.renderer.SetDrawColor(0, 0, 0, 255)
sdlVars.renderer.FillRect(&sdl.Rect{0, 0, int32(info.winWidth), int32(info.winHeight)})
sdlVars.renderer.Present()
sdl.ShowCursor(0)
return nil
}
此函数处理事件:
func (sdlVars *SDLstruct)HandleEvents() {
for sdlVars.event = sdl.PollEvent(); sdlVars.event != nil; sdlVars.event = sdl.PollEvent() {
switch t := sdlVars.event.(type) {
case *sdl.QuitEvent:
sdlVars.Close = true
}
}
}
而这个关闭了一切:
func (sdlVars *SDLstruct)CloseSDL() (err error) {
err =sdlVars.renderer.Destroy()
if err!=nil{
return err
}
err = sdlVars.window.Destroy()
if err!=nil{
return err
}
sdl.Quit()
return nil
}
这是我的主要功能:
func main() {
var wg sync.WaitGroup
SdlVars:= new(SDLstruct)
wg.Add(1)
go SdlVars.StartSDL()
time.Sleep(time.Second*5)
SdlVars.Close = true
time.Sleep(time.Second*15)
}
在我的 Main 函数中,我告诉它启动 sdl 并在 5 秒后关闭所有内容并等待 15 秒,但它没有关闭 window。
小心,因为从多线程使用 SDL 并非完全微不足道。通常,您的 SDL 循环必须位于 main
线程中。这是有充分理由的,因为事件循环是 main
线程的一部分,并且您的许多对象都是在 main
线程上创建和改变的……或者至少它们应该是。
当您引入多个线程时,可能会发生奇怪的未定义和危险行为。这就是为什么一个好的经验法则是使用 runtime.LockOSThread
来确保 Go 运行时不会将你的 main
goroutine 固定到其他线程并将其保留在 main
线程上。
有关详细信息,请参阅此内容:enter link description here
我有一个包含多个循环的程序,每个循环 运行 在一个 Goroutine 中。我需要在我的程序 运行s 时插入或拔出显示器,所以我必须重新启动 sdl 让它找到我的新显示器,我通过 sdl.quit() 退出最后一个 sdl 和 sdl.init(sdl.InitEverything) 再次初始化它。 我的问题是我必须在一个循环中处理 sdl 事件,如果我不这样做,它将变得无响应,但这个循环将阻止我的主代码。我不需要处理鼠标点击之类的任何事件,我只想显示一些简单的图片并对其进行操作,有什么方法可以停止事件或 运行 goroutine 中的整个 sdl 吗?我试过了,但得到了奇怪的结果。这是我的结构:
type SDLstruct{
window *sdl.Window
renderer *sdl.Renderer
texture *sdl.Texture
src, dst sdl.Rect
event sdl.Event
Close bool
winWidth, winHeight int32
}
此函数启动一个 window 和一个渲染器:
func (sdlVars *SDLstruct)StartWindow() (err error) {
sdlVars.winWidth, sdlVars.winHeight = 1920,1080
sdl.Init(sdl.INIT_VIDEO)
Num,err :=sdl.GetNumVideoDisplays()
if err!=nil {
return err
}
var rect sdl.Rect
rect,err = sdl.GetDisplayBounds(0)
if err!=nil {
return err
}
for i:=Num-1;i>=0;i--{
Mod , _:=sdl.GetDisplayMode(i,0)
if Mod.W ==info.winWidth && Mod.H==info.winHeight{
rect,err = sdl.GetDisplayBounds(i)
if err!=nil {
return err
}
break
}
}
sdlVars.window, err = sdl.CreateWindow(winTitle, rect.X, rect.Y,
rect.W, rect.H, sdl.WINDOW_SHOWN)
sdlVars.window.SetBordered(false)
sdlVars.window.SetFullscreen(1)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", err)
return err
}
sdlVars.renderer, err = sdl.CreateRenderer(sdlVars.window, -1, sdl.RENDERER_ACCELERATED)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create renderer: %s\n", err)
return err
}
sdlVars.renderer.Clear()
sdlVars.renderer.SetDrawColor(0, 0, 0, 255)
sdlVars.renderer.FillRect(&sdl.Rect{0, 0, int32(info.winWidth), int32(info.winHeight)})
sdlVars.renderer.Present()
sdl.ShowCursor(0)
return nil
}
此函数处理事件:
func (sdlVars *SDLstruct)HandleEvents() {
for sdlVars.event = sdl.PollEvent(); sdlVars.event != nil; sdlVars.event = sdl.PollEvent() {
switch t := sdlVars.event.(type) {
case *sdl.QuitEvent:
sdlVars.Close = true
}
}
}
而这个关闭了一切:
func (sdlVars *SDLstruct)CloseSDL() (err error) {
err =sdlVars.renderer.Destroy()
if err!=nil{
return err
}
err = sdlVars.window.Destroy()
if err!=nil{
return err
}
sdl.Quit()
return nil
}
这是我的主要功能:
func main() {
var wg sync.WaitGroup
SdlVars:= new(SDLstruct)
wg.Add(1)
go SdlVars.StartSDL()
time.Sleep(time.Second*5)
SdlVars.Close = true
time.Sleep(time.Second*15)
}
在我的 Main 函数中,我告诉它启动 sdl 并在 5 秒后关闭所有内容并等待 15 秒,但它没有关闭 window。
小心,因为从多线程使用 SDL 并非完全微不足道。通常,您的 SDL 循环必须位于 main
线程中。这是有充分理由的,因为事件循环是 main
线程的一部分,并且您的许多对象都是在 main
线程上创建和改变的……或者至少它们应该是。
当您引入多个线程时,可能会发生奇怪的未定义和危险行为。这就是为什么一个好的经验法则是使用 runtime.LockOSThread
来确保 Go 运行时不会将你的 main
goroutine 固定到其他线程并将其保留在 main
线程上。
有关详细信息,请参阅此内容:enter link description here