Pygame实战:前方高燃,外星人基地又双叒叕“空降”了。

Posted 顾木子吖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pygame实战:前方高燃,外星人基地又双叒叕“空降”了。相关的知识,希望对你有一定的参考价值。

 导语

“宇宙比任何人所能想像的大得多,如果只有我们,那不是太浪费空间了吗?”

忘了到底是从哪搞来的,可能是隔壁班借的,也可能是亲戚朋友给买的。

总之,打着手电筒躲在被窝里看到12点,还越怕越想看~

百慕大三角、UFO、消失多年的飞机、解剖外星人、水晶头盖骨、大脚怪、麦田怪圈、埃及金字塔……

今天的文章就是大家感兴趣的外星人话题!小编脑容量有限倒是想象不出来外星人长什么样子。

但是我可以卡通化一下这款外星人小游戏给大家!绝对不恐怖,甚至还有点儿可爱~

正文

写游戏嘛?还是大家熟悉的pygame模块,主要是分为三块py源码文件。

游戏规则:我方控制炮台击落外星人入侵地球🌏,每次可以重生三次,击毁一次外星人相应加分,进入下一关,完成全部关卡即可通关。

首先定义我方炮台类:有相应注释可看。

'''我方类'''
class aircraftSprite(pygame.sprite.Sprite):
    def __init__(self, color, bullet_color, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        # 生命值
        self.num_life = 3
        self.max_num_life = 5
        # 最小单元
        self.cell = [3, 3]
        self.num_cols = 15
        self.num_rows = 8
        # 用于碰撞检测
        self.rect = pygame.Rect(0, 550, self.cell[0] * self.num_cols, self.cell[0] * self.num_rows)
        # 填充颜色区域
        self.filled_cells = [7,21,22,23,36,37,38,46,47,48,49,50,51,52,53,54,55,56,57,58,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119]
        # 飞船颜色
        self.color = color
        # 飞船子弹颜色
        self.bullet_color = bullet_color
        # 子弹是否在冷却中
        self.is_cooling = False
        self.init_count = 35
        self.cooling_count = self.init_count
        # 得分
        self.score = 0
        # 避免重复增加生命值
        self.old_score = -1
        self.resetBoom()
    '''射击'''
    def shot(self):
        if self.is_cooling:
            return None
        self.is_cooling = True
        self.cooling_count = self.init_count
        return myBulletSprite(self.rect.x + self.rect.width // 2, self.rect.y, self.bullet_color)
    '''在屏幕上画出来'''
    def draw(self, screen):
        for i in range(0, len(self.filled_cells)):
            y = self.filled_cells[i] // self.num_cols
            x = self.filled_cells[i] % self.num_cols
            rect = [x * self.cell[0] + self.rect[0], y * self.cell[1] + self.rect[1], self.cell[0], self.cell[1]]
            pygame.draw.rect(screen, self.color, rect)
    '''更新飞船位置等信息'''
    def update(self, WIDTH):
        # 位置信息
        x = pygame.mouse.get_pos()[0] - (self.rect.width // 2)
        if x < 0:
            x = pygame.mouse.get_pos()[0]
        elif x > WIDTH - self.rect.width:
            x = WIDTH - self.rect.width
        self.rect.x = x
        # 子弹信息
        if self.is_cooling:
            self.cooling_count -= 1
            if self.cooling_count == 0:
                self.is_cooling = False
    '''被击中后爆炸'''
    def boom(self, screen):
        self.boomed_rect.x = self.rect.x
        self.boomed_rect.y = self.rect.y
        self.boomed_count += 1
        if self.boomed_count % 1 == 0:
            self.boomed_frame += 1
            for i in range(0, len(self.boomed_filled_cells)):
                y = self.boomed_filled_cells[i] // self.boomed_num_cols
                x = self.boomed_filled_cells[i] % self.boomed_num_cols
                rect = [x * self.boomed_cell[0] + self.boomed_rect[0], y * self.boomed_cell[1] + self.boomed_rect[1], self.boomed_cell[0], self.boomed_cell[1]]
                pygame.draw.rect(screen, self.color, rect)
        if self.boomed_frame > 4:
            return True
        else:
            return False
    '''重置爆炸所用到的数据'''
    def resetBoom(self):
        # 被击中爆炸时用
        self.one_dead = False
        self.boomed_filled_cells = [3,7,12,15,17,20,24,30,36,40,44,45,53,54,58,62,68,74,78,81,83,86,91,95]
        self.boomed_cell = [3, 3]
        self.boomed_num_cols = 11
        self.boomed_num_rows = 9
        self.boomed_rect = pygame.Rect(0, 0, self.boomed_num_cols*self.boomed_cell[0], self.boomed_num_rows*self.boomed_cell[1])
        # 控制每帧的时间
        self.boomed_count = 0
        # 爆炸特效当前帧
        self.boomed_frame = 0

然后定义地方ufo类:

class enemySprite(pygame.sprite.Sprite):
    def __init__(self, category, number, color, bullet_color, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        self.cell = [3, 3]
        # 编号
        self.number = number
        # 种类
        self.category = category
        if category == 'small':
            self.reward = 20
            self.num_cols = 8
            self.num_rows = 8
            self.rect = pygame.Rect(0, 0, self.num_cols * self.cell[0], self.num_rows * self.cell[1])
            self.filled_cells = [[3,4,10,11,12,13,17,18,19,20,21,22,24,25,27,28,30,31,32,33,34,35,36,37,38,39,42,45,49,51,52,54,56,58,61,63], 
                                 [3,4,10,11,12,13,17,18,19,20,21,22,24,25,27,28,30,31,32,33,34,35,36,37,38,39,41,43,44,46,48,55,57,62]]
        elif category == 'medium':
            self.reward = 15
            self.num_cols = 11
            self.num_rows = 8
            self.rect = pygame.Rect(0, 0, self.num_cols * self.cell[0], self.num_rows * self.cell[1])
            self.filled_cells = [[2,8,11,14,18,21,22,24,25,26,27,28,29,30,32,33,34,35,37,38,39,41,42,43,44,45,46,47,48,49,50,51,52,53,54,56,57,58,59,60,61,62,63,64,68,74,78,86], 
                                 [2,8,14,18,24,25,26,27,28,29,30,34,35,37,38,39,41,42,44,45,46,47,48,49,50,51,52,53,54,55,57,58,59,60,61,62,63,65,66,68,74,76,80,81,83,84]]
        elif category == 'large':
            self.reward = 10
            self.num_cols = 12
            self.num_rows = 8
            self.rect = pygame.Rect(0, 0, self.num_cols * self.cell[0], self.num_rows * self.cell[1])
            self.filled_cells = [[4,5,6,7,13,14,15,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,41,42,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,62,63,64,67,68,69,73,74,77,78,81,82,86,87,92,93], 
                                 [4,5,6,7,13,14,15,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,41,42,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,63,64,67,68,74,75,77,78,80,81,84,85,94,95]]
        self.color = color
        self.bullet_color = bullet_color
        self.speed = [8, 20]
        self.change_count = 0
        self.change_flag = False
        # 被击中爆炸时用
        self.boomed_filled_cells = [3,7,12,15,17,20,24,30,36,40,44,45,53,54,58,62,68,74,78,81,83,86,91,95]
        self.boomed_cell = [3, 3]
        self.boomed_num_cols = 11
        self.boomed_num_rows = 9
        self.boomed_rect = pygame.Rect(0, 0, self.boomed_num_cols * self.boomed_cell[0], self.boomed_num_rows * self.boomed_cell[1])
        self.boomed_count = 0
        self.boomed_frame = 0
    '''射击'''
    def shot(self):
        return enemyBulletSprite(self.rect.x + self.rect.width // 2, self.rect.y, self.bullet_color)
    '''在屏幕上画出来'''
    def draw(self, screen):
        if self.change_count > 50:
            self.change_count = 0
            self.change_flag = not self.change_flag
        if self.change_flag:
            for i in range(0, len(self.filled_cells[0])):
                y = self.filled_cells[0][i] // self.num_cols
                x = self.filled_cells[0][i] % self.num_cols
                rect = [x * self.cell[0] + self.rect[0], y * self.cell[1] + self.rect[1], self.cell[0], self.cell[1]]
                pygame.draw.rect(screen, self.color, rect)
        else:
            for i in range(0, len(self.filled_cells[1])):
                y = self.filled_cells[1][i] // self.num_cols
                x = self.filled_cells[1][i] % self.num_cols
                rect = [x * self.cell[0] + self.rect[0], y * self.cell[1] + self.rect[1], self.cell[0], self.cell[1]]
                pygame.draw.rect(screen, self.color, rect)
    '''更新敌方位置等信息'''
    def update(self, direction, HEIGHT):
        # 用于改变形状
        self.change_count += 1
        # 更新位置信息
        if direction == 'right':
            self.rect.x += self.speed[0]
        elif direction == 'left':
            self.rect.x -= self.speed[0]
        elif direction == 'down':
            self.rect.y += self.speed[1]
        if self.rect.y >= HEIGHT - self.rect.height:
            return True
        else:
            return False
    '''被击中后爆炸'''
    def boom(self, screen):
        self.boomed_rect.x = self.rect.x
        self.boomed_rect.y = self.rect.y
        self.boomed_count += 1
        if self.boomed_count % 1 == 0:
            self.boomed_frame += 1
            for i in range(0, len(self.boomed_filled_cells)):
                y = self.boomed_filled_cells[i] // self.boomed_num_cols
                x = self.boomed_filled_cells[i] % self.boomed_num_cols
                rect = [x * self.boomed_cell[0] + self.boomed_rect[0], y * self.boomed_cell[1] + self.boomed_rect[1], self.boomed_cell[0], self.boomed_cell[1]]
                pygame.draw.rect(screen, self.color, rect)
        if self.boomed_frame > 4:
            return True
        else:
            return False

​敌人跟我方交涉,射击子弹:

class myBulletSprite(pygame.sprite.Sprite):
    def __init__(self, x, y, color, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        self.cell = [2, 2]
        self.num_cols = 1
        self.num_rows = 4
        self.rect = pygame.Rect(x, y, self.num_cols * self.cell[0], self.num_rows * self.cell[1])
        self.filled_cells = [0,1,2,3]
        self.speed = 8
        self.color = color
    '''在屏幕上画出来'''
    def draw(self, screen):
        for i in range(0, len(self.filled_cells)):
            y = self.filled_cells[i] // self.num_cols
            x = self.filled_cells[i] % self.num_cols
            rect = [x * self.cell[0] + self.rect[0], y * self.cell[1] + self.rect[1], self.cell[0], self.cell[1]]
            pygame.draw.rect(screen, self.color, rect)
    '''更新子弹位置等信息'''
    def update(self):
        self.rect.y -= self.speed
        if self.rect.y + self.rect.height < 0:
            return True
        else:
            return False


'''敌方子弹精灵类'''
class enemyBulletSprite(pygame.sprite.Sprite):
    def __init__(self, x, y, color):
        pygame.sprite.Sprite.__init__(self)
        self.cell = [3, 3]
        self.num_cols = 3
        self.num_rows = 7
        self.rect = pygame.Rect(x, y, self.num_cols * self.cell[0], self.num_rows * self.cell[1])
        self.filled_cells = [[0,4,8,10,12,16,20], 
                             [2,4,6,10,14,16,18]]
        self.change_count = 0
        self.change_flag = False
        self.speed = 4
        self.color = color
    '''在屏幕上画出来'''
    def draw(self, screen):
        if self.change_count > 2:
            self.change_count = 0
            self.change_flag = not self.change_flag
        if self.change_flag:
            for i in range(0, len(self.filled_cells[0])):
                y = self.filled_cells[0][i] // self.num_cols
                x = self.filled_cells[0][i] % self.num_cols
                rect = [x * self.cell[0] + self.rect[0], y * self.cell[1] + self.rect[1], self.cell[0], self.cell[1]]
                pygame.draw.rect(screen, self.color, rect)
        else:
            for i in range(0, len(self.filled_cells[1])):
                y = self.filled_cells[1][i] // self.num_cols
                x = self.filled_cells[1][i] % self.num_cols
                rect = [x * self.cell[0] + self.rect[0], y * self.cell[1] + self.rect[1], self.cell[0], self.cell[1]]
                pygame.draw.rect(screen, self.color, rect)
    '''更新子弹位置等信息'''
    def update(self, HEIGHT):
        # 用于改变子弹形状的计数
        self.change_count += 1
        # 位置信息
        self.rect.y += self.speed
        if self.rect.y > HEIGHT:
            return True
        else:
            return False

代码很多,附主要代码文件:

import os
import sys
import cfg
import random
import pygame
from modules import *


'''开始游戏'''
def startGame(screen):
    clock = pygame.time.Clock()
    # 加载字体
    font = pygame.font.SysFont('arial', 18)
    if not os.path.isfile('score'):
        f = open('score', 'w')
        f.write('0')
        f.close()
    with open('score', 'r') as f:
        highest_score = int(f.read().strip())
    # 敌方
    enemies_group = pygame.sprite.Group()
    for i in range(55):
        if i < 11:
            enemy = enemySprite('small', i, cfg.WHITE, cfg.WHITE)
        elif i < 33:
            enemy = enemySprite('medium', i, cfg.WHITE, cfg.WHITE)
        else:
            enemy = enemySprite('large', i, cfg.WHITE, cfg.WHITE)
        enemy.rect.x = 85 + (i % 11) * 50
        enemy.rect.y = 120 + (i // 11) * 45
        enemies_group.add(enemy)
    boomed_enemies_group = pygame.sprite.Group()
    en_bullets_group = pygame.sprite.Group()
    ufo = ufoSprite(color=cfg.RED)
    # 我方
    myaircraft = aircraftSprite(color=cfg.GREEN, bullet_color=cfg.WHITE)
    my_bullets_group = pygame.sprite.Group()
    # 用于控制敌方位置更新
    # --移动一行
    enemy_move_count = 24
    enemy_move_interval = 24
    enemy_move_flag = False
    # --改变移动方向(改变方向的同时集体下降一次)
    enemy_change_direction_count = 0
    enemy_change_direction_interval = 60
    enemy_need_down = False
    enemy_move_right = True
    enemy_need_move_row = 6
    enemy_max_row = 5
    # 用于控制敌方发射子弹
    enemy_shot_interval = 100
    enemy_shot_count = 0
    enemy_shot_flag = False
    # 游戏进行中
    running = True
    is_win = False
    # 主循环
    while running:
        screen.fill(cfg.BLACK)
        for event in pygame.event.get():
            # --点右上角的X或者按Esc键退出游戏
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
            # --射击
            if event.type == pygame.MOUSEBUTTONDOWN:
                my_bullet = myaircraft.shot()
                if my_bullet:
                    my_bullets_group.add(my_bullet)
        # --我方子弹与敌方/UFO碰撞检测
        for enemy in enemies_group:
            if pygame.sprite.spritecollide(enemy, my_bullets_group, True, None):
                boomed_enemies_group.add(enemy)
                enemies_group.remove(enemy)
                myaircraft.score += enemy.reward
        if pygame.sprite.spritecollide(ufo, my_bullets_group, True, None):
            ufo.is_dead = True
            myaircraft.score += ufo.reward
        # --更新并画敌方
        # ----敌方子弹
        enemy_shot_count += 1
        if enemy_shot_count > enemy_shot_interval:
            enemy_shot_flag = True
            enemies_survive_list = [enemy.number for enemy in enemies_group]
            shot_number = random.choice(enemies_survive_list)
            enemy_shot_count = 0
        # ----敌方移动
        enemy_move_count += 1
        if enemy_move_count > enemy_move_interval:
            enemy_move_count = 0
            enemy_move_flag = True
            enemy_need_move_row -= 1
            if enemy_need_move_row == 0:
                enemy_need_move_row = enemy_max_row
            enemy_change_direction_count += 1
            if enemy_change_direction_count > enemy_change_direction_interval:
                enemy_change_direction_count = 1
                enemy_move_right = not enemy_move_right
                enemy_need_down = True
                # ----每次下降提高移动和射击速度
                enemy_move_interval = max(15, enemy_move_interval-3)
                enemy_shot_interval = max(50, enemy_move_interval-10)
        # ----遍历更新
        for enemy in enemies_group:
            if enemy_shot_flag:
                if enemy.number == shot_number:
                    en_bullet = enemy.shot()
                    en_bullets_group.add(en_bullet)
            if enemy_move_flag:
                if enemy.number in range((enemy_need_move_row-1)*11, enemy_need_move_row*11):
                    if enemy_move_right:
                        enemy.update('right', cfg.SCREENSIZE[1])
                    else:
                        enemy.update('left', cfg.SCREENSIZE[1])
            else:
                enemy.update(None, cfg.SCREENSIZE[1])
            if enemy_need_down:
                if enemy.update('down', cfg.SCREENSIZE[1]):
                    running = False
                    is_win = False
                enemy.change_count -= 1
            enemy.draw(screen)
        enemy_move_flag = False
        enemy_need_down = False
        enemy_shot_flag = False
        # ----敌方爆炸特效
        for boomed_enemy in boomed_enemies_group:
            if boomed_enemy.boom(screen):
                boomed_enemies_group.remove(boomed_enemy)
                del boomed_enemy
        # --敌方子弹与我方飞船碰撞检测
        if not myaircraft.one_dead:
            if pygame.sprite.spritecollide(myaircraft, en_bullets_group, True, None):
                myaircraft.one_dead = True
        if myaircraft.one_dead:
            if myaircraft.boom(screen):
                myaircraft.resetBoom()
                myaircraft.num_life -= 1
                if myaircraft.num_life < 1:
                    running = False
                    is_win = False
        else:
            # ----更新飞船
            myaircraft.update(cfg.SCREENSIZE[0])
            # ----画飞船
            myaircraft.draw(screen)
        if (not ufo.has_boomed) and (ufo.is_dead):
            if ufo.boom(screen):
                ufo.has_boomed = True
        else:
            # ----更新UFO
            ufo.update(cfg.SCREENSIZE[0])
            # ----画UFO
            ufo.draw(screen)
        # --画我方飞船子弹
        for bullet in my_bullets_group:
            if bullet.update():
                my_bullets_group.remove(bullet)
                del bullet
            else:
                bullet.draw(screen)
        # --画敌方子弹
        for bullet in en_bullets_group:
            if bullet.update(cfg.SCREENSIZE[1]):
                en_bullets_group.remove(bullet)
                del bullet
            else:
                bullet.draw(screen)
        if myaircraft.score > highest_score:
            highest_score = myaircraft.score
        # --得分每增加2000我方飞船增加一条生命
        if (myaircraft.score % 2000 == 0) and (myaircraft.score > 0) and (myaircraft.score != myaircraft.old_score):
            myaircraft.old_score = myaircraft.score
            myaircraft.num_life = min(myaircraft.num_life + 1, myaircraft.max_num_life)
        # --敌人都死光了的话就胜利了
        if len(enemies_group) < 1:
            is_win = True
            running = False
        # --显示文字
        # ----当前得分
        showText(screen, 'SCORE: ', cfg.WHITE, font, 200, 8)
        showText(screen, str(myaircraft.score), cfg.WHITE, font, 200, 24)
        # ----敌人数量
        showText(screen, 'ENEMY: ', cfg.WHITE, font, 370, 8)
        showText(screen, str(len(enemies_group)), cfg.WHITE, font, 370, 24)
        # ----历史最高分
        showText(screen, 'HIGHEST: ', cfg.WHITE, font, 540, 8)
        showText(screen, str(highest_score), cfg.WHITE, font, 540, 24)
        # ----FPS
        showText(screen, 'FPS: ' + str(int(clock.get_fps())), cfg.RED, font, 8, 8)
        # --显示剩余生命值
        showLife(screen, myaircraft.num_life, cfg.GREEN)
        pygame.display.update()
        clock.tick(cfg.FPS)
    with open('score', 'w') as f:
        f.write(str(highest_score))
    return is_win


'''主函数'''
def main():
    # 初始化
    pygame.init()
    pygame.display.set_caption('外星人入侵 ')
    screen = pygame.display.set_mode(cfg.SCREENSIZE)
    pygame.mixer.init()
    pygame.mixer.music.load(cfg.BGMPATH)
    pygame.mixer.music.set_volume(0.4)
    pygame.mixer.music.play(-1)
    while True:
        is_win = startGame(screen)
        endInterface(screen, cfg.BLACK, is_win)


'''run'''
if __name__ == '__main__':
    main()

效果如下:

​总结

好啦!这款外星人大战的小游戏就完成了~想要这款游戏嘛?

💖关注小编——获取更多精彩内容源码哦!

你们的支持是我最大的动力!!记得三连哦~mua 欢迎大家阅读往期更多的游戏文章~

 源码基地:

主页(pc端)左侧源码基地免费拿小程序!或者私信小编也可!



👑文章汇总——

1.1Python—2021 |已有文章汇总 | 持续更新,直接看这篇就够了~

以上是关于Pygame实战:前方高燃,外星人基地又双叒叕“空降”了。的主要内容,如果未能解决你的问题,请参考以下文章

bzoj又双叒叕挂了

struts2又双叒叕有漏洞了

又双叒叕种草了新家装风格?AI帮你家居换装

来了, 微信又双叒叕更新

32G V100 要不要?又双叒叕到白嫖时间!

我最高产的EasyPyPI又双叒叕更新了!v1.4.0发布