Monday, April 28, 2014

Crickets Make the Most Noise

It has been a while since I have posted. This is mostly due to the fact that I am on break before my last class starts. This class is the second half to my Senior Project and is the second sprint towards a Beta for Starbound Aces.

I have decided not to work on Starbound Aces during the break. This is unusual compared to my past patterns in which I would religiously throw myself at my code to fix all bugs that manifested themselves in the Alpha development. I have decided against this because burnout is a huge mood killer.

On another note I plan on purchasing a license for Unreal Engine 4 and taking the C++ for a spin since that is the language of my choice. I also have been working on some Unity prototypes that I though were neat. Within the week I will be able to show some prototypes here as well as explain them. In regards to UE4, we will see if I have anything to post.

In the meantime, enjoy your game programming and check back soon!

Wednesday, April 23, 2014

Unity / SmartFox Senior Project : Halfway Point

Today marks the halfway marker for our Unity project: Starbound Aces. It has been a long 8 weeks of producing documentation and an Alpha version. Playable here: Play Starbound Aces

I want to spend this time recapping all of the work done for the game and what I would have done differently in regards to the programming architecture of the game. Then I would like to explain what will happen moving forward from here.

In regards to the recap there are several subjects I would like to cover. These subjects are server extension design, database design, and the client side design.

The server extension design was originally intended to follow a simple authoritative design in which client data was verified by various classes. These classes I called game drivers. Each class was responsible for collecting data from each client. This was implemented fairly simply but did not achieve its ultimate purpose. Each of these classes were to have validation methods built in that accepted or rejected client data by virtue of 'is it possible'. For instance, if the client says their position is at a given point, the ship validation (containing all information for movement such as acceleration, velocity, position, and rotation) would determine whether this was possible in the time passed and the given latency. If not, it would tell the client that their ship is elsewhere. When implementing this method however, even without the validation, it caused a lot of jumping around client side. This leads into what I would have done differently in regards to the server extension design.

What I would have done differently in regards to server extension design is completely simulate, and drive, the game from the server. What does this mean? Well, it would imply all physics, movement, game logic, events, combat, everything, would be handled server side. Essentially, the game core systems to drive it would have been programmed server side. The only responsibility of Unity would be to collect the data, render, connect, give user feedback, and get user input.

The database design of the project was small. There are only three tables and two that are actually used. The two tables that are used are for the user and the user scores. This is simple enough and was just enough to accomplish the lowest core requirements of the game. This I have no problem with and went without a hitch.

There are a few, more ambitious, ways I would have used the database.

Now, what I wanted to have done is much more in depth. On top of the scores and users, I wanted to add in functionality for the game table. The game table would hold metadata about each game played. This would allow new people joining the lobby to see a game created before they entered. It would also allow a player to see their past game statistics. Finally, I would have added more tables for ship configurations. This would hold all data for each weapon, projectile, and ship hull available. It would then allow players to set configurations when connected to the server and pick one for the game they are about to join.

The client design I turned out to work well with what was originally planned with a few modifications. The SmartFox Server singleton class did the grunt of the work. Its main responsibility was to connect, login, handle events, and forward data between client and server. This worked out excellently without any problems and worked as intended.

There are few things I would have changed. One would have been to create smaller scripts based on network actions. These scripts would look similar to the one I added last week called NetworkTransform:

public enum NetworkObjectType {
    PLAYER = 0,
    PROJECTILE
}

public enum CommunicationType {
    SEND_ONLY,
    RECEIVE_ONLY,
    SEND_AND_RECEIVE
}


public class NetworkTransformer : MonoBehaviour, IEventListener {

    public NetworkObjectType type;
    public CommunicationType commType;

    private int networkId = -1;
    private string stype;
    private IClientController server;


// Use this for initialization
void Start () {
        server = GameManager.gameManager.ClientController;
        server.Register(this);
        switch (type) {
            case NetworkObjectType.PLAYER:
                stype = "player";
                break;

            case NetworkObjectType.PROJECTILE:
                stype = "projectile";
                break;

            default:
                break;
        }
}

    public int NetworkId {
        get {
            return networkId;
        }
        set {
            networkId = value;
        }
    }
// Update is called once per frame
void Update () {
        if (commType == CommunicationType.SEND_ONLY || commType == CommunicationType.SEND_AND_RECEIVE) {
            SendData();
        }
}

    private float delay = 0.1f;
    private float timepassed = 0.0f;
    private void SendData() {
        timepassed += Time.deltaTime;
        if (timepassed >= delay) {
            switch (type) {
                case NetworkObjectType.PLAYER:
                    SendPlayerData();
                    break;

                case NetworkObjectType.PROJECTILE:
                    SendProjectileData();
                    break;

                default:
                    break;
            }
            
            timepassed = 0.0f;
        }
    }

    private void SendPlayerData() {
        Dictionary<string, object> data = new Dictionary<string, object>();
        data.Add("transform", transform);
        data.Add("type", stype);
        server.Send(DataType.TRANSFORM, data);
    }

