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

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

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



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

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

#定义一个Bullet类,封装子弹的数据和方法
class Bullet(object):
    def __init__(self):
        self.x = 0
        self.y = -100
        self.speed = 600
        self.image = pygame.image.load(bullet_image_filename).convert_alpha()

    def move(self,passed_time_second):
        if self.y < 0:
            mouseX, mouseY = pygame.mouse.get_pos()
            self.x = mouseX - self.image.get_width()/2
            self.y = mouseY - self.image.get_width()/2
        else:
            self.y -= self.speed*passed_time_seconds

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

# -*- coding: utf8 -*-

background_image_filename = ‘background.png‘
mouse_image_filename = ‘hero.png‘
bullet_image_filename = ‘bullet.png‘
#指定图像文件名称

import pygame #导入pygame库
from sys import exit #向sys模块借一个exit函数用来退出程序

#定义一个Bullet类,封装子弹的数据和方法
class Bullet(object):
    def __init__(self):
        self.x = 0
        self.y = -100
        self.speed = 600
        self.image = pygame.image.load(bullet_image_filename).convert_alpha()

    def move(self, passed_time_second):
        if self.y < 0:
            mouseX, mouseY = pygame.mouse.get_pos()
            self.x = mouseX - self.image.get_width()/2
            self.y = mouseY - self.image.get_width()/2
        else:
            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()
while True:
#游戏主循环

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            #接收到退出事件后退出程序
            pygame.quit()
            exit()
    time_passed = clock.tick(100)
    time_passed_second = time_passed/1000.0
    screen.blit(background, (0,0))
    #将背景图画上去
    x, y = pygame.mouse.get_pos()
    #获得鼠标位置
    bullet.move(time_passed_second)#移动子弹

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

    screen.blit(bullet.image, (bullet.x, bullet.y))
    screen.blit(mouse_cursor, (x, y))
    #把元素画上去

    pygame.display.update()
    #刷新一下画面

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



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

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

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

class Enemy(object):#定义一个Enemy类,封装敌机的数据和方法
    def __init__(self):
        self.x = 200
        self.y = -50
        self.speed = 200
        self.image = pygame.image.load(enemy_image_filename).convert_alpha()

    def move(self, passed_time_second):
        if self.y < 650:
            self.y += self.speed*passed_time_second
        else:
            self.y = -50

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

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

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

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

from random import randint

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

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

