예제 #1
0
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()}
}
예제 #2
0
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
				}
			}
		}
	})
}
예제 #3
0
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)
	})
}