• pygame-KidsCanCode系列jumpy-part12-platform图片


    目前为止,Player的站立、行走、跳跃都是动画了,只有跳板(即:Platform类)还是难看的矩形,这节我们把Platform也换成图片:

    原来的Platform类长这个样子:

    1 class Platform(pg.sprite.Sprite):
    2     def __init__(self, x, y, w, h):
    3         pg.sprite.Sprite.__init__(self)
    4         self.image = pg.Surface((w, h))
    5         self.image.fill(GREEN)
    6         self.rect = self.image.get_rect()
    7         self.rect.x = x
    8         self.rect.y = y
    View Code

    如果用图片,就不再需要w,h这个参数了(因为图片自带尺寸大小),所以变成下面这样:

     1 class Platform(pg.sprite.Sprite):
     2     def __init__(self, game, x, y):
     3         pg.sprite.Sprite.__init__(self)
     4         self.game = game
     5         # 改成加载图片
     6         images = [self.game.spritesheet.get_image("ground_grass_broken.png"),
     7                   self.game.spritesheet.get_image("ground_grass_small_broken.png")]
     8         # 随机选一张
     9         self.image = random.choice(images)
    10         self.rect = self.image.get_rect()
    11         self.rect.x = x
    12         self.rect.y = y
    View Code

    相应的,最开始初始化的5块platform信息(settings.py)

    1 # starting platform
    2 PLATFORM_LIST = [(0, HEIGHT - 30, WIDTH, 30),
    3                  (WIDTH / 2 - 50, HEIGHT * 0.75, 100, 15),
    4                  (WIDTH * 0.12, HEIGHT * 0.5, 60, 15),
    5                  (WIDTH * 0.65, 200, 80, 10),
    6                  (WIDTH * 0.5, 100, 50, 10)]
    View Code

    调整成:

    1 # starting platform
    2 PLATFORM_LIST = [(5, HEIGHT - 35),
    3                  (WIDTH / 2 - 50, HEIGHT * 0.75),
    4                  (WIDTH * 0.12, HEIGHT * 0.5),
    5                  (WIDTH * 0.65, 200),
    6                  (WIDTH * 0.5, 100)]
    View Code

    同时,调整下Player出场时的位置,让它站在最底面的第1块板上:

    class Player(pg.sprite.Sprite):
        def __init__(self, game):
            pg.sprite.Sprite.__init__(self)
            self.game = game
            ...
            self.rect = self.image.get_rect()
            # 初始化时,停在第一块platform上
            self.rect.center = (35, HEIGHT - 35)
            self.pos = self.rect.center
            ...
    View Code

     main.py里的new函数,也做相应的调整:

        def new(self):
            self.score = 0
            ...
    
            for plat in PLATFORM_LIST:
                # 这里相应调整
                p = Platform(self, *plat)
                ...
    View Code

    main.py中的update函数里,最后再调整一下:

     1     def update(self):
     2         self.all_sprites.update()
     3         ...
     4 
     5         while len(self.platforms) <= 5:
     6             width = random.randrange(50, 100)
     7             # 这里也做相应调整
     8             p = Platform(self, random.randint(0, WIDTH - width),
     9                          random.randint(-70, -30))
    10             self.platforms.add(p)
    11             ...
    View Code

    跑起来看看,基本效果出来了,难看的矩形终于没有了,但是仔细观察下,漏洞百出,比如下面这些:

    问题1:跳板太靠右,边界跑到屏幕外了

    修复方法:

    检测下platform的right值,如果超出边界,向左挪一点

    1     def new(self):
    2        ...
    3 
    4         for plat in PLATFORM_LIST:
    5             p = Platform(self, *plat)
    6             # 如果platform位置太靠右,跑出屏幕外,校正位置
    7             if p.rect.right >= WIDTH:
    8                 p.rect.centerx = p.rect.centerx - (p.rect.right - WIDTH) - 2
    9             ...
    View Code

    问题二:platform把player实例给挡住了

    类似photoshop的图层一样,pygame里也有layer的概念,最后绘制的对象,默认在最上层

    修复方法:main.py的draw函数,在最后,强制再绘制一次player(tips: 其实有更好的办法,利用图层概念,可参考part17部分

    1     def draw(self):
    2         self.screen.fill(LIGHT_BLUE)
    3         self.all_sprites.draw(self.screen)
    4         self.debug()
    5         self.draw_text(str(self.score), 22, WHITE, WIDTH / 2, 15)
    6         # 强制把player放在最上层
    7         self.screen.blit(self.player.image, self.player.rect)
    8         pg.display.update()
    View Code

    问题三:跳板叠在一起

    解决方法:

    思路:随机生成的新跳板,先不急着加入self.platforms,而是运用碰撞检测原理,与现有跳板做碰撞检测(叠在一起,肯定就碰撞上了),如果碰撞了,就扔掉(pygame下一帧会重新生成,如此循环,直到满足条件的跳板加入)

     1     def update(self):
     2         self.all_sprites.update()
     3         ...
     4         # 跳板数<5,且player未跌落到屏幕外(否则player跌到屏幕外,仍在不停做碰撞检测,性能开销极大,会把程序卡死)
     5         while len(self.platforms) <= 5 and self.player.rect.bottom < HEIGHT:
     6             width = random.randrange(50, 100)
     7             # 这里也做相应调整
     8             p = Platform(self, random.randint(0, WIDTH - width),
     9                          random.randint(-70, -30))
    10             if p.rect.right >= WIDTH:
    11                 p.rect.centerx = p.rect.centerx - (p.rect.right - WIDTH) - 2
    12             self.all_sprites.add(p)
    13             # 防止二个plat平台叠在一起(原理:用待加入的plat与其它platform实例做碰撞检测,如果碰撞了,则扔掉)
    14             hits = pg.sprite.spritecollideany(p, self.platforms)
    15             if hits:
    16                 p.kill()
    17             else:
    18                 self.platforms.add(p)
    View Code

    问题四: player已经超过了屏幕顶端,但是屏幕并没有向上滚动,这样玩家就无法看到头顶的新跳板。

    解决办法:

    先来分析下main.py中update函数中的滚动处理

            if self.player.rect.top < HEIGHT / 4:
                self.player.pos.y += abs(self.player.vel.y)
                for plat in self.platforms:
                    plat.rect.top += abs(self.player.vel.y)
                    if plat.rect.top > HEIGHT:
                        ...

    如果player的y轴速度为0,abs函数算出来的值为0,所以跳板与兔子的y坐标值并不会动(也就是屏幕无法滚动),改进为下面这样:

     1     def update(self):
     2         self.all_sprites.update()
     3         ...
     4         if self.player.rect.top < HEIGHT / 4:
     5             # 防止垂直方向速度为0时,无法滚动屏幕
     6             self.player.pos.y += max(abs(self.player.vel.y), 2)
     7             for plat in self.platforms:
     8                 plat.rect.top += max(abs(self.player.vel.y), 2)
     9                 if plat.rect.top > HEIGHT:
    10                     ...
    View Code

    修复了上面这一堆bug后,再来运行下:

    源码: https://github.com/yjmyzz/kids-can-code/tree/master/part_12

  • 相关阅读:
    ZooKeeper的安装和API
    Flume案例Ganglia监控
    二十五、小程序的图片预览(放大滑动)
    二十四、小程序中改变checkbox和radio的样式
    二十三、小程序中的三级下拉框(下拉菜单)
    二十二:制作app的时候超出部分不能滑动
    二十一、当锚点遇到fixed(margin和padding)
    二十:让行内元素在div中垂直居中
    十九、多文件上传(ajaxFileupload实现多文件上传功能)
    十六、字符串和数组之间的转换
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/pygame-kidscancode-part12-platform-graphic.html
Copyright © 2020-2023  润新知