Sunday 23 February 2014

Plans for February?

I mentioned before that I had plans for February, but due to other things getting in the way and a lack of time to do what I had planned, I had to delay. I will hopefully be able to start my plan fully in March and look forward to doing so, but what is the plan.....

I am getting close to the release of my first credited game for iOS and Android and it is a very exciting time for me, but with this also comes the realisation that my portfolio is lacking content. With this in mind I am looking to create short game demos over the weeks in March of a few game ideas that I have. These game ideas vary from all types of games, whilst I will be working during the day, the time I have to create the demos will be shorter than I would have liked, but I am determined to create something in March that can be added to my portfolio and may even influence my final year project for University.

I aim to document my progress in regular updates over the course of the month and provide videos of gameplay and maybe even an embedded player to let you have a go and offer any feedback. The art for these demos may not be the best, but as a programmer, I will try my best to make the games look good.

I will keep this post short, as it is just an introduction of things to come, watch this space...

Frozen Fishy out.

Monday 17 February 2014

Technical Post 1: Integrating Facebook into unity C# Part 3

<< Part 2

Please Note: This shows the high scores system that I am currently using, it works where it will show the top 10 players if the player who is signed in is within the top 10, if the player is outside the top 10 it shows the top 5 players, there is then a break in the table and it shows the 2 players above you, you and then the 2 players below you. This is in C#.

I do not show the entirety of the script for all 10 positions on our table, I am using 3D Text, so all text assigned is using the TextMesh object, and Textures are assigned to OTSprites (Orthello).
Where the below code has "....." it means that the code continues to fill in the rest of the fields in similar fashion to that shown

//List used for FBResult from HTTP GET Request for scores
private static List<object> scoresFacebook = null; 
//Is the player in the top 10
bool PlayerTopTen = false; //used to align the table once
bool DoOnce = false; //used to remove any unused entries once
bool OneTime = false; //used to get profile pictures once
bool getProfilePics = false; 
//variable to take the number of entries to indicate the last position taken up //in the table, used to remove empty entries to our table
int lastPos; 

//Update function, where our methods are called
void Update()
{
    if (!DoOnce){
        friendsScore ();
        DoOnce = true; //make it so that the method is only called once
    }
    if (PlayerTopTen) {
        Divider.SetActive(false); 

        //the player is in the top 10, no break in table needed
        if (!OneTime) 

        {
            removeNames(lastPos); 

            //remove any names on table that are empty entries
            OneTime = true;
        }
    }

}

