技术小总结

安装pygame模块

安装制作游戏的模块

通过pip命令安装

pip install pygame

游戏初始化与退出

初始化

pygame.init()

退出

pygame.quit()

矩形区域对象

矩形区域四要素

x坐标,y坐标,宽,高

x,y,width,heigh

矩形区域的描述类

矩形区域有四个要素

  • x
  • y
  • width
  • height

有三种方式可以创建出矩形对象

矩形区域对象 = pygame.Rect(x,y,width,height)
矩形区域对象 = pygame.Rect((x,y),(width,height))
矩形区域对象 = pygame.Rect(object)

源码中的注释

Rect(left, top, width, height) -> Rect
Rect((left, top), (width, height)) -> Rect
Rect(object) -> Rect
pygame object for storing rectangular coordinates

补充说明

Rect对象不依赖于pygame.init()的初始化

意思是说,即便不初始化pygame,也可以使用pygame.Rect类创建对象

游戏主窗口

先创建窗口,然后再到窗口中绘制图画

创建管理游戏窗口的模块

pygame.display

主要使用两个函数
set_mode(),用于初始化游戏显示的窗口
update(),用于刷新屏幕显示

初始化游戏显示窗口

函数

pygame.display.set_mode(宽高元组)
返回一个窗口对象

例如
screen = pygame.display.set_mode((480,700))

函数的参数

set_mode(resolution=(0,0), flags=0, depth=0)
resolution,屏幕的宽高
flag,是否全屏等,一般不改默认值
depth,颜色位置,默认是自动匹配

游戏循环

为了让窗口不会马上消失,需要设置游戏循环

绘图三步曲

绘图步骤

  1. 加载图片数据

    图片对象 = pygame.image.load(图片路径)
    

    图片对象打印的结果与它的类型

    <Surface(480x700x24 SW)> <class 'pygame.Surface'>
    

    图片对象具有一个生成矩形对象的方法

    图片矩形对象 = 图片对象.get_rect()
    
  2. 屏幕上绘制该图片

    游戏窗口.blit(图片,绘制的位置元组)
    
    例如
    screen.blit(bg,(0,0))
    

    另外一种方式也可blit

    游戏窗口.blit(图片,矩形对象)
    
    例如
    screen.blit(hero,hero_rect)
    
  3. 显示更新

    pygame.display.update()
    

类比理解

首先需明确动画的原理

了解到动画实际上是一帧一帧图片快速切换的视觉效果

那么就可以按照下面的思路去理解了

  1. 加载图片数据,就是在把图片读到内存中,让图片作好准备

  2. 屏幕上绘图,相当于把图片绘制到展示区(屏幕的一帧)

    注意,我们绘制的是一下页(下一帧)

  3. 显示更新,相当翻一页,使我们刚刚绘制好的图片展示出来

绘制英雄

按照绘图三步曲可以绘制英雄了

  1. 加载英雄图片
  2. 窗口绘制英雄图片
  3. 更新显示

游戏时钟

游戏时钟类

pygame.time.Clock

创建一个时钟对象

clock = pygame.time.Clock()

帧率控制

在游戏循环内部,使用时钟对象的tick()方法

clock.tick(帧率)

关于帧率

值越大,动画越流畅

绘图注意

绘图是在上一个图片的基础上进行绘制的

所以

如果没有重新绘制背景图的话

新绘制上去的图片会与原来存在的图象共同呈现出来的

事件监听

事件模块

pygame.event

获取用户当前动作的事件列表

event_list = pygame.event.get()

事件对象…类型

叉掉窗口

<Event(12-Quit {})> .. <class 'Event'>

按下鼠标

<Event(5-MouseButtonDown {'pos': (359, 264), 'button': 1})> .. <class 'Event'>

按下键盘

待添加

事件类型

事件对象.type

这是一个整数

退出游戏事件类型

pygame.QUIT

点击关闭窗口的事件类型编号

更多的事件类型的编号在

pygame/constants.py

按下键盘

