作者 by 超米 / 2024-11-25 / 暂无评论 / 15 个足迹
# "桌上冰球"游戏
import simpleguitk as gui
import random
import math
from time import sleep
# 全局变量初始化
CANVAS_WIDTH = 1024 # 画布宽度
CANVAS_HEIGHT = 768 # 画布高度
PUCK_RADIUS = 40 # 冰球半径
MALLET_RADIUS = 47 # 球槌半径
MARGIN_WIDTH = 10 # 桌边宽度
GATE_RADIUS = 200 # 球门弧半径
puck_pos = [CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2] # 冰球的初始位置
puck_vel = [0, 0] # 冰球的初始速度
mallet1_angle = 0 # 左侧球槌的角度(以左侧球门中心为原点)
mallet1_angle_vel = math.pi / 180 # 左侧球槌的角速度
mallet1_vel = [0, 0] # 左侧球槌的线速度
mallet1_pos = [GATE_RADIUS, CANVAS_HEIGHT / 2] # 左侧球槌的初始位置
mallet2_angle = math.pi # 右侧球槌的角度(右侧球门中心为原点)
mallet2_angle_vel = 0 # 右侧球槌的角速度
mallet2_vel = [0, 0] # 由侧球槌的线速度
mallet2_pos = [CANVAS_WIDTH - GATE_RADIUS, CANVAS_HEIGHT / 2] # 右侧球槌的初始位置
score1 = 0 # 计算机得分
score2 = 0 # 玩家得分
game_over = False # 一场比赛是否结束
dire_w = ""
# 加载图片资源
table = gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/table2.png')
puck = gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/puck.png')
mallet = gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/mallet.png')
score_image = [gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/0_60x60.png'),
gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/1_60x60.png'),
gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/2_60x60.png'),
gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/3_60x60.png'),
gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/4_60x60.png'),
gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/5_60x60.png'),
gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/6_60x60.png'),
gui.load_image('http://202.201.225.74/video/PythonResoure/ProjectResource/images/project4/7_60x60.png')]
# 加载音效资源
collision_sound = gui.load_sound('http://202.201.225.74/video/PythonResoure/ProjectResource/sounds/project4/collision.wav')
goal_sound = gui.load_sound('http://202.201.225.74/video/PythonResoure/ProjectResource/sounds/project4/goal.wav')
lose_sound = gui.load_sound('http://202.201.225.74/video/PythonResoure/ProjectResource/sounds/project4/gameOver.ogg')
win_sound = gui.load_sound('http://202.201.225.74/video/PythonResoure/ProjectResource/sounds/project4/applause.ogg')
# 绘制比分的辅助函数
def draw_score(canvas, score1, score2):
canvas.draw_image(score_image[score1 % 8], [30, 30], [60, 60], [425, 45], [60, 60])
canvas.draw_image(score_image[score2 % 8], [30, 30], [60, 60], [600, 45], [60, 60])
# 计算两点距离的辅助函数
def distance(p, q):
d = math.sqrt((p[0]-q[0])**2 + (p[1]-q[1])**2)
return d
def locate_dire():
global dire_width, dire_w
if dire_width == 0:
dire_w = "LEFT"
elif dire_width == 1:
dire_w = "RIGHT"
return dire_w
# 碰撞检测辅助函数
def check_collision():
global puck_vel, mallet1_vel, mallet2_vel, score1, score2
collided = False
dis_1 = distance(puck_pos, mallet1_pos)
dis_2 = distance(puck_pos, mallet2_pos)
dis_3 = distance(puck_pos, [CANVAS_WIDTH, CANVAS_HEIGHT / 2])
dis_4 = distance(puck_pos, [0, CANVAS_HEIGHT / 2])
# 玩家进球
if dis_3 < GATE_RADIUS and score1 <= 7:
score2 = score2 + 1
puck_pos[0] = CANVAS_WIDTH / 2
puck_pos[1] = CANVAS_HEIGHT / 2
dire_w1 = locate_dire()
spawn_puck(dire_w1)
goal_sound.play()
# 计算机进球
if dis_4 < GATE_RADIUS and score1 <= 7:
score1 = score1 + 1
puck_pos[0] = CANVAS_WIDTH / 2
puck_pos[1] = CANVAS_HEIGHT / 2
dire_w1 = locate_dire()
spawn_puck(dire_w1)
goal_sound.play()
# 碰右壁
if puck_pos[0] + PUCK_RADIUS + puck_vel[0] >= CANVAS_WIDTH:
puck_vel[0] = - puck_vel[0]
collided = True
# 碰左壁
if puck_pos[0] - PUCK_RADIUS + puck_vel[0] <= 0:
puck_vel[0] = - puck_vel[0]
collided = True
# 碰下壁
if puck_pos[1] + puck_vel[1] + PUCK_RADIUS >= CANVAS_HEIGHT:
puck_vel[1] = - puck_vel[1]
collided = True
# 碰上壁
if puck_pos[1] - PUCK_RADIUS + puck_vel[1] <= 0:
puck_vel[1] = - puck_vel[1]
collided = True
# 冰球和计算机球槌碰撞
if dis_1 <= MALLET_RADIUS + PUCK_RADIUS and dis_1 >= MALLET_RADIUS and puck_pos[0] >= mallet1_pos[0]:
puck_vel[0] = -puck_vel[0]
if dis_1 <= MALLET_RADIUS + PUCK_RADIUS and dis_1 >= MALLET_RADIUS and puck_pos[0] < mallet1_pos[0]:
puck_vel[1] = -puck_vel[1]
collided = True
# 冰球和玩家球槌碰撞
if dis_2 <= MALLET_RADIUS + PUCK_RADIUS and dis_2 >= MALLET_RADIUS and puck_pos[0] >= mallet2_pos[0]:
puck_vel[1] = -puck_vel[1]
if dis_2 <= MALLET_RADIUS + PUCK_RADIUS and dis_2 >= MALLET_RADIUS and puck_pos[0] < mallet2_pos[0]:
puck_vel[0] = -puck_vel[0]
collided = True
puck_pos[1] = puck_pos[1] + puck_vel[1]
puck_pos[0] = puck_pos[0] + puck_vel[0]
# 播放碰撞音效
if collided:
collision_sound.play()
# 在球桌中央初始化冰球的位置和速度,方向可以向左或向右
def spawn_puck(direction):
pass
global puck_pos, puck_vel
if dire_height == 0:
puck_vel[1] = random.randrange(3, 6)
else:
puck_vel[1] = -random.randrange(3, 6)
if direction == "LEFT":
puck_vel[0] = -random.randrange(5, 8)
elif direction == "RIGHT":
puck_vel[0] = random.randrange(5, 8)
# 初始化全局变量, 也是按钮事件处理函数,用来初始化游戏
def new_game():
global dire_width, dire_height, score1, score2, game_over,mallet1_angle_vel,mallet1_angle,\
puck_pos,puck_vel,mallet1_vel,mallet1_pos,mallet2_angle,mallet2_angle_vel,mallet2_vel,mallet2_pos
puck_vel = [0, 0] # 冰球的初始速度
mallet1_angle_vel = math.pi / 180 # 左侧球槌的角速度
puck_pos = [CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2] # 冰球的初始位置
mallet1_angle = 0 # 左侧球槌的角度(以左侧球门中心为原点)
mallet1_vel = [0, 0] # 左侧球槌的线速度
mallet1_pos = [GATE_RADIUS, CANVAS_HEIGHT / 2] # 左侧球槌的初始位置
mallet2_angle = math.pi # 右侧球槌的角度(右侧球门中心为原点)
mallet2_angle_vel = 0 # 右侧球槌的角速度
mallet2_vel = [0, 0] # 右侧球槌的线速度
mallet2_pos = [CANVAS_WIDTH - GATE_RADIUS, CANVAS_HEIGHT / 2] # 右侧球槌的初始位置
score1 = 0 # 计算机得分
score2 = 0 # 玩家得分
dire_width = random.randrange(-1, 2)
dire_height = random.randrange(-1, 2)
direction_w = locate_dire()
spawn_puck(direction_w)
game_over = False
# 主绘制函数
def draw(canvas):
global score1, score2, mallet1_angle, mallet2_angle, mallet1_angle_vel, game_over,mallet2_angle_vel
# 检测碰撞
check_collision()
# 绘制冰球桌
canvas.draw_image(table, [512, 384], [1024, 768], [512, 384], [1024, 768])
# 绘制比分
draw_score(canvas, score2, score1)
# 绘制冰球
puck_pos[0] += puck_vel[0]
puck_pos[1] += puck_vel[1]
canvas.draw_image(puck, [128, 128], [256, 256], puck_pos, [PUCK_RADIUS * 2, PUCK_RADIUS * 2])
# 绘制左侧球槌
mallet1_angle += mallet1_angle_vel
if mallet1_angle_vel > 0 and mallet1_angle > math.radians(90-17):
mallet1_angle_vel = - mallet1_angle_vel
if mallet1_angle_vel < 0 and mallet1_angle < math.radians(-90+17):
mallet1_angle_vel = - mallet1_angle_vel
mallet1_pos[0] = GATE_RADIUS * math.cos(mallet1_angle)
mallet1_pos[1] = CANVAS_HEIGHT / 2 - GATE_RADIUS * math.sin(mallet1_angle)
canvas.draw_image(mallet, [47, 47], [94, 94], mallet1_pos, [MALLET_RADIUS * 2, MALLET_RADIUS * 2])
# 绘制右侧球槌
mallet2_pos[0] = CANVAS_WIDTH + GATE_RADIUS * math.cos(mallet2_angle)
mallet2_pos[1] = CANVAS_HEIGHT / 2 + GATE_RADIUS * math.sin(mallet2_angle)
canvas.draw_image(mallet, [47, 47], [94, 94], mallet2_pos, [MALLET_RADIUS * 2, MALLET_RADIUS * 2])
# 绘制游戏结束信息、播放音效
if score1 == 7 or score2 == 7:
game_over = True
win_sound.play()
if game_over:
canvas.draw_text("游戏结束,重新开始", (100, 150), 20, 'Black', 'arial')
# 键盘事件的处理函数
def key_down(key):
global mallet2_angle_vel,mallet2_angle
if key == gui.KEY_MAP["up"]:
mallet2_angle_vel += math.pi / 200
elif key == gui.KEY_MAP["down"]:
mallet2_angle_vel -= math.pi / 200
mallet2_angle += mallet2_angle_vel
if mallet2_angle < math.radians(90 + 17):
mallet2_angle_vel = - mallet2_angle_vel
if mallet2_angle > math.radians(270 - 17):
mallet2_angle_vel = - mallet2_angle_vel
def key_up(key):
global mallet2_angle_vel
mallet2_angle_vel = 0
# 创建窗口
frame = gui.create_frame("桌上冰球", CANVAS_WIDTH, CANVAS_HEIGHT)
button = frame.add_button('重新开始', new_game, 50)
frame.set_draw_handler(draw)
frame.set_keydown_handler(key_down)
frame.set_keyup_handler(key_up)
# 启动游戏
new_game()
frame.start()
独特见解