Friday, May 9, 2014

Preventing float overflow on endless runner type of game

If the character is moving against the world, instead of the world moving against the player also known as treadmill-type mechanism, there's a likely chance that the player's location could overflow the float's limitation.


Here's a way to deal with that problem:

using UnityEngine;
using System.Collections;

public class CameraRunnerScript : MonoBehaviour {

    public Transform player;

    // Update is called once per frame
    void Update () 
    {
        MoveCamera ();

        float currentCameraX = this.transform.position.x;

        // this prevents overflowing the float, reset the camera
        if (currentCameraX > 100) 
        {
            // reset the player position
            this.player.transform.position = new Vector3(0, player.position.y, 0);


            MoveCamera ();      


            // make all spawned object follow the camera's new position
            var grounds = GameObject.FindGameObjectsWithTag("Ground");
            foreach (var item in grounds) 
            {
                var delta = item.transform.position.x - currentCameraX;
                item.transform.position = new Vector3(this.transform.position.x + delta, item.transform.position.y, 0);
            }


        }
    }


    // move the camera based on player's position
    void MoveCamera ()
    {
        this.transform.position = new Vector3 (this.player.position.x + 6, 0, -10);
    }


}

Thursday, May 1, 2014

Things that are convenient when your RDBMS has first class boolean support

Other RDBMSes could embed boolean expression anywhere:

select exists(select * from person) as has_record;

select 
  person_id in (1,6,8) as one_of_the_chosen_ones,
  person_id % 2 = 0 has_even_id,
  * 
from person;


You have to do this in SQL Server:
select 
  case when exists(select * from person) then 
    convert(bit, 1)
  else
    convert(bit, 0)
end as has_record;

select 
  case when person_id in (1,6,8) then
    convert(bit, 1)
  else
    convert(bit, 0)
  end as one_of_the_chosen_ones,
  case when person_id % 2 = 0 then 
    convert(bit, 1)
  else
    convert(bit, 0)
  end as has_even_id,
  * 
from person;

Tuesday, April 29, 2014

Imagine there's no country

"Imagine there's no country..." – John Lennon

But alas, humans are subjected to suffer, especially the kind of humans called programmers and what have you


Having said that, sorting across cultures is one of things we must take into account when making our app locale-aware.


As of the time of this writing, it's not possible to use JavaScript for localization. We have to use server-side languages

using System;
using System.Linq;
using System.Globalization;

public class Program
{
    public static void Main()
    {
        var list = new[] {
            "honesty", "courage", "integrity", "character"
        };
         
                 
        list.OrderBy(x => x).Dump();    
        list.OrderBy(x => x, StringComparer.Create(new CultureInfo("cs-CZ"), true)).Dump();
    }
}



English sorting:
1. character
2. courage
3. honesty
4. integrity

Czech sorting:
1. courage
2. honesty
3. character
4. integrity

"...I wonder if you can" – John Lennon

Tuesday, April 15, 2014

Optimization through materialization

Saw a slow query which for the life of me I can't figure out why joining on inline TVF is slow, considering inline TVF is generally faster than variable-based TVF (a.k.a. multi-statement TVF)


SELECT p.Fullname, o.Organizations
FROM Person p
JOIN dbo.fn_GetPersonOrganizations() o ON P.PersonId = B.PersonId

And was optimized by pre-materializing the rows of the inline TVF by dumping its result to a temporary table first then joining to temporary table instead. As much as we don't like to use a temporary table and make a more solid solution by fixing the problem of the inline TVF itself instead, we don't have the luxury of time as the ticket is a hotfix one; besides, we are having a hard time discerning if the problem really lies on the inline TVF itself, the inline TVF's code is very tight and looks performant(at the risk of sounding like a sales brochure). So temporary table we go:


SELECT p.Fullname, o.Organizations
FROM Person p
JOIN #Organizations o ON P.PersonId = B.PersonId



Table variable don't need to be cleaned up, so we could use table variable instead of temporary table; however, temporary table could be faster than table variable, but then temporary table need to be cleaned up, so we come up with this alternative approach instead:


SELECT p.Fullname, o.Organizations
FROM Person p
JOIN
(
    SELECT TOP 4000000000 *
    FROM dbo.fn_GetPersonOrganizations()
) o ON P.PersonId = B.PersonId


We found out that TOP blah achieves the same effect of materializing the rows immediately; same fast performance as temporary table. We were able to speed up the query, but we don't know yet why we need to materialize the inline TVF's results to gain performance on joins.



Happy Coding! ツ

Tuesday, April 1, 2014

Generics not letting you become a full-fledged objected-oriented programmer?

Hello implements IGreeter, but the compiler won't allow us to return an IList<Hello> to IList<IGreeter>, that's very fundamental OOP, but all our hard-earned knowledge of OOP can't do its magic due to the covariance problem between generic types



Fear not, there's a solution to that, starting C# 4, IEnumerable is covariant to IList, we can just substitute IEnumerable for IList if we don't need to add elements to the collection.



Think of OOP generics papercuts prior to C# 4



Happy Coding! ツ