赞 | 65 |
VIP | 231 |
好人卡 | 2 |
积分 | 19 |
经验 | 35171 |
最后登录 | 2024-9-15 |
在线时间 | 1554 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 1912
- 在线时间
- 1554 小时
- 注册时间
- 2013-4-13
- 帖子
- 917
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
Scene_Title还有一些其他能说的地方
比如WindowLayer, 比如Scene_Load, Scene_Options...
不过我们先加快一下进度, 直接开始Scene_Map
但是, 我们还是要先分析一下它们的交接工作
于是Scene_Title可以再水一篇啦
=================================
第十一章
因为是创建新游戏,
Scene_Title在把指挥权交给Scene_Map之前
还是需要先做一点初始化
- Scene_Title.prototype.commandNewGame = function () {
- DataManager.setupNewGame(); // 初始化游戏数据
- this._commandWindow.close(); // 关闭(动画)菜单
- this.fadeOutAll(); // 淡出动画
- SceneManager.goto(Scene_Map); // 切换场景
- };
复制代码
我DataManager又回来了...
- DataManager.setupNewGame = function () {
- this.createGameObjects(); // 创建游戏对象
- this.selectSavefileForNewGame(); // 指向一个新的存档位置
- $gameParty.setupStartingMembers(); // 初始化队伍
- $gamePlayer.reserveTransfer($dataSystem.startMapId,
- $dataSystem.startX, $dataSystem.startY); // 初始化玩家位置
- Graphics.frameCount = 0;
- };
复制代码
创建游戏对象
这些对象代表了当前游戏的状态
不过日后再表
- DataManager.createGameObjects = function () {
- $gameTemp = new Game_Temp();
- $gameSystem = new Game_System();
- $gameScreen = new Game_Screen();
- $gameTimer = new Game_Timer();
- $gameMessage = new Game_Message();
- $gameSwitches = new Game_Switches();
- $gameVariables = new Game_Variables();
- $gameSelfSwitches = new Game_SelfSwitches();
- $gameActors = new Game_Actors();
- $gameParty = new Game_Party();
- $gameTroop = new Game_Troop();
- $gameMap = new Game_Map();
- $gamePlayer = new Game_Player();
- };
复制代码
为存档界面选择一个初始位置, 一个很小但是很贴心的功能
这个和之前我们判断存档是否存在的方法是很类似的
- DataManager.selectSavefileForNewGame = function () {
- var globalInfo = this.loadGlobalInfo();
- this._lastAccessedId = 1;
- if (globalInfo) {
- var numSavefiles = Math.max(0, globalInfo.length - 1);
- // 如果还有剩余存档位则指向下一个空存档点
- if (numSavefiles < this.maxSavefiles()) {
- this._lastAccessedId = numSavefiles + 1;
- // 否则指向最新的存档点
- } else {
- var timestamp = Number.MAX_VALUE;
- for (var i = 1; i < globalInfo.length; i++) {
- if (!globalInfo[i]) {
- this._lastAccessedId = i;
- break;
- }
- if (globalInfo[i].timestamp < timestamp) {
- timestamp = globalInfo[i].timestamp;
- this._lastAccessedId = i;
- }
- }
- }
- }
- };
复制代码 $gameParty是保存队伍信息的, 它是Game_Party类的实例
Game_Party又是Game_Unit的子类
不过这些以后再说
- Game_Party.prototype.setupStartingMembers = function () {
- this._actors = [];
- $dataSystem.partyMembers.forEach(function (actorId) {
- if ($gameActors.actor(actorId)) {
- this._actors.push(actorId);
- }
- }, this);
- };
复制代码
$dataSystem是数据库对象, 这个之前已经说过了
这里又出现了另外一个游戏对象$gameActors
这个是用来保存角色信息的
其实这个函数写得很莫名其妙啦
直接写this._actors = [...$dataSystem.partyMembers]
一行就搞定了
- $gamePlayer.reserveTransfer($dataSystem.startMapId,
- $dataSystem.startX, $dataSystem.startY);
- Game_Player.prototype.reserveTransfer = function (mapId, x, y, d, fadeType) {
- this._transferring = true; // 带过场的传送
- this._newMapId = mapId; // 新地图id
- this._newX = x; // 新x坐标
- this._newY = y; // 新y坐标
- this._newDirection = d; // 新朝向
- this._fadeType = fadeType; // 过场类型
- };
复制代码
$gamePlayer是玩家对象, 是Game_Player类的实例
代表玩家的人物行走图, 继承于Game_Character
它的兄弟类还有, Game_Follower, GameVehicle 和 Game_Event
本质上都是地图事件
setupNewGame就是这些内容
交接还有一些其他画面上的事情要处理
- this.fadeOutAll(); // 黑色画面淡出
- Scene_Base.prototype.fadeOutAll = function () {
- var time = this.slowFadeSpeed() / 60; // 淡出持续时间
- AudioManager.fadeOutBgm(time); // 淡出声音
- AudioManager.fadeOutBgs(time);
- AudioManager.fadeOutMe(time);
- this.startFadeOut(this.slowFadeSpeed()); // 初始化淡出
- };
- Scene_Base.prototype.startFadeOut = function (duration, white) {
- this.createFadeSprite(white); // 淡出蒙版精灵
- this._fadeSign = -1; // 淡出标识
- this._fadeDuration = duration || 30; // 持续时间
- this._fadeSprite.opacity = 0; // 初始化可见度
- };
- Scene_Base.prototype.createFadeSprite = function (white) {
- if (!this._fadeSprite) { // 如果淡出蒙版不存在则创建一个新的
- this._fadeSprite = new ScreenSprite();
- this.addChild(this._fadeSprite);
- }
- if (white) { // 白色的
- this._fadeSprite.setWhite();
- } else { // 黑色的
- this._fadeSprite.setBlack();
- }
- };
复制代码
回忆一下update方法
并贴出一个场景淡出的更新方法
- Scene_Base.prototype.update = function () {
- this.updateFade();
- this.updateChildren();
- };
- Scene_Base.prototype.updateFade = function () {
- // 如果持续时间还有
- if (this._fadeDuration > 0) {
- var d = this._fadeDuration;
- // 大于0则是淡入(透明度增大), 小于0是淡出(透明度减小)
- // 可以看出每次淡入淡出的幅度和剩余时间是有关系的
- // 剩余时间越小, 淡入淡出幅度越大
- if (this._fadeSign > 0) {
- this._fadeSprite.opacity -= this._fadeSprite.opacity / d;
- } else {
- this._fadeSprite.opacity += (255 - this._fadeSprite.opacity) / d;
- }
- // 持续时间递减
- this._fadeDuration--;
- }
- };
- `
- 关闭窗口和淡出都是需要持续一段时间的
- 如果这时候直接跳转场景, 这些设置就白费了
- 回顾一下SceneManager是如何判断是否可以跳转场景的
- `
- SceneManager.goto = function (sceneClass) {
- if (sceneClass) {
- this._nextScene = new sceneClass();
- }
- //... 略
- };
- // update时候调用
- SceneManager.changeScene = function () {
- if (this.isSceneChanging() && !this.isCurrentSceneBusy()) {
- //... 略
- }
- };
- SceneManager.isCurrentSceneBusy = function () {
- return this._scene && this._scene.isBusy();
- };
- Scene_Base.prototype.isBusy = function () {
- return this._fadeDuration > 0;
- };
复制代码
==========================================================
今天内容比较水, 所以补充点js的知识吧
今天的课题是JavaScript的作用域和作用域链
Javascript是一门静态作用域/词法作用域的语言
简单来说就是通过阅读代码(编译阶段)就能确定变量的可用范围
这点和之前说的属性是不一样的, 属性是动态委托
obj.a的a 我们并不一定能在这句代码执行前确认a是不是存在
也不能确定a是来源于a, 还是a.__proto__
而变量不一样, 如果有console.log(a), 你一定能在代码中找到它的指代
变量的可用范围, 也就是作用域在声明后就不会改变
变量的可用范围和其声明的关键字有关
ES5之前: var, 现在const, let
var的作用域范围是整个函数体
const的作用域是所在代码块, 也就是一对花括号之间, const变量不可变
let的作用域和const相同, 但是let声明的变量是可变的
可变不可变指的是是否能改变引用
比如const a = 1, a = 2就会报错
const obj = {}, obj = {} 也会报错
但是const obj = {}, obj.a = 1 就不会报错, 因为obj引用的对象没有变
变量分为全局变量和局部变量
在ES5之前, 在全局作用域中声明的变量, 等价于window对象的属性.
而const和let是不会有这种问题的
现在为了避免这种可能带来的困惑, 推荐使用const和let
再说一说什么是作用域链
假如我们有:
- const a = 1
- const b = 321
- const f = () => {
- const a = 2
- const f = () => {
- const a = 3
- console.log(a, b) // 3, 321
- }
- f()
- console.log(a, b) // 2, 321
- }
- f()
- console.log(a, b) // 1, 321
复制代码
js首先会去找在本作用域定义的变量
如果找不到则在上一层作用域里继续寻找, 这就是作用域链
静态作用域虽然简单, 但是会暴露一个问题
我们在用js来写类的时候, 会先写类的成员方法再实例化类的对象
而且一个类会有多个实例
这时候静态作用域就无法满足我们的需求了
我们需要this: 上下文对象
this和变量不一样, 它并不是静态的, 它的指代是在呼叫的时候确定的
比如obj.f(), 如果obj是一个引用类型, 那么f内的this指代就是obj
哪怕f并不是obj的方法, 而是obj.__proto__的方法
f中的this指向依然是obj, 这个this和它声明时候的作用域无关
嗯, 看上去一切都很美好
不过this的不确定性却带给了开发者很大的问题
比如回调函数 我们这么写:
- PluginManager.onError = function (e) {
- this._errorUrls.push(e.target._url);
- };
- PluginManager.loadScript = function (name) {
- // 略...
- var script = document.createElement('script');
- // 略...
- script.onerror = this.onError // 有什么问题?
- // 略...
- };
复制代码 问题是: 当script加载错误触发onerror的时候, this指代的是谁?
是script还是PluginManager?
你认为是script, 恭喜你很正确
但是我们想要this指向PluginManager呢?
这就需要bind, call和apply方法在声明时来强行绑定this对象了
call和apply区别不大
用途都是绑定this并呼叫函数
比如 f.call(obj, ...args) 和 f.apply(obj, args)
bind则是直接返回一个新函数, 这个函数的this在被绑定一次后不能再绑定
比如f.bind(obj)(...args) 就等价于f.call(obj, ...args)
在es5中class定义中也可以使用this, class的成员方法中的this指的是实例本身
- class A {
- constructor() {
- this.abc = 5
- }
- }
复制代码
然而this还是太灵活, 太容易出错了, 于是乎箭头函数出现了
- const f = () => {
- console.log(this)
- }
- const obj = { f }
- obj.f() // window
复制代码
在箭头函数中this指向的就是当前作用域中的this
这个还可以将class的成员函数中的this永久绑定
- class A {
- constructor() {
- this.f = () => {
- console.log(this)
- }
- }
- }
- const f = (new A()).f
- f() // A {f: ƒ}
复制代码
值得一提的箭头函数是无法再被bind, call, apply绑定的
好了水了这么多, 收工!
|
评分
-
查看全部评分
|