description import { MapLevel } from "../data/TankBattleLevel" ; import { TankBettle } from "../data/TankBattleGameData" ; import { TankBettleTankPlayer , TankBettleTankEnemy } from "./TankBattleTank" ; import TankBettleBullet from "./TankBattleBullet" ; import TankBattleBlock from "./TankBattleBlock" ; import TankBattleGameView from "../view/TankBattleGameView" ; import { Manager } from "../../../../script/common/manager/Manager" ; import TankBattleGameOver from "../view/TankBattleGameOver" ; import { ViewZOrder } from "../../../../script/common/config/Config" ; import TankBattleProps from "./TankBattleProps" ; const { ccclass , property } = cc . _decorator ; @ ccclass export default class TankBattleMap extends cc . Component { description private _blockPrefab : cc . Node = null ; description public setPrefabs ( node ) { this . _blockPrefab = node ; } description public playerOne : TankBettleTankPlayer = null ; description public playerTwo : TankBettleTankPlayer = null ; private outWall : cc . Node [ ] = [ ] ; public owner : TankBattleGameView = null ; description private _enemys : cc . Node [ ] = [ ] ; private _waitEnemy : cc . Node [ ] = [ ] ; description private _heart : cc . Node = null ; description public propsProductNode : cc . Node = null ; description private _waitingDestory : cc . Node [ ] = [ ] ; protected onLoad ( ) { this . node . children . forEach ( node => { this . outWall . push ( node ) ; } ) ; this . node . removeAllChildren ( false ) ; let node = new cc . Node ( ) ; this . node . addChild ( node ) ; this . propsProductNode = node ; } protected onDestroy ( ) { this . outWall . forEach ( ( value ) => { value . destroy ( ) ; } ) ; this . _waitEnemy . forEach ( ( value ) => { value . destroy ( ) ; } ) ; this . _waitEnemy = [ ] ; this . outWall = [ ] ; this . propsProductNode = null ; } protected update ( ) { this . addEnemy ( ) ; } description private randomEnemyPosition ( enemyNode ) { let pos = cc . randomRangeInt ( TankBettle . EnemyBornPosition . MIN , TankBettle . EnemyBornPosition . MAX + 1 ) ; let outPosition = cc . v3 ( 0 , 0 , 0 ) ; let outBornPosition = TankBettle . EnemyBornPosition . RIGHT ; if ( pos == 0 ) { outPosition . x = enemyNode . width / 2 ; outPosition . y = - enemyNode . height / 2 ; outBornPosition = TankBettle . EnemyBornPosition . LEFT ; } else if ( pos == 1 ) { outPosition . x = this . node . width / 2 ; outPosition . y = - enemyNode . height / 2 ; outBornPosition = TankBettle . EnemyBornPosition . MIDDLE ; } else { outPosition . x = this . node . width - enemyNode . width / 2 ; outPosition . y = - enemyNode . height / 2 ; outBornPosition = TankBettle . EnemyBornPosition . RIGHT ; } return { position : outPosition , bornPosition : outBornPosition } ; } description private randomEnemyDirction ( bornPosition ) { let allDir = [ TankBettle . Direction . LEFT , TankBettle . Direction . RIGHT , TankBettle . Direction . DOWN ] ; if ( bornPosition == TankBettle . EnemyBornPosition . LEFT ) { allDir = [ TankBettle . Direction . DOWN , TankBettle . Direction . RIGHT ] ; } else if ( bornPosition == TankBettle . EnemyBornPosition . RIGHT ) { allDir = [ TankBettle . Direction . DOWN , TankBettle . Direction . LEFT ] ; } let value = cc . randomRangeInt ( 0 , allDir . length ) ; let outDir = allDir [ value ] ; return outDir ; } public addEnemy ( ) { if ( this . _waitingDestory . length > 0 ) { return ; } if ( TankBettle . gameData . gameStatus == TankBettle . GAME_STATUS . GAME && TankBettle . gameData . curLeftEnemy > 0 && this . _enemys . length < TankBettle . MAX_APPEAR_ENEMY ) { let type = cc . randomRangeInt ( TankBettle . EnemyType . MIN , TankBettle . EnemyType . MAX + 1 ) ; let prefab = TankBettle . gameData . getEnemyPrefab ( type ) ; let randomPos = this . randomEnemyPosition ( prefab ) ; let enemyNode = this . _waitEnemy . shift ( ) ; if ( enemyNode == null ) { enemyNode = cc . instantiate ( prefab ) ; } else { } this . node . addChild ( enemyNode , TankBettle . ZIndex . TANK ) ; let enemy = enemyNode . getComponent ( TankBettleTankEnemy ) ; if ( ! enemy ) { enemy = enemyNode . addComponent ( TankBettleTankEnemy ) ; } enemy . type = type ; enemy . config = TankBettle . gameData . getEnemyConfig ( type ) ; enemyNode . position = randomPos . position ; enemy . direction = this . randomEnemyDirction ( randomPos . bornPosition ) ; enemyNode . getComponent ( cc . BoxCollider ) . enabled = false ; if ( this . checkBornPosition ( randomPos . position , enemyNode ) ) { enemy . move ( ) ; enemy . startShoot ( ) ; this . _enemys . push ( enemyNode ) ; enemyNode . getComponent ( cc . BoxCollider ) . enabled = true ; TankBettle . gameData . curLeftEnemy -= 1 ; TankBettle . gameData . gameView . showGameInfo ( ) ; } else { enemyNode . removeFromParent ( false ) ; this . _waitEnemy . push ( enemyNode ) ; } } } private intersects ( node , other ) { let box = node . getBoundingBox ( ) ; let otherBox = other . getBoundingBox ( ) ; let scale = 3 ; let width = box . width * scale ; let height = box . height * scale ; let newBox = cc . rect ( box . x - ( width - box . width ) / 2 , box . y - ( height - box . height ) / 2 , width , height ) ; if ( newBox . intersects ( otherBox ) ) { return true ; } return false ; } private checkBornPosition ( pos , node ) { let result = true ; for ( let i = 0 ; i < this . _enemys . length ; i ++ ) { let enemy = this . _enemys [ i ] ; if ( this . intersects ( enemy , node ) ) { result = false ; break ; } } if ( result ) { if ( this . playerOne && this . intersects ( node , this . playerOne . node ) ) { return false ; } if ( this . playerTwo && this . intersects ( node , this . playerTwo . node ) ) { return false ; } } return result ; } description public removeAllEnemy ( ) { for ( let i = 0 ; i < this . _enemys . length ; i ++ ) { let enemy = this . _enemys [ i ] ; enemy . getComponent ( TankBettleTankEnemy ) . die ( ) ; this . _waitingDestory . push ( enemy ) ; } this . _enemys = [ ] ; this . checkGamePass ( ) ; } public removeEnemy ( enemy ) { let i = this . _enemys . length ; while ( i -- ) { if ( this . _enemys [ i ] == enemy ) { enemy . removeFromParent ( ) ; enemy . destroy ( ) ; this . _enemys . splice ( i , 1 ) ; } } i = this . _waitingDestory . length ; while ( i -- ) { if ( this . _waitingDestory [ i ] == enemy ) { enemy . removeFromParent ( ) ; enemy . destroy ( ) ; this . _waitingDestory . splice ( i , 1 ) ; } } this . checkGamePass ( ) ; } description private checkGamePass ( ) { if ( TankBettle . gameData . curLeftEnemy <= 0 ) { if ( this . _enemys . length <= 0 ) { TankBettle . gameData . isNeedReducePlayerLive = false ; TankBettle . gameData . gameView . nextLevel ( ) ; } } } public setLevel ( level ) { if ( ! ! ! this . _blockPrefab ) { cc . error ( `请先设置预置节点` ) ; return ; } this . node . removeAllChildren ( true ) ; this . outWall . forEach ( ( value ) => { this . node . addChild ( cc . instantiate ( value ) ) ; } ) ; this . _enemys = [ ] ; let data = MapLevel [ level ] ; let x = 0 ; let y = 0 ; let tempBlock = this . _blockPrefab . getChildByName ( "block_1" ) ; let prefebSize = cc . size ( tempBlock . width , tempBlock . height ) ; for ( let i = 0 ; i < data . length ; i ++ ) { const element = data [ i ] ; y = - ( ( i + 1 ) * prefebSize . height / 2 + i * prefebSize . height / 2 ) ; for ( let j = 0 ; j < element . length ; j ++ ) { const blockData = element [ j ] ; if ( blockData > 0 && blockData != TankBettle . BLOCK_TYPE . ANOTHREHOME ) { let name = "block_" + blockData . toString ( ) ; let prefab = this . _blockPrefab . getChildByName ( name ) ; if ( prefab ) { let node = cc . instantiate ( prefab ) ; let block = node . addComponent ( TankBattleBlock ) ; block . type = blockData ; if ( blockData == TankBettle . BLOCK_TYPE . HOME ) { this . _heart = node ; } this . node . addChild ( node , TankBettle . ZIndex . BLOCK ) ; x = ( j + 1 ) * prefebSize . width / 2 + j * prefebSize . width / 2 ; node . x = x ; node . y = y ; if ( blockData == TankBettle . BLOCK_TYPE . HOME ) { x = this . node . width / 2 ; node . x = x ; node . y -= prefebSize . height / 2 ; } } } } } } protected randomPropPosition ( ) { let tank = TankBettle . gameData . getPlayerPrefab ( true ) ; let xMin = tank . width / 2 ; let xMax = this . node . width - tank . width / 2 ; let yMin = - tank . height / 2 ; let yMax = - this . node . height + tank . height / 2 ; let x = cc . randomRange ( xMin , xMax ) ; let y = cc . randomRange ( yMin , yMax ) ; return cc . v3 ( x , y , 0 ) ; } private createProps ( ) { let type = cc . randomRangeInt ( TankBettle . PropsType . MIN , TankBettle . PropsType . MAX ) ; let prefab = TankBettle . gameData . getPropsPrefab ( type ) ; let node = cc . instantiate ( prefab ) ; let props = node . addComponent ( TankBattleProps ) ; props . type = type ; this . node . addChild ( node , TankBettle . ZIndex . PROPS ) ; node . position = this . randomPropPosition ( ) ; } public starCreateProps ( ) { if ( TankBettle . gameData . gameStatus == TankBettle . GAME_STATUS . GAME ) { let time = cc . randomRange ( TankBettle . PROPS_CREATE_INTERVAL . min , TankBettle . PROPS_CREATE_INTERVAL . max ) ; this . propsProductNode . stopAllActions ( ) ; cc . tween ( this . propsProductNode ) . delay ( time ) . call ( ( ) => { this . createProps ( ) ; this . starCreateProps ( ) ; } ) . start ( ) ; } } public addPlayer ( isOne ) { let playerNode = cc . instantiate ( TankBettle . gameData . getPlayerPrefab ( isOne ) ) ; if ( isOne ) { this . playerOne = playerNode . addComponent ( TankBettleTankPlayer ) ; this . playerOne . isOnePlayer = isOne ; playerNode . x = this . node . width / 2 - 2 * playerNode . width ; playerNode . y = - this . node . height + playerNode . height / 2 ; this . node . addChild ( playerNode , TankBettle . ZIndex . TANK ) ; this . playerOne . born ( ) ; } else { this . playerTwo = playerNode . addComponent ( TankBettleTankPlayer ) ; this . playerTwo . isOnePlayer = isOne ; playerNode . x = this . node . width / 2 + 2 * playerNode . width ; playerNode . y = - this . node . height + playerNode . height / 2 ; this . node . addChild ( playerNode , TankBettle . ZIndex . TANK ) ; this . playerTwo . born ( ) ; } } public removePlayer ( player ) { let isOne = player . isOnePlayer ; player . node . removeFromParent ( ) ; player . node . destroy ( ) ; if ( TankBettle . gameData . isSingle ) { this . playerOne = null ; if ( TankBettle . gameData . playerOneLive > 0 ) { this . addPlayer ( isOne ) ; TankBettle . gameData . reducePlayerLive ( true ) ; TankBettle . gameData . gameView . showGameInfo ( ) ; } else { TankBettle . gameData . gameMap . gameOver ( ) ; } } else { if ( isOne ) { this . playerOne = null ; if ( TankBettle . gameData . playerOneLive > 0 ) { this . addPlayer ( isOne ) ; } TankBettle . gameData . reducePlayerLive ( true ) ; } else { this . playerTwo = null ; if ( TankBettle . gameData . playerTwoLive > 0 ) { this . addPlayer ( isOne ) ; } TankBettle . gameData . reducePlayerLive ( false ) ; } TankBettle . gameData . gameView . showGameInfo ( ) ; if ( TankBettle . gameData . playerTwoLive < 0 && TankBettle . gameData . playerOneLive < 0 ) { TankBettle . gameData . gameMap . gameOver ( ) ; } } } public addBullet ( bullet ) { this . node . addChild ( bullet . node , TankBettle . ZIndex . BULLET ) ; } public onKeyDown ( ev ) { switch ( ev . keyCode ) { case cc . macro . KEY . a : { this . _handlePlayerMove ( this . playerTwo , TankBettle . Direction . LEFT ) ; } break ; case cc . macro . KEY . w : { this . _handlePlayerMove ( this . playerTwo , TankBettle . Direction . UP ) ; } break ; case cc . macro . KEY . s : { this . _handlePlayerMove ( this . playerTwo , TankBettle . Direction . DOWN ) ; } break ; case cc . macro . KEY . d : { this . _handlePlayerMove ( this . playerTwo , TankBettle . Direction . RIGHT ) ; } break ; case cc . macro . KEY . left : { this . _handlePlayerMove ( this . playerOne , TankBettle . Direction . LEFT ) ; } break ; case cc . macro . KEY . up : { this . _handlePlayerMove ( this . playerOne , TankBettle . Direction . UP ) ; } break ; case cc . macro . KEY . down : { this . _handlePlayerMove ( this . playerOne , TankBettle . Direction . DOWN ) ; } break ; case cc . macro . KEY . right : { this . _handlePlayerMove ( this . playerOne , TankBettle . Direction . RIGHT ) ; } break ; case cc . macro . KEY . enter : { this . _handlePlayerShoot ( this . playerOne ) ; } break ; case cc . macro . KEY . space : { if ( TankBettle . gameData . isSingle ) { this . _handlePlayerShoot ( this . playerOne ) ; } this . _handlePlayerShoot ( this . playerTwo ) ; } break ; case cc . macro . KEY . t : { this . addEnemy ( ) ; } break ; case cc . macro . KEY . r : { this . removeAllEnemy ( ) ; } break ; } } private _handlePlayerMove ( player , dir ) { if ( TankBettle . gameData . gameStatus == TankBettle . GAME_STATUS . GAME ) { if ( player ) { player . direction = dir ; player . move ( ) ; } } } private _handlePlayerShoot ( player ) { if ( TankBettle . gameData . gameStatus == TankBettle . GAME_STATUS . GAME ) { if ( player ) { player . shoot ( ) ; } } } public gameOver ( ) { cc . log ( "gameOver" ) ; TankBettle . gameData . gameStatus = TankBettle . GAME_STATUS . OVER ; Manager . uiManager . open ( { type : TankBattleGameOver , bundle : this . owner . bundle , zIndex : ViewZOrder . UI } ) ; if ( this . _heart ) { let aniNode = cc . instantiate ( TankBettle . gameData . animationPrefab ) ; this . _heart . addChild ( aniNode ) ; let animation = aniNode . getComponent ( cc . Animation ) ; let state = animation . play ( "king_boom" ) ; aniNode . x = 0 ; aniNode . y = 0 ; cc . tween ( aniNode ) . delay ( state . duration ) . call ( ( ) => { aniNode . removeFromParent ( ) ; aniNode . destroy ( ) ; let sprite = this . _heart . getComponent ( cc . Sprite ) ; sprite . loadImage ( { url : { urls : [ "texture/images" ] , key : "heart_0" } , view : this . owner , bundle : this . owner . bundle } ) ; } ) . removeSelf ( ) . start ( ) ; } } }