summaryrefslogtreecommitdiffstats
path: root/pongo.go
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2024-08-25 20:41:15 -0700
committerRose Hogenson <rosehogenson@posteo.net>2024-08-25 20:41:15 -0700
commit4860f772af83e3bf8557bb0e3b1ebb44d2298537 (patch)
treed1906b6523ee1f6f3a1d9c0b5684e416074aa07f /pongo.go
parentFix jitter in the computer movement. (diff)
downloadpongo-4860f772af83e3bf8557bb0e3b1ebb44d2298537.tar.zst
Use GPU rendering and fix FPS limiter.
Diffstat (limited to 'pongo.go')
-rw-r--r--pongo.go145
1 files changed, 76 insertions, 69 deletions
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))
}
}