Pong for everyone

Godot Version

Godot Engine v4.3.stable.

Question

2D Pong game for everyone!!

I cannot add another thing to the showcase… but below a fully working pong game with increasing speed and dificulty and commentary.

  • Create a new Node2D scene
  • Attach a script.
  • Copy code below
  • And have Fun!.

Why am i doing this?.. just to share code and maybe you can learn from it :wink:

My 2 cents!

extends Node2D

# Game Variables
var screen_size
var score_player = 0
var score_computer = 0
var game_over = false
var game_started = false
var ball_speed = 400
var base_ball_speed = 400
var speed_increase = 20 # Speed increase per rebound
var computer_difficulty = 0.7 # Higher = more difficult (max 1.0)
var difficulty_increase = 0.02 # Difficulty increase per rebound
var consecutive_hits = 0
var commentary_label

# Nodes
var player_paddle
var computer_paddle
var ball
var player_score_label
var computer_score_label
var message_label

func _ready():
	randomize()
	screen_size = get_viewport_rect().size
	reset_game_parameters()
	
	# Create player paddle
	player_paddle = ColorRect.new()
	player_paddle.color = Color.GREEN
	player_paddle.size = Vector2(15, 80)
	player_paddle.position = Vector2(30, screen_size.y / 2 - player_paddle.size.y / 2)
	add_child(player_paddle)
	
	# Create computer paddle
	computer_paddle = ColorRect.new()
	computer_paddle.color = Color.RED
	computer_paddle.size = Vector2(15, 80)
	computer_paddle.position = Vector2(screen_size.x - 30 - computer_paddle.size.x, screen_size.y / 2 - computer_paddle.size.y / 2)
	add_child(computer_paddle)
	
	# Create ball
	ball = ColorRect.new()
	ball.color = Color.WHITE
	ball.size = Vector2(15, 15)
	ball.position = Vector2(screen_size.x / 2 - ball.size.x / 2, screen_size.y / 2 - ball.size.y / 2)
	add_child(ball)
	
	# Create score labels
	player_score_label = Label.new()
	player_score_label.position = Vector2(screen_size.x / 4, 20)
	player_score_label.text = "Player: 0"
	add_child(player_score_label)
	
	computer_score_label = Label.new()
	computer_score_label.position = Vector2(3 * screen_size.x / 4, 20)
	computer_score_label.text = "Computer: 0"
	add_child(computer_score_label)
	
	# Create message label
	message_label = Label.new()
	message_label.position = Vector2(screen_size.x / 2 - 100, screen_size.y / 2 - 20)
	message_label.text = "Press SPACE to start"
	add_child(message_label)
	
	# Create commentary label
	commentary_label = Label.new()
	commentary_label.position = Vector2(screen_size.x / 2 - 150, screen_size.y - 40)
	commentary_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
	commentary_label.size = Vector2(300, 30)
	commentary_label.visible = false
	add_child(commentary_label)
	
	# Create a midline
	var midline = Line2D.new()
	midline.width = 2
	midline.default_color = Color(1, 1, 1, 0.3)
	midline.add_point(Vector2(screen_size.x / 2, 0))
	midline.add_point(Vector2(screen_size.x / 2, screen_size.y))
	add_child(midline)
	
	# Setup ball velocity (will be assigned on game start)
	ball.set_meta("velocity", Vector2.ZERO)

