学习总结八
pygame小游戏(面向对象)
练习1
五子棋
import pygame
EMPTY = 0
BLACK = 1
WHITE = 2
black_color = [0, 0, 0]
white_color = [255, 255, 255]
class RenjuBoard(object):
def __init__(self):
self._board = [[]] * 15
self.reset()
def reset(self): # 重置棋盘
for row in range(len(self._board)):
self._board[row] = [EMPTY] * 15
def move(self, row, col, is_black): # 下棋
if self._board[row][col] == EMPTY:
self._board[row][col] = BLACK if is_black else WHITE
return True
return False
def draw(self, screen): # 画线和点
for n in range(1, 16):
pygame.draw.line(screen, black_color, [40, n * 40], [600, n * 40], 1)
pygame.draw.line(screen, black_color, [n * 40, 40], [n * 40, 600], 1)
pygame.draw.rect(screen, black_color, [36, 36, 568, 568], 4)
pygame.draw.circle(screen, black_color, [320, 320], 5, 0)
pygame.draw.circle(screen, black_color, [160, 160], 5, 0)
pygame.draw.circle(screen, black_color, [480, 160], 5, 0)
pygame.draw.circle(screen, black_color, [160, 480], 5, 0)
pygame.draw.circle(screen, black_color, [480, 480], 5, 0)
for row in range(len(self._board)):
for col in range(len(self._board[row])):
if self._board[row][col] != EMPTY:
ccolor = black_color \
if self._board[row][col] == BLACK else white_color
pos = [40 * (col + 1), 40 * (row + 1)]
pygame.draw.circle(screen, ccolor, pos, 20, 0)
def main():
board = RenjuBoard()
is_black = True
pygame.init()
pygame.display.set_caption('五子棋') # 窗口命名
screen = pygame.display.set_mode([640, 640]) # 创建窗口尺寸
screen.fill([255, 255, 0]) # 窗口填充颜色
board.draw(screen) # 调用draw行为画线与点
pygame.display.flip() # 刷新窗口
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: # event.button表示点击鼠标左键
x, y = event.pos
row = round((y - 40) / 40) # round表示四舍五入,判断落子在哪一行
col = round((x - 40) / 40) # 判断落子在哪一列
if board.move(row, col, is_black):
is_black = not is_black # 表示判断下的是黑棋还是白棋,并保存到列表中
screen.fill([255, 255, 0]) # 窗口填色
board.draw(screen) # 调用draw行为画线和点
pygame.display.flip() # 刷新窗口
pygame.quit()
if __name__ == '__main__':
main()
练习2
大球吃小球
from random import randint
from math import sqrt
import pygame
class Ball(object):
def __init__(self, x, y, color, radius, sx, sy): # x,y小球的坐标/color颜色/半径/sx,sy表示移动的距离
self._x = x
self._y = y
self._color = color
self._radius = radius
self._sx = sx
self._sy = sy
def move(self):
self._x += self._sx
self._y += self._sy
if self._x + self._radius >= 800 or self._x - self._radius <= 0:
self._sx = -self._sx
if self._y + self._radius >= 600 or self._y - self._radius <= 0:
self._sy = -self._sy
def eat(self, other):
if self._radius > other._radius and \
sqrt((self._x - other._x) ** 2 + (self._y - other._y) ** 2) < self._radius + other._radius:
self._radius += 10
other._radius = 0
# return self._radius, other._radius
elif self._radius < other._radius and \
sqrt((self._x - other._x) ** 2 + (self._y - other._y) ** 2) < self._radius + other._radius:
other._radius += 10
self._radius = 0
# return self._radius, other._radius
def draw(self, screen):
pygame.draw.circle(screen, self._color, (self._x, self._y), self._radius, 0) # 画圆(窗口,颜色,位置,半径,填充颜色)
def main():
balls = []
pygame.init()
screen = pygame.display.set_mode((800, 600)) # 建窗口尺寸
pygame.display.set_caption('大球吃小球')
clock = pygame.time.Clock() # 创建了一个计时器
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT: # 表示点关闭窗口按钮
running = False
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
x, y = event.pos # 鼠标点击的位置坐标
color = random_color() # 调用随机取色方法
radius = randint(10, 100)
sx, sy = randint(-10, 10), randint(-10, 10)
ball = Ball(x, y, color, radius, sx, sy)
balls.append(ball)
for num1 in range(len(balls)):
for num2 in range(len(balls)):
balls[num1].eat(balls[num2]) # 调用eat行为
for ball in balls:
if ball._radius == 0:
balls.remove(ball)
# if balls[num1]._radius == 0:
# balls.remove(balls[num1])
# elif balls[num2]._radius == 0:
# balls.remove(balls[num2])
refresh(screen, balls)
clock.tick(24)
for ball in balls:
ball.move()
pygame.quit()
def refresh(screen, balls):
bg_color = (242, 242, 242)
screen.fill(bg_color) # 填充背景颜色(循环填充背景颜色可以消除球的阴影)
for ball in balls:
ball.draw(screen)
pygame.display.flip() # 刷新窗口
def random_color(): # 随机取色
red = randint(0, 255)
green = randint(0, 255)
blue = randint(0, 255)
return red, green, blue
if __name__ == '__main__':
main()
贪吃蛇
from abc import ABCMeta, abstractmethod
from random import randint
import pygame
BLACK_COLOR = (0, 0, 0)
FOOD_COLOR = (230, 185, 185)
GREEN_COLOR = (0, 255, 0)
UP = 0
RIGHT = 1
DOWN = 2
LEFT = 3 # 一定要按照顺时针或者逆时针的方向
class GameObject(object, metaclass=ABCMeta): # 抽象类
def __init__(self, x, y, color):
self._x = x
self._y = y
self._color = color
@property
def x(self):
return self._x
@property
def y(self):
return self._y
@abstractmethod # 定义抽象行为,后面子类必须写
def draw(self, screen):
pass
class Wall(GameObject): # 定义围墙
def __init__(self, x, y, width, height, color=BLACK_COLOR):
super().__init__(x, y, color)
self._width = width
self._height = height
@property
def width(self):
return self._width
@property
def height(self):
return self._height
def draw(self, screen): # 画围墙的行为
pygame.draw.rect(screen, self._color, (self._x, self._y, self._width, self._height), 4) # rect表示画矩形
class Food(GameObject): # 定义食物
def __init__(self, x, y, size, color=FOOD_COLOR):
super().__init__(x, y, color)
self._size = size
self._hidden = False # 定义隐藏食物为假
def draw(self, screen): # 画食物的行为
if not self._hidden: # 隐藏食物为真,画出食物
pygame.draw.circle(screen, self._color,
(self._x + self._size // 2, self._y + self._size // 2), self._size // 2, 0)
self._hidden = not self._hidden # 隐藏食物为真
class SnakeNode(GameObject): # 蛇的节点
def __init__(self, x, y, size, color=GREEN_COLOR):
super().__init__(x, y, color)
self._size = size
@property
def size(self):
return self._size
def draw(self, screen): # 画出节点
pygame.draw.rect(screen, self._color, (self._x, self._y, self._size, self._size), 0) # 节点
pygame.draw.rect(screen, BLACK_COLOR, (self._x, self._y, self._size, self._size), 1) # 节点黑框
class Snake(GameObject): # 定义蛇由若干节点组成
def __init__(self):
super().__init__(290, 250, GREEN_COLOR) # 默认蛇的初始坐标及颜色
self._dir = LEFT # 蛇的方向(dir表示方向)
self._nodes = [] # 节点列表
self._eat_food = False # 吃食物
for index in range(5):
node = SnakeNode(self._x + index * 20, self._y, 20) # 节点
self._nodes.append(node)
@property
def dir(self):
return self._dir
def change_dir(self, new_dir): # 改变蛇的方向得到新方向
if (self._dir + new_dir) % 2 != 0: # 方向之和不是偶数
self._dir = new_dir
def move(self): # 蛇移动
head = self._nodes[0] # 蛇头
snake_dir = self._dir
x, y, size = head.x, head.y, head.size
if snake_dir == UP:
y -= size
elif snake_dir == RIGHT:
x += size
elif snake_dir == DOWN:
y += size
else:
x -= size
new_head = SnakeNode(x, y, size)
self._nodes.insert(0, new_head) # insert插入(在最前面插入新的头)
if self._eat_food:
self._eat_food = False
else:
self._nodes.pop() # 删掉最后一个节点
def collide(self, wall): # 撞墙
head = self._nodes[0]
return head.x < wall.x or head.x + head.size > wall.x + wall.width\
or head.y < wall.y or head.y + head.size > wall.y + wall.height
def eat_food(self, food): # 判断是否吃到食物
head = self._nodes[0]
if head.x == food.x and head.y == food.y:
self._eat_food = True
return True
return False
def eat_me(self): # 判断是否吃到自己
head = self._nodes[0]
for n in self._nodes[1:]:
if head.x == n.x and head.y == n.y:
return True
def draw(self, screen): # 在窗口画出蛇
for node in self._nodes:
node.draw(screen)
def main():
def refresh(): # 定义函数,嵌套作用域(嵌套函数)
screen.fill((242, 242, 242))
wall.draw(screen)
food.draw(screen)
snake.draw(screen)
pygame.display.flip()
def handle_key_event(key_event): # 接收按键处理事件
key = event.key
# new_dir = snake.dir
if key == pygame.K_w:
new_dir = UP
elif key == pygame.K_d:
new_dir = RIGHT
elif key == pygame.K_s:
new_dir = DOWN
elif key == pygame.K_a:
new_dir = LEFT
elif key == pygame.K_F2:
reset_game()
return
else:
return
if new_dir != snake.dir:
snake.change_dir(new_dir)
def create_food(): # 随机创建食物
row = randint(0, 29)
col = randint(0, 29)
return Food(10 + 20 * col, 10 + 20 * row, 20)
def reset_game(): # 重新开始游戏
nonlocal food, snake, game_over
game_over = False
food = create_food()
snake = Snake()
pygame.event.clear()
wall = Wall(10, 10, 600, 600)
food = create_food()
snake = Snake()
pygame.init()
screen = pygame.display.set_mode((620, 620))
pygame.display.set_caption('贪吃蛇')
screen.fill((242, 242, 242))
pygame.display.flip() # 刷新屏幕
clock = pygame.time.Clock() # 计时器
running = True
game_over = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN: # 按下键
handle_key_event(event)
if not game_over:
refresh()
clock.tick(5)
snake.move()
if snake.eat_food(food):
food = create_food()
if snake.collide(wall):
game_over = True
if snake.eat_me():
game_over = True
pygame.quit()
if __name__ == '__main__':
main()