0% found this document useful (0 votes)
3 views

CPPNotes

The document outlines the development process for two projects in a game development course, focusing on creating a game world with interactive elements and a magic projectile system. It details the setup of various components, including camera and movement systems, as well as the implementation of player input functionality. Additionally, it provides hints for project enhancements and emphasizes the use of smart pointers for memory management in C++.

Uploaded by

lomzo.etc
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

CPPNotes

The document outlines the development process for two projects in a game development course, focusing on creating a game world with interactive elements and a magic projectile system. It details the setup of various components, including camera and movement systems, as well as the implementation of player input functionality. Additionally, it provides hints for project enhancements and emphasizes the use of smart pointers for memory management in C++.

Uploaded by

lomzo.etc
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 33

old cpp NOTES

DRAFT

CS193U Project 1

CS193U Project 2

At the end off this there should be a

Base Systems 10
Camera System
Movement System

Interaction System 45
>barrel
>chest

Base Magic Projectile System 45


all of which are interactable with via walking up to them to interact or shooting

old cpp NOTES 1


HINTS

project 2
PART A)
change : Line Trace from Camera to World and find desired impact location
PART B)
add : new child class black hole ->
new(2): extra spherecompompent and VFX compoent
PART C)
add : new child class black hole ->
new(): If magic component collides with world static or time runs out THEN
teleport

old cpp NOTES 2


CS193U Project 1
Owner L LOMZO GAMING

Tags

Roughly 300 Lines Of CPP

Set Up World N Camera Component

Movement and ‘PIC’

Magic Projectile

Interactive Barrel

PROJECT ONE SOLUTION

Tom Looman Course


Lectures 0-3 && Project 1

CS193U Project 1 1
Lecture 0 : Setup GameWorld
Lecture 1: Setup Movement
Lecture 2: Setup Magic Projectile
Lecture 3: Setup Interactive Barrel
Project 1 :: Have a gameworld where you can cast magic projectile and interact
with BARREL

CS193U Project 1 2
Set Up World N Camera
Component
Owner L LOMZO GAMING

Tags

Getting the world set up and assigning the base player pawn that that the
character controller will posses during gameplay

WTF is ‘UPROPERTY’

It is everywhere and it’s macros like these which handle automatic garbage
collection. We basically will tag everything with UPROPERTY or some form of that.

Start of by creating a empty UE CPP project


Create your first CLASS : CPP Character ‘Hero’

CREATE BP of CPP classes:

Create a BP of previously made CPP Character ‘Hero’


Create a BP of the Game Mode ‘GM-PROJECT’ that was defaulted

SET UP WORLD SETTINGS AND GAME MODE

Set Up Player Start in New Level IN all actors panel


Set Up New Level World Settings to BP IN world settings panel
Set BP GM to Spawn BP Hero as Default Pawn IN game mode panel

Set Up World N Camera Component 1


SET UP BP HERO MESH AND ANIM
SELECT default character functions and settings add the Gideon paragon
character ( any mesh )
SELECT Gideon animation blueprint

LETS MAKE YOUR FIRST CPP COMPONENTS

In blueprints we would simply drag and drop the spring arm component and the
camera arm components to our character class. We are doing the same thing here
but in CPP we declare component in the .H and then initialize and customize them
in the constructor.

We will add to the : the Hero’s Header Section and the Hero’s CPP Constructor
Section
>Hero’s .H Section
> Hero’s CPP Constructor Section

>Hero’s .H Section

IN THE HEADER : For the following two components we have two steps in the
header :The Spring Arm and The Camera Component each are set aside an empty
pointer. In the constructor we will have a choice for Raw or Smart Pointers ( use
smart ptrs for less memory leak bugs)
1) Forward Declare Declare Classes (imports in CPP not H)
2) Create empty pointers

Set Up World N Camera Component 2


//under the imports
class SpringArmComponent
class CameraComponent

---------------------------

//in the constructor

//raw ptr
SpringArmComponent* CameraComp
UCameracompent* CameraComp

