{"id":146,"date":"2013-10-18T00:00:27","date_gmt":"2013-10-18T00:00:27","guid":{"rendered":"http:\/\/bryanwagstaff.com\/?p=146"},"modified":"2014-08-15T06:15:28","modified_gmt":"2014-08-15T06:15:28","slug":"making-a-game-in-2-weeks-day-5","status":"publish","type":"post","link":"https:\/\/bryanwagstaff.com\/index.php\/making-a-game-in-2-weeks-day-5\/","title":{"rendered":"Making a Game in 2 Weeks: Day 5"},"content":{"rendered":"<div class=\"entry\">\n<p>Day 5 of my <a href=\"http:\/\/bryanwagstaff.com\/index.php\/making-a-game-in-2-weeks\/\">Game in Two Weeks<\/a> is the a simple front-end scene, configuring the game with the front end, and transitioning into the game while keeping the game settings intact.<\/p>\n<h1>Day 5. Front End Choices<\/h1>\n<p>In yesterday\u2019s post I discussed the difference between permanent code and scaffolding. When it comes to the simple front-end, at this point I don\u2019t have any of the assets to fill it out. I need to add character selection and course selection and number of opponents and number of laps and type of race, and much more. But none of those things exist yet.<\/p>\n<p>In Unity when you switch scenes, by default everything gets destroyed and the new scene replaces it. This means that by default, no matter what options they set the player\u2019s choices will be lost. This is something that needs to be modified, and shouldn\u2019t be scaffolding.<\/p>\n<p>But I do have choices about how to display it. I want to display previews of the actual final models, previews of the actual courses, and previews of the other settings, but I am not far enough along to provide those. So while I can provide a backdrop on the scene, the UI elements can (and probably should) be scaffolding for now, until I hit first playable.<\/p>\n<p>So first, what data do I need for my race? For one thing, my first playable is going to include a regular circuit mode, a time trial mode, and a sprint mode. So that option goes in. I need to have the number of players. So I create my RaceSettings class and add the public data.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    public enum RaceType : int\r\n    {\r\n        Circuit,\r\n        TimeTrial,\r\n        Sprint        \r\n    }\r\n    public RaceType mRaceType = RaceType.Circuit;\r\n    public int mNumPlayers = 1;\r\n<\/pre>\n<p>Next I need to figure out exactly how I am going to keep my data available. I have a few options available, and each one has their own pros and cons. The easiest choice is to create a shared static instance of the class. Note that this is not quite the same thing as a singleton. The singleton pattern enforces that only one instance of the class can exist. I don\u2019t want that; I want the ability to replace the class and potentially have multiple instances. The biggest downsides of shared instances is that other locations can modify the instance underneath you, that it introduces hidden dependencies, and that it can be difficult to track down issues. In this case the game design only ever calls for a single instance but I don\u2019t want to enforce it as a policy. For now I\u2019ll keep my race settings as a shared instance.<\/p>\n<p>I create my basic scene with a big cube in the middle. Later I will want actual player characters and stuff, but for now a big cube is enough. Also since I am just using scaffolding for the GUI, I can use the OnGUI\u00a0 functionality to handle it.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    void OnGUI()\r\n    {\r\n\t\tGUILayout.BeginArea (new Rect (mBorder,mBorder, Screen.width - mBorder*2,Screen.height - mBorder*2));\r\n\r\n        \/\/ Begin the singular Horizontal Group\r\n\t\tGUILayout.BeginVertical();\r\n\r\n        if(mRaceSettings == null)\r\n        {\r\n            GUILayout.Label(\u201cRace Settings are null!\u201d);\r\n        }\r\n        else\r\n        {\r\n            GUILayout.Label(\u201cType of race:\u201d);\r\n            string&#x5B;] raceNames = Enum.GetNames(typeof(RaceSettings.RaceType));\r\n            mRaceSettings.mRaceType = (RaceSettings.RaceType)GUILayout.SelectionGrid((int)mRaceSettings.mRaceType, raceNames, raceNames.Length);\r\n\r\n\r\n            GUILayout.Label(\u201cNumber of racers: \u201c+mRaceSettings.mNumPlayers);\r\n            mRaceSettings.mNumPlayers = Mathf.RoundToInt(GUILayout.HorizontalSlider((int)mRaceSettings.mNumPlayers, 1, 6));\r\n\r\n            GUILayout.FlexibleSpace();\r\n            if(GUILayout.Button(\u201cSTART\u201d))\r\n            {\r\n                StartGame();\r\n            }\r\n        }\r\n        GUILayout.EndVertical();\r\n\t\tGUILayout.EndArea();\r\n    }\r\n\r\n    void StartGame()\r\n    {\r\n        DontDestroyOnLoad(mRaceSettings);\r\n        mRaceSettings.TransitionToRaceWorld();\r\n    }\r\n<\/pre>\n<p>And to finish it off, the race settings have a transition to the race world<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    public void TransitionToRaceWorld()\r\n    {\r\n        Application.LoadLevel(\u201cLakeValley\u201d);\r\n    }\r\n<\/pre>\n<p>I added the scenes to the build settings (otherwise LoadLevel won\u2019t work) and try it out in game. Everything works, and after the transition my scripts can still access the race settings.<\/p>\n<h1>Day 5. Starting Projectiles<\/h1>\n<p>None of the other tasks fit in the remaining time today, so the next thing on my to do list is missiles and self-guided missiles. Because they are fairies, we call them spells.<\/p>\n<p>There will be many different types of missiles so I start with the base class.<\/p>\n<p>I know that each missile (both straight fire and homing) will have a velocity and a maximum distance they can travel. They will also have the option to detonate at the end of the line, and to detonate when they collide. They also travel strait forward by default, but since the function is virtual I will have the opportunity to override them later as needed. The collision and detonation functions are also virtual, since I know I will need to override them as new spell missiles are created.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">    public float Velocity = 10;\r\n    public float MaxDistanceBeforeSelfDestruct = 30f;\r\n    public bool ShouldDetonateOnMaxDistance = false;\r\n    public virtual void Update()\r\n    {\r\n        if (mController != null)\r\n        {\r\n            mController.Move(transform.forward * Velocity * Time.deltaTime);\r\n        }\r\n        mTotalDistance += Velocity * Time.deltaTime;\r\n\r\n        if (mTotalDistance &amp;gt;= MaxDistanceBeforeSelfDestruct)\r\n        {\r\n            if (ShouldDetonateOnMaxDistance)\r\n                Detonate();\r\n            else\r\n                Destroy(gameObject);\r\n        }\r\n    }\r\n\r\n    public virtual void OnControllerColliderHit()\r\n    {\r\n        Detonate();\r\n    }\r\n\r\n    public virtual void Detonate()\r\n    {\r\n        Destroy(gameObject);\r\n    }\r\n<\/pre>\n<p>I assigned the script to a prefab, adjusted the controller to create a missile when the right joystick was tapped, and everything worked just fine.<\/p>\n<p><a href=\"http:\/\/bryanwagstaff.com\/wp-content\/uploads\/2013\/10\/shootingice.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-147\" src=\"http:\/\/bryanwagstaff.com\/wp-content\/uploads\/2013\/10\/shootingice-1024x695.png\" alt=\"shootingice\" width=\"640\" height=\"434\" srcset=\"https:\/\/bryanwagstaff.com\/wp-content\/uploads\/2013\/10\/shootingice-1024x695.png 1024w, https:\/\/bryanwagstaff.com\/wp-content\/uploads\/2013\/10\/shootingice-300x203.png 300w, https:\/\/bryanwagstaff.com\/wp-content\/uploads\/2013\/10\/shootingice.png 1433w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>With that done, I can make a subclass for homing missiles. Then I can make subclasses of either the regular missile or homing missile for any new objects I will need in the near future.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    public override void Update()\r\n    {\r\n        \/\/ Homing missiles attempt to turn toward the target\r\n        if (Target != null)\r\n        {\r\n            Vector3 direction = Target.transform.position - transform.position;\r\n            direction.Normalize();\r\n            Quaternion directionToTarget = new Quaternion(direction.x, direction.y, direction.z, 0f);\r\n            transform.rotation = Quaternion.RotateTowards(transform.rotation, directionToTarget, TurnAngleDegreesPerSecond * Time.deltaTime);\r\n        }\r\n\r\n        base.Update();\r\n    }\r\n<\/pre>\n<p>It is a bit of a trick to find the target for the missile, but if a target exists it will lock on, turn and twist, and attempt to hit the target.<\/p>\n<p>And that&#8217;s it for today. Tomorrow is modeling, so I&#8217;m not sure how much I can write.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Day 5 of my Game in Two Weeks is the a simple front-end scene, configuring the game with the front end, and transitioning into the game while keeping the game settings intact. Day 5. Front End Choices In yesterday\u2019s post I discussed the difference between permanent code and scaffolding. When it comes to the simple &#8230;<\/p>\n","protected":false},"author":1,"featured_media":152,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[5,4],"tags":[],"class_list":{"0":"post-146","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-games","8":"category-programming","9":"anons"},"jetpack_featured_media_url":"https:\/\/bryanwagstaff.com\/wp-content\/uploads\/2013\/10\/day5.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/posts\/146","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/comments?post=146"}],"version-history":[{"count":10,"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/posts\/146\/revisions"}],"predecessor-version":[{"id":206,"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/posts\/146\/revisions\/206"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/media\/152"}],"wp:attachment":[{"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/media?parent=146"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/categories?post=146"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bryanwagstaff.com\/index.php\/wp-json\/wp\/v2\/tags?post=146"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}