# 代码编写进阶

在已经学习了使用Python来编写逻辑玩法之后,我们还需要学习如何来提高自己的代码的质量。

# 规范

首先我们应该注意自己的代码规范。

零件开发拥有自己的规范,规范中的保留字段已经在之前介绍过了,其他部分的内容较为简单,大家可以自己查阅。

同时还有模组SDK,我们虽然是使用预设玩法和零件编程,进行玩法开发,但是实际上,我们还是使用了部分模组SDK中的函数来进行玩法开发,所以,在这篇规范中,我们可以参考除了命名以外的所有规范。命名由于涉及到一些已经保存了的预设的内部文件路径数据,所以不推荐进行修改。

同时,我们在编写代码的过程中,也需要注意编码规范。这样写出来的代码,不仅不容易出错,自己很容易看懂,也可以让团队里的其他成员更快的理解你的代码。这里我们抽取了官方插件规范中的一部分与代码编写相关的进行说明。

  • 所有类名都是用驼峰法命名,首字母大写,比如类 GameObjectType。
  • 常量都使用驼峰法命名,首字母大写,比如 ModVersion = "0.0.1"
  • 类非静态成员变量使用驼峰法命名,以“m”开头,例如 mLevel。
  • 类非静态成员函数使用驼峰法命名,首字母大写,例如 Init()。
  • event使用驼峰法命名,首字母大写,例如“PlayerTransactionFromClientEvent”
  • 统一用tab而不是四个空格缩进。
  • 例子:
class TitleScreen(ScreenNode):
    def __init__(self, namespace, name, param):
        ScreenNode.__init__(self, namespace, name, param)
        self.mMainPanel = "/main_panel"
        self.mTitleText = self.mMainPanel + "/title_text"
        self.mConfirmButton = self.mMainPanel + "/confirm_button"

    def Create(self):
        """
        @description UI创建成功时调用
        """
        buttonControl = self.GetBaseUIControl(self.mConfirmButton).asButton()
        buttonControl.AddTouchEventParams({"isSwallow": True})
        buttonControl.SetButtonTouchUpCallback(self.OnConfirmButtonClick)

    def OnConfirmButtonClick(self, args):
        text = self.GetBaseUIControl(self.mTitleText).asTextEditBox().GetEditText()
        presetApi.GetPresetByName("TitleScreen").GetPartByName("界面服务端监听").NotifyToServer("TitleEvent", {"text": text})
        clientApi.PopScreen()

# 技巧

# 函数的封装

例如需要求一组数据的平均值,我们可以自己封装一个函数,并在需要使用的时候进行调用,这样会大大提高代码的可读性。

def avg(*args)
	return sum(args) / len(args)

平均值只是一个比较简单的运用,如果不是像平均值这样的简单计算,大量的重复会显得代码很臃肿,并且如果在以后需要修改,就要在每个使用的地方进行修改。相对的,使用函数,我们就可以只在函数的定义处进行修改,从而减少工作量。

# 避免重复运算

假设我们需要使用模组SDK的接口制作一个连锁挖矿的功能,需要调用PlayerDestoryBlock这个接口来挖掘方块,并且已经通过搜索方法找到了要破坏的方块列表为blocks

那么实际上,循环调用PlayerDestoryBlock这个接口时,我们的blockInfoComp的对象是一模一样的。所以我们就可以将获取blockInfoComp放在循环外,然后在循环内只调用blockInfoComp.PlayerDestoryBlock,来减少运算量。

错误的写法:

for pos in blocks:
    blockInfoComp = serverApi.GetEngineCompFactory().CreateBlockInfo(playerId)
    blockInfoComp.PlayerDestoryBlock(pos,1,False)

正确的写法:

blockInfoComp = serverApi.GetEngineCompFactory().CreateBlockInfo(playerId)
for pos in blocks:
    blockInfoComp.PlayerDestoryBlock(pos,1,False)

使用正确的写法,在需要破坏的方块数量大时,极大地提高运行效率。

这种错误是很多新手都会犯的,所以我们查阅接口时,不能不假思索地直接将文档中示例代码直接复制到我们的项目中进行使用。我们应该思考代码中的每一行都是用来干什么的。同时应该清楚,每多执行一行代码,就会有更大的性能开销,如何使用速度更快的代码来实现同样的效果,是值得我们关注的。

# 使用xrange来代替range

xrange是python2独有的一个内置函数,他的用法与 range 完全相同,所不同的是生成的不是一个数组,而是一个生成器。

相比range,它拥有更高的执行效率。

for i in xrange(5):
	print i

# 使用dict来代替多分支if

修改前:

def getXXX(a):
	if a == "a":
    	return 1
    if a == "b":
    	return 2
    if a == "c":
    	return 3
    return 4

修改后:

exampleDict = {"a":1,"b":2,"c":3}
def getXXX(a):
	result = exampleDict.get(a)
    if not result
    	return result
    return 4

相比多个if,直接使用字典来存储数据,并通过get来获取并返回,在数据量大的时候会有更高的效率。

进阶

20分钟

规范

技巧

函数的封装

避免重复运算

使用xrange来代替range

使用dict来代替多分支if