博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UE4 C++代码实现碰撞小游戏
阅读量:685 次
发布时间:2019-03-17

本文共 8964 字,大约阅读时间需要 29 分钟。

新建项目选择空项目

复制Materials和Meshes到Content目录

重新构建关卡

添加SM_Backdrop,SM_Wall,并作如下修改:

添加C++类,并取名为Paddle

在Paddle.h中添加属性:

在类上声明:

FloatingPawnMovement是一个运动组件,为任何Pawn类提供简单的运动。

在Paddle.h中继续添加移动处理的函数

Paddle.cpp中添加头文件

构造函数中添加UStaticMeshComponent与UFloatingPawnMovement组件

实现MoveHorizontal函数:

在Paddle_BP蓝图设置SM_Padle的mesh

把Paddle_BP放入场景中

在场景中新建GameMode并改名为ArkanoidGameMode_BP

对GameMode进行设置

添加Camera

新建PlayerController的基类,并取名为Paddle_Player_Controller

Paddle_Player_Controller.h添加函数声明

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"#include "GameFramework/PlayerController.h"#include "Paddle_Player_Controller.generated.h"//class ABall/** *  */UCLASS()class PLAYBALL_API APaddle_Player_Controller : public APlayerController{	GENERATED_BODY()		APaddle_Player_Controller();	UFUNCTION()		virtual void SetupInputComponent() override;protected:	virtual void BeginPlay() override;	void MoveHorizontal(float AxisValue);	//ball reerences};

Paddle_Player_Controller.cpp中设置相机为主视角

// Fill out your copyright notice in the Description page of Project Settings.#include "Paddle_Player_Controller.h"#include "Kismet/GameplayStatics.h"#include "Camera/CameraActor.h"#include "Paddle.h"//#include "Ball.h"APaddle_Player_Controller::APaddle_Player_Controller(){}void APaddle_Player_Controller::SetupInputComponent(){}void APaddle_Player_Controller::BeginPlay(){	TArray
CameraActors; UGameplayStatics::GetAllActorsOfClass(GetWorld(), ACameraActor::StaticClass(), CameraActors); FViewTargetTransitionParams params; SetViewTarget(CameraActors[0], params);}void APaddle_Player_Controller::MoveHorizontal(float AxisValue){}

新建蓝图类,基类为Paddle_Player_Controller

然后设置游戏控制类为刚刚新建的蓝图类:

设置完之后运行游戏,可以看到:

添加输入

在Paddle_Player_Controller.h中绑定SetupInputComponent:

void APaddle_Player_Controller::SetupInputComponent(){	Super::SetupInputComponent();	EnableInput(this);	InputComponent->BindAxis("MoveHorizontal", this, &APaddle_Player_Controller::MoveHorizontal);}

实现MoveHorizontal

void APaddle_Player_Controller::MoveHorizontal(float AxisValue){	auto MyPawn = Cast
(GetPawn()); if (MyPawn) { MyPawn->MoveHorizontal(AxisValue); }}

这里需要注意的是,在关卡中只需要放PlayerStart即可,不需要放Paddle_BP,否则会不能移动。

添加球体

在ball.h添加属性:

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"#include "GameFramework/Actor.h"#include "Ball.generated.h"class UProjectileMovementComponent;UCLASS()class PLAYBALL_API ABall : public AActor{	GENERATED_BODY()	public:		// Sets default values for this actor's properties	ABall();	virtual void Launch();	bool BallLaunched;	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)		UStaticMeshComponent* SM_Ball;	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)		UProjectileMovementComponent* ProjectileMovement;protected:	// Called when the game starts or when spawned	virtual void BeginPlay() override;public:		// Called every frame	virtual void Tick(float DeltaTime) override;	UFUNCTION()		UStaticMeshComponent* GetBall();};

在Ball.cpp的构造函数中添加:

SM_Ball = CreateDefaultSubobject
(TEXT("Ball")); RootComponent = SM_Ball; SM_Ball->SetSimulatePhysics(true); SM_Ball->SetEnableGravity(false); SM_Ball->SetConstraintMode(EDOFMode::XZPlane); SM_Ball->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); SM_Ball->SetCollisionProfileName(TEXT("PhysicsActor"));

设置PhysicsActor的原因是Paddle_BP中StaticMesh的碰撞预设设置的是PhysicsActor

在构造函数中继续添加

ProjectileMovement = CreateDefaultSubobject
(TEXT("Projectile Movement")); ProjectileMovement->bShouldBounce = true; ProjectileMovement->Bounciness = 1.1f; ProjectileMovement->Friction = 0.0f; ProjectileMovement->Velocity.X = 0.0f;

实现Launch函数

void ABall::Launch(){	if (!BallLaunched) {		SM_Ball->AddImpulse(FVector(140.0f, 0.0f, 130.0f), FName(), true);		BallLaunched = true;	}}

添加函数绑定

在蓝图中实现:

修改Paddle_Player_Controller.h

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"#include "GameFramework/PlayerController.h"#include "Ball.h"#include "Paddle_Player_Controller.generated.h"/** *  */UCLASS()class PLAYBALL_API APaddle_Player_Controller : public APlayerController{	GENERATED_BODY()		APaddle_Player_Controller();	UFUNCTION()		virtual void SetupInputComponent() override;protected:	virtual void BeginPlay() override;	void MoveHorizontal(float AxisValue);	void Launch();	UPROPERTY(EditAnywhere)		TSubclassOf
BallObj; ABall* MyBall=nullptr; FVector SpawnLocation = FVector(10.0f, 0.0f, 40.0f); FRotator SpawnRotation = FRotator(0.0f, 0.0f, 0.0f); FActorSpawnParameters SpawnInfo;public: void SpawnNewBall(); //ball reerences};

在Paddle_Player_Controller.h实现SpawnNewBall()函数

void APaddle_Player_Controller::SpawnNewBall(){	if (!MyBall) {		MyBall = nullptr;	}	if (BallObj) {		MyBall = GetWorld()->SpawnActor
(BallObj, SpawnLocation, SpawnRotation, SpawnInfo); }}

开始游戏的时候调用SpawnNewBall

设置Ball Obj

新建Material

双击做如下设置

完成以上步骤后做如下步骤:

创建砖块,并命名为Brick.h:

在Brick.h中创建属性与函数:

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"#include "GameFramework/Actor.h"#include "Brick.generated.h"class UBoxComponent;UCLASS()class PLAYBALL_API ABrick : public AActor{	GENERATED_BODY()	public:		// Sets default values for this actor's properties	ABrick();protected:	// Called when the game starts or when spawned	virtual void BeginPlay() override;	UPROPERTY(VisibleAnywhere,BlueprintReadOnly)		UStaticMeshComponent* SM_Brick;	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)		UBoxComponent* Box_Collision;	float SpeedModifierOnBounce = 1.0f;	UFUNCTION()		void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor,			class UPrimitiveComponent* OtherComp, int32 OtherBodyIndexType, bool bFromSweep,			const FHitResult& SweepResult);	void DestroyBrick();public:		// Called every frame	virtual void Tick(float DeltaTime) override;};

初始化,以及绑定碰撞函数

新建Brick的蓝图类并做如下设置:

把Brick蓝图类拖入level中

添加Tag

实现碰撞函数

void ABrick::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndexType, bool bFromSweep, const FHitResult& SweepResult){	UE_LOG(LogTemp, Warning, TEXT("OnOverlapBegin"));	if (OtherActor->ActorHasTag("Ball"))	{		UE_LOG(LogTemp, Warning, TEXT("OnOverlapBegin  OtherActor"));		ABall* MyBall = Cast
(OtherActor); FVector BallVelocity = MyBall->GetVelocity(); BallVelocity *= (SpeedModifierOnBounce + 1.0001f); MyBall->GetBall()->SetPhysicsLinearVelocity(BallVelocity, true); FTimerHandle UnusedHandle; //先弹走,然后0.1s后再destroy造成视觉差 GetWorldTimerManager().SetTimer(UnusedHandle, this, &ABrick::DestroyBrick, 0.1f, false); }}void ABrick::DestroyBrick(){ this->Destroy();}

到这里,游戏基本功能已经实现,但是如果小球弹到下面了该怎么处理呢?

添加基类为Actor的ABallBoound C++类

BallBoound.h

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"#include "GameFramework/Actor.h"#include "BallBoound.generated.h"class UBoxComponent;class APaddle_Player_Controller;UCLASS()class PLAYBALL_API ABallBoound : public AActor{	GENERATED_BODY()	public:		// Sets default values for this actor's properties	ABallBoound();protected:	// Called when the game starts or when spawned	virtual void BeginPlay() override;	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)		UBoxComponent* Box_Collision;	APaddle_Player_Controller* PlayerController_REF;	UFUNCTION()		void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor,			class UPrimitiveComponent* OtherComp, int32 OtherBodyIndexType, bool bFromSweep,			const FHitResult& SweepResult);public:		// Called every frame	virtual void Tick(float DeltaTime) override;};

BallBound.cpp

// Fill out your copyright notice in the Description page of Project Settings.#include "BallBoound.h"#include "Components/BoxComponent.h"#include "Kismet/GameplayStatics.h"#include "Paddle_Player_Controller.h"// Sets default valuesABallBoound::ABallBoound(){ 	// 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;	Box_Collision = CreateDefaultSubobject
(TEXT("Box Collision")); RootComponent = Box_Collision;}// Called when the game starts or when spawnedvoid ABallBoound::BeginPlay(){ Super::BeginPlay(); Box_Collision->OnComponentBeginOverlap.AddDynamic(this, &ABallBoound::OnOverlapBegin); PlayerController_REF = Cast
( UGameplayStatics::GetPlayerController(GetWorld(), 0) ); }// Called every framevoid ABallBoound::Tick(float DeltaTime){ Super::Tick(DeltaTime);}void ABallBoound::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndexType, bool bFromSweep, const FHitResult& SweepResult){ if (OtherActor->ActorHasTag("Ball")) { OtherActor->Destroy(); PlayerController_REF->SpawnNewBall(); }}

新建该类的蓝图类,并调整好大小,放入蓝图中

运行截图:

 

转载地址:http://gezhz.baihongyu.com/

你可能感兴趣的文章