分为两种情况

  • 按住只触发一次

    event.type 与 pygame.KEYDOWN,作比较
    event.key 与 pygame.K_RIGHT,作比较
    
  • 按住不停的触发

    按键元组 = pygame.key.get_pressed()
    根据按下的键对应的数值,即event.key,用于下标可在元组中查数据
    如果值不为0表示被按住中
    

退出游戏套招

pygame.quit()
exit()

定时器

设置定时器的方法

pygame.time.set_timer()

方法的详细参数

set_timer(eventid, milliseconds)

eventid常用
pygame.USEREVENT
来指定

milliseconds
以豪秒为单位,1000相当于1秒

使用定时器的套招

  • 定义事件编号
  • 设置定时器
  • 监听事件

精灵

精灵类

pygame.sprite.Sprite

精灵的update方法

精灵类中定义了一个update方法

是一个占位的方法,代码用pass占位

我们可以重写这个方法

    def update(self, *args):
        """method to control sprite behavior

        Sprite.update(*args):

        The default implementation of this method does nothing; it's just a
        convenient "hook" that you can override. This method is called by
        Group.update() with whatever arguments you give it.

        There is no need to use this method if not using the convenience
        method by the same name in the Group class.

        """
        pass

精灵类中的pass方法

这个方法可以让生成的精灵对象消失,从内存中删除

kill方法

从所有精灵组中删除掉它

    def kill(self):
        """remove the Sprite from all Groups

        Sprite.kill(): return None

        The Sprite is removed from all the Groups that contain it. This won't
        change anything about the state of the Sprite. It is possible to
        continue to use the Sprite after this method has been called, including
        adding it to Groups.

        """
        for c in self.__g:
            c.remove_internal(self)
        self.__g.clear()

精灵组

精灵组类,继承自AbstractGroup类

pygame.sprite.Group

add方法

向组中添加精灵

def add(self, *sprites):
    """add sprite(s) to group

    Group.add(sprite, list, group, ...): return None

    Adds a sprite or sequence of sprites to a group.

    """
    for sprite in sprites:
        # It's possible that some sprite is also an iterator.
        # If this is the case, we should add the sprite itself,
        # and not the iterator object.
        if isinstance(sprite, Sprite):
            if not self.has_internal(sprite):
                self.add_internal(sprite)
                sprite.add_internal(self)
        else:
            try:
                # See if sprite is an iterator, like a list or sprite
                # group.
                self.add(*sprite)
            except (TypeError, AttributeError):
                # Not iterable. This is probably a sprite that is not an
                # instance of the Sprite class or is not an instance of a
                # subclass of the Sprite class. Alternately, it could be an
                # old-style sprite group.
                if hasattr(sprite, '_spritegroup'):
                    for spr in sprite.sprites():
                        if not self.has_internal(spr):
                            self.add_internal(spr)
                            spr.add_internal(self)
                elif not self.has_internal(sprite):
                    self.add_internal(sprite)
                    sprite.add_internal(self)

sprites方法

返回所有精灵列表,即精灵组中的所有成员

def sprites(self):
    """get a list of sprites in the group

    Group.sprite(): return list

    Returns an object that can be looped over with a 'for' loop. (For now,
    it is always a list, but this could change in a future version of
    pygame.) Alternatively, you can get the same information by iterating
    directly over the sprite group, e.g. 'for sprite in group'.

    """
    return list(self.spritedict)

update方法

让精灵组中的全部精灵,调用各自的update方法

def update(self, *args):
    """call the update method of every member sprite

    Group.update(*args): return None

    Calls the update method of every member sprite. All arguments that
    were passed to this method are passed to the Sprite update function.

    """
    for s in self.sprites():
        s.update(*args)

draw方法

在屏幕上绘制精灵

def draw(self, surface):
   spritedict = self.spritedict
   surface_blit = surface.blit
   dirty = self.lostsprites
   self.lostsprites = []
   dirty_append = dirty.append
   for s in self.sprites():
       r = spritedict[s]
       newrect = surface_blit(s.image, s.rect)
       if r:
           if newrect.colliderect(r):
               dirty_append(newrect.union(r))
           else:
               dirty_append(newrect)
               dirty_append(r)
       else:
           dirty_append(newrect)
       spritedict[s] = newrect
   return dirty

