【UE开发】2D飞机大战Demo

1.Demo介绍

        1.游戏:玩家以第三人称俯视角控制战机与随机生成的敌机进行射击战斗,击落战机玩家获得分数,战机触碰敌机触发爆炸且游戏结束。

        2.附件:

                1.工程源码:GitHub - CNEarly/SpaceShipBattleDemo: 使用虚幻引擎C++开发Roguelike类型2D飞机大战Demo

                2.演示视频:SpaceShipBattleDemo演示_单机游戏热门视频

        3.内容:

                1.移动:使用WSAD键控制战机上下左右移动

                2.朝向:使用鼠标控制战机朝向

                3.射击:使用鼠标左键控制战机开火

                4.阵亡:玩家触碰敌机触发爆炸

                5.生成:敌人在地图中随机生成

2.地图实现

        1.材料:①大气雾②音效③阻挡体积④生成敌人蓝图⑤静态网格体⑥光源⑦玩家出生⑧天空球⑨天光⑩球体反射捕获

        2.搭建:

                

3.战机实现

        1.C++头文件:

//预处理
#pragma once//保证头文件只被编译一次
#include "CoreMinimal.h"//包含一套来自UE4核心编程环境的普遍存在类型
#include "GameFramework/Pawn.h"//在新建类的时候选择了以Pawn作为父类(所以这里保存的就是Pawn源代码的头文件)
#include "SpaceShip.generated.h"//与反射机制有关(必须放在所有头文件的最下方)
//前向声明
class USphereComponent;//球体碰撞
class UCameraComponent;//摄像机
class USpringArmComponent;//弹簧臂
class ABullet;//子弹类
class USoundCue;//音效
//战机类
UCLASS()
class SPACESHIPBATTLE_API ASpaceShip : public APawn
{
	GENERATED_BODY()
public:
	//构造函数声明
	ASpaceShip();
protected:
	//球体碰撞组件变量
	UPROPERTY(VisibleAnywhere,Category="Component")
	USphereComponent* CollisionComp;
	//网格体组件变量
	UPROPERTY(VisibleAnywhere, Category = "Component")
	UStaticMeshComponent* ShipSM;
	//摄像机组件变量
	UPROPERTY(VisibleAnywhere, Category = "Component")
	UCameraComponent* CameraComp;
	//弹簧臂组件变量
	UPROPERTY(VisibleAnywhere, Category = "Component")
	USpringArmComponent* SpringArmComp;
	//玩家控制器类变量
	APlayerController* PC;
	//子弹类型变量
	UPROPERTY(EditAnywhere,Category="Fire")
	TSubclassOf<ABullet> Bullet;
	//子弹发射位置组件变量
	UPROPERTY(VisibleAnywhere, Category = "Component")
	USceneComponent* SpawnPoint;
	//战机速度变量
	UPROPERTY(EditAnywhere,Category="Move")
	float Speed;
	//射击间隔时间管理器变量
	FTimerHandle TimerHandle_BetweenShot;
	//游戏开始函数声明
	virtual void BeginPlay() override;
	//射击间隔变量
	UPROPERTY(EditAnywhere, Category = "Fire")
	float TimeBetweenShot;
	//重启游戏时间管理器变量
	FTimerHandle TimerHandle_Restart;
	//阵亡音效变量
	UPROPERTY(EditAnywhere,Category="Sound")
	USoundCue* GameOverCue;
	//射击音效变量
	UPROPERTY(EditAnywhere, Category = "Sound")
	USoundCue* ShootCue;
	//推进粒子组件变量
	UPROPERTY(VisibleAnywhere,Category="Component")
	UParticleSystemComponent* ThrusterParticleComp;
	//爆炸粒子变量
	UPROPERTY(EditAnywhere,Category="Particle")
	UParticleSystem* ExplosionParticle;
	//阵亡变量(布尔)
	bool bDead;
	//上下移动变量(布尔)
	bool bUpMove;
	//左右移动变量(布尔)
	bool bRightMove;
	//朝向光标函数实现
	void LookAtCursor();
	//上下移动函数实现
	void MoveUp(float Value);
	//左右移动函数实现
	void MoveRight(float Value);
	//移动函数实现
	void Move();
	//开火函数声明
	void Fire();
	//开始开火函数声明
	void StartFire();
	//停止开火函数声明
	void EndFire();
	//重启关卡函数声明
	void RestartLevel();
	//阵亡函数声明
	void OnDeath();
public:	
	//游戏每帧函数声明
	virtual void Tick(float DeltaTime) override;
	//玩家输入函数声明
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	//碰撞函数声明
	virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;
	//获取阵亡状态函数
	FORCEINLINE bool GetBDead() 
	{
		return bDead;//返回阵亡变量
	}
};

        2.C++源文件:

//预处理
#include "Public/SpaceShip.h"//战机类
#include "Components/StaticMeshComponent.h"//网格体组件
#include "Components/SphereComponent.h"//球体碰撞组件
#include "Camera/CameraComponent.h"//摄像机组件
#include "GameFramework/PlayerController.h"//玩家控制器
#include "Kismet/KismetMathLibrary.h"//数学库
#include "GameFramework/SpringArmComponent.h"//弹簧臂组件
#include "Public/Misc/App.h"//引擎处理
#include "Engine/World.h"//世界
#include "Public/Bullet.h"//子弹类头文件
#include "Public/Enemy.h"//敌人类头文件
#include "Kismet/GameplayStatics.h"//游戏状态
#include "TimerManager.h"//时间管理器
#include "Sound/SoundCue.h"//音效
#include "Particles/ParticleSystemComponent.h"//粒子特效组件
#include "Particles/ParticleSystem.h"//粒子特效
//构造函数实现
ASpaceShip::ASpaceShip()
{
	PrimaryActorTick.bCanEverTick = true;//开启tick函数

	CollisionComp = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionComp"));//实例化碰撞组件
	RootComponent = CollisionComp;//碰撞组件设置为根组件

	ShipSM = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ShipSM"));//实例化网格体组件
	ShipSM->SetupAttachment(RootComponent);//网格体组件绑定根组件

	SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp"));//实例化弹簧臂组件
	SpringArmComp->SetupAttachment(RootComponent);//弹簧臂组件绑定根组件

	CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComp"));//实例化摄像机组件
	CameraComp->SetupAttachment(SpringArmComp);//摄像机组件绑定弹簧臂组件

	SpawnPoint = CreateDefaultSubobject<USceneComponent>(TEXT("SpawnPoint"));//实例化发射位置场景组件
	SpawnPoint->SetupAttachment(ShipSM);//发射位置场景组件绑定网格体组件

	ThrusterParticleComp = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("TrusterParticle"));//实例化推进器粒子组件
	ThrusterParticleComp->SetupAttachment(RootComponent);//推进器粒子组件绑定根组件

	Speed = 2500.0f;//设置速度
	TimeBetweenShot = 0.2f;//设置发射间隔
	bDead = false;//设置阵亡
}
//游戏开始函数实现
void ASpaceShip::BeginPlay()
{
	Super::BeginPlay();
	
	PC =Cast<APlayerController>(GetController());//用变量接收获取到的玩家控制器
	PC->bShowMouseCursor = true;//控制开启显示光标
}
//朝向光标函数实现
void ASpaceShip::LookAtCursor()
{
	FVector MouseLocation, MouseDirection;//光标位置和方向变量
	PC->DeprojectMousePositionToWorld(MouseLocation,MouseDirection);//将光标位置投影到世界
	FVector TargetLocation = FVector(MouseLocation.X, MouseLocation.Y, GetActorLocation().Z);//将光标位置投影到与战机共面
	FRotator Rotator= UKismetMathLibrary::FindLookAtRotation(GetActorLocation(),TargetLocation);//计算旋转值
	SetActorRotation(Rotator);//设置战机旋转
}
//上下移动函数实现
void ASpaceShip::MoveUp(float Value)
{
	if (Value != 0)//上下移动传参非0 
	{
		bUpMove = true;//上下移动为真
	}
	else//上下移动传参为0 
	{
		bUpMove = false;//上下移动为假
	}
	AddMovementInput(FVector::ForwardVector,Value);//添加移动输入
}
//左右移动函数实现
void ASpaceShip::MoveRight(float Value)
{
	if (Value != 0)//左右移动传参非0 
	{
		bRightMove = true;//左右移动为真
	}
	else//左右移动传参为0 
	{
		bRightMove = false;//左右移动为假
	}
	AddMovementInput(FVector::RightVector,Value);//添加移动输入
}
//移动函数实现
void ASpaceShip::Move()
{
	AddActorWorldOffset(ConsumeMovementInputVector()*Speed*FApp::GetDeltaTime(), true);//获取一帧内移动的向量,在位置上增加增量
	//FApp::GetDeltaTime();//获取一帧的时间
}
//开火函数实现
void ASpaceShip::Fire()
{
	if (Bullet&&!bDead)//子弹为真且为阵亡
	{
		FActorSpawnParameters SpawnParams;//发射范围参数变量
		GetWorld()->SpawnActor<ABullet>(Bullet, SpawnPoint->GetComponentLocation(), SpawnPoint->GetComponentRotation(), SpawnParams);//发射子弹类
		if (ShootCue)//射击音效为真
		{
			UGameplayStatics::PlaySoundAtLocation(this, ShootCue, GetActorLocation());//播放射击音效
		}
	}
}
//开始开火函数实现
void ASpaceShip::StartFire()
{
	GetWorldTimerManager().SetTimer(TimerHandle_BetweenShot, this, &ASpaceShip::Fire, TimeBetweenShot, true, 0.0f);//开火间隔定时器开启
}
//停止开火函数实现
void ASpaceShip::EndFire()
{
	GetWorldTimerManager().ClearTimer(TimerHandle_BetweenShot);//开火间隔定时器停止
}
//重启关卡函数实现
void ASpaceShip::RestartLevel()
{
	UGameplayStatics::OpenLevel(this,"MainMap");//重新打开当前关卡
}
//阵亡函数实现
void ASpaceShip::OnDeath()
{
	bDead = true;//阵亡设置为真
	CollisionComp->SetVisibility(false,true);
	if (GameOverCue)//战败音效为真
	{
		UGameplayStatics::PlaySoundAtLocation(this, GameOverCue, GetActorLocation());//播放战败音效
	}
	if (ExplosionParticle)//爆炸特效为真
	{
		UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplosionParticle, GetActorLocation(), FRotator::ZeroRotator, true);//播放爆炸特效
		GetWorldTimerManager().SetTimer(TimerHandle_Restart, this, &ASpaceShip::RestartLevel, 2.0f, false);//重启游戏定时器开启
	}
}
//游戏每帧函数实现
void ASpaceShip::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	if (!bDead)//未阵亡
	{
		if (bUpMove || bRightMove)//上下移动或者左右移动
		{
			ThrusterParticleComp->Activate();//推机器粒子特效开启
		}
		else//未上下移动或者左右移动
		{
			ThrusterParticleComp->Deactivate();//推机器粒子特效结束
		}

		LookAtCursor();//调用朝向光标函数
		Move();//调用移动函数
	}
	else //阵亡
	{
		ThrusterParticleComp->Deactivate();//推机器粒子特效结束
	}
}
//玩家输入函数实现
void ASpaceShip::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAxis("MoveUp",this,&ASpaceShip::MoveUp);//轴映射上下移动
	PlayerInputComponent->BindAxis("MoveRight", this, &ASpaceShip::MoveRight);//轴映射左右移动

	PlayerInputComponent->BindAction("Fire",IE_Pressed,this,&ASpaceShip::StartFire);//操作映射按键开火
	PlayerInputComponent->BindAction("Fire", IE_Released, this, &ASpaceShip::EndFire);//操作映射松键停火
}
//碰撞函数实现
void ASpaceShip::NotifyActorBeginOverlap(AActor * OtherActor)
{
	Super::NotifyActorBeginOverlap(OtherActor);
	AEnemy* Enemy = Cast<AEnemy>(OtherActor);//碰撞检测敌人类型
	if (Enemy)//敌人为真 
	{
		Enemy->Destroy();//敌人销毁
		OnDeath();//战机调用阵亡函数
		//Destroy();战机销毁
	}
}

        3.虚幻蓝图类:①创建蓝图类继承战机C++类

                                 ②蓝图类组件添加素材

                                 ③蓝图类事件图表调用分数UI到窗口

        4.类设置:①类子弹细节添加子弹类

                          ②类音效细节添加音效

                          ③类粒子细节添加粒子

        5.总结:战机类作为玩家控制的对象需要根据玩家的输入来触发对应的函数,当战机在游戏中触发不同事件时会调用不同的函数

