首页 > 编程语言 >[6] UE C++ FlappyBird

[6] UE C++ FlappyBird

时间:2024-04-03 20:33:22浏览次数:24  
标签:RenderBirdComponent TEXT void ABirdPawn C++ 枚举 FlappyBird UE true

FlappyBird项目

引入Paper2D插件

//渲染资产的组件
class UPaperSpriteComponent* RenderLandComponent;
//资产
class UPaperSprite* LandSprite;

GameModeBase.h.cpp

UE枚举声明

//枚举(用于描述状态信息)
UENUM()
enum EBirdStateTest //传统枚举
{
	EBS_Wait,//等待游戏开始状态的小鸟
	EBS_Fly,//游戏开始小鸟可以飞
	EBS_Dead//游戏结束,小鸟标记为死亡状态
};
UENUM()
enum EColor //传统枚举
{
	EC_Wait,//等待游戏开始状态的小鸟
	EC_Fly,//游戏开始小鸟可以飞
	EC_Dead//游戏结束,小鸟标记为死亡状态
};
UENUM()
namespace  EBirdStateSecondTest //加命名空间的枚举,明明空间名是枚举名
{
	enum Type 
    {
		Wait,//等待游戏开始状态的小鸟
		Fly,//游戏开始小鸟可以飞
		Dead//游戏结束,小鸟标记为死亡状态
	};
}
UENUM()
enum class EBirdState:uint8 //C++11的枚举(UE中常见)
{
	Wait,//等待游戏开始状态的小鸟
	Fly,//游戏开始小鸟可以飞
	Dead//游戏结束,小鸟标记为死亡状态
};
//使用
    //在一个枚举用于纯C++源码而不应用于蓝图的时候,需要先写一个枚举变量记录状态,再添加一个函数用于修改状态

	EBirdStateTest CurrentBirdStateTest1;//记录状态(传统枚举)
	void SetBirdStateTest(EBirdStateTest BirdState);//高版本Rider不允许成员的名字与局部变量的名字冲突

	//A::B//B属于A这个作用域

	EBirdStateSecondTest::Type CurrentBirdStateSecondTest;//记录状态(加命名空间的枚举)
	void SetBirdStateSecondTest(EBirdStateSecondTest::Type BirdState);

	EBirdState	 CurrentBirdState;//记录状态(C++11的枚举)
	void SetBirdState(EBirdState BirdState);

void ABirdPawn::SetBirdState(EBirdState BirdState)
{
	CurrentBirdState = BirdState; //成员属性被参数修改(传值)
	//根据不同的状态做出不同的响应
	switch (CurrentBirdState)
	{
	case EBirdState::Wait: RenderBirdComponent->SetSimulatePhysics(false);
		break;
	case EBirdState::Fly: RenderBirdComponent->SetSimulatePhysics(true);
		break;
	case EBirdState::Dead: RenderBirdComponent->SetSimulatePhysics(false);
		break;
	}
}

 获取类的类型信息

DefaultPawnClass = ABirdPawn::StaticClass();

枚举赋值

CurrentGameState = EGameState::BeginUI;

生成一个SpawnActor

GetWorld()->SpawnActor<ABackgroundActor>(ABackgroundActor::StaticClass(), FVector(0, -50, 0),
                                         FRotator::ZeroRotator);

获取当前游戏世界的指针

GetWorld()

BackgroundActor.h.cpp

创建根组件 > 并设置附加关系

RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));  //创建USceneComponent的组件
RenderBackgroundComponent = CreateDefaultSubobject<UPaperSpriteComponent>(TEXT("RenderBackgroundComponent"));//创建UPaperSpriteComponent类型的组件
RenderBackgroundComponent->SetupAttachment(RootComponent); //把RenderBackgroundComponent附着到RootComponent上

加载ue项目文件

LoadObject<UPaperSprite>(nullptr,TEXT("/Script/Paper2D.PaperSprite'/Game/FlappyBird/Textures/Background/bg_day_Sprite.bg_day_Sprite'"));

 获取随机数

FMath::RandRange(1,100)

 渲染图片

//渲染资产的组件
    class UPaperSpriteComponent* RenderBackgroundComponent;
//资产
    class UPaperSprite* DayBackgroundTexture;
//加载文件对象
DayBackgroundTexture=LoadObject<UPaperSprite>(nullptr,TEXT("/Script/Paper2D.PaperSprite'/Game/FlappyBird/Textures/Background/bg_day_Sprite.bg_day_Sprite'"));
//设置渲染
RenderBackgroundComponent->SetSprite(NightBackgroundTexture);

 BirdHUD.h.cpp

 声明2d向量

FVector2D PlayButtonSize;
PlayButtonSize = FVector2D(116, 70); //按钮大小

 声明&&加载纹理&&渲染纹理&&添加命中事件

UTexture* PlayButtonTexture; 
//加载纹理
PlayButtonTexture = LoadObject<UTexture>(
		nullptr,TEXT("/Script/Engine.Texture2D'/Game/FlappyBird/Textures/UI/button_play.button_play'"))
//渲染简单纹理
DrawTextureSimple(PlayButtonTexture, Canvas->SizeX / 2 - (PlayButtonSize.X / 2),Canvas->SizeY / 2 - (PlayButtonSize.Y / 2));
//Canvas->SizeX 获取屏幕X宽度 Canvas->SizeY Y轴
//添加命中事件
AddHitBox(FVector2D(Canvas->SizeX / 2 - (PlayButtonSize.X / 2), Canvas->SizeY / 2 - (PlayButtonSize.Y / 2)),PlayButtonSize,TEXT("Play"), true);

//触发名字是 Play 的命中事件
void ABirdHUD::NotifyHitBoxRelease(FName BoxName)
{
	Super::NotifyHitBoxRelease(BoxName);
	if (BoxName == TEXT("Play"))
	{
		UE_LOG(LogTemp, Log, TEXT("单机"))
	}
}

 设置单击事件和显示鼠标

// Cast<To>()
BirdPawnInstancePointer = Cast<ABirdPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
APlayerController* PC = UGameplayStatics::GetPlayerController(GetWorld(), 0);
PC->SetShowMouseCursor(true);
PC->bEnableClickEvents = true;

 绘制矩形包括RGBA通道

//RectAlpha 0.38 -> 0.0
DrawRect(FLinearColor(0, 0, 0, RectAlpha), 0, 0, Canvas->SizeX, Canvas->SizeY);

 

BirdPawn.h.cpp

输入事件

virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
void ABirdPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	InputComponent->BindAction(TEXT("Fly"), EInputEvent::IE_Pressed, this, &ABirdPawn::FlyCallBack);//操作
	InputComponent->BindAxis(TEXT("Test"),this,&ABirdPawn::TestBindAxisFunction);//轴映射
}
//回调函数
void ABirdPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	InputComponent->BindAction(TEXT("Fly"), EInputEvent::IE_Pressed, this, &ABirdPawn::FlyCallBack);//操作映射
	InputComponent->BindAxis(TEXT("Test"),this,&ABirdPawn::TestBindAxisFunction);//轴映射
}

void ABirdPawn::FlyCallBack() //操作映射
{
	UE_LOG(LogTemp, Log, TEXT("按下"))
	RenderBirdComponent->SetPhysicsLinearVelocity(FVector::Zero()); //清除物体当前的线性速度
	RenderBirdComponent->AddImpulse(FVector(0, 0, 2000));//物体施加一个冲量
}

void ABirdPawn::TestBindAxisFunction(float AxisValue) //轴映射
{
	UE_LOG(LogTemp, Log, TEXT("按下A "))
}

void ABirdPawn::BeginPlay()
{
	Super::BeginPlay();
    //也可以在BeginPlay调用
	InputComponent->BindAction();//如果没有SetupPlayerInputComponent就可以在Begin函数中使用Actor类下的成员属性调用成员函数BindAction或者BindAxis
	RenderBirdComponent->SetSimulatePhysics(true);
    
    RenderBirdComponent->OnComponentHit.AddDynamic(this,&ABirdPawn::OnComponentHit);//绑定一个Hit事件并执行回调函数
	SphereCollision->OnComponentBeginOverlap.AddDynamic(this, &ABirdPawn::OnComponentBeginOverlap);

}

 设置物理

