游戏截图
游戏源码
写的一个小游戏,欢迎大家指正。这里使用了pygame的sprite类。碰撞检测使用的是pygame自带的像素级的碰撞检测(pg.sprite.collide_mask)。使用这个碰撞,那么在Sprite类的里,必须要定义一个self.mask。
这里就是一个最基础版的,没有做后续的美化什么的。就是供大家匹配指正。
import pygame as pg
from pygame.locals import *
import sys
import random
class BreakTheBricks:
# 设置窗口尺寸
WINDOW_WIDTH = 1024
WINDOW_HEIGHT = 768
# 设置刷新率
FPS = 30
def __init__(self):
pg.init()
self.DISPLAY_SURFACE = pg.display.set_mode((self.WINDOW_WIDTH, self.WINDOW_HEIGHT))
self.DISPLAY_CLOCK = pg.time.Clock()
self.main()
def main(self):
pg.display.set_caption("打砖块")
# 创建精灵组
ball_group = pg.sprite.LayeredDirty()
brick_group = pg.sprite.LayeredDirty()
board_group = pg.sprite.LayeredDirty()
# 添加砖块
x_num_for_brick = int(BreakTheBricks.WINDOW_WIDTH / self.Brick.BRICK_WIDTH)
y_num_for_brick = int((BreakTheBricks.WINDOW_HEIGHT / self.Brick.BRICK_HEIGHT) / 3)
for brick_x in range(x_num_for_brick):
for brick_y in range(y_num_for_brick):
brick = self.Brick(brick_x, brick_y)
brick_group.add(brick)
# 添加球拍
board = self.Board()
board_group.add(board)
# 添加小球
for i in range(1):
ball = self.Ball(board.rect.centerx, board.rect.top + self.Ball.BALL_RADIUS)
ball_group.add(ball)
while True:
self.DISPLAY_SURFACE.fill((245, 245, 245))
self.check_for_quit()
keys = pg.key.get_pressed()
if keys[K_LEFT]:
board_group.get_sprite(0).move("left")
elif keys[K_RIGHT]:
board_group.get_sprite(0).move("right")
# 小球精灵组
ball_group.draw(self.DISPLAY_SURFACE)
ball_group.update()
# 砖块精灵组
brick_group.draw(self.DISPLAY_SURFACE)
# 球拍精灵组
board_group.draw(self.DISPLAY_SURFACE)
# 碰撞检测
# 碰撞砖块
collided_bricks = pg.sprite.groupcollide(ball_group, brick_group, False, True, pg.sprite.collide_mask)
for col_ball, col_bricks in collided_bricks.items():
col_ball.collide_brick(col_bricks)
# 碰撞球拍
collided_board = pg.sprite.groupcollide(ball_group, board_group, False, False, pg.sprite.collide_mask)
for col_ball, col_board in collided_board.items():
col_ball.collide_board(col_board[0])
pg.display.update()
self.DISPLAY_CLOCK.tick(self.FPS)
def check_for_quit(self):
for event in pg.event.get():
if event.type == QUIT:
self.terminate()
if event.type == KEYUP:
if event.key == K_ESCAPE:
self.terminate()
@staticmethod
def terminate():
pg.quit()
sys.exit()
class Ball(pg.sprite.DirtySprite):
"""
精灵--小球
"""
UPLEFT = "upleft"
UPRIGHT = "upright"
DOWNLEFT = "downleft"
DOWNRIGHT = 'downright'
# 设置小球的半径
BALL_RADIUS = 6
# 小球的颜色
BALL_COLOR = (255, 0, 0)
# 小球的初始移动速度
BALL_SPEED = 8
def __init__(self, top, left):
super().__init__()
self.image = pg.Surface((self.BALL_RADIUS * 2, self.BALL_RADIUS * 2))
self.image.fill((0, 0, 0))
self.image.set_colorkey((0, 0, 0))
pg.draw.circle(self.image, self.BALL_COLOR, (self.BALL_RADIUS, self.BALL_RADIUS), self.BALL_RADIUS)
self.rect = self.image.get_rect(center=(top, left))
self.x_speed = self.BALL_SPEED
self.y_speed = self.BALL_SPEED
self.direction = self.UPRIGHT
self.mask = pg.mask.from_surface(self.image)
def update(self):
# 小球的行进方向
if self.direction == self.UPLEFT:
if self.rect.top <= 0:
self.direction = self.DOWNLEFT
elif self.rect.left <= 0:
self.direction = self.UPRIGHT
else:
self.rect.move_ip(-self.x_speed, -self.y_speed)
elif self.direction == self.UPRIGHT:
if self.rect.top <= 0:
self.direction = self.DOWNRIGHT
elif self.rect.right >= BreakTheBricks.WINDOW_WIDTH:
self.direction = self.UPLEFT
else:
self.rect.move_ip(self.x_speed, -self.y_speed)
elif self.direction == self.DOWNLEFT:
if self.rect.top >= BreakTheBricks.WINDOW_HEIGHT:
self.kill()
elif self.rect.left <= 0:
self.direction = self.DOWNRIGHT
else:
self.rect.move_ip(-self.x_speed, self.y_speed)
elif self.direction == self.DOWNRIGHT:
if self.rect.top >= BreakTheBricks.WINDOW_HEIGHT:
self.kill()
elif self.rect.right >= BreakTheBricks.WINDOW_WIDTH:
self.direction = self.DOWNLEFT
else:
self.rect.move_ip(self.x_speed, self.y_speed)
self.dirty = 1
def collide_brick(self, sprites):
for sprite in sprites[-1:]:
# 小球 左下 运动
if self.direction == self.DOWNLEFT:
if self.rect.centerx < sprite.rect.right:
self.direction = self.UPLEFT
elif sprite.rect.top < self.rect.centery:
self.direction = self.DOWNRIGHT
else:
self.direction = self.UPRIGHT
# 小球 右下 运动
elif self.direction == self.DOWNRIGHT:
if sprite.rect.left < self.rect.centerx:
self.direction = self.UPRIGHT
elif sprite.rect.top< self.rect.centery:
self.direction = self.DOWNLEFT
else:
self.direction = self.UPLEFT
# 小球 左上 运动
elif self.direction == self.UPLEFT:
if self.rect.centerx < sprite.rect.right:
self.direction = self.DOWNLEFT
elif self.rect.centery < sprite.rect.bottom:
self.direction = self.UPRIGHT
else:
self.direction = self.DOWNRIGHT
# 小球 右上 运动
elif self.direction == self.UPRIGHT:
if sprite.rect.left< self.rect.centerx:
self.direction = self.DOWNRIGHT
elif self.rect.centery < sprite.rect.bottom:
self.direction = self.UPLEFT
else:
self.direction = self.DOWNLEFT
def collide_board(self, sprite):
# 小球 左下 运动
if self.direction == self.DOWNLEFT:
if self.rect.centerx < sprite.rect.right:
self.direction = self.UPLEFT
elif sprite.rect.top < self.rect.centery:
self.direction = self.UPRIGHT
# 小球 右下 运动
elif self.direction == self.DOWNRIGHT:
if sprite.rect.left < self.rect.centerx:
self.direction = self.UPRIGHT
elif sprite.rect.top < self.rect.centery:
self.direction = self.UPLEFT
class Brick(pg.sprite.DirtySprite):
# 砖块颜色
ALL_COLORS = ((255, 215, 0), (0, 255, 255), (255, 128, 0), (127, 255, 0), (160, 32, 240),(255, 99, 71))
# 砖块尺寸
BRICK_WIDTH = 32
BRICK_HEIGHT = 16
# 砖块边框尺寸
BRICK_BORDER = 1
BRICK_BORDER_COLOR = (0, 0, 0)
def __init__(self, brick_x, brick_y):
super().__init__()
self.image = pg.Surface((self.BRICK_WIDTH, self.BRICK_HEIGHT))
self.image.fill(self.BRICK_BORDER_COLOR)
pg.draw.rect(self.image, random.choice(self.ALL_COLORS), (self.BRICK_BORDER, self.BRICK_BORDER, self.BRICK_WIDTH - self.BRICK_BORDER * 2, self.BRICK_HEIGHT - self.BRICK_BORDER * 2))
self.rect = self.image.get_rect()
self.set_topleft(brick_x, brick_y)
self.dirty = 2
self.mask = pg.mask.from_surface(self.image)
def set_topleft(self, brick_x, brick_y):
top = brick_x * self.BRICK_WIDTH
left = brick_y * self.BRICK_HEIGHT
self.rect.topleft = (top, left)
class Board(pg.sprite.DirtySprite):
BOARD_HEIGHT = 20
BOARD_COLOR = (128, 255, 255)
def __init__(self):
super().__init__()
self.__board_width = 100
self.image = pg.Surface((self.__board_width, self.BOARD_HEIGHT))
self.image.fill(self.BOARD_COLOR)
self.__BOARD_Y = BreakTheBricks.WINDOW_HEIGHT / 5 * 4 # 球拍在屏幕上的位置
self.mask = pg.mask.from_surface(self.image)
self.rect = self.image.get_rect()
self.rect.center = (BreakTheBricks.WINDOW_WIDTH / 2, self.__BOARD_Y)
self.dirty = 2
self.__speed = 15
def move(self, direction):
"""
球拍移动
:param direction: 移动的方向 “left” 或者 “right” 需要输入字符串,注意不要输入错误
:return:
"""
if direction == "left" and self.rect.left >= 0:
self.rect.left -= self.__speed
elif direction == "right" and self.rect.right <= BreakTheBricks.WINDOW_WIDTH:
self.rect.right += self.__speed
if __name__ == '__main__':
breaked = BreakTheBricks()