func _process(delta):
	if game_over:
		if Input.is_action_just_pressed("ui_select"):  # Restart game
			score_player = 0
			score_computer = 0
			reset_game_parameters()
			update_score_labels()
			game_over = false
			message_label.text = "Press SPACE to start"
			message_label.visible = true
		return
	
	if not game_started:
		if Input.is_action_just_pressed("ui_select"):
			game_started = true
			message_label.visible = false
			reset_ball()
			show_commentary("Game on!")
		return
		
	# Player paddle movement
	var player_movement = 0
	if Input.is_action_pressed("ui_down"):
		player_movement = 1
	if Input.is_action_pressed("ui_up"):
		player_movement = -1
	
	player_paddle.position.y += player_movement * 500 * delta
	player_paddle.position.y = clamp(player_paddle.position.y, 0, screen_size.y - player_paddle.size.y)
	
	# Computer AI (follows the ball with slight delay)
	var target_y = ball.position.y + ball.size.y / 2 - computer_paddle.size.y / 2
	
	# Add some difficulty scaling - only move towards ball if it's coming to the computer's side
	var ball_velocity = ball.get_meta("velocity")
	if ball_velocity.x > 0:
		# Add some intentional "error" based on difficulty
		var error_margin = (1.0 - computer_difficulty) * 100
		target_y += randf_range(-error_margin, error_margin)
		
		var computer_speed = 400 * computer_difficulty
		if computer_paddle.position.y < target_y:
			computer_paddle.position.y += computer_speed * delta
		elif computer_paddle.position.y > target_y:
			computer_paddle.position.y -= computer_speed * delta
	
	computer_paddle.position.y = clamp(computer_paddle.position.y, 0, screen_size.y - computer_paddle.size.y)
	
	# Ball movement
	var velocity = ball.get_meta("velocity")
	ball.position += velocity * delta
	
	# Ball collision with top and bottom walls
	if ball.position.y <= 0 or ball.position.y + ball.size.y >= screen_size.y:
		velocity.y = -velocity.y
		ball.set_meta("velocity", velocity)
	
	# Ball collision with paddles
	if ball.position.x <= player_paddle.position.x + player_paddle.size.x and \
	   ball.position.y + ball.size.y >= player_paddle.position.y and \
	   ball.position.y <= player_paddle.position.y + player_paddle.size.y and \
	   velocity.x < 0:
		
		# Adjust angle based on where ball hit the paddle
		var hit_pos = (ball.position.y + ball.size.y/2) - player_paddle.position.y
		var normalized_hit_pos = hit_pos / player_paddle.size.y - 0.5  # Range from -0.5 to 0.5
		
		velocity.x = -velocity.x
		velocity.y = normalized_hit_pos * 2 * ball_speed
		
		# Increase consecutive hits
		consecutive_hits += 1
		
		# Increase consecutive hits
		consecutive_hits += 1
		
		# Increase ball speed and computer difficulty
		ball_speed += speed_increase
		computer_difficulty = min(computer_difficulty + difficulty_increase, 1.0)
		
		# Update velocity with new speed
		velocity = velocity.normalized() * ball_speed
		ball.set_meta("velocity", velocity)
		
		# Display current speed and difficulty (for debug)
		update_debug_info()
		
		# Show commentary
		show_computer_hit_commentary()
		
		# Show commentary
		show_player_hit_commentary()
	
	if ball.position.x + ball.size.x >= computer_paddle.position.x and \
	   ball.position.y + ball.size.y >= computer_paddle.position.y and \
	   ball.position.y <= computer_paddle.position.y + computer_paddle.size.y and \
	   velocity.x > 0:
		
		# Adjust angle based on where ball hit the paddle
		var hit_pos = (ball.position.y + ball.size.y/2) - computer_paddle.position.y
		var normalized_hit_pos = hit_pos / computer_paddle.size.y - 0.5  # Range from -0.5 to 0.5
		
		velocity.x = -velocity.x
		velocity.y = normalized_hit_pos * 2 * ball_speed
		
		# Increase ball speed and computer difficulty
		ball_speed += speed_increase
		computer_difficulty = min(computer_difficulty + difficulty_increase, 1.0)
		
		# Update velocity with new speed
		velocity = velocity.normalized() * ball_speed
		ball.set_meta("velocity", velocity)
		
		# Display current speed and difficulty (for debug)
		update_debug_info()
	
	# Ball out of bounds (scoring)
	if ball.position.x < 0:
		score_computer += 1
		update_score_labels()
		consecutive_hits = 0
		show_commentary("Computer scores! That's rough!")
		check_for_game_over()
		reset_ball()
	
	if ball.position.x > screen_size.x:
		score_player += 1
		update_score_labels()
		consecutive_hits = 0
		show_commentary("You scored! Nice one!")
		check_for_game_over()
		reset_ball()

