桌上冰球”游戏

作者 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()

独特见解