Introduction
The Pong game is a classic arcade game that simulates table tennis. The objective is to control a paddle and hit a ball back and forth across the screen, preventing the ball from passing your paddle. The game ends when one player fails to hit the ball, and the opponent scores a point. In this tutorial, we will learn how to implement a simple Pong game using the Go programming language, leveraging the github.com/hajimehoshi/ebiten
package for rendering and game mechanics.
Objective
The goal of this project is to create a basic Pong game where two players can control paddles, try to score points by bouncing a ball back and forth, and see the result on the screen. You will learn how to set up a Go project, use external libraries for game development, and manage game logic like collision detection and scoring.
Go Pong Game Code
package main
import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"image/color"
"log"
"math"
)
const (
screenWidth = 640
screenHeight = 480
)
type Game struct {
paddle1Y, paddle2Y float64
paddleSpeed float64
ballX, ballY float64
ballDX, ballDY float64
score1, score2 int
}
func (g *Game) Update() error {
// Handle paddle movement
if ebiten.IsKeyPressed(ebiten.KeyW) {
g.paddle1Y -= g.paddleSpeed
}
if ebiten.IsKeyPressed(ebiten.KeyS) {
g.paddle1Y += g.paddleSpeed
}
if ebiten.IsKeyPressed(ebiten.KeyArrowUp) {
g.paddle2Y -= g.paddleSpeed
}
if ebiten.IsKeyPressed(ebiten.KeyArrowDown) {
g.paddle2Y += g.paddleSpeed
}
// Ball movement
g.ballX += g.ballDX
g.ballY += g.ballDY
// Ball collision with top and bottom
if g.ballY <= 0 || g.ballY >= screenHeight {
g.ballDY = -g.ballDY
}
// Ball collision with paddles
if (g.ballX <= 10 && g.ballY >= g.paddle1Y && g.ballY <= g.paddle1Y+60) || (g.ballX >= screenWidth-20 && g.ballY >= g.paddle2Y && g.ballY <= g.paddle2Y+60) {
g.ballDX = -g.ballDX
}
// Scoring
if g.ballX <= 0 { g.score2++ g.resetBall() } else if g.ballX >= screenWidth {
g.score1++
g.resetBall()
}
return nil
}
func (g *Game) resetBall() {
g.ballX = screenWidth / 2
g.ballY = screenHeight / 2
g.ballDX = -g.ballDX
g.ballDY = 2 * (math.Rand.Float64() - 0.5) * 2
}
func (g *Game) Draw(screen *ebiten.Image) {
screen.Fill(color.Black)
// Draw paddles
ebitenutil.DrawRect(screen, 10, g.paddle1Y, 10, 60, color.White)
ebitenutil.DrawRect(screen, screenWidth-20, g.paddle2Y, 10, 60, color.White)
// Draw ball
ebitenutil.DrawRect(screen, g.ballX, g.ballY, 10, 10, color.White)
// Draw scores
ebitenutil.DebugPrintAt(screen, "Player 1: "+strconv.Itoa(g.score1), 10, 10)
ebitenutil.DebugPrintAt(screen, "Player 2: "+strconv.Itoa(g.score2), screenWidth-120, 10)
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func main() {
g := &Game{
paddleSpeed: 4,
ballX: screenWidth / 2,
ballY: screenHeight / 2,
ballDX: 2,
ballDY: 2,
}
ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("Pong Game in Go")
if err := ebiten.RunGame(g); err != nil {
log.Fatal(err)
}
}
Program Structure and How to Run the Program
This Pong game is structured into different sections to handle game mechanics, rendering, and user inputs:
- Game struct: This holds the variables like paddle positions, ball position, speed, and scores.
- Update method: This handles the main game logic like paddle movement, ball movement, collision detection, and scoring.
- Draw method: This renders the paddles, ball, and score on the screen.
- resetBall method: This resets the ball’s position after a point is scored.
- Main function: This initializes the game and runs the game loop using the Ebiten library.
To run the program:
- Ensure you have Go installed on your system.
- Install the Ebiten library with the command:
go get github.com/hajimehoshi/ebiten/v2
- Create a new Go file and paste the code provided above.
- Run the program with the command:
go run .go
The game will open in a new window where you can use the W/S keys to move the left paddle and the Up/Down Arrow keys to move the right paddle. The ball will bounce back and forth between the paddles, and you will score a point when the ball passes the opponent’s paddle.