洗礼灵魂,修炼python(41)--巩固篇—从游戏《绝地求生-大逃杀》中回顾面向对象编程

时间:2022-12-17 14:50:35

声明:本篇文章仅仅以游戏《绝地求生》作为一个参考话题来介绍面向对象编程,只是作为学术引用,其制作的非常简易的程序也不会作为商业用途,与蓝洞公司无关。

洗礼灵魂,修炼python(41)--巩固篇—从游戏《绝地求生-大逃杀》中回顾面向对象编程

《绝地求生》最近很火,笼络了全球各地一大批玩家玩这个游戏,实话说,这游戏真不错,有了这个游戏后,当你去网吧时看到的屏幕终于不再清一色的《英雄联盟》界面了,98元就可以买《绝地求生》来玩,这个价格大众都比较能接受。简短介绍一下,游戏一开始,各个玩家都相同境遇,一无所有,赤手空拳,可以前后左右,跑,跳,还有趴下,再没有什么技能,然后乘坐飞机到达一个岛屿,每个岛屿固定有100个玩家同时存在,岛上有各种物资(各种枪,各种手雷,医疗包,绷带,肾上腺激素,头盔,汽车,摩托车,轮船等)供你捡起使用,然后每个玩家都是对立面,相互厮杀,最后一个存活的玩家获胜,屏幕出现“大吉大利,今晚吃鸡”的祝贺语。那么你有没有想过这么好玩的游戏,是怎么设计出来的?如果让你设计一个这种类型的游戏呢?有什么想法?

我们先考虑一下整个游戏的属性,然后做个简单的:

#player1
name='yang'             #玩家昵称
power=100               #生命值
pistol='P18C'           #手枪
grenade='Frag Grenade'  #手榴弹

#player2
name='lin'              #玩家昵称
power=100               #生命值
pistol='P18C'           #手枪
car='Dacia 1300'        #车

#player3
name='can'              #玩家昵称
power=100               #生命值
Bandage='Bandage'       #绷带
car='Dacia 1300'        #车

简单的三个玩家就创建好了,但是发现,这人太少了,玩着没劲对吧?所以我们可以利用字典,创建多个角色试试:

player={
    'player1':{
                name:'yang'
                power:100
                pistol:'P18C'
                grenade='Frag Grenade'
        }
    'player2':{
                name:'lin'
                power:100
                pistol:'P18C'
                car:'Dacia 1300'
        }

    'player3':{
                name='can'
                power=100
                Bandage='Bandage'
                car='Dacia 1300'
        }
    'player3':{
                name='lin'
                power=100
                Bandage='Bandage'
                pistol:'P18C'
                grenade='Frag Grenade'
                }

    'player4':{
                name:'cheng'
                power:100
                pistol:'P18C'
                Bandage='Bandage'
                car='Dacia 1300'
                }
    '………………'    
    'player10':{
                name:'cheng'
                power:100
                pistol:'P18C'
                Bandage='Bandage'
                car='Dacia 1300'
                }
    }

好的,在重复操作了10次后,我们把所有玩家创建好了,这样以后调用这些角色时只需要pleyer[pleyer1],pleyer[pleyer2]就可以建立一个玩家了。但是下面的玩家特性并没有体现出来:

  • 捡东西
  • 获取车后可以开车
  • 获取手枪后可以射击
  • 换子弹
  • 被打中后就会掉血
  • 获取狙击枪可以瞄准爆头
  • 走、跑、跳、趴下(藏起来)动作
  • 获取绷带等医疗设备后可以治疗回血

………………

这些功能怎么实现呢?

那么我们得想一个高级用法了,换成自定义函数:

def pick_up(name,goods):
    print('物品%s被玩家%s捡起'%(goods,name))

def car(name):
    print('玩家%s获取到一辆车'%name)

def  shot(name):
    print('玩家%s作射击操作,子弹减1'%name)    

def by_shot(name):
    print('玩家%s被射中,生命值降低'%name)
    name[power]-=10
  

………………

跟着这个思路继续这样下去,相信要不了多久就能把这些特性做好,然后给每个玩家使用。但是,有几个问题需要注意:

1.每生成一个玩家,我都要手动再设置一下属性和属性名等等,这样是很累不说,代码重复性太高,并且如果在添加玩家时把属性名输入错误,那么后面调用函数就会报错

2.每个玩家在捡到不同物品时,会有不同的属性存在,有的捡到枪,有的没捡到,更有的好几把枪,并且有的是步枪,有的是狙击枪,子弹数和枪的属性也不同,有的有车,有的有医疗用品,有的没有,这些等等的问题,都是没有相对性的解决的。