RenderBirdComponent->SetSimulatePhysics(true)//设置物理
RenderBirdComponent->GetBodyInstance()->bNotifyRigidBodyCollision = true; //如果组件开启了物理模拟,是否还响应Hit事件
RenderBirdComponent->SetCollisionProfileName(TEXT("BlockAll"));//将碰撞预设修改为BlockAll
RenderBirdComponent->SetCollisionObjectType(ECC_Pawn); //将Object(组件)类型修改为Pawn
RenderBirdComponent->OnComponentHit.AddDynamic(this, &ABirdPawn::OnComponentHit); //绑定一个Hit事件并执行回调函数

//打印被击中的Actor名称
void ABirdPawn::OnComponentHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
                               FVector NormalImpulse, const FHitResult& Hit)
{
	APipeActor* Pipe = Cast<APipeActor>(OtherActor); //转成bird

	if (Pipe)
	{
		UE_LOG(LogTemp, Log, TEXT("PipeInstanceName = %s"), *Pipe->GetName())
	}

	if (Cast<ALandActor>(OtherActor))
	{
	}
}

//创建一个球体设置碰撞类型和大小
SphereCollision = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere"));
SphereCollision->SetupAttachment(RenderBirdComponent);
SphereCollision->SetCollisionProfileName(TEXT("OverlapAll"));
SphereCollision->SetSphereRadius(26.f);
SphereCollision->bHiddenInGame = false;

冲量

void ABirdPawn::FlyCallBack()
{
   if (CurrentBirdState != EBirdState::Fly)return;
   //UE_LOG(LogTemp, Log, TEXT("按下"))
   RenderBirdComponent->SetPhysicsLinearVelocity(FVector::Zero()); //清除原有的速度
   RenderBirdComponent->AddImpulse(FVector(0, 0, 1300));
}

设置相对旋转

ArmComponent->SetRelativeRotation(FRotator(0, -90, 0));

 设置相机模式&&和正交

MainCamera->SetProjectionMode(ECameraProjectionMode::Orthographic);
MainCamera->OrthoWidth = 1000.f;

 添加本地偏移

RenderLandComponent->AddLocalOffset(FVector(_Speed,0,0));

 PipeActor.h.cpp

 自定义FString的名称

FString SceneName = FString::Printf(TEXT("Scene%d"),i);//字符串的格式化输出
FName _SceneName = *SceneName;//当*用到FString变量的前边的时候,代表的是强制类型转换(由FString强转为TCHAR类型的数组,TEXT("")宏本质就是一个TCHAR类型的数组)
USceneComponent* Scene=CreateDefaultSubobject<USceneComponent>(_SceneName);//假设循环第1次 地址是0X123

匿名加载纹理

ConstructorHelpers::FObjectFinder<UPaperSprite> UpPipePath(TEXT("/Script/Paper2D.PaperSprite'/Game/FlappyBird/Textures/Prop/pipe_up_Sprite.pipe_up_Sprite'"));
ConstructorHelpers::FObjectFinder<UPaperSprite> DownPipePath(TEXT("/Script/Paper2D.PaperSprite'/Game/FlappyBird/Textures/Prop/pipe_down_Sprite.pipe_down_Sprite'"));

在UE C++使用重载运算符

//声明
struct FPipeInfo
{
	bool bPlayCoinSound; //控制加分和播放加分音效的属性
	USceneComponent* SceneInstancePointer; //每组管道的父组件的对象地址
	FPipeInfo(bool bPlayCoin)
	{
		this->bPlayCoinSound = bPlayCoin;
		UE_LOG(LogTemp, Log, TEXT("FPipeInfo(bool bPlayCoin)"))
	}

	FPipeInfo(USceneComponent* SceneInstance)
	{
		UE_LOG(LogTemp, Log, TEXT("FPipeInfo(USceneComponent* SceneInstance)"))
		this->SceneInstancePointer = SceneInstance;
		bPlayCoinSound = true;
	}

	//将FPipeInfo强制类型转换到USceneComponent类型
	operator USceneComponent*()
	{
		return SceneInstancePointer;
	}

	//运算符重载 ->
	USceneComponent* operator->()
	{
		return SceneInstancePointer;
	}

