2.6
This commit is contained in:
40
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/01.玩法地图为什么需要新手引导?.md
Normal file
40
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/01.玩法地图为什么需要新手引导?.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
front: https://nie.res.netease.com/r/pic/20220408/67103a4f-1246-40d2-ae22-a7ba0518e16c.png
|
||||
hard: 入门
|
||||
time: 5分钟
|
||||
selection: true
|
||||
---
|
||||
# 玩法地图为什么需要新手引导?
|
||||
|
||||
玩法地图相较于普通的玩法组件会更加局限、规整,正因为这样,玩法地图才需好的引导;引导都有哪些好处?为什么需要新手引导?
|
||||
|
||||
### 玩家可以更好、更快的了解核心玩法
|
||||
|
||||
最重要的一点,引导需要能够让玩家了解地图的玩法,不需要花费大量的学习时间明白地图是怎么玩的;也可以让玩家对地图的玩法记忆更深刻。
|
||||
|
||||
### 融入地图背景,增强游戏代入感
|
||||
|
||||
合理的使用新手引导,可以让玩家对地图的背景更加了解,有更清晰的认知;同时利用一些剧情和带有背景色彩的文字描述使玩家融入到地图的故事中,增强代入感。
|
||||
|
||||

|
||||
|
||||
例如在季度玩法《三打白骨精》中,就利用剧情通过和其它玩法人物进行对话了解玩法背景,可以使玩家在第一时间知道自己身处西游的世界,扮演悟空西天取经。
|
||||
|
||||
### 新手引导很重要,但并不是所有玩法地图都需要
|
||||
|
||||
如果是以开放生存为核心玩法的地图,其乐趣就是需要玩家在世界中漫无目的的探索,并在探索时不断发现新的玩法,那么是否需要新手引导就取决于玩法地图的作者来判断;但不建议有核心玩法的玩法地图完全舍弃新手引导。
|
||||
|
||||

|
||||
|
||||
以[《我的海滨农场》](../../20-玩法地图教程/第00章:示例下载/示例下载.md)为例,其主要玩法是玩家在小岛上通过种植庄稼、养殖畜牧并且在规定时间内赚到足够的钱才可以获得胜利!这一目标点则需要新手引导告知给玩家。
|
||||
|
||||

|
||||
|
||||
### 明确游戏内容,在游戏的初期吸引玩家继续
|
||||
|
||||
在新手引导部分展露一些出彩、亮点的游戏内容可以大程度的吸引玩家继续游戏,并对后续的游戏内容报以期待。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
67
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/02.可以用什么方式进行新手引导?.md
Normal file
67
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/02.可以用什么方式进行新手引导?.md
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
front:
|
||||
hard: 入门
|
||||
time: 10分钟
|
||||
---
|
||||
# 可以用什么形式进行新手引导?
|
||||
|
||||
引导的形式可以有很多,每个开发者都有自己对引导独特的理解,怎么能将引导最大程度的发挥其作用是需要开发者们用心设计的;本节将介绍多种引导形式并展开举例。
|
||||
|
||||
常见的玩法地图引导形式可以有:引导关卡、NPC对话、剧情任务、镜头语言、引导手册、其它
|
||||
|
||||
## 引导关卡
|
||||
|
||||
将一些游戏玩法的内容拆解并在关卡内一步步引导玩家进行操作,熟络游戏核心玩法。通常引导关卡都会在正式开始游戏前出现;若游戏玩法复杂,且不仅只有一条核心玩法,那引导关卡也可以有多个,并在不同的游戏阶段出现。
|
||||
|
||||

|
||||
|
||||
在[《我的海滨农场》](../../20-玩法地图教程/第08章:在开头添加引导关卡/课程01.使用MODSDK自定义NPC的聊天对话.md)中,玩家会先出现在新手小岛中,玩家需要与NPC对话,简单了解地图的玩法背景;然后在NPC的指引下完成一些简单的操作:种菜、采集石头、升级建筑;这些都是在正式游戏时的循环玩法。
|
||||
|
||||

