当前位置:   article > 正文

Pygame学习笔记8:Block Breaker游戏_pygame关卡切换

pygame关卡切换

这次来制作一个Block Breaker游戏,即我们以前玩过的一个小游戏,用一块板子撞击小球,而小球碰到砖块会反弹,同时被碰到的砖块会消失,直到所有的砖块都消失,游戏结束,进入下一关。
那么接下来就好好介绍一下这个游戏的制作过程。

Block Breaker

在这次制作中,上一章制作的MyLibrary.py有一些改动和添加,完整的新代码如下:

import random
import sys
import math
import time
import pygame
from pygame.locals import *


# 类中的X、Y、position用于设置精灵的位置
class MySprite(pygame.sprite.Sprite):
    def __init__(self):
        # 调用父类的初始化方法
        pygame.sprite.Sprite.__init__(self)
        # self.image = pygame.image.load(image_file).convert_alpha()
        # self.rect = self.image.get_rect()
        self.master_image = None
        self.frame = 0
        self.old_frame = -1
        self.frame_width = 1
        self.frame_height = 1
        self.first_frame = 0
        self.last_frame = 0
        self.columns = 1
        self.last_time = 0
        self.direction = 0
        self.velocity = Point(0.0, 0.0)

    def getx(self):
        return self.rect.x

    def setx(self, value):
        self.rect.x = value
    X = property(getx, setx)

    def gety(self):
        return self.rect.y

    def sety(self, value):
        self.rect.y = value
    Y = property(gety, sety)

    def getpos(self):
        return self.rect.topleft

    def setpos(self, pos):
        self.rect.topleft = pos
    position = property(getpos, setpos)

    def load(self, filename, width=0, height=0, columns=1):
        self.master_image = pygame.image.load(filename).convert_alpha()
        self.set_image(self.master_image, width, height, columns)

    def set_image(self, image, width=0, height=0, columns=1):
        self.master_image = image
        if width == 0 and height == 0:
            self.frame_width = image.get_width()
            self.frame_height = image.get_height()
        else:
            self.frame_width = width
            self.frame_height = height
            rect = self.master_image.get_rect()
            self.last_frame = (rect.width // width) * (rect.height // height) - 1
        self.rect = Rect(0, 0, self.frame_width, self.frame_height)
        self.columns = columns

    def update(self, current_time, rate=30):
        # 帧变动
        if self.last_frame > self.first_frame:
            if current_time > self.last_time + rate:
                self.frame += 1
                if self.frame > self.last_frame:
                    self.frame = self.first_frame
                self.last_time = current_time
        else:
            self.frame = self.first_frame
        # 当帧发生变化时,进行修改
        if self.frame != self.old_frame:
            frame_x = (self.frame % self.columns) * self.frame_width
            frame_y = (self.frame // self.columns) * self.frame_height
            rect = Rect(frame_x, frame_y, self.frame_width, self.frame_height)
            # 将要展示的图片送给image属性,以便展示出来
            self.image = self.master_image.subsurface(rect)
            self.old_frame = self.frame

    def __str__(self):
        return str(self.frame) + "," + str(self.first_frame) + "," + str(self.last_frame) + \
               "," + str(self.frame_width) + "," + str(self.frame_height) + "," + \
               str(self.columns) + "," + str(self.rect)


class Point(object):
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    def getx(self):
        return self.__x

    def setx(self, x):
        self.__x = x
    x = property(getx, setx)

    def gety(self):
        return self.__y

    def sety(self, y):
        self.__y = y
    y = property(gety, sety)

    def __str__(self):
        return "{X:" + "{:.0f}".format(self.__x) + ",Y:" + "{:.0f}".format(self.__y) + "}"


def print_text(font, x, y, text, color=(255, 255, 255), shadow=True):
    imgText = font.render(text, True, color)
    screen = pygame.display.get_surface()
    screen.blit(imgText, (x, y))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118

关卡设置

游戏中设置了4个关卡,存储在levels中,每一关的样子如下。

关卡1:

(
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
    )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

图形如下:
在这里插入图片描述
关卡2:

(
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
        2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
        2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
    )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

图形如下:
在这里插入图片描述
关卡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,
        3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
        3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 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,
        3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
        3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
    )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

图形如下:
在这里插入图片描述
关卡4:

(
        4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
        4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4,
        4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4,
        4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4,
        4, 4, 4, 0, 0, 4, 4, 4, 0, 0, 4, 4,
        4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4,
        4, 4, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4,
        4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
        4, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 4,
        4, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 4
    )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

图形如下:
在这里插入图片描述

游戏初始化

这一次,因为代码量比较大,所以我们将很多部分进行了模块化,游戏的一些初始化操作都封装到一个函数中:

# 游戏的一些初始化设置
def game_init():
    global screen, font, timer
    global paddle_group, block_group, ball_group
    global paddle, block_image, block, ball

    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption("Block Breaker Game")
    font = pygame.font.Font(None, 40)
    pygame.mouse.set_visible(False)
    timer = pygame.time.Clock()

    # 创建精灵组
    paddle_group = pygame.sprite.Group()
    block_group = pygame.sprite.Group()
    ball_group = pygame.sprite.Group()

    # 创建板子
    paddle = MySprite()
    paddle.load("paddle.png")
    paddle.position = 400, 540
    paddle_group.add(paddle)

    # 创建球
    ball = MySprite()
    ball.load("ball.png")
    ball.position = 400, 300
    ball_group.add(ball)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

为了能够让函数中初始化后的变量能够在其他地方被使用,因此都是使用的global变量。

关卡的加载和修改

和关卡相关的一些操作其实就是对砖块的处理,共有3个函数:

# 加载关卡
def load_level():
    global level, levels, block_image, block_group
    block_image = pygame.image.load("blocks.png").convert_alpha()
    # 先将砖块组中的对象清空
    block_group.empty()
    for bx in range(0, 12):
        for by in range(0, 10):
            block = MySprite()
            block.set_image(block_image, 58, 28, 4)
            x = 40 + bx * (block.frame_width + 1)
            y = 60 + by * (block.frame_height + 1)
            block.position = x, y

            num = levels[level][by * 12 + bx]
            block.first_frame = num - 1
            block.last_frame = num - 1
            if num > 0:
                block_group.add(block)


# 更新砖块
def update_blocks():
    global block_group, waiting
    if len(block_group) == 0:
        goto_next_level()
        waiting = True
    block_group.update(ticks, 50)


# 进入到下一个关卡
def goto_next_level():
    global level, levels
    level += 1
    if level > len(levels) - 1:
        level = 0
    load_level()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

精灵图像的移动

需要移动的精灵图像分别是球和板子,其中球的处理如下:

# 重置球的速度
def reset_ball():
    ball.velocity = Point(4.5, -7.0)


# 移动球
def move_ball():
    global waiting, ball, game_over, lives
    ball_group.update(ticks, 50)
    # 若球掉下去了,重新将球放到板子上
    if waiting:
        ball.X = paddle.X + 40
        ball.Y = paddle.Y - 20
    ball.X += ball.velocity.x
    ball.Y += ball.velocity.y
    if ball.X < 0:
        ball.X = 0
        ball.velocity.x *= -1
    elif ball.X > 780:
        ball.X = 780
        ball.velocity.x *= -1
    if ball.Y < 0:
        ball.Y = 0
        ball.velocity.y *= -1
    elif ball.Y > 580:
        waiting = True
        lives -= 1
        if lives < 1:
            game_over = True
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

板子的移动如下:

# 移动板子
def move_paddle():
    global movex, movey, keys, waiting
    paddle_group.update(ticks, 50)
    # 可以通过空格、左右键控制板子
    if keys[K_SPACE]:
        if waiting:
            waiting = False
            reset_ball()
    elif keys[K_LEFT]:
        paddle.velocity.x = -10.0
    elif keys[K_RIGHT]:
        paddle.velocity.x = 10.0
    else:
        if movex < -2:
            paddle.velocity.x = movex
        elif movex > 2:
            paddle.velocity.x = movex
        else:
            paddle.velocity.x = 0
    paddle.X += paddle.velocity.x
    if paddle.X < 0:
        paddle.X = 0
    elif paddle.X > 710:
        paddle.X = 710
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

碰撞检测

对于碰撞检测,我们既需要检测球与板子之间的碰撞,也需要检测球与砖块之间的碰撞,其中球与板子之间的碰撞检测如下:

# 球与板子的冲突检测
def collision_ball_paddle():
    if pygame.sprite.collide_rect(ball, paddle):
        ball.velocity.y = -abs(ball.velocity.y)
        bx = ball.X + 8
        by = ball.Y + 8
        px = paddle.X + paddle.frame_width / 2
        py = paddle.Y + paddle.frame_height / 2
        if bx < px:
            ball.velocity.x = -abs(ball.velocity.x)
        else:
            ball.velocity.x = abs(ball.velocity.x)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这里可以看到,我们并不是简单地按照相反的方向反弹,而是要根据球落在板子的位置的不同,以不同的方式反弹。
球与砖块之间的碰撞检测如下:

# 球与砖块的冲突检测
def collision_ball_blocks():
    global score, block_group, ball
    hit_block = pygame.sprite.spritecollideany(ball, block_group)
    if hit_block:
        score += 10
        block_group.remove(hit_block)
        bx = ball.X + 8
        by = ball.Y + 8

        if bx > hit_block.X + 5 and bx < hit_block.X + hit_block.frame_width - 5:
            if by < hit_block.Y + hit_block.frame_height / 2:
                ball.velocity.y = -abs(ball.velocity.y)
            else:
                ball.velocity.y = abs(ball.velocity.y)
        elif bx < hit_block.X + 5:
            ball.velocity.x = -abs(ball.velocity.x)
        elif bx > hit_block.X + hit_block.frame_width - 5:
            ball.velocity.x = abs(ball.velocity.x)
        else:
            ball.velocity.y *= -1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

这里用到了pygame.sprite.spritecollideany()函数进行检测,因为我们需要将被碰到的砖块消去,同时对碰撞后球的速度和方向的处理同前面一样,而不是简单的相反的方向。

完整源代码

完整的代码如下:

import random
import sys
import pygame
from pygame.locals import *
from MyLibrary import *

levels = (
    (
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
    ), (
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
        2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
        2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
    ), (
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
        3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
        3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
        3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 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,
        3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
        3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3,
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
    ), (
        4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
        4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4,
        4, 0, 0, 4, 4, 0, 0, 4, 4, 0, 0, 4,
        4, 4, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4,
        4, 4, 4, 0, 0, 4, 4, 4, 0, 0, 4, 4,
        4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 4,
        4, 4, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4,
        4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
        4, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 4,
        4, 4, 4, 0, 0, 4, 4, 0, 0, 4, 4, 4
    )
)


# 游戏的一些初始化设置
def game_init():
    global screen, font, timer
    global paddle_group, block_group, ball_group
    global paddle, block_image, block, ball

    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption("Block Breaker Game")
    font = pygame.font.Font(None, 40)
    pygame.mouse.set_visible(False)
    timer = pygame.time.Clock()

    # 创建精灵组
    paddle_group = pygame.sprite.Group()
    block_group = pygame.sprite.Group()
    ball_group = pygame.sprite.Group()

    # 创建板子
    paddle = MySprite()
    paddle.load("paddle.png")
    paddle.position = 400, 540
    paddle_group.add(paddle)

    # 创建球
    ball = MySprite()
    ball.load("ball.png")
    ball.position = 400, 300
    ball_group.add(ball)


# 加载关卡
def load_level():
    global level, levels, block_image, block_group
    block_image = pygame.image.load("blocks.png").convert_alpha()
    # 先将砖块组中的对象清空
    block_group.empty()
    for bx in range(0, 12):
        for by in range(0, 10):
            block = MySprite()
            block.set_image(block_image, 58, 28, 4)
            x = 40 + bx * (block.frame_width + 1)
            y = 60 + by * (block.frame_height + 1)
            block.position = x, y

            num = levels[level][by * 12 + bx]
            block.first_frame = num - 1
            block.last_frame = num - 1
            if num > 0:
                block_group.add(block)


# 更新砖块
def update_blocks():
    global block_group, waiting
    if len(block_group) == 0:
        goto_next_level()
        waiting = True
    block_group.update(ticks, 50)


# 进入到下一个关卡
def goto_next_level():
    global level, levels
    level += 1
    if level > len(levels) - 1:
        level = 0
    load_level()


# 移动板子
def move_paddle():
    global movex, movey, keys, waiting
    paddle_group.update(ticks, 50)
    # 可以通过空格、左右键控制板子
    if keys[K_SPACE]:
        if waiting:
            waiting = False
            reset_ball()
    elif keys[K_LEFT]:
        paddle.velocity.x = -10.0
    elif keys[K_RIGHT]:
        paddle.velocity.x = 10.0
    else:
        if movex < -2:
            paddle.velocity.x = movex
        elif movex > 2:
            paddle.velocity.x = movex
        else:
            paddle.velocity.x = 0
    paddle.X += paddle.velocity.x
    if paddle.X < 0:
        paddle.X = 0
    elif paddle.X > 710:
        paddle.X = 710


# 重置球的速度
def reset_ball():
    ball.velocity = Point(4.5, -7.0)


# 移动球
def move_ball():
    global waiting, ball, game_over, lives
    ball_group.update(ticks, 50)
    # 若球掉下去了,重新将球放到板子上
    if waiting:
        ball.X = paddle.X + 40
        ball.Y = paddle.Y - 20
    ball.X += ball.velocity.x
    ball.Y += ball.velocity.y
    if ball.X < 0:
        ball.X = 0
        ball.velocity.x *= -1
    elif ball.X > 780:
        ball.X = 780
        ball.velocity.x *= -1
    if ball.Y < 0:
        ball.Y = 0
        ball.velocity.y *= -1
    elif ball.Y > 580:
        waiting = True
        lives -= 1
        if lives < 1:
            game_over = True


# 球与板子的冲突检测
def collision_ball_paddle():
    if pygame.sprite.collide_rect(ball, paddle):
        ball.velocity.y = -abs(ball.velocity.y)
        bx = ball.X + 8
        by = ball.Y + 8
        px = paddle.X + paddle.frame_width / 2
        py = paddle.Y + paddle.frame_height / 2
        if bx < px:
            ball.velocity.x = -abs(ball.velocity.x)
        else:
            ball.velocity.x = abs(ball.velocity.x)


# 球与砖块的冲突检测
def collision_ball_blocks():
    global score, block_group, ball
    hit_block = pygame.sprite.spritecollideany(ball, block_group)
    if hit_block:
        score += 10
        block_group.remove(hit_block)
        bx = ball.X + 8
        by = ball.Y + 8

        if bx > hit_block.X + 5 and bx < hit_block.X + hit_block.frame_width - 5:
            if by < hit_block.Y + hit_block.frame_height / 2:
                ball.velocity.y = -abs(ball.velocity.y)
            else:
                ball.velocity.y = abs(ball.velocity.y)
        elif bx < hit_block.X + 5:
            ball.velocity.x = -abs(ball.velocity.x)
        elif bx > hit_block.X + hit_block.frame_width - 5:
            ball.velocity.x = abs(ball.velocity.x)
        else:
            ball.velocity.y *= -1


if __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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270

运行结果如下:
在这里插入图片描述

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

添加颜色的部分如下,首先添加一个颜色的元组:

colors = (
    (0, 0, 0), (0, 100, 50), (50, 50, 50), (100, 100, 100), (200, 200, 200), (150, 200, 255)
)
  • 1
  • 2
  • 3

然后在循环外面申明一个color赋初值:

color = colors[0]
  • 1

最后在循环内部:

if ticks % 50 == 0:
	i = colors.index(color)
    color = colors[(i + 1) % len(colors)]
screen.fill(color)
  • 1
  • 2
  • 3
  • 4

而添加计时功能则如下:

times = 0.0
times = ticks / 1000
print_text(font, 640, 0, "TIME:" + "{:.0f}".format(times) + "s")
  • 1
  • 2
  • 3

因为ticks记录的是毫秒,因此将其转换成秒缩短表示的长度

任务二:每次球撞击板子的时候,球的速度都会随机发生变化,让游戏变得不可预测

这个问题只需要修改一下collision_ball_paddle()函数即可,如下:

# 球与板子的冲突检测
def collision_ball_paddle():
    if pygame.sprite.collide_rect(ball, paddle):
        ball.velocity.y = -abs(random.randint(5, 15))
        bx = ball.X + 8
        by = ball.Y + 8
        px = paddle.X + paddle.frame_width / 2
        py = paddle.Y + paddle.frame_height / 2
        if bx < px:
            ball.velocity.x = -abs(random.randint(5, 15))
        else:
            ball.velocity.x = abs(random.randint(5, 15))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/215818
推荐阅读
  

闽ICP备14008679号