	operator bool() //将当前的类型强制转换为bool类型
	{
		return bPlayCoinSound;
	}

	bool operator=(bool Value)
	{
		this->bPlayCoinSound = Value;
		return bPlayCoinSound;
	}
};

TArray<FPipeInfo> SceneArray;//使用

//.cpp 
//添加
APipeActor::APipeActor()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
    RootComponent=CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
    ConstructorHelpers::FObjectFinder<UPaperSprite> UpPipePath(TEXT("/Script/Paper2D.PaperSprite'/Game/FlappyBird/Textures/Prop/pipe_up_Sprite.pipe_up_Sprite'"));
    ConstructorHelpers::FObjectFinder<UPaperSprite> DownPipePath(TEXT("/Script/Paper2D.PaperSprite'/Game/FlappyBird/Textures/Prop/pipe_down_Sprite.pipe_down_Sprite'"));

	PipeSpace=220.f;
	for(int32 i=0;i<3;i++)
	{
		FString SceneName = FString::Printf(TEXT("Scene%d"),i);//字符串的格式化输出
		FName _SceneName = *SceneName;//当*用到FString变量的前边的时候,代表的是强制类型转换(由FString强转为TCHAR类型的数组,TEXT("")宏本质就是一个TCHAR类型的数组)
		USceneComponent* Scene=CreateDefaultSubobject<USceneComponent>(_SceneName);//假设循环第1次 地址是0X123

		FString UpName = FString::Printf(TEXT("Up%d"),i);
		FName _UpName = *UpName;
		UPaperSpriteComponent*Up=CreateDefaultSubobject<UPaperSpriteComponent>(_UpName);

		FString DownName = FString::Printf(TEXT("Down%d"),i);
		FName _DownName = *DownName;
		UPaperSpriteComponent*Down=CreateDefaultSubobject<UPaperSpriteComponent>(_DownName);

		Scene->SetupAttachment(RootComponent);
		Up->SetupAttachment( Scene);
		Down->SetupAttachment( Scene);

		//导入管道的资产
		if(UpPipePath.Object&&DownPipePath.Object)
		{
			Up->SetSprite(UpPipePath.Object);
			Down->SetSprite(DownPipePath.Object);
		}
		//设置每组上下管道之间的间距
        Up->SetRelativeLocation(FVector(0,0,-210));
        Down->SetRelativeLocation(FVector(0,0,260));
		//重置了声明
		SceneArray.Add(Scene);//Add本来需要一个FPipeInfo类型对象,但是因为有强制类型转换到
	}
	SetPipeSpace();//设置管道的左右间距
	RandPipeHeight();//设置随机高度
	//PipeMoveSpeed=170.f;
	PipeMoveSpeed=0.f;
	bAddScoreToggle=true;
	CoinSound=nullptr;
}
void APipeActor::UpdatePipeMove(float DeltaTime)
{   float _Speed=DeltaTime*PipeMoveSpeed*-1;
	if(SceneArray.Num()) //重载了布尔
	{
		for(int32 i=0;i<SceneArray.Num();i++)
		{
			//设置本次循环中一根管道的移动
			SceneArray[i]->AddRelativeLocation(FVector(_Speed,0,0)); //重载了 ->
			//移动过程中实时监控管道的位置是不是已经到达需要折返的位置(折返点 -280)
			if(SceneArray[i]->GetRelativeLocation().X<=-280)//折返点
			{
				int32 index=i-1;
				if(index<0)
				{
					index=2;
				}
				FVector OldLocation=SceneArray[i]->GetRelativeLocation();
				OldLocation.X=SceneArray[index]->GetRelativeLocation().X+PipeSpace;
				SceneArray[i]->SetRelativeLocation(OldLocation);
				RandPipeHeight(SceneArray[i]);
				//bAddScoreToggle=true;
				//SceneArray[i].bPlayCoinSound=true;
				SceneArray[i]=true; //重载了 =
			}
			if(SceneArray[i]->GetRelativeLocation().X<=-90)//加分点
			{
				if(BirdGameState)
				{
					//if(bAddScoreToggle)
					if(SceneArray[i])
					{
						BirdGameState->AddScore();
						UGameplayStatics::PlaySound2D(GetWorld(),CoinSound);
						//bAddScoreToggle=false;//本次已经加分完成,关闭加分开关
						//SceneArray[i].bPlayCoinSound=false;
						SceneArray[i]=false; //重载了 =
					}
				}
			}
		}
	}
}

 

