func run(title string, width, height int, fullscreen bool) { document := js.Global.Get("document") canvas = document.Call("createElement", "canvas") target := document.Call("getElementById", title) if target.IsNull() { target = document.Get("body") } target.Call("appendChild", canvas) attrs := webgl.DefaultAttributes() attrs.Alpha = false attrs.Depth = false attrs.PremultipliedAlpha = false attrs.PreserveDrawingBuffer = false attrs.Antialias = false var err error Gl, err = webgl.NewContext(canvas, attrs) if err != nil { log.Fatal(err) } js.Global.Set("onunload", func() { responder.Close() }) canvas.Get("style").Set("display", "block") winWidth := js.Global.Get("innerWidth").Int() winHeight := js.Global.Get("innerHeight").Int() if fullscreen { canvas.Set("width", winWidth) canvas.Set("height", winHeight) } else { canvas.Set("width", width) canvas.Set("height", height) canvas.Get("style").Set("marginLeft", toPx((winWidth-width)/2)) canvas.Get("style").Set("marginTop", toPx((winHeight-height)/2)) } canvas.Call("addEventListener", "mousemove", func(ev js.Object) { rect := canvas.Call("getBoundingClientRect") x := float32((ev.Get("clientX").Int() - rect.Get("left").Int())) y := float32((ev.Get("clientY").Int() - rect.Get("top").Int())) responder.Mouse(x, y, MOVE) }, false) canvas.Call("addEventListener", "mousedown", func(ev js.Object) { rect := canvas.Call("getBoundingClientRect") x := float32((ev.Get("clientX").Int() - rect.Get("left").Int())) y := float32((ev.Get("clientY").Int() - rect.Get("top").Int())) responder.Mouse(x, y, PRESS) }, false) canvas.Call("addEventListener", "mouseup", func(ev js.Object) { rect := canvas.Call("getBoundingClientRect") x := float32((ev.Get("clientX").Int() - rect.Get("left").Int())) y := float32((ev.Get("clientY").Int() - rect.Get("top").Int())) responder.Mouse(x, y, RELEASE) }, false) canvas.Call("addEventListener", "touchstart", func(ev js.Object) { rect := canvas.Call("getBoundingClientRect") for i := 0; i < ev.Get("changedTouches").Get("length").Int(); i++ { touch := ev.Get("changedTouches").Index(i) x := float32((touch.Get("clientX").Int() - rect.Get("left").Int())) y := float32((touch.Get("clientY").Int() - rect.Get("top").Int())) responder.Mouse(x, y, PRESS) } }, false) canvas.Call("addEventListener", "touchcancel", func(ev js.Object) { rect := canvas.Call("getBoundingClientRect") for i := 0; i < ev.Get("changedTouches").Get("length").Int(); i++ { touch := ev.Get("changedTouches").Index(i) x := float32((touch.Get("clientX").Int() - rect.Get("left").Int())) y := float32((touch.Get("clientY").Int() - rect.Get("top").Int())) responder.Mouse(x, y, RELEASE) } }, false) canvas.Call("addEventListener", "touchend", func(ev js.Object) { rect := canvas.Call("getBoundingClientRect") for i := 0; i < ev.Get("changedTouches").Get("length").Int(); i++ { touch := ev.Get("changedTouches").Index(i) x := float32((touch.Get("clientX").Int() - rect.Get("left").Int())) y := float32((touch.Get("clientY").Int() - rect.Get("top").Int())) responder.Mouse(x, y, PRESS) } }, false) canvas.Call("addEventListener", "touchmove", func(ev js.Object) { rect := canvas.Call("getBoundingClientRect") for i := 0; i < ev.Get("changedTouches").Get("length").Int(); i++ { touch := ev.Get("changedTouches").Index(i) x := float32((touch.Get("clientX").Int() - rect.Get("left").Int())) y := float32((touch.Get("clientY").Int() - rect.Get("top").Int())) responder.Mouse(x, y, MOVE) } }, false) js.Global.Call("addEventListener", "keypress", func(ev js.Object) { responder.Type(rune(ev.Get("charCode").Int())) }, false) js.Global.Call("addEventListener", "keydown", func(ev js.Object) { key := Key(ev.Get("keyCode").Int()) keyStates[key] = true }, false) js.Global.Call("addEventListener", "keyup", func(ev js.Object) { key := Key(ev.Get("keyCode").Int()) keyStates[key] = false // responder.Key(Key(ev.Get("keyCode").Int()), 0, RELEASE) }, false) Gl = Gl Gl.Viewport(0, 0, width, height) Wo.New() responder.Preload() Files.Load(func() { responder.Setup() RequestAnimationFrame(animate) }) }
func CreateWindow(title string, width, height int, fullscreen bool) { err := glfw.Init() fatalErr(err) Arrow = glfw.CreateStandardCursor(int(glfw.ArrowCursor)) Hand = glfw.CreateStandardCursor(int(glfw.HandCursor)) IBeam = glfw.CreateStandardCursor(int(glfw.IBeamCursor)) Crosshair = glfw.CreateStandardCursor(int(glfw.CrosshairCursor)) monitor := glfw.GetPrimaryMonitor() mode := monitor.GetVideoMode() gameWidth = float32(width) gameHeight = float32(height) if fullscreen { width = mode.Width height = mode.Height glfw.WindowHint(glfw.Decorated, 0) } else { monitor = nil } glfw.WindowHint(glfw.ContextVersionMajor, 2) glfw.WindowHint(glfw.ContextVersionMinor, 1) window, err = glfw.CreateWindow(width, height, title, nil, nil) fatalErr(err) window.MakeContextCurrent() if !fullscreen { window.SetPos((mode.Width-width)/2, (mode.Height-height)/2) } width, height = window.GetFramebufferSize() windowWidth, windowHeight = float32(width), float32(height) SetVSync(vsync) Gl = webgl.NewContext() Gl.Viewport(0, 0, width, height) window.SetFramebufferSizeCallback(func(window *glfw.Window, w, h int) { width, height = window.GetFramebufferSize() Gl.Viewport(0, 0, width, height) // TODO: when do we want to handle resizing? and who should deal with it? // responder.Resize(w, h) }) window.SetCursorPosCallback(func(window *glfw.Window, x, y float64) { Mouse.X, Mouse.Y = float32(x), float32(y) Mouse.Action = MOVE }) window.SetMouseButtonCallback(func(window *glfw.Window, b glfw.MouseButton, a glfw.Action, m glfw.ModifierKey) { x, y := window.GetCursorPos() Mouse.X, Mouse.Y = float32(x), float32(y) // this is only valid because we use an internal structure that is // 100% compatible with glfw3.h Mouse.Button = MouseButton(b) Mouse.Modifer = Modifier(m) if a == glfw.Press { Mouse.Action = PRESS } else { Mouse.Action = RELEASE } }) window.SetScrollCallback(func(window *glfw.Window, xoff, yoff float64) { Mouse.ScrollX = float32(xoff) Mouse.ScrollY = float32(yoff) }) window.SetKeyCallback(func(window *glfw.Window, k glfw.Key, s int, a glfw.Action, m glfw.ModifierKey) { key := Key(k) if a == glfw.Press { keyStates[key] = true } else if a == glfw.Release { keyStates[key] = false } }) window.SetSizeCallback(func(w *glfw.Window, widthInt int, heightInt int) { windowWidth = float32(widthInt) windowHeight = float32(heightInt) if !scaleOnResize { gameWidth, gameHeight = float32(widthInt), float32(heightInt) // Update default batch for _, scene := range scenes { if scene.world == nil { continue // with other scenes } for _, s := range scene.world.Systems() { if _, ok := s.(*RenderSystem); ok { Shaders.def.SetProjection(gameWidth, gameHeight) } } } } // Update HUD batch for _, scene := range scenes { if scene.world == nil { continue // with other scenes } for _, s := range scene.world.Systems() { if _, ok := s.(*RenderSystem); ok { // TODO: don't call it directly, but let HUD listen for it //Shaders.HUD.SetProjection(windowWidth, windowHeight) } } } }) window.SetCharCallback(func(window *glfw.Window, char rune) { // TODO: what does this do, when can we use it? // it's like KeyCallback, but for specific characters instead of keys...? // responder.Type(char) }) }
func run(customGame CustomGame, title string, width, height int, fullscreen bool) { err := glfw.Init() fatalErr(err) defer glfw.Terminate() Arrow = glfw.CreateStandardCursor(int(glfw.ArrowCursor)) Hand = glfw.CreateStandardCursor(int(glfw.HandCursor)) monitor := glfw.GetPrimaryMonitor() mode := monitor.GetVideoMode() if fullscreen { width = mode.Width height = mode.Height glfw.WindowHint(glfw.Decorated, 0) } else { monitor = nil } glfw.WindowHint(glfw.ContextVersionMajor, 2) glfw.WindowHint(glfw.ContextVersionMinor, 1) window, err = glfw.CreateWindow(width, height, title, nil, nil) fatalErr(err) window.MakeContextCurrent() if !fullscreen { window.SetPos((mode.Width-width)/2, (mode.Height-height)/2) } width, height = window.GetFramebufferSize() glfw.SwapInterval(1) Gl = webgl.NewContext() Gl.Viewport(0, 0, width, height) window.SetFramebufferSizeCallback(func(window *glfw.Window, w, h int) { width, height = window.GetFramebufferSize() Gl.Viewport(0, 0, width, height) // TODO: when do we want to handle resizing? and who should deal with it? // responder.Resize(w, h) }) window.SetCursorPosCallback(func(window *glfw.Window, x, y float64) { Mouse.X, Mouse.Y = float32(x), float32(y) Mouse.Action = MOVE }) window.SetMouseButtonCallback(func(window *glfw.Window, b glfw.MouseButton, a glfw.Action, m glfw.ModifierKey) { x, y := window.GetCursorPos() Mouse.X, Mouse.Y = float32(x), float32(y) if a == glfw.Press { Mouse.Action = PRESS } else { Mouse.Action = RELEASE } }) window.SetScrollCallback(func(window *glfw.Window, xoff, yoff float64) { Mouse.ScrollX = float32(xoff) Mouse.ScrollY = float32(yoff) }) window.SetKeyCallback(func(window *glfw.Window, k glfw.Key, s int, a glfw.Action, m glfw.ModifierKey) { key := Key(k) if a == glfw.Press { keyStates[key] = true } else if a == glfw.Release { keyStates[key] = false } }) window.SetCharCallback(func(window *glfw.Window, char rune) { // TODO: what does this do, when can we use it? // it's like KeyCallback, but for specific characters instead of keys...? // responder.Type(char) }) runLoop(customGame, false) }