2015/11/6用Python写游戏,pygame入门:控制大量的对象

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

昨天我们已经实现了这个游戏的三个基本类。

但是现在它还是没办法做成一个适合玩的游戏,毕竟只有一架敌机的游戏是很乏味的。所以,我们需要好多子弹,也需要好多敌机。

所以,我们要创建list,这个list存放Bullet或者Enemy的实例。

以Bullet为例:

bullet = []#创建子弹foriinrange(6):

bullet.append(Bullet())

...forbinbullet:#移动子弹b.move(time_passed_second)

...forbinbullet:#显示子弹screen.blit(b.image, (b.x, b.y))

我们可以用这样的代码替换我们原来创建子弹,移动子弹和显示子弹的部分。但是实际运行结果却并没有变化。这是为什么?

因为一个list的子弹都按照了同样的方法创建和发射了,所有的子弹在同一时间发射了出去,同时到达了屏幕上方,然后又同时发射。这样的效果和发射一发子弹是没有区别的。所以我们要让它按照一定的时间间隔,一个个地发射。

另外,如果到了屏幕顶端就回头了,重新发射的子弹和按时发射的子弹混在了一起,打乱了发射节奏,所以子弹回收的方法也要更改。我们可以选择每发子弹只写它的发射,不写它的回收,但是这样每发射一发子弹就会创建一个空间,读取一次图片,这样会消耗内存资源,一般都应该避免。

那么我们必须解决两个问题,一个是定时发射,一个是回收子弹。

Python有专门的time模块,但是,在游戏中,我们本来就有帧率固定的循环,只要用一个计数器来计数,每隔多少个循环出发一次,就可以实现定时效果。

比如说,我们定义一个子弹发射的间隔interval_bullet,让它递增或者递减,到达某个数后,就重置间隔,并且运行特定的程序,就可以使子弹定时发射。

如果要重复利用子弹,我们可以让子弹本身多一个属性,来表明这个子弹是否应该被激活,只有它是激活状态,我们去处理它的运动和显示。

子弹本身是可以重复利用的,我们用一个循环队列的结构来处理子弹的利用。

依照这样的方法,我们可以修改Bullet类:

classBullet(object):def__init__(self):

self.x=0

self.y= -100self.speed= 600self.image=pygame.image.load(bullet_image_filename).convert_alpha()

self.active=Falsedefmove(self, passed_time_second):ifself.y <0:

self.active=Falseelse:

self.y-= self.speed*passed_time_seconddefrestart(self):

self.active=True

mouseX, mouseY=pygame.mouse.get_pos()

self.x= mouseX - self.image.get_width()/2self.y= mouseY - self.image.get_width()/2

添加了一个重新激活该子弹的方法restart(),还添加了一个数据属性active来标记子弹本身是否被激活。然后,我们把添加子弹,移动子弹,显示子弹部分的代码改成这样:

bullet =[]foriinrange(6):#子弹总数量bullet.append(Bullet())

interval_bullet= 25#发射子弹的帧数间隔index_bullet = 0#初始化子弹坐标...

interval_bullet-= 1ifinterval_bullet <=0:

interval_bullet= 25bullet[index_bullet].restart()

index_bullet= (index_bullet + 1) % 6forbinbullet:ifb.active:

b.move(time_passed_second)#移动子弹screen.blit(b.image, (b.x, b.y))#显示子弹

结果就是这样了:

子弹完成了以后,飞机还会远么?

大家可以自己想一想敌机应该怎么去写,敌机不同的是,前后的间隔应该有更多的随机性。

我这里就不给出一步步的指南了,把自己实现的代码整个贴上来,也许大家有更好的控制方式,可以一起交流一下:

#-*- coding: utf8 -*-background_image_filename='background.png'mouse_image_filename='hero.png'bullet_image_filename='bullet.png'enemy_image_filename='enemy.png'#指定图像文件名称importpygame#导入pygame库fromsysimportexit#向sys模块借一个exit函数用来退出程序fromrandomimportrandint#引入随机数#定义一个Bullet类,封装子弹的数据和方法classBullet(object):def__init__(self):

self.x=0

self.y= -100self.speed= 600self.image=pygame.image.load(bullet_image_filename).convert_alpha()

self.active=Falsedefmove(self, passed_time_second):ifself.y <0:

self.active=Falseelse:

self.y-= self.speed*passed_time_seconddefrestart(self):

self.active=True

mouseX, mouseY=pygame.mouse.get_pos()

self.x= mouseX - self.image.get_width()/2self.y= mouseY - self.image.get_width()/2classEnemy(object):#定义一个Enemy类,封装敌机的数据和方法defrestart(self):

self.x= randint(-30,400)

self.y= randint(-100, -50)

self.speed= randint(100,400)

self.active=Truedef__init__(self):

self.restart()

self.active=False

self.image=pygame.image.load(enemy_image_filename).convert_alpha()defmove(self, passed_time_second):ifself.y < 650:

self.y+= self.speed*passed_time_secondelse:

self.active=False

pygame.init()#初始化pygame,为使用硬件做准备screen = pygame.display.set_mode((480, 650), 0, 32)#创建了一个窗口pygame.display.set_caption("PlaneFight!")#设置窗口标题pygame.mouse.set_visible(False)

background=pygame.image.load(background_image_filename).convert()

mouse_cursor=pygame.image.load(mouse_image_filename).convert_alpha()#加载并转换图像bullet =[]foriinrange(6):#子弹总数量bullet.append(Bullet())

interval_bullet= 25#发射子弹的帧数间隔index_bullet = 0#初始化子弹坐标enemy =[]foriinrange(10):#敌机总数量enemy.append(Enemy())

interval_enemy= 100#敌机出现的间隔index_enemy = 0#初始化敌机坐标clock =pygame.time.Clock()whileTrue:#游戏主循环foreventinpygame.event.get():ifevent.type ==pygame.QUIT:#接收到退出事件后退出程序pygame.quit()

exit()

time_passed= clock.tick(100)

time_passed_second= time_passed/1000.0screen.blit(background, (0,0))#将背景图画上去x, y =pygame.mouse.get_pos()#获得鼠标位置interval_bullet-= 1ifinterval_bullet <=0:

interval_bullet= 25bullet[index_bullet].restart()#重置子弹index_bullet = (index_bullet + 1) % 6#循环递增forbinbullet:ifb.active:

b.move(time_passed_second)#移动子弹screen.blit(b.image, (b.x, b.y))#显示子弹interval_enemy-= 1ifinterval_enemy <=0:

interval_enemy= randint(30,100)

enemy[index_enemy].restart()#重置飞机index_enemy = (index_enemy + 1) % 10#循环递增foreinenemy:ife.active:

e.move(time_passed_second)#移动敌机screen.blit(e.image, (e.x, e.y))#显示敌机x-= mouse_cursor.get_width() / 2y-= mouse_cursor.get_height() / 2#计算光标的左上角位置#screen.blit(bullet.image, (bullet.x, bullet.y))screen.blit(mouse_cursor, (x, y))#把各个元素画上去pygame.display.update()#刷新一下画面

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航