3.在玩家被射中的时候,射击者的子弹要减少,被射击者要减血等等的,但是如果这个程序被投入使用,别人直接把生成玩家的字典里的属性改了,比如把生命值改为100000000……,反正你无论多少枪都打不死我,这不就成了BUG了对吧?所以我们需要设置成不可更改,有人说设置成元组啊,就不可更改了,但是那么后期作为开发者的我们要更改呢?也改不了了

4.后期如果根据不同需求改进时,需要增加或减少属性,这样得改最底层的代码,然后如果改错,则导致与之有关联的全部被改到,那么后果很严重,并且就算没有改错,工程量也挺大,当然你可以用装饰器动态的增删功能,但是按照以上的代码操作,使用装饰器是不是有点蹩脚?装饰器只适用于对函数操作,我最底层的数据是字典啊

5.如果增加的新的玩法,新的模式(比如据说绝地求生要出僵尸模式),那么为了保证数据不被改动,在新的模式下,可能又得重新设置不同玩家在获取新的不同物品后新增的不同属性,还有僵尸模式,当玩家成为僵尸时,之前的属性哪些会失效,又会新增哪些属性?

6.………………………

总之,问题多多,需要我们修改,工程量太大,后期也不好维护,所以使用函数+字典是不行的,说了那么多,我想,你应该要问,搞了那么久,直接上类啊,用面向对象编程啊,是的,在这样的场景下,我们选择面向对象编程是最好的办法

# -*- coding:utf-8 -*-

import time

class Player(object):

    def __init__(self,name,sex='male',dress='base dress'):
        self.name=name          #玩家昵称
        self.sex=sex            #玩家选择角色性别
        self.power=100          #生命值
        self.dress=dress        #默认服饰        

        #游戏中的隐藏属性(暂时只以这几个为例)
        self.pack=0             #背包容纳物品数
        self.monney=0           #金币数
        self.bullet=0           #子弹数
        self.grenade=0          #手榴弹数
        self.bandage=0          #绷带
        self.pistol=0           #手枪
        self.car=0              #车

        self.goods_dict={
        #载具
        'vehicles':('沙漠赛车','越野车(无顶)','越野车UAZ','轿车','三人摩托车','摩托车','游艇'),
        #消耗品
        'consumables':('肾上腺素注射器','绷带','能量饮料','急救包','燃料','医疗箱','止痛药'),
        #弹药
        'ammo':('300马格南','.45口径','12号口径','5.56毫米','7.62毫米','9毫米'),
        #投掷物
        'missile':('碎片手雷','燃烧瓶','烟雾弹','震爆弹'),
        #霰弹枪
        'scatter_gun':('S12K','S1897','S686'),
        #狙击步枪
        'Sniper_rifle':('AWM','十字弩','Karabiner98','Kurz','M24','Mini14','Mk14EBR','SKS','VSSVintorez'),
        #突击步枪
        'Assault_rifle':('AKM','Groza','M16A4','M416','SCAR-L'),
        #冲锋枪
        'SMGs':('MicroUZI','TommyGun','UMP9','Vector'),
        #手枪
        'Pistol':('P18C','P1911','P92','R1895')
            }

        print('角色%s创建成功'%self.name)

    #基本动作方法
    def walking(self):
        print('玩家%s正在走路'%self.name)

    def running(self):
        print('玩家%s正在奔跑'%self.name)

    def fall(self):
        print('玩家%s作趴下动作'%self.name)

    #检测角色生命值的方法,当生命值一有变化就调用一次本方法
    def  testing_power(self):
        if not self.power:
            print('感谢使用我们的产品')

            #令这些值为零,可以触发每个技能调用时的检测功能,致使所有功能无法使用
            self.pack=0
            self.monney=0
            self.bullet=0
            self.grenade=0
            self.bandage=0
            self.pistol=0
            self.car=0

    #捡起物品动作,放进背包
    def pick_up(self,goods):
        print('物品“%s”被玩家%s捡起'%(goods,self.name))

        if goods in self.goods_dict['vehicles']:  #车
            self.car=1   #如果捡到的物品是载具,直接令载具数等于1,而不是加等于1,可以避免同时有两辆汽车的可能

        if goods in self.goods_dict['Pistol']: #手枪
            self.pack+=1
            self.pistol+=1
            if self.pack>=150:  #背包数量限制,默认最大150,暂只考虑一个等级的背包
                print('背包已满')
                self.pack-=1
                self.pistol-=1

        if goods == self.goods_dict['consumables'][1]: #绷带
            self.pack+=1
            self.bandage+=1
            if self.pack>=150:
                print('背包已满')
                self.pack-=1
                self.bandage-=1

        if goods == self.goods_dict['missile'][0]: #手雷
            self.pack+=1
            self.grenade+=1
            if self.pack>=150:
                print('背包已满')
                self.pack-=1
                self.grenade-=1

        if goods == self.goods_dict['ammo'][0]: #子弹
            self.pack+=15
            self.bullet+=15  #假设都是捡到15发子弹
            if self.pack>=150:
                print('背包已满')
                self.pack-=15
                self.bullet-=15

    #需要获得物品才能解锁的技能(暂时只测试这几个功能)
    def by_car(self):

        #检测功能
        if self.car:
            print('玩家%s正在开车'%self.name)
        else:
            print('抱歉,您目前无法使用该功能,因为您目前没有车')

    def by_bandage(self,goods='bandage'):
        if self.bandage:
            print('玩家%s使用绷带回血'%self.name)
            if self.power<100:
                self.power+=10
                print('生命值加10')
                self.bandage-=1
            elif self.power==100:
                print('生命值已满,不能使用疗伤物品')

        else:
            print('抱歉,您目前无法使用该功能,因为您目前没有绷带')
            #have(self,goods)

    def by_grenade(self):
        if self.grenade:
            print('玩家%s扔出手榴弹'%self.name)
            self.grenade-=1
        else:
            print('抱歉,您目前无法使用该功能,因为您目前没有手榴弹')

    def by_shot(self):
        print('玩家%s中弹,生命值减20'%self.name)
        self.power-=20
        self.testing_power()
    def by_headshot(self):
        print('玩家%s被一击毙命,游戏结束!\n 请调用方法exit()退出或者等待3秒自动退出'%self.name)
        self.power=0
        self.testing_power()
        time.sleep(3)
        self.exit()        

    def exit(self):
        print('游戏已退出,请关闭本窗口')

