From 4860f772af83e3bf8557bb0e3b1ebb44d2298537 Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Sun, 25 Aug 2024 20:41:15 -0700 Subject: Use GPU rendering and fix FPS limiter. --- pongo.go | 145 +++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 76 insertions(+), 69 deletions(-) (limited to 'pongo.go') diff --git a/pongo.go b/pongo.go index 44f79a2..cb0ebe3 100644 --- a/pongo.go +++ b/pongo.go @@ -118,8 +118,6 @@ func (p *paddle) bounds() *sdl.Rect { var pingWAV []byte func pong() error { - const fps = 60 - if err := sdl.Init(sdl.INIT_AUDIO & sdl.INIT_VIDEO & sdl.INIT_EVENTS); err != nil { return err } @@ -135,11 +133,12 @@ func pong() error { } defer ping.Free() - window, err := sdl.CreateWindow("pongo", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, screenWidth, screenHeight, sdl.WINDOW_SHOWN) + window, renderer, err := sdl.CreateWindowAndRenderer(screenWidth, screenHeight, sdl.WINDOW_OPENGL&sdl.WINDOW_BORDERLESS) if err != nil { return err } defer window.Destroy() + defer renderer.Destroy() upPressed := false downPressed := false @@ -153,7 +152,8 @@ func pong() error { paddle1 := paddle{pos: screenHeight / 2, side: left} paddle2 := paddle{pos: screenHeight / 2, side: right} - frameTargetTime := time.Now().Add(time.Second / fps) + lastFrameTime := time.Now() + accumulator := time.Duration(0) for { for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() { @@ -170,99 +170,106 @@ func pong() error { } } - switch { - case upPressed && paddle1.bounds().Y >= 0: - paddle1.pos -= paddleSpeed - case downPressed && rectBottom(paddle1.bounds()) <= screenHeight: - paddle1.pos += paddleSpeed - } + frameStart := time.Now() + accumulator += frameStart.Sub(lastFrameTime) + lastFrameTime = frameStart - if prediction, ok := ball.predictIntersection(float64(paddle2.bounds().X)); ok { + const simulationSpeed = time.Second / 120 + for ; accumulator >= simulationSpeed; accumulator -= simulationSpeed { switch { - case paddle2.pos <= prediction-paddleSpeed && rectBottom(paddle2.bounds()) <= screenHeight: - paddle2.pos += paddleSpeed - case paddle2.pos >= prediction+paddleSpeed && paddle2.bounds().Y >= 0: - paddle2.pos -= paddleSpeed + case upPressed && paddle1.bounds().Y >= 0: + paddle1.pos -= paddleSpeed + case downPressed && rectBottom(paddle1.bounds()) <= screenHeight: + paddle1.pos += paddleSpeed } - } - ball.pos = ball.pos.add(ball.velocity) - switch { - case ball.bounds().HasIntersection(paddle1.bounds()): - ping.Play(-1, 0) - d := ball.pos.y - paddle1.pos - if d < 0 { - d = -d - } - angle := d / (float64(paddle1.bounds().H)/2 + float64(ball.bounds().H)) * (75 * 2 * math.Pi / 360) - if ball.pos.y < paddle1.pos { - angle = -angle - } - speed := ballSpeed * (1 + 4*d/(float64(paddle1.bounds().H)/2+float64(ball.bounds().H))) - ball.velocity = vector2{speed * math.Cos(angle), speed * math.Sin(angle)} - case ball.bounds().HasIntersection(paddle2.bounds()): - ping.Play(-1, 0) - d := ball.pos.y - paddle2.pos - if d < 0 { - d = -d + if prediction, ok := ball.predictIntersection(float64(paddle2.bounds().X)); ok { + switch { + case paddle2.pos <= prediction-paddleSpeed && rectBottom(paddle2.bounds()) <= screenHeight: + paddle2.pos += paddleSpeed + case paddle2.pos >= prediction+paddleSpeed && paddle2.bounds().Y >= 0: + paddle2.pos -= paddleSpeed + } } - angle := d / (float64(paddle2.bounds().H)/2 + float64(ball.bounds().H)) * (75 * 2 * math.Pi / 360) - if ball.pos.y < paddle2.pos { - angle = -angle + + oldPos := ball.pos + ball.pos = ball.pos.add(ball.velocity) + switch { + case ball.bounds().HasIntersection(paddle1.bounds()): + ping.Play(-1, 0) + d := ball.pos.y - paddle1.pos + if d < 0 { + d = -d + } + angle := d / (float64(paddle1.bounds().H)/2 + float64(ball.bounds().H)) * (75 * 2 * math.Pi / 360) + if ball.pos.y < paddle1.pos { + angle = -angle + } + speed := ballSpeed * (1 + 4*d/(float64(paddle1.bounds().H)/2+float64(ball.bounds().H))) + ball.velocity = vector2{speed * math.Cos(angle), speed * math.Sin(angle)} + ball.pos = oldPos + case ball.bounds().HasIntersection(paddle2.bounds()): + ping.Play(-1, 0) + d := ball.pos.y - paddle2.pos + if d < 0 { + d = -d + } + angle := d / (float64(paddle2.bounds().H)/2 + float64(ball.bounds().H)) * (75 * 2 * math.Pi / 360) + if ball.pos.y < paddle2.pos { + angle = -angle + } + angle += math.Pi + speed := ballSpeed * (1 + 4*d/(float64(paddle2.bounds().H)/2+float64(ball.bounds().H))) + ball.velocity = vector2{speed * math.Cos(angle), speed * math.Sin(angle)} + ball.pos = oldPos + case rectRight(ball.bounds()) <= 0: + aiScore++ + ball.reset(right) + case ball.bounds().X >= screenWidth: + playerScore++ + ball.reset(left) + case ball.bounds().Y <= 0 || rectBottom(ball.bounds()) >= screenHeight: + ping.Play(-1, 0) + ball.pos = oldPos + ball.velocity.y = -ball.velocity.y } - angle += math.Pi - speed := ballSpeed * (1 + 4*d/(float64(paddle2.bounds().H)/2+float64(ball.bounds().H))) - ball.velocity = vector2{speed * math.Cos(angle), speed * math.Sin(angle)} - case rectRight(ball.bounds()) <= paddle1.bounds().X: - aiScore++ - ball.reset(right) - case ball.bounds().X >= paddle2.bounds().X: - playerScore++ - ball.reset(left) - case ball.bounds().Y <= 0 || rectBottom(ball.bounds()) >= screenHeight: - ping.Play(-1, 0) - ball.velocity.y = -ball.velocity.y } - surface, err := window.GetSurface() - if err != nil { + if err := renderer.SetDrawColor(0, 0, 0, 255); err != nil { fmt.Fprintln(os.Stderr, err) - continue } - - gray := sdl.MapRGB(surface.Format, 130, 130, 130) - offWhite := sdl.MapRGB(surface.Format, 245, 245, 245) - - if err := surface.FillRect(nil, 0); err != nil { + if err := renderer.FillRect(nil); err != nil { fmt.Fprintln(os.Stderr, err) } - if err := surface.FillRect(&sdl.Rect{X: screenWidth / 2, Y: 0, W: 1, H: screenHeight}, gray); err != nil { + if err := renderer.SetDrawColor(130, 130, 130, 255); err != nil { fmt.Fprintln(os.Stderr, err) } - - if err := surface.FillRect(paddle1.bounds(), offWhite); err != nil { + if err := renderer.FillRect(&sdl.Rect{X: screenWidth / 2, Y: 0, W: 1, H: screenHeight}); err != nil { fmt.Fprintln(os.Stderr, err) } - if err := surface.FillRect(paddle2.bounds(), offWhite); err != nil { + + if err := renderer.SetDrawColor(245, 245, 245, 255); err != nil { fmt.Fprintln(os.Stderr, err) } - if err := surface.FillRect(ball.bounds(), offWhite); err != nil { + if err := renderer.FillRect(paddle1.bounds()); err != nil { fmt.Fprintln(os.Stderr, err) } - - if err := numbers.Draw(surface, playerScore, paddle1.bounds().X+20, 30); err != nil { + if err := renderer.FillRect(paddle2.bounds()); err != nil { fmt.Fprintln(os.Stderr, err) } - if err := numbers.Draw(surface, aiScore, paddle2.bounds().X-500, 30); err != nil { + if err := renderer.FillRect(ball.bounds()); err != nil { fmt.Fprintln(os.Stderr, err) } - if err := window.UpdateSurface(); err != nil { + if err := numbers.Draw(renderer, playerScore, paddle1.bounds().X+20, 30); err != nil { + fmt.Fprintln(os.Stderr, err) + } + if err := numbers.Draw(renderer, aiScore, paddle2.bounds().X-500, 30); err != nil { fmt.Fprintln(os.Stderr, err) } - time.Sleep(time.Until(frameTargetTime)) - frameTargetTime = frameTargetTime.Add(time.Second / fps) + renderer.Present() + time.Sleep(time.Second/60 - time.Since(frameStart)) } } -- cgit v1.3.1