Friday, September 23, 2016

Linear Interpolation (LERP) with C++ and Unreal Engine 4.13.0


In Unreal Engine 4 you will eventually need Linear Interpolation between two values to do something like ping pong between two float values across Time Delta. I wrote a "ghetto" function that does this and takes the arguments min, max, factor (scale), and then the value itself, which it increments/decrements accordingly. You can also do this with trig functions across Delta Time to achieve a similar effect. You can always get Delta Time from the Overridable Tick Method.

Here is the code:

float GameHelper::IncrementLerp(float x, float v) {
    return v+=x;
}

float GameHelper::xLerp (float mMin, float mMax, float mFactor, float value) {
    if (value>=mMin && goBackwards){
        value = IncrementLerp(-mFactor,value);
        if (value<=mMin) {
            goForwards = true;
            goBackwards = false;
        }
    } else if (goForwards && value<=mMax) {
        value = IncrementLerp(mFactor,value);
        if (value>=mMax) {
            goBackwards = true;
            goForwards = false;
        }
    }
    return value;
}

I use it for sky lighting in a game I am working on. The sky light appears to be pulsating from 0.7f to 2.7f intensity. I use this function and expose other functions in Blueprints. HD demo of my latest game, Jumper utilizing the pulsating::



Monday, September 19, 2016

Get an ENUM value from an Enemy AI Behaviour Tree in Unreal Engine 4.13.0 using C++

Often we intermingle C++ and Blueprints, and need for the two to communicate. With Behavior Trees, using ENUMs is an everyday occurrence and on occasion we need to access said values in C++ Code. Below a Service I created called Check For Player which overrides base UBTService, uses the TickNode to check for the existence of a Player that the EnemyAI sees.

See below:


void UBTService_CheckForPlayer::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
AEnemyAI *EnemyPC = Cast<AEnemyAI>(OwnerComp.GetAIOwner());

if ( EnemyPC) {
        AJumperCharacter *Enemy = Cast<AJumperCharacter>(GetWorld()->GetFirstPlayerController()->GetPawn());
        if (!Enemy) {
            return;
        } else if (Enemy && EnemyPC->tChar->EnemyLife>0) {
                OwnerComp.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Object>(EnemyPC->PatrolKeyID,EnemyPC);
                OwnerComp.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Object>(EnemyPC->EnemyKeyID,Enemy);
        }
        uint8 EnemyMode = OwnerComp.GetBlackboardComponent()->GetValueAsEnum("EnemyModeBB");
FString str = FString::FromInt(EnemyMode);
EnemyPC->tChar->SetMode(EnemyMode);
/*
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, str);
*/
}

}
My EnemyCharacter.cpp referenced above has different modes. Since I get an unsigned int8 from GetValueAsEnum("EnemyModeBB"), which is my enum variable in my BehaviourTree , I need to translate the uint8 to an ENUM on my EnemyCharacter class. This isn't necessary and you can case it out but since EnemyCharacter is my main class with all of the EnemyProperties, I want to send the information back.  See below:

void AEnemyCharacter::SetMode(uint8 m) {
    if (Mode!=EnemyMode::Hit)
        switch (m) {
            case 0:SetMode(EnemyMode::Attack);  break;
            case 1:SetMode(EnemyMode::Dead);  break;
            case 2:SetMode(EnemyMode::Flee);  break;
            case 3:SetMode(EnemyMode::Hit);  break;
            case 4:SetMode(EnemyMode::Idle);  break;
            case 5:SetMode(EnemyMode::Patrol);  break;
            case 6:SetMode(EnemyMode::Pursue);  break;
            case 7:SetMode(EnemyMode::Talk);  break;
            case 8:SetMode(EnemyMode::Taunt);  break;
            default:SetMode(EnemyMode::Pursue);  break;
break;
        }

}


Here is the definition of EnemyMode in EnemyCharacter.cpp class:

UENUM(BlueprintType)
enum class EnemyMode : uint8
{
    Attack      UMETA(DisplayName="Attack"),
    Dead        UMETA(DisplayName="Dead"),
    Flee        UMETA(DisplayName="Flee"),
    Hit         UMETA(DisplayName="Hit"),
    Idle        UMETA(DisplayName="Idle"),
    Patrol      UMETA(DisplayName="Patrol"),
    Pursue      UMETA(DisplayName="Pursue"),
    Talk        UMETA(DisplayName="Talk"),
    Taunt       UMETA(DisplayName="Taunt")

};

