mirror of
https://github.com/zserge/fenster.git
synced 2025-04-12 10:48:41 +03:00
Merge pull request #3 from dim13/main
This commit is contained in:
@ -3,6 +3,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
@ -10,11 +11,12 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
f := fenster.New()
|
||||
f.Open(320, 240, "Hello")
|
||||
f, err := fenster.New(320, 240, "Hello")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
lastFrame := time.Now()
|
||||
for f.Loop() {
|
||||
for f.Loop(time.Second / 60) {
|
||||
// If escape is pressed - exit
|
||||
if f.Key(27) {
|
||||
break
|
||||
@ -25,11 +27,5 @@ func main() {
|
||||
f.Set(j, i, fenster.RGB(rand.Uint32()))
|
||||
}
|
||||
}
|
||||
// Wait for FPS rate
|
||||
sleep := 16*time.Millisecond - time.Since(lastFrame)
|
||||
if sleep > 0 {
|
||||
time.Sleep(sleep)
|
||||
}
|
||||
lastFrame = time.Now()
|
||||
}
|
||||
}
|
||||
|
97
examples/fire.go
Normal file
97
examples/fire.go
Normal file
@ -0,0 +1,97 @@
|
||||
//go:build example
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"log"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/zserge/fenster"
|
||||
)
|
||||
|
||||
type Fire struct {
|
||||
*image.Paletted
|
||||
}
|
||||
|
||||
var palette = color.Palette{
|
||||
color.RGBA{0x07, 0x07, 0x07, 0xff},
|
||||
color.RGBA{0x1f, 0x07, 0x07, 0xff},
|
||||
color.RGBA{0x2f, 0x0f, 0x07, 0xff},
|
||||
color.RGBA{0x47, 0x0f, 0x07, 0xff},
|
||||
color.RGBA{0x57, 0x17, 0x07, 0xff},
|
||||
color.RGBA{0x67, 0x1f, 0x07, 0xff},
|
||||
color.RGBA{0x77, 0x1f, 0x07, 0xff},
|
||||
color.RGBA{0x8f, 0x27, 0x07, 0xff},
|
||||
color.RGBA{0x9f, 0x2f, 0x07, 0xff},
|
||||
color.RGBA{0xaf, 0x3f, 0x07, 0xff},
|
||||
color.RGBA{0xbf, 0x47, 0x07, 0xff},
|
||||
color.RGBA{0xc7, 0x47, 0x07, 0xff},
|
||||
color.RGBA{0xdf, 0x4f, 0x07, 0xff},
|
||||
color.RGBA{0xdf, 0x57, 0x07, 0xff},
|
||||
color.RGBA{0xdf, 0x57, 0x07, 0xff},
|
||||
color.RGBA{0xd7, 0x5f, 0x07, 0xff},
|
||||
color.RGBA{0xd7, 0x67, 0x0f, 0xff},
|
||||
color.RGBA{0xcf, 0x6f, 0x0f, 0xff},
|
||||
color.RGBA{0xcf, 0x77, 0x0f, 0xff},
|
||||
color.RGBA{0xcf, 0x7f, 0x0f, 0xff},
|
||||
color.RGBA{0xcf, 0x87, 0x17, 0xff},
|
||||
color.RGBA{0xc7, 0x87, 0x17, 0xff},
|
||||
color.RGBA{0xc7, 0x8f, 0x17, 0xff},
|
||||
color.RGBA{0xc7, 0x97, 0x1f, 0xff},
|
||||
color.RGBA{0xbf, 0x9f, 0x1f, 0xff},
|
||||
color.RGBA{0xbf, 0x9f, 0x1f, 0xff},
|
||||
color.RGBA{0xbf, 0xa7, 0x27, 0xff},
|
||||
color.RGBA{0xbf, 0xa7, 0x27, 0xff},
|
||||
color.RGBA{0xbf, 0xaf, 0x2f, 0xff},
|
||||
color.RGBA{0xb7, 0xaf, 0x2f, 0xff},
|
||||
color.RGBA{0xb7, 0xb7, 0x2f, 0xff},
|
||||
color.RGBA{0xb7, 0xb7, 0x37, 0xff},
|
||||
color.RGBA{0xcf, 0xcf, 0x6f, 0xff},
|
||||
color.RGBA{0xdf, 0xdf, 0x9f, 0xff},
|
||||
color.RGBA{0xef, 0xef, 0xc7, 0xff},
|
||||
color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||
}
|
||||
|
||||
func newFire(r image.Rectangle, p color.Palette) *Fire {
|
||||
img := image.NewPaletted(r, p)
|
||||
b := r.Bounds().Max
|
||||
// seed
|
||||
for x := 0; x < b.X; x++ {
|
||||
img.SetColorIndex(x, b.Y-1, uint8(len(palette)-1))
|
||||
}
|
||||
return &Fire{Paletted: img}
|
||||
}
|
||||
|
||||
func (f *Fire) Next() {
|
||||
b := f.Bounds().Max
|
||||
for x := 0; x < b.X; x++ {
|
||||
for y := b.Y - 1; y > 0; y-- {
|
||||
z := rand.Intn(3) - 1 // -1, 0, 1
|
||||
n := f.ColorIndexAt(x, y)
|
||||
if n > 0 && z == 0 {
|
||||
n-- // next color
|
||||
}
|
||||
f.SetColorIndex(x+z, y-1, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
win, err := fenster.New(320, 200, "Doom Fire")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer win.Close()
|
||||
f := newFire(win.Bounds(), palette)
|
||||
for win.Loop(time.Second / 60) {
|
||||
if win.Key(27) || win.Key('Q') {
|
||||
break
|
||||
}
|
||||
f.Next()
|
||||
draw.Draw(win, win.Bounds(), f, image.Point{}, draw.Src)
|
||||
}
|
||||
}
|
@ -24,10 +24,11 @@ func openImage(fname string) (image.Image, error) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
f := fenster.New()
|
||||
f.Open(320, 240, "Hello")
|
||||
f, err := fenster.New(320, 240, "Hello")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
lastFrame := time.Now()
|
||||
|
||||
img, err := openImage("testdata/Testbild.png")
|
||||
if err != nil {
|
||||
@ -38,7 +39,7 @@ func main() {
|
||||
pimg := image.NewPaletted(img.Bounds(), palette.Plan9)
|
||||
draw.Draw(pimg, pimg.Bounds(), img, image.Point{}, draw.Src)
|
||||
|
||||
for f.Loop() {
|
||||
for f.Loop(time.Second / 24) {
|
||||
// If escape is pressed - exit
|
||||
if f.Key(27) {
|
||||
break
|
||||
@ -47,12 +48,5 @@ func main() {
|
||||
// rotate palette
|
||||
pimg.Palette = append(pimg.Palette[1:], pimg.Palette[0])
|
||||
draw.Draw(f, f.Bounds(), pimg, image.Point{}, draw.Src)
|
||||
|
||||
// Wait for FPS rate
|
||||
sleep := 16*time.Millisecond - time.Since(lastFrame)
|
||||
if sleep > 0 {
|
||||
time.Sleep(sleep)
|
||||
}
|
||||
lastFrame = time.Now()
|
||||
}
|
||||
}
|
||||
|
29
fenster.go
29
fenster.go
@ -13,6 +13,7 @@ import (
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"runtime"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@ -22,8 +23,7 @@ func init() {
|
||||
}
|
||||
|
||||
type Fenster interface {
|
||||
Open(w, h int, title string) error
|
||||
Loop() bool
|
||||
Loop(d time.Duration) bool
|
||||
Close()
|
||||
Key(byte) bool
|
||||
Mod() Mods
|
||||
@ -57,8 +57,9 @@ func rgbModel(c color.Color) color.Color {
|
||||
type Mods int
|
||||
|
||||
type fenster struct {
|
||||
f C.struct_fenster
|
||||
buf []uint32
|
||||
f C.struct_fenster
|
||||
buf []uint32
|
||||
lastFrame time.Time
|
||||
}
|
||||
|
||||
func (f *fenster) ColorModel() color.Model { return RGBModel }
|
||||
@ -66,21 +67,29 @@ func (f *fenster) Bounds() image.Rectangle {
|
||||
return image.Rect(0, 0, int(f.f.width), int(f.f.height))
|
||||
}
|
||||
|
||||
func New() Fenster { return &fenster{} }
|
||||
func (f *fenster) Open(w, h int, title string) error {
|
||||
func New(w, h int, title string) (Fenster, error) {
|
||||
f := new(fenster)
|
||||
f.f.title = C.CString(title)
|
||||
f.f.width = C.int(w)
|
||||
f.f.height = C.int(h)
|
||||
f.f.buf = (*C.uint32_t)(C.malloc(C.size_t(w * h * 4)))
|
||||
f.buf = unsafe.Slice((*uint32)(f.f.buf), w*h)
|
||||
f.lastFrame = time.Now()
|
||||
res := C.fenster_open(&f.f)
|
||||
if res != 0 {
|
||||
return fmt.Errorf("failed to open window: %d", res)
|
||||
return nil, fmt.Errorf("failed to open window: %d", res)
|
||||
}
|
||||
return nil
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (f *fenster) Close() { C.fenster_close(&f.f) }
|
||||
func (f *fenster) Loop(d time.Duration) bool {
|
||||
if sleep := d - time.Since(f.lastFrame); sleep > 0 {
|
||||
time.Sleep(sleep)
|
||||
}
|
||||
f.lastFrame = time.Now()
|
||||
return C.fenster_loop(&f.f) == 0
|
||||
}
|
||||
func (f *fenster) Loop() bool { return C.fenster_loop(&f.f) == 0 }
|
||||
func (f *fenster) Close() { C.fenster_close(&f.f) }
|
||||
|
||||
func (f *fenster) Key(code byte) bool { return f.f.keys[code] != 0 }
|
||||
func (f *fenster) Mod() Mods { return Mods(f.f.mod) }
|
||||
|
Reference in New Issue
Block a user