func CreateWindow(title string, width, height int, fullscreen bool, msaa int) { canvas := document.CreateElement("canvas").(*dom.HTMLCanvasElement) devicePixelRatio := js.Global.Get("devicePixelRatio").Float() canvas.Width = int(float64(width)*devicePixelRatio + 0.5) // Nearest non-negative int. canvas.Height = int(float64(height)*devicePixelRatio + 0.5) // Nearest non-negative int. canvas.Style().SetProperty("width", fmt.Sprintf("%vpx", width), "") canvas.Style().SetProperty("height", fmt.Sprintf("%vpx", height), "") if document.Body() == nil { js.Global.Get("document").Set("body", js.Global.Get("document").Call("createElement", "body")) log.Println("Creating body, since it doesn't exist.") } document.Body().Style().SetProperty("margin", "0", "") document.Body().AppendChild(canvas) document.SetTitle(title) var err error Gl, err = gl.NewContext(canvas.Underlying(), nil) // TODO: we can add arguments here if err != nil { log.Println("Could not create context:", err) return } Gl.Viewport(0, 0, width, height) Gl.GetExtension("OES_texture_float") // DEBUG: Add framebuffer information div. if false { //canvas.Height -= 30 text := document.CreateElement("div") textContent := fmt.Sprintf("%v %v (%v) @%v", dom.GetWindow().InnerWidth(), canvas.Width, float64(width)*devicePixelRatio, devicePixelRatio) text.SetTextContent(textContent) document.Body().AppendChild(text) } gameWidth = float32(width) gameHeight = float32(height) windowWidth = WindowWidth() windowHeight = WindowHeight() w := dom.GetWindow() w.AddEventListener("keypress", false, func(ev dom.Event) { // TODO: Not sure what to do here, come back //ke := ev.(*dom.KeyboardEvent) //responser.Type(rune(keyStates[Key(ke.KeyCode)])) }) w.AddEventListener("keydown", false, func(ev dom.Event) { ke := ev.(*dom.KeyboardEvent) Input.keys.Set(Key(ke.KeyCode), true) }) w.AddEventListener("keyup", false, func(ev dom.Event) { ke := ev.(*dom.KeyboardEvent) Input.keys.Set(Key(ke.KeyCode), false) }) Files = NewLoader() WorldBounds.Max = Point{GameWidth(), GameHeight()} }
func runLoop(defaultScene Scene, headless bool) { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) signal.Notify(c, syscall.SIGTERM) go func() { <-c closeEvent() }() app.Main(func(a app.App) { var ( images *glutil.Images fps *debug.FPS ) for e := range a.Events() { switch e := a.Filter(e).(type) { case lifecycle.Event: switch e.Crosses(lifecycle.StageVisible) { case lifecycle.CrossOn: Gl = gl.NewContext(e.DrawContext) RunPreparation(defaultScene) images = glutil.NewImages(e.DrawContext.(mobilegl.Context)) fps = debug.NewFPS(images) // Let the device know we want to start painting :-) a.Send(paint.Event{}) case lifecycle.CrossOff: closeEvent() } case size.Event: sz = e windowWidth = float32(sz.WidthPx) windowHeight = float32(sz.HeightPx) Gl.Viewport(0, 0, sz.WidthPx, sz.HeightPx) case paint.Event: if e.External { // As we are actively painting as fast as // we can (usually 60 FPS), skip any paint // events sent by the system. continue } RunIteration() if closeGame { break } fps.Draw(sz) // Reset mouse if needed if Mouse.Action == RELEASE { Mouse.Action = NEUTRAL } a.Publish() // same as SwapBuffers // Drive the animation by preparing to paint the next frame // after this one is shown. - FPS is ignored here! a.Send(paint.Event{}) case touch.Event: Mouse.X = e.X Mouse.Y = e.Y switch e.Type { case touch.TypeBegin: Mouse.Action = PRESS case touch.TypeMove: Mouse.Action = MOVE case touch.TypeEnd: Mouse.Action = RELEASE } } } }) }
func CreateWindow(title string, width, height int, fullscreen bool, msaa int) { err := glfw.Init() fatalErr(err) cursorArrow = glfw.CreateStandardCursor(int(glfw.ArrowCursor)) cursorIBeam = glfw.CreateStandardCursor(int(glfw.IBeamCursor)) cursorCrosshair = glfw.CreateStandardCursor(int(glfw.CrosshairCursor)) cursorHand = glfw.CreateStandardCursor(int(glfw.HandCursor)) cursorHResize = glfw.CreateStandardCursor(int(glfw.HResizeCursor)) cursorVResize = glfw.CreateStandardCursor(int(glfw.VResizeCursor)) 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) glfw.WindowHint(glfw.Samples, msaa) 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 = gl.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 { Input.keys.Set(key, true) } else if a == glfw.Release { Input.keys.Set(key, false) } }) window.SetSizeCallback(func(w *glfw.Window, widthInt int, heightInt int) { message := WindowResizeMessage{ OldWidth: int(windowWidth), OldHeight: int(windowHeight), NewWidth: widthInt, NewHeight: heightInt, } windowWidth = float32(widthInt) windowHeight = float32(heightInt) if !scaleOnResize { gameWidth, gameHeight = float32(widthInt), float32(heightInt) } Mailbox.Dispatch(message) }) 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) }) }