美文网首页
pygame 练手项目

pygame 练手项目

作者: 圣_狒司机 | 来源:发表于2023-03-30 12:45 被阅读0次

几个小孩在屏幕上乱跑的项目,撞人要互相说对不起!


1.005.png

解平对张娟说:对不起!
张娟对解平说:对不起!
王兵对马桂珍说:对不起!
马桂珍对王兵说:对不起!

一、 架构
init.py
play.py : 主入口文件
player.py : 精灵类文件
d61f0565d821438c9b7dcd4f48d5395d.png :人物图片
所有文件全部在一个文件夹内,调用play.py运行游戏。

二、主入口文件 play.py

import pygame
from player import Player,my_group
from rich import print

pygame.init()
screen = pygame.display.set_mode((400,300))
clock,FPS = pygame.time.Clock(),30
running = True
[Player() for _ in range(5)]
step = 0

while running:
    screen.fill((0, 255, 0))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
           running = False
    
    my_group.update()
    my_group.draw(screen)
    pygame.display.flip()
    clock.tick(FPS)
    step += 1
    if step>1000:
        pygame.image.save(screen,f"{step/1000}.png")

pygame.quit()

这是pygame的基本框架,每个pygame项目都会这么写。

if step>1000:
        pygame.image.save(screen,f"{step/1000}.png")

是游戏运行一段时间后自动截屏。

二、 精灵类文件player.py

import pygame
from pygame.sprite import Sprite
from itertools import cycle
import numpy as np
from faker import Faker

faker = Faker("zh_CN")
my_group = pygame.sprite.Group()

def collided(sprite, other):
    return sprite != other and sprite.rect.colliderect(other.rect)

class Player(Sprite):
    img = pygame.image.load("d61f0565d821438c9b7dcd4f48d5395d.png")
    fps_p = 30
    d1 = cycle([img.subsurface((0,0,32,32))]*fps_p+[img.subsurface((32,0,32,32))]*fps_p+[img.subsurface((64,0,32,32))]*fps_p+[img.subsurface((95,0,32,32))]*fps_p)
    d2 = cycle([img.subsurface((0,32,32,32))]*fps_p+[img.subsurface((32,32,32,32))]*fps_p+[img.subsurface((64,32,32,32))]*fps_p+[img.subsurface((95,32,32,32))]*fps_p)
    d3 = cycle([img.subsurface((0,64,32,32))]*fps_p+[img.subsurface((32,64,32,32))]*fps_p+[img.subsurface((64,64,32,32))]*fps_p+[img.subsurface((95,64,32,32))]*fps_p)
    d4 = cycle([img.subsurface((0,95,32,32))]*fps_p+[img.subsurface((32,95,32,32))]*fps_p+[img.subsurface((64,95,32,32))]*fps_p+[img.subsurface((95,95,32,32))]*fps_p)
    image_lib= {"stand":d1,"go_up":d4,"go_left":d2,"go_right":d3,"go_down":d1} 
    speed_lib= {"stand":(0,0),"go_up":(1,-5),"go_left":(-5,-1),"go_right":(5,1),"go_down":(-1,5)}

    def __init__(self):
        self.name = faker.name()
        super().__init__()
        self.state = "stand"
        self.image = self.image_lib[self.state].__next__()
        self.spped = self.speed_lib[self.state]
        self.rect = self.image.get_rect()
        self.rect.center = np.random.randint(0,300,2)
        my_group.add(self)
        self.steps = 0
    
    def update(self):
        self.steps += 1
        keys = pygame.key.get_pressed()
        if keys[pygame.K_RIGHT]:
            self.state = "go_right"
        if keys[pygame.K_LEFT]:
            self.state = "go_left"
        if keys[pygame.K_UP]:
            self.state = "go_up"
        if keys[pygame.K_DOWN]:
            self.state = "go_down"
        if keys[pygame.K_SPACE]:
            self.state = "stand"
        if keys[pygame.K_LCTRL]:
            self.state = np.random.choice(["stand","go_up","go_left","go_right","go_down"],p=np.array([1,3,3,3,3])/np.array([1,3,3,3,3]).sum())
        if self.rect.left <0:
            self.state = np.random.choice(["stand","go_up","go_right","go_down"])
        if self.rect.right >400:
            self.state = np.random.choice(["stand","go_up","go_left","go_down"])
        if self.rect.top <0:
            self.state = np.random.choice(["stand","go_left","go_right","go_down"])
        if self.rect.bottom >300:
            self.state = np.random.choice(["stand","go_up","go_left","go_right"])
        if self.steps>100:
            self.state = np.random.choice(["stand","go_up","go_left","go_right","go_down"])
            self.steps = 0

        self.image = self.image_lib[self.state].__next__()
        self.spped = self.speed_lib[self.state]
        self.rect.move_ip(self.spped)

        col = pygame.sprite.spritecollideany(self, my_group, collided)
        if col:
            print(f"{self.name}对{col.name}说:对不起!")