public void friendsScore()
{
    FB.API("/app/scoresfields=score", 

            Facebook.HttpMethod.GET, CallbackFriendScores);
    //HTTP GET request for the scores
}
public void CallbackFriendScores(FBResult result)
{
    scoresFacebook = new List<object>();

    //Our lists of objects and assigned list of object using the Util.cs script
    List<object> scoresList = Util.DeserializeScores(result.Text);

    int i = 0; //count the number of objects as we go through the foreach
    foreach(object score in scoresList)
    {
        var entry = (Dictionary<string,object>) score;
        var user = (Dictionary<string,object>) entry["user"];
        string name = (string)user["name"];
        string userId = (string)user["id"];

        //extract relevant data from objects to assign to text in game
        if (string.Equals(userId,FB.UserId)) 

        {
            playerScoreFound = true;
            //we have found the player
            myScore = "" + entry["score"];
        }
        //set the top 10 names regardless of player position
        if (i<10)
        {
            if (i==0)
            {
                firstRank.text = "#1";
                firstNameFB.text = name;
                firstScoreFB.text = "" + entry["score"];
                idPos1 = userId; //take a reference for the players id
                pic1.SetActive(true); //make sure their profile picture is active
            }
            else if (i==1) //repeat for first 10 objects in the list
            {
                secondRank.text = "#2";
                secondNameFB.text = name;
                secondScoreFB.text = "" + entry["score"];
                idPos2 = userId;
                pic2.SetActive(true);
            }
            else if (i==2)
            {
                thirdRank.text = "#3";
                thirdNameFB.text = name;
                thirdScoreFB.text = "" + entry["score"];
                idPos3 = userId;
                pic3.SetActive(true);
            }

.....

//now check if the player was found within the first 10 entries, if so only show //top 10 players from friends list
if (playerScoreFound && i<10)
{
    PlayerTopTen = true;
    tableFormed = true; //the table has been formed
    
//set the ranks for position 6-10 to their corresponding numbers
    if(i>=6)
        sixthRank.text = "#6";
    if(i>=7)
        seventhRank.text = "#7";

    if(i>=8)
        eighthRank.text = "#8";

    if(i>=9)
        ninethRank.text = "#9";

    if(i>=10)
        tenthRank.text = "#10";

}
//our player has not been found yet, so we need to keep looking through the //objects and move up the positions to make space for the new object data to be //added to position 10
else if (!tableFormed)
{
    //keep sorting for new places as player has not been found yet
    
//get the data at position 7 for storing in position 6
    tempName = seventhNameFB.text;
    tempScore = seventhScoreFB.text;
    rank = seventhRank.text;
    sixthRank.text = rank;
    sixthNameFB.text = tempName;
    sixthScoreFB.text = tempScore;
    idPos6 = idPos7; //change id position references for profile pictures
    //repeat for position 8 and 7

    tempName = eighthNameFB.text;         
    tempScore = eighthScoreFB.text;
    rank = eighthRank.text;
    seventhRank.text = rank;
    seventhNameFB.text = tempName;
    seventhScoreFB.text = tempScore; 
    idPos7 = idPos8; //change id position references
    //repeat for position 9 and 8
    tempName = ninethNameFB.text;          
    tempScore = ninethScoreFB.text;
    rank = ninethRank.text;
    eighthRank.text = rank;
    eighthNameFB.text = tempName;
    eighthScoreFB.text = tempScore; 
    idPos8 = idPos9; //change id position references
    //repeat for position 10 and 9
    tempName = tenthNameFB.text;          
    tempScore = tenthScoreFB.text;
    rank = tenthRank.text;
    ninethRank.text = rank;
    ninethNameFB.text = tempName;
    ninethScoreFB.text = tempScore;
    idPos9 = idPos10; //change id position references

    //update the tenth name with the current object
    tenthNameFB.text = name;
    tenthScoreFB.text = "" + entry["score"];
    tenthRank.text = "#" + (i+1);
    idPos10 = userId; //take the id for reference from the object
}


//if the player was not in the top 10 we need to see that their data is stored at //position 8 in the table to stop any further changes, 2 players above and 2 //below. If there are not 2 players below, the table will stop updating due to //there not being anymore objects in our foreach() loop
if (i>9) {
    if (myScore == eighthScoreFB.text)
    {

        //break needed as player is outside top 10
        Divider.SetActive(true);
        //sorting is complete
        tableFormed = true;
    }
}



//table sorting is complete, now to get profile pictures
if (tableFormed)
{
    if (!getProfilePics)
    {
        StartCoroutine(getFacebookProfile(0));
        StartCoroutine(getFacebookProfile(1));
        StartCoroutine(getFacebookProfile(2));

.....

IEnumerator getFacebookProfile(int key)
{
    if (key==0) //use the key to see which position to assign the texture

    {
        string url = "http://graph.facebook.com/" + idPos1 + "/picture";
        WWW www = new WWW(url);
        yield return www;
        Pic1Script.image = www.texture;
    }
    if (key==1) 

    {
        string url = "http://graph.facebook.com/" + idPos2 + "/picture";
        WWW www = new WWW(url);
        yield return www;
        Pic2Script.image = www.texture;
    }
    if (key==2) 

    {
        string url = "http://graph.facebook.com/" + idPos3 + "/picture";
        WWW www = new WWW(url);
        yield return www;
        Pic3Script.image = www.texture;

.....

//we need to check if we need to remove any names if the player is in the top 10
//do this by sending the lastPos value which should take the value of i+1 at the //end of each foreach() loop
public void removeNames (int j)
{

    //if j is 1, we want to remove the rest of the entries as well so check if       //doTheRest is true
    if (j == 1 || doTheRest) 
    {
        //remove all text and set objects renders to false
        firstRank.text = "";
        firstNameFB.text = "";
        firstScoreFB.text = "";
        pic1.SetActive(false);
        Pic1Script.image = null;
        doTheRest = true; 

        //it was true, so do the others so we don't need a new key value
    }
    if (j == 2 || doTheRest) //repeat process for all the positions possible

    {
        secondRank.text = "";
        secondNameFB.text = "";
        secondScoreFB.text = "";
        pic2.SetActive(false);

        Pic2Script.image = null;
        doTheRest = true;

    }
    if (j == 3 || doTheRest)
    {
        thirdRank.text = "";
        thirdNameFB.text = "";
        thirdScoreFB.text = "";
        pic3.SetActive(false);
        Pic3Script.image = null;
        doTheRest = true;
    }

....

I am aware that this may not be the best way to get high scores and put them in a table, I am open to any improvements that you may offer to my code, as I said I am relatively new to programming

Technical Post 1: Integrating Facebook into unity C# Part 2

<< Part 1
Note: This is in C#
We should now have the players name from Facebook, so now we will look at how to POST something to Facebook like a score. Where in our game, when the player dies we want to check if their new score is their highest and then we call the HTTP POST method to send their score to Facebook to compare with their friends. We use the following code;
public void setScore()
{
    int score = currentScore;
    var ScoreData =  new Dictionary<string, string>() {{"score", score.ToString()}};
    FB.API("/me/scores", Facebook.HttpMethod.POST, publishActionCallback, ScoreData);
    print ("Score data" + ScoreData);
}
void publishActionCallback(FBResult result)
{
    print ("say something");
}

When the setScore() Method is called a local variable is given the value of the players' score, and then a new variable is created under the Dictionary type which creates the value in a way that the Facebook SDK understands the value that is being sent up. Then we use FB.API to send the value to Facebook, with similar parameters before, but using a HTTP POST instead and adding the var created to the request that will be sent up to Facebook, on successful completion the method will call the Callback method in this case "publishActionCallback(FBResult result)" where FBResult is the data returned by Facebook on completion and the method tells the console to print something to show that the request was successful.

So now we can post scores and get scores, feel free to ask if you are having problems with this, (changing "me?fields=name" for "me/scores") we can now look at getting our friends scores from Facebook. First of all, we must make sure that the permissions for our game allow us to access our friends game data, so we must go to the Facebook Graph explorer and make sure that we have all the needed permissions. (Facebook Graph Link)

If we start by creating an access token for our app, simply by clicking "Get Access Token" and making sure the fields "user_games_activity" and "friends_games_activity" are checked, then create the access token. If we now set the request type to GET and type "me/permissions" and submit, we should see a list of permissions including the ones we just added with a value of 1(meaning true).

The easiest way to find the code for this to work, is to take the Util.cs script for the friend smash (script Link) and copy it into your own project so that you can access the Util directory and use this with MiniJSON to parse the data returned by Facebook and extract only the information you want. It is possible to search the return value as it was a string and look for a string before the one you want and take the string at the end, this would return the section of the string you want, but is not the best for using when you have more than one persons piece of data.

Using the Util.cs script, we can also look at the MainMenu.cs script from the same example (Link) and see how it is implemented into the game. In this case when we call our friends who use the app and have a score we use the following HTTP GET request;
FB.API("/app/scores?fields=score"Facebook.HttpMethod.GETCallbackFriendScores);
This will return an array of our friends scores and Facebook returns the values in descending order where the first value returned has the highest score. This makes it easier for assigning the return values to text within your game or UI.

We now want to look at how we can actually access the array of data, as a relatively beginner programmer, this was difficult for me, as there was little documentation that outlined exactly what I had to do in order to access the information I wanted. The answer is really simple in practice, even if you don't understand what exactly you are doing, if you follow this there should be no problem.

Using the Util.cs script, in our callback method, we create a list of objects to contain the parsed data from the Util method that we are about to call.
We can now use Util.DeserializeScores(result.Text) and assign the result to the list of objects that we have declared. This method will return the scores and names of the players and with that we can start to assemble a high scores table.
Next we can simply go through the list of objects using a "foreach(object score in [Enter list name])" method that will go through the data and write allow us to access it for manipulation and use in our game.
The code below is used within our foreach loop to get and assign the users name, id and score as a local string variable to make it easier to use.
var entry = (Dictionary<string,object>) score;
var user = (Dictionary<string,object>) entry["user"];
string name = (string)user["name"];
string userId = (string)user["id"];
string score = (string)entry["score"];

I have added some of my script to the next page for reference, if you want an example of how this will work, I cannot add screen shots of it working at this time, but will add them when available

Check the full method to get scores and post scores below

public void getScore()
{
    FB.API("me/scores", Facebook.HttpMethod.GET, CallbackMyScore);
}
public void CallbackMyScore(FBResult result)
{
    FriendScores = new List<object>();
    List<object> FriendScoresList = Util.DeserializeScores(result.Text);
      
    foreach(object score in FriendScoresList)
    {

        bool fbScoreExists = false;
        var entry = (Dictionary<string,object>) score;
        var user = (Dictionary<string,object>) entry["user"];
          
        string userId = (string)user["id"];
        if (string.Equals(userId,FB.UserId)) {

            fbScoreExists = true;
            int playerHighScore = getScoreFromEntry(entry);
            if (currentScore > playerHighScore)
            {
                setMyScore();
            }
            else return;

        }
    }

    if(!fbScoreExists)
        setMyScore();
}



Now that we have players names and scores used in our game, we wanted to get their profile picture within the high scores table, so that our players could recognise who they had beat easier, to do this using a HTTP GET method every time would have been a lot more complex than it needed to be, so what I did was use a simple url get request using the WWW object type and receive a texture directly from Facebook. With the way that our high scores table is written we had to wait until the table was formed and formatted until the pictures were assigned to reduce calls to the web, so I added in some temp string variables that will hold the id of each position in the table.

string url = "http://graph.facebook.com/" + idPos1 + "/picture";
WWW www = new WWW(url);
yield return www;
Pic1Script.image = www.texture;

*this is using OTSprite, the texture assign for other systems can be found online easily
This simply uses the id for position 1 in the table to get a texture from Facebook and assign that texture to the desired object in the scene.

One last piece of code that is useful is the check to see if the current object being looked at is the current player. To do this we take the userId string and compare it using our FB.userId method to see if they are identical.

See next post for full example code

Technical Post 1: Integrating Facebook into unity C# Part 1

Declaration: I'm sure this may not be the best way to do this, but I hope that I can clear up how to do this for others, so as to save others time.

Whilst making a game in unity for mobile devices, it became apparent that we would need to add in Social media integration to allow users to share the game and post their high scores, this seemed to be harder than it originally looked, hesitant to fork out $65+ on the prime[31] plugin we looked for a cheaper alternative. We have heard good things about the simplicity of prime[31], but with a small budget we were sure we could find an alternative.

After much searching and research, we found an all inclusive package that seemed to be able to do the job we needed, we had bought the UniShare package from the asset store for $35 (Link to Asset Store). Whilst this is a very easy plugin to use, where once you have set the prefabs to contain your app ID, app secret and a callback URL, you can easily call the prefab to log in, share and log out, the three things we were originally looking for.

However, there was one problem, we wanted the user to have confirmation they had shared through a window from Facebook or Twitter which allowed the player to enter their own messages and share them at the click of a button. This may be present in the UniShare package, but with the lacking documentation, we were wasting too much time trying to find the solution that we had to find another.

The UniShare package is great for value, if you need a simple, cheap system to share and post to the users' social media, where it supports all the major networks, but the incomplete documentation makes it quite stressful to use.

As we tested the game, we saw players were able to share their scores but not compare them with their friends, so we clearly needed a new system. We decided to drop Twitter from our game as a way of sharing, there is currently a link to the company Twitter account if there is need for it, but we noticed the majority of games on the market don't provide a Twitter share for your actions. So now we are only left with Facebook, and after a little searching we downloaded the free Facebook SDK (Link) after signing up as a Facebook developer and verifying the account with a mobile phone.

Now came the hard part, we had a working system with UniShare that we took apart and destroyed to replace with a new system that had equally as bad documentation. After searching for answers it seemed that others were struggling with the documentation with little success, now as we are starting to get ours to work, I am going to post some code that works (in 4.3.6) so that it may help others that are struggling.

I have provided two links below gave very useful information used for Initialising the app, logging in and out and sharing to Facebook, check these before heading into the score boards and posting scores to Facebook. 
First Video: iOS Setup 
Second Video: Android Setup

Now we have the player being able to log in, log out and share their scores to their wall (can even challenge friends if you want to implement that), we needed to look at getting data from Facebook itself. We started with getting the user name.
Note this is in C#
It is important before we start to add this before the class declaration
using System.Collections.Generic;
using Facebook.MiniJSON
This allows us to use all the code for Facebook with minimal errors, now we look at getting the name using a HTTP GET request. and the Facebook SDK has made this simple, where to get data from a specific URL from Facebook we can use this code
public void GetUserName()
{
    FB.API("me?fields=name", Facebook.HttpMethod.GET, Callback);
}

void Callback(FBResult result)
{
    nameFound = true;
}

Where we call the GetUserName() method at some point in our code, and this uses the FB.API call to Facebook with the parameters "URL", "Request type"(GET, POST, DELETE), "Callback Method"
Upon successful get request the Facebook SDK calls the Callback method as specified and that can print the name or change text to say hello [+ their name] to the player.