Files
fc/dev/project/assets/Scripts/mod/battle/act/cmp.battle.scene.js
T

703 lines
24 KiB
JavaScript
Raw Normal View History

2026-05-23 22:10:14 +08:00
/******************************************************************
*
* 新版战斗场景
*
******************************************************************/
//16 X 8格子地图,角色层 从左到右,从上到下,cellsize 80*80
//角色层只跟随场景销毁,角色死亡只隐藏
const BridgeWindow = require( "bridge.window" );
const PathTool = require( "pathtool" );
const BTC = require("battle_controller");
const BCT = require("battle_const");
const BET = require( "battle_event" );
const { SCENE_TAG,SCREEN_WIDTH,SCREEN_HEIGHT,PlayerAction } = require( "define" );
const NxSpine = require("nx.fx.spine");
cc.Class( {
extends: BridgeWindow,
properties: {
//主要节点
main_layer:{
default:null,
type:cc.Node
},
battle_layer:{
default:null,
type:cc.Node
},
black_layer:{
default:null,
type:cc.Node
},
pk_layer:{
default:null,
type:cc.Node
},
//挂机和剧情战斗地图
map_lLayer:{
default:null,
type:cc.Node,
displayName:"超远景"
},
map_fLayer:{
default:null,
type:cc.Node,
displayName:"远景"
},
map_sLayer:{
default:null,
type:cc.Node,
displayName:"近景"
},
//其他地图
map_oLayer:{
default:null,
type:cc.Node,
displayName:"单场景"
},
//角色层和特效层
role_layer:{
default:null,
type:cc.Node
},
effect_layer_2:{
default:null,
type:cc.Node,
displayName:"下层特效"
},
effect_layer_1:{
default:null,
type:cc.Node,
displayName:"上层特效"
},
elfin_layer:{
default:null,
type:cc.Node,
displayName:"精灵(僚机)层特效"
},
//地图图片
maps:{
default:[],
type:[cc.Node]
},
mapf:{
default:[],
type:[cc.Node]
},
mapl:{
default:[],
type:[cc.Node]
},
talk:{
default:null,
type:cc.Node
},
talkTxt:{
default:null,
type:cc.Node
},
startSp:{
default:null,
type:NxSpine
}
},
onLoad() {
this.battle_model = BTC.getInstance().getModel();
this.battle_hook_model = BTC.getInstance().getHookModel();
this.battle_drama_model = require( "battle_drama_controller" ).getInstance().getModel();
this.battle_res_id = 0 //当前战斗背景资源
this.is_real_fight = false
this.need_run_map = true //是否需要移动地图
this.l_speed = 60 //超远景移动速率
this.f_speed = 150 //地图移动速率
this.bg_speed = 100 // 背景层移动速率
this.combat_type = BCT.Fight_Type.Nil // 当前战斗类型
this.real_role_list = {} // 当前真实战斗的单位列表
this.resources_list = {} // 下载资源
this.is_pre_updatescene = false;
this.bindGEvent( BET.INIT_BATTLE_RESBG, this.initSceneResId.bind( this ) );
this.bindGEvent( BET.HIDE_BAT_UI_IN_SETTLE, this.hideSceneUI.bind(this));
},
hideSceneUI(){
if(this.node && this.node.isValid){
this.node.active = false;
}
},
start(){
},
initSceneResId: function() {
this.battle_res_id = 0;
this.init_drama_finish = false;
},
// 重载:参数打开
onOpenConfigs: function(params) {
this.buildUILayer();
if(params.finish_cb){//在model設置主場景
params.finish_cb(this);
}
},
onPreClosed: function() {
nx.bridge.camBattle.reset(0.1,null);
this.need_run_map = false;
if( this.black_layer ) {
this.black_layer.stopAllActions();
}
if(this.elfin_skill_container){
this.elfin_skill_container.destroy();
}
if(this.battle_model.isInRealBattle()){
this.battle_model.clearBattleNd();
// 只要不是剧情副本,都切出战斗
BTC.getInstance().requestCutOutBattle()
}
},
// 改变状态
changeVisible: function( status ) {
if( !status ) {
this.node.active = false;
} else {
this.node.active = true;
}
},
/**
* 更新或者创建战斗场景
* @param {*} is_real
*/
updateBattleScene: function( is_real ) {
this.is_real_fight = is_real
this.is_pre_updatescene = false;
this.node.active = true;
// 更新战斗地图 1
this.changeBattleScene( is_real );
// 初始化战斗单位 2
if( is_real ) {
this.battle_res_id = 0;
// 创建真战斗的角色
var need_enter = this.battle_model.needPlayEnterAction();
if( need_enter ) { // 如果是初始化战斗的话,需要播放进场动画
this.floorTips();
} else {
this.battle_model.createRoleList();
}
this.update_drama_battle = false;
this.init_drama_finish = false;
} else {
this.update_drama_battle = true;
// 创建假战斗的角色
if( this.is_pre_updatescene )
this.battle_hook_model.prepareStarBattle( this.initDramaFinish.bind( this ) )
}
},
// 判断是否需要播放进出场的boss来袭或者是pk的VS动画
floorTips: function() {
var battle_data = this.battle_model.getCurBattleData();
if( nx.dt.objEmpty(battle_data) ) return;
var combat_config = game.configs.combat_type_data.data_fight_list[ battle_data.combat_type ];
if( combat_config ) {
let start_effect = "E80038";
let eft_name = start_effect;
if(battle_data.combat_type == 44){
start_effect = "E80052";
eft_name = "action";
}
let res_path = cc.js.formatStr("resDB/effects/%s/%s",start_effect,eft_name);
this.startSp.load(res_path,(_e)=>{
if(!_e){
this.startSp.action(PlayerAction.action,false,(_key,_name)=>{
if(_key == "complete"){
this.battle_model.createRoleList();
return;
}
});
}else{
this.startSp.stop();
this.battle_model.createRoleList();
}
});
// Utils.playEffectOnce( start_effect, eft_name, 0, 0, this.pk_layer, ()=> {
// this.battle_model.createRoleList();
// }, PlayerAction.action, 1 )
} else {
this.battle_model.createRoleList();
}
},
// 获取当前战斗的资源
curBattleResId: function( combat_type ) {
let battle_res_id = 10001;
if( combat_type == BCT.Fight_Type.Darma ) {
var drama_data = this.battle_drama_model.getDramaData();
if(drama_data && drama_data.chapter_id){
let base_config = game.configs.battle_bg_data.data_info2[ combat_type ][drama_data.chapter_id];
if( base_config == null ) {
base_config = game.configs.battle_bg_data.data_info[ BCT.Fight_Type.Default ];
}
if( base_config == null ) {
battle_res_id = 10001;
} else {
battle_res_id = base_config.bid;
}
}
} else {
let base_config = game.configs.battle_bg_data.data_info[ combat_type ];
if( base_config == null ) {
base_config = game.configs.battle_bg_data.data_info[ BCT.Fight_Type.Default ];
}
if( base_config == null ) {
battle_res_id = 10001;
} else {
battle_res_id = base_config.bid;
}
// // 冒险战斗后面加
// if( combat_type == BCT.Fight_Type.Adventrue ) {
// var base_data = AdventureController.getInstance().getModel().getAdventureBaseData();
// if( base_data ) {
// var config = game.configs.adventure_data.data_battle_res[ base_data.id ];
// if( config && config.battle_res_id ) {
// battle_res_id = config.battle_res_id;
// }
// }
// }
}
return battle_res_id;
},
// 更新战斗背景
changeBattleScene: function( is_real ) {
var battle_data = this.battle_model ? this.battle_model.getCurBattleData() : null;
var unreal_battle_data = this.battle_hook_model.getUnrealBattleData();
if( battle_data == null && unreal_battle_data == null ) return;
var combat_type = BCT.Fight_Type.Nil;
if( is_real == true ) {
combat_type = battle_data.combat_type; // 如果是真实战斗,并且是剧情战斗的话,就要去当前剧情id然后获取资源
} else {
combat_type = BCT.Fight_Type.Darma
}
this.combat_type = combat_type; // 整场战斗唯一,也是判断的依据
this.need_run_map = !is_real; // 非真实战斗才需要移动地图
var battle_res_id = this.curBattleResId( combat_type );
this.loaderBattleScene( battle_res_id ); // 切换战斗背景资源
},
// 创建战斗背景,也用于更新下一章节的时候切换假战斗资源
loaderBattleScene: function( battle_res_id ) {
if( battle_res_id == 0 ) return;
if( this.battle_res_id != battle_res_id ) {
this.battle_res_id = battle_res_id;
if( this.combat_type == BCT.Fight_Type.Darma ) {
if( battle_res_id ) {
this.createSingleScene( battle_res_id );
this.is_pre_updatescene = true;
if( this.update_drama_battle && !this.init_drama_finish ) {
this.battle_hook_model.prepareStarBattle( this.initDramaFinish.bind( this ) )
}
// this.createDramaScene( battle_res_id );
}
} else {
this.createSingleScene( battle_res_id );
}
}else{
this.is_pre_updatescene = true;
}
},
// 创建剧情副本的背景资源
// s_parh:string 背景资源 f_path:string 前景资源
createDramaScene: function( battle_res_id ) {
// var bg_1_f = false;
// var bg_2_f = false;
// var drama_paths = PathTool.getBattleDrameBg( battle_res_id );
// this.map_oLayer.active = false;
// //需要计算实际屏幕宽度下的所需地图块的数量
// let self = this;
// cc.loader.loadRes(drama_paths.s,cc.SpriteFrame,(err,obj)=>{
// if(err){
// return;
// }
// let sps = nx.gui.getComponent(self.maps[0],"",cc.Sprite);
// sps.spriteFrame = obj;
// self.maps[0].x = 0;
// let num = Math.ceil(self.main_layer.width / self.maps[0].width);
// for(let i=1;i<=num;i++){
// let spsc = cc.instantiate(self.maps[0]);
// spsc.parent = this.maps[0].parent;
// spsc.x = self.maps[i-1].x + i * self.maps[0].width;
// self.maps.push(spsc);
// }
// // let sps2 = nx.gui.getComponent(this.maps[1],"",cc.Sprite);
// // sps2.spriteFrame = obj;
// // this.maps[1].x = this.maps[0].x + this.maps[0].width;
// bg_1_f = true;
// if( bg_2_f ) {
// self.is_pre_updatescene = true;
// if( self.update_drama_battle && !self.init_drama_finish ) {
// self.battle_hook_model.prepareStarBattle( self.initDramaFinish.bind( self ) )
// }
// }
// });
// cc.loader.loadRes(drama_paths.f,cc.SpriteFrame,(err,obj)=>{
// if(err){
// return;
// }
// let spf = nx.gui.getComponent(self.mapf[0],"",cc.Sprite);
// spf.spriteFrame = obj;
// self.mapf[0].x = 0;
// let numf = Math.ceil(self.main_layer.width / self.mapf[0].width);
// for(let l=1;l<=numf;l++){
// let spsf = cc.instantiate(self.mapf[0]);
// spsf.parent = this.mapf[0].parent;
// spsf.x = self.mapf[l-1].x + l * self.mapf[0].width;
// self.mapf.push(spsf);
// }
// // let spf2 = nx.gui.getComponent(this.mapf[1],"",cc.Sprite);
// // spf2.spriteFrame = obj;
// // this.mapf[1].x = this.mapf[0].x + this.mapf[0].width;
// bg_2_f = true;
// if( bg_1_f ) {
// self.is_pre_updatescene = true;
// if( self.update_drama_battle && !self.init_drama_finish ) {
// self.battle_hook_model.prepareStarBattle( self.initDramaFinish.bind( self ) )
// }
// }
// });
// cc.loader.loadRes(drama_paths.l,cc.SpriteFrame,(err,obj)=>{
// if(err){
// return;
// }
// let spl = nx.gui.getComponent(self.mapl[0],"",cc.Sprite);
// spl.spriteFrame = obj;
// self.mapl[0].x = 0;
// let numl = Math.ceil(self.main_layer.width / self.mapl[0].width);
// for(let a=1;a<=numl;a++){
// let spsl = cc.instantiate(self.mapl[0]);
// spsl.parent = this.mapl[0].parent;
// spsl.x = self.mapl[a-1].x + a * self.mapl[0].width;
// self.mapl.push(spsl);
// }
// // let spl2 = nx.gui.getComponent(this.mapl[1],"",cc.Sprite);
// // spl2.spriteFrame = obj;
// // this.mapl[1].x = this.mapl[0].x + this.mapl[0].width;
// });
},
initDramaFinish: function() {
this.init_drama_finish = true;
},
// 创建单张战斗背景的
createSingleScene: function( res_id ) {
this.map_oLayer.active = true;
var res_path = PathTool.getBattleSingleBg( res_id );
let spf = nx.gui.getComponent(this.map_oLayer,"",cc.Sprite);
nx.gui.setSpriteFrame(spf,"",res_path);
// cc.loader.loadRes( res_path,cc.SpriteFrame,( err,res_object )=> {
// if(err){
// return this.createSingleScene( 10001 );
// }
// spf.spriteFrame = res_object;
// } )
},
update: function(dt){
//只有准备场景完毕后才能执行地图更新
// if( this.need_run_map && this.init_drama_finish ) {
// this.moveMap(dt)
// }
},
// 设置是否移动地图,只有剧情战斗才需要做这个处理
changeMoveMapStatus: function( status ) {
if( this.combat_type == BCT.Fight_Type.Darma ) {
this.need_run_map = status;
}
},
// 移动地图
moveMap: function(dt) {
if(!this.maps[0] || !this.mapf[0] || !this.mapl[0])return;
for(let a=0;a<this.maps.length;a++){
this.changeBgPosition2(a, this.maps[a], this.maps[0].width )
this.maps[a].x = this.maps[a].x - this.bg_speed * dt;
}
for(let b=0;b<this.mapf.length;b++){
this.changeBgPosition3(b, this.mapf[b], this.mapf[0].width )
this.mapf[b].x = this.mapf[b].x - this.f_speed * dt;
}
for(let c=0;c<this.mapl.length;c++){
this.changeBgPosition4(c, this.mapl[c], this.mapl[0].width )
this.mapl[c].x = this.mapl[c].x - this.l_speed * dt;
}
},
changeBgPosition2(index,cur_bg,width){
if(cur_bg == null)return;
if( cur_bg.x <= -width ) {
if(this.maps[index - 1] != null){
cur_bg.x = this.maps[index - 1].x + width
}else{
cur_bg.x = this.maps[this.maps.length - 1].x + width
}
}
},
changeBgPosition3(index,cur_bg,width){
if(cur_bg == null)return;
if( cur_bg.x <= -width ) {
if(this.mapf[index - 1] != null){
cur_bg.x = this.mapf[index - 1].x + width
}else{
cur_bg.x = this.mapf[this.mapf.length - 1].x + width
}
}
},
changeBgPosition4(index,cur_bg,width){
if(cur_bg == null)return;
if( cur_bg.x <= -width ) {
if(this.mapl[index - 1] != null){
cur_bg.x = this.mapl[index - 1].x + width
}else{
cur_bg.x = this.mapl[this.mapl.length - 1].x + width
}
}
},
// 设置地图位置可能移动越界了
changeBgPosition: function( cur_bg, target_bg, width ) {
if( cur_bg == null || target_bg == null ) { return; }
if( cur_bg.x <= -width ) {
cur_bg.x = target_bg.x + width
}
},
// 获取战斗的特效层
getBattleEffectLayer: function( index ) {
if( index == 1 ) {
return this.effect_layer_1;
} else {
return this.effect_layer_2;
}
},
// 返回角色层
getBattleRoleLayer: function() {
return this.role_layer
},
// 设置黑屏,战斗效果播放
setBlack: function( status, alpha ) {
if( !status ) {
if( this.black_layer ) {
this.black_layer.runAction( cc.fadeOut( 0.2 ) );
// this.black_layer.stopAllActions();
this.black_layer.active = false;
this.black_on_show = false;
}
} else {
if( this.black_on_show ) return;
this.black_on_show = true;
this.black_layer.active = true;
this.black_layer.opacity = 0;
this.black_layer.runAction( cc.fadeIn( 0.2 ) );
}
},
// 震屏,战斗效果播放
shakeScreen: function( shake_id ) {
if( this.is_shake ) return;
if( shake_id == null ) return;
var data_config = game.configs.skill_data.data_get_shake_data[ shake_id ];
if( data_config == null ) return;
this.is_shake = true;
this.main_layer.stopAllActions();
this.main_layer.setPosition( 0, 0 );
// 重置位置
var returnPos = function() {
this.is_shake = false;
this.main_layer.setPosition( 0, 0 );
}.bind( this );
var order = [ 0, 3, 6, 4, 7, 8, 5, 2, 1 ];
var str = data_config.shake_strength; // 振幅,单位像素
var step = data_config.shake_rate * 0.003; // 振幅间隔,单位秒
var shakeTime = data_config.shake_time; // 振动次数
var shakeXTime = 0.35; // 横向加倍
var shakeYTime = 0.35; // 纵向加倍
var xy_list = [ [ -0.7, 0.7 ], [ 0, 1 ], [ 0.7, 0.7 ], [ -1, 0 ], [ 0, 0 ], [ 1, 0 ], [ -0.7, -0.7 ], [ 0, -1 ], [ 0.7, -0.7 ] ];
// 随机设置坐标
let setRandomPos = function( index ) {
var pos_x = str * shakeYTime * xy_list[ order[ index ] ][ 0 ];
var pos_y = -str * shakeXTime * xy_list[ order[ index ] ][ 1 ];
this.main_layer.setPosition( pos_x, pos_y );
}.bind( this );
let base_call = null;
for( let times = 0; times < shakeTime; times++ ) {
for( let index = 0; index < order.length; index++ ) {
var delay = cc.delayTime( step );
if( base_call == null ) {
base_call = cc.sequence( cc.callFunc( function() {
setRandomPos( index );
}.bind( this ) ), delay );
} else {
base_call = cc.sequence( base_call, cc.callFunc( function() {
setRandomPos( index );
}.bind( this ), delay ) );
}
}
str = str - 3;
}
if( base_call ) {
base_call = cc.sequence( base_call, cc.callFunc( returnPos ) );
this.main_layer.runAction( base_call );
}
},
showElfinSkillAni: function( attacker, call_back, is_act ) { //精灵的效果
if( attacker == null || !attacker.isValid || attacker.skill_data == null ) {
if( call_back ) {
call_back()
}
return
}
if( !is_act && attacker.temp_skill_bid != attacker.attacker_info.skill_bid ) {
attacker.temp_skill_bid = attacker.attacker_info.skill_bid
let is_left = this.battle_model.isLeft( attacker.group )
let object_type = attacker.object_type
if( object_type != BCT.BattleObjectType.Elfin ) { return }
//精靈喊招特效
// if( this.elfin_skill_container == null ) {
// this.elfin_skill_container = new cc.Node( "elfin_skill_container" )
// this.elfin_skill_container.setContentSize( cc.size( this.main_layer.width, this.main_layer.height ) )
// this.elfin_skill_container.setAnchorPoint( cc.v2( 0, 0 ) )
// this.elfin_skill_container.setPosition( 0, 0 )
// this.elfin_skill_container.setParent( this.effect_layer_1 );
// }
this.elfin_layer.setContentSize(cc.size( this.main_layer.width, this.main_layer.height ));
if( object_type == null ) {
if( call_back ) {
call_back()
}
} else {
this.elfin_layer.active = true;
this.elfin_layer.stopAllActions();
let call_back_fun = cc.callFunc( function() {
call_back()
}.bind( this ) )
let call_back_fun_1 = cc.callFunc( function() {
attacker.addSpriteRole(attacker.attacker_info.skill_bid,is_left);
attacker.spriteAction();
}.bind( this ) )
let head_delay = cc.delayTime( 0.5 )
let head_over = cc.callFunc( function() {
this.elfin_layer.active = ( false )
this.elfin_layer.scaleX = 1
}.bind( this ) )
this.elfin_layer.runAction(cc.sequence(call_back_fun_1,call_back_fun,head_delay,head_over));
}
} else {
if( call_back ) {
call_back()
}
}
},
talkOne(msg,scene_pos,is_friend,_cb){
nx.gui.setString(this.talkTxt,"",msg);
this.talk.y = scene_pos.y + 170;
if(is_friend){
this.talk.scaleX = 1;
this.talkTxt.scaleX *= 1;
this.talk.x = scene_pos.x - 60;
}else{
if(this.talkTxt.scaleX > 0){
this.talkTxt.scaleX *= -1;
}
this.talk.scaleX = -1;
this.talk.x = scene_pos.x + 60;
}
this.talk.active = true;
this.scheduleOnce(()=>{
nx.dt.fnInvoke( _cb, true );
this.talk.active = false;
},1.5);
},
// 创建UI层
buildUILayer: function() {
let layer = nx.gui.find( this.node, "battleUI" );
if( layer ) {
return;
}
layer = new cc.Node();
layer.name = "battleUI";
layer.setContentSize( this.node.getContentSize() );
layer.setAnchorPoint( 0.5, 0.5 )
layer.setPosition( 0, 0 );
layer.zIndex = cc.macro.MAX_ZINDEX - 1;
this.node.addChild( layer );
let widget = layer.addComponent( cc.Widget );
widget.isAlignTop = true;
widget.isAlignBottom = true;
widget.isAlignLeft = true;
widget.isAlignRight = true;
widget.alignMode = cc.Widget.AlignMode.ON_WINDOW_RESIZE;
widget.updateAlignment();
nx.bridge.ui.addSceneNode( SCENE_TAG.battleUI, layer );
},
} );