func reset_game_parameters():
	# Reset ball speed and computer difficulty to their initial values
	ball_speed = base_ball_speed
	computer_difficulty = 0.7
	consecutive_hits = 0
	update_debug_info()

func reset_ball():
	ball.position = Vector2(screen_size.x / 2 - ball.size.x / 2, screen_size.y / 2 - ball.size.y / 2)
	
	# Randomize direction but ensure it's not too vertical
	var angle = randf_range(-PI/4, PI/4)
	if randf() > 0.5:
		angle += PI
	
	var velocity = Vector2(cos(angle), sin(angle)).normalized() * ball_speed
	ball.set_meta("velocity", velocity)
	
	# Pause briefly
	game_started = false
	message_label.text = "Get ready..."
	message_label.visible = true
	await get_tree().create_timer(1.0).timeout
	game_started = true
	message_label.visible = false

func update_score_labels():
	player_score_label.text = "Player: " + str(score_player)
	computer_score_label.text = "Computer: " + str(score_computer)

func update_debug_info():
	# Optional debug information - you can add a label to your game to display this
	print("Ball Speed: ", ball_speed, " | Computer Difficulty: ", computer_difficulty)

func show_commentary(text):
	commentary_label.text = text
	commentary_label.visible = true
	
	# Auto-hide commentary after a delay
	var timer = get_tree().create_timer(2.0)
	await timer.timeout
	if is_instance_valid(commentary_label):
		commentary_label.visible = false

func show_player_hit_commentary():
	var comments = [
		"Nice hit!",
		"You're on fire!",
		"Keep it going!",
		"Speed increased! Getting spicy!",
		"That was sick!",
		"The AI is sweating now!",
		"BOOM! Another hit!",
		"Computer be like: 'Not fair!'",
		"You're making this look easy!"
	]
	
	if consecutive_hits > 3:
		comments.append("Combo x" + str(consecutive_hits) + "! Impressive!")
		comments.append("This is getting ridiculous!")
		comments.append("Are you a pro or what?!")
	
	if ball_speed > base_ball_speed + 100:
		comments.append("This ball is FLYING now!")
		comments.append("Speed demon activated!")
	
	show_commentary(comments[randi() % comments.size()])

func show_computer_hit_commentary():
	var comments = [
		"Computer returns!",
		"AI's getting good!",
		"The machine fights back!",
		"Denied by the computer!",
		"Computer's not giving up!",
		"Computer: 'Is that all you got?'",
		"Getting faster...",
		"The robot's learning!",
		"Computer's like 'Nope!'"
	]
	
	if consecutive_hits > 3:
		comments.append("Rally streak: " + str(consecutive_hits) + "!")
		comments.append("This rally is epic!")
	
	if computer_difficulty > 0.9:
		comments.append("Computer's almost at max difficulty!")
		comments.append("AI's almost reached its final form!")
	
	show_commentary(comments[randi() % comments.size()])

func check_for_game_over():
	var win_score = 5
	if score_player >= win_score:
		game_over = true
		message_label.text = "You win! Press SPACE to restart"
		message_label.visible = true
		show_commentary("VICTORY! You showed that AI who's boss!")
	elif score_computer >= win_score:
		game_over = true
		message_label.text = "Computer wins! Press SPACE to restart"
		message_label.visible = true
		show_commentary("Game over! The machines win this time...")

1 Like

Make sure to put it in the “Showcase”-category

Somehow i cant do that!.. maybe due to that i already have a showcase open ?

Showcase is strange you have to select a sub-category to post like In Development , Applications , or Games

3 Likes

Found it…