    private void SendProjectileData() {
        Dictionary<string, object> data = new Dictionary<string, object>();
        data.Add("transform", transform);
        data.Add("type", stype);
        data.Add("networkId", networkId);
        server.Send(DataType.TRANSFORM, data);
    }

    public void Notify(string eventType, object o) {
        if (commType == CommunicationType.RECEIVE_ONLY || commType == CommunicationType.SEND_AND_RECEIVE) {
            switch (eventType) {

                case "transform":
                    handleTransform(o);
                    break;

                default:
                    break;
            }
        }
    }

    void OnDestroy() {
        GameManager.gameManager.ClientController.Unregister(this);
    }

    private void handleTransform(object o) {
        Dictionary<string, object> data = o as Dictionary<string, object>;
        int id = (int)data["id"];

        if (id != networkId) {
            return;
        }

        float px = (float)data["position.x"];
        float py = (float)data["position.y"];
        float pz = (float)data["position.z"];
        float rx = (float)data["rotation.x"];
        float ry = (float)data["rotation.y"];
        float rz = (float)data["rotation.z"];
        float rw = (float)data["rotation.w"];

        transform.position = new Vector3(px, py, pz);
        transform.rotation = new Quaternion(rx, ry, rz, rw);
    }
}

This class was hacked in to resolve issues where the SmartFox instance on the client side was doing too much management of data and resolving who gets what data rather than forwarding its data as originally designed. In fact, I would dare say I would have created a base script for this design that determined whether an object was send, receive, or send and receive only, then create a class for each type of network event possible. Right now, a lot of the scripts are tied to specific functionality and make reuse virtually non-existent - poor OOP design.

Moving forward we have a lot of plans for the game in regards to our class. A lot of the work to be done is related to the features of the game. So, unfortunately, most of what I said before of how I should have/ wanted to do things will not be implemented in this game. So, here is a list of what I need to get done, but I will not go into long winded detail right now. Next week though, I will explain how I will go about this when my final class starts, and the last 8 weeks of this project. Here is what I plan on getting done for next period:
  • Fix room leaving errors on server side
  • Fix users attempting to double join rooms
  • Email response to activate accounts
  • Clean up all GUIs in the game
  • Implement full database for game creation
  • Create game waiting lobby so players can queue before going into a game
  • Generating random space debris
  • Fix messaging between client and server as redundant and 'dead' data is being sent.

Wednesday, April 16, 2014

Unity Project Web Player

While I have no major updates for you, or a video, I do supply a link to the web player for our Senior Project. Wait... what? Want to play? Well, here it IS: Play Starbound Aces

Short, sweet, to the point. Leave posts to comment on the game!

Monday, April 14, 2014

Unity Project Update Starbound Aces

Well, it seems yet again I was able to get done what I set out to do. This being the integration of the new combat system an the network. I have had some issues along the way; however, they all systems work out pretty well if I may say so myself.

The biggest issue now is the network latency. As it stands, the current combat system sends projectile spawning data to the server and the server sends that data back to the clients (all of them). This results in projectiles spawning in old positions due to the latency. The ship just moves to fast, which - as a gameplay feature - we want. So, I plan on letting the client decide where the projectile spawns in the next update, but still have the server dictate the rest of the properties. Not ideal in my mind, but good enough for a school project.

Tomorrow, I plan on implementing this new feature and getting a video up for everyone to view. If anybody wants to be in the video, and join in a multiplayer 'game' - feel free to comment below with some form of contact information. (G+ account should be good enough though - I will message you).

Unity Senior Project Client Side Update

This post is going to be short and sweet.

The client side updates have been finished. The updates are on the combat mechanics and flight controls.

The combat mechanics have changed in their underlying nature. First off, instead of a fixed laser beam, I changed the ammunition to projectiles. The new combat system consists of three scripts put together through the use of prefabs. This drag and drop set up will allow for a wide variety of new weapons and ammunition for each of these.

The folder with source code for that is found here.

The flight control scripts were changed by our other programmer David Tiscareno. He changed to ship to having a continuous forward motion. Direction is changed by mouse movements. Acceleration is controlled with the W and A keys.

Source code for that is found here.

Later today I plan on allowing the network to send/receive the position of projectiles from all clients to each client. This is so each player will he able to see enemy projectiles and the like.

Friday, April 11, 2014

Starbound Aces Unity Gameplay and Art

Well, the time for a lot of the server and database work has come to an end. Now the team and I are off to work on the client side of the game. Today I have a few goals in mind for myself. These goals are to refactor the client player ship by using components of scripts to build the ship.

What I hope to accomplish with this is to allow the developers to mix and match different parts of a ship and play with different configurations. Had we had more time on this project we could have even allowed players to mix and match parts for their own ship load outs. Perhaps in another time.

Although my goals for today are short in description, they will take some time to implement. But I will be posting later this week in regards to my progress. Also, below is our first ship model and some textures! Let us know what you think.

