- Blood Maiden -

Project Details
  • Project Length: 6 Weeks

  • Team Size: 16 people

  • Engine: Unreal Engine 5

  • Planning: Miro, Jira & Discord

  • Project Length: 6 Weeks

  • Team Size: 16 people

  • Engine: Unreal Engine 5

  • Planning: Miro, Jira & Discord

  • Project Length: 6 Weeks

  • Team Size: 16 people

  • Engine: Unreal Engine 5

  • Planning: Miro, Jira & Discord

  • My Roles: Programmer

  • Grappling Hook

  • Blood to Speed Curve

  • Other Blueprinting

  • My Roles: Programmer

  • Grappling Hook

  • Blood to Speed Curve

  • Other Blueprinting

  • My Roles: Programmer

  • Grappling Hook

  • Blood to Speed Curve

  • Other Blueprinting

Grappling Hook

During this project I spent most of my time working on the grappling hook ability.
In order to get a good feel from all angles I had to come up with a solution to increase the pull force of the grapple when grappling from an inter-cardinal direction, my solution to this was to increase the pull force with a bell-curve equation.

When the player would grapple I would check the down vector of the grapple point with a vector pointing at the player to determine the dot product which I used to determine where on the bell-curve the player is and apply force accordingly.

Show Related Code

.H

.CPP

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/SphereComponent.h"
#include "Interfaces/Interactable.h"
#include "Interfaces/Interactor.h"
#include "GrappleActor.generated.h"

class UNiagaraSystem;
UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSuccessfullGrapple, bool, grappled, FVector, GrapplePoint);

UCLASS(Blueprintable, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class UEPROJECT_API AGrappleActor : public AActor, public IInteractable, public IInteractor
{
	GENERATED_BODY()

public:
	AGrappleActor();

	UPROPERTY(BlueprintAssignable)
	FOnSuccessfullGrapple OnSuccessfullGrapple;
	
	UPROPERTY(VisibleAnywhere, Blueprintable, Category = "Collision")
	USphereComponent* CollisionSphere;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float Division = 50;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float MinPower = 1000;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float GrappleRadius = 500;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float GrapplePower = 3000;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Grapple")
	float DelayBeforeGrapple = 0.25f;
	
	
protected:
	virtual void BeginPlay() override;

	UPROPERTY(VisibleAnywhere)
	AActor* TargetedGrapple = nullptr;

	UPROPERTY(VisibleAnywhere)
	FVector Direction;

	UPROPERTY(VisibleAnywhere)
	ACharacter* InteractorCharacter;
	
public:
	virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;
	virtual void NotifyActorEndOverlap(AActor* OtherActor) override;

	virtual void Tick(float DeltaTime) override;
	
	virtual void Interact(const TScriptInterface<IInteractor>& Interactor) override;

private:
	FTimerHandle GrappleDelayHandle;
}

Show Related Code

.H

.CPP

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/SphereComponent.h"
#include "Interfaces/Interactable.h"
#include "Interfaces/Interactor.h"
#include "GrappleActor.generated.h"

class UNiagaraSystem;
UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSuccessfullGrapple, bool, grappled, FVector, GrapplePoint);

UCLASS(Blueprintable, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class UEPROJECT_API AGrappleActor : public AActor, public IInteractable, public IInteractor
{
	GENERATED_BODY()

public:
	AGrappleActor();

	UPROPERTY(BlueprintAssignable)
	FOnSuccessfullGrapple OnSuccessfullGrapple;
	
	UPROPERTY(VisibleAnywhere, Blueprintable, Category = "Collision")
	USphereComponent* CollisionSphere;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float Division = 50;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float MinPower = 1000;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float GrappleRadius = 500;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float GrapplePower = 3000;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Grapple")
	float DelayBeforeGrapple = 0.25f;
	
	
protected:
	virtual void BeginPlay() override;

	UPROPERTY(VisibleAnywhere)
	AActor* TargetedGrapple = nullptr;

	UPROPERTY(VisibleAnywhere)
	FVector Direction;

	UPROPERTY(VisibleAnywhere)
	ACharacter* InteractorCharacter;
	
public:
	virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;
	virtual void NotifyActorEndOverlap(AActor* OtherActor) override;

	virtual void Tick(float DeltaTime) override;
	
	virtual void Interact(const TScriptInterface<IInteractor>& Interactor) override;

private:
	FTimerHandle GrappleDelayHandle;
}

Show Related Code

.H

.CPP

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/SphereComponent.h"
#include "Interfaces/Interactable.h"
#include "Interfaces/Interactor.h"
#include "GrappleActor.generated.h"

class UNiagaraSystem;
UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSuccessfullGrapple, bool, grappled, FVector, GrapplePoint);

UCLASS(Blueprintable, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class UEPROJECT_API AGrappleActor : public AActor, public IInteractable, public IInteractor
{
	GENERATED_BODY()

public:
	AGrappleActor();

	UPROPERTY(BlueprintAssignable)
	FOnSuccessfullGrapple OnSuccessfullGrapple;
	
	UPROPERTY(VisibleAnywhere, Blueprintable, Category = "Collision")
	USphereComponent* CollisionSphere;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float Division = 50;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float MinPower = 1000;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float GrappleRadius = 500;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Grapple")
	float GrapplePower = 3000;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Grapple")
	float DelayBeforeGrapple = 0.25f;
	
	
protected:
	virtual void BeginPlay() override;

	UPROPERTY(VisibleAnywhere)
	AActor* TargetedGrapple = nullptr;

	UPROPERTY(VisibleAnywhere)
	FVector Direction;

	UPROPERTY(VisibleAnywhere)
	ACharacter* InteractorCharacter;
	
public:
	virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;
	virtual void NotifyActorEndOverlap(AActor* OtherActor) override;

	virtual void Tick(float DeltaTime) override;
	
	virtual void Interact(const TScriptInterface<IInteractor>& Interactor) override;

private:
	FTimerHandle GrappleDelayHandle;
}

Blood to Speed Curve

Since we wanted to have the players speed be effected by the amount of blood remaining in their blood-meter I set up some blueprints that read unreal engine curves, the designers could then edit the curve to their liking and have the player speed decrease in whatever manner they deemed fit.

Other Blueprinting

Since this was our first game project in unreal engine 5 a lot of the programming was done in blueprint over C++ to make more progress faster as we were still inexperienced with C++ and unreal engines way of working at this point in time.

Other than the Blood to Speed Curve I also created drop down platforms, Dash ability, Coyote time and the weakened state where the player has lost all blood resource and is now able to die from taking damage.

Reflections

With this project being the first unreal engine 5 project a lot of time went in to understanding its quirks and how it differs from unity's C# language, In this project we had dedicated project managers that up held the Jira and got us to fill out our tasks and partake in team management meetings which was different from our other projects, all of this combined to make things take longer than they would, had we been more familiar with the work environment.

Another problem we ran in to was the game size was far to large and we had to spend quite some time determining the cause if the inflated build size which was well over the imposed limit size limit of our Itch page.

Game Trailer
Smooth Scroll
This will hide itself!

Halldorkari13@gmail.com

0733920759

Contact:

Halldorkari13@gmail.com

0733920759

Contact:

Halldorkari13@gmail.com

0733920759

Contact: