首先給主角做了三個基本動畫,站立動畫、行走動畫、攻擊動畫。
如上圖所示,給Player加上動畫組件,並把創建的3個動畫文件分別拖拽到動畫組件中。給Player添加腳本組件,並把PlayerControl.ts腳本拖拽到腳本組件中。
在PlayerControl.ts腳本中添加上圖所示代碼。
效果如下圖:
接下來就是監聽鍵盤上下左右是個方向鍵讓主角在地圖中行走,並且監聽X鍵讓玩家攻擊"空氣"。直接上源碼:
PlaySceneControl.ts
const {ccclass, property} = cc._decorator;
import PlayerControl from "./PlayerControl"
import {PlayerDirection} from "./PlayerControl"
@ccclass
export default class PlaySceneControl extends cc.Component {
private m_player: PlayerControl = null;
onLoad()
{
//監聽鍵盤事件
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this);
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this);
//獲取腳本實例
this.m_player = this.node.getChildByName("Player").getComponent("PlayerControl");
}
start () {
// init logic
}
//按下
private onKeyDown(event: cc.Event.EventKeyboard): void
{
this.dealKeyBoardEvent(event, true);
}
//釋放
private onKeyUp(event: cc.Event.EventKeyboard): void
{
this.dealKeyBoardEvent(event, false);
}
//鍵盤事件處理函數
private dealKeyBoardEvent(event: cc.Event.EventKeyboard, isPress: boolean): void
{
if(event.keyCode == cc.macro.KEY.up)
{
this.m_player.setPlayerMoveDirectionByKeyBoard(PlayerDirection.E_Dir_Up, isPress);
}
else if(event.keyCode == cc.macro.KEY.down)
{
this.m_player.setPlayerMoveDirectionByKeyBoard(PlayerDirection.E_Dir_Down, isPress);
}
else if(event.keyCode == cc.macro.KEY.left)
{
this.m_player.setPlayerMoveDirectionByKeyBoard(PlayerDirection.E_Dir_Left, isPress);
}
else if(event.keyCode == cc.macro.KEY.right)
{
this.m_player.setPlayerMoveDirectionByKeyBoard(PlayerDirection.E_Dir_Right, isPress);
}
else if(event.keyCode == cc.macro.KEY.x)
{
this.m_player.setPlayerAttackByKeyBoard(isPress);
}
}
}
PlayerControl.ts
const {ccclass, property} = cc._decorator;
enum PlayerState
{
E_State_Idle = 0,
E_State_Walk,
E_State_Attack,
}
export enum PlayerDirection
{
E_Dir_Up = 0,
E_Dir_Down,
E_Dir_Left,
E_Dir_Right
}
@ccclass
export default class PlayerControl extends cc.Component {
private m_animation: cc.Animation = null;
private m_camera: cc.Node = null;
private m_state: PlayerState = PlayerState.E_State_Idle;
//方向鍵是否被按下
private m_dirUpIsPress: boolean = false;
private m_dirDownIsPress: boolean = false;
private m_dirLeftIsPress: boolean = false;
private m_dirRightIsPress: boolean = false;
//攻擊鍵是否被按下(X鍵)
private m_attackKeyIsPress: boolean = false;
//速度
private m_speed: number = 5;
//主角所能行走的範圍
private m_minX: number = null;
private m_maxX: number = null;
private m_minY: number = null;
private m_maxY: number = null;
onLoad ()
{
//初始化數據
this.m_animation = this.getComponent(cc.Animation);
this.m_camera = cc.find("Canvas/Main Camera");
let map: cc.Node = cc.find("Canvas/TiledMap");
//計算範圍
let designSize = cc.view.getDesignResolutionSize();
this.m_minX = -designSize.width/2;
this.m_maxX = map.width*2 + this.m_minX;
this.m_minY = -designSize.height/2 + this.node.height;
this.m_maxY = map.getComponent(cc.TiledMap).getTileSize().height*2*3 + this.m_minY;
}
start ()
{
//設置初始狀態
this.setPlayerState(PlayerState.E_State_Idle);
}
update (dt: number)
{
if(this.m_state == PlayerState.E_State_Walk)
{
if(this.m_dirLeftIsPress) this.node.x -= this.m_speed;
if(this.m_dirRightIsPress) this.node.x += this.m_speed;
if(this.m_dirUpIsPress) this.node.y += this.m_speed/2;
if(this.m_dirDownIsPress) this.node.y -= this.m_speed/2;
//範圍檢測
if(this.node.x < this.m_minX)this.node.x = this.m_minX;
if(this.node.x > this.m_maxX)this.node.x = this.m_maxX;
if(this.node.y < this.m_minY)this.node.y = this.m_minY;
if(this.node.y > this.m_maxY)this.node.y = this.m_maxY;
//攝像機跟着人物移動
if(this.node.x > 0 && this.node.x < this.m_maxX - cc.view.getDesignResolutionSize().width/2)
{
this.m_camera.x = this.node.x;
}
}
}
//設置人物狀態
public setPlayerState(state: PlayerState): void
{
this.m_state = state;
if(this.m_state == PlayerState.E_State_Idle)
{
this.m_animation.play("PlayerIdleAnim");
}
else if(this.m_state == PlayerState.E_State_Walk)
{
this.m_animation.play("PlayerWalkAnim");
}
else if(this.m_state == PlayerState.E_State_Attack)
{
this.m_animation.play("PlayerAttackAnim");
}
}
//獲取人物狀態
public getPlayerState(): PlayerState
{
return this.m_state;
}
//按下方向鍵的處理
public setPlayerMoveDirectionByKeyBoard(direction: PlayerDirection, isPress: boolean): void
{
if(direction == PlayerDirection.E_Dir_Up)
{
this.m_dirUpIsPress = isPress;
}else if(direction == PlayerDirection.E_Dir_Down){
this.m_dirDownIsPress = isPress;
}else if(direction == PlayerDirection.E_Dir_Left){
this.m_dirLeftIsPress = isPress;
if(this.m_dirLeftIsPress)this.node.scaleX = -Math.abs(this.node.scaleX);
}else if(direction == PlayerDirection.E_Dir_Right){
this.m_dirRightIsPress = isPress;
if(this.m_dirRightIsPress)this.node.scaleX = Math.abs(this.node.scaleX);
}
//修改人物狀態
if(isPress)
{
if(this.m_state == PlayerState.E_State_Idle)
{
this.setPlayerState(PlayerState.E_State_Walk)
}
}else{
if(this.m_state != PlayerState.E_State_Attack)
{
if((!this.m_dirUpIsPress) && (!this.m_dirDownIsPress)
&& (!this.m_dirLeftIsPress) && (!this.m_dirRightIsPress))
{
this.setPlayerState(PlayerState.E_State_Idle);
}
}
}
}
//按下攻擊鍵的處理
public setPlayerAttackByKeyBoard(isPress: boolean): void
{
this.m_attackKeyIsPress = isPress;
if(isPress)
{
if(this.m_state != PlayerState.E_State_Attack)
{
this.setPlayerState(PlayerState.E_State_Attack);
}
}
}
//攻擊動畫回調
private attackAnimCallBack(eventName: string): void
{
if(eventName == "checkCrash")
{
//檢測是否打到敵人
cc.log("checkCrash");
}else if(eventName == "animEnd"){
//動畫結束
if(this.m_attackKeyIsPress)
{
//如果攻擊鍵還處於被按下的狀態,繼續播放攻擊動畫
this.m_animation.play("PlayerAttackAnim");
}else{
//如果方向鍵有被按下,進入到行走狀態,否則進入站立狀態
if(this.m_dirUpIsPress || this.m_dirDownIsPress
|| this.m_dirLeftIsPress || this.m_dirRightIsPress)
{
this.setPlayerState(PlayerState.E_State_Walk)
}else{
this.setPlayerState(PlayerState.E_State_Idle)
}
}
}
}
}
代碼有點多,註釋我都寫好了,理解起來應該不難。
下面看下效果圖: