예제 #1
0
파일: pong.go 프로젝트: gophercoders/pong
// Render updates the screen, based on the new positions of the bats and the ball.
func render() {
	var fps uint32
	fps = 60
	var delay uint32
	delay = 1000 / fps

	var frameStart uint32
	frameStart = sdl.GetTicks()

	renderer.Clear()
	renderMyBat()
	renderComputersBat()
	renderScore()
	// if the game is over render the gameOver graphic
	if gameOver == true {
		renderGameOver()
	} else {
		// otherwise we need to draw the ball
		renderBall()
	}
	// Show the game window window.
	renderer.Present()

	var frameTime uint32
	frameTime = sdl.GetTicks() - frameStart
	if frameTime < delay {
		sdl.Delay(delay - frameTime)
	}
}
예제 #2
0
func MainLoop(gs *gamestate.GameState, renderer *rendering.WorldRenderer) {
	var frames int
	time := float32(sdl.GetTicks()) / 1000
	window := gs.Window
	running := true

	for running {
		currentTime := float32(sdl.GetTicks()) / 1000
		if currentTime > time+1 {
			gs.Fps = float32(frames)
			frames = 0
			time = currentTime
		}
		frames += 1
		running = Input(gs, renderer)

		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
		gl.Disable(gl.BLEND)

		simulation.Simulate(gs, renderer.ParticleSystem)
		renderer.View = gs.Camera.View()
		renderer.Render(gs.World, &gs.Options, window)

		tw.Draw()
		sdl.GL_SwapWindow(window)

		helpers.UpdateManagers()
	}
}
예제 #3
0
파일: 22timer.go 프로젝트: EvanTheB/SDLGame
func main() {

	start()
	defer window.Destroy()
	defer renderer.Destroy()

	text := loadText("Press enter to reset", sdl.Color{0, 0, 0, 255})
	startTime := sdl.GetTicks()

	quit := false
	for !quit {
		for e := sdl.PollEvent(); e != nil; e = sdl.PollEvent() {
			switch t := e.(type) {
			case *sdl.QuitEvent:
				quit = true
			case *sdl.KeyDownEvent:
				if t.Keysym.Sym == sdl.K_RETURN {
					startTime = sdl.GetTicks()
				}

			}
		}

		renderer.SetDrawColor(0xFF, 0xFF, 0xFF, 0xFF)
		renderer.Clear()
		timeText := loadText(fmt.Sprintf("time: %d", sdl.GetTicks()-startTime), sdl.Color{0, 0, 0, 255})
		renderer.Copy(text, nil, &sdl.Rect{0, 0, 400, 100})
		renderer.Copy(timeText, nil, &sdl.Rect{400, 0, 400, 100})

		renderer.Present()
	}
}
예제 #4
0
파일: main.go 프로젝트: jlippitt/gones
func main() {
	rom, err := LoadROM(os.Args[1])

	if err != nil {
		panic(err)
	}

	frameDelay := 1000 / frameRate

	window := sdl.CreateWindow(
		"Go NES",
		sdl.WINDOWPOS_UNDEFINED,
		sdl.WINDOWPOS_UNDEFINED,
		256,
		240,
		sdl.WINDOW_SHOWN,
	)

	if window == nil {
		panic(sdl.GetError())
	}

	defer window.Destroy()

	controller := NewController()
	ppu := NewPPU(window, NewVRAM(rom.Mapper()))
	cpu := NewCPU(NewMMU(rom.Mapper(), ppu, controller), ppu)

	ticksPerFrame := uint32(341 * 262)

	for {
		expectedTicks := sdl.GetTicks() + frameDelay

		for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch event := event.(type) {
			case *sdl.KeyDownEvent:
				controller.SetKeyState(event.Keysym.Sym, true)
			case *sdl.KeyUpEvent:
				controller.SetKeyState(event.Keysym.Sym, false)
			case *sdl.QuitEvent:
				return
			}
		}

		ppuTicks := uint32(0)

		for ppuTicks < ticksPerFrame {
			ppuTicks += ppu.Tick(cpu.Tick())
		}

		actualTicks := sdl.GetTicks()

		if actualTicks < expectedTicks {
			sdl.Delay(expectedTicks - actualTicks)
		}
	}
}
예제 #5
0
파일: game.go 프로젝트: doddo/gfx
func (g *Game) tick() {
	//var ticks uint32
	g.defaultSleep = 300 // this param will control the speed somehow TODO Fix this

	sdl.Delay(1)

	if sdl.GetTicks()%g.defaultSleep == 0 {
		g.heartbeat(sdl.GetTicks())
	}
}
예제 #6
0
// DelayToNextFrame waits until it's time to do the next event/render loop
func (g *GameManager) DelayToNextFrame() {
	curTime := sdl.GetTicks()

	if g.prevFrameTime == 0 {
		if curTime >= g.FrameDelay {
			g.prevFrameTime = curTime - g.FrameDelay
		}
	}

	diff := curTime - g.prevFrameTime

	if g.FrameDelay > diff {
		frameDelayUnder := g.FrameDelay - diff
		// we have not yet exceeded one frame, so we need to sleep
		//fmt.Printf("Under: %d %d %d %d\n", curTime, g.prevFrameTime, diff, frameDelayUnder)
		sdl.Delay(frameDelayUnder)
	} else {
		//frameDelayOver := diff - g.FrameDelay
		//fmt.Printf("Over: %d %d %d %d\n", curTime, g.prevFrameTime, diff, frameDelayOver)
		// we have exceeded one frame, so no sleep
		// TODO sleep less in the future to make up for it?
	}

	g.prevFrameTime = curTime
}
예제 #7
0
// GetTickCount returns the amount of time that has passed since the toolbox
// was initialised.
//
// The toolbox counts time in 'ticks'. One 'tick' is 1/1000th of a second.
// Time starts when Initialise() is called. The number for ticks always
// increases. The number of ticks cannot be reset, and time does cannot
// run backwards.
//
// If the function succeeds then a variable of type int64 will be returned
// back to the calling function. It is the programmers responsibility to
// store this in a variable of type int64.
// GetTickCount returns an int64 type, not an int because the maximum number
// of ticks is to large to store in an int.
//
// GetTickCount will panic if:
//
// 1. The toolbox has not been initialised.
func GetTickCount() int64 {
	if !initialised {
		// this stops execution here, so ne need for an else after the if
		panic(notInitialisedMessage)
	}

	var ticks uint32
	ticks = sdl.GetTicks()
	return int64(ticks)
}
예제 #8
0
파일: loader.go 프로젝트: yukiisbored/Kaori
func main() {
	// Run the game on main thread only.
	// This is important because SDL will freeze / crash
	// if an action is running outside the main thread
	runtime.LockOSThread()

	// Show us a welomce message
	log.Println("Welcome to Kaori")

	// Don't forget to say goodbye ;)
	defer log.Println("Goodbye o/")

	// Show information about the runtime
	log.Printf("Compiled with %s for %s %s\n", runtime.Compiler, runtime.GOOS, runtime.GOARCH)

	// Don't forget to clean the game after it's done
	game.Init("Kaori", sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, 800, 600, false)

	// Don't forget to clean the game after it's done
	defer game.Clean()

	for game.Running() {
		// Get the current time to mark a frame start
		frameStart = sdl.GetTicks()

		// Run all of the 'update' functions
		game.HandleEvents()
		game.Update()
		game.Render()

		// Record the time
		frameTime = sdl.GetTicks() - frameStart

		// Check if it's faster than delay time
		if frameTime < DELAY_TIME {
			// If it is faster, delay the game to prevent "speeding" on certain tick event
			sdl.Delay(DELAY_TIME - frameTime)
		}
	}
}
예제 #9
0
// updateState watches for internal state changes
func (ps *PlayState) updateState() {
	curTime := sdl.GetTicks()
	diff := curTime - ps.state.startTime

	switch ps.state.state {
	case stateInterlude:
		var duration uint32
		switch ps.level {
		case 1:
			duration = stateInterludeDurationLevel1
		default:
			duration = stateInterludeDuration
		}
		if diff >= duration {
			ps.setState(stateAction)
		}
	case stateAction:
	}

}
예제 #10
0
func main() {
	var window *sdl.Window
	var renderer *sdl.Renderer
	var event sdl.Event
	var running bool

	window = sdl.CreateWindow(winTitle, sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
		winWidth, winHeight, sdl.WINDOW_SHOWN)
	if window == nil {
		fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", sdl.GetError())
		os.Exit(1)
	}

	renderer = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	if renderer == nil {
		fmt.Fprintf(os.Stderr, "Failed to create renderer: %s\n", sdl.GetError())
		os.Exit(2)
	}

	var peepArray []sdl.Event = make([]sdl.Event, 2)
	peepArray[0] = &sdl.UserEvent{sdl.USEREVENT, sdl.GetTicks(), window.GetID(), 1331, nil, nil}
	peepArray[1] = &sdl.UserEvent{sdl.USEREVENT, sdl.GetTicks(), window.GetID(), 10101, nil, nil}

	running = true
	lastPushTime := sdl.GetTicks()
	for running {
		if lastPushTime+pushTime < sdl.GetTicks() {
			lastPushTime = sdl.GetTicks()
			sdl.PumpEvents()
			numEventsHandled := sdl.PeepEvents(peepArray, sdl.ADDEVENT, sdl.FIRSTEVENT, sdl.LASTEVENT)
			if numEventsHandled < 0 {
				fmt.Printf("PeepEvents error: %s\n", sdl.GetError())
			} else {
				fmt.Printf("Successful push of %d events\n", numEventsHandled)
			}
		}

		for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch t := event.(type) {
			case *sdl.QuitEvent:
				running = false
			case *sdl.MouseMotionEvent:
				fmt.Printf("[%d ms] MouseMotion\ttype:%d\tid:%d\tx:%d\ty:%d\txrel:%d\tyrel:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y, t.XRel, t.YRel)
			case *sdl.MouseButtonEvent:
				fmt.Printf("[%d ms] MouseButton\ttype:%d\tid:%d\tx:%d\ty:%d\tbutton:%d\tstate:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y, t.Button, t.State)
			case *sdl.MouseWheelEvent:
				fmt.Printf("[%d ms] MouseWheel\ttype:%d\tid:%d\tx:%d\ty:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y)
			case *sdl.KeyUpEvent:
				fmt.Printf("[%d ms] Keyboard\ttype:%d\tsym:%c\tmodifiers:%d\tstate:%d\trepeat:%d\n",
					t.Timestamp, t.Type, t.Keysym.Sym, t.Keysym.Mod, t.State, t.Repeat)
			case *sdl.UserEvent:
				fmt.Printf("[%d ms] UserEvent\tcode:%d\n", t.Timestamp, t.Code)
			}
		}
		sdl.Delay(1000 / 30)
	}

	renderer.Destroy()
	window.Destroy()
}
예제 #11
0
func windowLoop(window *sdl.Window) {
	data := &renderData{}

	data.renderSections = true
	data.zoom = -250
	data.nodes = loadTree("cmd/packer/test.priv.oct")
	data.box = genBox()
	defer gl.DeleteLists(data.box, 1)

	buttonDown := false
	t := float64(sdl.GetTicks())
	for {
		ticks := float64(sdl.GetTicks()) * 0.001
		dt := ticks - t
		t = ticks

		for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch t := event.(type) {
			case *sdl.QuitEvent:
				return
			case *sdl.KeyDownEvent:
				switch t.Keysym.Sym {
				case sdl.K_ESCAPE:
					return
				case sdl.K_SPACE:
					data.renderSections = !data.renderSections
				case sdl.K_PLUS:
					data.minNodeSize += 1.0
				case sdl.K_MINUS:
					data.minNodeSize -= 1.0
				}
			case *sdl.MouseButtonEvent:
				if t.State == 1 {
					buttonDown = true
				} else {
					buttonDown = false
				}
			case *sdl.MouseMotionEvent:
				if buttonDown {
					data.xrot += dt * float64(t.YRel) * rotSpeed
					data.yrot += dt * float64(t.XRel) * rotSpeed
				}
			case *sdl.MouseWheelEvent:
				data.zoom += dt * float64(t.Y) * rotSpeed
			}
		}

		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

		renderTree(data, &data.nodes[0], point3d{0, 0, 0}, 100)

		gl.Disable(gl.DEPTH_TEST)
		drawAxis(data)
		gl.Enable(gl.DEPTH_TEST)

		sdl.GL_SwapWindow(window)

		if glErr := gl.GetError(); glErr != gl.NO_ERROR {
			panic(fmt.Errorf("GL error: %x", glErr))
		}
	}
}
예제 #12
0
func (this *WorldRenderer) render(ww *gamestate.World, options *settings.BoolOptions, viewport Viewport, recursion int, srcPortal *gamestate.Portal) {

	this.Framebuffer[recursion].Bind()
	defer this.Framebuffer[recursion].Unbind()

	gl.Clear(gl.DEPTH_BUFFER_BIT)

	camera := gamestate.NewCameraFromMat4(this.View)
	Rot2D := camera.Rotation2D()

	gl.CullFace(gl.BACK)

	time := float64(sdl.GetTicks()) / 1000

	if options.Wireframe {
		gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE)
	} else {
		gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
	}

	if options.Skybox {
		gl.Disable(gl.DEPTH_TEST)
		this.SkyboxRenderer.Render(this.Skybox, this.Proj, this.View, this.ClippingPlane_ws, nil)
		gl.Enable(gl.DEPTH_TEST)
	}

	gl.Enable(gl.CULL_FACE)

	if recursion != 0 {
		gl.Enable(gl.CLIP_DISTANCE0)
		defer gl.Disable(gl.CLIP_DISTANCE0)
	}

	for _, entity := range ww.ExampleObjects {
		this.MeshRenderer.Render(entity, this.Proj, this.View, this.ClippingPlane_ws, nil)
	}

	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

	gl.Disable(gl.CULL_FACE)

	if options.WorldRender {
		this.HeightMapRenderer.Render(ww.HeightMap, this.Proj, this.View, this.ClippingPlane_ws, nil)
	}
	PlayerPos := ww.Player.Position()
	ww.Water.Height = PlayerPos[2] - 15
	if options.WaterRender {
		this.WaterRendererA.Render(ww.Water, this.Proj, this.View, this.ClippingPlane_ws, WaterRenderUniforms{time, PlayerPos})
	}
	if options.WaterNormals {
		this.WaterRendererB.Render(ww.Water, this.Proj, this.View, this.ClippingPlane_ws, WaterRenderUniforms{time, PlayerPos})
	}

	gl.Disable(gl.CULL_FACE)

	gl.Disable(gl.BLEND)
	if options.TreeRender {
		this.TreeRenderer.Render(ww.Trees, this.Proj, this.View, this.ClippingPlane_ws, Rot2D)
	}

	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE)
	if options.ParticleRender {
		this.ParticleSystem.Render(this.Proj, this.View, this.ClippingPlane_ws)
	}

	gl.Disable(gl.BLEND)

	boxVertices := (*gamestate.TriangleMesh)(gamestate.QuadMesh()).MakeBoxVertices()

	pv := this.Proj.Mul4(this.View)

	// calculating nearest portal
	pos4f := this.View.Inv().Mul4x1(mgl.Vec4{0, 0, 0, 1})
	nearestPortal := ww.NearestPortal(pos4f)

	// draw  all portals except the nearest and the portal that we are looking throug
	for _, portal := range ww.Portals {
		// do not draw the nearest portal or the portal behind the source portal if available
		if (nearestPortal != portal) && (srcPortal == nil || srcPortal.Target != portal) {
			gl.Enable(gl.DEPTH_CLAMP)
			additionalUniforms := map[string]int{"Image": 7}
			this.PortalRenderer.Render(portal, this.Proj, this.View, this.ClippingPlane_ws, additionalUniforms)
		}
	}

	gl.Disable(gl.BLEND)
	gl.Disable(gl.CULL_FACE)

	if options.DebugLines {

		if options.DepthTestDebugLines {
			gl.Disable(gl.DEPTH_TEST)
		}
		this.DebugRenderer.Render(this.Proj, this.View)
		gl.Enable(gl.DEPTH_TEST)
	}

	// draw
	if recursion < this.MaxRecursion {
		portal := nearestPortal
		pos := portal.Position
		rotation := portal.Orientation.Mat4()
		Model := mgl.Translate3D(pos[0], pos[1], pos[2]).Mul4(rotation)

		pvm := pv.Mul4(Model)
		meshMin := mgl.Vec4{math.MaxFloat32, math.MaxFloat32, math.MaxFloat32, math.MaxFloat32}
		meshMax := mgl.Vec4{-math.MaxFloat32, -math.MaxFloat32, -math.MaxFloat32, -math.MaxFloat32}
		for _, v := range boxVertices {
			v = pvm.Mul4x1(v)
			v = v.Mul(1 / v[3])
			meshMin = gamestate.Min(meshMin, v)
			meshMax = gamestate.Max(meshMax, v)
		}

		// at least partially visible
		if -1 < meshMax[0] && meshMin[0] < 1 &&
			-1 < meshMax[1] && meshMin[1] < 1 &&
			-1 < meshMax[2] && meshMin[2] < 1 {

			p1x, p1y := viewport.ToPixel(meshMin.Vec2())
			p2x, p2y := viewport.ToPixel(meshMax.Vec2())
			pw, ph := p2x-p1x, p2y-p1y

			// do scissoring only when all vertices are in front of the camera
			scissor := meshMax[2] < 1
			scissor = scissor && (p1x != 0 || p1y != 0 || pw != viewport.W-1 || ph != viewport.H-1)

			if scissor {
				gl.Enable(gl.SCISSOR_TEST)
				gl.Scissor(p1x, p1y, pw, ph)
			}

			// omit rendering when portal is not in frustum at all
			// calculation View matrix that shows the target portal from the same angle as view shows the source portal

			//pos2 := portal.Target.Position
			Model2 := portal.Target.Model()
			// model matrix, so that portal 1 in camera 1 looks identical to portal 2 in camera
			oldView := this.View
			this.View = this.View.Mul4(Model).Mul4(Model2.Inv())

			normal_os := portal.Target.Normal
			normal_ws := Model.Mul4x1(normal_os)
			view_dir := helpers.HomogenDiff(portal.Position, camera.Position)
			sign := view_dir.Dot(normal_ws)

			oldClippingPlane := this.ClippingPlane_ws
			this.ClippingPlane_ws = portal.Target.ClippingPlane(sign > 0)

			this.render(ww, options, viewport, recursion+1, nearestPortal)
			this.ClippingPlane_ws = oldClippingPlane
			this.View = oldView

			gl.ActiveTexture(gl.TEXTURE0)
			this.Framebuffer[recursion+1].RenderTexture.Bind(gl.TEXTURE_RECTANGLE)

			if scissor {
				//gl.Scissor(0, 0, w, h)
				gl.Disable(gl.SCISSOR_TEST)
			}
			this.Framebuffer[recursion].Bind()
			gl.Enable(gl.DEPTH_CLAMP)
			additionalUniforms := map[string]int{"Image": 0}
			this.PortalRenderer.Render(nearestPortal, this.Proj, this.View, this.ClippingPlane_ws, additionalUniforms)
		}
	}
}
예제 #13
0
파일: window.go 프로젝트: FSX/nanovg
func StartGame() {
	window := initSDL()
	context := initGL(window)
	nvg := initNanovg()

	ww, wh := window.GetSize()
	gw := ww / 5
	gh := wh / 5

	life := NewLife(gw, gh)

	refgrid := make([][]bool, gh)
	for i := range refgrid {
		refgrid[i] = make([]bool, gw)
	}

	// Run the game at 15fps. This gives us about 66ms to calculate
	// and render everything. 30ms is not possible yet.
	minms := uint32(1000 / 15)
	running := true

	gl.ClearColor(0.3, 0.3, 0.32, 1.0)
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)

	// Draw all squares first.
	tw, th := float32(life.w), float32(life.h)
	for y := float32(0); y < th; y++ {
		for x := float32(0); x < tw; x++ {
			nvg.BeginPath()
			nvg.Rect(x*5+1, y*5+1, 3, 3)
			nvg.FillColor(nanovg.RGBA(100, 100, 100, 255))
			nvg.Fill()
			nvg.ClosePath()
		}
	}

	// Loop!
	for running {
		lt := sdl.GetTicks()

		for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch t := event.(type) {
			case *sdl.QuitEvent:
				running = false
			case *sdl.KeyUpEvent:
				if t.Keysym.Sym == sdl.K_ESCAPE {
					running = false
				}
			}
		}

		life.Step()

		ww, wh := window.GetSize()
		gl.Viewport(0, 0, ww, wh)

		nvg.BeginFrame(ww, wh, 1.0)
		drawGrid(life, nvg, refgrid)
		nvg.EndFrame()

		if d := sdl.GetTicks() - lt; d < minms {
			sdl.Delay(minms - d)
		}

		sdl.GL_SwapWindow(window)
	}

	// Cleanup.
	window.Destroy()
	sdl.GL_DeleteContext(context)
	nvg.Close()
	sdl.Quit()
}
예제 #14
0
파일: timer.go 프로젝트: tanema/amore
// GetTime get the current time from the length that the application has been running.
func GetTime() float32 {
	return float32(sdl.GetTicks()) / 1000.0
}
예제 #15
0
// setState sets the current states and does timer management
func (ps *PlayState) setState(state int) {
	ps.state.state = state
	ps.state.startTime = sdl.GetTicks()
}
예제 #16
0
// Get time in seconds.  Time zero is platform specific.
func Now() float64 {
	return float64(sdl.GetTicks()) * 0.001
}
예제 #17
0
파일: PushEvent.go 프로젝트: emlai/go-sdl2
func main() {
	var window *sdl.Window
	var renderer *sdl.Renderer
	var event sdl.Event
	var running bool

	window = sdl.CreateWindow(winTitle, sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
		winWidth, winHeight, sdl.WINDOW_SHOWN)
	if window == nil {
		fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", sdl.GetError())
		os.Exit(1)
	}

	renderer = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	if renderer == nil {
		fmt.Fprintf(os.Stderr, "Failed to create renderer: %s\n", sdl.GetError())
		os.Exit(2)
	}

	running = true
	lastPushTime := sdl.GetTicks()
	for running {

		// Push a UserEvent every second
		if lastPushTime+pushTime < sdl.GetTicks() {
			lastPushTime = sdl.GetTicks()
			pEvent := &sdl.UserEvent{sdl.USEREVENT, sdl.GetTicks(), window.GetID(), 1331, nil, nil}

			retVal := sdl.PushEvent(pEvent) // Here's where the event is actually pushed

			switch retVal {
			case 1:
				fmt.Println("PushEvent returned success")
			case 0:
				fmt.Println("PushEvent returned filtered")
			case -1:
				fmt.Printf("PushEvent returned error: %s\n", sdl.GetError)
			}
		}

		for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch t := event.(type) {
			case *sdl.QuitEvent:
				running = false
			case *sdl.MouseMotionEvent:
				fmt.Printf("[%d ms] MouseMotion\ttype:%d\tid:%d\tx:%d\ty:%d\txrel:%d\tyrel:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y, t.XRel, t.YRel)
			case *sdl.MouseButtonEvent:
				fmt.Printf("[%d ms] MouseButton\ttype:%d\tid:%d\tx:%d\ty:%d\tbutton:%d\tstate:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y, t.Button, t.State)
			case *sdl.MouseWheelEvent:
				fmt.Printf("[%d ms] MouseWheel\ttype:%d\tid:%d\tx:%d\ty:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y)
			case *sdl.KeyUpEvent:
				fmt.Printf("[%d ms] Keyboard\ttype:%d\tsym:%c\tmodifiers:%d\tstate:%d\trepeat:%d\n",
					t.Timestamp, t.Type, t.Keysym.Sym, t.Keysym.Mod, t.State, t.Repeat)
			case *sdl.UserEvent:
				fmt.Printf("[%d ms] UserEvent\tcode:%d\n", t.Timestamp, t.Code)
			}
		}
		sdl.Delay(1000 / 30)
	}

	renderer.Destroy()
	window.Destroy()
}