• 售前

  • 售后

热门帖子
入门百科

Pygame学习笔记8:Block Breaker游戏

[复制链接]
里脊鱼鱼si 显示全部楼层 发表于 2022-1-12 22:50:14 |阅读模式 打印 上一主题 下一主题
这次来制作一个Block Breaker游戏,即我们以前玩过的一个小游戏,用一块板子撞击小球,而小球碰到砖块会反弹,同时被碰到的砖块会消失,直到所有的砖块都消失,游戏结束,进入下一关。
那么接下来就好好介绍一下这个游戏的制作过程。
Block Breaker

在这次制作中,上一章制作的MyLibrary.py有一些改动和添加,完整的新代码如下:
  1. import random
  2. import sys
  3. import math
  4. import time
  5. import pygame
  6. from pygame.locals import *
  7. # 类中的X、Y、position用于设置精灵的位置
  8. class MySprite(pygame.sprite.Sprite):
  9.     def __init__(self):
  10.         # 调用父类的初始化方法
  11.         pygame.sprite.Sprite.__init__(self)
  12.         # self.image = pygame.image.load(image_file).convert_alpha()
  13.         # self.rect = self.image.get_rect()
  14.         self.master_image = None
  15.         self.frame = 0
  16.         self.old_frame = -1
  17.         self.frame_width = 1
  18.         self.frame_height = 1
  19.         self.first_frame = 0
  20.         self.last_frame = 0
  21.         self.columns = 1
  22.         self.last_time = 0
  23.         self.direction = 0
  24.         self.velocity = Point(0.0, 0.0)
  25.     def getx(self):
  26.         return self.rect.x
  27.     def setx(self, value):
  28.         self.rect.x = value
  29.     X = property(getx, setx)
  30.     def gety(self):
  31.         return self.rect.y
  32.     def sety(self, value):
  33.         self.rect.y = value
  34.     Y = property(gety, sety)
  35.     def getpos(self):
  36.         return self.rect.topleft
  37.     def setpos(self, pos):
  38.         self.rect.topleft = pos
  39.     position = property(getpos, setpos)
  40.     def load(self, filename, width=0, height=0, columns=1):
  41.         self.master_image = pygame.image.load(filename).convert_alpha()
  42.         self.set_image(self.master_image, width, height, columns)
  43.     def set_image(self, image, width=0, height=0, columns=1):
  44.         self.master_image = image
  45.         if width == 0 and height == 0:
  46.             self.frame_width = image.get_width()
  47.             self.frame_height = image.get_height()
  48.         else:
  49.             self.frame_width = width
  50.             self.frame_height = height
  51.             rect = self.master_image.get_rect()
  52.             self.last_frame = (rect.width // width) * (rect.height // height) - 1
  53.         self.rect = Rect(0, 0, self.frame_width, self.frame_height)
  54.         self.columns = columns
  55.     def update(self, current_time, rate=30):
  56.         # 帧变动
  57.         if self.last_frame > self.first_frame:
  58.             if current_time > self.last_time + rate:
  59.                 self.frame += 1
  60.                 if self.frame > self.last_frame:
  61.                     self.frame = self.first_frame
  62.                 self.last_time = current_time
  63.         else:
  64.             self.frame = self.first_frame
  65.         # 当帧发生变化时,进行修改
  66.         if self.frame != self.old_frame:
  67.             frame_x = (self.frame % self.columns) * self.frame_width
  68.             frame_y = (self.frame // self.columns) * self.frame_height
  69.             rect = Rect(frame_x, frame_y, self.frame_width, self.frame_height)
  70.             # 将要展示的图片送给image属性,以便展示出来
  71.             self.image = self.master_image.subsurface(rect)
  72.             self.old_frame = self.frame
  73.     def __str__(self):
  74.         return str(self.frame) + "," + str(self.first_frame) + "," + str(self.last_frame) + \
  75.                "," + str(self.frame_width) + "," + str(self.frame_height) + "," + \
  76.                str(self.columns) + "," + str(self.rect)
  77. class Point(object):
  78.     def __init__(self, x, y):
  79.         self.__x = x
  80.         self.__y = y
  81.     def getx(self):
  82.         return self.__x
  83.     def setx(self, x):
  84.         self.__x = x
  85.     x = property(getx, setx)
  86.     def gety(self):
  87.         return self.__y
  88.     def sety(self, y):
  89.         self.__y = y
  90.     y = property(gety, sety)
  91.     def __str__(self):
  92.         return "{X:" + "{:.0f}".format(self.__x) + ",Y:" + "{:.0f}".format(self.__y) + "}"
  93. def print_text(font, x, y, text, color=(255, 255, 255), shadow=True):
  94.     imgText = font.render(text, True, color)
  95.     screen = pygame.display.get_surface()
  96.     screen.blit(imgText, (x, y))
复制代码
关卡设置

游戏中设置了4个关卡,存储在levels中,每一关的样子如下。
关卡1:
  1. (
  2.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  3.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  4.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  5.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  6.         1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
  7.         1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
  8.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  9.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  10.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  11.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  12.     )
复制代码
图形如下:

关卡2:
  1. (
  2.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  3.         2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
  4.         2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
  5.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  6.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  7.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  8.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  9.         2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
  10.         2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
  11.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  12.     )
复制代码
图形如下:

关卡3:
  1. (
  2.         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  3.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  4.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  5.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  6.         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  7.         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  8.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  9.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  10.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  11.         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  12.     )
复制代码
图形如下:

关卡4:
  1. (
  2.         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  3.         4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4,
  4.         4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4,
  5.         4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4,
  6.         4, 4, 4, 0, 0, 4, 4, 4, 0, 0, 4, 4,
  7.         4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4,
  8.         4, 4, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4,
  9.         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  10.         4, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 4,
  11.         4, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 4
  12.     )
复制代码
图形如下:

游戏初始化

这一次,因为代码量比较大,所以我们将很多部分进行了模块化,游戏的一些初始化操作都封装到一个函数中:
  1. # 游戏的一些初始化设置
  2. def game_init():
  3.     global screen, font, timer
  4.     global paddle_group, block_group, ball_group
  5.     global paddle, block_image, block, ball
  6.     pygame.init()
  7.     screen = pygame.display.set_mode((800, 600))
  8.     pygame.display.set_caption("Block Breaker Game")
  9.     font = pygame.font.Font(None, 40)
  10.     pygame.mouse.set_visible(False)
  11.     timer = pygame.time.Clock()
  12.     # 创建精灵组
  13.     paddle_group = pygame.sprite.Group()
  14.     block_group = pygame.sprite.Group()
  15.     ball_group = pygame.sprite.Group()
  16.     # 创建板子
  17.     paddle = MySprite()
  18.     paddle.load("paddle.png")
  19.     paddle.position = 400, 540
  20.     paddle_group.add(paddle)
  21.     # 创建球
  22.     ball = MySprite()
  23.     ball.load("ball.png")
  24.     ball.position = 400, 300
  25.     ball_group.add(ball)
复制代码
为了能够让函数中初始化后的变量能够在其他地方被使用,因此都是使用的global变量。
关卡的加载和修改

和关卡相关的一些操作其实就是对砖块的处理,共有3个函数:
  1. # 加载关卡
  2. def load_level():
  3.     global level, levels, block_image, block_group
  4.     block_image = pygame.image.load("blocks.png").convert_alpha()
  5.     # 先将砖块组中的对象清空
  6.     block_group.empty()
  7.     for bx in range(0, 12):
  8.         for by in range(0, 10):
  9.             block = MySprite()
  10.             block.set_image(block_image, 58, 28, 4)
  11.             x = 40 + bx * (block.frame_width + 1)
  12.             y = 60 + by * (block.frame_height + 1)
  13.             block.position = x, y
  14.             num = levels[level][by * 12 + bx]
  15.             block.first_frame = num - 1
  16.             block.last_frame = num - 1
  17.             if num > 0:
  18.                 block_group.add(block)
  19. # 更新砖块
  20. def update_blocks():
  21.     global block_group, waiting
  22.     if len(block_group) == 0:
  23.         goto_next_level()
  24.         waiting = True
  25.     block_group.update(ticks, 50)
  26. # 进入到下一个关卡
  27. def goto_next_level():
  28.     global level, levels
  29.     level += 1
  30.     if level > len(levels) - 1:
  31.         level = 0
  32.     load_level()
复制代码
精灵图像的移动

需要移动的精灵图像分别是球和板子,其中球的处理如下:
  1. # 重置球的速度
  2. def reset_ball():
  3.     ball.velocity = Point(4.5, -7.0)
  4. # 移动球
  5. def move_ball():
  6.     global waiting, ball, game_over, lives
  7.     ball_group.update(ticks, 50)
  8.     # 若球掉下去了,重新将球放到板子上
  9.     if waiting:
  10.         ball.X = paddle.X + 40
  11.         ball.Y = paddle.Y - 20
  12.     ball.X += ball.velocity.x
  13.     ball.Y += ball.velocity.y
  14.     if ball.X < 0:
  15.         ball.X = 0
  16.         ball.velocity.x *= -1
  17.     elif ball.X > 780:
  18.         ball.X = 780
  19.         ball.velocity.x *= -1
  20.     if ball.Y < 0:
  21.         ball.Y = 0
  22.         ball.velocity.y *= -1
  23.     elif ball.Y > 580:
  24.         waiting = True
  25.         lives -= 1
  26.         if lives < 1:
  27.             game_over = True
复制代码
板子的移动如下:
  1. # 移动板子
  2. def move_paddle():
  3.     global movex, movey, keys, waiting
  4.     paddle_group.update(ticks, 50)
  5.     # 可以通过空格、左右键控制板子
  6.     if keys[K_SPACE]:
  7.         if waiting:
  8.             waiting = False
  9.             reset_ball()
  10.     elif keys[K_LEFT]:
  11.         paddle.velocity.x = -10.0
  12.     elif keys[K_RIGHT]:
  13.         paddle.velocity.x = 10.0
  14.     else:
  15.         if movex < -2:
  16.             paddle.velocity.x = movex
  17.         elif movex > 2:
  18.             paddle.velocity.x = movex
  19.         else:
  20.             paddle.velocity.x = 0
  21.     paddle.X += paddle.velocity.x
  22.     if paddle.X < 0:
  23.         paddle.X = 0
  24.     elif paddle.X > 710:
  25.         paddle.X = 710
复制代码
碰撞检测

对于碰撞检测,我们既需要检测球与板子之间的碰撞,也需要检测球与砖块之间的碰撞,其中球与板子之间的碰撞检测如下:
  1. # 球与板子的冲突检测
  2. def collision_ball_paddle():
  3.     if pygame.sprite.collide_rect(ball, paddle):
  4.         ball.velocity.y = -abs(ball.velocity.y)
  5.         bx = ball.X + 8
  6.         by = ball.Y + 8
  7.         px = paddle.X + paddle.frame_width / 2
  8.         py = paddle.Y + paddle.frame_height / 2
  9.         if bx < px:
  10.             ball.velocity.x = -abs(ball.velocity.x)
  11.         else:
  12.             ball.velocity.x = abs(ball.velocity.x)
复制代码
这里可以看到,我们并不是简单地按照相反的方向反弹,而是要根据球落在板子的位置的不同,以不同的方式反弹。
球与砖块之间的碰撞检测如下:
  1. # 球与砖块的冲突检测
  2. def collision_ball_blocks():
  3.     global score, block_group, ball
  4.     hit_block = pygame.sprite.spritecollideany(ball, block_group)
  5.     if hit_block:
  6.         score += 10
  7.         block_group.remove(hit_block)
  8.         bx = ball.X + 8
  9.         by = ball.Y + 8
  10.         if bx > hit_block.X + 5 and bx < hit_block.X + hit_block.frame_width - 5:
  11.             if by < hit_block.Y + hit_block.frame_height / 2:
  12.                 ball.velocity.y = -abs(ball.velocity.y)
  13.             else:
  14.                 ball.velocity.y = abs(ball.velocity.y)
  15.         elif bx < hit_block.X + 5:
  16.             ball.velocity.x = -abs(ball.velocity.x)
  17.         elif bx > hit_block.X + hit_block.frame_width - 5:
  18.             ball.velocity.x = abs(ball.velocity.x)
  19.         else:
  20.             ball.velocity.y *= -1
复制代码
这里用到了pygame.sprite.spritecollideany()函数进行检测,因为我们需要将被碰到的砖块消去,同时对碰撞后球的速度和方向的处理同前面一样,而不是简单的相反的方向。
完整源代码

完整的代码如下:
  1. import randomimport sysimport pygamefrom pygame.locals import *from MyLibrary import *levels = (    (
  2.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  3.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  4.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  5.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  6.         1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
  7.         1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
  8.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  9.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  10.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  11.         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  12.     ), (
  13.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  14.         2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
  15.         2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
  16.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  17.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  18.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  19.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  20.         2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
  21.         2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
  22.         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  23.     ), (
  24.         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  25.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  26.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  27.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  28.         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  29.         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  30.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  31.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  32.         3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
  33.         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  34.     ), (
  35.         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  36.         4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4,
  37.         4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4,
  38.         4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4,
  39.         4, 4, 4, 0, 0, 4, 4, 4, 0, 0, 4, 4,
  40.         4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4,
  41.         4, 4, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4,
  42.         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  43.         4, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 4,
  44.         4, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 4
  45.     ))# 游戏的一些初始化设置
  46. def game_init():
  47.     global screen, font, timer
  48.     global paddle_group, block_group, ball_group
  49.     global paddle, block_image, block, ball
  50.     pygame.init()
  51.     screen = pygame.display.set_mode((800, 600))
  52.     pygame.display.set_caption("Block Breaker Game")
  53.     font = pygame.font.Font(None, 40)
  54.     pygame.mouse.set_visible(False)
  55.     timer = pygame.time.Clock()
  56.     # 创建精灵组
  57.     paddle_group = pygame.sprite.Group()
  58.     block_group = pygame.sprite.Group()
  59.     ball_group = pygame.sprite.Group()
  60.     # 创建板子
  61.     paddle = MySprite()
  62.     paddle.load("paddle.png")
  63.     paddle.position = 400, 540
  64.     paddle_group.add(paddle)
  65.     # 创建球
  66.     ball = MySprite()
  67.     ball.load("ball.png")
  68.     ball.position = 400, 300
  69.     ball_group.add(ball)# 加载关卡
  70. def load_level():
  71.     global level, levels, block_image, block_group
  72.     block_image = pygame.image.load("blocks.png").convert_alpha()
  73.     # 先将砖块组中的对象清空
  74.     block_group.empty()
  75.     for bx in range(0, 12):
  76.         for by in range(0, 10):
  77.             block = MySprite()
  78.             block.set_image(block_image, 58, 28, 4)
  79.             x = 40 + bx * (block.frame_width + 1)
  80.             y = 60 + by * (block.frame_height + 1)
  81.             block.position = x, y
  82.             num = levels[level][by * 12 + bx]
  83.             block.first_frame = num - 1
  84.             block.last_frame = num - 1
  85.             if num > 0:
  86.                 block_group.add(block)
  87. # 更新砖块
  88. def update_blocks():
  89.     global block_group, waiting
  90.     if len(block_group) == 0:
  91.         goto_next_level()
  92.         waiting = True
  93.     block_group.update(ticks, 50)
  94. # 进入到下一个关卡
  95. def goto_next_level():
  96.     global level, levels
  97.     level += 1
  98.     if level > len(levels) - 1:
  99.         level = 0
  100.     load_level()# 移动板子
  101. def move_paddle():
  102.     global movex, movey, keys, waiting
  103.     paddle_group.update(ticks, 50)
  104.     # 可以通过空格、左右键控制板子
  105.     if keys[K_SPACE]:
  106.         if waiting:
  107.             waiting = False
  108.             reset_ball()
  109.     elif keys[K_LEFT]:
  110.         paddle.velocity.x = -10.0
  111.     elif keys[K_RIGHT]:
  112.         paddle.velocity.x = 10.0
  113.     else:
  114.         if movex < -2:
  115.             paddle.velocity.x = movex
  116.         elif movex > 2:
  117.             paddle.velocity.x = movex
  118.         else:
  119.             paddle.velocity.x = 0
  120.     paddle.X += paddle.velocity.x
  121.     if paddle.X < 0:
  122.         paddle.X = 0
  123.     elif paddle.X > 710:
  124.         paddle.X = 710# 重置球的速度
  125. def reset_ball():
  126.     ball.velocity = Point(4.5, -7.0)
  127. # 移动球
  128. def move_ball():
  129.     global waiting, ball, game_over, lives
  130.     ball_group.update(ticks, 50)
  131.     # 若球掉下去了,重新将球放到板子上
  132.     if waiting:
  133.         ball.X = paddle.X + 40
  134.         ball.Y = paddle.Y - 20
  135.     ball.X += ball.velocity.x
  136.     ball.Y += ball.velocity.y
  137.     if ball.X < 0:
  138.         ball.X = 0
  139.         ball.velocity.x *= -1
  140.     elif ball.X > 780:
  141.         ball.X = 780
  142.         ball.velocity.x *= -1
  143.     if ball.Y < 0:
  144.         ball.Y = 0
  145.         ball.velocity.y *= -1
  146.     elif ball.Y > 580:
  147.         waiting = True
  148.         lives -= 1
  149.         if lives < 1:
  150.             game_over = True# 球与板子的冲突检测
  151. def collision_ball_paddle():
  152.     if pygame.sprite.collide_rect(ball, paddle):
  153.         ball.velocity.y = -abs(ball.velocity.y)
  154.         bx = ball.X + 8
  155.         by = ball.Y + 8
  156.         px = paddle.X + paddle.frame_width / 2
  157.         py = paddle.Y + paddle.frame_height / 2
  158.         if bx < px:
  159.             ball.velocity.x = -abs(ball.velocity.x)
  160.         else:
  161.             ball.velocity.x = abs(ball.velocity.x)# 球与砖块的冲突检测
  162. def collision_ball_blocks():
  163.     global score, block_group, ball
  164.     hit_block = pygame.sprite.spritecollideany(ball, block_group)
  165.     if hit_block:
  166.         score += 10
  167.         block_group.remove(hit_block)
  168.         bx = ball.X + 8
  169.         by = ball.Y + 8
  170.         if bx > hit_block.X + 5 and bx < hit_block.X + hit_block.frame_width - 5:
  171.             if by < hit_block.Y + hit_block.frame_height / 2:
  172.                 ball.velocity.y = -abs(ball.velocity.y)
  173.             else:
  174.                 ball.velocity.y = abs(ball.velocity.y)
  175.         elif bx < hit_block.X + 5:
  176.             ball.velocity.x = -abs(ball.velocity.x)
  177.         elif bx > hit_block.X + hit_block.frame_width - 5:
  178.             ball.velocity.x = abs(ball.velocity.x)
  179.         else:
  180.             ball.velocity.y *= -1if __name__ == "__main__":    game_init()    game_over = False    waiting = True    score = 0    lives = 3    level = 3    load_level()    while True:        timer.tick(30)        ticks = pygame.time.get_ticks()        for event in pygame.event.get():            if event.type == QUIT:                sys.exit()            elif event.type == MOUSEMOTION:                movex, movey = event.rel            elif event.type == MOUSEBUTTONUP:                if waiting:                    waiting = False                    reset_ball()            elif event.type == KEYUP:                if event.key == K_RETURN:                    goto_next_level()        keys = pygame.key.get_pressed()        if keys[K_ESCAPE]:            sys.exit()        if not game_over:            update_blocks()            move_paddle()            move_ball()            collision_ball_paddle()            collision_ball_blocks()        screen.fill((50, 50, 100))        block_group.draw(screen)        ball_group.draw(screen)        paddle_group.draw(screen)        print_text(font, 0, 0, "SCORE:" + str(score))        print_text(font, 200, 0, "LEVEL:" + str(level + 1))        print_text(font, 400, 0, "BLOCKS:" + str(len(block_group)))        print_text(font, 670, 0, "BALLS:" + str(lives))        if game_over:            print_text(font, 300, 380, "G A M E O V E R")        pygame.display.update()
复制代码
运行结果如下:

任务一:将游戏的背景颜色设置成随着游戏的进行而逐渐淡入淡出,多种颜色循环变化,同时添加一个计时器,记录玩家的攻关时间

添加颜色的部分如下,首先添加一个颜色的元组:
  1. colors = (
  2.     (0, 0, 0), (0, 100, 50), (50, 50, 50), (100, 100, 100), (200, 200, 200), (150, 200, 255)
  3. )
复制代码
然后在循环外面申明一个color赋初值:
  1. color = colors[0]
复制代码
最后在循环内部:
  1. if ticks % 50 == 0:
  2.         i = colors.index(color)
  3.     color = colors[(i + 1) % len(colors)]
  4. screen.fill(color)
复制代码
而添加计时功能则如下:
  1. times = 0.0
  2. times = ticks / 1000
  3. print_text(font, 640, 0, "TIME:" + "{:.0f}".format(times) + "s")
复制代码
因为ticks记录的是毫秒,因此将其转换成秒缩短表示的长度
任务二:每次球撞击板子的时候,球的速度都会随机发生变化,让游戏变得不可预测

这个问题只需要修改一下collision_ball_paddle()函数即可,如下:
  1. # 球与板子的冲突检测
  2. def collision_ball_paddle():
  3.     if pygame.sprite.collide_rect(ball, paddle):
  4.         ball.velocity.y = -abs(random.randint(5, 15))
  5.         bx = ball.X + 8
  6.         by = ball.Y + 8
  7.         px = paddle.X + paddle.frame_width / 2
  8.         py = paddle.Y + paddle.frame_height / 2
  9.         if bx < px:
  10.             ball.velocity.x = -abs(random.randint(5, 15))
  11.         else:
  12.             ball.velocity.x = abs(random.randint(5, 15))
复制代码
来源:https://blog.caogenba.net/weixin_55267022/article/details/122397828
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作