Menu background theme
Menu background theme

Main menu button
One of many buttons


Starbound Aces Ship
Space Ship


Wednesday, April 9, 2014

Unity Senior Project Update Video

Whoa! What is this? An Update video for the epic Starbound Aces.

I did a massive update to a lot of the assets in the game as well as the GUI. As promised, this game now looks somewhat slicker. Also, here is a free video for your enjoyment!


Wow! Isn't that awesome, and aren't I awesome to share it with you!? Please comment on what you think so far to help improve the project.

Unity / SmartFox Senior Project Update

Starting early today in regards to programming.

I just finished implementing the high scores page and the server logic for getting the high scores as well as the player score.

This work went along smoothly. Server side, the code just required an extra request handler in the multihandler. Then I added a method to the DBService class. As a note, the DBService class is a utility class with static members. Personally, this is not how I usually go about utilities, but this is C# and Java land.

The client does all of the visual work. It requests the high scores and the current player's current score. It then renders this to the screen using the OnGUI event. Other than that, not much else is done, data is only ever received, not sent.

The impact of this is that it is the first step to giving players a drive to play. Giving a reason for the player to care about our game is the driving force to having a successful game. The goal of Starbound Aces is to offer an action packed competitive game. A scoring system is the first step in doing so.

I will be working on some effects stuff for the rest of the day and make a video to post on YouTube at my channel. When we have some models, I will also find someplace to put the Web player so that every body can enjoy a game or two.

Tuesday, April 8, 2014

Unity and SmartFox Server Update

Whew, I did it!

I spent the last four hours of my life trying to fix code and implement features. I accomplished what I set for goals for myself today. These goals were to streamline the Unity UI and get players registered into the score database table when they register for the game.

The Unity GUI is a powerful tool. It allows for a lot of customization. Add that to their already powerful scripting engine, they have it made. The GUI buttons and test fields that I already had in the game seemed generic and stale. As they should have been. They were using the engine default styles. This was easily fixed by exposing a public GUIStyle to the editor and applying it to all the buttons in that level. Finally, I made it easier to position the buttons and see changes by exposing the rectangles that define their position width and height to the editor. This allowed for a more streamlined approach of custom GUIStyles.

The server side code was a bit of an issue. There were two issues in my way that soaked up a lot of my time. These issues were a dumb mistake on my part and a issue with SmartFox Server itself. The first mistake was that I was setting query executes to not autocommit. With the jdbc drivers this caused any update or insert SQL queries to not be, well executed. The problem was that I was stupidly not calling the connection to commit the changes. The second issue was something I had not run into before. The SignUpAssistantComponent from SmartFoxServer allows you to do pre and post processing by defining an interface. The interface takes several parameters. These are the user, the SFSObject, and the config itself. The preprocessor worked fine with all of the parameters. However, the postprocessor seemed to have lost scope of the SFSObject. Any calls to get any type of data resulted in NullPointerExceptions. I circumnavigated this issue by providing the needed data (the username of the registering player) as a user variable for the temporarily logged in guest user during registration.

All in all, it was a long day and I spent what seemed too long working in circles. I am glad that I was able to accomplish my goals. Soon, I will have a video up with some in-game theme music and *hopefully* some artwork.

Unity GUI and HighScores

Quick update of what I plan on getting done after work today. The goals I have in mind for today are to customize our GUI menus and getting the high scores scene to display player scores.

For the most part, our game is a handful of menus and a multiplayer level. Since most people will be seeing our menu system first, I figured beautifying first would be a good goal to have. Right now we are using the basic GUI.Button calls in the OnGUI event in Unity. This is fine for prototyping, but we need a game with our own look. So, I am using the overloaded method of the GUI.Button methods. These take GUIStyle and GUIContent arguments. Thankfully, these are member fields that are configured to be edited in a friendly manner from the Unity Editor. This will make the life of our artist easier.

Secondly, I want to get the score table in our SQL database to work correctly. What is supposed to happen in the SignUpAssistantComponent postprocessor is that the server will insert the user into the scores table. This will allow them to keep track of their scores. In our game, there is an option to view highscores. In this scene I hope to show the player's current score and rank, the top ten players and their scores. I also want to put in a scrolling menu for going through all of the other players' scores.

I will have an update post later tonight on what I accomplished so far. Hopefully it won't look like I took a step backwards.

Monday, April 7, 2014

Starbound Aces Registration Complete

Whew! What a few days it had been.

I have finally finished the custom sign up component configuration and the server/client code.

The final configuration code sets up the servers configuration to relate to database tables. Originally I was getting an exception thrown due to a weird issue. The SFS (SmartFoxServer) SignUpAssistant was, it seemed, looking at the first column and automatically assumed it was the id column. It assumed it was also of a 32-bit or 64-bit integral value. Well, that was wrong for my database. It was, by mistake, made with a first column of type char var. I quickly remedied this by dropping the table and re-creating it. This resolved all issues I had with both the SignUpAssistant and LoginAssistant components.

