关于this和箭头函数
箭头函数里使用的this不是它自己的this, 是上层环境的this. 默认情况下, 是window.
cocos creator学习浅谈
cocos creator集electron, node.js, vue.js, 浏览器对象, canvas, webGL于一身, 哦看起来还是很强大的.
结构
/assets 根目录下面主要编辑的文件都在这儿
/library, /temp 可以认为都是临时文件, 貌似为了加速编辑器某些处理产生的, 和assets里的资源是匹配关系, 如果匹配出了问题, 这些都删掉, creator会自动再次生成.
/local 编辑器布局, 一般情况下并没有什么用, 貌似删了也没有关系
/settings 构建发布等相关配置, 蛮重要的,要保留.
package.json 也规定了一些重要的信息, 要保留.
运行后还会生成很多.meta文件, 是一个资源文件对应一个.meta, 里面主要是资源文件的uuid和其他一些信息.
assets资源
所以, 主要的编辑工作都是在assets里面. 再说说assets, 文件可以包括:
.fire 场景文件, 规定了场景中各个内容, 也就是creator中层级管理器里面显示的那些东东. 其实是一个json文件.
.js 脚本文件, 当然了, 是JavaScript, 这个后面专门说一下
资源文件:
图片 包括.png, jpg等, 这个不消说, 是在场景中添加到精灵里面的;
粒子 以.plist结尾. plist和json文件作用相同, 只不过是xml形式的. 粒子文件的粒子图片可以是独立图片, 也可以是内嵌在plist中的base64数据.独立图片的话, 需要和plist放在一个目录中. cocos支持的粒子文件在windows上可以用Particle Editor编辑.
字体 可以使用ttf字体或者是位图字体.fnt, windows下使用BMFont制作, MAC下使用glyph designer制作. windows下的制作方法查看这儿
动画 动画目前就我所知, 有三种形式:
- 通过creator编辑的动画, 以.anim结尾, 实际上也是json文件. 这个应该和项目是紧密耦合的, 因为在文件里面规定了frame帧引用的资源是uuid形式的, 而uuid是在项目中生成的.
- spine骨骼动画 是使用spine软件制作的骨骼动画, 收费才能使用, 恩, 因此我也不知道这个文件是什么样子的.
- DragonBones骨骼动画 是使用DragonBones软件制作的骨骼动画, 常被称为龙骨动画, 免费开源, 但似乎以前cocos不支持, 现在貌似也支持的吧太好, 我下载了一个动画加入, 发现骨头缺了一块...不厚道地揣测, 也许是因为龙骨软件的开发商是Egret, 也就是另一个游戏引擎白鹭的开发方, 白鹭引擎貌似现在发展的也不错, 在知乎上还能看到两个引擎的拥护者对喷, 是由于这种竞争关系导致的支持不好吗? 龙骨动画包括三个文件, xxx_ske.json, xxx_tex.json, _tex.png. 在creator中, 将xxx_ske.json拖进层级管理器, 再把_tex.png拖到Dragon Atlas Asset中即可.
- 音乐等其他文件, 目前暂未涉及.
js脚本与nodejs和浏览器js异同
js脚本很大程度上结合了node.js和浏览器环境, 然而又有所不同.
目前发现与nodejs一致的有:
- 可以使用node.js的require加载自定义在assets中的任何js模块.
- js中定义的所有变量var ,function 都只能在本js文件中引用.
- 要让require的方式暴露本模块中的变量, 同nodejs一样,需要通过module.exports的方式.
- 可以使用ES2015语法, 如let, const, 箭头函数等
不一致的有:
- 不能使用node.js自带的模块, 如fs, path等.
与浏览器环境一致的有:
- 包含一个全局变量window, 向window.xxx赋值,可以在任一js中访问. window其实本来是BOM(浏览器对象模型)的一部分, 然而可以在这儿使用.
据说还可以使用npm install安装第三方纯js库使用, 尚未试过.
另外根据帮助文档, cocos creator的项目中也有一个类似于electron的index.html文件, 目前暂未开放出来提前修改.
js脚本运行方式
- 事实上, 在assets目录中的js脚本, 会在游戏一开始加载的时候全部运行一遍, 运行的顺序似乎并没有什么规律. 如果要控制运行顺序参考这儿
- 所以, 在js正文中所书写的内容都会被运行.
- 通过require('js文件名')可以直接引用任意目录下的js 文件, 所以js文件就算在不同的目录下也不能同名.
js脚本与其他资源文件的关联
- 所有的资源是以节点树的方式组织, 有点类似于DOM树, 节点树的在'层级管理器'中显示.
- 在js文件中定义一个cc.Class, 就可以与其他资源节点关联, 每个js文件最多只能有一个cc.Class
- 这时把js拖到资源节点的属性面板中, 在cc.Class的properties中定义的内容可以显示在面板上,
- 如果将内容定义为内置的类型, 则可以将节点拖放到属性面板的该类型上, 在程序中可以对此节点进行引用. 如
cc.Class({
extends: cc.Component,
properties: {
label: cc.Label,
}
},
accessLabel: function(){
// 访问 this.label
}
}
- 通过几个父子方法, 从本节点可以到达任意其他节点. 如果本节点不是一个node,要获取node后才能使用.
this.label.node.parent //父节点
this.label.node.children // 子节点的array
this.label.node.parent.children // 父节点的子节点array. 由于父节点是node,所以可以直接使用node下的元素children
this.label.node.getParent() === this.label.node.parent // true. 目前暂不清楚get方法与直接访问元素是否可能有什么区别.
this.label.node.getChildern() === this.label.node.children //true
this.label.node.getChildByName('childname') // 按名字查找
- 通过修改某个节点的父节点来改变这个节点的位置.
this.label.node.parent = another.node
js脚本对任一资源引用
通过cc.find()方法, 可以从根节点到达任意子节点
cc.find('Canvas/Label') //返回Canvas下的Label节点.
js对某个节点的及其组件component的操作
- 获取到某个节点后, 你就可以对节点下面的属性直接操作.
this.label.node.x = 123 // 其他在属性检查器中看得到的都可以这样操作
- 要操作节点上的某个组件, 使用getComponent和addComponent
this.label.getComponent(cc.Widget).top = 123 // getComponent可以传入一个cc类型
this.label.getComponent('js_file_name') //可以传入字符串, 获取节点上附加的脚本组件
this.label.addComponent(cc.Layout) //也可以通过addComponent添加组件
- 使用new cc.Node()创建新的节点, 还可以通过cc.instantiate克隆一个节点.
var newNode = new cc.Node('newNodeName')
var clonedNode = cc.instantiate(anExistedNode)
- 使用destory()删除一个节点
somenode.destory()
节点生命周期
附加在节点上的js组件,可以获得节点的生命周期变更通知, 并通过回调函数进行操作.生命周期的顺序是:
onLoad
onEnable
start
update, lastUpdate 依次循环
onDisable
onDestroy对节点的active赋值true/false, 将触发onEnable/onDisable事件
somenode.active = false // onDisable
somenode.active = true // onEnable
- 对节点调用onDestroy, 触发onDisable, onDestory事件
somenode.destroy() // onDisable, onDestory - 节点destory以后, 可以用isValid判断是否被destory了. 恩, 我认为这个名称按照上面的active命名方式, 应该叫valid..., 要么需要把active改为isActive以表明其boolean身份.
somenode.isValid //true
somenode.destroy()
somenode.isValid //false
- 需要注意的是, 节点生命随着scene的load开始, scene关闭结束. 节点(node)的生命周期和js本身的只执行一次不同, 请注意区分.
js与被附属节点的关联
- 通过this可以获取到当前的js脚本组件, 通过this.node可以获取js脚本所附属的节点.
- 由于properties和自定义function都是通过this来引用的, 所以, 在cc.Class中定义properties和function的时候要注意了, 这两者都不要起一些creator保留的名字, 列了一下, 这样的保留字还是很多的:
__cid__
__classname__
__eventTargets
__instanceId
__onNodeActivated
__preload
__scriptAsset
__scriptUuid
_deserialize
_destroyImmediate
_destruct
_enabled
_getLocalBounds
_id
_instantiate
_isOnLoadCalled
_name
_objFlags
_onPreDestroy
addComponent
constructor
destroy
enabled
enabledInHierarchy
getComponent
getComponentInChildren
getComponents
getComponentsInChildren
isRunning
lateUpdate
name
node
onEnable
onFocusInEditor
onLoad
onLostFocusInEditor
onRestore
playJump
playRun
resetInEditor
schedule
scheduleOnce
start
unschedule
unscheduleAllCallbacks
update
uuid
场景切换与固定部分节点
加载另一个场景
cc.director.loadScene('anotherScene', callSomeFunctionWhenLoaded)
预加载另一个场景
cc.director.preLoadScene('anotherScene', callSomeFunctionWhenPreloaded)
保留一个场景中的节点到下一个场景.
cc.game.addPersistRootNode('nodeName')
取消保留节点
cc.game.removePersistRootNode('nodeName')
排列节点树中的节点
- 前面说过了, 把一个节点下挂到其他节点下,只需要继续改这个节点的parent属性就行了
somenode.parent = someNewParentNode
- 然而, 与兄弟节点间的排序, 该怎么做呢? 可以用父节点的addChild()和removeChild(), 每次addChild()以后, 被增加的节点都会自动加到父节点树的最后面, 也就是场景的最顶端.
var pa = somenode.parent
pa.removeChild(somenode)
pa.addChild(somenode) // 将somenode移动到了父节点树的最后面.
值得注意的是, 虽然可以用pa.children直接访问到children的array, 然而此array做pop/push/shift/unshift等操作, 似乎并不会对节点树有任何影响. 因此还是乖乖用addChild和removeChild吧!
* 还可以在本级使用setSiblingIndex(index), 可以调整自己在本级中的位置为index
somenode.getSiblingIndex() // 例如, 0, 是在最低端
somenode.setSiblingIndex(2) // 例如, 2, 上移两层.
发射和监听事件
- 只能从节点上发送和监听事件
- 通过在本节点上使用emit发射的事件, 只能被本节点接收到.
- 通过在本节点上dispatchEvent发射的事件, 通过冒泡的方式逐层被上级节点接收到.
sublime3中运行JavaScript
这儿介绍使用nodejs的方式运行, 当然你要装好了nodejs.
以mac版为例, 打开sublime, 选择"Tools->Build System->New Build System...", sublime将打开一个"untitled.sublime-build"文件, 里面有一些json内容, 删掉这些内容, 替换为:
{
"cmd": ["node", "$file"],
"selector": "source.js"
}
保存文件, 取名为"node".
打开一个js文件, 按"command+B"(windows下是ctrl+B)试试, 看console界面有没有输出.
如果输出提示找不到node, 需要修改上面文件的地址为绝对路径.
在mac下打开终端, 输入
which node
我的mac上显示的是
/usr/local/bin/node
将显示node的绝对路径, 复制到上面的文件中, 修改为:
{
"cmd": ["/usr/local/bin/node", "$file"],
"selector": "source.js"
}
再试试!
如何让vim不生成备份文件
以下在windows系统中测试过.
默认vim编辑完一个文件后, 要生成一个以~为结尾的备份文件.
不需要该文件, 则需要在用户的根目录如/user/name/下设置 _vimrc 文件.
加入
set nobackup
也可以指定一个其备份的地方:
set backupdir=D:/Program/ Files/Vim /tmp
safari怎么进入类似chrome的模拟手机显示模式?
Safari需要先打开开发菜单,然后在开发菜单里面选择"Responsive Design Mode".
letter-spacing文字不居中的问题的解决方式
有时,为了设计美观的关系, 需要字体留一定空隙, 使用css属性letter-spacing, 如下代码:
<div style="text-align: center;">
<div style="font-size: 88px;color: #f7517f;">loading</div>
<div style="font-size: 28px;letter-spacing:45px;color:#806d92">呐喊Pro</div>
</div>
显示效果如下:
然而, 却会发现, 下面的文字和上面的没有letter-spacing的文字对不齐.
用鼠标选择下面的文字, 你会发现letter-spacing的45px空间是加在每一个字符后面的, 这样字符都会靠左一点点.
怎么解决呢? 有的网友建议在前面加空格, 当然是转义的空格了:
代码改为:
<div style="text-align: center;">
<div style="font-size: 88px;color: #f7517f;">loading</div>
<div style="font-size: 28px;letter-spacing:45px;color:#806d92"> 呐喊Pro</div>
</div>
显示效果如下:
然而加上空格你又会发现,由于空格还是占用了空间, 整体字符又会靠右一点点...
css的问题还是要回到css的方法上解决, 正确的姿势之一是增加text-indent, 如下:
<div style="text-align: center;">
<div style="font-size: 88px;color: #f7517f;">loading</div>
<div style="font-size: 28px;letter-spacing:45px;text-indent: 45px;color:#806d92">呐喊Pro</div>
</div>
显示效果如下:
除了text-indent方案以外,应该还可以使用padding-left. 不过, 能在text的css属性内解决的, 就不要放到box的属性去解决, 所以text-indent的方式要更优雅一些吧
在nginx中限速以测试网络不好的时候的网页表现
打开"nginx根目录/conf/nginx.conf"配置文件修改如下:
http{
……
limit_zone one $binary_remote_addr 10m;
……
server {
location / {
……
limit_conn one 2;
limit_rate 40k;
}
}
}
JS类,对象,function...
正常情况下的一个function
写法一f = function(){}
或者写法二
function f(){}
- 为new以后的新对象提供属性的function
function F(){this.x = 1; this.obj_f = function(){}}
var o = new F()
o.x
o.obj_f()
- 为所有new以后的新对象提供公共属性的function
写法1
function F(){F.prototype.pub_x = 1; F.prototype.pub_f = function(){} }
var o1 = new F()
var o2 = new F()
o1.pub_x === o2.pub_x
o1.pub_f === o2.pub_f
写法2
function F(){}
F.prototype = {pub_x : 1, pub_f : function(){} }
var o1 = new F()
var o2 = new F()
o1.pub_x === o2.pub_x
o1.pub_f === o2.pub_f
- 不需要new直接使用的function
function F(){}
F.F_pub_f = function(){}
- 综上所述的F, 自己既是一个function, 又是一个object, 又能给别人new. 可以为new的对象提供单独的属性, 公共的属性, 以及不需要new也能使用的属性.
function F(){} //F是一个函数
function F(){this.x = 1; this.obj_f = function(){}} //F可以给别人new了. 提供单独的属性x, obj_f. 如 var f = new F()
F.prototype = {pub_x : 1, pub_f : function(){} } // F可以给new出来的对象提供公共的属性pub_x, pub_f
F.F_pub_x = 1
F.F_pub_f = function(){} //不需要new也能直接访问的F的属性F_pub_x, F_pub_f.
如何将HTML转为图片下载?
可能会有这么几个方案:
如何获取dom元素的实际宽高?
获取dom元素的实际宽高,而不是style里面设置的宽高, 使用offsetWidth/offsetHeight.例如:
<div id="element">test</div>
<script>
console.log(element.offsetWidth, element.offsetHeight)
</script>
COCOS安装过程中的android环境变量
首先安装android studio
下载安卓的几个插件包,sdk,ndk等等.
被Wall了? 找个hosts. 我发现223.255.227.170作为developer.android.com, 74.125.28.121作为tools.android.com似乎速度还不错.
最后的ant属于单独安装的. 里面的ant.cmd在编译时需要用到.
我都是默认安装, 几个系统环境变量如下
NDK_ROOT
C:\Users\Jac\AppData\Local\Android\Sdk\ndk-bundle\
ANDROID_SDK_ROOT
C:\Users\Jac\AppData\Local\Android\Sdk
ANT_ROOT
C:\r\apache-ant-1.9.7-bin\apache-ant-1.9.7\bin
如何分析文件是被哪个进程创建的
今天打算修改一下hosts文件, 却发现文件不能修改. 上网查一下windows可否知道哪个进程锁定了文件? 貌似并没有方法. 需要借助其他软件.
首先用下载 unlocker
用unlocker看了一下,并没有什么锁定它.关掉所有的软件.只保留一个administrator权限的cmd窗口.
cmd下使用ren命令重命名hosts,发现可以, 然而很快就被某个进程创建一个新的hosts文件, 里面只有一句话:
192.168.0.143 windows10.microdone.cn
这是什么鬼?
这首先说明了, 创建这个的不是windows的系统行为.因为微软就算升级了系统要锁定hosts也不可能指向一个莫名其妙的.cn地址.
那么问题来了, 到底是哪个进程创建了hosts?
- 下载process monitor,微软官方推荐, 值得信赖
解压缩打开procmon.exe后, 创建filter, 先通过下拉菜单选择event class is File System ,再选择 operation is CreateFile
确定后, 在输出的窗口搜索hosts, 发现一个可疑的对象UPService.exe
中毒了? 搜索发现这个对象是银联的软件... 我用银联吗? 不用, 删掉它!
然后发现hosts已经不会被自动创建了.
改好hosts, 用attrib +R hosts 先给加个只读属性, 以防哪个家伙修改. 当然这个级别的保护还是比较低的. 要升高保护, 可以再加上+S属性, 以及设定访问权限.
VR发展已过裂口?
根据gamelook文章VR眼镜盒月出货超2000万,单台利润仅1毛,以及其他一些VR发展的历史事件, 猜测VR发展已过了The chasm裂口.
2012年-2014年, Innovator阶段,如果这次VR技术的发展, 以2012年Oculus成立和众筹作为起点的话, 那么2014年7月, Oculus以20亿美元卖给Facebook, 同年谷歌发布VR盒子原型Cardboard, 暴风魔镜以及一批VR创业公司集中进入VR盒子开发领域, 意味着2014年到达VR发展的超高期望顶点(Peak Of Infacted Expectation)
2014-2016年初, Early Adapters阶段, 同时也是裂口阶段The Chasm. 正如gamelook文章中所言: "2014年团队是淌着血过来的,每月尽亏80万", 而到了"去年(2015年)12月以后,销量开始往上蹭蹭地涨". 暴风的VR团队在今年也爆出大幅裁员的新闻.
- 2016-今后3-5年, Early Majority阶段, 除了上述的VR盒子销量暴涨外, HTC Vive于2016年4月上市, 6月北美上市. HTC同时携steam带来超过100款游戏作品. HTC之后, Oculus有些乱了手脚, 先发后至, 发货之间到了5-8月之间. SONY PSVR以及适配PSVR的"PS4.5"版本PS4 Pro也同期发布, 同期上线30余款游戏. 由于VR设备昂贵, 深圳地区出现多家Vive体验中心, 多为初创公司创建.
快速迭代,你是否可以交付一个半成品?
快速迭代,快速试错似乎成为敏捷思想带给葫芦娃啊不互联网经济的灵丹妙药,经典图式常常拿一张蒙娜丽莎的画举例,你不应该做的是:画面分成五块,每一块填完色才画下一块;你应该先快速勾一个蒙娜丽莎的轮廓,哪怕很丑,但能立刻让别人知道你画的是什么,然后再修轮廓,描细线,画背景,最后上色。
如果上面的图破了, 在bing.com搜索mona lisa agile
然而这不是万能的。这适用于做一些功能性应用,并且有一些创新的核心点需要快速早期验证的情况。但这不适合做艺术品,比如蒙娜丽莎。因为达芬奇不可能希望拿一个只描了轮廓丑不拉几的画作给世人看,更不可能问世人这么画对不对你喜不喜欢不喜欢我另画?你画这样我能喜欢吗?
对于另一些需要按时间依次浏览的艺术形式,如长篇小说,电视剧,和章节式游戏,有时可以先试试大家的兴趣。然而,发一个粗制滥造的框架或者只是讲述一下提纲,并不能说明你这是个好作品。而是应该一部分一部分的去向读者和观众呈现一个精雕细琢的作品,正如敏捷方法一开始所反对的那样。观众看完一部分,反馈的意见有用吗,或许有,但有时并不那么重要。极端情况,也许像中国网络小说最赚钱作者唐家三少所说,故事我一开始就想好了,读者的意见并不能改变我。