2015/11/5用Python写游戏,pygame入门:面向对象的游戏设计

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

昨天的内容里有了运动的子弹,虽然我们只添加了一个子弹,但你可以看到我们需要记录子弹的x,y坐标,每次要更新它的坐标。如果我们想要有多颗子弹,就需要存储多个坐标。那时候处理起来就不显得那么简单,也许我们可以使用两个list,一个专门存储各个子弹的x坐标,另一个专门存储子弹的y坐标,问题似乎变得没那么复杂,写起来会简单一些。但是我们到现在还没有加入过敌机,如果加入了敌机,加入别的东西的设计,我们将需要很多不同的数据的存储。虽然一个思路清晰的程序员可以记住所有的坐标存储在哪个list里,但是这毕竟比较麻烦。那有什么方法呢?

这就需要提到程序语言的数据抽象方法了,也就是面向对象的抽象方法,可以让我们更好地处理数据。

面向对象的关键在于封装,我们来看看应该怎样封装一个子弹。

描述一个子弹,最主要要用的就是它的图片,坐标的位置。它需要的就这么多,还有是一段处理子弹显示的代码。

#定义一个Bullet类,封装子弹的数据和方法classBullet(object):def__init__(self):

self.x=0

self.y= -100self.speed= 600self.image=pygame.image.load(bullet_image_filename).convert_alpha()defmove(self,passed_time_second):ifself.y <0:

mouseX, mouseY=pygame.mouse.get_pos()

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

self.y-= self.speed*passed_time_seconds

这段代码的写法和昨天写的完全一样,但是用了面向对象的写法。然后我们将昨天的代码更改一下:

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

self.x=0

self.y= -100self.speed= 600self.image=pygame.image.load(bullet_image_filename).convert_alpha()defmove(self, passed_time_second):ifself.y <0:

mouseX, mouseY=pygame.mouse.get_pos()

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

self.y-= self.speed*passed_time_second

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=Bullet()

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()#获得鼠标位置bullet.move(time_passed_second)#移动子弹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()#刷新一下画面

这样,我们就掌握了子弹的创建方法。

我们用同样的思路去考虑敌机应该怎样创建。

敌机需要封装的数据,主要也是图片,坐标。以及封装一个处理它坐标变化的方法。

那么我们就可以定义敌机的类:

classEnemy(object):#定义一个Enemy类,封装敌机的数据和方法def__init__(self):

self.x= 200self.y= -50self.speed= 200self.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.y= -50

然后用相同的方法给它实例化,显示,就可以得到这样的画面:

敌机和子弹一样,我们就将它显示了出来。

但是,这里有个很明显的问题,那就是敌机每次都从上面的中间飞到下面的中间,和真实游戏相差很多,怎么才能让它多变呢?

这里我们可以import另外一个常用的库了,也就是random

fromrandomimportrandint

在开始加上这一句,引入randint(),这个方法用于生成随机整数,可以给它两个参数,分别作为下界和上界,使用时下界不能比上界大。

然后我们把这个Enemy类改写成这样:

classEnemy(object):#定义一个Enemy类,封装敌机的数据和方法defrestart(self):

self.x= randint(-30,400)

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

self.speed= randint(100,400)def__init__(self):

self.restart()

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.restart()

这样,敌机的出现速度,出现位置都会发生变化,就显得没有那么呆板了。

整体的代码如下:

#-*- 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()defmove(self, passed_time_second):ifself.y <0:

mouseX, mouseY=pygame.mouse.get_pos()

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

self.y-= self.speed*passed_time_secondclassEnemy(object):#定义一个Enemy类,封装敌机的数据和方法defrestart(self):

self.x= randint(-30,400)

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

self.speed= randint(100,400)def__init__(self):

self.restart()

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.restart()

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=Bullet()

enemy=Enemy()

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()#获得鼠标位置bullet.move(time_passed_second)#移动子弹enemy.move(time_passed_second)

x-= mouse_cursor.get_width() / 2y-= mouse_cursor.get_height() / 2#计算光标的左上角位置screen.blit(enemy.image, (enemy.x, enemy.y))

screen.blit(bullet.image, (bullet.x, bullet.y))

screen.blit(mouse_cursor, (x, y))#把各个元素画上去pygame.display.update()#刷新一下画面

今天除了将程序方法改成了面向对象以外,基本上也没有多讲什么。

现在,飞机只有一架,子弹只有一发,敌机也只有一架,感觉不出面向对象的威力,但当它数目多起来时,你会觉得面向对象的抽象的确很省事。

明天我就来给出我的多架飞机的方法。

由于我最近事情比较多,这个更新也写的很拖沓,每天只讲了一点点。对于每天在试着做的人来讲是太慢了。不过我每天都会坚持更新,直到把这个游戏搭建起来。

觉得我讲的慢的朋友,有两个方法,一是自己试着查一些资料,二是先不管我的更新,一周以后再看,到时候就可以看到比较多的变化。

最近比较忙,没办法一气呵成,不好意思了。

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