Client side the code could not have been simpler. In fact, in regards to the login assistant, I changed nothing. As far as the sign up component, I explained the process in my last post.

When I finished the sign up and login component extensions I went about implementing our server-side game driver. This is the next step in my part of the project.

The game is somewhat represented server side. It contains a lot of the data of current games in memory. For instance, the players, the ships, and the weapons attached to the ships. It also keeps track of player scores. Considering that this game's main focus is on competition and the scores are a large part of that, I thought that keeping the scoring system entirely server side was a good idea. During games, players rack up points, then when this game is over, the server exports and aggregates this score to the player's persistent database row.

On another note, we have music! So next video you will get to hear that. I am very exciting about finishing this project and continuing on at the rate we are. Check back soon for more updates!

Unity Senior Project Update

Over the past two days I have been working on deploying my database to our server and writing code for the client side so that players can register and log in.

The database deployment went smoothly with little hick ups. The code on the server extensions; however, are causing some issues. The SmartFoxServer LoginAssistant and SignUpAssistant are a bit different than I anticipated. Both of these classes expect several parameters when it comes to registering and logging in a user. A lot of these parameters are the database column names and the database column data types. The names are an easy fix by simply calling getConfig() of each of the class instances. The difficulty is that I could not find a reference - in a quick search - to the datatypes each of these columns should be for the Login and SignUp assistant classes. I am going by what the server spews out as errors.

Client side everything has gone smoothly as I can see of right now. The reason I give this little disclaimer is that the client side code can't really be fully tested until the server side code is finished without errors. Right now I have some new GUI code up using the Unity OnGUI event method. I have a new level and script for registration. It is pretty simple, it calls a C# class instance of SmartFox, then calls the SmartFox send() method, finally, it sends the ExtensionRequestion for '$Signup.Submit' server side.

"$SignUp.Submit" is a SignUpAssistant command. The reason it is done this way is that the SignUpAssistant class is treated much in the same way of a multihandler extension class in SmartFoxServer. This is explained in depth here. But in short, a mutlihandler allows you to give it an identifying string for requests to be sent to. Then, there is a period, the second command that the extension will handle. Think of this as a call to a class method.

What I have found out is that the data being sent to the server in the SFSObject on the C# side needs to match the column names set in the SingUpAssitant.getConfig() calls. So, for instance, the SFSObject needs to put in the UtfString with the parameters ("user_name", username) if the SignUpAssistant username field column name is defined as "user_name".

So far, I am having some issues with matching the datatypes that SmartFox's SignUpAssitant expects on my SQL tables. But, I am moving along and soon players will be able to create their own accounts. Then they will be able to log in with those accounts and play.

Saturday, April 5, 2014

One More Step

Well, after some digging around the net, I managed to find some good tutorials on my chosen server technology and database technology. From these tutorials I was able to initialize and setup a database.

I know, doesn't sound too exciting. I agree, not the most pleasant experience. So I will move on to talking about what really matters. What really matters is what we can do with this new remote database and SmartFox extension.

If you read my last post you will see that I wrote some code to interact with a database to allow a custom login for our game. With this we also were able to setup a custom signup interface as well. Using this technology; however, required the use of an SQL database. That meant I either needed to set up a remote database and have the server remotely connect to it. Or I could set up a local database for the server. I am lazy and so went with the latter route. This made configuration and set up simple.

Now, the SmartFox extension ran smoothly, reporting no errors. This means there is only one step left. The step that is left is to roll out code for the client application to allow a user to sign up for our game and to get an email confirmation  with an activation code.

There is a lot of information on this and a lot of ways to do it. However, I will most likely being following the examples for previous peers and the SmartFoxServer documentation.

Next post will be about the client side code to sign up and log in, with the ability for you to do so yourself.

Friday, April 4, 2014

Friday Dataday

I dreamt of data today. Sad, I know. But that is my life. However, it gives me great ideas.

What are these wonderful ideas? Well, several, all part of my Senior Project. These ideas are a website and a phone app.

The website idea is something in its infancy. And I know that it is beyond the scope of our project, but if we can get a game running, imagine what we can do. What does this have to do with data? Everything. Our game will store data on a database (duh) but that database is not specialized to our game, not tied to the API, it is independent. That will be useful. By using the popular MVC design pattern I could create a website for the players. What would this website have? Well, to keep in scope and with my own abilities, it would have a registration page, login page, and a rankings page. That would be pretty neat. By using technologies such as ASP.NET, JSP, AJAX, or other client-server web application technologies, this could be done with ease. It would be a totally independent environment, but connected for a full experience.

Secondly, a phone app has been on my mind. A phone app for Starbound Aces. "You mean another Unity game ported to the phone?" You may ask. No, is what I say. It would be similar to the web page, except you can't register through it. You can keep tabs on your rankings.

