簡単な2Dゲームを作ろう
2Dゲーム制作の練習シリーズです。
アンリアルエンジンで2Dゲーム制作方法をまとめていきます。
説明を省略したり、細かな数値設定などの説明をしない場合もありますので、ご参考程度で確認ください。
※作業環境:UEバージョン5.3.2 Windows11 VSCode
ゲームのリセットを実装
前回作成した障害物に衝突したときにゲームを初めからにしてみます。
ゲームモードクラスのコードを編集する
VSCodeエディタを開いて、ゲームモードクラスを編集していきます。
GM_MyGameMode.h
インクルードを追加します。
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
// 追加↓
#include "Engine/TimerHandle.h"
// ここまで↑
#include "GM_MyGameMode.generated.h"
「class PAPERGAME1_API AGM_MyGameMode : public AGameModeBase{}」内にコードを追加します。
UCLASS()
class PAPERGAME1_API AGM_MyGameMode : public AGameModeBase
{
GENERATED_BODY()
// 追加↓
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float LoseResetTime = 1.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float WinResetTime = 3.0f;
FTimerHandle ResetGameTimer;
void ResetLevel(bool IsWin);
void OnResetGameTimerTimeout();
// ここまで↑
};
GM_MyGameMode.cpp
インクルードを追加します。
#include "GM_MyGameMode.h"
// 追加↓
#include "Kismet/GameplayStatics.h"
// ここまで↑
ヘッダーファイルで追加した2つの関数定義を作成します。
・void ResetLevel(bool IsWin)
・void OnResetGameTimerTimeout()
// 関数定義
void AGM_MyGameMode::ResetLevel(bool IsWin)
{
// 追加↓
float ResetTime = LoseResetTime; // 負けた場合の時間をセットする
if (IsWin) // もし勝ったら
{
ResetTime = WinResetTime; // 勝利したときの時間をセットする
}
GetWorldTimerManager().SetTimer(ResetGameTimer, this, &AGM_MyGameMode::OnResetGameTimerTimeout, 1.0f, false, ResetTime); // セットした時間経過後に関数を呼び出す
// ここまで↑
}
// 関数定義
void AGM_MyGameMode::OnResetGameTimerTimeout()
{
// 追加↓
UGameplayStatics::OpenLevel(GetWorld(), FName("MainLevel")); // 指定したレベルを呼び出す
// ここまで↑
}
今回は勝ち負けを設定しませんが、勝ち負けを追加する場合のコードにしています。
呼び出すレベルは現在プレイしているステージです。
なので、レベルを呼び出すとゲームが初めからになります。
プレイしてみると、プレイヤーの位置はプレイ初めの位置に戻る感じになると思います。
障害物に接触したときの処理を編集する
次に障害物と接触したときに、先ほど作成した処理を呼び出すように編集します。
Obstacle.h
インクルードを追加します。
#include "PaperSpriteComponent.h"
// 追加↓
#include "GM_MyGameMode.h"
// ここまで↑
#include "Obstacle.generated.h"
「public:」内にコードを追加します。
UCLASS()
class PAPERGAME1_API AObstacle : public AActor
{
GENERATED_BODY()
public:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UCapsuleComponent* CapsuleComp;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
UPaperSpriteComponent* ObstaclSprite;
// 追加↓
AGM_MyGameMode* MyGameMode;
// ここまで↑
AObstacle();
Obstacle.cpp
インクルードを追加します。
#include "Obstacle.h"
// 追加↓
#include "Kismet/GameplayStatics.h"
// ここまで↑
#include "PlayerCharacter.h"
void AObstacle::BeginPlay(){}にコードを追加します。
void AObstacle::BeginPlay()
{
Super::BeginPlay();
CapsuleComp->OnComponentBeginOverlap.AddDynamic(this, &AObstacle::OverlapBegin);
// 追加↓
AGameModeBase* GameMode = UGameplayStatics::GetGameMode(GetWorld()); // ゲームモードを取得する
MyGameMode = Cast<AGM_MyGameMode>(GameMode); // キャストする
// ここまで↑
}
プレイヤーが衝突したらレベルを呼び出す処理を追加します。
void AObstacle::OverlapBegin(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool FromSweep, const FHitResult &SweepResult)
{
APlayerCharacter* Player = Cast<APlayerCharacter>(OtherActor);
if (Player)
{
// GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::White, TEXT("Overlapped with player!")); // デバック用
if (Player->CanMove)
{
Player->CanMove = false;
// 追加↓
MyGameMode->ResetLevel(false); // レベルを呼び出す
// ここまで↑
}
}
}
保存して、リフレッシュ&コンパイルをします。
正常に終了したら、実際にプレイして確かめます。
プレイヤーが障害物に触れると、少し時間をおいてからプレイヤーの位置が初めの位置に戻ります。
レベルを呼び出すと、データを読み込み直すのでゲームが初めからになります。
ゴールを設定したり、呼び出すレベルを変えたりすることでゲームっぽくなると思います。
ゲームのリセット実装完了
今回はここまでです。
次回は「BGMを実装する」です。
前後記事
他の記事を探す
他の記事も気になる方は、以下の記事の目次を確認ください。