Calling the Draw function on request #2651
-
Basically, I have a goroutine that generates series of images (frames), and I plan to use Ebiten more like a rendering library to display those frames in a window as soon as they are ready. Therefore, I don't need my Draw function to be called on every game engine iteration because most of the time, there won't be anything to draw. Instead, I would like to control drawing from outside of the game loop, so that the Draw function can be called when a new frame is available. I've come up with a solution using a channel to block the Update function and wait until it is signalled about a new frame. type Game struct {
frame *[100][100]color.RGBA
signal chan struct{}
}
func (d *Game) Trigger() {
d.signal <- struct{}{}
}
func (d *Game) Update() error {
<-d.signal
return nil
}
func (d *Game) Draw(screen *ebiten.Image) {
for x := 0; x < 100; x++ {
for y := 0; y < 100; y++ {
screen.Set(x, y, d.frame[x][y])
}
}
} It works, but it seems a bit off to me. Firstly, I'm not sure whether it's okay to block inside the Update function for a long period of time. Secondly, the use of a channel here introduces overhead that I'd prefer to avoid, ideally. I'm hoping someone can suggest an alternative and more idiomatic way to implement this. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
Could you set https://pkg.go.dev/github.com/hajimehoshi/ebiten/v2#SetScreenClearedEveryFrame |
Beta Was this translation helpful? Give feedback.
-
Blocking in your Also, I'd create a new type Game struct {
frame *[100][100]color.RGBA
signal chan struct{}
frameImage *ebiten.Image
}
func (d *Game) Trigger() {
d.signal <- struct{}{}
}
func (d *Game) Update() error {
select {
case <-d.signal:
if d.frameImage == nil {
d.frameImage = ebiten.NewImage(100, 100)
}
pix := make([]byte, 4 * 100 * 100)
for y := 0; y < 100; y++ {
for x := 0; x < 100; x++ {
pix[4*(100*y+x)] = d.frame[y][x].R
pix[4*(100*y+x)+1] = d.frame[y][x].G
pix[4*(100*y+x)+2] = d.frame[y][x].B
pix[4*(100*y+x)+3] = d.frame[y][x].A
}
}
d.frameImage.WritePixels(pix)
default:
}
return nil
}
func (d *Game) Draw(screen *ebiten.Image) {
if d.frameImage != nil {
screen.DrawImage(d.frameImage, nil)
}
} |
Beta Was this translation helpful? Give feedback.
Blocking in your
Update
would cause various issues. I would render the last image every Draw, or useSetScreenClearedEveryFrame(false)
as @mcarpenter622 suggested.Also, I'd create a new
*ebiten.Image
fromframe
and use it.