if __name__=='__main__':
    yang=Player('yang')
    lin=Player('lin','women')

简单的测试结果:

洗礼灵魂,修炼python(41)--巩固篇—从游戏《绝地求生-大逃杀》中回顾面向对象编程

洗礼灵魂,修炼python(41)--巩固篇—从游戏《绝地求生-大逃杀》中回顾面向对象编程

有了面向对象的思路来写代码,是不是感觉思路都很清楚,这样的话,是不是觉得很规范有理有据但又不难?

当然你会想,卧槽???就这么简单的程序,调用几次方法得到提示,这就叫游戏,一点体验都没有啊?

是的,还有很多很多需要我们完善

  • 没有游戏模块pygame支持
  • 没有图形化界面
  • 没有注册帐号系统
  • 没有商城交易
  • 缺少连入网络
  • 缺少后期调试维护的后台管理系统
  • 还没有很多的交互式(比如中弹,子弹来自谁,谁的子弹数需要减少,谁得掉血。或者被一击毙命,谁杀了谁,等等的)
  • 捡到的物品还得手动输入
  • 没有查看背包里有哪些物品的功能
  • 并没有对定义的字典数据进行保护(本人思路要嘛改用元组,要嘛设置管理修改权限)
  • ………

这些等等的,好多都没有的,确实,目前这段代码只是一个简单得不能再简单的小型框架,但是已经能完美解决之前在未使用面向对象编程时遇到的等等问题(可能有漏掉的功能,加上就行,感兴趣的自己去完善了)。至于以上的问题,这已经是游戏开发者才需要思考的问题了。并且如果只是用python来搞游戏开发,实话说,是很鸡肋的。小型游戏还差不多,像绝地求生这种大型游戏,抱歉,仅仅靠python真不行,关于其中原因在我的博文第一篇有提到。

所以,通过这个例子,有没有切身的体会到面向对象的强大?

详细的面向对象概念和什么相关的总结不用再说了,前面已经说过,本篇博文和后面几篇博文都将是对面向对象的巩固(也或许是对面向对象编程另一种思维模式的解读),因为真的很重要,所以才一直提这个话题。

不过放心,我也不会一直解析关于面向对象,只是重新走一遍,后期还会有爬虫,web等的项目篇的,所以不会一直浪费时间在面向对象编程这里

