TFCOE: Devlog #1

Conor Kirkby

05/11/25

" title="Devlog1" allowfullscreen>

Click to Enlarge

TLDR

What Happened

Hey everyone, this marks the first devlog for my personal project, The Forgotten City of Echronia. A monumentous occasion. Lets waste no time and get straight into the meat. So what did I do for this session? Of course it was mainly setting up the Unreal Project, Github, GDD and management boards. However I did get do some hands on work with the project. The main thing I needed to do for this at present was to figure out how to use sprites correctly with Unreal. As Unreal is primarily used for 3D it might be an unusual choice as much more lightweight engines such as Unity or Godot exist.

The answer is simply... Its what I am most comfortable with, although I did spend a while weighting them against each other when deciding if I should make either a 2D or 3D game. In the end I chose the middle choice and went 2.5D. Unreal Engine is not without its hurdles however, so I actually watched a tutorial on how to effectively setup the project and also learned how to use a custom plugin called Paper ZD, which greatly simplifies the process.

The tutorial I used can be found here and was made by Cobra Code, so a special thank you to them:

This tutorial helped me create a simple character, that can walk around using 8 Directional movement. I still have not decided if I want to stick with this 8 directions or move to a more simpler 4 directional movement system but its something to think about in the future. Once the tutorial was finished, I then took all I had learned and converted it to C++ which marked the end of the first session.

Code

				
					#pragma once

					#include "CoreMinimal.h"
					#include "PaperZDCharacter.h"
					#include "EnhancedInputSubsystems.h"
					#include "PlayerCharacter.generated.h"

					/**
					* 
					*/
					UCLASS()
					class TFCOE_API APlayerCharacter : public APaperZDCharacter
					{
						GENERATED_BODY()

						protected:

						// Input Mapping & Actions // 
						UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input|MappingContext")
						UInputMappingContext* MappingContext = nullptr;
						UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input|Actions")
						UInputAction* MoveAction = nullptr;
						UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input|Actions")
						UInputAction* SprintAction = nullptr;
						UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input|Actions")
						UInputAction* InteractAction = nullptr;

						// Settings
						UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings|Movement")
						float WalkSpeed = 400.0f;
						UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Settings|Movement")
						float SprintSpeed = 700.0f;

						// Components
						UPROPERTY()
						UCharacterMovementComponent* MovementComponent = nullptr;
						
						// Functions
						virtual void BeginPlay() override;
						virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;

						void InitialiseMovementComponent();
						
						// Input Functions
						void MoveTrigger(const FInputActionValue& Value);
						void SprintTrigger();
						void SprintEnd();
						void InteractTrigger();
					};
				
			
				
					#include "PlayerCharacter.h"
					#include "EnhancedInputComponent.h"
					#include "GameFramework/CharacterMovementComponent.h"


					void APlayerCharacter::BeginPlay()
					{
						Super::BeginPlay();

						// Gets the movement component and stores it for future use.
						InitialiseMovementComponent();
					}

					// Initialises the player input system
					void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
					{
						Super::SetupPlayerInputComponent(PlayerInputComponent);

						if (const APlayerController* PlayerController = Cast(GetController()))
						{
							if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem(PlayerController->GetLocalPlayer()))
							{
								if (MappingContext)
								{
									Subsystem->AddMappingContext(MappingContext, 0);
								}
							}
						}

						// Initialises the action bindings 
						if (UEnhancedInputComponent* EnhancedInputComponent = Cast(PlayerInputComponent))
						{
							// Insert Action bindings here

							// Binds the movement action to the input variables
							if (MoveAction)
							{
								EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &APlayerCharacter::MoveTrigger);
							}

							// Binds the interact action to the triggered function
							if (InteractAction)
							{
								EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Started, this, &APlayerCharacter::InteractTrigger);
							}

							// Binds the sprint action to the trigger for starting, and the completed to the end function
							if (SprintAction)
							{
								EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &APlayerCharacter::SprintTrigger);
								EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &APlayerCharacter::SprintEnd);
								EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Canceled, this, &APlayerCharacter::SprintEnd);
							}
							
						} 
					}

					void APlayerCharacter::InitialiseMovementComponent()
					{
						// Gets and caches the movement component for use 
						if (UCharacterMovementComponent* CharacterMovementComp = GetCharacterMovement())
						{
							MovementComponent = CharacterMovementComp;
						}
					}

					void APlayerCharacter::MoveTrigger(const FInputActionValue& Value)
					{
						const FVector2D MovementVector = Value.Get();
						
						// Movement for X vector
						AddMovementInput(FVector(1, 0, 0), MovementVector.X);

						// Movement for Y vector
						AddMovementInput(FVector(0, 1, 0), MovementVector.Y);
					}

					void APlayerCharacter::SprintTrigger()
					{
						if (MovementComponent)
						{
							// Sets the movement speed to be the sprint speed on sprint start
							MovementComponent->MaxWalkSpeed = SprintSpeed;
						}
					}

					void APlayerCharacter::SprintEnd()
					{
						if (MovementComponent)
						{
							// Sets the movement speed to be the walk speed on the sprint end
							MovementComponent->MaxWalkSpeed = WalkSpeed;
						}
					}

					void APlayerCharacter::InteractTrigger()
					{
						UE_LOG(LogTemp, Warning, TEXT("The player has interacted with something"))
					}

				
			
Code blocks / snippets available on desktop.
Go Back