Also, here is a screenshot for the ENUM:


The variable definition in my BehaviourTree BlackBoard (zombieBB):


Wednesday, June 15, 2016

Custom Font(s) for TextView in Android (Java)

Using customized fonts in Android OS is not supported by default. You have to essentially put your fonts in an assets folder in TTF or OTF format, then reference it in an extended widget of EditText/TextView or whichever widget you'd want to use.

First copy your ttf to your /assets/ directory in your project root.

The next thing you need to do is create a helper class, mine is called TextViewHelper.java ->

package com.yourdomain.yourapp.helper;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
import com.yourdomain.yourapp.R;

public class TextViewHelper extends TextView {
    private static final String TAG = "TextViewHelper";
    private static final String fontname = "SourceSansPro-Semibold.ttf";

    public TextViewHelper(Context context) {
        super(context);
    }

    public TextViewHelper(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public TextViewHelper(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setCustomFont(context, attrs);
    }

    private void setCustomFont(Context ctx, AttributeSet attrs) {
        TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewHelper);
        String customFont = a.getString(R.styleable.TextViewHelper_customFont);
        setCustomFont(ctx);
        a.recycle();
    }
    /* force custom font */
    public boolean setCustomFont(Context ctx) {
        Typeface tf = null;
        try {
        tf = Typeface.createFromAsset(ctx.getAssets(), fontname);  
        } catch (Exception e) {
            Log.e(TAG, "Could not get typeface: "+e.getMessage());
            return false;
        }

        setTypeface(tf);  
        return true;
    }

    public boolean setCustomFont(Context ctx, String asset) {
        Typeface tf = null;
        try {
        tf = Typeface.createFromAsset(ctx.getAssets(), asset);  
        } catch (Exception e) {
            Log.e(TAG, "Could not get typeface: "+e.getMessage());
            return false;
        }

        setTypeface(tf);  
        return true;
    }

}

Mine forces a custom font programmatically. Though there are many ways to skin this cat, this way I am assuming all fonts need to be the same, and I am using only one. You could theoretically expose and use numerous fonts instead of just one, but this simply does only one, SourceSansPro-Semibold.ttf.

The next and final step is you have to reference it from your layout.xml(s). See below sample:

Wherever you have <TextView /> tags referenced change it to:

            <com.yourdomain.yourapp.helper.TextViewHelper
                android:id="@+id/hm_vpn_txt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_alignParentLeft="true"
                android:textColor="@color/test_color"
                android:textSize="16sp"
                android:text="@string/yourstring" />

And voila! You have custom fonts.

Tuesday, June 14, 2016

C++ Unreal Engine 4 -> Adjust Field of View Camera

This simple function will change your FOV in UE4 in your code. Field of View is the camera's viewport of how much you want to include in your view. The lower the FOV the more magnified everything will appear to be, the higher, it'll show more in the viewport.

This function takes one parameter float x which is the FOV value:

float AGameController::ToggleCamera(float x) {
    FString str = FString::SanitizeFloat(x);
        APlayerController* PController= UGameplayStatics::GetPlayerController(GetWorld(), 0);
        PController->ConsoleCommand(TEXT("fov " + str), true);
    return x;

}

Thursday, May 12, 2016

Determine if device is an Amazon/Fire TV in Unity 3D

Often when you use the same apk for google play and amazon stores and you need to determine at run time whether your device is running Android OS or a Kindle on Fire OS. You may need to even further determine if the device is an Amazon Fire TV or Android TV app.

In Unity3D you can often use SystemInfo.deviceModel, and put it into if/then or case and set appropriate flags. Then you can implement google play, game circle, forward to the appropriate store for rating an app, etc.:

public static string getDevice() {
if (  SystemInfo.deviceModel.ToLower().Contains("aftb")) {
isAmazon = true;
return "Fire TV";
}
        if (  SystemInfo.deviceModel.ToLower().Contains("amazon")) {
isAmazon = true;
return SystemInfo.deviceModel;
}
isAmazon = false;
return SystemInfo.deviceModel;
}