4.子弹实现

        1.C++头文件:

//预处理
#pragma once//编译一次
#include "CoreMinimal.h"//核心编程环境
#include "GameFramework/Actor.h"//Actor源代码
#include "Bullet.generated.h"//反射机制
//前向声明
class UProjectileMovementComponent;//发射物移动
//子弹类
UCLASS()
class SPACESHIPBATTLE_API ABullet : public AActor
{
	GENERATED_BODY()	
public:	
	//构造函数声明
	ABullet();
protected:
	//游戏开始函数声明
	virtual void BeginPlay() override;
	//根组件变量
	UPROPERTY(VisibleAnywhere, Category = "Component")
	USceneComponent* RootComp;
	//网格体组件变量
	UPROPERTY(VisibleAnywhere,Category="Component")
	UStaticMeshComponent* BulletSM;
	//发射物移动组件变量
	UPROPERTY(VisibleAnywhere, Category = "Component")
	UProjectileMovementComponent* ProjectileMovementComp;
public:	
	//游戏每帧函数声明
	virtual void Tick(float DeltaTime) override;
	//碰撞函数声明
	virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;
};

        2.C++源文件:

//预处理
#include "Public/Bullet.h"//子弹类
#include "Components/StaticMeshComponent.h"//网格体
#include "Components/SceneComponent.h"//场景
#include "GameFramework/ProjectileMovementComponent.h"//发射物移动
#include "Public/Enemy.h"//敌人类
#include "Engine/BlockingVolume.h"//阻挡体积
#include "Kismet/GameplayStatics.h"//游戏状态
//构造函数实现
ABullet::ABullet()
{
	PrimaryActorTick.bCanEverTick = true;//开启tick函数

	RootComp = CreateDefaultSubobject<USceneComponent>(TEXT("RootComp"));//实例化根组件
	RootComponent = RootComp;//设置根组件
	BulletSM = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BulletSM"));//实例化网格体组件
	BulletSM->SetupAttachment(RootComponent);//绑定根组件
	ProjectileMovementComp = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComp"));//实例化发射物移动组件
}
//游戏开始函数实现
void ABullet::BeginPlay()
{
	Super::BeginPlay();
}
//游戏每帧函数实现
void ABullet::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}
//碰撞函数实现
void ABullet::NotifyActorBeginOverlap(AActor * OtherActor)
{
	Super::NotifyActorBeginOverlap(OtherActor);

	AEnemy* Enemy= Cast<AEnemy>(OtherActor);//碰撞检测敌人类型
	if (Enemy)//敌人为真 
	{
		Enemy->OnDeath();//敌人调用阵亡函数
		Destroy();//子弹销毁
	}
	else if (Cast<ABlockingVolume>(OtherActor))//碰撞检测其他类型
	{
		Destroy();//子弹销毁
	}

}

        3.虚幻蓝图类:①创建蓝图类继承子弹C++类

                                 ②蓝图类组件添加素材

        4.总结:子弹类作为战机拥有移动能力的生成物发射,需要检测碰撞的结果来触发对应的函数

5.敌机实现

        1.C++头文件:

//预处理
#pragma once//保证头文件只被编译一次
#include "CoreMinimal.h"//包含一套来自UE4核心编程环境的普遍存在类型
#include "GameFramework/Pawn.h"//在新建类的时候选择了以Pawn作为父类(所以这里保存的就是Pawn源代码的头文件)
#include "Enemy.generated.h"//与反射机制有关(必须放在所有头文件的最下方)
//前向声明
class USphereComponent;//球体碰撞
class ASpaceShip;//战机类
class AShipGameMode;//战机游戏模式类
class AEnemySpawner;//生成类
//敌人类
UCLASS()
class SPACESHIPBATTLE_API AEnemy : public APawn
{
	GENERATED_BODY()
public:
	//构造函数声明
	AEnemy();
protected:
	//球体碰撞组件变量
	UPROPERTY(VisibleAnywhere,Category="Component")
	USphereComponent* CollisionComp;
	//网格体组件变量
	UPROPERTY(VisibleAnywhere,BlueprintReadOnly, Category = "Component")
	UStaticMeshComponent* ShipSM;
	//游戏开始函数声明
	virtual void BeginPlay() override;
	//移动至战机函数声明
	void MoveTowardsPlayer(float DeltaTime);
	//战机类变量
	ASpaceShip* SpaceShip;
	//速度变量
	float Speed = 300.0f;
	//战机游戏模式类变量
	AShipGameMode* MyGameMode;
	//生成类变量
	AEnemySpawner* EnemySpawner;
	//爆炸粒子变量
	UPROPERTY(EditAnywhere, Category = "Particle")
	UParticleSystem* ExplosionParticle;
	//设置颜色函数声明
	UFUNCTION(BlueprintImplementableEvent)
	void SetColor();
	//生成爆炸函数声明
	UFUNCTION(BlueprintImplementableEvent)
	void SpawnExplosion();
public:	
	//游戏每帧函数声明
	virtual void Tick(float DeltaTime) override;
	//玩家输入函数声明
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	//阵亡函数声明
	void OnDeath();
};

        2.C++源文件:

//预处理
#include "Public/Enemy.h"//敌人类
#include "Components/SphereComponent.h"//球体碰撞
#include "Components/StaticMeshComponent.h"//网格体
#include "Kismet/GameplayStatics.h"//游戏状态
#include "Public/SpaceShip.h"//战机类
#include "Kismet/KismetMathLibrary.h"//数学库
#include "Public/ShipGameMode.h"//战机游戏模式类
#include "Public/EnemySpawner.h"//生成类
#include "Particles/ParticleSystem.h"//粒子特效
//构造函数实现
AEnemy::AEnemy()
{
	PrimaryActorTick.bCanEverTick = true;//开启tick函数

	CollisionComp = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionComp"));//实例化碰撞组件
	RootComponent = CollisionComp;//设置根组件

	ShipSM = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ShipSM"));//实例化网格体组件
	ShipSM->SetupAttachment(RootComponent);//绑定根组件
}
//游戏开始函数实现
void AEnemy::BeginPlay()
{
	Super::BeginPlay();

	SpaceShip= Cast<ASpaceShip>(UGameplayStatics::GetPlayerPawn(this,0));//战机类型检测
	SetColor();//设置敌人颜色
	MyGameMode= Cast<AShipGameMode>(UGameplayStatics::GetGameMode(this));//游戏模式类型检测
	TArray<AActor*> EnemySpawnerArray;//敌人生成数组
	UGameplayStatics::GetAllActorsOfClass(this, AEnemySpawner::StaticClass(), EnemySpawnerArray);//获取敌人类的所有对象
	EnemySpawner = Cast<AEnemySpawner>(EnemySpawnerArray[0]);//生成敌人类型检测
}
//移动至战机函数实现
void AEnemy::MoveTowardsPlayer(float DeltaTime)
{
	FVector Direction = (SpaceShip->GetActorLocation() - GetActorLocation()).GetSafeNormal();//获取玩家方向
	AddActorWorldOffset(Direction*Speed*DeltaTime, true);//设置敌人的位移
	SetActorRotation(UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), SpaceShip->GetActorLocation()));//设置敌人的旋转
}
//阵亡函数实现
void AEnemy::OnDeath()
{
	MyGameMode->IncreaseScore();//游戏模式类调用分数增加函数
	EnemySpawner->DecreaseEnemyCount();//敌人生成类调用减少敌人计数函数
	SpawnExplosion();//生成爆炸
	Destroy();//销毁敌人
}
//游戏每帧函数实现
void AEnemy::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (SpaceShip->GetBDead() == false)//战机未阵亡
	{
		MoveTowardsPlayer(DeltaTime);//移动至战机位置
	}
}
//玩家输入函数实现
void AEnemy::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
}

        3.虚幻蓝图类:①创建蓝图类继承敌机C++类

                                 ②蓝图类组件添加素材

                                 ③蓝图类事件图表调用设置颜色和生成爆炸函数

        4.总结:与战机类的基本设置相同,只是作为npc需要使用设置好的函数来控制敌人的行为