Indeed, these are the ideas that come to mind of what can be done with the game and a dedicated database. So much potential, so little time. First thing is first though, time to put up the database.

Let phase two of three begin!

Thursday, April 3, 2014

Todays Work in SmartFox Server

Alright, well, I got done most of what I planned to. The work I planned on getting done was to get all of the Java code set up for creating our own custom login and sign up for our game. This will be exciting once fully done and is one of the larger requirements. What I finished tonight was database related data classes and SmartFox configuration for login and signup.

There are several classes that I added to our game that are meant to serve a small purpose. The purpose of these classes are to be direct relations to the tables we will be querying on our database. I did this so that we would have an efficient, easy to implement, way to store objects in memory when they are needed. Hopefully this will reduce the number of queries we will need by not hitting the database as much. Really, this is the only reason I did this. The classes are simple, private members that reflect data on the database, some different constructors, and setters and getters. They have zero functionality, again, serving only as data containers.

The SmartFox code was simple and easy to put in. I simply added it to our Extension class. I followed some tutorials that were out there and I was able to add it all in with no hitch. No hitch, mostly because I need to have a database set up before I can test it. The code, for Starbound Aces needs, is as follows:

   private void login(){
        login = new LoginAssistantComponent(this);
        login.getConfig().loginTable = "sa_user";
        login.getConfig().userNameField = "user_name";
        login.getConfig().passwordField = "user_password";
        login.getConfig().useCaseSensitiveNameChecks = true;
        login.getConfig().activationField = "user_state";
        login.getConfig().activationErrorMessage =
                "Your account is not yet activated. "+
                "Please check you inbox for the confirmation email";
        login.getConfig().postProcessPlugin = new LoginAssistantPlugin();
    }

Above you can see that the method is made for handling the login request calls. This will be used for logging in players who have set up username accounts. We will also allow guests to log in as an option client side. The LoginAssistantPlugin is a private class implementing the interface with the same name (with a prefixing I).
It does nothing right now and is of no importance at the moment.
   
    private void signUp(){
        signup = new SignUpAssistantComponent();
        signup.getConfig().signUpTable = "sa_user";
        signup.getConfig().minUserNameLength = 4;
        signup.getConfig().maxUserNameLength = 64;
        signup.getConfig().minPasswordLength = 8;
        signup.getConfig().maxPasswordLength = 64;
       

        signup.getConfig().userIsActiveField = "user_state";
        signup.getConfig().activationCodeField = "user_activation_code";
        signup.getConfig().logSQL = true;
       
        signup.getConfig().emailResponse.isActive = true;
        signup.getConfig().emailResponse.fromAddress = "signup@starboundaces.com";
        signup.getConfig().emailResponse.subject = "It is time for you to begin your adventure.";
        signup.getConfig().emailResponse.template = "SignUpEmailTemplates/SignUpConfirmation.html";
        signup.getConfig().preProcessPlugin = new SignUpAssistantPlugin();
        addRequestHandler(SignUpAssistantComponent.COMMAND_PREFIX, signup);
    }

The signup method is a little bit longer. But from the configuration you can see that we have a table name, some requirements, and email confirmation. SmartFox handles a lot of this for us (thankfully) so we merely need to configure it. Unlike the login component, the sign up component needs to be added as a RequestHandler in the extension. To note, login and signup are private classes in the Extension class. SignUpAssistantPlugin is an implementation of the SmartFox interface of the same name (prefixed with an I) and does nothing at the moment.

So far I am a third of the way done. To finish this requirement I need to add the database tables to our server and implement the client interface for signing up and registering.

Until next time, enjoy your own game programming and have a good day!

Smart Fox Server Starbound Aces Style

Lately I have been doing a lot of work client side. I have done some with server side that would help client side move along smoothly. Also, we have just begun putting up issues to filter though what needs to get done on the project. So, for now on, I will be picking from there what I will work on. Tonight I don't have a lot of time so I plan on getting done one requirement. This requirement is to implement a custom user log in server side.

Completing this task shouldn't be too difficult. There are plenty of examples online on how to do this. All I need to do is create the database and tables to do this. Having made a draft, this won't take long either, I just need to move them to the server.

That is pretty much all for now, and I know it was so exciting to read. Check back later for some updates!

Wednesday, April 2, 2014

Starbound Aces Update Video

Here is an update video on the current state of the game. It is me and a classmate in a game, chill around, and shooting things. The quality is bad because I accidentally put a 10 instead of a 100, so bear with me. The rest will look better.

Enjoy!


Unity Project Starbound Aces Update

Well, it seems like my goals resulted in a shorter day of work for me in regards to my senior project. This is good in that it means I didn't run into a whole lot of issues.

As state before I had a few goals in mind for today. These goals were to offer some visual feedback to the client that they died, implement a better smooth follow camera, and begin drafting out tables for the game database.

Player Death Changes

