Files
2025-03-17 13:24:39 +08:00

130 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
front:
hard: 进阶
time: 20分钟
---
# 代码编写进阶
在已经学习了使用Python来编写逻辑玩法之后我们还需要学习如何来提高自己的代码的质量。
<iframe src="https://cc.163.com/act/m/daily/iframeplayer/?id=6328686fc6dfd1bb76f1d13c" width="800" height="600" allow="fullscreen"/>
## 规范
首先我们应该注意自己的代码规范。
零件开发拥有自己的<a href="../../../../mcguide/20-玩法开发/14-预设玩法编程/2-深入理解零件/6-零件开发规范.html?catalog=1">规范</a>,规范中的保留字段已经在之前介绍过了,其他部分的内容较为简单,大家可以自己查阅。
同时还有<a href="../../../../mcguide/20-玩法开发/13-模组SDK编程/20-制作规范.html?catalog=1">模组SDK</a>我们虽然是使用预设玩法和零件编程进行玩法开发但是实际上我们还是使用了部分模组SDK中的函数来进行玩法开发所以在这篇规范中我们可以参考**除了命名**以外的所有规范。命名由于涉及到一些已经保存了的预设的内部文件路径数据,所以不推荐进行修改。
同时,我们在编写代码的过程中,也需要注意编码规范。这样写出来的代码,不仅不容易出错,自己很容易看懂,也可以让团队里的其他成员更快的理解你的代码。这里我们抽取了<a href="../../../../mcguide/27-网络游戏/课程6插件教学/第1节官网插件规范.html?catalog=1">官方插件规范</a>中的一部分与代码编写相关的进行说明。
- 所有类名都是用驼峰法命名,首字母大写,比如类 GameObjectType。
- 常量都使用驼峰法命名,首字母大写,比如 ModVersion = "0.0.1"
- 类非静态成员变量使用驼峰法命名以“m”开头例如 mLevel。
- 类非静态成员函数使用驼峰法命名,首字母大写,例如 Init()。
- event使用驼峰法命名首字母大写例如“PlayerTransactionFromClientEvent”
- 统一用tab而不是四个空格缩进。
- 例子:
```python
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()
```
## 技巧
### 函数的封装
例如需要求一组数据的平均值,我们可以自己封装一个函数,并在需要使用的时候进行调用,这样会大大提高代码的可读性。
```python
def avg(*args)
return sum(args) / len(args)
```
平均值只是一个比较简单的运用,如果不是像平均值这样的简单计算,大量的重复会显得代码很臃肿,并且如果在以后需要修改,就要在每个使用的地方进行修改。相对的,使用函数,我们就可以只在函数的定义处进行修改,从而减少工作量。
### 避免重复运算
假设我们需要使用模组SDK的接口制作一个连锁挖矿的功能需要调用`PlayerDestoryBlock`这个接口来挖掘方块,并且已经通过搜索方法找到了要破坏的方块列表为`blocks`
那么实际上,循环调用`PlayerDestoryBlock`这个接口时我们的blockInfoComp的对象是一模一样的。所以我们就可以将获取blockInfoComp放在循环外然后在循环内只调用`blockInfoComp.PlayerDestoryBlock`,来减少运算量。
错误的写法:
```python
for pos in blocks:
blockInfoComp = serverApi.GetEngineCompFactory().CreateBlockInfo(playerId)
blockInfoComp.PlayerDestoryBlock(pos,1,False)
```
正确的写法:
```python
blockInfoComp = serverApi.GetEngineCompFactory().CreateBlockInfo(playerId)
for pos in blocks:
blockInfoComp.PlayerDestoryBlock(pos,1,False)
```
使用正确的写法,在需要破坏的方块数量大时,极大地提高运行效率。
这种错误是很多新手都会犯的,所以我们查阅接口时,不能不假思索地直接将文档中示例代码直接复制到我们的项目中进行使用。我们应该思考代码中的每一行都是用来干什么的。同时应该清楚,每多执行一行代码,就会有更大的性能开销,如何使用速度更快的代码来实现同样的效果,是值得我们关注的。
### 使用xrange来代替range
xrange是python2独有的一个内置函数他的用法与 range 完全相同,所不同的是生成的不是一个数组,而是一个生成器。
相比range它拥有更高的执行效率。
```python
for i in xrange(5):
print i
```
### 使用dict来代替多分支if
修改前:
```python
def getXXX(a):
if a == "a":
return 1
if a == "b":
return 2
if a == "c":
return 3
return 4
```
修改后:
```python
exampleDict = {"a":1,"b":2,"c":3}
def getXXX(a):
result = exampleDict.get(a)
if not result
return result
return 4
```
相比多个if直接使用字典来存储数据并通过get来获取并返回在数据量大的时候会有更高的效率。