add the menu of two mode and the timer
This commit is contained in:
148
main.py
148
main.py
@@ -1,5 +1,21 @@
|
|||||||
import pgzrun
|
import pgzrun
|
||||||
import random
|
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
|
scorep1 = 0
|
||||||
@@ -8,29 +24,24 @@ scorep2 = 0
|
|||||||
hit_paddle1 = False
|
hit_paddle1 = False
|
||||||
hit_paddle2 = False
|
hit_paddle2 = False
|
||||||
|
|
||||||
#随机数生成
|
#随机方块坐标
|
||||||
random_intX = random.randint(235, 1685)
|
random_intX = random.randint(235, 1685)
|
||||||
random_intY = random.randint(235, 845)
|
random_intY = random.randint(235, 845)
|
||||||
|
|
||||||
|
# 背景音乐
|
||||||
music.play('bgm')
|
music.play('bgm')
|
||||||
# 窗口参数
|
|
||||||
WIDTH = 1920
|
|
||||||
HEIGHT = 1080
|
|
||||||
TITLE = "Ping_Pang"
|
|
||||||
|
|
||||||
# 左右球拍
|
# 左右球拍
|
||||||
paddle1 = Actor("1")
|
paddle1 = Actor("1")
|
||||||
paddle1.x = 80
|
paddle1.x = 10
|
||||||
paddle1.y = HEIGHT / 2
|
paddle1.y = HEIGHT / 2
|
||||||
paddle_speed = 8
|
paddle_speed = 8
|
||||||
|
|
||||||
paddle2 = Actor("2")
|
paddle2 = Actor("2")
|
||||||
paddle2.x = WIDTH - 80
|
paddle2.x = WIDTH - 10
|
||||||
paddle2.y = HEIGHT / 2
|
paddle2.y = HEIGHT / 2
|
||||||
|
|
||||||
|
# 障碍方块
|
||||||
#box生成
|
|
||||||
tbox = Actor("t_box")
|
tbox = Actor("t_box")
|
||||||
tbox.x = random_intX
|
tbox.x = random_intX
|
||||||
tbox.y = HEIGHT / 2
|
tbox.y = HEIGHT / 2
|
||||||
@@ -41,8 +52,6 @@ ball.pos = (WIDTH//2, HEIGHT//2)
|
|||||||
ball_speed_x = 7
|
ball_speed_x = 7
|
||||||
ball_speed_y = 7
|
ball_speed_y = 7
|
||||||
|
|
||||||
# 游戏状态: playing / gameover
|
|
||||||
game_state = "playing"
|
|
||||||
lose_text = ""
|
lose_text = ""
|
||||||
|
|
||||||
# 球拍上下限位
|
# 球拍上下限位
|
||||||
@@ -53,29 +62,67 @@ bottom = HEIGHT - half_h
|
|||||||
bg = Actor("bg")
|
bg = Actor("bg")
|
||||||
|
|
||||||
def draw():
|
def draw():
|
||||||
global scorep1, scorep2
|
global elapsed_time
|
||||||
screen.clear()
|
screen.clear()
|
||||||
bg.draw()
|
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()
|
paddle1.draw()
|
||||||
paddle2.draw()
|
paddle2.draw()
|
||||||
ball.draw()
|
ball.draw()
|
||||||
tbox.draw()
|
tbox.draw()
|
||||||
|
|
||||||
#分数
|
# 左右分数
|
||||||
screen.draw.text('Score_p1: ' + str(scorep1), (15,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('Score_p2: ' + str(scorep2), (1750,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":
|
if game_state == "gameover":
|
||||||
screen.draw.text(lose_text, center=(WIDTH//2, HEIGHT//2), fontsize=80, color="red")
|
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():
|
def update():
|
||||||
global ball_speed_x, ball_speed_y, game_state, lose_text
|
global ball_speed_x, ball_speed_y, game_state, lose_text
|
||||||
global scorep1, scorep2, hit_paddle1, hit_paddle2
|
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_paddle1 = False
|
||||||
hit_paddle2 = False
|
hit_paddle2 = False
|
||||||
|
|
||||||
@@ -102,60 +149,91 @@ def update():
|
|||||||
ball_speed_y *= -1
|
ball_speed_y *= -1
|
||||||
sounds.bump.play()
|
sounds.bump.play()
|
||||||
|
|
||||||
# 左球拍接住加分
|
# 左球拍碰撞加分
|
||||||
if ball.colliderect(paddle1) and not hit_paddle1:
|
if ball.colliderect(paddle1) and not hit_paddle1:
|
||||||
ball_speed_x *= -1
|
ball_speed_x *= -1
|
||||||
sounds.bump.play()
|
sounds.bump.play()
|
||||||
scorep1 += 1
|
scorep1 += 1
|
||||||
hit_paddle1 = True
|
hit_paddle1 = True
|
||||||
|
|
||||||
# 右球拍接住加分
|
# 右球拍碰撞加分
|
||||||
if ball.colliderect(paddle2) and not hit_paddle2:
|
if ball.colliderect(paddle2) and not hit_paddle2:
|
||||||
ball_speed_x *= -1
|
ball_speed_x *= -1
|
||||||
sounds.bump.play()
|
sounds.bump.play()
|
||||||
scorep2 += 1
|
scorep2 += 1
|
||||||
hit_paddle2 = True
|
hit_paddle2 = True
|
||||||
|
|
||||||
#方块实现
|
# 撞击方块逻辑
|
||||||
if ball.colliderect(tbox):
|
if ball.colliderect(tbox):
|
||||||
sounds.box_co.play()
|
sounds.box_co.play()
|
||||||
# 判断撞方块左侧/右侧:翻转X速度
|
|
||||||
if ball.centerx < tbox.x:
|
if ball.centerx < tbox.x:
|
||||||
ball_speed_x = -abs(ball_speed_x) - 1
|
ball_speed_x = -abs(ball_speed_x) - 1
|
||||||
else:
|
else:
|
||||||
ball_speed_x = abs(ball_speed_x) + 1
|
ball_speed_x = abs(ball_speed_x) + 1
|
||||||
# 判断撞方块上侧/下侧:翻转Y速度
|
|
||||||
if ball.centery < tbox.y:
|
if ball.centery < tbox.y:
|
||||||
ball_speed_y = -abs(ball_speed_y)
|
ball_speed_y = -abs(ball_speed_y)
|
||||||
else:
|
else:
|
||||||
ball_speed_y = abs(ball_speed_y)
|
ball_speed_y = abs(ball_speed_y)
|
||||||
# 重新生成方块坐标
|
|
||||||
random_intX = random.randint(235, 1685)
|
random_intX = random.randint(235, 1685)
|
||||||
random_intY = random.randint(235, 845)
|
random_intY = random.randint(235, 845)
|
||||||
tbox.x = random_intX
|
tbox.x = random_intX
|
||||||
tbox.y = random_intY
|
tbox.y = random_intY
|
||||||
|
|
||||||
# 出左右边界游戏结束,这里不再加分
|
# 球出界逻辑,区分两种模式
|
||||||
if ball.left <= 0:
|
if ball.left <= 0:
|
||||||
game_state = "gameover"
|
if game_mode == 1:
|
||||||
lose_text = "player 2 win!"
|
# 计分模式:仅加分,球回中心继续
|
||||||
sounds.zhanbai.play()
|
scorep2 += 1
|
||||||
if ball.right >= WIDTH:
|
ball.pos = (WIDTH//2, HEIGHT//2)
|
||||||
game_state = "gameover"
|
ball_speed_x = 7
|
||||||
lose_text = "player 1 win!"
|
ball_speed_y = 7
|
||||||
sounds.zhanbai.play()
|
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):
|
def on_key_down(key):
|
||||||
global game_state, ball_speed_x, ball_speed_y, scorep1, scorep2
|
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":
|
if key == keys.SPACE and game_state == "gameover":
|
||||||
game_state = "playing"
|
game_state = "playing"
|
||||||
ball.pos = (WIDTH//2, HEIGHT//2)
|
ball.pos = (WIDTH//2, HEIGHT//2)
|
||||||
ball_speed_x = 7
|
ball_speed_x = 7
|
||||||
ball_speed_y = 7
|
ball_speed_y = 7
|
||||||
# 重启清空分数,不需要就注释掉下面两行
|
|
||||||
scorep1 = 0
|
scorep1 = 0
|
||||||
scorep2 = 0
|
scorep2 = 0
|
||||||
|
start_time = time.perf_counter()
|
||||||
|
elapsed_time = 0
|
||||||
|
|
||||||
pgzrun.go()
|
pgzrun.go()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user