|
||||
|
||||
完成这些简单的操作后,玩家才可以乘坐小船离开新手岛屿并正式开始游戏。
|
||||
|
||||
## NPC对话
|
||||
|
||||
在一些RPG / 生存类型的玩法地图中,经常会有一些与剧情或故事背景相关的人物NPC,可以通过这些NPC对话,提示玩家需要注意的游戏内容;同时添加对话剧情,也可以带入游戏的背景,增强玩家对地图的代入感。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## 剧情任务
|
||||
|
||||
这一引导形式应该会被大部分玩家及开发者熟知,很多的地图和除我的世界以外的游戏都或多或少的有剧情任务。
|
||||
|
||||
而由剧情任务作为主线贯穿整个玩法的地图,不需要过多的引导,玩家可以根据任务提示一步步摸索游玩,当然任务提示也算是引导的一种。
|
||||
|
||||

|
||||
|
||||
## 镜头语言
|
||||
|
||||
通过控制玩家的摄像头,利用镜头语言来传达信息并引导玩家。
|
||||
|
||||
例如直接控制玩家看向某个地方,直接的引导玩家目标地点;虽然比较生硬,但也最直观、简便。
|
||||
|
||||
## 引导手册
|
||||
|
||||
在游戏大厅放置引导手册,将游戏内容列举在手册中供玩家翻阅;在开始游戏前就可以了解到几乎所有的游戏内容。相对其它引导形式来说,这是最简单的引导之一,也很受开发者和玩家青睐。非常适用于小游戏地图。
|
||||
|
||||

|
||||
|
||||
当然也可以在游戏时提供引导手册,玩家可以在游玩的过程中随时翻阅。
|
||||
|
||||
## 其它
|
||||
|
||||
在一些需要玩家等待的地方委婉的添加引导,如PVP地图中玩家在死亡、复活阶段添加有关玩法技巧的提示。
|
||||
|
||||

