今回は自機が敵キャラに当たった時のアクションを作成します。
具体的には、以下の処理を行ないます。
1. 自機に爆発するアニメーションを設定する。
2. 自機を画面上から削除する。
まず、自機が爆発するアニメーションを作成します。
アニメーションを作成する場合、それぞれのコマの画像を準備します。
CocosSharpGameSample.iOS プロジェクトに爆発する画像を追加します。
/Resources/Images/Character/Explosion/Explosion00.png ~ Explosion04.png
CocosSharpGameSample.Android プロジェクトに爆発する画像を追加します。
/Assets/Images/Character/Explosion/Explosion00.png ~ Explosion04.png
CocosSharpGameSample.Core プロジェクトに処理を作成します。
Layers/GameLayer.cs に処理を追加します。
まずは、アニメーションの状態を把握できるフィールドを追加します。
public class GameLayer : LayerBase
{
private ExtendedCCSprite player;
private bool enableCollisionDetection = true;
private CCActionState playerShotDownActionState;
次に爆発のアニメーションを作成します。
アニメーションは以下の要領で作成できます。
1. 各コマの画像の CCSprite を作成
2. CCSprite から CCSpriteFrame を作成
3. List としてアニメーションを構築
4. ループ回数、所要時間を設定し、アニメーションを適用させたい CCSprite に設定し実行
5. アニメーションの状態を返却
この手順をコードにすると以下の通りになります。
protected CCActionState PerformExplosionAnimation(CCSprite sprite)
{
var sprite00 = new CCSprite("/Resources/Images/Character/Explosion/Explosion00.png", null);
var sprite01 = new CCSprite("/Resources/Images/Character/Explosion/Explosion01.png", null);
var sprite02 = new CCSprite("/Resources/Images/Character/Explosion/Explosion02.png", null);
var sprite03 = new CCSprite("/Resources/Images/Character/Explosion/Explosion03.png", null);
var sprite04 = new CCSprite("/Resources/Images/Character/Explosion/Explosion04.png", null);
var frame00 = new CCSpriteFrame(sprite01.Texture, sprite01.TextureRectInPixels);
var frame01 = new CCSpriteFrame(sprite02.Texture, sprite02.TextureRectInPixels);
var frame02 = new CCSpriteFrame(sprite03.Texture, sprite03.TextureRectInPixels);
var frame03 = new CCSpriteFrame(sprite04.Texture, sprite04.TextureRectInPixels);
var frame04 = new CCSpriteFrame(sprite03.Texture, sprite03.TextureRectInPixels);
var frame05 = new CCSpriteFrame(sprite02.Texture, sprite02.TextureRectInPixels);
var frame06 = new CCSpriteFrame(sprite01.Texture, sprite01.TextureRectInPixels);
var frame07 = new CCSpriteFrame(sprite00.Texture, sprite00.TextureRectInPixels);
var frames = new List<CCSpriteFrame>();
frames.Add(frame00);
frames.Add(frame01);
frames.Add(frame02);
frames.Add(frame03);
frames.Add(frame03);
frames.Add(frame04);
frames.Add(frame05);
frames.Add(frame06);
frames.Add(frame07);
var animation = new CCAnimation(frames, 0.15f);
animation.Loops = 1;
var animate = new CCAnimate(animation);
var state = sprite.RunAction(animate);
return state;
}
衝突を検出した場合、爆発のアニメーションを実行するように、当たり判定検出のメソッドに下記の爆発のアニメーションを実行処理を追加します。
追加する処理
this.playerShotDownActionState = this.PerformExplosionAnimation(this.player);
追加場所は下から6行目です。
private void DetectCollisions()
{
if (this.player == null)
{
return;
}
if (this.EnableCollisionDetection == false)
{
return;
}
var rectPlayer = player.BoundingBox;
var rectTrimedPlayer = new CCRect(
rectPlayer.MidX - (GameSettings.PlayerWidth / 6),
rectPlayer.MidY - (GameSettings.PlayerHeight / 3),
GameSettings.PlayerWidth / 3,
GameSettings.PlayerHeight / 3);
var enemies = new List<CCNode>();
enemies.AddRange(this.GetChildrenByTag((int)NodeTag.Enemy));
if (enemies.Count > 0)
{
foreach (var node in enemies)
{
if (this.player.ScreenArea != ((ExtendedCCSprite)node).ScreenArea)
{
continue;
}
var rectEnemy = node.BoundingBox;
if (rectTrimedPlayer.IntersectsRect(rectEnemy) == true)
{
Debug.WriteLine("敵キャラに当たった!");
this.EnableCollisionDetection = false;
this.playerShotDownActionState = this.PerformExplosionAnimation(this.player);
break;
}
}
}
}
爆発のアニメーションが終了した後、自機を画面上から削除します。
private void RemovePlayer()
{
if (this.player == null)
{
return;
}
if (this.playerShotDownActionState == null)
{
return;
}
if (this.playerShotDownActionState.IsDone == true)
{
this.RemoveChild(this.player);
Debug.WriteLine("プレーヤー削除!");
this.player = null;
}
}
自機削除を0.5秒に1回行なうようスケジューラに登録します。
private void StartScheduling()
{
this.Schedule(t => this.UpdatePlayer(), 0.02f);
this.Schedule(t => this.RemoveOffScreenNodes(), 1.0f);
this.Schedule(t => this.DetectCollisions(), 0.1f);
this.Schedule(t => this.RemovePlayer(), 0.5f);
}
既存のメソッドで自機を削除することによる、null参照エラーが発生する部分に対策を入れます。
private void UpdatePlayer()
{
if (this.player == null)
{
return;
}
private void DetectCollisions()
{
if (this.player == null)
{
return;
}
以上をまとめると、CocosSharpGameSample.Core プロジェクトの Layers/GameLayer.cs は以下の通りになります。
using System.Collections.Generic;
using System.Diagnostics;
using CocosSharp;
namespace CocosSharpGameSample.Core
{
public class GameLayer : LayerBase
{
private ExtendedCCSprite player;
private bool enableCollisionDetection = true;
private CCActionState playerShotDownActionState;
public bool EnableCollisionDetection
{
get { return this.enableCollisionDetection; }
set { this.enableCollisionDetection = value; }
}
public GameLayer()
: base()
{
var listener = new CCEventListenerTouchOneByOne();
listener.OnTouchBegan = this.CCEventListener_TouchBegan;
this.AddEventListener(listener, this);
}
protected bool CCEventListener_TouchBegan(CCTouch touch, CCEvent touchEvent)
{
Debug.WriteLine(this.ChildrenCount);
var touchedLocation = touch.Location;
if (touchedLocation.Y > GameSettings.ScreenHeight * 3 / 4)
{
var addingEnemy = new ExtendedCCSprite("/Resources/Images/Character/Enemy/Enemy001.png", null);
addingEnemy.Position = touchedLocation;
addingEnemy.Tag = (int)NodeTag.Enemy;
this.ApplyGoStraightFromTopDownAction(addingEnemy);
this.AddChild(addingEnemy);
return true;
}
return false;
}
public void ApplyGoStraightFromTopDownAction(CCNode enemy)
{
var destinationPoint = new CCPoint(enemy.PositionX, -100);
var action = new CCMoveTo(8.0f, destinationPoint);
enemy.RunAction(action);
}
public void RemoveOffScreenNodes()
{
foreach (var node in this.Children)
{
if (node.Position.Y < 0)
{
this.RemoveChild(node);
}
}
}
protected override void AddedToScene()
{
base.AddedToScene();
var gameBackground = new CCSprite("/Resources/Images/Background/GameBackground.png", null);
gameBackground.Position = new CCPoint(this.ContentSize.Center.X, this.ContentSize.Center.Y);
AddChild(gameBackground);
this.AddPlayer();
this.StartScheduling();
}
private void StartScheduling()
{
this.Schedule(t => this.UpdatePlayer(), 0.02f);
this.Schedule(t => this.RemoveOffScreenNodes(), 1.0f);
this.Schedule(t => this.DetectCollisions(), 0.1f);
this.Schedule(t => this.RemovePlayer(), 0.5f);
}
private void AddPlayer()
{
this.player = new ExtendedCCSprite("/Resources/Images/Character/Player/Player.png", null);
this.player.Position = new CCPoint(this.ContentSize.Center.X, this.ContentSize.Center.Y);
this.AddChild(this.player);
}
private void UpdatePlayer()
{
if (this.player == null)
{
return;
}
this.player.PositionX = this.player.PositionX;
this.player.PositionY = this.player.PositionY;
if (this.player.PositionX < 0 + GameSettings.PlayerWidth)
{
this.player.PositionX = 0 + GameSettings.PlayerWidth;
}
if (this.player.PositionX > GameSettings.ScreenWidth - GameSettings.PlayerWidth)
{
this.player.PositionX = GameSettings.ScreenWidth - GameSettings.PlayerWidth;
}
if (this.player.PositionY < 0 + GameSettings.PlayerHeight)
{
this.player.PositionY = 0 + GameSettings.PlayerHeight;
}
if (this.player.PositionY > GameSettings.ScreenHeight - GameSettings.PlayerHeight)
{
this.player.PositionY = GameSettings.ScreenHeight - GameSettings.PlayerHeight;
}
}
private void DetectCollisions()
{
if (this.player == null)
{
return;
}
if (this.EnableCollisionDetection == false)
{
return;
}
var rectPlayer = player.BoundingBox;
var rectTrimedPlayer = new CCRect(
rectPlayer.MidX - (GameSettings.PlayerWidth / 6),
rectPlayer.MidY - (GameSettings.PlayerHeight / 3),
GameSettings.PlayerWidth / 3,
GameSettings.PlayerHeight / 3);
var enemies = new List<CCNode>();
enemies.AddRange(this.GetChildrenByTag((int)NodeTag.Enemy));
if (enemies.Count > 0)
{
foreach (var node in enemies)
{
if (this.player.ScreenArea != ((ExtendedCCSprite)node).ScreenArea)
{
continue;
}
var rectEnemy = node.BoundingBox;
if (rectTrimedPlayer.IntersectsRect(rectEnemy) == true)
{
Debug.WriteLine("敵キャラに当たった!");
this.EnableCollisionDetection = false;
this.playerShotDownActionState = this.PerformExplosionAnimation(this.player);
break;
}
}
}
}
private void RemovePlayer()
{
if (this.player == null)
{
return;
}
if (this.playerShotDownActionState == null)
{
return;
}
if (this.playerShotDownActionState.IsDone == true)
{
this.RemoveChild(this.player);
Debug.WriteLine("プレーヤー削除!");
this.player = null;
}
}
protected CCActionState PerformExplosionAnimation(CCSprite sprite)
{
var sprite00 = new CCSprite("/Resources/Images/Character/Explosion/Explosion00.png", null);
var sprite01 = new CCSprite("/Resources/Images/Character/Explosion/Explosion01.png", null);
var sprite02 = new CCSprite("/Resources/Images/Character/Explosion/Explosion02.png", null);
var sprite03 = new CCSprite("/Resources/Images/Character/Explosion/Explosion03.png", null);
var sprite04 = new CCSprite("/Resources/Images/Character/Explosion/Explosion04.png", null);
var frame00 = new CCSpriteFrame(sprite01.Texture, sprite01.TextureRectInPixels);
var frame01 = new CCSpriteFrame(sprite02.Texture, sprite02.TextureRectInPixels);
var frame02 = new CCSpriteFrame(sprite03.Texture, sprite03.TextureRectInPixels);
var frame03 = new CCSpriteFrame(sprite04.Texture, sprite04.TextureRectInPixels);
var frame04 = new CCSpriteFrame(sprite03.Texture, sprite03.TextureRectInPixels);
var frame05 = new CCSpriteFrame(sprite02.Texture, sprite02.TextureRectInPixels);
var frame06 = new CCSpriteFrame(sprite01.Texture, sprite01.TextureRectInPixels);
var frame07 = new CCSpriteFrame(sprite00.Texture, sprite00.TextureRectInPixels);
var frames = new List<CCSpriteFrame>();
frames.Add(frame00);
frames.Add(frame01);
frames.Add(frame02);
frames.Add(frame03);
frames.Add(frame03);
frames.Add(frame04);
frames.Add(frame05);
frames.Add(frame06);
frames.Add(frame07);
var animation = new CCAnimation(frames, 0.15f);
animation.Loops = 1;
var animate = new CCAnimate(animation);
var state = sprite.RunAction(animate);
return state;
}
}
}
以上で、自機が敵キャラにぶつかった時、爆発する動きが完成しました。
今回は、ここまでです。
何かご質問などございましたらコメント頂ければご回答させていただきますのでお気軽にどうぞ!
また、間違い等ございましたら、ご指摘頂ければ幸いです。