zoukankan      html  css  js  c++  java
  • Pygame

    前言

      一段时间没有敲代码,感觉忘得好快!!今天我们继续完成前面的任务,不知道大家有木有发现之前的飞机撞到敌人是不会爆炸的,这很不符合规律,今天我们加入这个小功能,玩家飞机坠毁并产生动画。(°∀°)ノ

    正片开始~

      1. 判断飞机是否坠毁

      关于碰撞检测,我们在上一节的内容中就作了简单介绍了,这一节中我们使用一个新函数,用于判断玩家是否被敌机击中:

      pygame.sprite.spritecollide()——检测sprite与group之间的碰撞

      spritecollide(sprite, group, dokill, collided = None) -> Sprite_list

      参数跟上一节中参数说明相同,函数返回group中与sprite发生碰撞的所有精灵,以列表(list)形式

      我们现在加入几代码

    1 enemy1_down_list = pygame.sprite.spritecollide(hero, enemy1_group, True)
    2     if len(enemy1_down_list) > 0: # 不空
    3         enemy1_down_group.add(enemy1_down_list)
    4         hero.is_hit = True

      如果玩家被击中(即enemy1_down_list不空),就将击中玩家的敌机加入到enemy1_down_group中,将渲染enemy1坠毁动画的过程交给该group;最后将hero的is_hit属性更改为True(Hero类新加入的属性,便于进行后续的逻辑判断)。

      2. 制造玩家飞机坠毁动画

      当然玩家被击中了也是不可能凭空消失的,我们将以前在主循环中制造玩家飞机动画的代码更新一下,即将:

    1 hero.image = hero_surface[ticks//(ANIMATE_CYCLE//2)]

      改为:

    1 if hero.is_hit:
    2         if ticks%(ANIMATE_CYCLE//2) == 0:
    3             hero_down_index += 1
    4         hero.image = hero_surface[hero_down_index]
    5         if hero_down_index == 5:
    6             break
    7     else:
    8         hero.image = hero_surface[ticks//(ANIMATE_CYCLE//2)]

      如果玩家没有被击中,则按以前普通的玩家图片制造动画;若玩家被击中,则按每15tick换一次图片的频率制造爆炸动画,当图片索引增加至上限时(爆炸动画显示完成),跳出主循环,即结束游戏。

      3. 完整的结束游戏

      如果你只完成了上面的代码,你会发现,玩家被击中了之后,飞机爆炸,之后画面静止,然后所有动作都进行不了,包括右上角红叉。这是怎么回事?(╯°口°)╯(┴—┴  认真思考过后你会发现,你此时已经跳出了主循环,而捕捉击键事件和点击事件的功能却写在主循环中~就是这样啦~

      无奈之下只能再写一段捕捉事件的代码(#-_-)┯━┯

    1 # 跳出主循环
    2 screen.blit(gameover, (0, 0))
    3 # 玩家坠毁后退出游戏
    4 while True:
    5     pygame.display.update()
    6     for event in pygame.event.get():
    7         if event.type == pygame.QUIT:
    8             pygame.quit()
    9             exit()

      跳出主循环后,我们重写绘制一个“gameover”的背景,用户通过右上角红叉结束游戏~

      这样就算是一个完整的游戏了吧(°∀°)ノ

      附上此节的完整代码:

      1 # -*- coding = utf-8 -*-
      2 """
      3 @author: Will Wu
      4 
      5 增加功能:
      6 1. 玩家碰到敌人会坠毁
      7 2. 游戏结束
      8 """
      9 
     10 import pygame                   # 导入pygame库
     11 from pygame.locals import *     # 导入pygame库中的一些常量
     12 from sys import exit            # 导入sys库中的exit函数
     13 from random import randint
     14 
     15 # 定义窗口的分辨率
     16 SCREEN_WIDTH = 480
     17 SCREEN_HEIGHT = 640
     18 
     19 # 子弹类
     20 class Bullet(pygame.sprite.Sprite):
     21 
     22     def __init__(self, bullet_surface, bullet_init_pos):
     23         pygame.sprite.Sprite.__init__(self)            
     24         self.image = bullet_surface
     25         self.rect = self.image.get_rect()
     26         self.rect.topleft = bullet_init_pos
     27         self.speed = 8
     28 
     29     # 控制子弹移动
     30     def update(self):
     31         self.rect.top -= self.speed
     32         if self.rect.bottom < 0:
     33             self.kill()
     34             
     35 
     36 # 玩家类
     37 class Hero(pygame.sprite.Sprite):
     38     
     39     def __init__(self, hero_surface, hero_init_pos):
     40         pygame.sprite.Sprite.__init__(self)            
     41         self.image = hero_surface
     42         self.rect = self.image.get_rect()
     43         self.rect.topleft = hero_init_pos
     44         self.speed = 6
     45         self.is_hit = False # new
     46 
     47         # 子弹1的Group
     48         self.bullets1 = pygame.sprite.Group()
     49 
     50     # 控制射击行为
     51     def single_shoot(self, bullet1_surface):
     52         bullet1 = Bullet(bullet1_surface, self.rect.midtop)
     53         self.bullets1.add(bullet1)
     54 
     55     # 控制飞机移动
     56     def move(self, offset):
     57         x = self.rect.left + offset[pygame.K_RIGHT] - offset[pygame.K_LEFT]
     58         y = self.rect.top + offset[pygame.K_DOWN] - offset[pygame.K_UP]
     59         if x < 0:
     60             self.rect.left = 0
     61         elif x > SCREEN_WIDTH - self.rect.
     62             self.rect.left = SCREEN_WIDTH - self.rect.width
     63         else:
     64             self.rect.left = x
     65             
     66         if y < 0:
     67             self.rect.top = 0
     68         elif y > SCREEN_HEIGHT - self.rect.height:
     69             self.rect.top = SCREEN_HEIGHT - self.rect.height
     70         else:
     71             self.rect.top = y
     72 
     73 # 敌人类
     74 class Enemy(pygame.sprite.Sprite):
     75     def __init__(self, enemy_surface, enemy_init_pos):
     76         pygame.sprite.Sprite.__init__(self)            
     77         self.image = enemy_surface
     78         self.rect = self.image.get_rect()
     79         self.rect.topleft = enemy_init_pos
     80         self.speed = 2
     81 
     82         # 爆炸动画画面索引
     83         self.down_index = 0
     84 
     85     def update(self):
     86         self.rect.top += self.speed
     87         if self.rect.top > SCREEN_HEIGHT:
     88             self.kill()
     89         
     90 ###########################################################################
     91 
     92 # 定义画面帧率
     93 FRAME_RATE = 60
     94 
     95 # 定义动画周期(帧数)
     96 ANIMATE_CYCLE = 30
     97 
     98 ticks = 0
     99 clock = pygame.time.Clock()
    100 offset = {pygame.K_LEFT:0, pygame.K_RIGHT:0, pygame.K_UP:0, pygame.K_DOWN:0}
    101 
    102 # 玩家坠毁图片索引
    103 hero_down_index = 1 # new
    104           
    105 # 初始化游戏
    106 pygame.init()                   # 初始化pygame
    107 screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])     # 初始化窗口
    108 pygame.display.set_caption('This is my first pygame-program')       # 设置窗口标题
    109 
    110 # 载入背景图
    111 background = pygame.image.load('resources/image/background.png')
    112 # 游戏结束图
    113 gameover = pygame.image.load('resources/image/gameover.png') # new
    114 
    115 # 载入资源图片
    116 shoot_img = pygame.image.load('resources/image/shoot.png')
    117 
    118 # 用subsurface剪切读入的图片
    119 # Hero图片
    120 hero_surface = []
    121 hero_surface.append(shoot_img.subsurface(pygame.Rect(0, 99, 102, 126)))
    122 hero_surface.append(shoot_img.subsurface(pygame.Rect(165, 360, 102, 126)))
    123 hero_surface.append(shoot_img.subsurface(pygame.Rect(165, 234, 102, 126)))     
    124 hero_surface.append(shoot_img.subsurface(pygame.Rect(330, 624, 102, 126)))
    125 hero_surface.append(shoot_img.subsurface(pygame.Rect(330, 498, 102, 126)))
    126 hero_surface.append(shoot_img.subsurface(pygame.Rect(432, 624, 102, 126)))
    127 hero_pos = [200, 500]
    128 
    129 # bullet1图片
    130 bullet1_surface = shoot_img.subsurface(pygame.Rect(1004, 987, 9, 21))
    131 
    132 # enemy1图片 
    133 enemy1_surface = shoot_img.subsurface(pygame.Rect(534, 612, 57, 43))
    134 enemy1_down_surface = []
    135 enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(267, 347, 57, 43)))
    136 enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(873, 697, 57, 43)))
    137 enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(267, 296, 57, 43)))
    138 enemy1_down_surface.append(shoot_img.subsurface(pygame.Rect(930, 697, 57, 43)))
    139 
    140 # 创建玩家
    141 hero = Hero(hero_surface[0], hero_pos)
    142 
    143 # 创建敌人组
    144 enemy1_group = pygame.sprite.Group()
    145 
    146 # 创建击毁敌人组
    147 enemy1_down_group = pygame.sprite.Group()
    148 
    149 # 事件循环(main loop)
    150 while True:
    151 
    152     # 控制游戏最大帧率
    153     clock.tick(FRAME_RATE)
    154 
    155     # 绘制背景
    156     screen.blit(background, (0, 0))
    157 
    158     # 改变飞机图片制造动画
    159     if ticks >= ANIMATE_CYCLE:
    160         ticks = 0
    161 
    162     # 制造飞机动画 ######################################
    163     # 更新的代码段
    164     if hero.is_hit:
    165         if ticks%(ANIMATE_CYCLE//2) == 0:
    166             hero_down_index += 1
    167         hero.image = hero_surface[hero_down_index]
    168         if hero_down_index == 5:
    169             break
    170     else:
    171         hero.image = hero_surface[ticks//(ANIMATE_CYCLE//2)]
    172     # #################################################
    173 
    174     # 射击
    175     if ticks % 10 == 0:
    176         hero.single_shoot(bullet1_surface)
    177     # 控制子弹
    178     hero.bullets1.update()
    179     # 绘制子弹
    180     hero.bullets1.draw(screen)
    181 
    182     # 产生敌机 
    183     if ticks % 30 == 0:
    184         enemy = Enemy(enemy1_surface, [randint(0, SCREEN_WIDTH - enemy1_surface.get_width()), -enemy1_surface.get_height()])
    185         enemy1_group.add(enemy)
    186     # 控制敌机
    187     enemy1_group.update()
    188     # 绘制敌机
    189     enemy1_group.draw(screen)
    190 
    191     # 检测敌机与子弹的碰撞 
    192     enemy1_down_group.add(pygame.sprite.groupcollide(enemy1_group, hero.bullets1, True, True))
    193     
    194     for enemy1_down in enemy1_down_group:
    195         screen.blit(enemy1_down_surface[enemy1_down.down_index], enemy1_down.rect)
    196         if ticks % (ANIMATE_CYCLE//2) == 0:
    197             if enemy1_down.down_index < 3:
    198                 enemy1_down.down_index += 1
    199             else:
    200                 enemy1_down_group.remove(enemy1_down)
    201 
    202     # 检测敌机与玩家的碰撞 #################################
    203     # 更新的代码段
    204     enemy1_down_list = pygame.sprite.spritecollide(hero, enemy1_group, True)
    205     if len(enemy1_down_list) > 0: # 不空
    206         enemy1_down_group.add(enemy1_down_list)
    207         hero.is_hit = True
    208     # ###################################################
    209         
    210     # 绘制飞机   
    211     screen.blit(hero.image, hero.rect)
    212     ticks += 1 # python已略去自增运算符
    213 
    214     # 更新屏幕
    215     pygame.display.update()                                         
    216     
    217     # 处理游戏退出
    218     # 从消息队列中循环取
    219     for event in pygame.event.get():
    220         if event.type == pygame.QUIT:
    221             pygame.quit()
    222             exit()
    223 
    224         # ※ Python中没有switch-case 多用字典类型替代
    225         # 控制方向       
    226         if event.type == pygame.KEYDOWN:
    227             if event.key in offset:
    228                 offset[event.key] = hero.speed
    229         elif event.type == pygame.KEYUP:
    230             if event.key in offset:
    231                 offset[event.key] = 0
    232 
    233     # 移动飞机
    234     hero.move(offset)
    235 
    236 # 更新的代码段 ###############################
    237 # 跳出主循环
    238 screen.blit(gameover, (0, 0))
    239 # 玩家坠毁后退出游戏
    240 while True:
    241     pygame.display.update()
    242     for event in pygame.event.get():
    243         if event.type == pygame.QUIT:
    244             pygame.quit()
    245             exit()
    246 ############################################
    View Code
  • 相关阅读:
    Codeforces 877 C. Slava and tanks
    Codeforces 877 D. Olya and Energy Drinks
    2017 10.25 NOIP模拟赛
    2017 国庆湖南 Day1
    UVA 12113 Overlapping Squares
    学大伟业 国庆Day2
    51nod 1629 B君的圆锥
    51nod 1381 硬币游戏
    [JSOI2010]满汉全席
    学大伟业 2017 国庆 Day1
  • 原文地址:https://www.cnblogs.com/wuzhanpeng/p/4310312.html
Copyright © 2011-2022 走看看