精灵图:


精灵图是4*4的整合图片,pygame是每帧读取的,把任务动作分解成状态类,['站着','往左','往右','往前','往后'],站着的状态图可以取'往后'。
每个状态用Python的itertools.cycle包裹,cycle的特性是无限循环,每次yield出一张图片,每个状态都有多张图片,cycle最适合pygame每次循环挤出一张图片的场景。
把状态类集合成字典:

d1 = cycle([img.subsurface((0,0,32,32))]*fps_p+[img.subsurface((32,0,32,32))]*fps_p+[img.subsurface((64,0,32,32))]*fps_p+[img.subsurface((95,0,32,32))]*fps_p)
d2 = cycle([img.subsurface((0,32,32,32))]*fps_p+[img.subsurface((32,32,32,32))]*fps_p+[img.subsurface((64,32,32,32))]*fps_p+[img.subsurface((95,32,32,32))]*fps_p)
d3 = cycle([img.subsurface((0,64,32,32))]*fps_p+[img.subsurface((32,64,32,32))]*fps_p+[img.subsurface((64,64,32,32))]*fps_p+[img.subsurface((95,64,32,32))]*fps_p)
d4 = cycle([img.subsurface((0,95,32,32))]*fps_p+[img.subsurface((32,95,32,32))]*fps_p+[img.subsurface((64,95,32,32))]*fps_p+[img.subsurface((95,95,32,32))]*fps_p)
image_lib= {"stand":d1,"go_up":d4,"go_left":d2,"go_right":d3,"go_down":d1} 

fps_p 是放大的循环次数,要是没有放大,每张图片就在每个FPS里面一闪而过,根本看不清。
每张图片的取出方法:先确定当前状态,再挤出一个图片。

self.state = "stand"
self.image = self.image_lib[self.state].__next__()

每个精灵类都要重写update方法,因为没法在精灵类外部获得event事件,它里面有个特殊函数:keys = pygame.key.get_pressed(),获得需要的键盘事件,也可以把事件函数写在主文件里,那样主文件就很大很难看。

三、 碰撞检测

def collided(sprite, other):
    return sprite != other and sprite.rect.colliderect(other.rect)

col = pygame.sprite.spritecollideany(self, my_group, collided)
        if col:
            print(f"{self.name}对{col.name}说:对不起!")

pygame 有很丰富的碰撞检测,可是都无法直接用到本项目里!它自带的检测函数:

方法 说明
collide_rect() 两个精灵之间的矩形检测,即矩形区域是否有交汇,返回一个布尔值。
collide_circle() 两个精灵之间的圆形检测,即圆形区域是否有交汇,返回一个布尔值。
collide_mask() 两个精灵之间的像素蒙版检测,更为精准的一种检测方式。
spritecollide() 精灵和精灵组之间的矩形碰撞检测,一个组内的所有精灵会逐一地对另外一个单个精灵进行碰撞检测,返回值是一个列表,包含了发生碰撞的所有精灵。
spritecollideany() 精灵和精灵组之间的矩形碰撞检测,上述函数的变体,当发生碰撞时,返回组内的一个精灵,无碰撞发生时,返回 None。
groupcollide() 检测在两个组之间发生碰撞的所有精灵,它返回值是一个字典,将第一组中发生碰撞的精灵作为键,第二个组中发生碰撞的精灵作为值。

精灵与组碰撞检测,如果精灵在组内,结果会是精灵与组一直碰撞,调用
pygame.sprite.spritecollideany(self, my_group),返回错误,必须加入回调函数pygame.sprite.spritecollideany(self, my_group, collided),
collided(sprite, other)函数把spritecollideany的前两项做自己的参数,返回弹出精灵的新的组。

相关文章

网友评论

      本文标题:pygame 练手项目

      本文链接:https://www.haomeiwen.com/subject/lqzqddtx.html