//smart ptr
TObjectPtr<USpringArmComponent> SpringArmComp;
TObjectPtr<UCameraCompent> UCameraComp;
//**RAW VS SMART POINTERS**
//Raw Ptr
//UCameracompent* CameraComp
//Smart Ptr
//TObjectPtr<USpringArmComponent> SpringArmComp;

> Hero’s CPP Constructor Section

In the CPP we follow the three steps listed below, these steps all happen in the
constructor. The customization of components can be done in the menu or bp
GUI’s as well as right here baby.
1) Create default sub objects
2) Customize properties of each sub object
3) Attach components to appropriate component

Set Up World N Camera Component 3


By the way right now the camera will be static. When we code in player movement
and camera control with the PIC or player input component the camera will be
moving around and be cool.

//All done in the constructor of this Hero class and all Compone

//Innit Of Components
SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(
CameraComp = CreateDefaultSubobject<UCameraComponent>("Camer

//Customing Components
SpringArmComp->bUsePawnControlRotation = true;
SpringArmComp->SetUsingAbsoluteRotation(true);

//Attaching Components
SpringArmComp->SetupAttachment(RootComponent);
CameraComp->SetupAttachment(SpringArmComp);

WE ARE NOW SPAWNING AND STANDING

AS ANIMATED GIDEON IN A BLANK WORLD

Set Up World N Camera Component 4


Movement and ‘PIC’
Owner L LOMZO GAMING

Tags

The PIC otherwise known as the Player Input Component

*Also Viewable as arrows A → B → C

There are real world inputs <keyboard event>


There are game world events <SomeFunc>
And then there’s PIC

The player input component allows us to bind these together for total immersion
The PIC will recognize a input function and fire the gameplay function
corresponding to it
While PIC is deprecated in favor of enhanced input system {5.1}, PIC is still popular

Movement and ‘PIC’ 1


Introduction and INNIT of the PIC
Before we add our cool gameplay functionality we must set up the player input
functinality using the PIC. The pic enables inputs from project settings work with
our gameplay functions. There are three very important aspects of the Player
Input Component or PIC:

1) Project Setting Keyboard or Axis binding name


2) In the PIC binding the prior step to a gameplay function
3) Confirm that the gameplay code lines up to either a inhereinted or user defined
function

SETTING UP THE PLAYER INPUT COMPONENT {PIC}

