Thursday, 21 November 2013

Sunday, 17 November 2013

Real Space Rush mobile game #update 3 - Adding and removing level in real time

This weekend I added functionality that will add new corridor when player activate the trigger and remove old corridor that is not in use anymore. In theory in game there will be only 2 corridors in one time. To illustrate it check this screenshot.


Currently I build only 1 type of corridor but I am planning to create at least 10 different. They will be stored in array and randomly pulled and added to scene. Corridors will not have the same sizes so I will have to make sure that transition between them is very smooth.

To main camera that is following character I added script (LevelCount) that will hold information how many levels are in the game.

public GameObject[] gameLevels; 
    public int levelsAdded = 0;
        
    // Use this for initialization
    void Start () {
        // Store gameLevels in list, so we can remove them later for performance
        gameLevels = new GameObject[2];
    }
    
    // Update is called once per frame
    void Update () {
    
    }


To my first corridor that is build in the game I added this script(LevelAppear).

public class LevelAppear : MonoBehaviour {
    
    private GameObject spawnPoint;
    private GameObject Corridor;
    bool PlayerEnteredZone;
    public GameObject Player;
    
    //hold information on levels
    private LevelCount LevelCountScript;
    
    // Use this for initialization
    void Start () {
        spawnPoint = GameObject.Find("spawnPoint");
        Corridor = GameObject.FindGameObjectWithTag("Corridor");
        LevelCountScript = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<LevelCount>();
        
    }
    
    // Update is called once per frame
    void Update () {
        if(PlayerEnteredZone)
        {
            AddLevel();
        }
    }
    
    void OnTriggerEnter(Collider player)
    {
            PlayerEnteredZone = true;
        
    }
    
    void AddLevel()
    {
        GameObject objectInstantiated = Instantiate(Corridor, new Vector3(transform.position.x + 28f, transform.position.y + 31f, transform.position.z + 20f), Quaternion.identity) as GameObject;
                
        if(LevelCountScript.levelsAdded == 2)
        {        
                LevelCountScript.levelsAdded = LevelCountScript.levelsAdded -2;
                Destroy(LevelCountScript.gameLevels[LevelCountScript.levelsAdded]);
                
        }
        
        if(LevelCountScript.levelsAdded == 1)
        {        
                LevelCountScript.levelsAdded = LevelCountScript.levelsAdded--;
                Destroy(LevelCountScript.gameLevels[LevelCountScript.levelsAdded]);
                
        }
        
        LevelCountScript.gameLevels[LevelCountScript.levelsAdded] = objectInstantiated;
        
        LevelCountScript.levelsAdded++;
        
        PlayerEnteredZone = false;
        
    }
    
}

It works fine however I am not very happy with hard coded position when adding new level (1st line of AddLevel function). I must find a better way of finding a point where new corridor will be added without having to hard code position. If anyone have any ideas I will be grateful.

Till next time.


Tuesday, 12 November 2013

Adding datepicker in ASP.NET MVC 4 application



This tutorial will be very easy for most of you intermediate developers, but I wanted to show bundle feature that is available in MVC 4 using date picker example. I will also show how we can add datepicker in previous versions of MVC.
There are few methods we can do it however I will show you only 2.
First we have to add some references to jquery, jquery-ui and styles. As I mention in mvc 4 we can use bundles which improve performance and give us less headache in the future.
To access bundle configuration go to App_Start and open BundleConfig.cs.



You can very easily add your own custom styles and scripts to existing bundles. For instance you can MyCustomStyles.css to existing bundle:

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css", "~/Content/MyCustomStyles.css"));



Open _Layout page and find at the bottom @Scripts.Render("~/bundles/jquery"). Cut it and paste inside head – sounds creepy. Also add @Styles.Render("~/Content/themes/base/css") and @Scripts.Render("~/bundles/jqueryui"). This way we included files we need to use datepicker.

Your code should like this:
 @Styles.Render("~/Content/css")
        @Styles.Render("~/Content/themes/base/css")
        @Scripts.Render("~/bundles/modernizr")
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/jqueryui")


Using model for datepicker (preferred method).
To use this method we are going to create Discount model. Create a new class and call it Discount.

