An game where you need to escape a expanding black hole. Dodge asteroids as you try to reach the end goal before the dark hole engulfs you. I was responsible for all the asset implementation(Sound, 3D Assets, UI, etc.) and functionality.

Source Code

Key Contributions

  • Designed and programmed a custom Pawn movement controller in C++ for responsive, smooth character handling.
  • implemented a time-pressure system that gets closer to the player, accelerating over time (black hole).
  • Implemented gameplay features like player state handling, item pickups health system etc.
  • Implemented all the UI systems(Player HUD, Dialogue UI, Options Screen, etc.)
  • Implemented Settings with save functionality.
  • Perforce Server setup and maintenance.
  • Implemented all Sound and VFX events.

Player Controller

I created a custom Pawn controller in C++, with some funny rotation where the planet faces towards your input. We always move forwards and we increase speed overtime, with movement limited to Up/Down Left/Right, with the camera bounds as its movement limits.

I realized that the physics that are handled by the movement component sweeps only when it registers movement. Therefor we need to call AddMovementInput to simulate physics, as we can’t enable “Simulate Physics” option on the capsule component.

void APlanetController::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	
	if (IsDead)
	{
		return;
	}

	//We add a bit of movement input to resolve  physics as pawns cannot have simulate physics enabled.
	AddMovementInput(FVector::ForwardVector, 0.01f, true);
	
	if (HasTeleported)
	{
		auto Location = GetActorLocation();
		SpawnLocation = FVector2D(Location.Y, Location.Z);
		MovementComponent->Velocity = FVector::ZeroVector;
	}
	auto CurrentLocation = GetActorLocation();
	
	auto Max = SpawnLocation + MaxExtents;
	auto Min = SpawnLocation - MaxExtents;
	auto ClampedY = FMath::Clamp(CurrentLocation.Y, Min.X, Max.X);
	auto ClampedZ = FMath::Clamp(CurrentLocation.Z, Min.Y, Max.Y);

	ForwardSpeed = FMath::Clamp(ForwardSpeed + ForwardAcceleration * DeltaTime,
		InitialSpeed,
		ForwardMaxSpeed);

	SetActorLocation(FVector(CurrentLocation.X + ForwardSpeed, ClampedY, ClampedZ));

	auto Velocity = MovementComponent->Velocity;
	auto NewRotation = Velocity.ToOrientationRotator();

	NewRotation.Yaw = GetActorRotation().Yaw + SpinSpeed * DeltaTime;

	SetActorRotation(NewRotation);
}

I needed to have the camera separate from the player so I can implement more custom following logic easier. We only want to follow the planet on one axis but we can retain the rest.

void APlayerCamera::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (TargetPawn == nullptr)
	{
		return;
	}

	auto ActorLocation = GetActorLocation();
	auto PlanetControllerLocation = TargetPawn->GetActorLocation();
	auto TargetLocation = FVector(PlanetControllerLocation.X, ActorLocation.Y, ActorLocation.Z);
	SetActorLocation(TargetLocation);
}

Black Hole System

Black Hole BP Implemented a time-pressure system that gets closer to the player, accelerating over time. If it touches the player the game is over. It can be temporarily slowed by picking up the hourglasses.

The UI bar at the bottom tracks the black hole, player and the end goal. Progress Tracker

Final Thoughts

This was a fun jam to work on, where I learn’t the most about using perforce with unreal and sharing the project with non-programmer collaborators. Things like sharing binaries, how to share plugins, etc.