Friday, November 1, 2019

Time Calculator

I don't know why there is no program, which is able to set source time and based on the time difference calculate destination's time.

LA is -16 hours slower than South Korea. To make comfortable time for each others, I had to calculate -16 hours but as you know I'm a programmer and lazy.

So I created a program to calculate for me.




Source is really simple.

===================================

public partial class frmTimeCalculator : Form
{
    public frmTimeCalculator()
    {
        InitializeComponent();
    }


    private void frmTimeCalculator_Load(object sender, EventArgs e)
    {
        sourceTime.CustomFormat = "MM/dd/yyyy hh:mm:ss tt";
        sourceTime.Format = DateTimePickerFormat.Custom;

        destTime.CustomFormat = "MM/dd/yyyy hh:mm:ss tt";
        destTime.Format = DateTimePickerFormat.Custom;
    }

    private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
    {
        DateTime laTime = sourceTime.Value.AddHours(-16);
        destTime.Value = laTime;
    }
}

Thursday, October 31, 2019

Quackit Tutorials

https://www.quackit.com/

Unity : FPS Microgame Analysis -1-

Unity released very good FPS example for people and I decided to analysis how they make this. Personally I wanted to show you how I analysis the games.

Class: Player Input Handler


What Player Input Handler class does is controlling a player. It reference to GameFlowManager and get the state of current game to ignore user input when game is finished.

To Change Weapon
If user press 1, 2, 3 and so on, we can get positive number and it is used in PlayerWeaponsManager class.

Class: Player Character Controller

PlayerCharacterController class controls player’s character. Many properties are adjustable to game feel better. It uses PlayerWeaponsManager to change weapon and Health Class. Health Class is managing health for player and bots.(Both uses Health Class)

Class: PlayerWeaponsManager

At the beginning of the game player should have weapon. Variable ‘startingWeapons’ contains initial weapon list.

Weapon camera
Weapon has its own camera to render the weapon on top of main camera. Default position of weapon uses DefaultWeaponPosition. When User Press zoom (which is aiming), it will use AimingWeaponPosition. Its x value is 0 which means aligned to 0 of x.

Aiming
When user press right button, Aiming is activated. As soon as aiming is activated then all of camera’s FOV(field of view) is changed. This effect will make zoom in. FOV Animation is code driven which means changing FOV value is running by code.

void UpdateWeaponAiming()
{
    if (m_WeaponSwitchState == WeaponSwitchState.Up)
    {
        WeaponController activeWeapon = GetActiveWeapon();
        if (isAiming && activeWeapon)
        {
            m_WeaponMainLocalPosition = Vector3.Lerp(m_WeaponMainLocalPosition, aimingWeaponPosition.localPosition + activeWeapon.aimOffset, aimingAnimationSpeed * Time.deltaTime);

            SetFOV(Mathf.Lerp(m_PlayerCharacterController.playerCamera.fieldOfView, activeWeapon.aimZoomRatio * defaultFOV, aimingAnimationSpeed * Time.deltaTime));
        }
        else
        {
            m_WeaponMainLocalPosition = Vector3.Lerp(m_WeaponMainLocalPosition, defaultWeaponPosition.localPosition, aimingAnimationSpeed * Time.deltaTime);
            SetFOV(Mathf.Lerp(m_PlayerCharacterController.playerCamera.fieldOfView, defaultFOV, aimingAnimationSpeed * Time.deltaTime));
        }
    }
}
In here, we use aimingWeaponPosition and defaultWeaponPosition.


To display crosshair hud
At the end of update function, raycast and set the isPointingAtEnemy bool variable. This variable is used by CrosshairManager which will display crosshair hud based on isPointingAtEnemy.

<Raycast fail and no enemy>

<Raycast success then CrosshairManager will show different hud>

Weapon Change Animation
When user change the weapon, current weapon position moves down and changed 3d model (actually hide current weapon and show new weapon) and then move up. In this case, we use DownWeaponPosition.


 

Class: Jetpack

After user unlock Jetpack, user press spacebar then player can fly. A relationship between PlayerCharacterController and Jetpack is like down below.


Player’s movement uses characterVelocity. In every update frame of Jetpack checks and applying additional velocity into characterVelocity.

<<Gameplay Idea: Implement a skill ‘Relentless Pursuit’ of Lucian in LOL or Tracer’s Blink>>

Class: Actor


When Actor is activated, we register itself to ActorsManager actors container. ActorsManager doesn’t have any other logic. Actor also has no logic at all but it has aimPoint variable. This variable is for aiming. For instance bot is targeting a player then bot should have specific target. The target will use aimPoint of Actor class.

Class: WeaponController

Every weapon objects has WeaponController component. WeaponController represent weapon itself. Weapon type, decide which projectile should use, bulletSpreadAngle (for shotgun), aimZoomRatio and so on.

Zoom for sniper
For instance, we have sniper rifle then we probably has zooming function more than pistol. In that case, we can use aimZoomRatio. If we set animZoomRatio to be 0.3 for instance, then zoom is way bigger than 0.7

<aimZoomRatio 0.7>

<aimZoomRatio 0.3>

Firing
In WeaponController, we instantiate projectile prefabs. Function flow like down below.