To change how the game handles a player death, I did several things. These were to implement a new script for player death (short and sweet) and add a prefab of an 'explosion'. The prefab for the explosion is nothing special, just a sphere growing in size with a basic Bubble material pulled from the standard assets. The script itself is similar to the Explosion script I have for hitting remote players. The only difference is that after this is played, it request for the player to go back to the lobby. Also, because of how I have my cameras set up, it gets a new handle to a new camera. I will explain this below.

The entire script that handles the room transition and prefab creation is show below:

using UnityEngine;
using System.Collections;

public class PlayerDeath : MonoBehaviour {
    public float effectLength;
    public Camera camera;

// Use this for initialization
void Start () {
        Destroy ( gameObject, effectLength );
        camera = (Camera)Instantiate ( camera, transform.position, transform.rotation );
        camera.GetComponent<SASmoothFollowLook> ().target = transform;
}

    void OnDestroy ( ) {
        GameManager.gameManager.ClientController.Send ( DataType.JOINGAME, "lobby" );
    }

// Update is called once per frame
void Update () {
        transform.localScale += new Vector3 ( transform.localScale.x + 1.0f * Time.deltaTime,
            transform.localScale.y + 1.0f * Time.deltaTime,
            transform.localScale.z + 1.0f * Time.deltaTime );

}
}


Camera Follow Script Changes

Long story short, the changes to my camera following script were extremely simple. The Unity one is nice, as I stated before, but does not meet my needs. My needs being full camera movement in a 3D environment with objects that have the same capabilities of movement. I also kept the smooth following and smooth look at components, but all in one script. Finally, I also attached the camera with the script to the player as a child object. This made the camera following smoother, and tighter. It fit our needs perfectly.

The script is as follows:

using UnityEngine;
using System.Collections;

//Script for a smooth follow and lookat that is more appropiate for our game
public class SASmoothFollowLook : MonoBehaviour {
    public Transform target;
    public float distance;
    public float height;
    public float damping;
    public bool smoothRotation;
    public float rotationDamping;

// Use this for initialization
void Start () {
        if ( target == null ) {
                    Debug.LogError ( "SASmoothFollowLook Script on " + 
    gameObject.name + " has no associated target reference." );
                }    
}

// Update is called once per frame
void FixedUpdate () {
        Vector3 position = target.TransformPoint ( 0, height, -distance );
        transform.position = Vector3.Lerp ( transform.position, 
position, 
Time.deltaTime * damping);

        if ( smoothRotation ) {
               Quaternion rotation = Quaternion.LookRotation ( 
target.position - transform.position, 
target.up );
               transform.rotation = Quaternion.Slerp ( 
transform.rotation, 
rotation, 
Time.deltaTime * rotationDamping );
             } else {
                transform.LookAt ( target, target.up );
            }
}
}

However, one thing that happens is that on the players death, the camera is destroyed too, since it is a child object. So, I simply create the camera as its own prefab, attach it to the player death script, and create a new instance when needed. It works perfectly. I may even consider make a new camera script to make a more cinematic effect.

Database Schemas

In order to create a database that was going to be worth it and done in a timely manner, I needed to consider what was vitally needed. After doing some consideration and the features in the game, I have come down to implementing four tables for our game as it stands right now. This database will support the features listed: persistent user login data, a scoring system, and maintaining game data.

The first feature we want to complete is having our own login setup so that players can have a personal account on the system. Right now, all users log in as a guest with a server supplied name. This ruins the fun. So, creating an account will allow players to pick their own names. It will also allow players to have an entry in the scoring system to keep track of their career scores.

This brings us to the next table. The scoring table. This table is simple and only has an id, a foreign key to the user whose score it maintains, and the player's score itself. That is pretty much it. The score is on a career (lifetime) basis, not per game.

Finally, we have a table containing a list of all games, past and present. The table also maintains the state of these games, active, inactive, or queuing. Right now, when a player logs in, they will only be able to join games created after the fact. This is how registering with the SmartFox Client works, they only get events after the fact. So, the table will maintain all queuing games, and when a player logs in, the server will update the client based on the games in the table that are in a queuing status.

The database is a relational database and uses SQL for queries and what not. 

That is everything I have accomplished so far today, meeting my goals. If I decide to, I may start testing working with the database and server for a custom login.

Starbound Ace's Goals

For the next 8 hours or so today I need to focus on doing my homework, as I typically do on a fine Wednesday.

 As a acknowledgement, I know I have only been posting about my Unity project and pretty much nothing about my GameMaker project. There are several reasons for that. The GameMaker project is done on the side, and the Unity one is actual homework, for a grade, for entertainment, and for a better future.

Anyways, I have several goals in mind today which involve scripting some new features for our game. I also want to fix a persistent issue that I had to report as a bug on github. These goals that I want to accomplish today are to implement a better smooth follow camera, implement a player death prefab, and start drafts of designing our database for the game.

A lot of this doesn't seem too crazy awesome. But I also plan on making a video of what we have so far.

I plan on accomplishing these goals in several ways. To fix the bug, I will have to do some research on SmartFoxServer's events and the data put in their BaseEvent Params for each event. Then I will come up with a solution and implement it.