6.生成实现

        1.C++头文件:

//预处理
#pragma once//编译一次
#include "CoreMinimal.h"//核心编程环境
#include "GameFramework/Actor.h"//Actor源代码
#include "EnemySpawner.generated.h"//反射机制
//前向声明
class AEnemy;//敌人类
class UBoxComponent;//盒体碰撞
class ASpaceShip;//战机类
//生成类
UCLASS()
class SPACESHIPBATTLE_API AEnemySpawner : public AActor
{
	GENERATED_BODY()
public:	
	//构造函数声明
	AEnemySpawner();
protected:
	//游戏开始函数声明
	virtual void BeginPlay() override;
	//敌人类型变量
	UPROPERTY(EditAnywhere,Category="Enemy")
	TSubclassOf<AEnemy> Enemy;
	//盒体碰撞组件变量
	UPROPERTY(VisibleAnywhere,Category="Component")
	UBoxComponent* SpawnArea;
	//获取生成位置函数声明
	FVector GetGenerateLocation();
	//与玩家最小距离变量
	float MinimumDistanceToPlayer = 1200.0f;
	//战机类
	ASpaceShip* SpaceShip;
	//生成敌人函数声明
	void SpawnEnemy();
	//生成敌人时间管理器变量
	FTimerHandle TimerHandle_Spawn;
	//生成敌人间隔变量
	float SpawnInterval;
	//最大敌人数量变量
	UPROPERTY(EditAnywhere,Category="Spawn")
	int MaxEnemyNum;
	//当前敌人数量变量
	int CurrentEnemyCount;
public:	
	//游戏每帧函数声明
	virtual void Tick(float DeltaTime) override;
	//减少敌人数量函数声明
	void DecreaseEnemyCount();
};

        2.C++源文件:

//预处理
#include "Public/EnemySpawner.h"//生成敌人类
#include "Components/BoxComponent.h"//盒体碰撞
#include "Kismet/KismetMathLibrary.h"//数学库
#include "Kismet/GameplayStatics.h"//游戏状态
#include "Public/SpaceShip.h"//战机类
#include "Engine/World.h"//世界
#include "Public/Enemy.h"//敌人类
#include "TimerManager.h"//时间管理器
//构造函数实现
AEnemySpawner::AEnemySpawner()
{
	PrimaryActorTick.bCanEverTick = true;//开启tick函数

	SpawnArea = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnArea"));//实例化碰撞组件
	RootComponent = SpawnArea;//设置根组件
	SpawnInterval = 2.0f;//敌人生成间隔为2s
	MaxEnemyNum = 30;//最大敌人数量为30
	CurrentEnemyCount = 0;//当前敌人计数为0
}
//游戏开始函数实现
void AEnemySpawner::BeginPlay()
{
	Super::BeginPlay();	
	SpaceShip=Cast<ASpaceShip>( UGameplayStatics::GetPlayerPawn(this,0));//战机类型检测
	GetWorldTimerManager().SetTimer(TimerHandle_Spawn,this,&AEnemySpawner::SpawnEnemy,SpawnInterval,true,0.0f);//开启敌人生成定时器
}
//获取生成位置函数实现
FVector AEnemySpawner::GetGenerateLocation()
{
	float Distance=0;//敌人生成位置与玩家位置距离变量
	FVector Location;//敌人生成位置变量
	while (Distance < MinimumDistanceToPlayer)//敌人生成位置与玩家位置距离小于敌人与玩家最小距离
	{
		Location = UKismetMathLibrary::RandomPointInBoundingBox(SpawnArea->Bounds.Origin, SpawnArea->Bounds.BoxExtent);//盒体内获取随机坐标
		Distance = (Location - SpaceShip->GetActorLocation()).Size();//计算距离
	}
	return Location;//返回生成位置
}
//生成敌人函数实现
void AEnemySpawner::SpawnEnemy()
{
	if (SpaceShip->GetBDead() == false&&CurrentEnemyCount<MaxEnemyNum)//战机未阵亡且当前敌人计数小于最大
	{
		FActorSpawnParameters SpawnParameters;//生成范围变量
		GetWorld()->SpawnActor<AEnemy>(Enemy, GetGenerateLocation(), FRotator::ZeroRotator, SpawnParameters);//生成敌人
		CurrentEnemyCount++;//当前敌人计数+1
	}
}
//游戏每帧函数实现
void AEnemySpawner::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}
//减少敌人数量函数实现
void AEnemySpawner::DecreaseEnemyCount()
{
	if (CurrentEnemyCount > 0)//当敌人数量大于1时
	{
		CurrentEnemyCount--;//当前敌人数量-1
		UE_LOG(LogTemp,Warning,TEXT("%s"),*FString::SanitizeFloat(CurrentEnemyCount));//打印日志记录敌人数量
	}
}

        3.虚幻蓝图类:①创建蓝图类继承生成C++类

                                 ②蓝图类组件添加素材

        4.类设置:①类敌人细节添加敌人类

                          ②类最大敌人数量细节添加数量

        5.总结:生成类负责敌人在一个确定范围内的生成以及敌人生成数量,生成间隔,生成位置的管制

7.模式实现

        1.C++头文件:

//预处理
#pragma once//编译一次
#include "CoreMinimal.h"//核心编程环境
#include "GameFramework/GameModeBase.h"//GameModeBase源代码
#include "ShipGameMode.generated.h"//反射机制
//战机游戏模式类
UCLASS()
class SPACESHIPBATTLE_API AShipGameMode : public AGameModeBase
{
	GENERATED_BODY()
protected:
	//构造函数声明
	AShipGameMode();
	//分数变量
	UPROPERTY(BlueprintReadOnly)
	int Score;
public:
	//增加敌人数量函数声明
	void IncreaseScore();
};

        2.C++源文件:

#include "Public/ShipGameMode.h"//战机游戏模式类
//构造函数实现
AShipGameMode::AShipGameMode() 
{
	Score = 0;//分数初始化为0
}
//增加敌人数量函数实现
void AShipGameMode::IncreaseScore()
{
	Score++;//击败敌人分数增加
}

        3.类设置:①类默认pawn细节添加战机类

        4.总结:游戏模式负责游戏分数的管理

8.编辑器实现

        1.设置:①将游戏模式添加到编辑器默认游戏模式

                      ②将地图添加到编辑器游戏默认地图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值