洗礼灵魂,修炼python(41)--巩固篇—从游戏《绝地求生-大逃杀》中回顾面向对象编程的更多相关文章

  1. Python 第六篇&lpar;中&rpar;:面向对象编程中级篇

    面向对象编程中级篇: 编程思想概述: 面向过程:根据业务逻辑从上到下写垒代码  #最low,淘汰 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 #混口饭吃 def add(ho ...

  2. Python 中的面向对象编程

    面向对象编程(Object-oriented programming, OOP)是一种基于对象概念的编程范式,可包含属性(attribute)形式的数据以及方法(method)形式的代码.另一种对 O ...

  3. python中的面向对象编程

    在python中几乎可以完成C++里所有面向对象编程的元素. 继承:python支持多继承: class Derived(base1, base2, base3): pass 多态:python中的所 ...

  4. 洗礼灵魂,修炼python(44)--巩固篇—反射之重新认识hasattr,gettattr,setattr,delattr

    不急着进入正题.先动手完成一个小程序: 设计一套简单的服务开启关闭程序,每次开启或关闭都得打印服务当前的状态: class Server(object): def __init__(self): se ...

  5. Python之面向对象编程学习

    不知不觉,学到了python的面向对象编程思想.今天我们来讨论下面向对象编程的思想. 顾名思义,面向对象,就是面向于对象,这里所说的对象不是你现实生活中你的女朋友,你的老婆,你的爱人,在编程的世界里面 ...

  6. 洗礼灵魂,修炼python(85)-- 知识拾遗篇 —— 深度剖析让人幽怨的编码

    编码 这篇博文的主题是,编码问题,老生常谈的问题了对吧?从我这一套的文章来看,前面已经提到好多次编码问题了,的确这个确实很重要,这可是难道了很多能人异士的,当你以为你学懂了,在研究爬虫时你发现你错了, ...

  7. 洗礼灵魂,修炼python(69)--爬虫篇—番外篇之feedparser模块

    feedparser模块 1.简介 feedparser是一个Python的Feed解析库,可以处理RSS ,CDF,Atom .使用它我们可从任何 RSS 或 Atom 订阅源得到标题.链接和文章的 ...

  8. 洗礼灵魂,修炼python(47)--巩固篇—定义类的方法之&commat;classmethod,&commat;staticmethod

    定义类的方法,相信你会说,不就是在class语句下使用def () 就是定义类的方法了嘛,是的,这是定义的方法的一种,而且是最普通的方式 首先,我们已经知道有两种方式: 1.普通方法: 1)与类无关的 ...

  9. 洗礼灵魂,修炼python(48)--巩固篇—模块

    模块 其实前面都说过的,不过还是系统的再说一次,相信学到这,大部分都被搞忘了吧,所以再提一下,也为后面的博文做铺垫 1.什么是模块 在程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越 ...

随机推荐

  1. 今天心情好,给各位免费呈上200兆SVN代码服务器一枚,不谢!

    开篇先给大家讲个我自己的故事,几个月前在网上接了个小软件开发的私活,平日上班时间也比较忙,就中午一会儿休息时间能抽出来倒腾着去做点.每天下班复制一份到U盘带回去继续摸索,没多久U盘里躺着的文件列表那叫 ...

  2. 《JavaScript高级程序设计》第4章 变量、作用域和内存问题

    4.1 基本类型和引用类型 5种基本类型:Undefined.Null.Boolean.Number和String,这5种基本类型是按值访问的,因为可以操作保存在变量中的实际的值. 引用类型:可能由多 ...

  3. IEEE发布2016年度编程语言排行榜

    C 语言占据榜首,但大数据类是最大赢家. IEEE Spectrum 的第三次"最受欢迎编程语言"交互式排行榜新鲜出炉.因为不可能顾及到每一个程序员的想法,Spectrum 使用多 ...

  4. python&lowbar;json常用的方法

    1. 什么是JSON? JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从 Web 客户机传递给服务器端 ...

  5. (六十六)TableView内容超过一屏时滚动到屏幕底部的方法

    假设数据放置在self.chatMessage数组内,只需要让tableView滚动到最后一条数据底部即可,调用scrollToRowAtIndexPath方法: [_tableView reload ...

  6. Docker入门 配置篇

    docker配置 http://www.runoob.com/docker/docker-tutorial.html

  7. SpaceVim的基本安装和常见问题

    SpaceVim官网:https://spacevim.org/ SpaceVim中文官网:http://spacevim.org/cn/ SpaceVim的Github页面:https://gith ...

  8. &lbrack;golang 易犯错误&rsqb; golang 局部变量初始化&colon;&equals;的陷阱

    我们知道,golang中局部变量初始化方法(使用“:=”创建并赋值),让我们在使用变量时很方便.但是,这也是易犯错误的地方之一.特别是这个初始化符还支持多个变量同时初始化,更特别的是它还支持原有变量赋 ...

  9. python&&num;39&semi;s fnmatch&amp&semi;glob&amp&semi;os&period;listdir

    [python's fnmatch&glob&os.listdir] fnmatch: fnmatch只有4种special character,用于提供和shell中一样的文件名的匹 ...

  10. map集合根据value找key,默认取第一个key

    private static String getKey(Map<String,String> map,String value){ String key=""; fo ...