Python008

学习总结八

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()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值