pygame笔记

直接去看英文官方文档了:Pygame Front Page — pygame v2.6.0 documentation

以及pygame4000:

https://gitcode.com/open-source-toolkit/a4796/?utm_source=tools_gitcode&index=top&type=card&&isLogin=1

这是学习版连接,等以后有钱了,一定会补票的!!!

顺便(主要)锻炼一下英语能力。

这个笔记要记录什么呢?

大概就例子加代码吧,把官方文档从英文转为中文再加上一些我的自己的理解和遇到的坑.

不过这种东西我找到的就有很多,多我一个不多,少我一个不少,就随心记一记吧。

总而言是就是我怎么学的就怎么记,看到哪里有价值的往上写。

1.第一个程序

这个是根据pygame 4000 book 写的,感觉比较由浅入深。

1.导入库:

import pygame, sys,os
from pygame.locals import *

2.初始化:

pygame.init()

此函数的作用是将导入的pygame模块全部初始化,比较方便

3.设置游戏窗口:

window = pygame.display.set_mode((720,480))

这个是你游戏的窗口大小,前面是宽,后面是高

!!!里面的是个元组,而不是一个数

4.设置标题:

pygame.display.set_caption("漫宿骄盛的例子")

括号里面的就是游戏上面的标题了

5.获取画布:

screen = pygame.display.get_surface()

pygame.display.get_surface()函数用于获取当前显示的Surface对象。Surface是Pygame中的一个基本概念,可以理解为一个可以在其上绘制图像、形状或文本的画布。

6.获取资源地址:

main_dir = os.path.split(os.path.abspath(__file__))[0]
pic_dir = os.path.join(main_dir,'pic')

这两步的作用可以我的写的另一篇笔记:python库的常用函数1--4

7.加载图片资源:

monkey_pic = os.path.join(pic_dir,'chimp.bmp')
monkey_surface = pygame.image.load(monkey_pic)
screen.blit(monkey_surface,(0,0))
pygame.display.flip()

第一步的作用是获取名为"chimp.bmp"的图片地址

第二步 pygame.image.load()的作用是创建一个对象,用来加载这张图片

第三步screen.blit()的作用是设置monkey_surface的初始位置为0,0

第四步pygame.display.flip()的作用是刷新,告诉pygame 你已经将你要展示的图片弄好了,可以展出了

这个应该可以自定义一个函数完成上面的所有的东西,不过这就是第一个程序,就不弄那么多东西了。

8.设置退出事件:

def input(events):
    for event in events:
        if event.type == QUIT:
            sys.exit(0)

这个的作用是让你点右上角的X号能直接退出程序

9.运行程序:

while True:
    input(pygame.event.get())

pygame.event.get()的作用是时刻获取你的操作,从而能实现各种功能

10.完整代码:

import pygame,os,sys
from pygame.locals import *
pygame.init()
window = pygame.display.set_mode((720,480))
pygame.display.set_caption("漫宿骄盛的例子")
screen = pygame.display.get_surface()
main_dir = os.path.split(os.path.abspath(__file__))[0]
pic_dir = os.path.join(main_dir,'pic')
monkey_pic = os.path.join(pic_dir,'chimp.bmp')
monkey_surface = pygame.image.load(monkey_pic)
screen.blit(monkey_surface,(0,0))
pygame.display.flip()
def input(events):
    for event in events:
        if event.type == QUIT:
            sys.exit(0)
while True:
    input(pygame.event.get())

结果:

给的图片的实在有点小,后面应该会有设置图片尺寸的东西,点右上角的X号也能直接退出

第一个程序的使命达成了

作业练习:

没想到还有作业,这些也没有放到主要的内容上来,我还以为是一步一步的教所有的东西……

不会啊,先继续往下面看,回过头来再完成。

1.让图片移动:

我自己写了一个代码,然后让AI帮我看看,给我重构了一下,真是赏心悦目,比我写的屎好看多了

import pygame,os,sys
from pygame.locals import *

CONFIG={
    'screen_size':(720,720),
    'background_color':(250,250,250),
    'fps':60,
    'chimp_speed':8,
    'chimp_image':'chimp.bmp',
    'colorkey':-1,
}
def load_pic(name,colorkey=None):
    fullname = os.path.join(CONFIG['pic_dir'],name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error:
        print('Cannot load image:',fullname)
        raise SystemExit
    image = image.convert()
    if colorkey is not None:
        if colorkey == -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey,RLEACCEL)
    return image,image.get_rect()
