示例#1
0
文件: graphics.go 项目: am4/chip8
func initGraphics() error {
	if err := gl.Init(); err != nil {
		return err
	}

	if err := glfw.Init(); err != nil {
		return err
	}

	glfw.WindowHint(glfw.Resizable, glfw.False)

	var err error
	window, err = glfw.CreateWindow(64*scaleRatio, 32*scaleRatio, "CHIP-8 Emulator", nil, nil)

	if err != nil {
		return err
	}

	window.MakeContextCurrent()

	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(0, 64, 32, 0, 0, 1)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()

	clear()
	window.SwapBuffers()

	return nil
}
示例#2
0
func (ctx *DrawContext) drawHud(o *orrery.Orrery, frametime time.Duration) {
	txt, size, err := ctx.createHudTexture(o, frametime)
	if err != nil {
		log.Fatalf(`can't create texture from text surface: %s`, err)
	}
	defer gl.DeleteTextures(1, &txt)

	gl.MatrixMode(gl.PROJECTION)
	gl.PushMatrix()
	gl.LoadIdentity()
	gl.Ortho(0.0, float64(ctx.width), float64(ctx.height), 0.0, -1.0, 1.0)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
	gl.Clear(gl.DEPTH_BUFFER_BIT)

	gl.BindTexture(gl.TEXTURE_2D, txt)
	gl.Enable(gl.TEXTURE_2D)
	defer gl.Disable(gl.TEXTURE_2D)

	gl.Color3f(1, 1, 1)
	gl.Begin(gl.QUADS)
	gl.TexCoord2f(0, 0)
	gl.Vertex2f(0.0, 0.0)
	gl.TexCoord2f(1, 0)
	gl.Vertex2f(float32(size[0]), 0.0)
	gl.TexCoord2f(1, 1)
	gl.Vertex2f(float32(size[0]), float32(size[1]))
	gl.TexCoord2f(0, 1)
	gl.Vertex2f(0.0, float32(size[1]))
	gl.End()

	gl.PopMatrix()
}
示例#3
0
文件: demo.go 项目: rdterner/gl
func drawScene(w *glfw.Window) {
	width, height := w.GetFramebufferSize()
	ratio := float32(width) / float32(height)
	var x1, x2, y1, y2 float32
	if ratio > 1 {
		x1, x2, y1, y2 = -ratio, ratio, -1, 1
	} else {
		x1, x2, y1, y2 = -1, 1, -1/ratio, 1/ratio
	}

	gl.Viewport(0, 0, int32(width), int32(height))
	gl.Clear(gl.COLOR_BUFFER_BIT)

	// Applies subsequent matrix operations to the projection matrix stack
	gl.MatrixMode(gl.PROJECTION)

	gl.LoadIdentity()                                                   // replace the current matrix with the identity matrix
	gl.Ortho(float64(x1), float64(x2), float64(y1), float64(y2), 1, -1) // multiply the current matrix with an orthographic matrix

	// Applies subsequent matrix operations to the modelview matrix stack
	gl.MatrixMode(gl.MODELVIEW)

	gl.LoadIdentity()

	gl.LineWidth(1)
	gl.Begin(gl.LINE)   // delimit the vertices of a primitive or a group of like primitives
	gl.Color3f(0, 0, 0) // set the current color
	gl.Vertex3f(0, y1, 0)
	gl.Vertex3f(0, y2, 0)
	gl.Vertex3f(x1, 0, 0)
	gl.Vertex3f(x2, 0, 0)
	gl.End()

	gl.Rotatef(float32(glfw.GetTime()*50), 0, 0, 1) // multiply the current matrix by a rotation matrix

	s := float32(.95)

	gl.Begin(gl.TRIANGLES)
	gl.Color3f(1, 0, 0)  // set the current color
	gl.Vertex3f(0, s, 0) // specify a vertex
	gl.Color3f(0, 1, 0)
	gl.Vertex3f(s*.866, s*-0.5, 0)
	gl.Color3f(0, 0, 1)
	gl.Vertex3f(s*-.866, s*-0.5, 0)
	gl.End()

	gl.LineWidth(5)
	gl.Begin(gl.LINE_LOOP)
	for i := float64(0); i < 2*math.Pi; i += .05 {
		r, g, b := hsb2rgb(float32(i/(2*math.Pi)), 1, 1)
		gl.Color3f(r, g, b)
		gl.Vertex3f(s*float32(math.Sin(i)), s*float32(math.Cos(i)), 0)
	}
	gl.End()

}
示例#4
0
/* new window size or exposure */
func reshape(width int32, height int32) {
	h := float64(height) / float64(width)
	gl.Viewport(0, 0, width, height)
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Frustum(-1.0, 1.0, -h, h, 5.0, 600.0)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
	gl.Translatef(0.0, 0.0, -100)
}
示例#5
0
// onResize sets up a simple 2d ortho context based on the window size
func onResize(window *glfw.Window, w, h int) {
	w, h = window.GetSize() // query window to get screen pixels
	width, height := window.GetFramebufferSize()
	gl.Viewport(0, 0, int32(width), int32(height))
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(0, float64(w), 0, float64(h), -1, 1)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
	gl.ClearColor(1, 1, 1, 1)
}
示例#6
0
func main() {
	runtime.LockOSThread()

	if err := glfw.Init(); err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	window, err := glfw.CreateWindow(800, 600, "fontstash example", nil, nil)
	if err != nil {
		panic(err)
	}

	window.MakeContextCurrent()
	glfw.SwapInterval(1)
	gl.Init()

	data, err := ioutil.ReadFile(filepath.Join("..", "ClearSans-Regular.ttf"))
	if err != nil {
		panic(err)
	}

	gl.Enable(gl.TEXTURE_2D)

	tmpBitmap := make([]byte, 512*512)
	cdata, err, _, tmpBitmap := truetype.BakeFontBitmap(data, 0, 32, tmpBitmap, 512, 512, 32, 96)
	var ftex uint32
	gl.GenTextures(1, &ftex)
	gl.BindTexture(gl.TEXTURE_2D, ftex)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, 512, 512, 0,
		gl.ALPHA, gl.UNSIGNED_BYTE, unsafe.Pointer(&tmpBitmap[0]))

	gl.ClearColor(0.3, 0.3, 0.32, 1.)

	for !window.ShouldClose() {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
		gl.MatrixMode(gl.PROJECTION)
		gl.LoadIdentity()
		gl.Ortho(0, 800, 600, 0, 0, 1)
		gl.MatrixMode(gl.MODELVIEW)
		gl.LoadIdentity()
		gl.Disable(gl.DEPTH_TEST)
		gl.Color4ub(255, 255, 255, 255)
		gl.Enable(gl.BLEND)
		gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

		my_print(100, 100, "The quick brown fox jumps over the fence", ftex, cdata)

		window.SwapBuffers()
		glfw.PollEvents()
	}
}
示例#7
0
func setupScene(width int, height int) {
	gl.Disable(gl.DEPTH_TEST)
	gl.Disable(gl.LIGHTING)

	gl.ClearColor(0.5, 0.5, 0.5, 0.0)

	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(0, float64(width), 0, float64(height), -1, 1)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
}
示例#8
0
func drawSpinner(spinner int) {
	gl.LoadIdentity()
	gl.Translatef(30.5, 30.5, 0)
	gl.Rotatef(float32(spinner), 0, 0, 1)
	gl.Color3d(0, 0, 0)
	gl.Rectd(-0.5, -10.5, 0.5, 10.5)
}
示例#9
0
func drawSlide() {
	gl.Clear(gl.COLOR_BUFFER_BIT)

	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
	gl.Translatef(0, 0, -3.0)

	gl.Begin(gl.QUADS)

	//top left
	gl.TexCoord2f(0, 0)
	gl.Vertex3f(-1, 1, 0)
	//top right
	gl.TexCoord2f(1, 0)
	gl.Vertex3f(1, 1, 0)

	//bottom right
	gl.TexCoord2f(1, 1)
	gl.Vertex3f(1, -1, 0)

	//bottom left
	gl.TexCoord2f(0, 1)
	gl.Vertex3f(-1, -1, 0)

	gl.End()

}
示例#10
0
func setupScene() {

	gl.ClearColor(0, 0, 0, 0)
	if texDel {
		gl.DeleteTextures(1, tex1)
	}
	tex1 = newTexture(*slides[selCell].getImage(monWidth, monHeight))

	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(-1, 1, -1, 1, 1.0, 10.0)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
	texDel = true

}
示例#11
0
// OpenGL draw function
func draw() {
	gl.Clear(gl.COLOR_BUFFER_BIT)
	gl.Enable(gl.BLEND)
	gl.Enable(gl.POINT_SMOOTH)
	gl.Enable(gl.LINE_SMOOTH)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.LoadIdentity()

	gl.Begin(gl.LINES)
	gl.Color3f(.2, .2, .2)
	for i := range staticLines {
		x := staticLines[i].GetAsSegment().A.X
		y := staticLines[i].GetAsSegment().A.Y
		gl.Vertex3f(float32(x), float32(y), 0)
		x = staticLines[i].GetAsSegment().B.X
		y = staticLines[i].GetAsSegment().B.Y
		gl.Vertex3f(float32(x), float32(y), 0)
	}
	gl.End()

	gl.Color4f(.3, .3, 1, .8)
	// draw balls
	for _, ball := range balls {
		gl.PushMatrix()
		pos := ball.Body.Position()
		rot := ball.Body.Angle() * chipmunk.DegreeConst
		gl.Translatef(float32(pos.X), float32(pos.Y), 0.0)
		gl.Rotatef(float32(rot), 0, 0, 1)
		drawCircle(float64(ballRadius), 60)
		gl.PopMatrix()
	}
}
示例#12
0
文件: camera.go 项目: gonutz/settlers
func (cam *camera) recalcOrthoBorders() {
	const totalW = gameW + leftBorder + rightBorder
	const totalH = gameH + topBorder + bottomBorder
	const totalRatio = float64(totalW) / totalH

	windowRatio := float64(cam.WindowWidth) / float64(cam.WindowHeight)

	var horizontalBorder, verticalBorder float64

	if windowRatio > totalRatio {
		// window is wider than game => borders left and right
		horizontalBorder = (windowRatio*totalH - totalW) / 2
	} else {
		// window is higher than game => borders on top and bottom
		verticalBorder = (totalW/windowRatio - totalH) / 2
	}

	cam.Left = -leftBorder - horizontalBorder
	cam.Right = gameW + rightBorder + horizontalBorder
	cam.Top = -topBorder - verticalBorder
	cam.Bottom = gameH + bottomBorder + verticalBorder

	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(cam.Left, cam.Right, cam.Bottom, cam.Top, -1, 1)
	gl.MatrixMode(gl.MODELVIEW)
}
示例#13
0
文件: opengl.go 项目: manyminds/tmx
func main() {
	err := glfw.Init()
	if err != nil {
		panic(err)
	}
	defer glfw.Terminate()
	fp, err := os.Open("example.tmx")
	if err != nil {
		panic(err)
	}

	m, err := tmx.NewMap(fp)
	if err != nil {
		panic(err)
	}

	var monitor *glfw.Monitor
	window, err := glfw.CreateWindow(screenWidth, screenHeight, "Map Renderer", monitor, nil)
	if err != nil {
		panic(err)
	}

	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		panic(err)
	}

	width, height := window.GetFramebufferSize()
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
	gl.ClearColor(1.0, 1.0, 1.0, 1.0)
	gl.Viewport(0, 0, int32(width), int32(height))
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Ortho(0, float64(width), float64(height), 0, -1, 1)
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	canvas := newOpenGLCanvas(width, height, float32(width)/float32(screenWidth), float32(height)/float32(screenHeight))
	renderer := tmx.NewRenderer(*m, canvas)
	fps := 0
	startTime := time.Now().UnixNano()
	timer := tmx.CreateTimer()
	timer.Start()
	for !window.ShouldClose() {
		elapsed := float64(timer.GetElapsedTime()) / (1000 * 1000)
		renderer.Render(int64(math.Ceil(elapsed)))
		fps++
		if time.Now().UnixNano()-startTime > 1000*1000*1000 {
			log.Println(fps)
			startTime = time.Now().UnixNano()
			fps = 0
		}

		window.SwapBuffers()
		glfw.PollEvents()
		timer.UpdateTime()
	}
}
示例#14
0
func draw() {
	gl.Clear(gl.COLOR_BUFFER_BIT)
	gl.Enable(gl.BLEND)
	gl.Enable(gl.POINT_SMOOTH)
	gl.Enable(gl.LINE_SMOOTH)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.LoadIdentity()

	//Transform screen to keep player in middle. Added intentation to make obvious the push matrix is like a block
	gl.PushMatrix()
	// gl.Translatef((1280/2)-float32(player.x), 0, 0.0)

	// gl.Begin(gl.LINES)
	// gl.Color3f(.2, .5, .2)
	// for i := range staticLines {
	// 	x := staticLines[i].GetAsSegment().A.X
	// 	y := staticLines[i].GetAsSegment().A.Y
	// 	gl.Vertex3f(float32(x), float32(y), 0)
	// 	x = staticLines[i].GetAsSegment().B.X
	// 	y = staticLines[i].GetAsSegment().B.Y
	// 	gl.Vertex3f(float32(x), float32(y), 0)
	// }
	// gl.End()

	gl.Color4f(player.color_r, player.color_g, player.color_b, player.color_a)

	//Draw Player
	gl.PushMatrix()
	rot := player.rot
	pos_x := player.x
	pos_y := player.y

	gl.Translatef(pos_x, pos_y, 0.0)
	gl.Rotatef(float32(rot), 0, 0, 1)
	drawCircle(float64(BALL_RADIUS), 20)
	gl.PopMatrix()

	//Draw the grapple
	gl.PushMatrix()
	gl.Translatef(player.hook.x_end, player.hook.y_end, 0.0)
	drawCircle(float64(5), 5)
	gl.PopMatrix()

	//Grapple Line
	gl.LineWidth(2.5)
	gl.Color3f(1.0, 0.0, 0.0)
	gl.Begin(gl.LINES)
	gl.Vertex3f(player.x, player.y, 0.0)
	gl.Vertex3f(player.hook.x_end, player.hook.y_end, 0)
	gl.End()

	//Second Pop
	gl.PopMatrix()
}
示例#15
0
func (c *Camera) Update() {
	// This has to be called in the GL thread
	vx := math.Cos(c.alpha)*10 + c.Pos.X
	vy := math.Sin(c.alpha)*10 + c.Pos.Y
	vz := math.Sin(c.theta)*10 + c.Pos.Z

	c.lookAt(vector.V3{vx, vy, vz})

	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Frustum(-c.frustum.nearW, c.frustum.nearW, -c.frustum.nearH, c.frustum.nearH, c.frustum.zNear, c.frustum.zFar)
}
示例#16
0
文件: ui.go 项目: egonelbre/spector
func (state *State) Reset(window *glfw.Window) {
	gl.ClearColor(1, 1, 1, 1)
	gl.Clear(gl.COLOR_BUFFER_BIT)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()

	gl.Disable(gl.DEPTH)
	gl.Enable(gl.FRAMEBUFFER_SRGB)

	width, height := window.GetSize()
	gl.Viewport(0, 0, int32(width), int32(height))
	gl.Ortho(0, float64(width), float64(height), 0, 30, -30)
}
示例#17
0
func setupScene() {
	gl.Enable(gl.DEPTH_TEST)
	gl.Enable(gl.LIGHTING)

	gl.ClearColor(0.5, 0.5, 0.5, 0.0)
	gl.ClearDepth(1)
	gl.DepthFunc(gl.LEQUAL)

	ambient := []float32{0.5, 0.5, 0.5, 1}
	diffuse := []float32{1, 1, 1, 1}
	lightPosition := []float32{-5, 5, 10, 0}
	gl.Lightfv(gl.LIGHT0, gl.AMBIENT, &ambient[0])
	gl.Lightfv(gl.LIGHT0, gl.DIFFUSE, &diffuse[0])
	gl.Lightfv(gl.LIGHT0, gl.POSITION, &lightPosition[0])
	gl.Enable(gl.LIGHT0)

	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
	gl.Frustum(-1, 1, -1, 1, 1.0, 10.0)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
}
示例#18
0
文件: Window.go 项目: XO-Lib/GCXO
func reshape(w int, h int) {
	/* Because Gil specified "screen coordinates" (presumably with an
	   upper-left origin), this short bit of code sets up the coordinate
	   system to correspond to actual window coodrinates.  This code
	   wouldn't be required if you chose a (more typical in 3D) abstract
	   coordinate system. */

	gl.Viewport(0, 0, int32(w), int32(h))         /* Establish viewing area to cover entire window. */
	gl.MatrixMode(gl.PROJECTION)                  /* Start modifying the projection matrix. */
	gl.LoadIdentity()                             /* Reset project matrix. */
	gl.Ortho(0, float64(w), 0, float64(h), -1, 1) /* Map abstract coords directly to window coords. */
	gl.Scalef(1, -1, 1)                           /* Invert Y axis so increasing Y goes down. */
	gl.Translatef(0, float32(-h), 0)              /* Shift origin up to upper-left corner. */
}
示例#19
0
func reshape(window *glfw.Window, w, h int) {
	gl.ClearColor(1, 1, 1, 1)
	//fmt.Println(gl.GetString(gl.EXTENSIONS))
	gl.Viewport(0, 0, int32(w), int32(h))         /* Establish viewing area to cover entire window. */
	gl.MatrixMode(gl.PROJECTION)                  /* Start modifying the projection matrix. */
	gl.LoadIdentity()                             /* Reset project matrix. */
	gl.Ortho(0, float64(w), 0, float64(h), -1, 1) /* Map abstract coords directly to window coords. */
	gl.Scalef(1, -1, 1)                           /* Invert Y axis so increasing Y goes down. */
	gl.Translatef(0, float32(-h), 0)              /* Shift origin up to upper-left corner. */
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.Disable(gl.DEPTH_TEST)
	width, height = w, h
}
示例#20
0
// OpenGL draw function
func draw() {
	gl.Clear(gl.COLOR_BUFFER_BIT)
	gl.Enable(gl.BLEND)
	gl.Enable(gl.POINT_SMOOTH)
	gl.Enable(gl.LINE_SMOOTH)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.LoadIdentity()

	player := game.Player

	//Transform screen.
	gl.PushMatrix()
	gl.Translatef((1280/2)-float32((player.Body.Position().X)), 0, 0.0)

	gl.Begin(gl.LINES)
	gl.Color3f(.2, .5, .2)
	for _, segment := range game.Level.GetChipmunkSegments() {
		x := segment.GetAsSegment().A.X
		y := segment.GetAsSegment().A.Y
		gl.Vertex3f(float32(x), float32(y), 0)
		x = segment.GetAsSegment().B.X
		y = segment.GetAsSegment().B.Y
		gl.Vertex3f(float32(x), float32(y), 0)
	}
	gl.End()

	gl.Color4f(.9, .1, 1, .9)
	// draw balls
	for _, enemy := range game.Enemies {
		gl.PushMatrix()
		pos := enemy.Body.Position()
		rot := enemy.Body.Angle() * game.DegreeConst
		gl.Translatef(float32(pos.X), float32(pos.Y), 0.0)
		gl.Rotatef(float32(rot), 0, 0, 1)
		drawCircle(float64(enemy.Radius), 60)
		gl.PopMatrix()
	}
	gl.Color4f(.3, .3, 1, .8)
	//Draw Player
	gl.PushMatrix()
	pos := player.Body.Position()
	rot := player.Body.Angle() * game.DegreeConst
	gl.Translatef(float32(pos.X), float32(pos.Y), 0.0)
	gl.Rotatef(float32(rot), 0, 0, 1)
	drawCircle(float64(player.Radius), 60)
	gl.PopMatrix()

	gl.PopMatrix()
}
示例#21
0
func drawScene() {
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

	gl.LineWidth(1)

	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
	gl.Translatef(0, 0, 0.0)
	//gl.Rotatef(rotationX, 1, 0, 0)
	//gl.Rotatef(rotationY, 0, 1, 0)

	//rotationX += 0.5
	//rotationY += 0.5

	//gl.BindTexture(gl.TEXTURE_2D, texture)

}
示例#22
0
func drawBox() {
	gl.LoadIdentity()
	/*gl.Translatef(50, 100, 0)
	gl.Color3d(201.0/255, 201.0/255, 201.0/255)
	gl.Recti(0, 0, 106, 18)
	if !boxUpdated {
		gl.Color3d(1, 1, 1)
	} else {
		gl.Color3d(0, 1, 0)
	}
	gl.Recti(0+1, 0+1, 106-1, 18-1)*/

	c := mgl64.Vec3{1, 1, 1}
	if boxUpdated {
		c = mgl64.Vec3{42.0 / 255, 154.0 / 255, 254.0 / 255}
	}

	drawInnerRoundedBox(mgl64.Vec2{50, 100},
		mgl64.Vec2{106, 18},
		c.Mul(201.0/255),
		c)
}
示例#23
0
文件: main.go 项目: egonelbre/spector
func main() {
	flag.Parse()

	go func() {
		http.ListenAndServe("localhost:6060", nil)
	}()

	go func() {
		for {
			runtime.GC()
			time.Sleep(1)
		}
	}()

	if err := glfw.Init(); err != nil {
		log.Fatalln("failed to initialize glfw:", err)
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.True)
	glfw.WindowHint(glfw.Visible, glfw.False) // do not steal focus
	glfw.WindowHint(glfw.Samples, 4)

	glfw.WindowHint(glfw.ContextVersionMajor, 2)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)

	window, err := glfw.CreateWindow(800, 600, "Spector", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()
	window.Restore()
	window.SetPos(32, 64)

	if err := gl.Init(); err != nil {
		panic(err)
	}

	if err := gl.GetError(); err != 0 {
		fmt.Println("INIT", err)
	}

	startnano := time.Now().UnixNano()

	DrawList := draw.NewList()
	for !window.ShouldClose() {
		start := qpc.Now()
		if window.GetKey(glfw.KeyEscape) == glfw.Press {
			return
		}

		now := float64(time.Now().UnixNano()-startnano) / 1e9
		width, height := window.GetSize()

		{ // reset window
			gl.MatrixMode(gl.MODELVIEW)
			gl.LoadIdentity()

			gl.Viewport(0, 0, int32(width), int32(height))
			gl.Ortho(0, float64(width), float64(height), 0, 30, -30)
			gl.ClearColor(1, 1, 1, 1)
			gl.Clear(gl.COLOR_BUFFER_BIT)
		}

		DrawList.Reset()

		DrawList.AddRectFill(&draw.Rectangle{
			draw.Vector{10, 10},
			draw.Vector{50, 50},
		}, draw.Red)

		CircleRadius := float32(50.0 * math.Sin(now*1.3))
		DrawList.AddCircle(
			draw.Vector{100, 100}, CircleRadius, draw.Red)
		DrawList.AddArc(
			draw.Vector{200, 100}, CircleRadius/2+50,
			float32(now),
			float32(math.Sin(now)*10),
			draw.ColorHSL(float32(math.Sin(now*0.3)), 0.8, 0.5))

		LineWidth := float32(math.Sin(now*2.1)*5 + 5)

		LineCount := int(width / 8)
		line := make([]draw.Vector, LineCount)
		for i := range line {
			r := float64(i) / float64(LineCount-1)
			line[i].X = float32(r) * float32(width)
			line[i].Y = float32(height)*0.5 + float32(math.Sin(r*11.8+now)*100)
		}
		DrawList.AddLine(line[:], LineWidth,
			draw.ColorHSL(float32(math.Sin(now*0.3)), 0.6, 0.6))

		CircleCount := int(width / 8)
		circle := make([]draw.Vector, CircleCount)
		for i := range circle {
			p := float64(i) / float64(CircleCount)
			a := now + p*math.Pi*2
			w := math.Sin(p*62)*20.0 + 100.0
			circle[i].X = float32(width)*0.5 + float32(math.Cos(a)*w)
			circle[i].Y = float32(height)*0.5 + float32(math.Sin(a)*w)
		}

		// DrawList.PushClip(draw.Rect(0, 0, float32(width)/2, float32(height)/2))
		DrawList.AddClosedLine(circle[:], LineWidth, draw.Green)
		// DrawList.PopClip()

		render.List(width, height, DrawList)
		if err := gl.GetError(); err != 0 {
			fmt.Println(err)
		}
		stop := qpc.Now()

		window.SwapBuffers()
		runtime.GC()
		glfw.PollEvents()

		fmt.Printf("%-10.3f\n", stop.Sub(start).Duration().Seconds()*1000)
	}

}
示例#24
0
文件: main.go 项目: rexposadas/gx
func main() {
	if err := glfw.Init(nopContextWatcher{}); err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	window, err := glfw.CreateWindow(1536, 960, "", nil, nil)
	if err != nil {
		panic(err)
	}
	globalWindow = window
	window.MakeContextCurrent()

	window.SetInputMode(glfw.CursorMode, glfw.CursorHidden)

	if err := gl.Init(); nil != err {
		panic(err)
	}

	glfw.SwapInterval(1) // Vsync.

	framebufferSizeCallback := func(w *glfw.Window, framebufferSize0, framebufferSize1 int) {
		gl.Viewport(0, 0, int32(framebufferSize0), int32(framebufferSize1))

		var windowSize [2]int
		windowSize[0], windowSize[1] = w.GetSize()

		// Update the projection matrix
		gl.MatrixMode(gl.PROJECTION)
		gl.LoadIdentity()
		gl.Ortho(0, float64(windowSize[0]), float64(windowSize[1]), 0, -1, 1)
		gl.MatrixMode(gl.MODELVIEW)
	}
	{
		var framebufferSize [2]int
		framebufferSize[0], framebufferSize[1] = window.GetFramebufferSize()
		framebufferSizeCallback(window, framebufferSize[0], framebufferSize[1])
	}
	window.SetFramebufferSizeCallback(framebufferSizeCallback)

	var inputEventQueue []InputEvent
	mousePointer = &Pointer{VirtualCategory: POINTING}

	var lastMousePos mgl64.Vec2
	lastMousePos[0], lastMousePos[1] = window.GetCursorPos()
	MousePos := func(w *glfw.Window, x, y float64) {
		//fmt.Println("MousePos:", x, y)

		inputEvent := InputEvent{
			Pointer:    mousePointer,
			EventTypes: map[EventType]bool{SLIDER_EVENT: true, AXIS_EVENT: true},
			InputId:    0,
			Buttons:    nil,
			Sliders:    []float64{x - lastMousePos[0], y - lastMousePos[1]}, // TODO: Do this in a pointer general way?
			Axes:       []float64{x, y},
		}
		lastMousePos[0] = x
		lastMousePos[1] = y
		inputEventQueue = EnqueueInputEvent(inputEvent, inputEventQueue)
	}
	window.SetCursorPosCallback(MousePos)
	MousePos(window, lastMousePos[0], lastMousePos[1])

	gl.ClearColor(0.85, 0.85, 0.85, 1)

	rand.Seed(4)
	var widget = newMultitouchTestBoxWidget(mgl64.Vec2{600, 300}, rand.Intn(6))
	var widget2 = newMultitouchTestBoxWidget(mgl64.Vec2{600 + 210, 300 + 210}, rand.Intn(6))
	var widget3 = newMultitouchTestBoxWidget(mgl64.Vec2{600 + 210, 300}, rand.Intn(6))
	var widget4 = newMultitouchTestBoxWidget(mgl64.Vec2{600, 300 + 210}, rand.Intn(6))

	go func() {
		<-time.After(5 * time.Second)
		log.Println("trigger!")
		widget.color++ // HACK: Racy.

		glfw.PostEmptyEvent()
	}()

	for !window.ShouldClose() {
		//glfw.PollEvents()
		glfw.WaitEvents()

		// Process Input.
		inputEventQueue = ProcessInputEventQueue(inputEventQueue)

		gl.Clear(gl.COLOR_BUFFER_BIT)

		widget.Render()
		widget2.Render()
		widget3.Render()
		widget4.Render()

		mousePointer.Render()

		window.SwapBuffers()
		log.Println("swapped buffers")
		runtime.Gosched()
	}
}
示例#25
0
文件: window.go 项目: fmd/gogol
func modelViewMode() {
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
}
示例#26
0
文件: main.go 项目: rexposadas/gx
func main() {
	if err := glfw.Init(nopContextWatcher{}); err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Samples, 8) // Anti-aliasing.

	window, err := glfw.CreateWindow(400, 400, "", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		panic(err)
	}

	glfw.SwapInterval(1) // Vsync.

	InitFont()
	defer DeinitFont()

	framebufferSizeCallback := func(w *glfw.Window, framebufferSize0, framebufferSize1 int) {
		gl.Viewport(0, 0, int32(framebufferSize0), int32(framebufferSize1))

		var windowSize [2]int
		windowSize[0], windowSize[1] = w.GetSize()

		// Update the projection matrix.
		gl.MatrixMode(gl.PROJECTION)
		gl.LoadIdentity()
		gl.Ortho(0, float64(windowSize[0]), float64(windowSize[1]), 0, -1, 1)
		gl.MatrixMode(gl.MODELVIEW)
	}
	{
		var framebufferSize [2]int
		framebufferSize[0], framebufferSize[1] = window.GetFramebufferSize()
		framebufferSizeCallback(window, framebufferSize[0], framebufferSize[1])
	}
	window.SetFramebufferSizeCallback(framebufferSizeCallback)

	var inputEventQueue []events.InputEvent
	mousePointer = &events.Pointer{VirtualCategory: events.POINTING}

	window.SetMouseMovementCallback(func(w *glfw.Window, xpos, ypos, xdelta, ydelta float64) {
		inputEvent := events.InputEvent{
			Pointer:    mousePointer,
			EventTypes: map[events.EventType]struct{}{events.SLIDER_EVENT: {}},
			InputId:    0,
			Buttons:    nil,
			Sliders:    []float64{xdelta, ydelta},
		}
		if w.GetInputMode(glfw.CursorMode) != glfw.CursorDisabled {
			inputEvent.EventTypes[events.AXIS_EVENT] = struct{}{}
			inputEvent.Axes = []float64{xpos, ypos}
		}
		inputEventQueue = events.EnqueueInputEvent(inputEventQueue, inputEvent)
	})

	window.SetMouseButtonCallback(func(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) {
		inputEvent := events.InputEvent{
			Pointer:     mousePointer,
			EventTypes:  map[events.EventType]struct{}{events.BUTTON_EVENT: {}},
			InputId:     uint16(button),
			Buttons:     []bool{action != glfw.Release},
			Sliders:     nil,
			Axes:        nil,
			ModifierKey: uint8(mods),
		}
		inputEventQueue = events.EnqueueInputEvent(inputEventQueue, inputEvent)
	})

	go func() {
		<-time.After(5 * time.Second)
		log.Println("trigger!")
		boxUpdated = true

		glfw.PostEmptyEvent()
	}()

	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) // For font.

	gl.ClearColor(247.0/255, 247.0/255, 247.0/255, 1)

	var spinner int

	var widgets []events.Widgeter

	widgets = append(widgets, NewButtonWidget(mgl64.Vec2{50, 200}, func() { fmt.Println("button triggered") }))

	for !window.ShouldClose() && glfw.Press != window.GetKey(glfw.KeyEscape) {
		glfw.WaitEvents()

		// Process Input.
		inputEventQueue = events.ProcessInputEventQueue(inputEventQueue, widgets[0])

		gl.Clear(gl.COLOR_BUFFER_BIT)
		gl.LoadIdentity()

		for _, widget := range widgets {
			widget.Render()
		}

		drawSpinner(spinner)
		spinner++

		drawBox()

		gl.Color3d(1, 0, 0)
		NewOpenGlStream(mgl64.Vec2{50, 300}).PrintText(` !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
` + "`" + `abcdefghijklmno
pqrstuvwxyz{|}~`)

		window.SwapBuffers()
		log.Println("swapped buffers")

		//runtime.Gosched()
	}
}
示例#27
0
func main() {
	runtime.LockOSThread()

	if err := glfw.Init(); err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	window, err := glfw.CreateWindow(800, 600, "fontstash example", nil, nil)
	if err != nil {
		panic(err)
	}

	window.MakeContextCurrent()
	glfw.SwapInterval(1)
	gl.Init()

	stash := fontstash.New(512, 512)

	clearSansRegular, err := stash.AddFont(filepath.Join("..", "ClearSans-Regular.ttf"))
	if err != nil {
		panic(err)
	}

	clearSansItalic, err := stash.AddFont(filepath.Join("..", "ClearSans-Italic.ttf"))
	if err != nil {
		panic(err)
	}

	clearSansBold, err := stash.AddFont(filepath.Join("..", "ClearSans-Bold.ttf"))
	if err != nil {
		panic(err)
	}

	droidJapanese, err := stash.AddFont(filepath.Join("..", "DroidSansJapanese.ttf"))
	if err != nil {
		panic(err)
	}

	gl.ClearColor(0.3, 0.3, 0.32, 1.)

	for !window.ShouldClose() {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
		gl.MatrixMode(gl.PROJECTION)
		gl.LoadIdentity()
		gl.Ortho(0, 800, 0, 600, -1, 1)
		gl.MatrixMode(gl.MODELVIEW)
		gl.LoadIdentity()
		gl.Disable(gl.DEPTH_TEST)
		gl.Color4ub(255, 255, 255, 255)
		gl.Enable(gl.BLEND)
		gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

		gl.Disable(gl.TEXTURE_2D)
		gl.Begin(gl.QUADS)
		gl.Vertex2i(0, -5)
		gl.Vertex2i(5, -5)
		gl.Vertex2i(5, -11)
		gl.Vertex2i(0, -11)
		gl.End()

		sx := float64(100)
		sy := float64(250)

		stash.BeginDraw()

		dx := sx
		dy := sy
		dx = stash.DrawText(clearSansRegular, 24, dx, dy, "The quick ", [4]float32{0, 0, 0, 1})
		dx = stash.DrawText(clearSansItalic, 48, dx, dy, "brown ", [4]float32{1, 1, 0.5, 1})
		dx = stash.DrawText(clearSansRegular, 24, dx, dy, "fox ", [4]float32{0, 1, 0.5, 1})
		_, _, lh := stash.VMetrics(clearSansItalic, 24)
		dx = sx
		dy -= lh * 1.2
		dx = stash.DrawText(clearSansItalic, 24, dx, dy, "jumps over ", [4]float32{0, 1, 1, 1})
		dx = stash.DrawText(clearSansBold, 24, dx, dy, "the lazy ", [4]float32{1, 0, 1, 1})
		dx = stash.DrawText(clearSansRegular, 24, dx, dy, "dog.", [4]float32{0, 1, 0, 1})
		dx = sx
		dy -= lh * 1.2
		dx = stash.DrawText(clearSansRegular, 12, dx, dy, "Now is the time for all good men to come to the aid of the party.", [4]float32{0, 0, 1, 1})
		_, _, lh = stash.VMetrics(clearSansItalic, 12)
		dx = sx
		dy -= lh * 1.2 * 2
		dx = stash.DrawText(clearSansItalic, 18, dx, dy, "Ég get etið gler án þess að meiða mig.", [4]float32{1, 0, 0, 1})
		_, _, lh = stash.VMetrics(clearSansItalic, 18)
		dx = sx
		dy -= lh * 1.2
		stash.DrawText(droidJapanese, 18, dx, dy, "どこかに置き忘れた、サングラスと打ち明け話。", [4]float32{1, 1, 1, 1})

		stash.EndDraw()
		gl.Enable(gl.DEPTH_TEST)

		window.SwapBuffers()
		glfw.PollEvents()
	}
}
示例#28
0
func drawScene() {
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()
	gl.Translatef(0, 0, -3.0)
	gl.Rotatef(rotationX, 1, 0, 0)
	gl.Rotatef(rotationY, 0, 1, 0)

	rotationX += 0.5
	rotationY += 0.5

	gl.BindTexture(gl.TEXTURE_2D, texture)

	gl.Color4f(1, 1, 1, 1)

	gl.Begin(gl.QUADS)

	gl.Normal3f(0, 0, 1)
	gl.TexCoord2f(0, 0)
	gl.Vertex3f(-1, -1, 1)
	gl.TexCoord2f(1, 0)
	gl.Vertex3f(1, -1, 1)
	gl.TexCoord2f(1, 1)
	gl.Vertex3f(1, 1, 1)
	gl.TexCoord2f(0, 1)
	gl.Vertex3f(-1, 1, 1)

	gl.Normal3f(0, 0, -1)
	gl.TexCoord2f(1, 0)
	gl.Vertex3f(-1, -1, -1)
	gl.TexCoord2f(1, 1)
	gl.Vertex3f(-1, 1, -1)
	gl.TexCoord2f(0, 1)
	gl.Vertex3f(1, 1, -1)
	gl.TexCoord2f(0, 0)
	gl.Vertex3f(1, -1, -1)

	gl.Normal3f(0, 1, 0)
	gl.TexCoord2f(0, 1)
	gl.Vertex3f(-1, 1, -1)
	gl.TexCoord2f(0, 0)
	gl.Vertex3f(-1, 1, 1)
	gl.TexCoord2f(1, 0)
	gl.Vertex3f(1, 1, 1)
	gl.TexCoord2f(1, 1)
	gl.Vertex3f(1, 1, -1)

	gl.Normal3f(0, -1, 0)
	gl.TexCoord2f(1, 1)
	gl.Vertex3f(-1, -1, -1)
	gl.TexCoord2f(0, 1)
	gl.Vertex3f(1, -1, -1)
	gl.TexCoord2f(0, 0)
	gl.Vertex3f(1, -1, 1)
	gl.TexCoord2f(1, 0)
	gl.Vertex3f(-1, -1, 1)

	gl.Normal3f(1, 0, 0)
	gl.TexCoord2f(1, 0)
	gl.Vertex3f(1, -1, -1)
	gl.TexCoord2f(1, 1)
	gl.Vertex3f(1, 1, -1)
	gl.TexCoord2f(0, 1)
	gl.Vertex3f(1, 1, 1)
	gl.TexCoord2f(0, 0)
	gl.Vertex3f(1, -1, 1)

	gl.Normal3f(-1, 0, 0)
	gl.TexCoord2f(0, 0)
	gl.Vertex3f(-1, -1, -1)
	gl.TexCoord2f(1, 0)
	gl.Vertex3f(-1, -1, 1)
	gl.TexCoord2f(1, 1)
	gl.Vertex3f(-1, 1, 1)
	gl.TexCoord2f(0, 1)
	gl.Vertex3f(-1, 1, -1)

	gl.End()
}
示例#29
0
文件: window.go 项目: fmd/gogol
func projectionMode() {
	gl.MatrixMode(gl.PROJECTION)
	gl.LoadIdentity()
}
示例#30
0
func main() {
	if err := glfw.Init(); err != nil {
		fmt.Println("glfw.Init():", err)
		return
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Decorated, glfw.True)
	glfw.WindowHint(glfw.ContextVersionMajor, 1)
	glfw.WindowHint(glfw.ContextVersionMinor, 0)
	glfw.WindowHint(glfw.Resizable, glfw.True)

	window, err := glfw.CreateWindow(10, 10, "Settlers", nil, nil)
	if err != nil {
		fmt.Println("glfw.CreateWindow():", err)
		return
	}
	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		fmt.Println("gl.Init():", err)
		return
	}

	stash := fontstash.New(512, 512)
	fontID, err := stash.AddFont(resourcePath("MorrisRoman-Black.ttf"))
	if err != nil {
		fmt.Println(err)
		return
	}
	stash.SetYInverted(true)
	font := &font{stash, fontID, 35}

	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.MatrixMode(gl.MODELVIEW)
	gl.LoadIdentity()

	rand.Seed(time.Now().UnixNano())
	g := game.New([]game.Color{game.Red, game.White, game.Blue}, rand.Int())

	var lines []string
	window.SetCharCallback(func(_ *glfw.Window, r rune) {
		if len(lines) == 0 {
			lines = []string{""}
		}
		lines[len(lines)-1] += string(r)
	})
	window.SetCharModsCallback(func(_ *glfw.Window, r rune, _ glfw.ModifierKey) {
	})
	window.SetKeyCallback(func(_ *glfw.Window, key glfw.Key, _ int, action glfw.Action, _ glfw.ModifierKey) {
		if action == glfw.Release {
			return
		}
		if key == glfw.KeyEscape {
			window.SetShouldClose(true)
		}
		if key == glfw.Key1 {
			g.CurrentPlayer = 0
		}
		if key == glfw.Key2 {
			g.CurrentPlayer = 1
		}
		if key == glfw.Key3 {
			g.CurrentPlayer = 2
		}
		if key == glfw.Key4 {
			g.CurrentPlayer = 3
		}
		if key == glfw.KeyR {
			state = buildingRoad
		}
		if key == glfw.KeyS {
			state = buildingSettlement
		}
		if key == glfw.KeyKP2 {
			g.DealResources(2)
		}
		if key == glfw.KeyKP3 {
			g.DealResources(3)
		}
		if key == glfw.KeyKP4 {
			g.DealResources(4)
		}
		if key == glfw.KeyKP5 {
			g.DealResources(5)
		}
		if key == glfw.KeyKP6 {
			g.DealResources(6)
		}
		if key == glfw.KeyKP8 {
			g.DealResources(8)
		}
		if key == glfw.KeyKP9 {
			g.DealResources(9)
		}
		if key == glfw.KeyKP0 {
			g.DealResources(10)
		}
		if key == glfw.KeyKP1 {
			g.DealResources(11)
		}
		if key == glfw.KeyKP7 {
			g.DealResources(12)
		}
		if len(lines) > 0 && key == glfw.KeyBackspace && (action == glfw.Press || action == glfw.Repeat) {
			if len(lines[len(lines)-1]) == 0 {
				lines = lines[:len(lines)-1]
			} else {
				lines[len(lines)-1] = removeLastRune(lines[len(lines)-1])
			}
		}
		if (action == glfw.Press || action == glfw.Repeat) &&
			(key == glfw.KeyEnter || key == glfw.KeyKPEnter) {
			lines = append(lines, "")
		}
	})
	window.SetInputMode(glfw.CursorMode, glfw.CursorHidden)
	window.SetInputMode(glfw.CursorMode, glfw.CursorNormal)
	window.SetSizeCallback(func(_ *glfw.Window, w, h int) {
		windowW, windowH = w, h
		cam.WindowWidth, cam.WindowHeight = w, h
		gl.Viewport(0, 0, int32(w), int32(h))
	})

	if err := loadImages(); err != nil {
		fmt.Println(err)
		return
	}

	var background image.Image
	var backImg *glImage
	go func() {
		gameW, gameH := 7*200, 7*tileYOffset+tileSlopeHeight
		back := image.NewRGBA(image.Rect(0, 0, gameW, gameH))
		clearToTransparent(back)
		drawGameBackgroundIntoImage(back, g)
		background = back
	}()

	gameColorToString := func(c game.Color) string {
		switch c {
		case game.Red:
			return "red"
		case game.Orange:
			return "orange"
		case game.Blue:
			return "blue"
		default:
			return "white"
		}
	}

	roadImage := func(pos game.TileEdge, c game.Color) *glImage {
		color := gameColorToString(c)
		dir := "up"
		if isEdgeVertical(pos) {
			dir = "vertical"
		}
		if isEdgeGoingDown(pos) {
			dir = "down"
		}
		return glImages["road_"+color+"_"+dir]
	}

	settlementImage := func(c game.Color) *glImage {
		return glImages["settlement_"+gameColorToString(c)]
	}

	cityImage := func(c game.Color) *glImage {
		return glImages["city_"+gameColorToString(c)]
	}

	// TODO this is for showing the road/settlement being built currently
	var movingSettlementCorner game.TileCorner
	var movingSettlementVisible bool
	var movingRoadEdge game.TileEdge
	var movingRoadVisible bool
	window.SetCursorPosCallback(func(_ *glfw.Window, x, y float64) {
		mouseX, mouseY = x, y
		gameX, gameY := cam.screenToGame(x, y)
		movingSettlementCorner, movingSettlementVisible = screenToCorner(gameX, gameY)
		movingRoadEdge, movingRoadVisible = screenToEdge(gameX, gameY)
	})
	window.SetCursorEnterCallback(func(_ *glfw.Window, entered bool) {
		mouseIn = entered
		if entered == false {
			movingSettlementVisible = false
			movingRoadVisible = true
		}
	})
	//////////////////////////////////////////////////////////////////

	drawGame := func() {
		if backImg == nil && background != nil {
			backImg, _ = NewGLImageFromImage(background)
		}
		if backImg != nil {
			backImg.DrawAtXY(0, 0)

			for _, p := range g.GetPlayers() {
				for _, r := range p.GetBuiltRoads() {
					x, y := edgeToScreen(r.Position)
					img := roadImage(r.Position, p.Color)
					img.DrawAtXY(x-img.Width/2, y-img.Height/2)
				}
				for _, s := range p.GetBuiltSettlements() {
					x, y := cornerToScreen(s.Position)
					img := settlementImage(p.Color)
					img.DrawAtXY(x-img.Width/2, y-(5*img.Height/8))
				}
				for _, c := range p.GetBuiltCities() {
					x, y := cornerToScreen(c.Position)
					img := cityImage(p.Color)
					img.DrawAtXY(x-img.Width/2, y-(5*img.Height/8))
				}
			}

			if state == buildingSettlement && movingSettlementVisible && mouseIn {
				color := [4]float32{1, 1, 1, 1}
				x, y := cornerToScreen(movingSettlementCorner)
				if !movingSettlementVisible || !g.CanBuildSettlementAt(movingSettlementCorner) {
					color = [4]float32{0.7, 0.7, 0.7, 0.7}
					x, y = cam.screenToGame(mouseX, mouseY)
				}
				img := settlementImage(g.GetCurrentPlayer().Color)
				// TODO duplicate code:
				img.DrawColoredAtXY(x-img.Width/2, y-(5*img.Height/8), color)
			}
			if state == buildingRoad && movingRoadVisible && mouseIn {
				color := [4]float32{1, 1, 1, 1}
				x, y := edgeToScreen(movingRoadEdge)
				if !(!movingRoadVisible || !g.CanBuildRoadAt(movingRoadEdge)) {
					img := roadImage(movingRoadEdge, g.GetCurrentPlayer().Color)
					// TODO duplicate code:
					img.DrawColoredAtXY(x-img.Width/2, y-(5*img.Height/8), color)
				}
			}

			x, y, w, h := tileToScreen(g.Robber.Position)
			robber := glImages["robber"]
			robber.DrawAtXY(x+(w-robber.Width)/2, y+(h-robber.Height)/2)
		}
	}

	buildMenu := &menu{color{0.5, 0.4, 0.8, 0.9}, rect{0, 500, 800, 250}}

	showCursor := 0
	start := time.Now()
	frames := 0

	window.SetSize(windowW, windowH)

	for !window.ShouldClose() {
		glfw.PollEvents()

		gl.MatrixMode(gl.PROJECTION)
		gl.LoadIdentity()
		const controlsHeight = 0 // TODO reserve are for stats and menus
		gameW, gameH := 7.0*200, 7.0*tileYOffset+tileSlopeHeight+controlsHeight
		gameRatio := gameW / gameH
		windowRatio := float64(windowW) / float64(windowH)
		var left, right, bottom, top float64
		if windowRatio > gameRatio {
			// window is wider than game => borders left and right
			border := (windowRatio*gameH - gameW) / 2
			left, right = -border, border+gameW
			bottom, top = gameH, 0
		} else {
			// window is higher than game => borders on top and bottom
			border := (gameW/windowRatio - gameH) / 2
			left, right = 0, gameW
			bottom, top = gameH+border, -border
		}
		gl.Ortho(left, right, bottom, top, -1, 1)
		cam.Left, cam.Right, cam.Bottom, cam.Top = left, right, bottom, top
		gl.ClearColor(0, 0, 1, 1)
		gl.Clear(gl.COLOR_BUFFER_BIT)

		drawGame()

		lines = make([]string, g.PlayerCount*6)
		for i, player := range g.GetPlayers() {
			lines[i*6+0] = fmt.Sprintf("player %v has %v ore", i+1, player.Resources[game.Ore])
			lines[i*6+1] = fmt.Sprintf("player %v has %v grain", i+1, player.Resources[game.Grain])
			lines[i*6+2] = fmt.Sprintf("player %v has %v lumber", i+1, player.Resources[game.Lumber])
			lines[i*6+3] = fmt.Sprintf("player %v has %v wool", i+1, player.Resources[game.Wool])
			lines[i*6+4] = fmt.Sprintf("player %v has %v brick", i+1, player.Resources[game.Brick])
		}

		if len(lines) > 0 {
			stash.BeginDraw()
			const fontSize = 35
			const cursorText = "" //"_"
			cursor := ""
			if showCursor > 60 {
				cursor = cursorText
			}
			for i, line := range lines {
				output := line
				if i == len(lines)-1 {
					output += cursor
				}
				font.Write(output, 0, float64(i+1)*fontSize)
			}
			if len(lines) == 0 {
				font.Write(cursor, 0, fontSize)
			}
			stash.EndDraw()
		}

		buildMenu.draw()

		window.SwapBuffers()

		showCursor = (showCursor + 1) % 120
		frames++
		if time.Now().Sub(start).Seconds() >= 1.0 {
			fmt.Println(frames, "fps")
			frames = 0
			start = time.Now()
		}
	}
}