Python编写带音效游戏——击球打玻璃块

Python编写游戏的环境搭建和编写过程已在上篇“Python编写游戏——拼图游戏”中进行了介绍,在此基础上本篇再介绍键盘控制、背景图像设置和音效设置。

一、开发工具

Python版本:Python 3.6.4或以上版本

二、相关模块:

pgzrun模块以及一些Python自带的标准模块。

三、环境搭建

在运行Python文件目录下建三个文件夹:imagesfonts和music。背景图像、角色图像(默认是png格式)全部放在images文件夹、字库(默认为ttf字库)放在fonts文件夹、音效文件放在music文件夹中。

四、相关函数与方法

1.事件更新和绘图

绘图(draw())和更新(update())函数是相似的,更新(update())函数每秒会调用60次,而绘图(draw())函数只有在某些事情发生变化时才调用。

所以一般将变化多的:如键盘运动,球运动等放在更新(update())函数中,而背景图像、角色图像等放在绘图(draw())函数中。

1.设置背景色

screen.fill((R, G, B))

2.加载图像

screen.blit(图像, 坐标)

其中:图像默认为png图像,坐标为图像的topleft(即左上角,见图1)

 

图像位置名称

3.鼠标与按键

游戏外部事件的触发控制on_xxx_xxxpgzero提供了常用的鼠标和键盘事件:

键盘事件:on_key_downon_key_up

鼠标事件:on_mouse_downon_mouse_upon_mouse_move

键盘的按键信息是通过keyboard内置对象获取的,鼠标是mouse来获取的,例如:

keyboard.a                          # 'a'

keyboard.left                     # 向左箭头键

keyboard.rshift                  # 右侧shift

keyboard.kp0                     # 小键盘上的'0'

keyboard.k_0                     # 主键盘上的'0'

mouse.left                          # 鼠标左键

mouse.right                        # 鼠标右键

mouse.middle                    # 鼠标中键(如果有的话)

也可以用key == keys.按键(按键用大写字母表示),例如:

if key == keys.LEFT:

    player.x -= 5

4.音效

music.play_once(音乐)用于一次性播放“音乐”。音乐文件必须是存储在位于与游戏脚本相同位置的music文件夹,支持oggmp3格式,不支持wav格式。

5. colliderect()碰撞检测

colliderect()用于判断两个角色是否发生碰撞,如果发生碰撞返回True,没有发生碰撞返回False

角色1.colliderect(角色2)

6.目录结构:

 

五、拼图游戏源代码

初始小球向上向左或向右移动,碰到玻璃块,玻璃块消失并发出击碎玻璃声音,向下移动时需要按左右箭头键移动击球棒将小球反弹回去,如果没有接住,当小球到达下边界时游戏结束。如果能够击碎所有玻璃块,你将赢得游戏。完整代码如下。

##############################################
# 设计 Zhang Ruilin    创建 2022-12-07 20:06 #
# 用 pgzrun 模块编制带音效的击球打玻璃块游戏 #
##############################################
import pgzrun
import random, sys
import time

TITLE = '击球打玻璃块'
WIDTH = 800
HEIGHT = 500

bat = Actor('bat')			# 游戏角色1——击球棒
bat.x = 120
bat.y = 420

ball = Actor('ball')			# 游戏角色2——球
ball.x = 30
ball.y = 300

bars_list=[]
ball_x_speed = 2*random.randint(0,1)-1
ball_y_speed = 1
gameover = False			# 游戏结束标志(gameover=True结束游戏)
start = time.time()			# 程序运行开始计时
newTime = 0				# 游戏计时所用秒数
st = 0					# 结束游戏计时

