はじめに
この記事は #2各種オブジェクトについて です。
#0:https://qiita.com/komugikoShimizu/items/9e9a18232d2d5bf7db6a
#1:https://qiita.com/komugikoShimizu/items/5e66093a0a22e57e1e8c
#3:https://qiita.com/komugikoShimizu/items/6f0cc002f9f7fbd30760
今回の実装について
シューティングを作る際、必要なオブジェクトはなにか と考えたところ
- プレイヤー
- エネミー
- 弾
の3種類であると考えました。
また、これらのオブジェクトはすべて当たり判定を必要とするものであり
ある程度統一された機能を持ったものを作成するのを完成としました。
オブジェクトの基本機能の実装
今回制作するオブジェクトに当たるものはある程度すべてが持つ機能があります。
- 座標................................:描画や移動などに使用する
- 画像サイズ..................:描画後の中心座標を割り出すのに使用する
- 当たり判定用の半径:円形の当たり判定をする行うために必要
- 接触時に行う処理.....:当たって時に何をするか をできるものが必要
といったような機能があります。
これを実装るために基底クラスを作成します。
class CollisionObject
{
public :
virtual void CollisionAction();
// 各種要素のGet用関数
protected :
Vector2 position;
Vector2 spriteSize;
int radius;
}
今回使用するオブジェクトにはこれを継承していきます。
プレイヤー / エネミー
これらのオブジェクトは正直Unityでやってきた実装が多いのであまり話すことがないです...
しいて言えば体力を減少させる点でしょうか
void PlayerObject::CollisionAction()
{
if (bulletHitable)
{
bulletHitable = false;
hitPoint--;
}
}
このように OnCollisionEnter のようなものに変わり、CollisionAction が入っています。
これらのオブジェクトはアニメーションについて話したいので#3がメインになっていきます。
弾
こっちがメインのお話です。
弾はBulletクラスがCollisionObjectを継承していますが、それをさらに継承しています。
弾には2種類あり
- NormalBullet
- ChasableBullet
の2つがあります。
これらを「当たり判定を持つオブジェクト」であり「弾」であるためにBulletクラスを継承しました。
NormalBulletクラスは、最初に決めた発射角度で進み続ける弾です。
#define NORMAL_BULLET_SPEED 3
bool NormalBullet::BulletUpdate()
{
// 移動座標を作成する
float rx = NORMAL_BULLET_SPPED * cos(angle) + position.x;
float ry = NORMAL_BULLET_SPPED * sin(angle) + position.y;
position = Vector2(rx, ry); // 移動座標に座標を移動する
}
ChasableBulletクラスは、対象を追従し続けます。
bool ChasableBullet::BulletUpdate()
{
Vector2 distance = *targetPosPtr - position; // 対象座標との距離を作成
float hypotenuse = sqrt(pow(distance.x, 2) + pow(distance.y, 2)); // 斜辺を計算
// 移動ベクトルを作成
float mx = (distance.x / hypotenuse) * ChasableBulletSpped;
float my = (distance.y / hypotenuse) * ChasableBulletSpped;
position += Vector2(mx, my); // 座標に移動ベクトルを加算
animationController.AnimaitonUpdate(GetPos(), false); // アニメーション更新
if (targetTime < GetNowCount()) // 目標時間を超えたら
{
active = false; // 無効化する
type = CollisionType::TYPE_NONE; // 接触タイプを未設定にする
}
}
また、これらの弾を管理するため、BulletManagerクラスが存在します。
このクラスで管理している弾すべてを動かしています。
void BulletManager::BulletUpdate()
{
for (int i = 0; i < BULLET_MAXINSTANCE_COUNT; i++) // インスタンス上限まで実行
{
if (instanceBullets[i] != nullptr) // その配列要素番号に値があれば
{
if (!instanceBullets[i]->BulletUpdate()) // 弾更新処理を実行
{
BulletUnregister(i); // 有効でなければ弾設定を解除
}
}
}
}
このように弾すべてに更新命令を出したかったため、Bulletクラスが継承されています。
プレイヤーやエネミーからは 弾がどんなものか を知らなくても扱えるようになっています。
class BulletManager
{
public :
/// <summary>
/// 通常弾作成関数
/// </summary>
/// <param name="angle">発射角度</param>
/// <param name="createPos">生成座標</param>
/// <param name="collisionPos">接触タイプ</param>
/// <returns>生成した弾のインデックス</returns>
int NormalBulletCreate(int angle, Vector2 createPos, CollisionType collisionPos);
/// <summary>
/// 追従弾作成関数
/// </summary>
/// <param name="createPos">生成座標</param>
/// <param name="collisionPos">接触タイプ</param>
/// <returns>生成した弾のインデックス</returns>
int ChasableBulletCreate(Vector2 createPos,CollisionType collisionPos);
}
このように関数実行のみで、使用したい弾が登録されて、それをBulletManagerが実行してくれます。
#3につづく...