The tank's moving now!

Hi There!

In this lecture, we make the tank to take the player’s input and move accordingly!

Prepare for this lecture, by googling some bits like quaternions and gimbal locking, it’ll help you a lot and you might get less confused.

UE_EDITOR-

Tanks’ initial position, it’s just like normal games, pressing “W” will move it forward, and “S” will move it backward, " A" rotates it towards the left, and “D” rotates it towards the right. I can’t insert videos tho to show it.

VS Code-

Header File-

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

#pragma once

#include "CoreMinimal.h"
#include "PawnBase.h"
#include "PawnTank.generated.h"

class USpringArmComponent;
class UCameraComponent;
UCLASS()
class TOONTANKS_API APawnTank : public APawnBase
{
	GENERATED_BODY()

private:

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
	USpringArmComponent* SpringArm;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
	UCameraComponent* Camera;
	
	FVector MoveDierection;
	FQuat RotationDierection;

	float MoveSpeed = 500.f;
	float RotateSpeed = 250.f;

	void CalculateMoveInput(float Value);
	void CalculateRotateInput(float Value);

	void Move();
	void Rotate();

public:

	APawnTank();

	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
};

In the header file, I’ve made 2 components for the camera, spring arm, and camera component. 4 functions and 4 variables.

The MoveSpeed variable is the speed at which the tanks gonna move, the RotateSpeed variable determines the speed of rotation.

CalculateMoveInput(float Value) takes a value depending upon the scale in the project settings,
and then decides in which direction the tank shall move and stores it in FVector MoveDierection.

CalculateRotateInput(float Value) takes a value too depending upon the scale in the project settings and tells in which direction the tank must rotate FQuat RotationDierection. FQuat is used to represent the rotation of an object in its 3D space.

Move() implements the movement and Rotate() implements the rotation. Ahead to C++!!

C++ File-

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


#include "PawnTank.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"

APawnTank::APawnTank()
{
    SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("Spring Arm"));
    SpringArm->SetupAttachment(RootComponent);

    Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
    Camera->SetupAttachment(SpringArm);
}

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

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

    Rotate();
    Move();
}

// Called to bind functionality to input
void APawnTank::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
    PlayerInputComponent->BindAxis("MoveForward", this, &APawnTank::CalculateMoveInput);
    PlayerInputComponent->BindAxis("Turn", this, &APawnTank::CalculateRotateInput);
}

void APawnTank::CalculateMoveInput(float Value)
{
    MoveDierection = FVector(Value * MoveSpeed * GetWorld()->DeltaTimeSeconds, 0, 0);
    UE_LOG(LogTemp, Warning, TEXT("%f"), GetWorld()->DeltaTimeSeconds);
}

void APawnTank::CalculateRotateInput(float Value) 
{
   float RotateAmount = Value * RotateSpeed * GetWorld()->DeltaTimeSeconds;
   FRotator Rotation = FRotator(0, RotateAmount, 0);
   RotationDierection = FQuat(Rotation);
}

void APawnTank::Move() 
{
    AddActorLocalOffset(MoveDierection, true);
}

void APawnTank::Rotate() 
{
    AddActorLocalRotation(RotationDierection, true);
}

Moving to my constructor first, I have set the SpringArm component to inherit from the CapsuleComponent and the camera to inherit from the SpringArm.

I’m calling the Move() and Rotate() function in the Tick so the position of the tank is changed every frame.

Then next function is SetupPlayerInputComponent(), this function allows us to set up custom input(s) bindings. If MoveForward AxisMapping is called, then then the CalculateMoveInput() function is called, and if Turn AxisMapping is called then the CalclutaRotateInput() is called.

CalculateMoveInput() calculates in which direction the tank must move and it makes it framerate independent, CalclutaRotateInput() calculates in which direction the tank must rotate.

Move() and Rotate() function Implements these Movements and Rotations

Phew… that was quite a lot of talking.

Previous ToonTanks post: My first child C++ classes

Thanks for reading,
Good BYE!!

3 Likes

This is such a fun section. I tried turning this into the wii tank game. I built the first 10 levels and made enemy tanks. I just need to work on the enemy tank ai.

1 Like

True! I really like this section a lot too. Good luck with the Wii game. So the game’s still in progress, I don’t know much about AI(yet) so cant’ tell much about it.

1 Like

Yeah it’s on hold right now but I made all the same 10 levels that were in the game. AI is tough. I’m still trying to figure it out :sweat_smile:

1 Like