Unreal Stuffs

I’ve been playing too much xcom and I felt like my c++ skills were waning so I thought it would be a fun quick project to quickly spin up a turn based squad commander system.

There’s probably a way to make these go away…

The camera

First thing that is distinctive about xcom is that it’s an isometric game, therefore the camera is fixed above the level and travels along various levels of the map. To achieve this effect I made a quick camera pawn that does two things: Ray traces to a fixed height above the ground and constantly aligns itself to a specific pre-set orientation.

Instead of going crazy with pre-mades I just threw a camera component onto a pawn class with a few pre-set parameters.

Header code:

  //CLASS BLUEPRINT EXPOSED PROPERTIES
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "2D Camera Settings")
		float BaseHeightOffGround;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "2D Camera Settings")
		float CameraAlignmentRate;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "2D Camera Settings")
		float HeightCorrectionRate;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "2D Camera Settings")
		FRotator BaseCameraRotation;
	//END CLASS EXPOSED PROPERTIES

	//START COMPONENTS
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PrimaryCamera", meta = (AllowPrivateAccess = "true"))
		UCameraComponent* PlayerCamera;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Collision", meta = (AllowPrivateAccess = "true"))
    	UCapsuleComponent* CameraCollider;

The tick function I have two lerps: 1.) for the current camera orientation and 2.) for the result of a down racytrace + a fixed offset.

//Ensure we're rotated properly to the desired world rotator that the user specified
    FRotator currentRot = GetActorRotation();
    FQuat newRotation =  FQuat::Slerp(currentRot.Quaternion(), BaseCameraRotation.Quaternion(), CameraAlignmentRate*DeltaTime);
    SetActorRotation(newRotation);
    // Get the world object
    UWorld* World = GetWorld(); 
    // Check if the world exists
    if (World)
    {
        FVector Start = GetActorLocation();
        FVector End = Start + FVector::DownVector * BaseHeightOffGround*10.0f;
        FHitResult Hit;
        FCollisionQueryParams QueryParams;
        QueryParams.AddIgnoredActor(this); 
        bool bHit = World->LineTraceSingleByChannel(
            Hit,                
            Start,             
            End,              
            ECC_Visibility,     
            QueryParams         
        );
        if (bHit)
        {
            FVector newWorldPos = FMath::Lerp(Start, Hit.Location + FVector(0,0,BaseHeightOffGround), HeightCorrectionRate*DeltaTime); 
            DrawDebugLine(
                GetWorld(),
                Start,
                Hit.Location,
                FColor(255, 0, 0),
                false, -1, 0,
                12.333
            );
            SetActorLocation(newWorldPos);
        }
    }

THE RESULTS!

Note: the red line is just for my debugging purposes. Also the camera will not be visible in game.

The DSP engineer in me is balking at the casual use of a delta time and a linear interpolation. But, we’re on a PC running at low data rates (60hz!?!? pfffffff I could get this running at 24khz) and variable frame sizes so while I keep thinking “I could optimize this to be less MIPS” I think I’ll just press on…

Commanding/ Game structure

In xcom the turns are play out that you select a squad member, choose their action, move to the next squad member, choose their action, until you have no more squad members, then your turn is over.

Now there’s a few ways I could implement the squad mechanics. Specifically the way that each squad member gets controlled and how the player controller interacts with them. I could have the user’s controller re-posses each pawn upon selecting them (which might save memory but increase the work upon possession). However, I would still need to perform path finding to move the character to a specific location. Instead I think the way I want to play it is to have every squad member owned by an AI controller that receives broadcasts from the player controlled camera pawn. Below is my rough diagram (I think there’s a gamemode state in there that I need to throw in but generally I think this is fine)

www.drawio.com FYI

In addition to handling the general flow of the game I think the other side is that this sets the game up for multiplayer from the start.

The command/game state messages I think I’ll probably make delegates in the game mode that the controllers can subscribe to. Then the deaths of squad members and selections I think I’ll push to to the controllers? My thought here is:

I’ll probably jump back on this tomorrow and start coding up the events and perform in a test or two.

Leave a Reply