class Chimp(pygame.sprite.Sprite):
    def __init__(self,image_path,colorkey=None,speed =8):
        pygame.sprite.Sprite.__init__(self)
        self.image,self.rect = load_pic(image_path,colorkey)
        self.speed = speed
def game_init():
    pygame.init()
    window = pygame.display.set_mode(CONFIG['screen_size'])
    pygame.display.set_caption("漫宿骄盛的例子")
    background = pygame.Surface(window.get_size())
    background = background.convert()
    background.fill(CONFIG['background_color'])     
    
    return window,background
def handle_events(run):
    for event in pygame.event.get():
        if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
            run = False
    return run
def updata_chimp(chimp):
    keys = pygame.key.get_pressed()
    chimp.rect.x += (keys[K_d] - keys[K_a])* chimp.speed
    chimp.rect.y += (keys[K_s] - keys[K_w])* chimp.speed
    chimp.rect.clamp_ip(window.get_rect())
def main():
    global window,background,CONFIG
    main_dir = os.path.split(os.path.abspath(__file__))[0]
    CONFIG['pic_dir'] = os.path.join(main_dir,'pic')
    CONFIG['font_dir'] = os.path.join(main_dir,'font')
    
    window,background = game_init()
    chimp = Chimp(CONFIG['chimp_image'],CONFIG['colorkey'],CONFIG['chimp_speed'])
    all_sprites = pygame.sprite.RenderPlain((chimp,))
    clock = pygame.time.Clock()
    
    run = True
    while run:
        clock.tick(CONFIG['fps'])
        run = handle_events(run)
        updata_chimp(chimp)
        window.blit(background,(0,0))
        all_sprites.draw(window)
        pygame.display.flip()
    
    pygame.quit()
    sys.exit()

if __name__ == '__main__':
    main()

其实应该不用那么长的代码,但我就是想练习一下面向对象编程,还有规范的写代码,就这样弄了。


练习2,按任意退出:

def handle_events(run):
    for event in pygame.event.get():
        if event.type == QUIT or event.type == KEYDOWN:
            run = False
    return run

练习3,获取图片大小:

image_width,image_height = image.get_size()
print("size{}*{}".format(image_width,image_height))

练习4,按按键是图片移动到指定位置:

class Chimp(pygame.sprite.Sprite):
    def __init__(self,image_path,colorkey=None,speed =8):
        pygame.sprite.Sprite.__init__(self)
        self.image,self.rect = load_pic(image_path,colorkey)
        self.speed = speed
        self.initial_position = self.rect.topleft
    def reset(self,new_position):##添加此处
        self.rect.topleft = new_position
def handle_events(run,chimp):
    for event in pygame.event.get():
        if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
            run = False##添加之下代码
        elif event.type== KEYDOWN and event.key == K_KP5:
            chimp.reset((110,100))
        elif event.type== KEYDOWN and event.key == K_KP4:
            chimp.reset((0,0))
    return run

2.第二个程序.Chimp Tutorial, Line by Line(卷毛狒狒也能学会的教程)

Pygame Tutorials - Line By Line Chimp Example — pygame v2.6.0 documentation

这个在pygame 4000 上比较详细,我就用pygame 4000那个版本的了.

这个例子会一步一步教去做一个打猴子得金币的游戏?

0.导入库:

这一步的作用是获取文件地址,方便后续对文件的操作

import os
import pygame as pg
#检查pygame的字体文件
if not pg.font:
    print("Warning, fonts disabled")
#检查pygame的音频文件
if not pg.mixer:
    print("Warning, sound disabled")

main_dir = os.path.split(os.path.abspath(__file__))[0]
pic_dir = os.path.join(main_dir, "pic")
sound_dir = os.path.join(main_dir,'sound')
font_dir = os.path.join(main_dir,'font')

1.创建加载图片的函数:

#加载图片
def load_pic(name,colorkey=None):
    fullname = os.path.join(pic_dir,name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error:
        print('Cannot load image:',fullname)
        raise SystemExit
    image = image.convert()
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey,RLEACCEL)
    return image,image.get_rect()

image.convert()是一个优化性能的函数

    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey,RLEACCEL)

这个的作用是根据colorkey的数组来设置图片的透明度

2.创建加载声音的函数:

#加载音效
def load_sound(name):
    class NoneSound:
        def play(self): pass
    if not pygame.mixer:
        return NoneSound()
    fullname = os.path.join(sound_dir,name)
    try:
        sound = pygame.mixer.Sound(fullname)
    except pygame.error:
        print("Cannot load sound:",fullname)
        raise SystemExit
    return sound    

对照一下加载图片的函数:

pygame.mixer.Sound()这个应该是加载声音的函数

这个函数先检查pygame.mixer是否被正确加载(不过好像最开始就已经检测过了,这里应该作者的疏忽)

然后再尝试加载声音

3.游戏逻辑:

直接就到这里来了,但关于pygame的函数好多我都一无所知,我应该先去完成作业再来的,算了,等我理解这些逻辑再去完成上面的练习作业吧。

不过看的人应该能看到我完成的作业,应该能很好的理解下面的内容。

拳头的逻辑

lass Fist(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image,self.rect = load_pic('fist.bmp',-1)
        self.punching =0
    def update(self):
        pos = pygame.mouse.get_pos()
        self.rect.midtop = pos
        if self.punching:
            self.rect.move_ip(5,10)
    def punch(self,target):
        if not self.punching:
            self.punching =1
            hitbox = self.rect.inflate(-5,-5)
            return hitbox.colliderect(target.rect)
    def unpunch(self):
        self.punching =0

self.rect中的rect是一种属性,用于控制位置,检测碰撞等等

pygame.mouse.get_pos()是获取鼠标位置

self.rect.midtop是设置self的矩形中心的位置

self.rect.move_ip(5,10)用了move_ip方法,向X轴移动5个像素,向Y轴移动10个像素.

self.rect.inflate(-5,-5)使用了inflate方法,这个的作用是将图片横向纵向加上这个数值,-5,就是缩小

hitbox.colliderect(target.rect)这个调用了colliderect()方法,检查hitboxtarget.rect是否有体积碰撞。

__init__函数初始化了图片

update函数让拳头中心一直在鼠标上

punch函数检查是否处于打击状态,如果否,就调小碰撞体积,然后检测是否碰撞,

unpunch函数用来结束打击,使拳头回到正常

卷毛狒狒的逻辑

class Chimp(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image,self.rect = load_pic('chimp.bmp',-1)
        screen = pygame.display.get_surface()
        self.area = screen.get_rect()
        self.rect.topleft = (10,10)
        self.move = 9
        self.dizzy =0
    def update(self):
        if self.dizzy:
            self._spin()
        else:
            self._walk()
    def _walk(self):
        newpos = self.move((self.move),0)
        if self.rect.left <self.area.left or self.rect.right >self.area.right:
            self.move = -self.move
            newpos = self.rect.move((self.move,0))
            self.image = pygame.transform.flip(self.image,1,0)
        self.rect = newpos
    def _spin(self):
        center = self.rect.center
        self.dizzy = self.dizzy +12
        if self.dizzy >=360:
            self.dizzy =0
            self.image = self.original
        else:
            rotate =pygame.transform.rotate
            self.image = rotate(self.original,self.dizzy)
        self.rect = self.image.get_rect()
        self.rect.center = center
    def punched(self):
        if not self.dizzy:
            self.dizzy =1
            self.original =self.image

__init__函数中,初始化了资源,通过

screen = pygame.display.get_surface()#获取屏幕状态

self.area = screen.get_rect()#获取屏幕大小

这两个获取了窗口的大小,为后续移动做准备

self.rect.topleft = (10,10)将图片的左上角设置在10,10位置

self.move = 9,设置图片的移动速度为9像素/步,应该默认向右

self.dizzy =0初始化状态为没有旋转


updata 函数中根据猩猩是否旋转而判断采取哪种方法


_walk方法中检查是否超出屏幕,如果超出,则创建一个新对象,让其移动方向相反

pygame.transform.flip(self.image,1,0)这个是让图片反转,第一个参数是图片,第二个参数是判断是否垂直翻转,第二个是是否水平翻转。1是,0否


_spin方法,self.rect.center记录图片中心点,然后判断图片是否翻转,如果是,这恢复原来状态,否则就根据角度旋转图片

rotate =pygame.transform.rotate这一步其实是没用的……作者说这一步的作用其实是让代码看起来更美观……

注意,每次旋转后,图片的画质会下降,也会导致图片的大小发生改变

4.初始化其他

pygame.init()
screen = pygame.display.set_mode((468,60))
pygame.display.set_caption("攻击狒狒")
pygame.mouse.set_visible(0)

这个就不解释了

5.设置屏幕

background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250,250,250))

pygame.Surface(screen.get_size())设置一个和窗口大小相同的背景

background.fill((250,250,250))颜色设为灰色

6.准备让屏幕上显示字

if pygame.font:
    text = os.path.join(font_dir,'msyh.ttc')
    font = pygame.font.Font(text,50)
    text = font.render("击狒得¥¥",1,(10,10,10))
    textpos =text.get_rect()
    textpos.centerx = background.get_rect().centerx
    background.blit(text,textpos)

text = os.path.join(font_dir,'msyh.ttc')这一行是获取字体路径,我想打中文,所以要有,用到是微软雅黑,如果是默认字体那么打出的汉字会是一个方块,无法正常显示。

pygame.font.Font(text,50)第一个text是设置字体,None就是默认,50是字的大小

font.render("击狒得¥¥",1,(10,10,10)) 1是判断是否开启拒斥,后面那个元组是颜色

textpos =text.get_rect()这是获取文字的大小,位置,颜色等信息

background.blit(text,textpos)这个是在textpos位置打出来文字

7.将上述准备展现:

screen.blit(background,(0,0))
pygame.display.flip()

screen.blit(background,(0,0))这个是将之前准备好的background放到0,0位置,也就是将整个屏幕设置为之前给其的颜色

pygame.display.flip() 刷新屏幕,展现之前所有的准备,在pygame中,所有的改变不会立刻可见,需要通过这个函数刷新才行。

结果:

8.准备游戏操作:

whiff_sound = load_sound('whiff.wav')
punch_sound = load_sound('punch.wav')
chimp =Chimp()
fist =Fist()
allsprites = pygame.sprite.RenderPlain((fist,chimp))
clock = pygame.time.Clock()

whiff_sound = load_sound('whiff.wav')加载声音文件

allsprites = pygame.sprite.RenderPlain((fist,chimp))创建一个精灵组,并将fist与chimp加入其中,RenderPlain 是精灵组的容器,用来批量管理精灵

clock = pygame.time.Clock()设置对帧率的对象

9.处理事件:

def main():
    events = pygame.event.get()
    for event in events:
        if event.type ==QUIT:
            sys.exit()
        elif event.type == KEYDOWN and event.key == K_ESCAPE:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:
            if fist.punch(chimp):
                punch_sound.play()
                chimp.punched()
            else:
                whiff_sound.play()
        elif event.type == MOUSEBUTTONUP:
            fist.unpunch()
    allsprites.update()    
    screen.blit(background, (0, 0))
    allsprites.draw(screen)
    pygame.display.flip()
           
while True:
    clock.tick(60)
    main()

剩下的我一股脑的全部列出来了

突然发现AI的注释很好用,我就直接用AI的了


def main():
    # 获取当前帧的所有事件(鼠标、键盘等输入)
    events = pygame.event.get()
    
    # 遍历本帧发生的所有事件
    for event in events:
        # 处理窗口关闭事件(点击X按钮)
        if event.type == QUIT:
            sys.exit()  # 退出游戏
            
        # 处理键盘按下事件(实际代码有误,正确写法见下方说明)
        elif event.type == KEYDOWN and event.type == K_ESCAPE:
            sys.exit()  # 按ESC键退出游戏
            
        # 处理鼠标按下事件(任何鼠标按键)
        elif event.type == MOUSEBUTTONDOWN:
            # 检测拳头是否击中黑猩猩
            if fist.punch(chimp):
                punch_sound.play()  # 播放击中音效
                chimp.punched()     # 触发黑猩猩被击中的动画/状态
            else:
                whiff_sound.play()  # 播放挥空音效
                
        # 处理鼠标松开事件
        elif event.type == MOUSEBUTTONUP:
            fist.unpunch()  # 重置拳头状态为未出拳
    
    # 更新所有精灵状态(位置、动画帧等)
    allsprites.update()    
    
    # 绘制背景(将背景图像覆盖整个屏幕)
    screen.blit(background, (0, 0))
    
    # 绘制所有精灵到屏幕(自动调用每个精灵的draw方法)
    allsprites.draw(screen)
    
    # 更新屏幕显示(将内存中的画面推送到实际显示器)
    pygame.display.flip()
# 主游戏循环
while True:
    clock.tick(60)  # 控制游戏帧率,确保每秒不超过60帧
    main()          # 每帧执行一次main函数

10.完整代码:

import pygame,os,sys
from pygame.locals import *
#获取资源地址
main_dir = os.path.split(os.path.abspath(__file__))[0]
pic_dir = os.path.join(main_dir,'pic')
sound_dir = os.path.join(main_dir,'sound')
font_dir = os.path.join(main_dir,'font')
#加载图片
def load_pic(name,colorkey=None):
    fullname = os.path.join(pic_dir,name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error:
        print('Cannot load image:',fullname)
        raise SystemExit
    image = image.convert()
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey,RLEACCEL)
    return image,image.get_rect()
#加载音效
def load_sound(name):
    class NoneSound:
        def play(self): pass
    if not pygame.mixer:
        return NoneSound()
    fullname = os.path.join(sound_dir,name)
    try:
        sound = pygame.mixer.Sound(fullname)
    except pygame.error:
        print("Cannot load sound:",fullname)
        raise SystemExit
    return sound    
class Fist(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)#初始化sprite.Sprite
        self.image,self.rect = load_pic('fist.bmp',-1)#加载图片
        self.punching =0
    def update(self):
        pos = pygame.mouse.get_pos()#获取鼠标位置
        self.rect.midtop = pos#让图片中心始终在鼠标位置
        if self.punching:#如果打中
            self.rect.move_ip(5,10)#图片向右移动,模拟动画
    def punch(self,target):
        #返回真,如果打中
        if not self.punching:
            self.punching =1
            hitbox = self.rect.inflate(-5,-5)
            return hitbox.colliderect(target.rect)
    def unpunch(self):
        #结束动作
        self.punching =0
class Chimp(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image,self.rect = load_pic('chimp.bmp',-1)
        screen = pygame.display.get_surface()
        self.area = screen.get_rect()
        self.rect.topleft = (10,10)
        self.move = 9
        self.dizzy =0
    def update(self):
        if self.dizzy:
            self._spin()
        else:
            self._walk()
    def _walk(self):
        newpos = self.rect.move((self.move,0))
        if self.rect.left <self.area.left or self.rect.right >self.area.right:
            self.move = -self.move
            newpos = self.rect.move((self.move,0))
            self.image = pygame.transform.flip(self.image,1,0)
        self.rect = newpos
    def _spin(self):
        center = self.rect.center
        self.dizzy = self.dizzy +12
        if self.dizzy >=360:
            self.dizzy =0
            self.image = self.original
        else:
            rotate =pygame.transform.rotate
            self.image = rotate(self.original,self.dizzy)
        self.rect = self.image.get_rect()
        self.rect.center = center
    def punched(self):
        if not self.dizzy:
            self.dizzy =1
            self.original =self.image
pygame.init()
screen = pygame.display.set_mode((468,60))
pygame.display.set_caption("攻击狒狒")
pygame.mouse.set_visible(0)
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250,250,250))
if pygame.font:
    text = os.path.join(font_dir,'msyh.ttc')
    font = pygame.font.Font(text,50)
    text = font.render("击狒得¥¥",1,(10,10,10))
    textpos =text.get_rect()
    textpos.centerx = background.get_rect().centerx
    background.blit(text,textpos)
screen.blit(background,(0,0))
pygame.display.flip()
whiff_sound = load_sound('whiff.wav')
punch_sound = load_sound('punch.wav')
chimp =Chimp()
fist =Fist()
allsprites = pygame.sprite.RenderPlain((fist,chimp))
clock = pygame.time.Clock()
def main():
    events = pygame.event.get()
    for event in events:
        if event.type ==QUIT:
            sys.exit()
        elif event.type == KEYDOWN and event.key == K_ESCAPE:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:
            if fist.punch(chimp):
                punch_sound.play()
                chimp.punched()
            else:
                whiff_sound.play()
        elif event.type == MOUSEBUTTONUP:
            fist.unpunch()
    allsprites.update()    
    screen.blit(background, (0, 0))
    allsprites.draw(screen)
    pygame.display.flip()
if __name__ == '__main__':
    while True:
        clock.tick(60)
        main()

感觉这个代码有点太难看了,这就是屎吗,下次注意一下吧,

运行结果:

11.打包成exe

看我另一篇博客Pylnstaller打包 - 漫宿骄盛 - 博客园

12.后记

终于完成了一个基本能玩的游戏,虽然代码全是看书照抄的,但一回生二回熟,后面再抄几个就要独立去完成一个游戏了

posted @ 2025-03-31 12:04  漫宿骄盛  阅读(33)  评论(0)    收藏  举报