Right now the game uses the supplied Unity camera follow scripts. They are fine, but not suited for a game with full 3D movement, such as flight. They are more for a platforming game, or one where the character is bound to solid earth. I want the camera to remain behind and above the player at all times with minimal drag and no snapping.

I also wish to add a player death prefab that will give visual fidelity that a player was destroyed. For the local client, this means I need to delay the room transition for a moment. This will allow a client to see themselves be destroyed as well.

Finally, I want to begin with designing the database tables we will be using for our game. So far I know that the tables I want are for registered users, game metadata, and a table of all currently active games. I hope that by implementing this, we will offer a richer user experience.

I will report back later tonight on how things went and any relevant code.

Unity Project Starbound Aces Cleanup and Source

When I last left a post, Starbound Aces was working but there were a lot of issues that needed to be fixed. Tonight was spent doing mostly that. It also allowed me to take a look at the code again to discuss how the final combat system works at a lower level.

To recap, I earlier explained that players have one weapon as of right now, a laser. It is a health based system. Each player has health, each weapon has damage. If a player is hit by a weapon, they lose health equal to the damage the weapon does. When a player has no more health, they die and are removed from the current game.

That pretty much covers what was done this morning and tonight.

How was all of this implemented using Unity and SmartFox? Well, this is where the fun part begins.

Laser

In Unity the laser is actually just a simple raycast that is fire from a muzzle point (which I added) or the center of the object if the muzzle point (a Transform) is null. The direction of the laser is that of the muzzle point. The reason this is important is that a muzzle point can be an independent child object of the ship. This means it can fire in directions other than forward. Think of this as a rotating turret.

The raycast returns an out parameter containing information of what it hit, if it hit anything. I then check this with GetComponent<> to see if the hit object has the RemotePlayerScript. If so, I package up some information in a Dictionary of type Dictionary<string, type>. The information I package is the Id of the player hit ( supplied by RemotePlayerScript ), the player's weapon damage, and the position coordinates of where the laser hit the remote player.

  protected void OnFire() {
        laser.enabled = true;
        laser.SetPosition(0, transform.position);
        laser.SetPosition(1, transform.position + transform.forward * range);
        currEffectCooldown = effectCooldown;
        RaycastHit hitInfo = new RaycastHit();
        if(Physics.Raycast(new Ray(weaponMuzzlePoint.position, 
weaponMuzzlePoint.TransformDirection(Vector3.forward)), out hitInfo, range)){
            RemotePlayerScript rmplayer = null;
            try {
                rmplayer = hitInfo.collider.gameObject.GetComponent<RemotePlayerScript> ();
                Dictionary<string, object> data = new Dictionary<string, object> ();
                data.Add ( "damage", damage );
                data.Add ( "player.hit.id", rmplayer.Id );
                Vector3 contactPoint = hitInfo.point;
                data.Add ( "contact.point.x", contactPoint.x );
                data.Add ( "contact.point.y", contactPoint.y );
                data.Add ( "contact.point.z", contactPoint.z );
                server.Send ( DataType.FIRE, data );
            } catch ( System.Exception e ) {
                //here I actually intend to ignore the null reference because that means i hit something that isn't a player.
            }
        }
        currCooldown = cooldown;
    }

Then the SFSClient script handles it from here:

    private void SendFireRequest ( object data ) {
        SFSObject sfsdata = new SFSObject ();
        Dictionary<string, object> firedata = data as Dictionary<string, object>;
        sfsdata.PutFloat ( "damage", ( float ) firedata[ "damage" ] );
        sfsdata.PutInt ( "player.hit.id", ( int ) firedata[ "player.hit.id" ] );
        sfsdata.PutFloat ( "contact.point.x", ( float ) firedata[ "contact.point.x" ] );
        sfsdata.PutFloat ( "contact.point.y", ( float ) firedata[ "contact.point.y" ] );
        sfsdata.PutFloat ( "contact.point.z", ( float ) firedata[ "contact.point.z" ] );
        SFSInstance.Send ( new ExtensionRequest ( "server.fire", sfsdata, SFSInstance.LastJoinedRoom, useUDP ) );
    }

After this is done, a request is sent to the server as part of the extension multi-handler. For right now, the extension simple unpacks the information and repacks it for sending off to all of the other players in the game. In future releases the server will actually verify that it is possible for the player to even hit who he is saying he hit. If not, it will just throw away the message and not respond.

    private void handleFire(User user, ISFSObject params){
        ISFSObject response = SFSObject.newInstance();
        response.putFloat("damage", params.getFloat("damage"));
        response.putInt("player.hit.id", params.getInt("player.hit.id"));
        response.putFloat("contact.point.x", params.getFloat("contact.point.x"));
        response.putFloat("contact.point.y", params.getFloat("contact.point.y"));
        response.putFloat("contact.point.z", params.getFloat("contact.point.z"));
        send("player.hit", response, user.getLastJoinedRoom().getPlayersList());
    }

