From ca2d07272a6eda71a46809dd5a03dee5f377b45b Mon Sep 17 00:00:00 2001 From: Frank <123@emial.com> Date: Thu, 18 Jun 2026 10:57:08 +0800 Subject: [PATCH] add the menu of two mode and the timer --- main.py | 148 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 113 insertions(+), 35 deletions(-) diff --git a/main.py b/main.py index 717df58..01f3168 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,21 @@ import pgzrun import random +import time + +# 窗口参数 +WIDTH = 1920 +HEIGHT = 1080 +TITLE = "Ping_Pang" + +# 计时变量 +start_time = time.perf_counter() +elapsed_time = 0 +TIME_LIMIT = 60 # 分数模式限时60秒 + +# 游戏状态:menu / playing / gameover +game_state = "menu" +# mode 1=Score Mode(1分钟限时) 2=Game Over Mode +game_mode = 1 #分数 scorep1 = 0 @@ -8,29 +24,24 @@ scorep2 = 0 hit_paddle1 = False hit_paddle2 = False -#随机数生成 +#随机方块坐标 random_intX = random.randint(235, 1685) random_intY = random.randint(235, 845) - +# 背景音乐 music.play('bgm') -# 窗口参数 -WIDTH = 1920 -HEIGHT = 1080 -TITLE = "Ping_Pang" # 左右球拍 paddle1 = Actor("1") -paddle1.x = 80 +paddle1.x = 10 paddle1.y = HEIGHT / 2 paddle_speed = 8 paddle2 = Actor("2") -paddle2.x = WIDTH - 80 +paddle2.x = WIDTH - 10 paddle2.y = HEIGHT / 2 - -#box生成 +# 障碍方块 tbox = Actor("t_box") tbox.x = random_intX tbox.y = HEIGHT / 2 @@ -41,8 +52,6 @@ ball.pos = (WIDTH//2, HEIGHT//2) ball_speed_x = 7 ball_speed_y = 7 -# 游戏状态: playing / gameover -game_state = "playing" lose_text = "" # 球拍上下限位 @@ -53,29 +62,67 @@ bottom = HEIGHT - half_h bg = Actor("bg") def draw(): - global scorep1, scorep2 + global elapsed_time screen.clear() bg.draw() + + # 开局选择菜单界面 + if game_state == "menu": + screen.draw.text("PING PONG GAME", center=(WIDTH//2, 200), fontsize=90, color="white") + screen.draw.text("Please select game mode", center=(WIDTH//2, 320), fontsize=45, color="yellow") + screen.draw.text("Press D - Score Mode (1 minute time limit)", center=(WIDTH//2, 420), fontsize=40, color="white") + screen.draw.text("Ball out of bounds → add score, ball reset to center", center=(WIDTH//2, 470), fontsize=28, color="#cccccc") + screen.draw.text("Press F - Game Over Mode", center=(WIDTH//2, 570), fontsize=40, color="white") + screen.draw.text("Ball out of bounds → opponent wins, game end", center=(WIDTH//2, 620), fontsize=28, color="#cccccc") + return + + # 游戏进行画面 paddle1.draw() paddle2.draw() ball.draw() tbox.draw() - #分数 - screen.draw.text('Score_p1: ' + str(scorep1), (15,10), color=(255,255,255), fontsize=30) - screen.draw.text('Score_p2: ' + str(scorep2), (1750,10), color=(255,255,255), fontsize=30) + # 左右分数 + screen.draw.text(f'Player 1 Score: {scorep1}', (15,10), color=(255,255,255), fontsize=30) + screen.draw.text(f'Player 2 Score: {scorep2}', (1700,10), color=(255,255,255), fontsize=30) + + # 顶部居中计时,区分限时模式显示剩余时间 + if game_mode == 1: + remain = TIME_LIMIT - elapsed_time + if remain < 0: + remain = 0 + screen.draw.text(f"Time Left: {remain:.1f} s", center=(WIDTH//2, 12), color=(255,255,255), fontsize=32) + else: + screen.draw.text(f"Time: {elapsed_time:.2f} s", center=(WIDTH//2, 12), color=(255,255,255), fontsize=32) # 游戏结束提示 if game_state == "gameover": screen.draw.text(lose_text, center=(WIDTH//2, HEIGHT//2), fontsize=80, color="red") - screen.draw.text("click space to restar", center=(WIDTH//2, HEIGHT//2+80), fontsize=40, color="white") + screen.draw.text("Press SPACE to restart", center=(WIDTH//2, HEIGHT//2+80), fontsize=40, color="white") def update(): global ball_speed_x, ball_speed_y, game_state, lose_text global scorep1, scorep2, hit_paddle1, hit_paddle2 - global random_intX, random_intY + global random_intX, random_intY, elapsed_time, start_time + + # 菜单界面不运行游戏逻辑 + if game_state == "menu": + return + + # 游戏进行中刷新计时 + if game_state == "playing": + elapsed_time = time.perf_counter() - start_time + # 分数模式计时到60秒结束游戏 + if game_mode == 1 and elapsed_time >= TIME_LIMIT: + game_state = "gameover" + if scorep1 > scorep2: + lose_text = "Player 1 Win!" + elif scorep2 > scorep1: + lose_text = "Player 2 Win!" + else: + lose_text = "Draw!" + sounds.zhanbai.play() - # 每一帧重置碰撞标记,保证一次碰撞只加一次分 hit_paddle1 = False hit_paddle2 = False @@ -102,60 +149,91 @@ def update(): ball_speed_y *= -1 sounds.bump.play() - # 左球拍接住加分 + # 左球拍碰撞加分 if ball.colliderect(paddle1) and not hit_paddle1: ball_speed_x *= -1 sounds.bump.play() scorep1 += 1 hit_paddle1 = True - # 右球拍接住加分 + # 右球拍碰撞加分 if ball.colliderect(paddle2) and not hit_paddle2: ball_speed_x *= -1 sounds.bump.play() scorep2 += 1 hit_paddle2 = True - #方块实现 + # 撞击方块逻辑 if ball.colliderect(tbox): sounds.box_co.play() - # 判断撞方块左侧/右侧:翻转X速度 if ball.centerx < tbox.x: ball_speed_x = -abs(ball_speed_x) - 1 else: ball_speed_x = abs(ball_speed_x) + 1 - # 判断撞方块上侧/下侧:翻转Y速度 if ball.centery < tbox.y: ball_speed_y = -abs(ball_speed_y) else: ball_speed_y = abs(ball_speed_y) - # 重新生成方块坐标 random_intX = random.randint(235, 1685) random_intY = random.randint(235, 845) tbox.x = random_intX tbox.y = random_intY - # 出左右边界游戏结束,这里不再加分 + # 球出界逻辑,区分两种模式 if ball.left <= 0: - game_state = "gameover" - lose_text = "player 2 win!" - sounds.zhanbai.play() - if ball.right >= WIDTH: - game_state = "gameover" - lose_text = "player 1 win!" - sounds.zhanbai.play() + if game_mode == 1: + # 计分模式:仅加分,球回中心继续 + scorep2 += 1 + ball.pos = (WIDTH//2, HEIGHT//2) + ball_speed_x = 7 + ball_speed_y = 7 + else: + # 出局即结束模式 + game_state = "gameover" + lose_text = "Player 2 Win!" + sounds.zhanbai.play() + + if ball.right >= WIDTH: + if game_mode == 1: + scorep1 += 1 + ball.pos = (WIDTH//2, HEIGHT//2) + ball_speed_x = 7 + ball_speed_y = 7 + else: + game_state = "gameover" + lose_text = "Player 1 Win!" + sounds.zhanbai.play() -# 空格重新开局 def on_key_down(key): global game_state, ball_speed_x, ball_speed_y, scorep1, scorep2 + global start_time, elapsed_time, game_mode + + # 菜单界面按 D / F 选择模式 + if game_state == "menu": + if key == keys.D: + game_mode = 1 + game_state = "playing" + start_time = time.perf_counter() + elapsed_time = 0 + elif key == keys.F: + game_mode = 2 + game_state = "playing" + start_time = time.perf_counter() + elapsed_time = 0 + return + + # 游戏结束按空格重启 if key == keys.SPACE and game_state == "gameover": game_state = "playing" ball.pos = (WIDTH//2, HEIGHT//2) ball_speed_x = 7 ball_speed_y = 7 - # 重启清空分数,不需要就注释掉下面两行 scorep1 = 0 scorep2 = 0 + start_time = time.perf_counter() + elapsed_time = 0 pgzrun.go() + +