import tkinter as tk
import random
import os
import platform
# --- Sound function ---
def play_background_sound():
try:
if platform.system() == "Windows":
import winsound
winsound.PlaySound("SystemExit", winsound.SND_ALIAS | winsound.SND_ASYNC | winsound.SND_LOOP)
else:
os.system("afplay /System/Library/Sounds/Hero.aiff &")
except Exception:
pass
# --- Game class ---
class TableTennisGame:
def __init__(self, root):
self.root = root
self.root.title("Virtual Table Tennis")
self.root.resizable(False, False)
self.canvas = tk.Canvas(root, width=800, height=400, bg="green")
self.canvas.pack()
# Ball
self.ball = self.canvas.create_oval(390, 190, 410, 210, fill="white")
self.ball_dx = 3
self.ball_dy = 3
# Player racket
self.player_racket = self.draw_racket(30, 150)
# Opponent racket
self.opponent_racket = self.draw_racket(760, 150)
# Scores
self.player_score = 0
self.opponent_score = 0
self.score_text = self.canvas.create_text(400, 20, text="Player: 0 Opponent: 0",
font=("Arial", 16), fill="white")
# Bind controls
self.root.bind("<Up>", lambda e: self.move_racket(self.player_racket, -20))
self.root.bind("<Down>", lambda e: self.move_racket(self.player_racket, 20))
self.update_game()
def draw_racket(self, x, y):
handle = self.canvas.create_rectangle(x, y+40, x+10, y+100, fill="brown")
head = self.canvas.create_oval(x-20, y-20, x+30, y+30, fill="red")
return (handle, head)
def move_racket(self, racket, dy):
for part in racket:
self.canvas.move(part, 0, dy)
def get_racket_coords(self, racket):
return self.canvas.coords(racket[1])
def update_score(self):
self.canvas.itemconfig(self.score_text,
text=f"Player: {self.player_score} Opponent: {self.opponent_score}")
def update_game(self):
self.canvas.move(self.ball, self.ball_dx, self.ball_dy)
bx1, by1, bx2, by2 = self.canvas.coords(self.ball)
# Bounce top/bottom
if by1 <= 0 or by2 >= 400:
self.ball_dy *= -1
# Player collision
px1, py1, px2, py2 = self.get_racket_coords(self.player_racket)
if bx1 <= px2 and by2 >= py1 and by1 <= py2:
self.ball_dx = abs(self.ball_dx)
# Opponent AI
ox1, oy1, ox2, oy2 = self.get_racket_coords(self.opponent_racket)
racket_center = (oy1 + oy2) / 2
ball_center = (by1 + by2) / 2
if racket_center < ball_center:
self.move_racket(self.opponent_racket, 5)
else:
self.move_racket(self.opponent_racket, -5)
# Opponent collision
if bx2 >= ox1 and by2 >= oy1 and by1 <= oy2:
self.ball_dx = -abs(self.ball_dx)
# Scoring
if bx1 <= 0: # Opponent scores
self.opponent_score += 1
self.update_score()
self.reset_ball()
elif bx2 >= 800: # Player scores
self.player_score += 1
self.update_score()
self.reset_ball()
self.root.after(20, self.update_game)
def reset_ball(self):
self.canvas.coords(self.ball, 390, 190, 410, 210)
self.ball_dx = random.choice([-3, 3])
self.ball_dy = random.choice([-3, 3])
# --- Run game ---
if __name__ == "__main__":
play_background_sound()
root = tk.Tk()
game = TableTennisGame(root)
root.mainloop()