HandleShootInputs -> TryShoot -> HandleShoot

Bullet position
Every generated bullets position set by weaponMuzzle. In addition, muzzle flash effect is generated.

Prevent firing too quickly
If we call HandleShoot function really quickly, bullets will be generated. If we call HandleShoot every single time when user press the button then bullets will be generated really quickly if user has lighting speed hand! We have to prevent it. There is a variable m_LastTimeShoot which will prevent calling a function really quickly. This is timing logic.


Class: EnemyController


Class: Damageable

There is a Health class, which represent health of Player or Bot. To decrease player/bot health, there are two ways.

1.     Call TakeDamage method of health class.
2.     Through Damageable, call TakeDamage method of health class.

Number 2 used for projectiles. Number 1 used for player itself. (get damage by falling/environment or other reasons)



That is it for today. Next time I'll look how projectile works (probably collision detection), add more features such as spawner for bot, user's new skills (tracer blink!)





Wednesday, October 30, 2019

Regression Analysis in Games.

I like Gameplay Programming. Why? Because change one value a little bit then feels very different. When I talk about the feel, I usually talk example of comparing Unreal Tournament and Quake series.

For instance jump. Feel of jump in UT and Quake are definitely different. Yes, they use similar vector calculation but different tune values.

There are another example which is Super mario. There are tons of different platformer games. but feel of jump in Super mario much better than other games. I don't know what values they use but I could use different method to make similar jump feel.

Using regression analysis, I could get a formula. First of all, you can visit http://physmo.sourceforge.net

Using PhysMo, you can get Mario's jump curve data such as


Time
Height
0
0
0.015683
0
0.033367
0.25974
0.05005
0.519481
0.066733
0.727273
0.083417
0.987013
0.1001
1.194805
0.116783
1.350649
0.133467
1.558442
0.15015
1.714286
0.166834
1.818182
0.183517
1.922078
...
...
0.500501
0.415584
0.517174
0.199842
0.523867
0
0.540551
0

With this data and use regression analysis in Excel then you can get the formula like below.





f(x) = -32.038x2 + 17.486x - 0.2101


with this f(x), we can get y value of Mario. it feels same as Super Mario. Of course we can't use it for Ground -> Air -> Falling situation and others but you get the idea how to use Regression Analysis in Games.


Reference
Original idea of Super Mario analysis by Kenton.

Tuesday, October 29, 2019

One pattern that I use on multi-threaded environment.

As many Unity developer already knows, Unity's logic runs in main thread. When you need network feature in your project you probably use socket or other network library. Of course when you send/receive some packets over the network, you will use non-blocking or asynchronize mechanism.

Normally we use callback or event function and those are called by OS. Ok then you can do whatever you want. Something like this.

void MyReceiveFunction(data)
{
    // ok, I received a data!
    if ( data == 0 )
    {
        foo(0);
    }
    else if ( data == 1001 )
    {
        foo(1001);
    }
    else
    {
        ...
    }
}

The problem is that the function is called on different thread. (which is not mianthread)

so If you do anything that it is related with main thread or GUI, logic won't run correctly. The pattern I'm going to talk about is saving this situation! (very simple)

void MyReceiveFunction(data)
{
    // ok, I received a data!
    if ( data == 0 )
    {
        reserveFoo(0);
    }
    else if ( data == 1001 )
    {
        reserveFoo(1001);
    }
    else
    {
        ...
    } 
}

in the reserveFoo function we can reserve the command like below.

void reserveFoo(int cmd)
{
    lock
    {
        reserveFooList.add(cmd);
    }
}

reserveFooList is a container. It store a cmd. and it is used in consumer logic in mainthread.


// Update function is called in main thread.
void Update()
{
    if ( reserveFooList.size > 0 )
    {
        foreach(element : reserveFooList)
        {
            Foo(element);
        }

        reserveFooList.clear;
    }
}

Now Update function is called in main thread and checks whether size of reserveFooList is greater than 0 which means it has some element to do.

if the list is not empty then iterate all the elements and process those in main thread. That's is the main idea.

Of course you can use invoke method for solve this issue but personally I prefer to do this.

Saturday, October 26, 2019

Every programming language has its own idioms.

Every programming language has its own idioms and idioms are not the same as Design Pattern. If you already know computer language such as C, C++, Java but you feel you are not good at it, then I suggest you to know/use/apply the idioms of the languages.
I'm sure you get the idea.

I should ignore domain specific problems, formula when I read books.

Formula are invented over time and tons of books talks about their domain specific problems, how to solve it. I read many different kind of books and tried to understand everything but I realized it is not possible. I should make some rule that ignore domain specific problems but understand roughly. fundamental is much important.

I think this rule can be applied to programming exercise too. I worked on gaming industry many years and worked on other industry too. I know audio programming, tools development, AI, compiler construction, mobile app development, reverse engineering, server development. even arduio programming. but I couldn't know everything.

1 : Concentrate on fundamental thing and ignore domain specific problems.
2 : Work on domain specific problems and solve it.
3 : Summarized.

Task in UnrealEngine

 https://www.youtube.com/watch?v=1lBadANnJaw