Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Rocket Fist - Throwing one punch at a time

Discussion in 'Works In Progress - Archive' started by DanielSnd, Apr 15, 2015.

  1. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Thanks guys!! \o/

    ___________________________________________________

    So, I've been working pretty damn hard on the game over the past few days, but I've been neglecting actually updating the blog with what I was doing because a lot of it simply isn't flashy nor I actually had something to show for it… But I might as well :D

    First things first, we're at the end of our 5th day in Greenlight. In 5 days we became number 15 of the list and got lots of positive comments and support from the community ^^ I'm quite happy also that our vote ratio is pretty much the inverse of the average top 50 game :D


    Alright, so, what have I been working on? Well, the game was being pretty much being duct-taped together since the original prototype about 8 months ago. I've learned so much over the course of these 8 months, both on side-projects and with “real” programmers over at the centre fro digital media. While looking over how to make the online mode, it was clear that if I kept the code-base the way it was it would be quite a nightmare to keep on working with it.

    So I went back and reorganized the codebase, re-wrote most of the game manager and game-modes logic. I spent most of the week with the game in an unplayable state because I was changing so much, but finally it's playable back again and much sturdier, ready for my next steps! :D


    Since I reorganized the way I was keeping player data, I figured I might as well take the time and reorganize the menu. I made it so the first thing the player is prompted with is picking the color they want. While playtesting I noticed certain people actually wanted to be a specific color, and it was kind of a hassle to get them to be what they wanted to be. Plus, for team-based gameplay, all you have to do is pick the same color as other player, which makes that part of game-mode selection easier to handle. I went ahead and changed the weapon logic and game-mode logic to account for color instead of specific player when checking whether to damage someone or not. So now the team-mode is fully functional :)

    Next up it'll go straight into the ”Press Ok to confirm” screen. Most times when playing people didn't really care for the names, and just wanted to play, so the actual changing of the name is now an option, otherwise it'll use the last name picked using that controller (Before it was last name picked on that player ID, but since ID is determined by who presses first, usually when playtesting the person that typed the name was still holding the same controller but was now a different ID). I also redid the name-picking system with a grid of letters, which makes the name selection process way less painful.

    For adding and removing bots, that are now considered by the Game Data like regular players, it's now done with the press of a button. Another button will toggle the difficulty setting for the bots. They'll always attempt to pick an unpicked color. Still not sure how I'm going to choose the robot's color individually without making it over-complicated.


    For the Online Mode menu, you get the same Name selection and color selection menu, then you're taken to the regular forge networking menu, redone within my UI system. I'll use the name and color to spawn the right player and show the player's name once he's connected.


    Another thing I finally did was to remove NGUI from the project (finally!) So I also took the time to make some 2D panels that look like the panels I have on the 3D Menu and use those for my scoreboards. I also added a little text that specifies what those things are (In the survival mode's case… Lives! :D which was something that people always got confused at first, some people thought those numbers were the score/kills or whatever).

    Well, there's more things that are happening behind the scenes, but nothing to really show for it, just boring code stuff. So that's it for now!

    Ah! I'm oficially done with my classes, and I'll only be starting my new job on September First (Part-time!) so I'll have this whole week before pax to work full time on the game, after Pax I'll be working part-time on it for a long time! Rocket Fist will be moving along way faster from now on ^^ I'm hoping to get it into an early-access worthy state by the end of october.
     
  2. georetro

    georetro

    Joined:
    Jan 18, 2013
    Posts:
    218
    Wow really well done for all your hard work, it looks really good. May I ask, did you create your multiplayer infrastructure or did you use some plugins?
     
  3. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Thanks :D
    I'm using Forge Networking ( http://forum.unity3d.com/threads/forge-networking-superpowered-fully-cross-platform.286900/ ) totally in love with it. I tried photon and bolt before, just could not wrap my head around it... Forge is so simple and easy to understand ;o could not be doing it without them!
     
    RavenOfCode likes this.
  4. georetro

    georetro

    Joined:
    Jan 18, 2013
    Posts:
    218
    @DanielSnd Oh wow that actually does look decent. Think I might give it a go and try it out. Thanks for telling me :)
     
    DanielSnd likes this.
  5. RavenOfCode

    RavenOfCode

    Joined:
    Apr 5, 2015
    Posts:
    869
    I just looked it up, its looks really good and simple, I might try it out too. :)
     
    georetro likes this.
  6. Keith90

    Keith90

    Joined:
    Sep 27, 2013
    Posts:
    116
    Great job Dan! Looks awesome and I know you've been working hard to get everything aligned so whatever is needed later will HOPEFULLY be easy to incorporate. I can't wait to see more.

    Also, I recommend Forge as well. I've been using it myself after 3-4 days and it's easy, simple and the support is amazing. Well worth it.
     
    DanielSnd and georetro like this.
  7. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Thanks! You guys should totally try it! The guys that are developing it and the community around it are just amazing! :DThey have a slack group with users and people are always sharing information and helping each other. If you do get it ask to be invited to the slack \o

    Yep, that's what I'm hoping XD thanks!

    __________________________________________________________

    Alright, now that the code is better organized I started to try and get my game data networked :D

    I have tried photon before, bolt, and even tried following a tutorial series on the new UNET but every single time all I ended up with was a headache and the feeling that I would never be able to make Rocket Fist an online game. I just couldn't wrap my head around it! Whenever someone would ask me if Rocket Fist was going to have an online mode I would answer that it wouln't because I tried to learn how to write networking code several times unsucessfully and I didn't have the funds to hire someone to do it for me. I even considered doing a kickstarter for Rocket Fist to try and hire a programmer to do it!

    Then I met forge, and within about 2 hours of messing around with it and it's tutorials this is how I felt:


    This was my first test using forge with Rocket Fist, while following this Forge tutorial. I had my PC as a server/client and my macbook as a client connected to the pc, and the whole thing just worked. Out of the box all that's needed to get positions and rotations syncing is to extend one of the classes in your object from their class NetworkedMonobehavior, and override Awake, Update and Start. Using “isOwner” to check if I own the object, I ignored the input if I didn't own the object and accept the input if I did, as simple as that, my players were moving around the screen. With a few extra variables tracked using [NetSync] and some RPCs for the actions, soon enough I had dash, picking up rockets and shooting working.


    Now as you see, both players are green and the rockets weren't even taking their color when picked… Back then the way I was keeping track of the game data was quite a mess, and to get that mess to sync back and forth would be a nightmare, that's one of the reasons that led me to reorganize and clean up my code.


    So this is how my Game Data is kept now. It's a persistent singleton that has settings in it and a list of playerinfo. I'm so happy with it I figured I might as well share the code here. I don't know if this is the best way to do things as most of my programming was self-taught, but I'm happy with it :D

    Code (Csharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using BeardedManStudios.Network;
    5.  
    6. //This serialiazable class will keep our player information.
    7. [System.Serializable]
    8. public class PlayerInfo
    9. {
    10.     //For now all I'm using this for is to keep a nice name in the inspector list.
    11.     public string identifier;
    12.  
    13.     //I use this private serializable field to be able to see it from the inspector.
    14.     [SerializeField]
    15.     private int _ID;
    16.     //The public field will try and update the network helpers if the game is in networked mode :)
    17.     //That way I won't need to change the way I do things for the local mode, I'll just set these values
    18.     //like I regularly do and the data will be updated automatically.
    19.     public int ID
    20.     {
    21.         get { return _ID; }
    22.         set
    23.         {
    24.             if (_ID != value)
    25.             {
    26.                 _ID = value;
    27.                 GameData.info.SetInfoNetworkHelpers(this);
    28.             }
    29.         }
    30.     }
    31.  
    32.     //This will be set with Forge's NetworkedID from NetworkMonobehavior, so I can know who is the "owner" of this.
    33.     public ulong networkID;
    34.     //Player 3 letters name they can pick :)
    35.     public string name;
    36.     //Is this a local player or a networked one?
    37.     public bool isLocal = false;
    38.     //Which input am I using? For use with Rewired, awesome controller wrangling asset.
    39.     public int input = 4;
    40.  
    41.     [SerializeField]
    42.     private int _score = 0;
    43.     public int Score { get{return _score;}
    44.         set
    45.         {
    46.             if (_score != value)
    47.             {
    48.                 _score = value;
    49.                 GameData.info.SetInfoNetworkHelpers(this);
    50.             }
    51.         }
    52.     }
    53.  
    54.     [SerializeField]
    55.     private int _lives = 0;
    56.     public int Lives
    57.     {
    58.         get { return _lives; }
    59.         set
    60.         {
    61.             if (_lives != value)
    62.             {
    63.                 _lives = value;
    64.                 GameData.info.SetInfoNetworkHelpers(this);
    65.             }
    66.         }
    67.     }
    68.  
    69.     [SerializeField]
    70.     private int _kills = 0;
    71.     public int Kills
    72.     {
    73.         get { return _kills; }
    74.         set
    75.         {
    76.             if (_kills != value)
    77.             {
    78.                 _kills = value;
    79.                 GameData.info.SetInfoNetworkHelpers(this);
    80.             }
    81.         }
    82.     }
    83.  
    84.     //If I'm in networked mode, the GameManager will spawn a GameDataNetworkHelper and assign it here.
    85.     public GameDataNetworkHelper networkHelper;
    86.  
    87.     //Here I can keep my color with a nice enumerator easy to read and understand :D
    88.     public PlayerColor color = PlayerColor.Green;
    89.     //And here I can know if I'm an AI and if I am, which difficulty of AI.
    90.     public AIMode AI = AIMode.None;
    91. }
    92.  
    93. public enum PlayerColor {
    94.     None = 0,
    95.     Green = 1,
    96.     Orange = 2,
    97.     Blue = 3,
    98.     Pink = 4
    99. }
    100.  
    101. public enum AIMode {
    102.     None = 0,
    103.     Easy = 1,
    104.     Medium = 2,
    105.     Hard = 3,
    106.     Insane = 4
    107. }
    108.  
    109. public class GameData : MonoBehaviour {
    110.     //Static private variable that holds the current reference to our existing GameData object.
    111.     private static GameData _info;
    112.  
    113.     //Static variable to check if the game is about to quit
    114.     public static bool isShuttingDown;
    115.  
    116.     //Here's a list of our own
    117.     public List playerInfo = new List();
    118.     public bool Networked = false;
    119.     public bool Ghost = false;
    120.     public string Arena = "Game4P_PC";
    121.  
    122.     //Static public variable that gets and sets our private variable that holds the current refernece to our existing GameData object.
    123.     public static GameData info
    124.     {
    125.         //If we try to get this variable, this is what will happen
    126.         get
    127.         {
    128.             //If there is a private variable _info already set, we'll return it to whoever asked about it and stop here.
    129.             if (_info != null) return _info;
    130.  
    131.             //If we got to this line it means we haven't returned it, so we don't have a private _info set yet.
    132.             //We should then check if there is one on the scene already that we can set so we don't have to create one.
    133.             _info = GameObject.FindObjectOfType();
    134.  
    135.             //Let's check if now that we tried to set _info to our search on the scene for objects that contain the Component GameData returned something.
    136.             if (!_info)
    137.             {
    138.                 //Nope, if I got here, it didn't return anything, we must create one!
    139.                 //However, if I just clicked on stop playing and the client is shutting down and I try to create one it'll give me an error... So let's check
    140.                 //our isShuttingDown static variable, I set it down in a OnApplicationQuit function that unity calls whenever it's exiting.
    141.                 if (!isShuttingDown && Application.isPlaying)
    142.                 {
    143.                     //Alright, so I'm playing and I'm not shutting down, all set to create our singleton! :D
    144.                     //Let's try to instantiate it from the Resources folder, there should be a prefab there with
    145.                     //the name GAMEDATA to be loaded. Cool thing about instantiating from prefab is that we can
    146.                     //easily change our variables whenver we want instead of going through code.
    147.                     GameObject singleton = (GameObject)Instantiate(Resources.Load("GAMEDATA"));
    148.  
    149.                     //Let's name it GAMEDATA, right now it's called GAMEDATA(Clone) because of the instantiation
    150.                     singleton.name = "GAMEDATA";
    151.  
    152.                     //Now let's set our _info by getting component GameData on the object we just spawned in the scene.
    153.                     _info = singleton.GetComponent();
    154.                 }
    155.             }
    156.             //Alright so if I got here it means that I set a new _info... So...
    157.             //Tell unity not to destroy this new info when loading a new scene!
    158.             if (_info != null)
    159.             {
    160.                 DontDestroyOnLoad(_info.gameObject);
    161.             }
    162.  
    163.             //After all this hard work, let's return our newly set _info to whoever was asking about it :)
    164.             return _info;
    165.         }
    166.     }
    167.  
    168.     void OnApplicationQuit()
    169.     {
    170.         isShuttingDown = true;
    171.     }
    172.  
    173.     void Awake()
    174.     {
    175.         // If my static variable is null and I just awoke on the scene, I should set it to be me. And make sure I persist between scenes
    176.         if (_info == null)
    177.         {
    178.             _info = this;
    179.             DontDestroyOnLoad(this);
    180.         }
    181.         else
    182.         {
    183.             //If there's already a static variable set and it's not me... Then I should be destroyed... There should only be one!!!
    184.             if (this != _info)
    185.                 Destroy(this.gameObject);
    186.         }
    187.     }
    188.  
    189.     //If we're online and I'm the server, this function will update the info on the network helpers for all the helpers.
    190.     public void SetInfoAllNetworkHelpers()
    191.     {
    192.         if (Networking.PrimarySocket == null || !Networking.PrimarySocket.IsServer)
    193.         {
    194.             return;
    195.         }
    196.         for (int i = 0; i < playerInfo.Count; i++)
    197.         {
    198.             SetInfoNetworkHelpers(playerInfo[i]);
    199.         }
    200.     }
    201.  
    202.     //If we're online and I'm the server, I'll ask the network helper to send an RPC with this player info variables!
    203.     public void SetInfoNetworkHelpers(PlayerInfo _pInfo)
    204.     {
    205.         if (_pInfo.networkHelper != null && Networking.PrimarySocket != null && Networking.PrimarySocket.IsServer)
    206.         {
    207.             _pInfo.networkHelper.SendServerPlayerInfo(_pInfo.networkID,_pInfo.Kills,_pInfo.Lives, _pInfo.Score, _pInfo.ID);
    208.         }
    209.     }
    210.  
    211.     //If I want to create a new PlayerInfo (either when I'm online and someone connected or I'm at the menu locally
    212.     //and someone pressed start. This function will create a new one and pick a new available ID for it. This way
    213.     //if someone dropped out whoever connects next will fill up that ID.
    214.     public PlayerInfo AddPlayerInfo(bool _local = true) {
    215.         PlayerInfo newPlayerInfo = new PlayerInfo ();
    216.         playerInfo.Add (newPlayerInfo);
    217.         newPlayerInfo.ID = getNextAvailableID();
    218.         newPlayerInfo.isLocal = _local;
    219.         return newPlayerInfo;
    220.     }
    221.  
    222.     //Will go over the player infos and return the one with this specific player ID.
    223.     public PlayerInfo GetPlayerInfoByID(int id)
    224.     {
    225.         for (int i = 0; i < playerInfo.Count; i++)
    226.         {
    227.             if (playerInfo[i].ID == id)
    228.             {
    229.                 return playerInfo[i];
    230.             }
    231.         }
    232.         return null;
    233.     }
    234.  
    235.     //Will find what's the next available ID.
    236.     public int getNextAvailableID()
    237.     {
    238.         if (playerInfo.Count == 0)
    239.         {
    240.             return 1;
    241.         }
    242.  
    243.         List testList = new List();
    244.         for (int i = 0; i < playerInfo.Count; i++)
    245.         {
    246.             testList.Add(playerInfo[i].ID);
    247.         }
    248.  
    249.         for (int i = 1; i < 10; i++)
    250.         {
    251.             if (!testList.Contains(i))
    252.             {
    253.                 return i;
    254.             }
    255.         }
    256.  
    257.         return 0;
    258.     }
    259.    
    260.     //This function will check if the list is out of order, and if it is it'll sort it.
    261.     public void SortList()
    262.     {
    263.         int previousID = 0;
    264.         for (int i = 0; i < playerInfo.Count; i++)
    265.         {
    266.             if (playerInfo[i].ID >= previousID)
    267.             {
    268.                 previousID = playerInfo[i].ID;
    269.                 continue;
    270.             }
    271.  
    272.             playerInfo = playerInfo.OrderBy(p => p.ID).ToList();
    273.             return;
    274.         }
    275.     }
    276.  
    277. }
    Now to keep this stuff updated I'm using a object that each client spawns and owns, this object helps keep track of data that the client should own (like it's player color and name), and receives data from the server to update the PlayerInfo it's responsible for (for the important game mode info like kills, lives, player ID).

    Code (Csharp):
    1. using UnityEngine;
    2. using BeardedManStudios.Network;
    3.  
    4. public class GameDataNetworkHelper : NetworkedMonoBehavior
    5. {
    6.     //Reference to the PlayerInfo I own.
    7.     public PlayerInfo mPlayerInfo;
    8.  
    9.     //My player ID.
    10.     public int ID;
    11.  
    12.     //NetSync is an easy way to execute a function whenever the value changes.
    13.     [NetSync("SetMyPlayerInfo", NetworkCallers.Everyone)]
    14.     public string name;
    15.     [NetSync("SetMyPlayerInfo", NetworkCallers.Everyone)]
    16.     public int input = 4;
    17.     [NetSync("SetMyPlayerInfo", NetworkCallers.Everyone)]
    18.     public int color = (int)PlayerColor.Green;
    19.  
    20.     public bool isLocal = false;
    21.     public int Score = 0;
    22.     public int Lives = 0;
    23.     public int Kills = 0;
    24.  
    25.     //This function is called by the [NetSync] whenever one of those values changes, it'll update the PlayerInfo I own accordingly.
    26.     protected void SetMyPlayerInfo()
    27.     {
    28.         if (mPlayerInfo == null) return;
    29.  
    30.         mPlayerInfo.color = (PlayerColor) color;
    31.         mPlayerInfo.input = input;
    32.         mPlayerInfo.name = name;
    33.     }
    34.  
    35.     //This function will call an RPC with all the info I want to be sent through it.
    36.     public void SendServerPlayerInfo(ulong _NetworkedId, int _kills, int _lives, int _score, int _id)
    37.     {
    38.         RPC("RPCServerPlayerInfo", NetworkReceivers.AllBuffered, new object[] { _NetworkedId, _kills, _lives, _score, _id });
    39.     }
    40.  
    41.     //So this is the RPC I use to request updated info from the server.
    42.     [BRPC]
    43.     public void RequestUpdatedInformation()
    44.     {
    45.         //Only do this if I'm the server, if not just ignore it.
    46.         //This check shouldn't be needed since I'm sending RPC to server directly, but just in case.
    47.         if (Networking.PrimarySocket.IsServer)
    48.         {
    49.             //Ask Game data to ask for a SendServerPlayerInfo for all network helpers.
    50.             GameData.info.SetInfoAllNetworkHelpers();
    51.         }
    52.     }
    53.  
    54.     //This RPC will set my info with information sent from the server.
    55.     [BRPC]
    56.     public void RPCServerPlayerInfo( ulong _NetworkedId, int _kills, int _lives, int _score, int _id)
    57.     {
    58.         if (NetworkedId == _NetworkedId && mPlayerInfo != null )
    59.         {
    60.             ID = _id;
    61.             Score = _score;
    62.             Kills = _kills;
    63.             Lives = _lives;
    64.             //If I'm not the server I also want to update the information on my player info stuff so it's the same
    65.             if (!Networking.PrimarySocket.IsServer)
    66.             {
    67.                 //For debugging purposes I'm asking the chat to show the message with the received RPC.
    68.                 Chat.instance.ChatMessage("Received RPC " + ID + " score " + Score + " kills " + Kills + " nID " +
    69.                                           _NetworkedId);
    70.  
    71.                 mPlayerInfo.ID = ID;
    72.                 mPlayerInfo.Score = Score;
    73.                 mPlayerInfo.Lives = Lives;
    74.                 mPlayerInfo.Kills = Kills;
    75.  
    76.                 //Let's ask GameData to sort the list just in case. It'll only sort it if it's needed anyways.
    77.                 GameData.info.SortList();
    78.             }
    79.         }
    80.     }
    81.  
    82.     //Yeah... I don't want to be destroyed on load... so... let's tell unity to keep me around alright?
    83.     protected override void Awake()
    84.     {
    85.         DontDestroyOnLoad(gameObject);
    86.         base.Awake();
    87.     }
    88.  
    89.     //When I start, if the game manager network controller doesn't have a reference to me it should add one to it's list.
    90.     protected override void Start()
    91.     {
    92.         base.Start();
    93.  
    94.         if (!GameManager.instance.NetworkController.dataHelpers.Contains(this))
    95.         {
    96.             GameManager.instance.NetworkController.dataHelpers.Add(this);
    97.         }
    98.  
    99.         //If I'm the owner I should let my game manager know I'm here so he can get a reference directly to me.
    100.         if (IsOwner)
    101.         {
    102.             GameManager.instance.DataHelperRegistered();
    103.             //For each player info in there, if it doesn't have a helper and it's local, then it most probably is my info
    104.             //I should set my stuff in there like my NetworkedID from Forge, my own reference, color and etc.
    105.             //Should also save a direct reference for it here so I can talk to it better later.
    106.             foreach (PlayerInfo _info in GameData.info.playerInfo)
    107.             {
    108.                 if (_info.networkHelper == null && _info.isLocal)
    109.                 {
    110.                     _info.networkID = NetworkedId;
    111.                     _info.networkHelper = this;
    112.                     name = _info.name;
    113.                     tempName = name;
    114.                     input = _info.input;
    115.                     color = (int)_info.color;
    116.                     mPlayerInfo = _info;
    117.                 }
    118.             }
    119.         }
    120.         else
    121.         {
    122.             //Well íf I'm not the owner, I should create a new player info for it and set my id and helper into it. Also
    123.             //Pick a reference for it to update it later.
    124.             PlayerInfo _createdInfo = GameData.info.AddPlayerInfo(false);
    125.             _createdInfo.networkID = NetworkedId;
    126.             _createdInfo.networkHelper = this;
    127.             mPlayerInfo = _createdInfo;
    128.         }
    129.         //If I'm not the server, and I just finished creating my player info stuff on game data, I should ask the server
    130.         //to send me updated information for everyone so I can make sure I'm syncing everything alright.
    131.         if (!Networking.PrimarySocket.IsServer)
    132.         {
    133.             RPC("RequestUpdatedInformation", NetworkReceivers.Server);
    134.         }
    135.     }
    136.  
    137.     //Those are just there to test the syncing, if I'm the owner and I press a button, I change values in this helper :)
    138.     private string tempName;
    139.     protected override void Update()
    140.     {
    141.         base.Update();
    142.  
    143.         if (!IsOwner)
    144.             return;
    145.  
    146.         if (Input.GetKeyDown(KeyCode.I))
    147.         {
    148.             int tempColor = color;
    149.             tempColor++;
    150.             if (tempColor >= 5)
    151.             {
    152.                 tempColor = 0;
    153.             }
    154.             color = tempColor;
    155.         }
    156.  
    157.         if (Input.GetKeyDown(KeyCode.O))
    158.         {
    159.             name = "Bob";
    160.         }
    161.  
    162.         if (Input.GetKeyDown(KeyCode.P))
    163.         {
    164.             name = "LOL";
    165.         }
    166.  
    167.         if (Input.GetKeyDown(KeyCode.L))
    168.         {
    169.             name = tempName;
    170.         }
    171.     }
    172. }
    And then I have my GameManager. Which was always used for the whole game, but got now an upgraded networking section which is only really used if it's in networked mode :D This one I'm only showing the networking-relevant parts.

    Code (Csharp):
    1. //I have a separated class to keep my networking variables separated in the inspector for my game manager.
    2. [System.Serializable]
    3. public class NetworkingController
    4. {
    5.     public bool networkInitialized = false;
    6.     public NetworkingManager mNetworkingManager;
    7.     public bool isPlaying = false;
    8.     public bool AllowedSpawning = false;
    9.     public GameObject chatPrefab;
    10.     public GameObject DataHelperPrefab;
    11.     public NetworkingManager NetworkingManagerPrefab;
    12.     public GameDataNetworkHelper mDataHelper;
    13.     public List dataHelpers = new List();
    14.     public Action FinishedSpawningPlayer = null;
    15. }
    16.  
    17. //In my Game Manager I set a variable for my serializable class to keep my inspector tidy.
    18.     public NetworkingController NetworkController;
    19.  
    20.     //In my awake function, that now is overriding from SimpleNetworkedMonobehavior so I can send RPCs, I will only call the base.Awake if
    21.     //I'm actually in a Networked game, which Game Data would be set Networked if I am. Then to make sure I check if I have a PrimarySocket.
    22.     //If I do then I call my StartNetworkingGameManager.
    23.      protected override void Awake()
    24.     {
    25.         if (GameData.info.Networked)
    26.         {
    27.             base.Awake();
    28.  
    29.             if (Networking.PrimarySocket != null)
    30.             {
    31.                 StartNetworkingGameManager();
    32.             }
    33.         }
    34.     }
    35.  
    36.    
    37. #region Networking
    38. //Over here I see if NetworkingManager exists (It's a forge thing). If it doesn't I'll spawn one form a prefab I have
    39. //set on my NetworkController class. That manager contains references to my networkedmonobehaviors.
    40.     public void StartNetworkingGameManager()
    41.     {
    42.         if (NetworkingManager.Instance == null)
    43.         {
    44.             Instantiate(NetworkController.NetworkingManagerPrefab.gameObject);
    45.             //If succesfully instantiated lets set a referene to it.
    46.             if (NetworkingManager.Instance != null)
    47.             {
    48.                 NetworkController.mNetworkingManager = NetworkingManager.Instance;
    49.             }
    50.         }
    51.         //If I have been initialized before, no need to do this, if I haven't, let's continue!
    52.         if (NetworkController.networkInitialized)
    53.         {
    54.             return;
    55.         }
    56.  
    57.         //Now I have been initialized :)
    58.         NetworkController.networkInitialized = true;
    59.  
    60.         //If connected let's toggle this bool to allow spawning, and let's add an event to fire on player disconnect.
    61.         if (Networking.PrimarySocket.Connected)
    62.         {
    63.             NetworkController.AllowedSpawning = true;
    64.             Networking.PrimarySocket.playerDisconnected += PlayerDisconnected;
    65.         }
    66.         else
    67.         {
    68.             Networking.PrimarySocket.connected += delegate()
    69.             {
    70.                 NetworkController.AllowedSpawning = true;
    71.                 Networking.PrimarySocket.playerDisconnected += PlayerDisconnected;
    72.             };
    73.         }
    74.     }
    75.  
    76.     //This function is only used for testing purposes right now, it adds a kill to either me or other players.
    77.     void TrySyncData(bool myself = false)
    78.     {
    79.         if (IsServerOwner)
    80.         {
    81.             foreach (var _info in GameData.info.playerInfo)
    82.             {
    83.                 if (myself)
    84.                 {
    85.                     if (_info.networkHelper != null && _info.networkHelper.IsOwner)
    86.                     {
    87.                         _info.Kills++;
    88.                     }
    89.                 }
    90.                 else
    91.                 {
    92.                         if (_info.networkHelper != null && !_info.networkHelper.IsOwner)
    93.                         {
    94.                             _info.Kills++;
    95.                         }
    96.                 }
    97.             }
    98.         }
    99.     }
    100.  
    101.     //This is what I'm using to see if my tests are working, a simple OnGUI UI to show my helpers and my playerinfos on the screen.
    102.     //Plus 2 buttons to test the syncing.
    103.     private void OnGUI()
    104.     {
    105.         if (!NetworkController.networkInitialized)
    106.         {
    107.             return;
    108.         }
    109.  
    110.         int i = 0;
    111.         foreach (var _gameDataNetworkHelper in NetworkController.dataHelpers)
    112.         {
    113.             i++;
    114.             GUI.Label(new Rect(280, 20 * i, 400, 20), "Data Obj " + _gameDataNetworkHelper.name);
    115.             i++;
    116.             GUI.Label(new Rect(280, 20 * i, 400, 20), "ID " + _gameDataNetworkHelper.ID);
    117.             i++;
    118.             GUI.Label(new Rect(280, 20 * i, 400, 20), "color " + (PlayerColor)_gameDataNetworkHelper.color);
    119.             i++;
    120.             GUI.Label(new Rect(280, 20 * i, 400, 20), "input " + _gameDataNetworkHelper.input);
    121.             i++;
    122.             GUI.Label(new Rect(280, 20 * i, 400, 20), "networked ID " + _gameDataNetworkHelper.NetworkedId);
    123.             i++;
    124.             GUI.Label(new Rect(280, 20 * i, 400, 20), "Kills " + _gameDataNetworkHelper.Kills);
    125.             i++;
    126.         }
    127.         i = 0;
    128.         foreach (PlayerInfo _info in GameData.info.playerInfo)
    129.         {
    130.             i++;
    131.             GUI.Label(new Rect(500, 20 * i, 400, 20), "PlayerInfo " + _info.name);
    132.             i++;
    133.             GUI.Label(new Rect(500, 20 * i, 400, 20), "ID " + _info.ID);
    134.             i++;
    135.             GUI.Label(new Rect(500, 20 * i, 400, 20), "color " + _info.color);
    136.             i++;
    137.             GUI.Label(new Rect(500, 20 * i, 400, 20), "input " + _info.input);
    138.             i++;
    139.             GUI.Label(new Rect(500, 20 * i, 400, 20), "networked ID " + _info.networkID);
    140.             i++;
    141.             GUI.Label(new Rect(500, 20 * i, 400, 20), "Kills " + _info.Kills);
    142.             i++;
    143.         }
    144.  
    145.         GUILayout.BeginArea(new Rect(Screen.width * 0.7f, 0, Screen.width * 0.3f, Screen.height * 0.2f));
    146.  
    147.  
    148.         if (NetworkController.AllowedSpawning)
    149.         {
    150.                 if (GUILayout.Button("Try Add Kill Other", GUILayout.Height(Screen.height * 0.1f)))
    151.                 {
    152.                     TrySyncData();
    153.                 }
    154.                 if (GUILayout.Button("Try Add Kill Myself", GUILayout.Height(Screen.height * 0.1f)))
    155.                 {
    156.                     TrySyncData(true);
    157.                 }
    158.         }
    159.         else
    160.         {
    161.             GUILayout.Label("Connecting to server...");
    162.         }
    163.         GUILayout.EndArea();
    164.  
    165.         GUILayout.BeginArea(new Rect(0, Screen.height * 0.85f, Screen.width, Screen.height * 0.15f));
    166.        
    167.         GUILayout.Label("Connections: " + Networking.PrimarySocket.Connections, alignmentGuiStyle);
    168.         GUILayout.Label("Server time: " + NetworkingManager.Instance.ServerTime, alignmentGuiStyle);
    169.  
    170.         GUILayout.EndArea();
    171.     }
    172.  
    173.     //Whenever I get disabled I want to unregister the event for playerdisconnected.
    174.     void OnDisable()
    175.     {
    176.         if (Networking.PrimarySocket != null)
    177.         {
    178.             Networking.PrimarySocket.playerDisconnected -= PlayerDisconnected;
    179.             NetworkController.networkInitialized = false;
    180.         }
    181.     }
    182.  
    183.     //Whenever the player disconnects I want tor emove the player from the list and remove it's playerinfo as well
    184.     private void PlayerDisconnected(NetworkingPlayer player)
    185.     {
    186.         for (int i = players.Count - 1; i >= 0; --i)
    187.         {
    188.             if (players[i] == null)
    189.             {
    190.                 players.Remove(players[i]);
    191.                 continue;
    192.             }
    193.             if (players[i].MPlayerInfo.networkID == player.NetworkId)
    194.             {
    195.                 players[i].removePlayer();
    196.             }
    197.         }
    198.  
    199.         for (int i = GameData.info.playerInfo.Count - 1; i >= 0; --i)
    200.         {
    201.             if (GameData.info.playerInfo[i] == null || GameData.info.playerInfo[i].networkID == player.NetworkId)
    202.             {
    203.                 GameData.info.playerInfo.Remove(GameData.info.playerInfo[i]);
    204.             }
    205.         }
    206.     }
    207.    
    208.     //When a data helper registers, if I'm it's owner I want to set a reference of it in my networkcontroller.
    209.     public void DataHelperRegistered()
    210.     {
    211.         foreach (GameDataNetworkHelper gData in NetworkController.dataHelpers)
    212.         {
    213.             if (gData.IsOwner)
    214.             {
    215.                 NetworkController.mDataHelper = gData;
    216.                 break;
    217.             }
    218.         }
    219.     }
    220.  
    221.     //Unity calls this when the level ended loading, if it's networked it's a good moment to check if we should spawn data helpers.
    222.     void OnLevelWasLoaded(int level)
    223.     {
    224.         if (GameData.info.Networked)
    225.         {
    226.             SpawnDataHelper();
    227.         }
    228.         LevelInitialization();
    229.     }
    230.  
    231.     //This is called when the level ends loading, so if my level is the Lobby I should check if I already have a data helper set.
    232.     //If I don't have a data helper set I should see if I'm connected and spawn one, if I'm not, I should register a delegate to
    233.     //spawn one whenever I do get connected.
    234.     private void SpawnDataHelper()
    235.     {
    236.         if (Application.loadedLevelName.Contains("Lobby"))
    237.         {
    238.             if (!NetworkController.mDataHelper)
    239.             {
    240.                 if (Networking.PrimarySocket.Connected)
    241.                     Networking.Instantiate(NetworkController.DataHelperPrefab.gameObject, NetworkReceivers.AllBuffered, null);
    242.                 else
    243.                 {
    244.                     Networking.PrimarySocket.connected += delegate()
    245.                     {
    246.                         Networking.Instantiate(NetworkController.DataHelperPrefab.gameObject, NetworkReceivers.AllBuffered, null);
    247.                     };
    248.                 }
    249.             }
    250.         }
    251.     }
    252.  
    253. #endregion


    And that's it :) Just like that I got the helpers spawning and syncing each other. The cool thing is that the whole system works in a way that all I really have to do in my actual game logic code is to change the PlayerInfo like I always do, and the whole syncing of it happens outside of my game logic like magic *_*

    Well, that's it for now, next step is to start spawning my players based on this player info and to get the actual game-mode logic working with it :D

    Until next time!
     
    georetro and RavenOfCode like this.
  8. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382

    We did it guys! :D We got greenlit in 9 days! Thank you so much for your support in this process, it was great to see so many people excited about our game!!! These were our stats as we got the greenlight:


    This week I’ve dedicated entirely to the online mode :) I had to rewrite a good part of the game to make it easier to sync across the network and I can say the code is way cleaner and easier to work with now. It currently syncs all player and weapon actions. I still don’t want to “promise” an online mode, but I’m fairly confident about it! ^^ Next step is actually getting the match flow to work on the online mode with game-over state and all. So far I’ve been testing in a kind of “lobby scene”.

    Oh! If you’re going to PAX, I'll be expoing the game really close to PAX this sunday over at the Seattle Indies Expo! Come by and say hi \o

     
    PenguinEmporium, JanCDS and georetro like this.
  9. georetro

    georetro

    Joined:
    Jan 18, 2013
    Posts:
    218
    Wow really amazing. Well done :) How was the green light process?
     
  10. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    So, it’s been a long time since I worked on Rocket Fist… My life went through some changes, I started a new job, and whenever I had the time I was just too tired and not in a mood to work on it. However now with some extra changes I got my time back :) and I want to get back at working on Rocket Fist daily. Keeping this devlog helped me a lot to stay motivated, hopefully it’ll do the same again.


    Well, today’s task has been a long time coming. It’s replay. I have spent quite some time in the past messing around with replay, I was trying to record all positions, rotations, visibility of particle effects and etc… It was getting pretty confusing and convoluted and not working as it should.

    This last week I had the not-very-original idea of simply recording/replaying screencaptures of the past X seconds (That’s how Towerfall does it :eek:). I searched around a bit and found this post with that exact solution :D



    Based on that code I changed it around a little bit so I could show the latest rendertextures in a RawImage without actually having to save it to textures, which I believe isn’t as performance heavy :) Worked like a charm. Send a quick build to a friend with a lower-end computer and didn’t see much of an FPS drop, so I’m counting this as a win :D + if I really like the replay I can save it to a gif with one button ^^

    I also added a bigger/cooler scoreboard, so people can figure out better what’s going on (Now with the lives going out, maybe people will stop being confused that that number actually means they’re losing lives).
     
    FuzzyQuills and RavenOfCode like this.
  11. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Never thought that would work for replays! Mind if I borrow that solution off you? I was thinking of putting an instant replay feature in my current project... :)

    EDIT: GIF finally loaded... I approve the replay screen; definitely a nice touch! :)
     
  12. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Lol, I didn't invent it, no need to ask my permission xD
    The solution is right here: http://forum.unity3d.com/threads/free-moments-a-quick-gif-replay-recorder.319842/
     
  13. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    This past week was absurdly productive. I was invited to showcase the game at the Vancouver's Twitch Meetup this past sunday so with that deadline in mind I rushed to get as much done as I could, including the idea for a Twitch Interaction mode, which would be getting votes from players on what crazy things should happen.


    With the in-between matches replay screen the game flow got better, to improve it even more I added a proper game over screen with some stats on the players and a better order of who did the best. Before it was simply a 2 second message which would instantly go back to the game.

    To get the twitch interaction features working, I implemented the beginning of the power up system. I haven't made the actual spawning and picking up of powerups but I made the system that gives the effects and takes them away after a certain time or event. From the power up base script I can extend to create other effects/powerups :).

    These are the powerups I made for now:

    • Confusion - Inverted controls curse, if you touch other player it will pass on to it (bomberman inspired).
    • Big - Big robot, easier to hit.
    • Shrink - Small robots, harder to hit
    • Blackout - Everything gets REALLY DARK.
    • SlowMotion -SLOOOOW MOOOOOTIOOOOON
    • SuperSpeed - OMFG EVERYTHING IS SO FAST I CAN'T EVEN
    • RunSlower - Player movement decreased
    • RunFaster - Player movement increase
    For the Twitch interaction, I made a new option in the options screen where you can input your channel's name. In the game I then connect to the channel's IRC using this nifty little script and for each message received I check to see if it's content is one of the possible votes. If a new match starts at least 25 seconds later than the last time we counted votes I will activate the picked powerup for all players with an absurd amount of time to last.


    The meetup was loads of fun, and I got a 10 minute time window to show the game on the meetup's official stream :D That gave me the chance to playtest the new twitch interaction mode, which people seemed to enjoy. I also added a “Random mode” to play with the random powerups changing each match for extra craziness, it was quite fun. My favorite mode to play in is the Slow motion mode, makes everything feel so epic!

    During the meetup as usual I noticed a few bugs so I fixed them (fists that was thrown by a now dead players not being able to damage anyone; counter fist not getting new color from the person who countered it.)


    After the meetup I improved on the replay screen, making it bigger and adding feedback to the gif-saving (It will stop and wait until the gif is saved, and show on the text the progress of saving).

    Tonight I'm attending the local game developers meetup and I'm bringing the new version :) Let's see how it fares there.
     
    RavenOfCode likes this.
  14. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    So, one thing that people who have been following Rocket Fist's development for a while know is that I've only had the same 2 levels in the game for like… forever (Even before the game had art, the 2 levels were pretty much the same layout, only thing I did was cover that layout with art).

    One of the main reasons for that is that it's a pain in the ass to create the levels, the tile editor I was using back then stopped working once I update to Unity 5 and even when it did work it wasn't super easy. So I decided to put some time into making a level editor for Rocket Fist. I figured I could use the Steam Workshop to upload and download levels users make, so I started looking into building a runtime level-editor.




    A long while ago I picked up the Rotorz Tile Editor from the Asset Store. It came with a really simple example of runtime level editor that caught my attention. Started experimenting with it, asked some questions to the developer (which were answered SUPER QUICKLY, awesome support!) and in no time I had something functional working :)


    From there I went to work into actually saving the levels. On their support forums they had an example of serializing the level to JSON, I based myself off of that and adapted it into XML which I find easier to read and mantain. Once I had the Save/Load working as intended I spent some time adding some UI to assist with the level creation.

    One thing I really enjoy about this is that I have different tile systems for different brush types. If I currently have a floor brush selected and I erase, I'm erasing the floors, not the walls on top of them. If I have a decoration brush selected I'll only erase decoration, and so on. That makes my life easier as I don't have to constantly be switching brushes if I delete a wall to place a floor on that tile instead.

    I also made a way to playtest the levels quickly by pressing play. It spawns a keyboard-controlled player and with keyboard keys you can spawn bots if you so desire.




    The Level Editor is now quite functional, with one more day I should get it to the place I want it to be. I'm missing a way to setup the desired camera distance… Camera distance is different depending on the aspect ratio you're playing in. If I'm playing in 16:9 the camera should be more zoomed in than if I was playing in 16:10… Not sure how I'm going to figure this out, will probably have to come up with a way to calculate distance based on aspect ratio, right now on the levels I made I set it up manually for each aspect ratio. I'm also missing a way to setup the tracks for the Ghost carts, but that one is easy to solve, just need to create the UI for it.

    Well, that's it for this update :) Things have been progressing well, really happy to be working in this project again.
     
    kittik, JanCDS and RavenOfCode like this.
  15. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Over the past few days I made some improvements to the level editor :)


    The UI is now prettier, I reorganized a few of the buttons and changed the colors/sprites.


    I added a button for Level Preferences in which the player can adjust the camera, the path for the Ghost Carts, color correction and music options.


    The player can also go into the lighting options and adjust the lighting of the level further, changing it's color and intensity.

    I also added a marquee mode (by pressing shift) so you can click and drag over an area for quick positioning of several objects.



    With that, the level editor is fully functional. Next step is making those levels created with it loadable in the actual gameplay mode.
     
    RavenOfCode likes this.
  16. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Alright, this week has been quite productive :D I finished up the level editor system, now it's possible to pick which level you want to play in. The custom level editor arenas are selectable, and if you do play on them it will open a loader scene which loads the level from XML and batches the static elements to save drawcalls *_* working like a charm. Not entirely sold on the UI for it, will probably change in the future. The level editor also got new music and SFX by Thiago Adamo :D


    Another menu related update is that now I added an "OK" and a "Back" button to the name selection. It was super annoying to have your name there already spelled and have to respell it just because… Now you can just mash ok and it will keep the letters that are already there.


    Another update that has been a long time coming is the addition of more materials for team-mode. Whenever people on playtests picked same color it was hard to differentiate between them in the team mode because the material was the same (except for green and orange.


    I ended up adding some extra colors too. More often than not people would pick the same color without wanting to be in a team, just because there were only 4 colors to pick from… So I added 3 more. Purple, White and Black. Will experiment with them and see if they're worth keeping or if I have to come up with different ones. This does mean I could have a 6 player deathmatch… Not sure I should though :eek: maybe I should test that.


    Last but not least, I "finished up" (mostly) the power up system. Powerups now can be spawned, picked up, expired… It still can use more polish, and will need a menu to pick frequency of spawns or even disable specific ones… But it's mostly there and I like it :)



    Another thing I added to the powerups after a friend suggested it to me (Thanks Raf!), and this definitely still needs some playtesting to know if I'll keep, is that the powerups are actual physical objects. They can get knocked around by weapons and can bounce of other powerups. This way you can actually throw a "bad" powerup into another player.



    Well, that's it for now :) Let me know if you have any suggestions/feedback
     
    RavenOfCode and JanCDS like this.
  17. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Today was a nice productive day :) I also got to stream a little bit over at http://www.twitch.tv/danielsnd some friends showed up and we got to chat while I worked :D it was pretty cool, I want to do that more often.


    It's always bothered me how little we could notice of the robot details from the regular camera position. I had fixed it on the rocket fist redoing it's art to show off the details more, but I haven't touched the robot's art in a while. So I revamped it's art (from 1k tris to 5k tris) making it more detailed and with a larger gap between panels. Looks better and can see the details more :)



    During the stream I finished up some temporary art for the other powerups I have implemented already, and I finished up the logic for picking and spawning random powerups :D Only thing left is the menu to pick powerups and power up frequency, which I should tackle next.



    Since I added the extra colors, I was thinking of experimenting with having more than 4 players, so I made it possible now :D I guess I need to buy more controllers XD



    I also made the first of the dynamic tiles I'm planning to introduce :D the conveyor belt. It's pretty funny ^^

    I think that's it for now, tomorrow I'll probably be mostly tackling menus D: I need to revamp the game mode menu :/
     
    RavenOfCode likes this.
  18. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Today I sent the game to a playtest meeting back home, ran by a group of developers from my hometown. It was nice seeing things that were confusing new users, I haven't playtested the game in a while as well, so there was lots of valuable information.



    Something unexpected was the small map I made to record that little Power ups gif last night. I forgot to delete it so it shipped with the build for the playtest, and playtest they did. Surprisingly enough, some people liked the closed-quarters chaotic combat of that really small level. I tested it a little bit with a bot and I liked some aspects of it, I iterated a bit on the design and came up with this one that I felt gives enough opportunity to dodge and escape.

    One thing people had trouble with, and this wasn't the first time I saw people confused with this, was the "Press A to join" menu. There were too many options with the buttons to add/remove bots and toggle bot difficulty, so I changed the way it worked to keep things more contained. I also added at the bottom of the menus the buttons that are being used to control it, to clear any remaining confusion.






    Other than that, I fixed some small bugs that they found and that was it for the day. Next up I shall make the new level blocks and start making some new levels!
     
    RavenOfCode and Kellyrayj like this.
  19. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Today I added 2 more colors. Now there are 9 possible colors to choose from, which means… I could actually have 8 simultaneous players…

    So I did! I made a bigger level for 8 players and added support for 8 players D:




    It is REALLY chaotic D: can't wait to playtest with real people.
     
    RavenOfCode likes this.
  20. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    So, I made a bunch of new level blocks a while ago, and simply never implemented them. So today I decided to finally implement those. And I made a quick level with them to test them out.


    The level is for 2 players only, and it makes you pass through conveyor belts to reach the other side. It’s kinda interesting, adds a different dynamic to things, and is has some big open areas. Looking forward to testing it with real people


    I ended up also making some changes to the level editor. The brushes were way too small to see. I made them bigger. Also made it so if there are more available then possible to show a scrollbar appears. Plus now there are tabs of different brush types on the top, so you can only see the brushes of the type you want to use at the moment.


    In the Level preferences side, I wanted to revamp a few things because I wanted to also be able to pick how many players I want to be able to play this level, so I can limit the levels per number of players (Don’t want to support 8 players playing on a level intended for 2 players D:). Also whenever I do implement other modes, I want to be able to make levels that are only available on that mode, so I also made an area to account for that.


    I still need to implement the code to make that possible, but it’s getting late so I’ll do that tomorrow. Plus, I’ll be adding even more blocks I made a while ago and never implemented, like the ones I made for the music-reactive level.
     
    RavenOfCode likes this.
  21. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    This past 2 days were pretty productive. I started by importing the new door art and implementing a dynamic block for the door, looping around the level.



    I can't wait to play around with it in real-matches :D The bots don't quite understand how to account for that yet (I have a plan for making them understand, but I don't want to spend time on that right now). The doors auto-setup on the level if they find another suitable door, otherwise if you do place a door that doesn't have a suitable pair, it'll appear with it's doors closed :D So it can also be a decoration piece even if you don't want the looping when making a level.



    One thing that new players have been commenting on is that they don't have enough time to figure out where is their character (Since spawn points are randomized for people to not get too attached to the same starting strategy). So I finally decided to fix that by adding a little "Ready? GO!" moment on the start of the level.


    Other than that, I finished importing the new brushes and started working on some levels. The brushes window was way too crowded and it was annoying to keep scrolling trying to find what I wanted, so I reorganized the UI a bit, pulling most of the options to the top and leaving only the camera preview and the brushes on the left, that improved the usability a lot.

    I went over and added some new color correction options, which added a bit more of a variation on the looks of the levels. I also recreated the 2 classic levels using the level editor and updated their visuals a bit (or a lot in case of the classic 2p one). Now I only have 2 scenes in my builds (menu and level editor), all the levels are loaded by XML :).









    This is how the levels are looking like at the moment. I haven't playtested most of them with people, but I'm going to be doing that this weekend :D (+ Tomorrow I'll take it to playtest with my ex-game design teacher at the CDM ^^ Looking forward to hearing his feedback).
     
    RavenOfCode and JanCDS like this.
  22. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
  23. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Ok, so it's been a little while since I wrote a post, and a lot of things and decisions have been happening in the meanwhile so I wanted to update you guys. (Whoever is reading this, you, person who reads and never comments, I still like you, despite your lack of comments, I would like you even more if you commented, made questions, suggestions or something, but it's ok, I get it :eek:)


    Alright, so in november I was hard at work in Rocket Fist again and loving it, I decided I should just polish the game and add everything it was lacking for an early access release, a minimum viable product. I set myself the deadline of December 15th to have something worth of releasing in early access, and as you have seen on the devlog, I worked pretty damn hard at it.


    This week was it, the week of december 15. This date wasn't completely arbitrary, this week there were a couple of opportunities to playtest Rocket Fist, and it would be the perfect test for my ”Is this ready for an early access?” question. My ex-game-design teacher had some time to playtest with me and give me feedback; My friend Kramer had a house-party filled with game devs which I could playtest with; And last but not least, the vancouver Full Indie Meetup was happening.


    The self-imposed deadline came, I had put everything I wanted to put into the game, all of the minimum viable product features I wanted were there, the game had even more levels than I had originally planned for the minimum viable product and people were loving it. The new dynamic levels were a great hit, people loved to stop and point things on the replays, they were comparing kills on the game over, they would change levels between matches and play around with settings, it was everything I was expecting! A lot of the people I was talking to thought I had already released the game, they told me it felt complete and they believed it was ready.



    Of course, I found some bugs that need fixing, had new ideas of things I should add, things I should fix, things I should remove (Like this on the gif above, this is one thing I should remove XD even though it looks cool, it plays terribly)… However, the game is ready, it could be out there, it could make an early access release. Then the question came, should it though?

    Had a meeting this week with my friends over at Amnia Interactive (They're helping to publish the game :D) and we were pondering whether or not to do Early Access, the pros and cons.

    Lots of people don't view early access under a good light anymore, and a lot of the media won't cover early access games. I don't know if I would even get any coverage with Rocket Fist even as a full release, but I know that if I try with it as early access my chances are even slimmer, would be better to make a great first impression with a even more complete game. :/ Releasing in early access would also create a lot of new tasks, like community management, customer support, social media, etc. Those will take away part of my development time, if I don't do early access I would still have those new tasks but it would be at a moment that all the other game tasks would be mostly done, with only bugfixes and minor updates remaining.

    I'm fortunate enough to have lots of access to playtesters here. I can get a lot of feedback and testing done without the need for early access, it would be nice to see a community start forming around the game (hopefully that will happen once the game is out XD), but that can also wait, so… I have decided to wait and keep working on the game towards a full release. I have set the date of April 25 as a release date for Rocket Fist, and planned accordingly. I believe I can achieve everything I wanted to achieve with the game by March 15, and use the rest of the time for certification and marketing.


    So, what is next for Rocket Fist? If the game feels so close to completion according to playtests, what are you going to be doing from now until March 15/April 25? Well… I was going to write about that now too, but this post is so long I'll leave it for another post :)
     
  24. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382


    I like taking cool screenshots of my games, and over time I ended up putting up a couple of scripts together to help me get the perfect moment for a good screenshot.

    As a unity developer, at first I used to try and manually pause the gameplay with the pause button of Unity Editor and manually pick the Camera game object and move it. I had a hard time getting the right angle with the transform tool, in the end my camera was in the wrong place to continue the game and the screenshot wasn’t as high quality as I wanted because I was taking it in the editor.

    So I put together pauseFreeCamera.cs , which can:
    • Press a button to toggle “Screenshot Mode”
    • Screenshot mode sets timescale to 0 “pausing the game”
    • Allows for disabling certain scripts while in screenshot mode, and re-enables them when exiting screenshot mode.
    • Allows for camera movement using the mouse while in screenshot mode (pan, zoom, rotate) for getting those nice angles. (I got this part of the script from somewhere, but couldn’t find the original to credit :/)
    • Remembers the original camera position/rotation and returns you to it once screenshot mode has been disabled to resume gameplay
    • Let’s you go to the next frame with a button, for when your pause wasn’t exactly where you wanted but close.
    • With one button toggles “Slowmotion Mode” which allows you to use the middle mouse scroll to control the timescale, if getting that perfect moment you want is tricky within the game’s regular speed.
    That script has made it so much easier for me to get the exact moments for nice screenshots, I love the control it gives me over time and the camera :)

    Now for actually taking the screenshots, I made a modified version of Saad Khawaja’s hi-resolution screenshot script.
    • One button to take a screenshot at the set resolution.
    • Can pick a number to enlarge the resolution by, for taking high-resolution screenshots, which will produce better sharper results when scaled down.
    • Allows for transparent screenshots by toggling a boolean, for making cooltransparent pngs like this.
    • Saves to a screenshots folder outside of Assets, so unity won’t try and use the screenshot as a texture.
    With those 2 scripts in place I have a blast taking screenshots of Rocket Fist, playing around and stopping at good moments to find nice angles :D Here are some examples from today’s #screenshotsaturday:



    Lastly, I made a little 2 minutes video showing the scripts in action and talking a little bit more about then.



    Well, that’s about it, I hope this helps someone out there how it has been helping me :) If you have any questions feel free to ask.
     
    Last edited: Dec 19, 2015
    Aiursrage2k likes this.
  25. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    This past few days I've worked on a couple of things, one of them I want to save for a longer post later on so I won't mention for now.



    I've wanted to introduce costumes into Rocket Fist for a long while now, and I finally got around to it, made 5 costumes and made a system to select and use them. The system also colors parts of the costume based on the player's team color.



    From a top-view, you can't see the costume as well, but you can still get the gist of it, and I believe that it helps to further differentiate between players (team-matched will be made easier to differentiate with players using fairly different costumes :D)



    Now, the player's "press start menu" had several screens to actually get to play, which was kind of annoying. I decided to just consolidate all the choices the player can make there to just one screen there, because most of the time the player doesn't actually want to make all those choices, all he wants to do is press READY and play.

    So if you want to change your color, you can change there. Costume? There. Now if you want to change your name, you can press a button there to take you to the old name-selection screen, but since the game remembers the last name you used, chances are you probably don't want to change your name.

    I believe that'll make that menu easier to navigate. Looking forward to playtest the game with costumes :D



    Oh, a long time ago a friend of mine, Erik, suggested a billiards 8-ball costume, long before I decided to make costumes for the game xD I finally made his suggestion, and it's probably one of my favorite costumes:
     
  26. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382

    Merry Christmas folks! :D HO HO HO CKET FIST!
     
    Mothil likes this.
  27. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    So I figured it’d be cool to look back at the year of 2015 and what I accomplished/did in my path as a Game Developer.

    January
    January I got to assist 2 teams in the Global Game Jam, made some quick cuby-art crossyroad style for a team and some Fungus code for another :)


    That same month Rocket Fist’s original prototype was born, as a local multiplayer 2p vita game:


    April
    Made a little procedural action game called Sede for a Game Jam:

    And made a crazy little game about a gardener sword for Ludum Dare:


    May
    Finished my masters second term project, a cool little PS Vita game called Blanket.

    Went down to Seattle to showcase Rocket Fist in the Power of Play Indie Expo


    June
    Made a really cool Virtual Reality experience for a class. That one got to be showcased in a lot of different events :D Had lots of fun with it.


    August
    Got to port the VR Experience we made for that class in June to the Vive in a Vive Game Jam.

    Wrapped up Term 3 project in the masters degree, which is so NDA I’m not sure what I can say about it, this picture was on the public blog so It should be good to share:

    Lastly, made some quick art for a friend’s Ludum Dare entry, Monster Sheep Vs The Aliens

    Rocket Fist was greenlit after 9 days in the Steam Greenlight :D


    September
    Went down to Pax and got to Showcase the game in the Seattle Indie Expo and in a Pre-pax party at the Facebook HQ :D


    Started working on my first game industry job, which led to me stopping working on Rocket Fist for a while :(

    October
    Changed jobs to my second game industry job :D which led me to freeing some time to work on Rocket Fist again, Rocket Fist started to take huge strides toward completion.



    2015 Review

    2015 was a great year for me, I learned a lot, completed my masters degree, oficially entered the games industry and produced a lot of great work! :D I wanted to develop a longer-term commercial project for a while now and this year I finally got it started with Rocket Fist. Today as the year ends I feel way more confident on my skills as a game developer and I’m excited to see what 2016 has in store for me :)

    2016
    I’m so excited for 2016 :D It has a lot of uncertainty for me, questions waiting to be answered. Things can either go terribly wrong for me, or awesomely right, and I can’t wait to see which way it’ll go ^^
    • I’m working towards releasing Rocket Fist in April of 2016, can’t wait to see if people will actually care/like this game I’ve been working in so much. Rocket Fist has already taught me so much, and I feel this upcoming year it will teach me even more as I will have to deal with things like Marketing, PR and Community Management :D Not to mention everything that’s involved with releasing a game in consoles.
    • As part of marketing for Rocket Fist, I’m hoping to start a streaming schedule. I actually have wanted to do a regular gamedev-stream for a while, hopefully in 2016 I’ll make that a habit.
    • The next project(s)… Every now and again I’m daydreaming about my next personal project(s). One thing I know for sure is that I don’t want to do it alone. I don’t regret making Rocket Fist as my baby project, but I do want to experience sharing more of the project’s responsabilities with someone else, I’ve started talking with someone about possibly making the next project together in 2016 :) I think that’d be a lot of fun.
    Well, that’s about it for this retrospective :D Looking forward to see what the next year has in store for me and for Rocket Fist :)

    Happy new years everyone!
     
    RavenOfCode and kittik like this.
  28. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382


    A year of Rocket Fist.
     
  29. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    People seemed to really enjoy the post in which I shared my scripts to take marketing screenshots, so let's share another script that I made a long while ago and I always import into every new project I make, my SoundManager script!


    It's a thing I've seen lot of newcomers struggling with, they come up with this weird solutions involving lots of audio sources all over the place tangled in the code, then whenever they need to change an audio clip it becomes this huge problem. I've heard more than once from sound designers in game jams that they made way more sounds but the programmer didn't have the time to implement it into the game…

    Well, if that sounds like something you've experienced, this might help you!

    This is the system I use to implement sounds in my games, it allows for:

    • All of the sounds are prefabs inone folder, so it's easy to know where to go to change things later.
    • Each prefab, which I call “SoundGroup” is a group of audioclips, from which one of them will be picked and played at random. A SoundGroup can be one single audioclip if you so desire. This makes having random sounds for the same action really easy.
    • You can also pick a random pitch range for the soundgroup to introduce even more variation.
    • If the SoundGroup is marked as music, instead of picking a random one it'll play them in order as a playlist.
    • For easy implementation of per-level-music if you have a soundgroup on the “Resources\SoundGroups” folder with the same name of a level and that level is played, the SoundGroup will start playing automatically.
    • It uses a built-in pooling system to reuse the SoundGroup gameobjects instead of destroying it every time, that way there's no garbage collection mess while the game is playing :D
    • It uses playerprefs to store and use volume preferences, volume preferences (0 minimum 1 maximum) are then multiplied by the volume you picked on the prefab's audio source :)
    • This part might annoy some programmers but I find it way easier for me… You can call the sounds in the code by using the prefab name (string). However, for the programmers that hate doing that kind of stuff, you can call it with the prefab.
    • I commented the hell out of this script D:
    • Calling it is as easy as: hurtSFX.PlaySound();
    Well, that's about it :D I find it really useful for my projects, so hopefully it'll help you on yours as well, you can download it here.

    I also recorded a quick video showing how to use it.
     
    Last edited: Jan 6, 2016
    RavenOfCode likes this.
  30. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382


    Alright, so for 2016 I set as a personal goal to stream at least twice a week on a regular schedule! I picked mondays and wednesdays from 3pm to 5pm PST!http://twitch.tv/danielsnd

    I just had my first stream yesterday afternoon and It was a lot of fun :D

    One of the people who reads my devlog (Or maybe the only one that reads the blog, since no one else comments on anything ;_;) actually turns out to be a really cool developer from another local multiplayer game called Skyhook, we talked a bunch and I ended up watching his daily stream. He gave me some tips on how to setup my stream better with Streampro, which helped me a lot :D Now my stream looks really cool with a custom RocketFist themed overlay.

    I'm not sure if it's because I streamed earlier in the day, or if it's because the overlay makes it look more professional, but there were a lot more people on the stream than usual and they were actually chatting with me and asking questions, which made the whole experience way better :) I'm now looking forward to the next stream.



    What I made on the stream yesterday was a little fire hazard for Rocket Fist, so the player can catch on fire when it touches fire. It adds random input so it's harder to control your character while it's on fire :D

    I also integrated it into Uncle Knuckle's firepuking attacks.

    Well that's it :D If you'd like to always know when I start my stream make sure you give me a follow on http://www.twitch.tv/danielsnd
     
    RavenOfCode likes this.
  31. RavenOfCode

    RavenOfCode

    Joined:
    Apr 5, 2015
    Posts:
    869
    Here ya go:
    This game has come along way, and I think its pretty darn awesome. :) I'm a huge fan of couch coop games, and multiplayer games in general, and this fits right into both of those.

    The graphics all blend together very nicely and I like the idea of costumes. :)

    Just curious, but is there any chance of this coming out for the Wii-U/x-Box One/360?

    Also thanks for sharing those scripts, the way you do sound seems alot better than the way I was doing it. ;)

    As far as suggestions go, maybe making powerup/tile that increases the amount of bounces/distance the fist has before it looses its velocity.

    Overall great job! This game looks great. :)
     
  32. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Hahahah thanks! :D Yay for comments and feedback *_*!

    Yes :) I'm currently working with XBone, I'm still considering whether or not to go for the Wii U, since I'd have a hard time porting the controllers and not sure if it'd be worth it all the extra work :/

    You're welcome :D Glad that people are enjoying it, I'll be sharing more in the future, I have tons of useful scripts that I made a while ago and always use in my new projects.

    I like that! :D Will use it!

    Thanks for the great comment ^^ Now I have 2 people that comment to me about the devlogs! hahahhaa
     
    RavenOfCode likes this.
  33. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382


    Today I made some advances with the Fire Hazard during the stream. I implemented it into the Uncle Knuckle projectile attacks so the projectile leaves a trail of fire hazards behind it :)



    I like the trail idea so much I decided to make a powerup out of it. So I changed the way the firehazard works to not affect health actors of the same color of it, made a method to tint it to the player's color and made it so if you have this powerup you'll constantly spawn a trail of fire hazard behind yourself that will affect players of other colors.



    I've been meaning to do powerups that affect the weapons for a while, so I finally added a system into my powerup system to do just that :) The weapons on their shoot method look for powerups currently in use by the player with the shooter ID and hook into that powerup, whenever it goes harmless again or changes color the powerup gets unhooked and the weapon goes back to normal. I have used that to also add a trail of fire to the fists thrown by the player with that powerup.

    This opens a lot of cool powerup possibilities that enhance fist functionalities :D I also hooked up some events like Hit wall and Hit other fist into the powerup so I can make use of those in powerups as well… Possibly a fist that explodes in AoE damage when hitting walls?



    Another thing I did a while ago but haven't showed you guys is the new singleplayer game over screen xD I also added a little glitch effect in it, I think it looks so cool :D

    Actually, I said I was going to write a longer post about a new Rocket Fist thing and then I never did… Well, that thing is the Singleplayer D: I know what I said before, but… this time it's different, I swear! I believe my mistake before was that the singleplayer was going so far away from the multiplayer, a lot of the time you didn't even have a Rocket Fist with you, the enemies were so different and honestly, boring. A lot of it was running around empty rooms backtracking, the whole thing was a disaster.



    So I made a little prototype of this new singleplayer idea, it's way simpler and plays pretty much exactly like the multiplayer does, I'm even reusing the multiplayer AI for it :) Pretty much you go from arena to arena fighting a team of enemies that are against you, they also use Rocket Fists (I might make some special ones that use other things as well) so there are always weapons around. When you clear the room a trapdoor opens to the next arena, and you fight your way down different sectors of this building. Each sector has a boss you need to defeat to unlock the next sector. I think it can be actually pretty fun :D

    Now I need to make new enemy art, looking back at the old ones… I don't like any of them :/ Well, that's it for today, this was a long post D:
     
    RavenOfCode and kittik like this.
  34. kittik

    kittik

    Joined:
    Mar 6, 2015
    Posts:
    565
    Your project looks amazing. I'll be checking your updates from now on. :) Well done on getting Greenlit so fast.
     
    DanielSnd likes this.
  35. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Thanks! :D That's always great to hear!

    __________________________________________________

    It all started this thursday when Phaze Pyre, one of the friends I’ve sent a test build to, told me the game was freezing his whole computer when he booted it up. That is a big problem and I couldn’t reproduce in my machines, however my machines are pretty powerful so it’s hard for me to find those kind of issues.

    I started profiling it, and as I was in fact doing a lot of the scene’s setup right on Start there was a huge spike on the first frame. I was also reading and parsing all of the XMLs for the levels in that first frame as well, which in retrospect was a bad idea.

    So I went on to change the way the level serializer works to make it read the XMLs over several frames, spacing it out. I also changed the way the first scene works so it adds one element at a time over several frames, which should also mitigate that initial spike. After that the game started loading way faster than it was loading for me. I wasn’t seeing it hanging before, but there was some delay between starting and “actually starting”.

    Another point that could be problematic is actually loading the gameplay level, as a lot starts at the same frame. I remember seeing a loading screen in Skyhook so I asked WaseQazi about it and he pointed me towards this gamasutra article about it



    After several hours, I got the game working with a loading screen and starting potentially heavy stuff over several frames, and even though I wasn’t having hanging problems before, the whole thing felt more responsive and lighter! I then ping my friend again and send him a new build. He then tries it and… It’s still hanging. At this point I’m starting to get desperate, it doesn’t make sense that it’s hanging, after slamming my head against the wall a few times I decided to do what I always do when debugging something, turn things off one at a time until I find the culprit. My first suspect was the XML level serializer, and when my friend confirmed that it was still hanging without it, I was a bit relieved. However when I turned off the inputmanager (which interacts with the gamepads) he wasn’t seeing hanging anymore. D: That could be a big problem since A LOT of my code relies on that. He told me that he was using DInputMapper to use a PS4 controller on his pc, so I asked him to turn that off and try it without it. No more hanging. He then turned it on again and… NO MORE HANGING!

    So… In the end… All of this was made to solve something that wasn’t actually a problem on my part, but on some third-party stuff that just needed a restart or something. Well, at least the new loading system and the spaced out start calls did make the game lighter and more responsive, which will be specially good for the consoles :)

    This actually caused a lot of other problems in other parts of the code, since a lot of it was relying that certain things would happen on the start and when a certain thing started the other would already be there… I believe I have fixed all the bugs that caused, but it did take quite a while, according to toggl I’ve spent about 12 hours on this.



    Other than that, which took a lot of time to deal with, I added a little “invisible powerup” which is really cool ^^ it will make you and your fist invisible, so you can potentially surprise an unsuspecting player.

    Well that’s it for now :) Next up I should be working more on the singleplayer. I need to make new enemy art, so the enemies can look different, then make some more enemy behavioral variations for it.
     
    RavenOfCode likes this.
  36. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382


    I was interviewed for Made With Unity! :D I talked a lot about the origins of Rocket Fist, it’s inspirations and where it’s going! It’s featured on the front page of their website ^^
     
  37. Aiursrage2k

    Aiursrage2k

    Joined:
    Nov 1, 2009
    Posts:
    4,835
    Cool hopefully it builds some buzz for the game
     
    DanielSnd likes this.
  38. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Today during the stream someone mentioned something about networking, I decided to try and playtest the online multiplayer with the viewers against my best judgement… Some of the viewers were actually watching from the UK, so I figured the lag was going to make it pretty unplayable.



    However it was unexpectedly good D: The bugs I already knew were there (death effects not spawning sometimes) were still there but damn it was really playable, and except for a moment or another I didn’t even notice much lag! It was really fun and the viewers seem to really have enjoyed it.

    I’m not going to be working more in the online mode for another couple of months because of the other priorities, but damn, this is going to be awesome *_*
     
    RavenOfCode likes this.
  39. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Alright, so this past week I’ve been hard at work on the Level Editor, I wanted to be able to create game logic with it so making the Singleplayer levels would be way easier :)

    Because showing is easier than writing, here’s how the process of making a singleplayer level is looking like:



    I made a longer video better showing and explaining those new features ^^


    And here is how the first 2 tutorial levels I made are looking like :D



     
    Debhon and RavenOfCode like this.
  40. RavenOfCode

    RavenOfCode

    Joined:
    Apr 5, 2015
    Posts:
    869
    I would think it would take more work to add all that code. :eek: Just curious how many levels are you planning on having?
     
    DanielSnd likes this.
  41. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Hahahahha I wanted to do it, and I figured it would save me time on the long run.

    Amount of levels... I think the technical term for the number is "a S***-ton of levels" xD Hahahha, jokes apart I'm not sure... I'm thinking 15 per sector of the singleplayer, 4 to 5 sectors... Between 60 to 75 on singleplayer and around 20 on the multiplayer?
     
    kittik and RavenOfCode like this.
  42. RavenOfCode

    RavenOfCode

    Joined:
    Apr 5, 2015
    Posts:
    869
    I could see a use then, its also a good experience I suppose. :)
     
  43. gavinb80

    gavinb80

    Joined:
    Nov 4, 2012
    Posts:
    96
    Still one of my projects at present, and the dev updates and images etc are superb
     
    DanielSnd likes this.
  44. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Wow this has come a long way since I last read this thread! Where are my thread notifications when I need them? :D
     
    DanielSnd likes this.
  45. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Thanks guys! :D
    If you see a thread notification and you ignore it, it'll not show you new notifications after that one that you ignored XD I've missed posts I wanted to see in a few threads because of that, it happens lol. After you visit the topic again it starts working properly from there on.

    __________________________________________________________________________

    I haven't wrote here in a while D: So this is going to be a long-ish post!

    I've been working more on the stuff missing on the Singleplayer. I made a menu to pick which sector you want to start in. (Later on I'll make a way of unlocking sectors, so you start with only the Sector Zero/Tutorial unlocked.) You can also pick your color/costume.


    The singleplayer's progression requires that you pass a number of levels before getting to the boss (at the moment 3) without dying. However on playtesting people were getting really frustrated by getting to the boss, dying and having to replay the 3 levels to be able to try again. So I introduced a "lives" system, which will allow you to continue from the same number of levels passed if you die (If you die in the boss, you restart on the boss provided you still have lives left). I also introduced a UI showing the progression and number of lives :)


    I'm now starting to work on different enemies. The current enemy I'm working on is a cannon enemy. It doesn't walk around, it just turns and shoots cannon-balls.


    A Cannon ball will hurt characters in a radius around it when it explodes. It has a bigger deceleration than regular fists, giving it a heavier feeling. (I really enjoyed throwing it around, if I ever get the mutators in the game I might make a "HEAVY ROCKET FIST" mode where all the fists get the same deceleration of the cannonball D:). It explodes if it hits the wall with a certain amount of speed, gets hit by a fist with certain speed or if enough time passes. I did a little animation to represent the time of explosion :) it expands/flashes red quicker the closest it is to exploding.



    I also think I'll add the cannonball into the multiplayer, maybe a pipe that will spawn cannonballs every once in a while, or connect it to a button on the floor that players can step on to shoot cannonball from the pipe :eek: It'll be interesting to play around with that :D

    Another thing that I introduced initially thinking of the singleplayer but can be interesting on the multiplayer as well is the Shield Powerup. It's a bubble that allows you to receive 1 hit without dying. (Still needs more particle effects when blocking a fist).



    I also did several optimizations as I started porting into another platform (No more Resources.Load! :D it's starting way smoother!). In this platform I was having some troubles with loading a different unity scene, so after thinking a lot about the problem I said screw it and just started doing the whole game in one single master scene. It was way easier than expected, and the transition between menu and gameplay now is really smooth and quick.


    Lastly. I've started streaming a lot more lately over at twitch.tv/danielsnd I'm really enjoying having other people to talk to about my work that give me suggestions and instant feedback :D I started working for fun on a little overlay for my stream that interacts with the chat. It started by just spawning little Rocket Fist robots at the bottom of the screen for the viewers whenever someone said something in the chat, so they would be visually represented on the stream itself. From there I ended up enjoying it so much I kept adding stuff into it. Now viewers can pick a color/costume for them, they can fight other robots, there's an energy system, scores, highscores, self-destruction… I also added a question system that integrates with the energy system, so when people ask me questions using it it appears big on the screen and I can answer it while the question is displayed on the screen, rewarding energy for good questions or taking energy away from bad/troll questions.



    Oh! By the way on last Full Indie meetup I got to play Rocket Fist in a huuuuge screen :D It was awesome.


    Well, that's it D: I'll try to not spend this much time without making a new post, this post ended up being really long.
     
    RavenOfCode and kittik like this.
  46. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    I've had to do this before... :D We've all been to too-long-since-last-post land!
    And which platform? I'm curious. :)
     
  47. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    I'd rather not say which platform xD NDAs and all.

    ---------------------------------------------------------------------

    It's been a while since I posted, but I have been hard at work in the game! I'm now streaming every weekday from 3pm to 5pm at http://www.twitch.tv/danielsnd



    I actually integrated Rocket Fist with the Oculus DK2 the other day on the stream for no good reason xD It does feel kinda good to play with it though.



    I finished up the cannon enemy, it nows shoots bombs and gets to be killed when you shoot their own bomb back at them. I added another enemy based on the bomb, it's pretty much the bomb but with little legs, so he can walk around going towards the player, he'll only explode either when he dies or when he gets close enough to the player (his beeps get faster the closer he gets).



    The most annoying enemy though is the shielded enemy. I made this shield powerup that gives you a frontal shield you can use to bounce shots back, and made an enemy around this powerup. He's always looking at the player and will get pretty agressive if the player gets close enough (pressing A like crazy) to make him less OP I made his shots be waaaay weaker than the players shots. He still is pretty hard to kill and deadly so I might need to nerf him further, maybe making him get stunned when he blocks a shot with his shield.



    I sent the game over to Highsight, a cool streamer that does feedback sessions for WIP games on twitch. It was great seeing him playing Rocket Fist and I learned a lot! It was my first time actually seeing a real player playing the adventure mode with all the new enemies and such and it was great! Showed me I'm in the right track with the new adventure mode :D


    One thing that he gave me a ton of feedback on was the boss, Uncle Knuckle. I wasn't really liking the boss myself when fighting it, and Highsight's suggestions helped me improve the boss, now it's getting to be a pretty satisfying fight! Uncle knuckle learned some new tricks this week ^^



    The counter seemed to confuse players a lot in my playtests since it's inception, Highsight suggested changing it to catch and I think that's a good idea, you can actually see a couple of gifs back I managed to catch a fist that the Shielded enemy shot. My latest playtest session seems to have proven that catch is easier for players to accept.

    Well that's it, I got to showcase the game in another twitch meetup yesterday and it was great! But If I write about it in this post, with all that is already in this post it's going to be too much D: So I'll write about it another day!
     
    RavenOfCode, Darkays and kittik like this.
  48. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    This saturday I got to playtest the game at the Vancouver Twitch Meetup! I had an awesome time and got to meet tons of great people learning a lot about the game in the process!


    Got out of there with a huge list of things to fix/change! Best thing was seeing people actually enjoying the hell out of the singleplayer, and trying again until they managed to kill the boss! Only 2 people got to kill Uncle Knuckle though, despite many more attempting xD it was awesome seeing them retrying and learning the patterns!

    Found some pesky bugs still from the changes into one-scene for everything some things weren't getting cleaned up properly from one scene to another, so playing on the singleplayer and then going into multiplayer was causing some problems with players being controlled by multiple controllers.

    Also noticed some things that were making the singleplayer really hard for some people. Increased the number of starting lifes to 6, decreased the explosion radius and got rid of the game over screen when you lose a life (so it drops you straight back into the action). The game over screen now only appears when you run out of lives,in which case if you decide to continue instead of bringing you back to 0 progress it only makes you lose 2 levels worth of progress. Punishing but not that punishing.



    Another nerf that I did was on the biggest jerk of the game, the shielded enemy, he was way too mean, so I nerfed him a bit by slowing down his turn speed and making it so that whenever he gets hit in his shield he'll get stunned for a moment, giving you a chance to get the upper hand on him.

    I also changed the colors surrounding the enemies, so you can tell at a glance what kind of enemy that is (Before all with the same colors it was harder to spot which enemy you should worry about first, like the bomb enemies).



    Another thing I noticed was that unless I was one of the players and actively went back to the menu to pick a different level between matches, people would just keep playing in the same level over and over. For that I did 2 fixes. One, I changed the button on the multiplayer game over to read “SELECT LEVEL” instead of “MENU”, so maybe that will prompt people to click it to change levels between matches. And the other fix was the introduction of a RANDOM ARENA mode, where it'll pick a random arena for each match :) No better way of keeping things fresh than that!

    I also finally found sort of a fix for people who want to play but don't have a gamepad handy! Now it's possible to play with the mouse, using the left mouse button to move the character towards the mouse direction, and either spacebar or right mouse button to shoot. You can actually see it in the Shielded Enemy nerf gif earlier in this post, that reticle in the floor is the mouse position. When I'm playtesting something and too lazy to pick up the controller that's my new favorite way of playing.

    Oh, another cool thing, at the meetup I met a really cool streamer that loved the game and asked me if I'd be interested in him streaming the game. He did a stream on it the other day and him and his viewers were the best! Such great ideas and feedback! :D The mouse to move idea actually came out of a conversation in his chat that day. The twitch interaction stuff didn't work though, no idea why :/ So I decided to make some changes to make it more reliable and to make it easier to debug.


    So now when you select twitch interaction you get to put your channel in, press Connect and actually see the server messages, and see if the connection was actually stablished or not. Even chat messages would be visible in that box, so if twitch interaction is working you'll know right away, and if it isn't you'll have some information to figure out why it isn't working.


    Lastly, at a friend's suggestion I increased Uncle Knuckle's fists, and it looks way more awesome :O easier to hit his fists, but harder to dodge. I like it!

    To close this post, I'll leave you with my favorite gif replays from the Twitch Meetup:

    #1 This match that ended so quickly it's all in the replay!



    #2 This one where a really improbable indirect shot actually landed.



    #3 This slow motion persistent fist finally hitting it's target

     
    gavinb80 and RavenOfCode like this.
  49. gavinb80

    gavinb80

    Joined:
    Nov 4, 2012
    Posts:
    96
    Great work Daniel, still really loving the updates
     
  50. DanielSnd

    DanielSnd

    Joined:
    Sep 4, 2013
    Posts:
    382
    Are you at the GDC? You can play a build of the game at the Xbox Lounge :D




    I didn’t get to go to the GDC myself, but I’m happy my game got to go ^^ From what I’m told, people are enjoying the hell out of it! :D
     
    RavenOfCode likes this.