def draw():
    global gameover, st
    screen.blit('sky', (0,0))					# 绘制背景图
    for bar in bars_list:
        bar.draw()
    bat.draw()
    screen.draw.text('游戏运行:'+str(newTime)+'秒', (10, 10),
           fontname='simkai', fontsize=15, color='yellow')	# 楷体
    screen.draw.text('还剩'+str(len(bars_list))+'块玻璃', (10, 30),
           fontname='simkai', fontsize=15, color='yellow')	# 楷体
    if gameover:
        ds = '您赢了!' if len(bars_list)==0 else '游戏结束!'	# 玻璃块全击碎则赢
        screen.draw.text(ds, center=(WIDTH/2, HEIGHT/2),	# 居中显示
            fontname='msyh.ttc',fontsize=50, color='orange')	# 微软雅黑
        if st == 0: st = time.time()				# 结束游戏开始计时
    ball.draw()

def place_bars(x,y,image):
    bar_x = x
    bar_y = y
    for i in range(8):
        bar = Actor(image)
        bar.x = bar_x
        bar.y = bar_y
        bar_x += 90
        bars_list.append(bar)

clrglassbar_list = ['glassbar_b', 'glassbar_g', 'glassbar_r']	# 三种颜色玻璃块
x = 88
y = 100
for clrglassbar in clrglassbar_list:
    place_bars(x, y, clrglassbar)
    y += 50

def update():
    global ball_x_speed, ball_y_speed, gameover, newTime, st
    if not gameover:
        end = time.time()
        newTime = int(end-start+0.5)				# 更新程序运行时间(秒)
    else:
        if time.time() - st >=5:				# 延时5秒退出系统
            st = '您有'+str(len(bars_list))+'块玻璃没有击碎!'
            sys.exit('您赢了!' if len(bars_list)==0 else st)
    if keyboard.left:						# 按向左键,向左移动击球棒
        bat.x = bat.x - 5
    if keyboard.right:						# 按向右键,向右移动击球棒
        bat.x = bat.x + 5
    if keyboard.down:						# 按向下键,降低球速
        kx = 1 if ball_x_speed>0 else -1
        ball_x_speed = kx*(abs(ball_x_speed)-1 if abs(ball_x_speed)>1 else 1)
        ky = 1 if ball_y_speed>0 else -1
        ball_y_speed = ky*(abs(ball_y_speed)-1 if abs(ball_y_speed)>1 else 1)
    if keyboard.up:						# 按向上键,增加球速
        kx = 1 if ball_x_speed>0 else -1
        ball_x_speed = kx*(abs(ball_x_speed)+1 if abs(ball_x_speed)<3 else 3)
        ky = 1 if ball_y_speed>0 else -1
        ball_y_speed = ky*(abs(ball_y_speed)+1 if abs(ball_y_speed)<3 else 3)
    update_ball()
    for bar in bars_list:
        if ball.colliderect(bar):				# 如果球遇到玻璃块
            bars_list.remove(bar)				# 删除此玻璃块
            ball_y_speed *= -1					# 球改变上下移动方向
            music.play_once('击碎玻璃.mp3')			# 发出击碎玻璃音效
            if len(bars_list) == 0: gameover = True		# 如果玻璃块没有了赢得游戏
    if bat.colliderect(ball):					# 如果球遇到击球棒
        ball_y_speed *= -1					# 球改变上下移动方向
        rand = random.randint(0,1)				# 击球时随机向左或向右反弹
        if rand:
            ball_x_speed *= -1
        music.play_once('击球.mp3')				# 发出击球音效

def update_ball():
    global ball_x_speed, ball_y_speed, gameover
    ball.x -= ball_x_speed
    ball.y -= ball_y_speed
    if (ball.x >= WIDTH-12) or (ball.x <=12):			# 如果球遇到左右边界,反弹
        ball_x_speed *= -1
    if (ball.y <=12):						# 如果球遇到上边界,反弹
        ball_y_speed *= -1
    if (ball.y >= HEIGHT-12):					# 如果球遇到下边界
        gameover = True						# 没有击到球,游戏结束

pgzrun.go()

六、执行效果

2 初始状态

3 失败结束

4 获胜结束

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值