class Enemy(object):#定义一个Enemy类,封装敌机的数据和方法
    def restart(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()

    def move(self, passed_time_second):
        if self.y < 650:
            self.y += self.speed*passed_time_second
        else:
            self.restart()

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

整体的代码如下:

# -*- coding: utf8 -*-

background_image_filename = ‘background.png‘
mouse_image_filename = ‘hero.png‘
bullet_image_filename = ‘bullet.png‘
enemy_image_filename = ‘enemy.png‘
#指定图像文件名称

import pygame #导入pygame库
from sys import exit #向sys模块借一个exit函数用来退出程序
from random import randint #引入随机数

#定义一个Bullet类,封装子弹的数据和方法
class Bullet(object):
    def __init__(self):
        self.x = 0
        self.y = -100
        self.speed = 600
        self.image = pygame.image.load(bullet_image_filename).convert_alpha()

    def move(self, passed_time_second):
        if self.y < 0:
            mouseX, mouseY = pygame.mouse.get_pos()
            self.x = mouseX - self.image.get_width()/2
            self.y = mouseY - self.image.get_width()/2
        else:
            self.y -= self.speed*passed_time_second

class Enemy(object):#定义一个Enemy类,封装敌机的数据和方法
    def restart(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()

    def move(self, passed_time_second):
        if self.y < 650:
            self.y += self.speed*passed_time_second
        else:
            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()
while True:
#游戏主循环

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            #接收到退出事件后退出程序
            pygame.quit()
            exit()
    time_passed = clock.tick(100)
    time_passed_second = time_passed/1000.0
    screen.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() / 2
    y-= 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()
    #刷新一下画面


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

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

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



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

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

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

时间: 2024-07-30 13:38:14

2015/11/5用Python写游戏,pygame入门(5):面向对象的游戏设计的相关文章

2015/11/1用Python写游戏,pygame入门(1):pygame的安装

这两天学习数据结构和算法,有时感觉并不如直接做项目来的有趣.刚刚学完python的基本使用,现在刚好趁热打铁做个小项目. 由于本人一直很想制作一款游戏,就想使用Python制作一个基础的游戏.搜了一下资料,看到一个很便于使用的库,也就是pygame. pygame介绍 pygame是一个建立在SDL(Simple DirectMedia Layer)上的Python模块,是一个跨平台模块.SDL是用C写的,也可以用C++开发,也有很多语言,pygame就是一个Python中使用的库. 安装pyg

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

昨天我们已经实现了这个游戏的三个基本类. 但是现在它还是没办法做成一个适合玩的游戏,毕竟只有一架敌机的游戏是很乏味的.所以,我们需要好多子弹,也需要好多敌机. 所以,我们要创建list,这个list存放Bullet或者Enemy的实例. 以Bullet为例: bullet = [] #创建子弹 for i in range(6): bullet.append(Bullet()) ... for b in bullet:#移动子弹 b.move(time_passed_second) ... fo

2015/11/7用Python写游戏,pygame入门(7):碰撞检测

我们已经完成了飞机大战的大部分东西,但是游戏还是没有办法正式开玩,因为子弹并不能打掉飞机.只有完成了这一个工作,游戏才算基本成型. 今天的内容就非常简单了,就是做到这个碰撞检测,以及控制好子弹和飞机的消失.pygame里的sprite模块里有碰撞检测部分,但是,我们这里自己动手实现一个碰撞检测的函数. 检测碰撞的方法很简单,就是子弹的位置在飞机图片的内部.由于子弹和飞机的速度比较快,所以不需要非常精确地判别. 我们认为,如果子弹的坐标(b.x, b.y)在飞机的图片范围内,也就是(e.x, e,

2018用Python写网络爬虫(视频+源码+资料)

课程目标实现Python写网络爬虫入门适用人群数据零基础爱好者,职场新人 ,在校大学生课程简介1.基本Http请求以及验证方式分析 2.Python用于处理Html格式数据beautifulsoup模块3.Pyhton的requests模块的使用并实现爬取B站.网易云.微博.内涵段子等网站4.异步IO模块的使用,如:asyncio.gevent.aiohttp.twisted.torando 5.自定义异步IO模块 6.Scrapy框架的使用以及应用 下载地址:百度网盘 原文地址:http://

游戏编程入门

<游戏编程入门>是2005年由人民邮电出版社出版的图书,该书作者是king,译者是虹夜.游戏编程入门介绍了如何设计和构建自己的电脑游戏. 游戏编程入门适用于任何对C++语言有基本了解的读者阅读,适宜作为读者进入游戏开发领域的技术入门学习用书.游戏编程入门介绍如何设计和构建自己的电脑游戏.游戏编程入门不是泛泛地介绍编程理论,而是引导读者开发一个“即插即用”的游戏引擎,可以增强和重用这个游戏引擎以开发各种游戏.QKXue.NTE友情提示:书中包括了7个完整游戏的详尽解释以及示例代码,使读者准备好开

Pygame - Python游戏编程入门(0)

引言 博客刚开,想把最近学习的东西记录下来,算是一种笔记.最近打算开始学习Python,因为我感觉Python是一门很有意思的语言,很早以前就想学了(碍于懒),它的功能很强大,你可以用它来做科学运算,或者数字图像处理,或者任务的自动化,还可以构建动态网站,很多很多听起来就很有意思的实现.关于Python你还可以找到更多的资料,这里不一一赘述. 一说到开始学习一门新的编程语言,很多童鞋可能马上想到,“嗯,哥去买本书啃啃!”,结果买了本大部头,全是枯燥的语法知识,看了后面忘了前面,事倍功半.记得以前

python写的第一个简单小游戏-猜数字

1 #Filename:game1.py 2 3 guess=10 4 running=True 5 while running: 6 try: 7 answer=int(raw_input('Guess what i think:')) 8 except: 9 print 'Please input interga\n' 10 continue 11 12 if answer<guess: 13 print 'Your answer is too small\n' 14 continue 15

python写游戏运维管理后台

最近在用python写游戏运维管理的后台,待功能完善后放源码,大致功能如下: 有兴趣的可以加我一起来做.

Python入门学习:一步步教你怎么用Python写贪吃蛇游戏

前几天,有人提到贪吃蛇,一下子就勾起了我的兴趣,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Python(蛇)玩Snake(贪吃蛇),再合适不过了. 这里通过一个Python入门学习的例子跟大家详细讲解一下! 先通过下面这个效果图来感受下吧! 1 环境 操作系统:Windows Python版本:3.7.3 2 需求分析 我们先来回顾下贪吃蛇中的游戏元素及游戏规则. 首先呢,需要有贪吃蛇.有食物:需要能控制贪吃蛇来上下移动获取食物:贪吃蛇在吃取食物后,自身长度增加,同时食物消