标签:RenderBirdComponent,TEXT,void,ABirdPawn,C++,枚举,FlappyBird,UE,true
From: https://www.cnblogs.com/Aquakinn/p/18107185

相关文章

  • C++中的虚函数和虚函数表
    在上面一篇博客中 https://www.cnblogs.com/wphl-27/p/18111083,提到了虚函数,纯虚函数这篇博客我想继续进一步来说一下虚函数和虚函数表在C++中,每一个含有虚函数的类,编译器都会为它啊做出一个虚函数表(通常叫做vtable),这个虚函数表里面的每个元素都是函数指针,每个元素(函数......
  • Java登陆第三十七天——VUE3插值表达式、文本渲染、属性渲染、事件绑定
    插值表达式VUE中最基本的数据绑定形式。语法格式如下:{{数据来源}}插值表达式的特点:不依靠标签。可以调用函数。支持运算符。栗子App.vue<scriptsetup>letmsg="字符串";letnum=10;functionf1(){return"有返回值的方法"}letf2=()=>{......
  • C++构建工具_bazel
    apollo工具1.DreamView可视化交互工具DreamView是一个web应用程序,提供如下的功能: 可视化显示当前自动驾驶车辆模块的输出信息。例如:规划路径、车辆定位、车架信息等。为使用者提供人机交互接口以监测车辆硬件状态,对模块进行开关操作,启动自动驾驶车辆等。提供......
  • 用c++实现百元买百鸡问题、顺序查找
    5.1.2百元买百鸡问题【问题】已加公鸡5元一只,母鸡3元一只,小鸡1元三只,用100元钱买100只鸡, 问公鸡、母鸡、小鸡各多少只?【想法】 设公鸡、母鸡和小鸡的个数分别为x、y、z,则有如下方程组成立,则百元买百鸡问题转换为求方程组的解。应用蛮力法求力程组的解只能依次试探变量x......
  • Vue3+vite打包Failed to load module script
    完整報錯信息:Failedtoloadmodulescript:ExpectedaJavaScriptmodulescriptbuttheserverrespondedwithaMIMEtypeof"text/html".StrictMIMEtypecheckingisenforcedformodulescriptsperHTMLspec.目前vite.config.js打包寫法://拆分js到......
  • 基于SSM+SpringBoot+Vue前后端分离的体育商品商城系统(附论文)
    演示视频基于SSM+SpringBoot+Vue前后端分离的体育商品商城系统(附论文)-源码乐园文字描述本系统的设计严格遵循软件开发流程,使用MVC模式,采用开源框架SpringBoot+MybatisPlus+Vue进行开发,使用java语言编写,后端的数据库采用MySQL,Jpa自动创表,通过Spring配置文件与数据......
  • 基于springboot+vue+Mysql的招生管理系统
    开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9系统展示系统首页学生注册专业信息个人中心管理员登录管理员功能界面学生管理专业信息管理专业报名......
  • Vue3+TypeScript项目(SKU管理模块)
    一、SKU模块静态页面src\views\product\sku\index.vue<template><el-card><el-tableborderstyle="margin:10px0px"><el-table-columntype="index"label="序号"width="80px"></el-table......
  • C++之STL的algorithm(5)之生成算法(accumulate、fill)整理
    C++之STL的algorithm(5)之生成算法(accumulate、fill)整理注:整理一些突然学到的C++知识,随时mark一下例如:忘记的关键字用法,新关键字,新数据结构C++的遍历算法整理C++之STL的algorithm(5)之生成算法(accumulate、fill)整理一、生成算法1、accumulate累加算法2、fill填充算法......
  • vue3配置使用环境变量.env.development
    参考:https://blog.csdn.net/perfect2011/article/details/1299308191.新建环境配置文件,根目录.env基础系统变量,无论何种环境,都可使用其中配置的值,其他环境中的变量会覆盖.env中的同名变量。.env.development开发环境.env.production生产环境.env.staging测试环境2.vue3使用vit......