|
||||
|
||||
或者适当添加跳跃性的文字提示,每隔一段时间或是玩家游玩到某个阶段,在玩家屏幕上显示。
|
||||
|
||||
虽然很生硬直接,但适当的与其它引导形式相结合,就会产生不同的效果。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
371
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/03.为小游戏地图添加引导.md
Normal file
371
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/03.为小游戏地图添加引导.md
Normal file
@@ -0,0 +1,371 @@
|
||||
---
|
||||
front:
|
||||
hard: 进阶
|
||||
time: 40分钟
|
||||
---
|
||||
# 为小游戏地图添加引导
|
||||
|
||||
我们来制作一个小游戏玩法地图DEMO,并且为这个地图的大厅中添加一些引导。
|
||||
|
||||
点击[链接](https://g79.gdl.netease.com/Jungle_Demo.zip)可下载本章地图Demo。
|
||||
|
||||
## 在大厅添加NPC
|
||||
|
||||
先简单制作一个大厅场景,地图名为《丛林激流》,是一个轻松的“水上竞速”玩法地图;而游戏场景设定是游乐园风格,所以在大厅添加了多个游乐园会出现的小摊,引导NPC将放置于此。
|
||||
|
||||

|
||||
|
||||
在大厅内添加多个小动物形态的NPC:熊猫、鹦鹉、狼。
|
||||
|
||||
> 有游戏背景或世界观的玩法地图,将所有的游戏元素风格统一化也是很重要的;
|
||||
|
||||

|
||||
|
||||
## 制作UI添加引导手册
|
||||
|
||||
引导手册可以有很多方式体现,最简单的方法就是将引导文字写在【书与笔】上并放在游戏比较“显眼”的位置即可。不过这次我们放置了NPC,所以需要制作UI,在玩家与NPC交互的时候,显示UI。
|
||||
|
||||

|
||||
|
||||
打开我的世界开发工作台的界面编辑器,制作引导手册界面和欢迎界面;
|
||||
|
||||

|
||||
|
||||
欢迎界面主要填充一些对于地图的基本介绍和简单引导;当然,实际需要什么内容,还是根据引导设计和开发者习惯来决定。
|
||||
|
||||
引导手册则需要多页,将玩法内容罗列在此供玩家翻阅、学习。大部分情况下,小游戏地图不怎么需要引导手册,因为无论是场景还是玩法都是有局限性的,玩家在游玩的过程中必定会发现和体验到,全部的内容被玩家了解后,在真正游玩的时候可能会丧失一定的新鲜感。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
**制作好UI后,我们需要将UI与NPC“连接”起来:**
|
||||
|
||||
创建UI的脚本文件FlumeRideInfoUI.py,并继承ScreenNode类
|
||||
|
||||
```python
|
||||
# -*- coding: utf-8 -*-
|
||||
import mod.client.extraClientApi as clientApi
|
||||
ViewBinder = clientApi.GetViewBinderCls()
|
||||
ViewRequest = clientApi.GetViewViewRequestCls()
|
||||
ScreenNode = clientApi.GetScreenNodeCls()
|
||||
|
||||
class FlumeRideInfoUI(ScreenNode):
|
||||
def __init__(self, namespace, name, param):
|
||||
ScreenNode.__init__(self, namespace, name, param)
|
||||
```
|
||||
|
||||
创建FlumeRideServerSystem.py、FlumeRideClientSystem.py
|
||||
|
||||
```python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import mod.server.extraServerApi as serverApi
|
||||
ServerSystem = serverApi.GetServerSystemCls()
|
||||
|
||||
class FlumeRideServerSystem(ServerSystem):
|
||||
def __init__(self, namespace, systemName):
|
||||
ServerSystem.__init__(self, namespace, systemName)
|
||||
# 提前将放在大厅的NPC生物ID获取到并保存在这里,用于判断玩家交互的NPC
|
||||
self.npcIdList = {"panda": "-85899345885", "panda2": "-158913789845", "parrot": "-158913789915", "wolf": "-158913789911"}
|
||||
|
||||
nameSpace, systemName = serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName()
|
||||
# 监听PlayerAttackEntityEvent事件
|
||||
self.ListenForEvent(nameSpace, systemName, "PlayerAttackEntityEvent", self, self.PlayerAttackEntityEvent)
|
||||
|
||||
# 玩家攻击生物时触发
|
||||
def PlayerAttackEntityEvent(self, args):
|
||||
|
||||
# 由事件获取到的玩家攻击的生物ID
|
||||
playerId = args['playerId']
|
||||
entityId = args['victimId']
|
||||
|
||||
# 判断不同的NPC生物
|
||||
if entityId == self.npcIdList["panda"]:
|
||||
# 发送事件到客户端,打开UI,传输字典参数UIType用来判断玩家交互的生物以打开不同UI
|
||||
self.NotifyToClient(playerId, "OpenGameInfoUI", {"UIType": "panda"})
|
||||
|
||||
elif entityId == self.npcIdList["panda2"]:
|
||||
pass
|
||||
|
||||
elif entityId == self.npcIdList["parrot"]:
|
||||
pass
|
||||
|
||||
elif entityId == self.npcIdList["wolf"]:
|
||||
self.NotifyToClient(playerId, "OpenGameInfoUI", {"UIType": "wolf"})
|
||||
|
||||
```
|
||||
|
||||
在服务端脚本添加玩家攻击生物的事件并判断,如果是大厅的NPC,就传输事件到客户端创建UI。
|
||||
|
||||
```python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import mod.client.extraClientApi as clientApi
|
||||
ClientSystem = clientApi.GetClientSystemCls()
|
||||
|
||||
class FlumeRideClientSystem(ClientSystem):
|
||||
def __init__(self, namespace, systemName):
|
||||
ClientSystem.__init__(self, namespace, systemName)
|
||||
print "Client初始化"
|
||||
nameSpace, systemName = clientApi.GetEngineNamespace(), clientApi.GetEngineSystemName()
|
||||
# 监听UiInitFinished事件
|
||||
self.ListenForEvent(nameSpace, systemName, "UiInitFinished", self, self.UiInitFinished)
|
||||
# 监听由FlumeRideServerSystem传过来的OpenGameInfoUI事件
|
||||
self.ListenForEvent("FlumeRide", "FlumeRideServerSystem", "OpenGameInfoUI", self, self.OpenUI)
|
||||
|
||||
# 由FlumeRideServerSystem传过来的OpenGameInfoUI事件
|
||||
# 当玩家与NPC交互时,判断交互的NPC类型并打开对应的UI
|
||||
def OpenUI(self, args):
|
||||
UIType = args['UIType']
|
||||
if UIType == "panda":
|
||||
clientApi.PushScreen("FlumeRide", "FlumeRideGameInfo")
|
||||
elif UIType == "wolf":
|
||||
clientApi.PushScreen("FlumeRide", "FlumeRideGameBook_1")
|
||||
|
||||
# UI初始化完成,将UI注册
|
||||
def UiInitFinished(self, args):
|
||||
clientApi.RegisterUI("FlumeRide", "FlumeRideGameInfo", "Script_FlumeRide.uiScript.FlumeRideInfoUI.FlumeRideInfoUI", "GameInfo.main")
|
||||
clientApi.RegisterUI("FlumeRide", "FlumeRideGameBook_1", "Script_FlumeRide.uiScript.FlumeRideInfoUI.FlumeRideInfoUI", "GameBook.main")
|
||||
clientApi.RegisterUI("FlumeRide", "FlumeRideGameBook_2", "Script_FlumeRide.uiScript.FlumeRideInfoUI.FlumeRideInfoUI", "GameBook_2.main")
|
||||
|
||||
```
|
||||
|
||||
现在,我们攻击大厅的生物,就可以打开UI界面了。
|
||||
|
||||
<img src="./images/16.gif" alt="16" style="zoom:120%;" />
|
||||
|
||||
简单修改UI文件,将关闭按钮和引导手册的翻页按钮与FlumeRideInfoUI.py脚本文件中的某个函数绑定。
|
||||
|
||||
```json
|
||||
// ...
|
||||
// UI文件
|
||||
// 关闭按钮控件
|
||||
"GameInfoButton@common.button" : {
|
||||
// ···
|
||||
// 绑定按钮按下时触发的函数 %ScreenNode脚本.函数名
|
||||
"$pressed_button_name" : "%FlumeRideInfoUI.ClickedCloseButton",
|
||||
// 需要删除
|
||||
"button_mappings" : [],
|
||||
// ...
|
||||
},
|
||||
// 翻页按钮同理
|
||||
```
|
||||
|
||||
```python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ...
|
||||
class FlumeRideInfoUI(ScreenNode):
|
||||
def __init__(self, namespace, name, param):
|
||||
ScreenNode.__init__(self, namespace, name, param)
|
||||
|
||||
# 绑定关闭按钮
|
||||
@ViewBinder.binding(ViewBinder.BF_ButtonClickUp)
|
||||
def ClickedCloseButton(self, args):
|
||||
clientApi.PopScreen()
|
||||
|
||||
# 绑定翻页按钮
|
||||
@ViewBinder.binding(ViewBinder.BF_ButtonClickUp)
|
||||
def ClickedPageTurnButton(self, args):
|
||||
GameBook1UI = clientApi.GetUI("FlumeRide", "FlumeRideGameBook_1")
|
||||
GameBook2UI = clientApi.GetUI("FlumeRide", "FlumeRideGameBook_2")
|
||||
if GameBook1UI:
|
||||
clientApi.PopScreen()
|
||||
clientApi.PushScreen("FlumeRide", "FlumeRideGameBook_2")
|
||||
elif GameBook2UI:
|
||||
clientApi.PopScreen()
|
||||
clientApi.PushScreen("FlumeRide", "FlumeRideGameBook_1")
|
||||
|
||||
```
|
||||
|
||||
<img src="./images/17.gif" alt="17" style="zoom:120%;" />
|
||||
|
||||
## 添加NPC对话
|
||||
|
||||
接下来为另一位NPC添加对话,简单描述一下地图背景和引导即可。
|
||||
|
||||
```python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import mod.server.extraServerApi as serverApi
|
||||
ServerSystem = serverApi.GetServerSystemCls()
|
||||
commandComp = serverApi.GetEngineCompFactory().CreateCommand(serverApi.GetLevelId())
|
||||
|
||||
class FlumeRideServerSystem(ServerSystem):
|
||||
def __init__(self, namespace, systemName):
|
||||
ServerSystem.__init__(self, namespace, systemName)
|
||||
# ...
|
||||
# 监听PlayerAttackEntityEvent事件
|
||||
self.ListenForEvent(nameSpace, systemName, "PlayerAttackEntityEvent", self, self.PlayerAttackEntityEvent)
|
||||
# 监听ClientLoadAddonsFinishServerEvent事件
|
||||
self.ListenForEvent(nameSpace, systemName, "ClientLoadAddonsFinishServerEvent", self, self.DataInit)
|
||||
|
||||
# 玩家客户端加载完毕时触发,创建玩家数据
|
||||
def DataInit(self, args):
|
||||
# 由事件获取的玩家ID
|
||||
playerId = args['playerId']
|
||||
# 获取玩家的数据
|
||||
playerDataComp = serverApi.GetEngineCompFactory().CreateExtraData(playerId)
|
||||
pandaMsgData = playerDataComp.GetExtraData("pandaMsg")
|
||||
# 如果这个玩家没有数据,就设置一个
|
||||
if not pandaMsgData:
|
||||
playerDataComp.SetExtraData("pandaMsg", 0) # 用来判断玩家的对话阶段
|
||||
|
||||
# 玩家攻击生物时触发
|
||||
def PlayerAttackEntityEvent(self, args):
|
||||
|
||||
def Panda2Guide():
|
||||
# 获取玩家的名称
|
||||
playerNameComp = serverApi.GetEngineCompFactory().CreateName(playerId)
|
||||
playerName = playerNameComp.GetName()
|
||||
# 获取玩家的pandaMsg数据
|
||||
playerDataComp = serverApi.GetEngineCompFactory().CreateExtraData(playerId)
|
||||
pandaMsg = playerDataComp.GetExtraData("pandaMsg")
|
||||
commandComp.SetCommand("playsound random.orb " + playerName + " ~ ~ ~ 3 1 1")
|
||||
# 根据玩家当前的对话阶段,触发不同的对话分支
|
||||
if pandaMsg == 0:
|
||||
# 使用指令接口生成对话
|
||||
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f《丛林激流》欢迎你! §a(1/6)"}]}')
|
||||
elif pandaMsg == 1:
|
||||
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f丛林的小动物们和人类一起建造了这里! §a(2/6)"}]}')
|
||||
elif pandaMsg == 2:
|
||||
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f今天是激流游乐园开业的第一天; §a(3/6)"}]}')
|
||||
elif pandaMsg == 3:
|
||||
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f鹦鹉小姐会教你如何在水赛道上更加灵活 §a(4/6)"}]}')
|
||||
elif pandaMsg == 4:
|
||||
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f关于丛林激流的一切还可以问问狼先生,他什么都知道 §a(5/6)"}]}')
|
||||
elif pandaMsg == 5:
|
||||
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"熊猫 §a§l| §r§f当然,不要忘了叫上小伙伴一起享受这快乐的游戏时光! §a(6/6)"}]}')
|
||||
# 到最后一条对话就重置数据并且return
|
||||
playerDataComp.SetExtraData("pandaMsg", 0)
|
||||
return
|
||||
# 更新当前数据+1
|
||||
pandaMsg += 1
|
||||
playerDataComp.SetExtraData("pandaMsg", pandaMsg)
|
||||
|
||||
playerId = args['playerId']
|
||||
entityId = args['victimId']
|
||||
|
||||
if entityId == self.npcIdList["panda"]:
|
||||
# ...
|
||||
elif entityId == self.npcIdList["panda2"]:
|
||||
Panda2Guide()
|
||||
elif entityId == self.npcIdList["parrot"]:
|
||||
# ...
|
||||
elif entityId == self.npcIdList["wolf"]:
|
||||
# ...
|
||||
|
||||
```
|
||||
|
||||
<img src="./images/18.gif" alt="18" style="zoom:120%;" />
|
||||
|
||||
使用【指令】实现这种对话效果,表现力较为薄弱,如果用UI代替会更好;但是实现起来会非常简单,如果对UI不熟练,可以使用这种方法。
|
||||
|
||||
## 控制镜头介绍内容
|
||||
|
||||
还剩最后一位NPC:鹦鹉;它将带领玩家观赏和讲解游戏中的场景和内容。
|
||||
|
||||
<img src="./images/19.gif" alt="19" style="zoom:120%;" />
|
||||
|
||||
```python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import mod.server.extraServerApi as serverApi
|
||||
ServerSystem = serverApi.GetServerSystemCls()
|
||||
timerComp = serverApi.GetEngineCompFactory().CreateGame(serverApi.GetLevelId())
|
||||
commandComp = serverApi.GetEngineCompFactory().CreateCommand(serverApi.GetLevelId())
|
||||
|
||||
class FlumeRideServerSystem(ServerSystem):
|
||||
def __init__(self, namespace, systemName):
|
||||
ServerSystem.__init__(self, namespace, systemName)
|
||||
# ...
|
||||
|
||||
def DataInit(self, args):
|
||||
# ...
|
||||
if not pandaMsgData:
|
||||
playerDataComp.SetExtraData("pandaMsg", 0)
|
||||
# 添加新的数据用于判断鹦鹉讲解的阶段
|
||||
playerDataComp.SetExtraData("parrotMsg", 0)
|
||||
|
||||
def PlayerAttackEntityEvent(self, args):
|
||||
|
||||
def ParrotGuide():
|
||||
# 获取玩家的名称
|
||||
playerNameComp = serverApi.GetEngineCompFactory().CreateName(playerId)
|
||||
playerName = playerNameComp.GetName()
|
||||
# 获取玩家的parrotMsg数据
|
||||
playerDataComp = serverApi.GetEngineCompFactory().CreateExtraData(playerId)
|
||||
parrotMsg = playerDataComp.GetExtraData("parrotMsg")
|
||||
# 根据玩家当前的讲解阶段,触发不同的讲解分支
|
||||
if parrotMsg == 0:
|
||||
# 传送玩家
|
||||
commandComp.SetCommand("tp " + playerName + " 29.5 80 -242.5 -20.4 31.4")
|
||||
# 发送事件到客户端用于锁定玩家的控制
|
||||
self.NotifyToClient(playerId, "PlayerCamera", {"Camera": "Lock"})
|
||||
# 使用指令接口生成对话
|
||||
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"鹦鹉 §e§l| §r§f这是摩托艇,你需要驾驶它驰骋在丛林河道上 §a(1/3)"}]}')
|
||||
elif parrotMsg == 1:
|
||||
commandComp.SetCommand("tp " + playerName + " 23.6 79 -252.5 54.1 16.4")
|
||||
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"鹦鹉 §e§l| §r§f在丛林中,你会看到幸运Q块,用弩射击它将会发生随机的事件 §a(2/3)"}]}')
|
||||
elif parrotMsg == 2:
|
||||
commandComp.SetCommand("tp " + playerName + " 33.4 112 -136.4 -162.6 -7.8")
|
||||
commandComp.SetCommand('tellraw ' + playerName + ' {"rawtext":[{"text":"鹦鹉 §e§l| §r§f熟练操控摩托艇,精准射击幸运Q块,在丛林中激流吧! §a(3/3)"}]}')
|
||||
elif parrotMsg == 3:
|
||||
commandComp.SetCommand("tp " + playerName + " 22 68 -254 -114.8 0.9")
|
||||
# 讲解结束后,解锁玩家的控制
|
||||
self.NotifyToClient(playerId, "PlayerCamera", {"Camera": "UnLock"})
|
||||
# 重置阶段数据并return
|
||||
playerDataComp.SetExtraData("parrotMsg", 0)
|
||||
return
|
||||
commandComp.SetCommand("playsound random.orb " + playerName + " ~ ~ ~ 3 1 1")
|
||||
# 更新当前数据+1
|
||||
parrotMsg += 1
|
||||
playerDataComp.SetExtraData("parrotMsg", parrotMsg)
|
||||
|
||||
playerId = args['playerId']
|
||||
entityId = args['victimId']
|
||||
|
||||
if entityId == self.npcIdList["panda"]:
|
||||
# ...
|
||||
elif entityId == self.npcIdList["panda2"]:
|
||||
# ...
|
||||
elif entityId == self.npcIdList["parrot"]:
|
||||
# 触发四次ParrotGuide,利用定时器接口,实现延迟触发
|
||||
ParrotGuide()
|
||||
timerComp.AddTimer(10, ParrotGuide)
|
||||
timerComp.AddTimer(20, ParrotGuide)
|
||||
timerComp.AddTimer(30, ParrotGuide)
|
||||
elif entityId == self.npcIdList["wolf"]:
|
||||
# ...
|
||||
```
|
||||
|
||||
```python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import mod.client.extraClientApi as clientApi
|
||||
ClientSystem = clientApi.GetClientSystemCls()
|
||||
|
||||
class FlumeRideClientSystem(ClientSystem):
|
||||
def __init__(self, namespace, systemName):
|
||||
ClientSystem.__init__(self, namespace, systemName)
|
||||
# 监听由FlumeRideServerSystem传过来的PlayerCamera事件
|
||||
self.ListenForEvent("FlumeRide", "FlumeRideServerSystem", "PlayerCamera", self, self.PlayerCamera)
|
||||
|
||||
# 用于锁定和解锁玩家控制
|
||||
def PlayerCamera(self, args):
|
||||
# 获取玩家控制接口
|
||||
controlComp = clientApi.GetEngineCompFactory().CreateOperation(clientApi.GetLevelId())
|
||||
if args["Camera"] == "Lock":
|
||||
controlComp.SetCanAll(False)
|
||||
elif args["Camera"] == "UnLock":
|
||||
controlComp.SetCanAll(True)
|
||||
```
|
||||
|
||||
这种形式非常直观、生动;镜头可以是静态的,也可以制作成动态;镜头内的方块、生物等内容也可以通过动画加强表现力。非常适合用来设计引导!
|
||||
|
||||
## 其它
|
||||
|
||||
在一些可交互或者有玩法内容的实体、方块上添加标识,会更加直观:
|
||||
|
||||

|
||||
|
||||
0
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/README.md
Normal file
0
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/README.md
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/1.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/1.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/10.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/10.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/11.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/11.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/12.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/12.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/13.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/13.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/14.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/14.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/15.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/15.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/16.gif
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/16.gif
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/17.gif
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/17.gif
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/18.gif
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/18.gif
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/19.gif
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/19.gif
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/2.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/2.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/20.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/20.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/3.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/3.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/4.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/4.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/5.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/5.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/6.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/6.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/7.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/7.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/8.5.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/8.5.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/8.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/8.png
LFS
Normal file
Binary file not shown.
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/9.png
LFS
Normal file
BIN
docs/mconline/50-新手引导教程/新手引导之玩法地图篇/images/9.png
LFS
Normal file
Binary file not shown.
Reference in New Issue
Block a user