黑马程序员 飞机大战 笔记 上

飞机大战

前言

近来,受到朋友嘱托,做一款简单的小游戏,本小白很久没有碰过这方面的东西了,想知新还需温故,便书写此篇博客,本人只是利用博客记录自己的学习经历,水平较低。
很久之前,曾在b站观看黑马程序员的python教学视频,其中有不小的篇幅细致讲解了利用pygame库做一款飞机大战的游戏。但是只是懵懵懂懂跟着码,有很多东西值得去总结,所以本篇博客由黑马源码黑马分享的飞机素材笔记组成。
谈及黑马,他那部视频非常基础、细致,正如他所说:听得懂中文都能学会。对python语言感兴趣却不知道如何下手的同学,可以考虑去看一两集。

第一步:程序运行顺序

    def start_game(self):
       print("游戏开始...")
       while True:
           #1.刷新频率
           self.clock.tick(FRAME_PER_SEC)
           #2.事件监听
           self.__event_handler()
           #3.碰撞检测
           self.__check_collide()
           #4.更新/绘制精灵
           self.__updata_sprites()
           #5.更新检测
           pygame.display.update()

本次程序主要运用到的库:pygame(核心)
运行程序后游戏直接进行,设定刷新频率、事件监听(是否有摁键摁下)、碰撞检测(敌机与本机,子弹与敌机)、绘制图像(根据前几步骤,确定场上的子弹、子弹、本机的位置并画出)、全员更新(例如敌机逼近,子弹前行)。

第二步:游戏窗口

游戏窗口的创建:

    SCREEN_RECT = pygame.Rect(0,0,480,720)
    self.screen = pygame.display.set_mode(SCREEN_RECT.size)   #常量 > 700

主屏上将会承载接下来所有的元素,且应该给玩家留有反应空间,长方形最佳。
这里运用到了pygame.Rect类,传入参数(left, top, width, height),随后在set_mode函数中传入隶属于Rect类、名叫SCREEN_RECT对象的size:(480,720)。于是一个宽480,长720的游戏窗口便建立完成。

第三步:敌机精灵

飞机大战类似雷电,本次游戏中,敌机出现的位置,数量,飞行速度和外观均为随机。
这里运用到了pygame库中精灵与精灵组(类)的概念:https://blog.csdn.net/houyanhua1/article/details/84193317。而在该类中,比较重要的有image,rect,最为关键亦是最为常用的是update成员函数,我们往往因自身需求改写该函数。

	class GameSprite(pygame.sprite.Sprite):  #(继承父类) 其中sprite是模块 Sprite是类名称
	    '''飞机大战游戏精灵'''
	    #构造函数/初始化
	    def __init__(self,image_name,speed = 1):
	        #调用父类初始化方法
	        super().__init__()
	        #定义对象的属性
	        self.image = pygame.image.load(image_name)
	        self.rect = self.image.get_rect()  #图像的属性
	        self.speed = speed
	
	    def update(self, *args):    #*args 一定保留
	        #屏幕上垂直移动
	        self.rect.y += self.speed

创建精灵类,继承自pygame.sprite.Sprite,增添初始化函数内容,写入装载img,设置rect内容。updata函数用于更新状态,例如敌机、子弹不断前进。

	class Enemy(GameSprite):
	    def __init__(self):
	        #调用父类 指定图片
	        super().__init__("./image/enemy1.png")
	        #指定随机速度
	        self.speed = random.randint(1,3)
	        #敌机初始位置
	        #垂直方向
	        self.rect.bottom = 0
	        #水平方向 加以限定 只在游戏界面出现
	        max_x = SCREEN_RECT.width - self.rect.width
	        self.rect.x = random.randint(0,max_x)

	    def update(self, *args):
	        super().update()
	        #若敌机飞出游戏屏幕
	        if self.rect.y >= SCREEN_RECT.height:
	            #将精灵从所有的组移出  并被del调用
	            self.kill()
	            #print("飞出了屏幕")

敌机类继承精灵类,于初始化中定义了几种属性。此外,当敌机自上而下飞出游戏屏幕时,需要销毁,无限增加敌机会给电脑带来很大负担。
出现了一个新的问题:一个敌机出现后,在更新画图的时候调用enemy1.update()便有了数据上的位移,但是实际情况上,游戏中敌机数量往往很多,难道需要一个个调用成员函数?
利用pygame中精灵组,定义定时产生敌机事件并且监听,产生后将其放入一个敌机精灵组,在需要绘制时,对精灵组进行更新即可。

	#创建敌机的定时器常量
	CREATE_ENEMY_EVENT = pygame.USEREVENT  #用户事件的常量
	pygame.time.set_timer(CREATE_ENEMY_EVENT,1000)  #时间一到,触发名叫CREAT_ENEMY_EVENT的事件
	
	#事件监听
	for event in pygame.event.get():
	    if event.type == CREATE_ENEMY_EVENT:
               #创建敌机精灵
               enemy = Enemy()
               #添加到精灵组
               self.enemy_group.add(enemy)
    
    #更新并绘制敌机精灵组
    def __updata_sprites(self):
    	#精灵组调用update
	    self.enemy_group.update()
    	self.enemy_group.draw(self.screen)

第四步:动态背景

在没有摁键摁下的时候,本机是静止的,为了营造飞翔的视觉效果,采用背景动态划动的做法。两张相同的图上下相连,持续向下位移,循环初始。
持续移动,装载图片,拥有长宽属性,这不恰恰和自己定义的GameSprite类很像似?同样的道理,本机,子弹都拥有着相似的属性,我们只需要继承并改写就好。

	class Background(GameSprite):
    	"""游戏背景精灵"""
	    def __init__(self,is_alt=False):
	        #调用父类方法
	        super().__init__("./image/background.png")   #传入背景图片
	        #判断图像
	        if is_alt:
	            self.rect.y = -self.rect.height
	    def update(self, *args):
	        #1.调用父类的更新,默认速度为1
	        super().update()
	        #2.判断是否移出屏幕
	        if self.rect.y >= SCREEN_RECT.height:
	            self.rect.y = -self.rect.height
    
	def __create_sprites(self):
	        #背景精灵组
	        bg1 = Background()
	        bg2 = Background(1)
	        self.back_group = pygame.sprite.Group(bg1,bg2)
	
	#更新并绘制
    self.back_group.update()
    self.back_group.draw(self.screen)
发布了3 篇原创文章 · 获赞 0 · 访问量 220

猜你喜欢

转载自blog.csdn.net/chunqingzhanna/article/details/104082945