The finally step is all players getting the information that player A has hit player B (the remote player for player A). Then a message is sent from the SmartFox Event handler client side using the OnEvent method provided by the EventListener/Messenger Interface I designed. When a remote player object realizes that the server says it was hit it does several things. All of this is handled in RemotePlayerScript. Each of these events are as follows: subtract damage from health and instantiate a small explosion at the impact points.

The ClientPlayer scenario:

            case "player.hit":
                if (o.GetType() != typeof(Dictionary<string, object>)) {
                    return;
                }
                Dictionary<string, object> hitdata = o as Dictionary<string, object>;
                float dmg = (float)hitdata["damage"];
                Vector3 contactPoint = new Vector3(
                    (float)hitdata["contact.point.x"],
                    (float)hitdata["contact.point.y"],
                    (float)hitdata["contact.point.z"]);
                
                hullHealth -= dmg;
                Instantiate(Resources.Load("HitPrefab"), contactPoint, transform.rotation);
                Debug.Log("Damage Taken by Client. Damage: " + dmg + " Remaining Health: " + hullHealth);
                break;

The Remote Player scenario:

    private void handlePlayerRemoteHit(object o){
        Dictionary<string, object> data = o as Dictionary<string, object>;
        if ( ( int ) data[ "player.hit.id" ] == remoteId ) {
            localHealth -= ( float ) data[ "damage" ];
            Vector3 contactPoint = new Vector3 (
                ( float ) data[ "contact.point.x" ],
                ( float ) data[ "contact.point.y" ],
                ( float ) data[ "contact.point.z" ] );
            Instantiate ( Resources.Load ( "HitPrefab" ), contactPoint, transform.rotation );
            Debug.Log ( "Damage taken <Damage : Health> <" + ( ( float ) data[ "damage" ] ).ToString () + " : "
                + localHealth.ToString () + "> to remote player." );
        }
    }
Finally, how the SmartFox client delegates these messages:

    private void PlayerHitResponse ( SFSObject sfsdata ) {
        float damage = sfsdata.GetFloat ( "damage" );
        int playerid = sfsdata.GetInt ( "player.hit.id" );
        Debug.Log ( "Player hit: " + playerid.ToString () );
        Dictionary<string, object> fdata = new Dictionary<string, object> ();
        fdata.Add ( "player.hit.id", playerid );
        fdata.Add ( "damage", damage );
        fdata.Add ( "contact.point.x", sfsdata.GetFloat ( "contact.point.x" ) );
        fdata.Add ( "contact.point.y", sfsdata.GetFloat ( "contact.point.y" ) );
        fdata.Add ( "contact.point.z", sfsdata.GetFloat ( "contact.point.z" ) );
        if ( playerid == SFSInstance.MySelf.Id ) {
            OnEvent ( "player.hit", fdata );
        } else {
            OnEvent ( "player.remote.hit", fdata );
        }
    }

Death

Handling the destruction of a player is pretty straight forward here. A player keeps track of his own health in the ClientPlayer script in Unity. When it receives enough "player.hit" messages from the server, its health will eventually reach 0. When this happens the player notifies the server that they have died. Then, the player object is destroyed and the actual user moved back to the lobby.

        if (hullHealth <= 0.0f) {
            server.Send(DataType.DEATH, null);
            //TODO: handle death for player clientside
            server.Send(DataType.JOINGAME, "lobby");
            //TODO: be careful, the camera will be destroyed if the player is
        }
Then the SFSClient handles this as so:

    private void SendDeathRequest ( object data ) {
        SFSObject sfsdata = new SFSObject ();
        SFSInstance.Send ( new ExtensionRequest ( "server.death", sfsdata, SFSInstance.LastJoinedRoom, useUDP ) );
    }

When the server receives the event from the client that the client has died, it notifies the rest of the clients by sending out the dead player's id to each player left in the game.

    private void handleDeath(User user, ISFSObject params){
        ISFSObject response = SFSObject.newInstance();
        response.putInt("id", user.getId());
        
        send("death", response, user.getLastJoinedRoom().getPlayersList());
    }

Finally, when the player's receive the message, they simply ask the GameManager to remove and destroy that player's representing RemotePlayer object.

    private void DeathResponse ( SFSObject sfsdata ) {
        OnEvent ( "player.remote.death", sfsdata.GetInt ( "id" ) );
    }
    private void handlePlayerRemoteDeath ( object o ) {
        if ( ( int ) o == remoteId ) {
            GameManager.gameManager.RemoveRemotePlayer ( remoteId );
        }
    }

To improve this, I would actually store the player's health on the server. That way the server is in charge and tells a player if they are dead or still alive. This would help reduce cheating.

As always, the source code is now up on the repository at https://github.com/hollsteinm/GSPSeniorProject. However, this time I decided to add source code to help pinpoint where I am talking about. Let me know what you think about this approach!