From 25814cf0222640a910214250968b5a0ebe23edc3 Mon Sep 17 00:00:00 2001 From: Marvin Blum Date: Sun, 14 Aug 2016 13:20:01 +0200 Subject: [PATCH] Set GL version to 3.1 (lowest possible version), fixed cleanup bug when calling Stop(), added input handling. --- CHANGELOG.md | 5 ++ README.md | 9 ++-- ToDo.md | 2 +- actor.go | 2 - demo/input/assets/gopher.png | Bin 0 -> 41276 bytes demo/input/input.go | 87 +++++++++++++++++++++++++++++++ demo/text/text.go | 2 +- fbo.go | 2 +- game.go | 11 ++-- gl_util.go | 2 +- input.go | 98 +++++++++++++++++++++++++++++++++++ keyframe.go | 2 +- loader.go | 2 +- model.go | 2 +- shader.go | 2 +- sprite.go | 2 +- tex.go | 2 +- text.go | 2 +- vao.go | 2 +- vbo.go | 2 +- 20 files changed, 213 insertions(+), 25 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 demo/input/assets/gopher.png create mode 100644 demo/input/input.go create mode 100644 input.go diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..713205a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.1_beta + +* beta release diff --git a/README.md b/README.md index 58fc00f..be5a71d 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,13 @@ # go-game (package "goga") Game engine written in Go using OpenGL and GLFW. Mostly for 2D rendering, but also capable of rendering 3D, providing everything to get you started. -**Under heavy development, do not use yet!** ## Install go-game requires OpenGL and GLFW. The following three steps install everything you need: ``` -go get github.com/go-gl/gl/v4.5-core/gl +go get github.com/go-gl/gl/v3.1-core/gl go get github.com/go-gl/glfw/v3.1/glfw go get github.com/DeKugelschieber/go-game ``` @@ -17,18 +16,16 @@ You also need a cgo compiler (typically gcc) and GL/GLFW development libraries a ## Usage -*WIP* - Examples can be found within the demo folder. For full reference visit: https://godoc.org/github.com/DeKugelschieber/go-game ## Dependencies * https://github.com/go-gl/gl - - 4.5-core + - 3.1-core * https://github.com/go-gl/glfw - 3.1 -To use an older GL version, you need to replace the GL imports in package goga. It should mostly be compatible down to 3.x. +To use a different GL version, you need to replace the GL imports in package goga. ## Contribute diff --git a/ToDo.md b/ToDo.md index 77af0cc..8d0d7b1 100644 --- a/ToDo.md +++ b/ToDo.md @@ -5,6 +5,6 @@ * ~~limit FPS~~ - does this really work? * ~~fullscreen~~ -* simple access to default resources like GetTex() +* ~~simple access to default resources like GetTex()~~ * ~~text rendering + font loading~~ * more options for GLFW diff --git a/actor.go b/actor.go index fd73d14..da247ee 100644 --- a/actor.go +++ b/actor.go @@ -1,7 +1,5 @@ package goga -import () - // An actor ID is a unique integer, // which can be used to reference an actor. type ActorId uint64 diff --git a/demo/input/assets/gopher.png b/demo/input/assets/gopher.png new file mode 100644 index 0000000000000000000000000000000000000000..cb5e2e19f150d8b131819b069bbfa40b86e458dc GIT binary patch literal 41276 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 IM6N<$g3C<*5&!@I literal 0 HcmV?d00001 diff --git a/demo/input/input.go b/demo/input/input.go new file mode 100644 index 0000000..f6a4f16 --- /dev/null +++ b/demo/input/input.go @@ -0,0 +1,87 @@ +package main + +import ( + "github.com/DeKugelschieber/go-game" + "github.com/go-gl/glfw/v3.2/glfw" +) + +const ( + gopher_path = "src/github.com/DeKugelschieber/go-game/demo/input/assets/gopher.png" +) + +type Game struct { + mouseX, mouseY float64 + sprite *goga.Sprite +} + +func (g *Game) Setup() { + // load texture + _, err := goga.LoadRes(gopher_path) + + if err != nil { + panic(err) + } + + // create sprite + tex, err := goga.GetTex("gopher.png") + + if err != nil { + panic(err) + } + + sprite := goga.NewSprite(tex) + sprite.Size.X = sprite.Size.X / 4 + sprite.Size.Y = sprite.Size.Y / 4 + g.sprite = sprite + renderer, ok := goga.GetSystemByName("spriteRenderer").(*goga.SpriteRenderer) + + if !ok { + panic("Could not find renderer") + } + + renderer.Add(sprite.Actor, sprite.Pos2D, sprite.Tex) + + culling, ok := goga.GetSystemByName("culling2d").(*goga.Culling2D) + + if !ok { + panic("Could not find culling") + } + + culling.Add(sprite.Actor, sprite.Pos2D) + + // register input listeners + goga.AddKeyboardListener(g) + goga.AddMouseListener(g) +} + +func (g *Game) Update(delta float64) {} + +func (g *Game) OnKeyEvent(key glfw.Key, code int, action glfw.Action, mod glfw.ModifierKey) { + // ESC + if key == 256 { + goga.Stop() + } +} + +func (g *Game) OnMouseButton(button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) { + if button == 0 { + g.sprite.Pos.X = g.mouseX + g.sprite.Pos.Y = g.mouseY + } +} + +func (g *Game) OnMouseMove(x float64, y float64) { + g.mouseX = x + g.mouseY = y +} + +func (g *Game) OnMouseScroll(x float64, y float64) {} + +func main() { + game := Game{} + options := goga.RunOptions{ClearColor: goga.Vec4{1, 1, 1, 0}, + Resizable: true, + SetViewportOnResize: true, + ExitOnClose: true} + goga.Run(&game, &options) +} diff --git a/demo/text/text.go b/demo/text/text.go index 3e0769d..7ce3cb1 100644 --- a/demo/text/text.go +++ b/demo/text/text.go @@ -2,7 +2,7 @@ package main import ( "github.com/DeKugelschieber/go-game" - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" ) const ( diff --git a/fbo.go b/fbo.go index 07c76c7..a168fec 100644 --- a/fbo.go +++ b/fbo.go @@ -1,7 +1,7 @@ package goga import ( - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" ) // Frame Buffer Object. diff --git a/game.go b/game.go index f7d8acf..fedbb00 100644 --- a/game.go +++ b/game.go @@ -1,7 +1,7 @@ package goga import ( - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" "github.com/go-gl/glfw/v3.2/glfw" "log" "math" @@ -58,7 +58,8 @@ var ( ) func init() { - // GL functions must be called from main thread. + // GL functions must be called from main thread, + // so we disable multithreading by the runtime here. log.Print("Locking OS thread") runtime.LockOSThread() } @@ -154,6 +155,8 @@ func Run(game Game, options *RunOptions) { } }) + initInput(wnd) + // make GL context current wnd.MakeContextCurrent() @@ -178,8 +181,8 @@ func Run(game Game, options *RunOptions) { delta := time.Duration(0) var deltaSec float64 - for running { - if exitOnClose && wnd.ShouldClose() { + for true { + if !running || exitOnClose && wnd.ShouldClose() { cleanup() return } diff --git a/gl_util.go b/gl_util.go index 6f46f10..b1fe6d6 100644 --- a/gl_util.go +++ b/gl_util.go @@ -1,7 +1,7 @@ package goga import ( - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" "log" ) diff --git a/input.go b/input.go new file mode 100644 index 0000000..ec5d239 --- /dev/null +++ b/input.go @@ -0,0 +1,98 @@ +package goga + +import ( + "github.com/go-gl/glfw/v3.2/glfw" +) + +var ( + keyboardListener []KeyboardListener + mouseListener []MouseListener +) + +// Interface for keyboard input events. +// Implement and register to receive keyboard input. +type KeyboardListener interface { + OnKeyEvent(glfw.Key, int, glfw.Action, glfw.ModifierKey) +} + +// Interface for mouse input events. +// Implement and register to receive mouse input. +type MouseListener interface { + OnMouseButton(glfw.MouseButton, glfw.Action, glfw.ModifierKey) + OnMouseMove(float64, float64) + OnMouseScroll(float64, float64) +} + +func initInput(wnd *glfw.Window) { + wnd.SetKeyCallback(keyboardCallback) + wnd.SetMouseButtonCallback(mouseButtonCallback) + wnd.SetCursorPosCallback(mouseMoveCallback) + wnd.SetScrollCallback(mouseScrollCallback) + + keyboardListener = make([]KeyboardListener, 0) + mouseListener = make([]MouseListener, 0) +} + +func keyboardCallback(wnd *glfw.Window, key glfw.Key, code int, action glfw.Action, mod glfw.ModifierKey) { + for _, listener := range keyboardListener { + listener.OnKeyEvent(key, code, action, mod) + } +} + +func mouseButtonCallback(wnd *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) { + for _, listener := range mouseListener { + listener.OnMouseButton(button, action, mod) + } +} + +func mouseMoveCallback(wnd *glfw.Window, x float64, y float64) { + for _, listener := range mouseListener { + listener.OnMouseMove(x, float64(viewportHeight)-y) + } +} + +func mouseScrollCallback(wnd *glfw.Window, x float64, y float64) { + for _, listener := range mouseListener { + listener.OnMouseScroll(x, y) + } +} + +// Adds a new keyboard listener. +func AddKeyboardListener(listener KeyboardListener) { + keyboardListener = append(keyboardListener, listener) +} + +// Removes given keyboard listener if found. +func RemoveKeyboardListener(listener KeyboardListener) { + for i, l := range keyboardListener { + if l == listener { + keyboardListener = append(keyboardListener[:i], keyboardListener[i+1:]...) + return + } + } +} + +// Removes all registered keyboard listeners. +func RemoveAllKeyboardListener() { + keyboardListener = make([]KeyboardListener, 0) +} + +// Adds a new mouse listener. +func AddMouseListener(listener MouseListener) { + mouseListener = append(mouseListener, listener) +} + +// Removes given mouse listener if found. +func RemoveMouseListener(listener MouseListener) { + for i, l := range mouseListener { + if l == listener { + mouseListener = append(mouseListener[:i], mouseListener[i+1:]...) + return + } + } +} + +// Removes all registered mouse listeners. +func RemoveAllMouseListener() { + mouseListener = make([]MouseListener, 0) +} diff --git a/keyframe.go b/keyframe.go index 432eb7d..cc3d0f4 100644 --- a/keyframe.go +++ b/keyframe.go @@ -1,7 +1,7 @@ package goga import ( - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" ) const ( diff --git a/loader.go b/loader.go index e083629..90b4148 100644 --- a/loader.go +++ b/loader.go @@ -3,7 +3,7 @@ package goga import ( "bufio" "errors" - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" "image" "image/draw" "image/png" diff --git a/model.go b/model.go index 428e7f2..f4033e5 100644 --- a/model.go +++ b/model.go @@ -1,7 +1,7 @@ package goga import ( - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" ) const ( diff --git a/shader.go b/shader.go index 33129bc..a3f2e1c 100644 --- a/shader.go +++ b/shader.go @@ -2,7 +2,7 @@ package goga import ( "errors" - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" "log" "strings" ) diff --git a/sprite.go b/sprite.go index 9da1067..06aea5c 100644 --- a/sprite.go +++ b/sprite.go @@ -1,7 +1,7 @@ package goga import ( - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" ) const ( diff --git a/tex.go b/tex.go index dccefb5..9f39779 100644 --- a/tex.go +++ b/tex.go @@ -1,7 +1,7 @@ package goga import ( - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" "image" ) diff --git a/text.go b/text.go index ea37efe..5990374 100644 --- a/text.go +++ b/text.go @@ -2,7 +2,7 @@ package goga import ( "encoding/json" - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" "io/ioutil" ) diff --git a/vao.go b/vao.go index 92995af..2aad4ef 100644 --- a/vao.go +++ b/vao.go @@ -1,7 +1,7 @@ package goga import ( - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" ) // Vertex Array Object. diff --git a/vbo.go b/vbo.go index 1445ec2..175121d 100644 --- a/vbo.go +++ b/vbo.go @@ -1,7 +1,7 @@ package goga import ( - "github.com/go-gl/gl/v4.5-core/gl" + "github.com/go-gl/gl/v3.2-core/gl" "unsafe" )