//.h{PIC}
virtual void SetupPlayerInputComponent(class UInputComponent* Pl

//.cpp{PIC}
void AHero::SetupPlayerInputComponent(UInputComponent* PlayerInp
{
Super::SetupPlayerInputComponent(PlayerInputComponent); //in
}

And now for setting up some inputs to interact with our character!

> Camera Movement —> Inherited Controller

Movement and ‘PIC’ 2


> Character Movement —> Writing our own Declarations and Definitions to have it
interact w/ camera in a action role playing game fashion

Camera Movement

Make sure this step was followed in the previous part

Spring Arm Component customized in the character


constructor
Engine Input for the Camera

void AHero::SetupPlayerInputComponent(UInputComponent* Player


InputComponent)
{

//Using the pawn class underneath


PlayerInputComponent->BindAxis("LookAround",this,&APawn::
AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp",this,&APawn::AddC
ontrollerPitchInput);
}

&APawn:: Means this function is defined and declared within the pawn class
In the PIC we have bounded our look around inputs to actually look around with
the built in pawn class and controller class!
We don't have to write anymore code and are free to LOOK but not move around
the game world!

Movement and ‘PIC’ 3


//This code block is not bonus, add this to you constructor for
bUseControllerRotationYaw = false;
GetCharacterMovement()->bOrientRotationToMovement = true;

Character Movement

Again make sure previous steps were followed especially that this is included in
the HERO’S CONSTRUCTOR bUseControllerRotationYaw = false;

This is because we want our characters yaw or front direction to not be the literal
front of the mesh but where the camera is facing in terms of camera. AKA Front is
where the camera is facing

In the Header of our Hero in the protected section add

void MoveForeward(float Value);


void MoveRight(float Value);

While in CAMERA we used &APawn:: here for CHARACTER we will use &AHERO::
because above we declared our functions and then we’re gonna bind and define
em

In the PIC of our Hero add the following binding!

PlayerInputComponent->BindAxis("MoveForward",this,&AHero::MoveFo
PlayerInputComponent->BindAxis("MoveRight",this,&AHero::MoveRigh

Movement and ‘PIC’ 4


Using the Scope Operator add the following some where in the HERO’S CPP
define the function therefore completing the bind and ensuring character action
within the world

void AHero::MoveForeward(float Value)


{
//Get the FORWARD vector
FRotator ControlRot = GetControlRotation();

//On forward vector of the character add the value of this m


AddMovementInput(ControlRot.Vector(), Value);
}

void AHero::MoveRight(float Value)


{
//This line would also work : //FVector RightVector = GetAct
FRotator ControlRot = GetControlRotation(); //needed for the
FVector RightVector = FRotationMatrix(ControlRot).GetScaledA

//On right vector of the character add the value of this mov
AddMovementInput(RightVector, Value);
}

BONUS : ADDING JUMP

A) Add engine action input named ‘jumpmove’ and bind it to space bar
B) In the constructor bind action ‘jumpmove’ to &Character::Jump

WE ARE NOW MOVING AND LOOKING AROUND


AS ANIMATED GIDEON IN A BLANK WORLD

Movement and ‘PIC’ 5


Movement and ‘PIC’ 6
Magic Projectile

sections
Setting Up The Magic Projectile
To Cast A Magic Projectile pt1
To Cast A Magic Projectile pt2
The Magic Of Collisions

SETTING UP THE MAGIC PROJECTILE

So things should start to make a little bit more sense, the world is made up of
actors some actors are a bit more specialized than others. —> we then make
children classes of these actors and add our own functionality. The actor class
being the most default of them all.

>Our magic projectile will be a actor of class

THIS WILL ADD A COUPLE LINES OF BOILER PLATE

Magic Projectile 1
Our Magic Projectile is built of these following components we will add on to the
base class
>Sphere
COMPONENT
>Projectile Movement
COMPONENT
>Particle System Component
COMPONENT

First we create them as UPROPERTIES in the .H and then in the .CPP constructor
set up custom features of each component if they have any and then they
attachments of the components And Tada! We have a moving projectile that exists
in the world and something to work with!

THIS IS SIMILAR TO HOW WE SET UP THE SPRING ARM

Our magic projectile needs the following components


>Sphere
>Projectile Movement
>Particle System
Innit them with smart pointers the .h AND THEN in the constructor of the CPP
customize and set roots for those values

SOLUTION <ALSO quickly in your GIDEON SKELETON Add or find the arm socket
for the code below>

.H

//In our the PROTECTED section of .H Constructor of course


//Because the magic projectile properties ought only belong
//TObjectPtr is designed specifically for UObjects //SEE UPD
//Fundamental straightforeward RAW component decleration

Magic Projectile 2
UPROPERTY(VisibleAnywhere)
USphereComponent* SphereComp;

UPROPERTY(VisibleAnywhere)
UProjectileMovementComponent* ProjectileMovementComp;

UPROPERTY(VisibleAnywhere)
UAudioComponent* AudioComp;

UPROPERTY(VisibleAnywhere)
UParticleSystemComponent* ParticleSystemComp;

best practices : grouping components customized properties

.CPP

// Sets default values inside our constructor


AMagicProjectile::AMagicProjectile()
{
//Innit and Customization of all our components
//Instead of ticking boxing visually we simply write out and

// Set this actor to call Tick() every frame. You can turn
PrimaryActorTick.bCanEverTick = true;

//SPHERE COMP
SphereComp = CreateDefaultSubobject<USphereComponent>("Spher
SphereComp->SetCollisionProfileName("Projectile");
RootComponent = SphereComp;

//PARTICLE SYS
ParticleSystemComp = CreateDefaultSubobject<UParticleSystemC
ParticleSystemComp->SetupAttachment(RootComponent);

//AUDIO FX

Magic Projectile 3
AudioComp = CreateDefaultSubobject<UAudioComponent>("AudioCo
AudioComp->SetupAttachment(RootComponent);

//PROJECTILE MOVMEMENT
ProjectileMovementComp = CreateDefaultSubobject<UProjectileM
ProjectileMovementComp->bRotationFollowsVelocity = true;
ProjectileMovementComp->bInitialVelocityInLocalSpace = true;
ProjectileMovementComp->ProjectileGravityScale = 0.0f;
ProjectileMovementComp->InitialSpeed = 8000;
}

TO CAST A MAGIC PROJECTILE PT1 ‘Hello Magic Projectile’

1) PRESS KEYBOARD

2) EXECUTE GAME FUNCTION CODE

Iff you remember PIC then nice IF NOT hgo back and review it’s core for
interacting with the game via input.

Lets do step one binding our 3input for


calling the function

To Call the function we must set up the following:


> Engine Input ( Cast Projectile will be bound to this)
> Cast Projectile deceleration (.h) and definition (.cpp)
> Wire aforementioned in the player input component (char input component)
(char .cpp)
(
Solution for this part viewable in code for project solution)

//SIMPLE def in the ,H


void PrimaryAttack();

Magic Projectile 4
//Action event binding in The PIC (cpp con)
PlayerInputComponent->BindAction("PrimaryAttack",IE_Pressed,

//CPP DECLR
void AHero::PrimaryAttack()
{
BVFE//GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow,
}

TO CAST A MAGIC PROJECTILE PT2 ‘adding functionality’

This is great all we need to do now is add the functionality of spawning it in the
world, see commented areas for the breakdown of how what is happening
happens !

TSubclassOf<AActor> ProjectileClassParam; is needed in the header file for the


last line of the codeblock in the HERO CON then in the BP it must be set to what
projectile you want

This is happening in the CPP of the Hero

void AHero::PrimaryAttack()
{
//Lets shoot our simple magic projectile first4 Log It!
UE_LOG(LogTemp, Warning, TEXT("Player performed the Prim

//LOCATION N DIRECTION
//The Transform is the arrow rotation and the hand locat
FVector HandLocation = GetMesh()->GetSocketLocation("han
FTransform SpawnTransform = FTransform(GetControlRotatio

//ALWAYS SPAWN
//setting the spawn parameters to always spawn
FActorSpawnParameters SpawnParams;

Magic Projectile 5
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActor

//SPAWN ACTOR IN WORLD !! of type projectile class(uprop


//Projectile motion and action reaction are made in that
GetWorld()->SpawnActor<AActor>(ProjectileClass,SpawnTran
}

THE MAGIC OF COLLISIONS

In project preferences create the following new collision channel in the image,
yeah working with project settings can feel werid and stuff but it really is the norm

Magic Projectile 6
Now lets add the following line to our MAGIC PROJECTILE’s Constructor .CPP

//Setting this SPHERE HITBOX to our custom overlap channel {IMPO


SphereComp->SetCollisionProfileName("MagicProjectile");

So now our spawned projectile will block against world static items such as blocks
and meshes

//Something important to remember is our character is spawning t


//so its important to add "TSubclassOf<AActor> ProjectileClassPa

Magic Projectile 7
//and then set it to our target projectile visualizes in the edi

Magic Projectile 8
Interactive Barrel
Owner L LOMZO GAMING

Tags

BARREL
2 simple components
>mesh
>force

Innit both these components, In the .CPP constructor there is some write up for
the force, which is viewable in the project solution.

The important thing about this lesson is the “PostInitializeComponents”, this


occurs after the constructor and before begin play. It is my current understanding
that here is a optimal place to bind stuff.

//This runs after constructor and before beginplay


//We want this actor to have some kiunda functionality
virtual void PostInitializeComponents() override;

// Must be marked with ufunction in order to 'bind' the even


UFUNCTION()
void OnActorHit(UPrimitiveComponent* HitComponent, AActor* O

So here in my .H’s protected I defined a UFUNC aswell as stating “hey Ima use
POST INNIT COMP”

Interactive Barrel 1
void ABarrel::PostInitializeComponents()
{
// Don't forget to call parent function
Super::PostInitializeComponents();

//In postInnit we want to bind to ON HIT


MeshComp->OnComponentHit.AddDynamic(this, &ABarrel::OnActorH
}

Within the POST INNIT COMP func I added a binding that when this component is
hit I want to call whichever function I writeup for my OnActorHit. In this case of the
barrel I am perhaps gonna use the force component as well as some debug
messages

Interactive Barrel 2
Enhancing Magic Projectile
Owner L LOMZO GAMING

Tags

1) Destroy Magic Projectile once it collides after a few seconds


2) Wait 2seconds for the char to raise their hand then spawn magic projectile with
timer
3) Add a debounce so magic projectile is not spammed
4) fix so it aims off better the cursor that is the players eyes

Once the magic projectile collides with a static mesh, leave it be for two seconds
and then destroy it. This code will be added directly to the .cpp of magic projectile
and I believe other thangz aint needed

1)

MAGIC PROJECTILE SOLUTION

MAGIC PROJECTILE .CPP <destroy on hit>

//SNEAK THIS IN THE BEGIN PLAY


FTimerHandle LifeSpan;
float Lifespan =2.f;
GetWorldTimerManager().SetTimer(LifeSpan, this, &AMagicProje

/* THE REST CAN JUST BE SLAPPED IN */


// Function to handle destroying the projectile
void AMagicProjectile::DestroyProjectile()
{
Destroy();
}

Enhancing Magic Projectile 1


// Override the function to handle collisions
void AMagicProjectile::OnHit(AActor* OtherActor, UPrimitiveCompo
{
// Call the function to destroy the projectile
DestroyProjectile();
}

2)
HERO .CPP <will need some header stuff>

void AHero::PrimaryAttack()
{

PlayAnimMontage(PrimaryAttackAnimMonty);
GetWorldTimerManager().SetTimer(TimerHandle_PrimaryAttack,th
//GetWorldTimerManager().ClearTimer(&AHero::PrimaryAttack);
}

void AHero::PrimaryAttack_TimeElapsed()
{

//LOCATION N DIRECTION
//The Transform is the arrow rotation and the hand location
FVector HandLocation = GetMesh()->GetSocketLocation("hand_lS
FTransform SpawnTransform = FTransform(GetControlRotation(),

//ALWAYS SPAWN
//setting the spawn parameters to always spawn
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorColl

//SPAWN ACTOR IN WORLD !! of type projectile class(uprop exp

Enhancing Magic Projectile 2


//Projectile motion and action reaction are made in that cla
// We Spawn It :: We Log It!
UE_LOG(LogTemp, Warning, TEXT("Player performed the PrimaryA
GetWorld()->SpawnActor<AActor>(ProjectileClassParam,SpawnTra

3)
HERO.CPP <updating above with debounce>,<will need some header stuff>

void AHero::PrimaryAttack()
{
if (!bIsPrimaryAttackOnCooldown)
{
PlayAnimMontage(PrimaryAttackAnimMonty);
GetWorldTimerManager().SetTimer(TimerHandle_PrimaryAttac

bIsPrimaryAttackOnCooldown = true;
GetWorldTimerManager().SetTimer(TimerHandle_PrimaryAttac
}
}

void AHero::ResetPrimaryAttackCooldown()
{
bIsPrimaryAttackOnCooldown = false;
}

void AHero::PrimaryAttack_TimeElapsed()
{
FVector HandLocation = GetMesh()->GetSocketLocation("hand_lS
FTransform SpawnTransform = FTransform(GetControlRotation(),

FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorColl

Enhancing Magic Projectile 3


UE_LOG(LogTemp, Warning, TEXT("Player performed the PrimaryA
GetWorld()->SpawnActor<AActor>(ProjectileClassParam, SpawnTr
}

Enhancing Magic Projectile 4


Interaction Component !
Owner L LOMZO GAMING

Tags

https://docs.unrealengine.com/5.0/en-US/interfaces-in-unreal-engine/
Literally Read The Documentation

There is NUANCE in applying interface to pure bp things and cpp pure/hybrid


things

Interactable_Interface.h

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Interactable_Interface.generated.h"

// This class does not need to be modified.


UINTERFACE(MinimalAPI)
class UInteractionInterface : public UInterface
{
GENERATED_BODY()
};

//my custom interface stuff


class TOMMY_L_API IInteractionInterface

Interaction Component ! 1
{
GENERATED_BODY()

// Add interface functions to this class. This is the class


public:

//INTERFACE FUNCTION
UFUNCTION(BlueprintNativeEvent)
void DoInteraction (APawn* InstigatorPawn);
};

So this interface does not really have a CPP, this is like a shared list of things that
all classes that implement {this} interface will have. That list of thing starting at the
bottom.

This is really cool because the top half we’re creating a UOBJECT and in the
bottom we are working with it in the I-Interfacestuff.

ON TO THE INTERACTION COMPONENT

Our interaction component will belong to the player and give them the funconitlity
to interact with the world. How does this happen?
>Interaction comp offloads code off of our character
>Interaction comp has function interact, where it casts a ray from our chars eyes
forward
>If the ray hits any CPP actors that implement our interface have them call their
version of that function

INTERACTION COMPONENT

.H

void PrimaryInteract();//A FUNCTION THAT ALL HOLDERS OF THIS COM

Interaction Component ! 2
CPP

void UInteractionComponent::PrimaryInteract()
{

//Our interacting should shoot out a raycast starting at our

//HIT OUTPUT
FHitResult hit;

//SET UP COLLISION
FCollisionObjectQueryParams MyColParam;
MyColParam.AddObjectTypesToQuery(ECC_WorldDynamic);
MyColParam.AddObjectTypesToQuery(ECC_PhysicsBody);

//Getting RayTrace Start


FVector EyeLocation;
FRotator EyeRotation;
AActor* MyOwner = GetOwner();
MyOwner->GetActorEyesViewPoint(EyeLocation,EyeRotation);
//Getting RayTrace End
FVector EndLocation = EyeLocation + (EyeRotation.Vector() *

//Do Da Cast
//GetWorld()->LineTraceSingleByObjectType(hit,EyeLocation,En

bool bIsBlockingHit = GetWorld()->LineTraceSingleByObjectTyp


//-------------------------
//WE HIT SOMETHING

IInteractionInterface* ReactingObj = Cast<IInteractionInterf

Interaction Component ! 3
if (ReactingObj)
{
APawn* MyInstigatingPawn = Cast<APawn>(MyOwner);

UE_LOG(LogTemp, Warning, TEXT("INTERFACE HIT!!!!!!!"));


ReactingObj->DoInteraction_Implementation(MyInstigatingP
}

//FColor LineColor = bIsBlockingHit ? FColor :: Green : FCol


DrawDebugLine(GetWorld(),EyeLocation,EndLocation,FColor::Red

Remember things like adding on to class headers with a comma to include a


implemented interface

for example our barrel

In the header add “, public IInteractionInterface”

.CPP

class TOMMY_L_API ABarrel : public AActor, public IInteractionIn


{
GENERATED_BODY()

void ABarrel::DoInteraction_Implementation(APawn* InstigatorPawn


{
IInteractionInterface::DoInteraction_Implementation(Instigat

FString Message = TEXT("BARREL Called Interface!");


GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::White, Me

Interaction Component ! 4
ForceComp->FireImpulse();
}

Why is there ‘I’ and ‘U’, read the documentation

https://docs.unrealengine.com/5.0/en-US/interfaces-in-unreal-engine/

Interaction Component ! 5

You might also like