需求的精灵

功能一览

  • image,记录图象的数据
  • rect,记录图象位置
  • speed,移动速度与方向
  • update方法,更新精灵的位置
  • kill方法,从所有精灵组中删除

需求的精灵组

功能一览

  • 初始化方法
  • add方法,向组中添加精灵
  • sprites方法,返回所有精灵列表
  • update方法,让组中所有精灵调用各自的update方法
  • draw方法,将组中所有精灵的image图片绘制到 屏幕对象的对应位置

碰撞检测

组与组的碰撞

pygame.sprite.groupcollide()

源码

def groupcollide(groupa, groupb, dokilla, dokillb, collided=None):
    """detect collision between a group and another group

    pygame.sprite.groupcollide(groupa, groupb, dokilla, dokillb):
        return dict

    Given two groups, this will find the intersections between all sprites in
    each group. It returns a dictionary of all sprites in the first group that
    collide. The value for each item in the dictionary is a list of the sprites
    in the second group it collides with. The two dokill arguments control if
    the sprites from either group will be automatically removed from all
    groups. Collided is a callback function used to calculate if two sprites
    are colliding. it should take two sprites as values, and return a bool
    value indicating if they are colliding. If collided is not passed, all
    sprites must have a "rect" value, which is a rectangle of the sprite area
    that will be used to calculate the collision.

    """
    crashed = {}
    SC = spritecollide
    if dokilla:
        for s in groupa.sprites():
            c = SC(s, groupb, dokillb, collided)
            if c:
                crashed[s] = c
                s.kill()
    else:
        for s in groupa:
            c = SC(s, groupb, dokillb, collided)
            if c:
                crashed[s] = c
    return crashed

精灵与组的碰撞

pygame.sprite.spritecollide()
返回值是一个列表,是精灵组中发生撞击的成员列表

源码

def spritecollide(sprite, group, dokill, collided=None):
    """find Sprites in a Group that intersect another Sprite

    pygame.sprite.spritecollide(sprite, group, dokill, collided=None):
        return Sprite_list

    Return a list containing all Sprites in a Group that intersect with another
    Sprite. Intersection is determined by comparing the Sprite.rect attribute
    of each Sprite.

    The dokill argument is a bool. If set to True, all Sprites that collide
    will be removed from the Group.

    The collided argument is a callback function used to calculate if two
    sprites are colliding. it should take two sprites as values, and return a
    bool value indicating if they are colliding. If collided is not passed, all
    sprites must have a "rect" value, which is a rectangle of the sprite area,
    which will be used to calculate the collision.

    """
    if dokill:

        crashed = []
        append = crashed.append

        if collided:
            for s in group.sprites():
                if collided(sprite, s):
                    s.kill()
                    append(s)
        else:
            spritecollide = sprite.rect.colliderect
            for s in group.sprites():
                if spritecollide(s.rect):
                    s.kill()
                    append(s)

        return crashed

    elif collided:
        return [s for s in group if collided(sprite, s)]
    else:
        spritecollide = sprite.rect.colliderect
        return [s for s in group if spritecollide(s.rect)]

—开始正式—

分析框架

游戏的主要构成

  • 游戏初始化
  • 游戏循环

飞机游戏类

PlaneGame

属性

screen,屏幕对象

clock,时钟对象

精灵或精灵组

方法

__init__(self):

初始化方法

__create_sprites(self):

创建精灵的方法

私有方法

start_game(self):

开始游戏的方法,具体里面还包括以下内容:

  • __event_handler(self):

    事件监听方法

  • __check_collide(self):

    碰撞检测

  • __update_sprites(self):

    更新或绘制精灵组

  • __game_over():

    游戏结束

猜你喜欢

转载自blog.csdn.net/lyq562551775/article/details/89303504