public class Discount
    {
        public Discount()
        {
            dateFrom = DateTime.Now.Date;
            dateTo = DateTime.Now.Date;
        }

        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        public DateTime dateFrom { get; set; }
        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        public DateTime dateTo { get; set; }
        public decimal discountPercentage { get; set; }
        public string discountName { get; set; }
    }

We are using simple constructor to define default date. Date are also formatted to show only date.
Add new controller and call it Date and add new View from the controller(you can right click on the Action name and choose add View.




public ActionResult Index()
        {
            return View(new Discount());
        }



Open Index view from Date controller.

@model Components.Models.Discount
<script>
    $(function () {
        $("#dateFrom, #dateTo").datepicker();
    });
</script>
<h2>
    Date picker test</h2>
<table>
    <tr>
        <td>@Html.EditorFor(m => m.dateFrom)
        </td>
        <td>@Html.EditorFor(m => m.dateTo)
        </td>
    </tr>
</table>


In view we added class for model (Components is the name of the project, Models is the folder where we created Discount class).
As you can see we do not have to reference jquery here, as it was already referenced in Layout. In previous MVC you would have to include 3 separate files inside layout, or on the individual page (not recommended).
It would look something like that:

<script src="../../Scripts/jquery-ui-1.8.20.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
        <link href="../../Content/themes/base/jquery.ui.datepicker.css" rel="stylesheet"
            type="text/css" />

In the old MVC version if you wanted to update jquery you would have to manually change the version name to match your newest jquery, where in MVC 4 system will automatically figure it out.
Check BundleConfig.cs file again:

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

 Adding date picker without model.

@{
    ViewBag.Title = "Index";
}
@model Components.Models.Discount
<script>
    $(function () {
        $("#dateFrom, #dateTo, #datepickerNoModel").datepicker();
    });
</script>
<h2>
    Date picker test</h2>
<table>
    <tr>
        <td>@Html.EditorFor(m => m.dateFrom)
        </td>
        <td>@Html.EditorFor(m => m.dateTo)
        </td>
        <td>
            <input type="text" id="datepickerNoModel" />
        </td>
    </tr>
</table>


Main advantage using the model for datepicker is that you can very easily pass data from view to controller, where in other case you would have to formcollection.

Calling the controller with model date picker
@using(Html.BeginForm("SubmitDiscount", "Date", FormMethod.Post))
{
<table>
<tr>
<td>@Html.LabelFor(m=>m.discountName)</td>
<td>@Html.LabelFor(m=>m.dateFrom)</td>
<td>@Html.LabelFor(m=>m.dateTo)</td>
</tr>
    <tr>
        <td>@Html.TextBoxFor(m=>m.discountName)</td>
        <td>@Html.EditorFor(m => m.dateFrom)
        </td>
        <td>@Html.EditorFor(m => m.dateTo)
        </td>
    </tr>
</table>
    <input type="submit" value="Apply discount"/>
}

 We have modified View a bit and added new controller SubmitDiscount.


Run the application and go to date controller so your path should something like that localhost:9930//Date, put a break point for debugger on SubmitDiscount method. You will see that the fields we have submitted have been passed to controller via model.




Now let’s use form collection now to pass date without using the model.

Modify controller:

public ActionResult SubmitDiscount(Discount model, FormCollection form)
        {
            var date = form["dateNoModel"];
            DateTime convertDateFromString = DateTime.Parse(date);
            return RedirectToAction("Index");
        }

And view by replacing dateTo model with input.


@using(Html.BeginForm("SubmitDiscount", "Date", FormMethod.Post))
{
<table>
<tr>
<td>@Html.LabelFor(m=>m.discountName)</td>
<td>@Html.LabelFor(m=>m.dateFrom)</td>
<td>@Html.LabelFor(m=>m.dateTo)</td>
</tr>
    <tr>
        <td>@Html.TextBoxFor(m=>m.discountName)</td>
        <td>@Html.EditorFor(m => m.dateFrom)
        </td>
        <td><input type="text" id ="dateTo" name="dateNoModel"/>
        </td>
    </tr>
</table>
    <input type="submit" value="Apply discount"/>
}

Run the application and debug the method again. Choose dateTo and check your model and form.



As you can see it is faster and more reliable to use model with date picker. All elements within the form are type of string so you will have to convert them if necessary which is time consuming and can be avoided.