Download

[C++ VIDEO TUTORIAL] - Making a simple "Subway Surfer" game

This short tutorial is a follow-up from my “Temple Run” tutorial which you can find over here: https://www.youtube.com/watch?v=43N9aGI84YU

https://youtube.com/watch?v=BWYdaRsYPQo

It shows how to add collectable items and it also shows how to change the player movement to be like that in games such as “Subway Surfer”.

Here is the code for the “good” items which the player can collect:

GoodItem.h


#pragma once

#include "GameFramework/Actor.h"
#include "GoodItem.generated.h"

UCLASS()
class SKYRUN_API AGoodItem : public AActor
{
	GENERATED_BODY()
	/** Sphere collision component */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Enemy, meta = (AllowPrivateAccess = "true"))
	UStaticMeshComponent* CollectableMeshComponent;

	USphereComponent *myCollisionSphere;

public:	
	// Sets default values for this actor's properties
	AGoodItem();

	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	
	// Called every frame
	virtual void Tick( float DeltaSeconds ) override;

	UFUNCTION()
	void HandleCollision(AActor* Other, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& OverlapInfo);
};

GoodItem.cpp


#include "SkyRun.h"
#include "GoodItem.h"


// Sets default values
AGoodItem::AGoodItem()
{
 	// 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;

	myCollisionSphere = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionSphere"));
	myCollisionSphere->InitSphereRadius(150.0f);

	static ConstructorHelpers::FObjectFinder<UStaticMesh> GoodMesh(TEXT("/Game/StarterContent/Shapes/Shape_Torus.Shape_Torus"));
	// Create the mesh component
	CollectableMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("GoodMesh"));
	RootComponent = myCollisionSphere;
	CollectableMeshComponent->SetCollisionProfileName(UCollisionProfile::Pawn_ProfileName);
	CollectableMeshComponent->SetStaticMesh(GoodMesh.Object);

	CollectableMeshComponent->SetWorldScale3D(FVector(.5f, .5f, .5f));

	CollectableMeshComponent->AttachTo(RootComponent);

	myCollisionSphere->OnComponentBeginOverlap.AddDynamic(this, &AGoodItem::HandleCollision);
}

// Called when the game starts or when spawned
void AGoodItem::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AGoodItem::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

}

void AGoodItem::HandleCollision(AActor* Other, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& OverlapInfo)
{
	FString name = Other->GetName();
	if (!name.Contains("ThirdPersonCharacter"))
		return;

	UWorld* const World = GetWorld();
	if (World)
		Destroy();

}

and in SkyRunCharacter.cpp, you can use code like this to make the player move left and right when the A and D key are pressed:

void ASkyRunCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{

InputComponent->BindAxis(“MoveRight”, this, &ASkyRunCharacter::ChangeDirection);

}

and then


void ASkyRunCharacter::**ChangeDirection**(float Value)
{
	if (Value != 0 && canTurnRight) {
		canTurnRight = false;

		if (Value == 1)
			SetActorLocation(GetActorLocation() + FVector(0, 400, 0));//move to the right
		else if (Value == -1)
			SetActorLocation(GetActorLocation() + FVector(0, -400, 0));//move to the left
	}
	else if (Value == 0)
		canTurnRight = true;

	return;
}

Note that if the player is moving along a spline, then the left and right movement will need to be along the right / left vector which depends on the player’s rotation at any given time. Then you can use


FTransform ft = SplineIterator->GetTransformAtDistanceAlongSpline(length, ESplineCoordinateSpace::World);
FVector right = ft.GetRotation().GetAxisY();

and add or subtract a multiple of that vector to move the player right and left.

That’s what I did for the roller coaster movement here: https://www.youtube.com/watch?v=8fn6LYcUF10

Hope it helps.

GOD Bless you man…

Thank you man!!!