前言
这段时间完成了playcanvas简单的展示功能,重构完成之后,我才拿过来记录一下。
传送门
PlayCanvas(一)__入门篇
PlayCanvas(二)__EngineSetting篇
PlayCanvas(三)__进阶篇
PlayCanvas(四)__业务逻辑篇
PlayCanvas(六)__发布篇
正文
重构的内容主要是 讲摄像机逻辑、事件逻辑、模型逻辑、UI逻辑、工具方法。
脚本
Globals.js
全局类似于单例,并引入GameMain
var Globals = pc.createScript('globals');
//当前的步骤
Globals.attributes.add("CurrentStep",{
type:"number",
"default":-1
});
//当前的内容
Globals.attributes.add("CruuentGeneral",{
type:"number",
"default":1
});
//总共步骤
Globals.attributes.add("TotalSteps",{
type:"number",
"default":6
});
//换模型事件
Globals.attributes.add("Evt_GeneralEvent", {
type: "string",
"default": "GeneralEvent"
});
//步骤UI切换好像是
Globals.attributes.add("Evt_StepChange", {
type: "string",
"default": "StepChangeEvent"
});
//爆炸
Globals.attributes.add("Evt_StartBoom", {
type: "string",
"default": "StartBoom"
});
//返回
Globals.attributes.add("Evt_ReturnBoom", {
type: "string",
"default": "ReturnBoom"
});
//内容事件
Globals.attributes.add("Evt_Content",{
type:"string",
"default":"ContentEvent"
});
//事件转换器
Globals.attributes.add("EvtMgr", {
type: "entity"
});
//摄像机
Globals.attributes.add("MainCamera", {
type: "entity"
});
Globals.attributes.add("Model",{
type:"entity"
});
Globals.attributes.add("UI",{
type:"entity"
});
//步骤json
Globals.attributes.add("StepJsonData",{
type:"asset",
assetType: 'json'
});
var icanvas;
var iwidth;
var iheight;
var iproportion;
Globals.prototype.initialize = function() {
window.GameMain = this;
this.DebugCam = this.MainCamera.script.orbitCamera;
this.ModelControl = this.Model.script.modelControl;
this.UIControl = this.UI.script.uicontrol;
//获取设备的canvas 其实可以写在初始化
icanvas = this.app.graphicsDevice.canvas;
iwidth = icanvas.offsetWidth ;
iheight = icanvas.offsetHeight ;
iproportion = iheight / 1280;
this.point = new pc.Vec3();
//加载Json
this.AnimationStepData = this.StepJsonData.resources;
};
// update code called every frame
Globals.prototype.update = function(dt) {
//this.printCam(); //打印信息
this.UIFollowModel(); //跟随信息
};
Globals.prototype.calcShortRot = function(y) {
return y < -360 || y > 360 ? y % 360 : y;
};
Globals.prototype.printCam = function() {
console.log("Cam yaw Y轴 " + this.DebugCam.yaw +
"\nCam Cam pitch X轴 " + this.DebugCam.pitch +
"\nCam distance 距离 " + this.DebugCam.distance );
};
Globals.prototype.UIFollowModel = function()
{
//让UI跟随模型
for (var a = 0; a < GameMain.ModelControl.ArrayModel.length; a++)
{
this.MainCamera.camera.worldToScreen(GameMain.ModelControl.ArrayModel[a].getPosition(),this.point);
GameMain.UIControl.ArrayPointUI[a].setLocalPosition(
(this.point.x - iwidth / 2 ) / iproportion,
(-this.point.y + iheight / 2 ) / iproportion,
0);
}
};
GlobalEventMgr.js
事件id处理器
var GlobalEventMgr = pc.createScript('globalEventMgr');
// initialize code called once per entity
GlobalEventMgr.prototype.initialize = function()
{
this.entity.on(GameMain.Evt_GeneralEvent, this.onGeneral, this);
this.entity.on(GameMain.Evt_StepChange,this.onStepChange, this);
};
GlobalEventMgr.prototype.update = function(dt)
{
};
GlobalEventMgr.prototype.onStepChange = function(t)
{//本来也在这里改的,有点条件
//GameMain.CurrentStep += t;
//console.log(" globals.CurrentStep" + globals.CurrentStep);
};
GlobalEventMgr.prototype.onGeneral = function(t)
{//改值
GameMain.CruuentGeneral = t;
console.log(" GlobalEventMgr:GameMain.CruuentGeneral" + GameMain.CruuentGeneral);
};
CameraHandle.js
摄像机角度处理,此处只要是根据id调用json数据
var CameraHandle = pc.createScript('cameraHandle');
CameraHandle.self = null;
// initialize code called once per entity
CameraHandle.prototype.initialize = function()
{
CameraHandle.self = this;
GameMain.EvtMgr.on(GameMain.Evt_StepChange, this.StepChangeClick, this);
this.StepChange(GameMain.CurrentStep);
};
CameraHandle.prototype.StepChangeClick = function(a)
{
setTimeout(function(){
CameraHandle.self.StepChange(GameMain.CurrentStep);
},1);
};
CameraHandle.prototype.StepChange = function(stepid)
{
console.log("CameraHandle.CurrentStep" + GameMain.CurrentStep);
this.dis = parseFloat(GameMain.AnimationStepData[stepid].Distance);
this.yaw = parseFloat(GameMain.AnimationStepData[stepid].Yaw);
this.pitch = parseFloat(GameMain.AnimationStepData[stepid].Pitch);
this.posX = parseFloat(GameMain.AnimationStepData[stepid].PosX);
this.posY = parseFloat(GameMain.AnimationStepData[stepid].PosY);
this.posZ = parseFloat(GameMain.AnimationStepData[stepid].PosZ);
GameMain.DebugCam.setMoveRot(this.yaw,this.pitch,this.dis ,new pc.Vec3(this.posX ,this.posY ,this.posZ));
};
Commont.js
全局工具类
var Commont = pc.createScript('commont');
//Static function 虽然js并不支持重载
Commont.ActiveGo = function(go,b)
{
go.enabled = b;
};
Commont.ActiveGos = function(a,array,b)
{
for (var e = a; e < array.length; e++)
{
this.ActiveGo(array[e],b);
}
};
Commont.ActiveGosIndex = function(a,array,index,b)
{
for (var e = a; e < array.length; e++)
{
var isAct = (e=== index) ? b : !b;
this.ActiveGo(array[e],isAct);
}
};
Commont.Wait = function(func,time)
{
setTimeout(function () {
func();
}, time);
};
//UI调用部分
Commont.onChangeUI = function(t, a) {
for (var e = 0; e < t.length; e++)
{
if(e === a )
{
t[e].enabled = true;
}
else
{
t[e].enabled = false;
}
}
};
ModelControl.js
模型处理
var ModelControl = pc.createScript('modelControl');
ModelControl.attributes.add("ModelTotal",{
type: "entity"
});
//动画播放时间 毫秒单位
ModelControl.attributes.add("AnimationTime",{
type:"number",
"default":1
});
ModelControl.attributes.add("OutAnimationName", {
type: "string",
max:15,
array:!0
});
ModelControl.attributes.add("InAnimationName", {
type: "string",
max:15,
array:!0
});
ModelControl.attributes.add("ArrayModel",{//模型部件
type:"entity",
max:15,
array:!0
});
// initialize code called once per entity
ModelControl.prototype.initialize = function() {
Commont.ActiveGos(0,this.ArrayModel,false);
};
ModelControl.prototype.PlayAnimation = function(name)
{
this.ModelTotal.animation.play(name);
};
ModelControl.prototype.OnReset = function(b)
{
Commont.ActiveGo(this.ModelTotal,!b);
Commont.ActiveGo(this.ArrayModel[GameMain.CruuentGeneral],b);
};
ModelControl.prototype.SelectAnimationName = function(num,a)
{
return a<0? this.InAnimationName[num]:this.OutAnimationName[num];
};
// update code called every frame
ModelControl.prototype.update = function(dt) {
};
UIControl.js
UI处理
var Uicontrol = pc.createScript('uicontrol');
Uicontrol.attributes.add("BtnPlay", {
type: "entity"
});
Uicontrol.attributes.add("BtnReturn", {
type: "entity"
});
Uicontrol.attributes.add("BtnLast",{
type:"entity"
});
Uicontrol.attributes.add("BtnNext",{
type:"entity"
});
Uicontrol.attributes.add("BtnContentIntroduceUI",{
type:"entity"
});
Uicontrol.attributes.add("ArrayPointUI",{
type:"entity",
max:15,
array:!0
});
Uicontrol.attributes.add("ArrayTitleUI",{
type:"entity",
max:15,
array:!0
});
Uicontrol.attributes.add("ArrayContentUI",{
type:"entity",
max:15,
array:!0
});
Uicontrol.attributes.add("ArrayPlayUIAssetUI",{
type:"asset",
max:2,
array:!0
});
Uicontrol.self = null;
// initialize code called once per entity
Uicontrol.prototype.initialize = function() {
Uicontrol.self = this;
//初始化事件
GameMain.EvtMgr.on(GameMain.Evt_StepChange, this.StepChangeClick, this);
GameMain.EvtMgr.on(GameMain.Evt_GeneralEvent, this.GeneralClick, this);
GameMain.EvtMgr.on(GameMain.Evt_StartBoom, this.StartBoomClick, this);
GameMain.EvtMgr.on(GameMain.Evt_ReturnBoom,this.ReturnBoomClick, this);
GameMain.EvtMgr.on(GameMain.Evt_Content,this.ContentClick,this);
//初始化操作
Commont.ActiveGo(this.BtnReturn,false);
Commont.ActiveGo(this.BtnContentIntroduceUI,false);
Commont.ActiveGo(this.BtnLast,true);
Commont.ActiveGo(this.BtnNext,true);
Commont.ActiveGo(this.BtnPlay,true);
Commont.ActiveGos(0,this.ArrayPointUI,false);
Commont.ActiveGos(0,this.ArrayTitleUI,false);
Commont.ActiveGos(0,this.ArrayContentUI,false);
//初始化播放UI
this.BtnPlay.element.texture = this.ArrayPlayUIAssetUI[0].resource;
this.isPut = true;
this.isPlay = false;
this.isPlayContent = false;
};
Uicontrol.isStep = true;
Uicontrol.isPlayAnimation = true;
Uicontrol.prototype.StepChangeClick = function(a)
{//播放步骤动画
if(Uicontrol.isStep && this.isPut){
this.OnStepChange(a);
}
};
Uicontrol.prototype.OnStepChange = function(a){
GameMain.CurrentStep += a;
console.log("Uicontrol.CurrentStep" + GameMain.CurrentStep);
if(GameMain.CurrentStep <0)
{
GameMain.CurrentStep = 0;
return;
}
else if(GameMain.CurrentStep>GameMain.TotalSteps)
{
GameMain.CurrentStep = GameMain.TotalSteps;
return;
}
Uicontrol.isStep = false;
// 下一步 0 1 2 3 上一步 0 1 2 3 globals.CurrentStep 1 2 3 4
var isActive = a<0? false: true; //判断显隐
var currentNum = a<0? GameMain.CurrentStep :GameMain.CurrentStep-1; //判断iD
var animationName = GameMain.ModelControl.SelectAnimationName(currentNum,a); //判断动画名字
var time = isActive ? GameMain.ModelControl.AnimationTime:0;
GameMain.ModelControl.PlayAnimation(animationName); //调用模型播放动画的事件
setTimeout(function () {
if(currentNum==(GameMain.TotalSteps-1))
{
Commont.ActiveGos(currentNum,Uicontrol.self.ArrayPointUI,isActive);
}
Commont.ActiveGo(Uicontrol.self.ArrayPointUI[currentNum], isActive);
}, time);
setTimeout(function () {
Uicontrol.isStep = true;
}, GameMain.ModelControl.AnimationTime);
};
Uicontrol.prototype.StartBoomClick = function()
{//点击播放爆炸动画
if(this.isPut &&Uicontrol.isStep)
{
Uicontrol.isPlayAnimation = !Uicontrol.isPlayAnimation;
this.isPut = !this.isPut;
this.isPlay = !this.isPlay;
var num = this.isPlay ? GameMain.TotalSteps :0;
GameMain.MainCamera.script.cameraHandle.StepChange(num); //旋转和中心点都做完了
this.BtnPlay.element.texture =this.isPlay ?
this.ArrayPlayUIAssetUI[1].resource:this.ArrayPlayUIAssetUI[0].resource;//变换播放按钮
var offset = this.isPlay? 1: -1 ;
this.OnStepChange(offset);
var a = setInterval(function(){
if((Uicontrol.self.isPlay&& GameMain.CurrentStep >=GameMain.TotalSteps) ||( GameMain.CurrentStep <=0 &&!Uicontrol.self.isPlay) )
{
Uicontrol.isPlayAnimation = true;
Uicontrol.self.isPut = true;
Uicontrol.isStep = true;
clearInterval(a);
}
Uicontrol.self.OnStepChange(offset);
},GameMain.ModelControl.AnimationTime);
}
};
Uicontrol.prototype.GeneralClick = function()
{//点击UI直接传参 globals.CurrentStep
if(Uicontrol.isPlayAnimation){
this.OnReset(true);
Commont.ActiveGos(0,this.ArrayPointUI, false);
GameMain.DebugCam.focusEntity = GameMain.ModelControl.ArrayModel[GameMain.CruuentGeneral];
}
};
Uicontrol.prototype.ReturnBoomClick = function()
{
this.OnReset(false);
for (var e = 0; e < GameMain.CurrentStep; e++)
{
Commont.ActiveGo(this.ArrayPointUI[e],true);
}
if(GameMain.CurrentStep==GameMain.TotalSteps)
{
Commont.ActiveGos(GameMain.TotalSteps,this.ArrayPointUI,true);
}
GameMain.DebugCam.focusEntity = GameMain.ModelControl.ModelTotal;
GameMain.MainCamera.script.cameraHandle.StepChange(GameMain.TotalSteps); //旋转和中心点都做完了
};
Uicontrol.prototype.OnReset = function(b)
{
Commont.ActiveGo(this.BtnReturn,b);
Commont.ActiveGo(this.BtnPlay,!b);
Commont.ActiveGo(this.BtnContentIntroduceUI,b);
Commont.ActiveGo(this.BtnLast,!b);
Commont.ActiveGo(this.BtnNext,!b);
Commont.ActiveGo(this.ArrayTitleUI[GameMain.CruuentGeneral],b);
GameMain.ModelControl.OnReset(b); //模型
};
Uicontrol.prototype.ContentClick = function(a)
{
if(GameMain.CruuentGeneral ==1){return;}
this.isPlayContent = !this.isPlayContent;
Commont.ActiveGo(this.ArrayContentUI[GameMain.CruuentGeneral],this.isPlayContent);
};
StepUIClick.js
按钮事件
var StepUiclick = pc.createScript('stepUiclick');
StepUiclick.attributes.add("eventName",{
type:"string",
"default":"name_EventName"
});
//不知道有啥用
StepUiclick.attributes.add("eventType",{
type: "number",
"default": 0,
"enum": [{
StepChangeEvent : 0
},{
GeneralEvent:1,
},{
StartBoom : 2,
},{
ReturnBoom :3
},{
ContentEvent:4,
}]
});
StepUiclick.attributes.add("eventIndex_listen", {
type: "number",
"default": 0
});
// initialize code called once per entity
StepUiclick.prototype.initialize = function() {
this.entity.element.on('touchstart', this.onStateChange, this);
};
StepUiclick.prototype.onStateChange = function(t)
{
console.log("点击到UI "+this.eventName +" " +this.eventIndex_listen);
GameMain.EvtMgr.fire(this.eventName, this.eventIndex_listen);
};
读解摄像机
OrbitCamera.js
外部参数
- DistanceMax 最大距离
- DistanceMin 最小距离
- PitchAngleMax 最大角度(仰视)
- PitchAngleMin 最小角度(俯视)
- inertiaFactor 平滑阻尼,建议0.3左右,表示滑动完之后的一个平滑过程。
- FocusEntity 焦点模型,外部直接调用替换就可以更换模型。
- FrameonStart 好像是预加载的意思。
- CamCenter 中心点(如果有更换中心点的需求)。
内部参数
- distance(属性) 距离。
- pitch(属性) X轴的角度。
- yaw(属性) Y轴的角度。
- pivotPoint(属性) 中心点的位置。
- setMoveRot(方法) 自己加的,用来设置距离、角度和中心点。(floatY,floatX,floatDistance,Vec3)
- 处理了旋转角度的问题。
// yaw是Y轴 paich是X轴 distance是距离 center是中心点。
OrbitCamera.prototype.setMoveRot = function(yaw, pitch, distance,center)
{
var y = this.calShortRotate( yaw,this._targetYaw );
this._targetYaw = y;
this._targetPitch = pitch;
this._targetDistance = distance;
this.pivotPoint = center;
};
OrbitCamera.prototype.calShortRotate = function( t, e)
{
if((0 > e) || (e > 360))
{
var a = (e - e % 360) + parseFloat(t);//t是目标值,读的json所以要转一下。
return a;
}
return t;
};
MouseInput.js
MouseInput 没做修改。相对Touch来说比较简单容易理解,Down Up Move Wheel 四个事件单逻辑就够了。
Down的时候开启Move监听,Up的时候关闭Move监听,Move对 pitch 和 yaw 进行更改。
Wheel 对 distance 进行更改。
TouchInput.js
TouchInput也没做修改也是四个事件 TOUCHSTART TOUCHEND TOUCHCANCEL TOUCHMOVE。
主要Move事件,分为单点和多点。单点和鼠标逻辑一样。
多点分为 两个Touch距离是变化还是不变,变化的话更改距离,不变的话就是改中心点。
写博客不易,如果想请我喝一杯冰阔落的话,请用手机在下方扫描二维码向我打赏哦。款项将使用于本站阿里云主机的托管费用,在此非常感谢您的打赏。
Comments | NOTHING