本文共 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(){ TArrayCameraActors; 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) TSubclassOfBallObj; 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/