<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-8980299626399938734</atom:id><lastBuildDate>Fri, 08 Nov 2024 15:03:35 +0000</lastBuildDate><category>Misc</category><title>Ballistic Telegram</title><description>Game Designer Plus Plus</description><link>http://ballistictelegram.blogspot.com/</link><managingEditor>noreply@blogger.com (Chris)</managingEditor><generator>Blogger</generator><openSearch:totalResults>66</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-355902278177286179</guid><pubDate>Thu, 06 Apr 2017 03:58:00 +0000</pubDate><atom:updated>2017-04-05T20:59:13.580-07:00</atom:updated><title>Blog Migration</title><description>Alternate title: &quot;The Sponges Migrated About A Foot And A Half&quot;&lt;br /&gt;
&lt;br /&gt;
I am closing up shop at Blogger to consolidate all my Unity Noob and other blogging efforts at my own site: &lt;a href=&quot;http://www.chrisklepac.com/&quot;&gt;www.chrisklepac.com&lt;/a&gt;. All this stuff still gets auto-posted to the same accounts, so whatever.&lt;br /&gt;
&lt;br /&gt;</description><link>http://ballistictelegram.blogspot.com/2017/04/blog-migration.html</link><author>noreply@blogger.com (Chris)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-5279741266331572806</guid><pubDate>Fri, 25 Mar 2016 18:19:00 +0000</pubDate><atom:updated>2016-03-25T11:19:09.491-07:00</atom:updated><title>&quot;The Cranky Teacher Routine&quot;</title><description>&quot;I don&#39;t feel like it.&quot;&lt;br /&gt;
&lt;br /&gt;
[clasps hands behind back, walks slowly around desk]&lt;br /&gt;
&lt;br /&gt;
&quot;I don&#39;t feel like it, says the young man. Mm.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;Mm, well I quite sympathize. I certainly do.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;When you&#39;re young, the world lies before you sprawled out like a slovenly woman.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;All roads lead to greatness, all paths are strewn with garlands of glory, your feet never touch the earth, songbirds flutter about, tweeting of springtime lust, spurring your wretched meander through life to new depths of drunken merriment, is that about right?&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;When you&#39;re young, things that don&#39;t tickle your insipid fancy can be tossed aside, tossed out of your crib like brightly colored baubles that have finally bored you, because that&#39;s the way you treat everything and every one who has the misfortune to cross your careening, self-satisfied, nose-picking path, isn&#39;t that about right?&quot;&lt;br /&gt;
&lt;br /&gt;
[sighs, looks down glasses, taps foot]&lt;br /&gt;
&lt;br /&gt;
&quot;Mm but when you&#39;re old.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;When your skin is made of paper and the days fly by. When life is like a winter evening you spend huddled around the hearth as the sky presses blacker and blacker against the windowpanes.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;Maybe you think you&#39;ll never get there, or don&#39;t give a hang if you do. That&#39;s fine. Barring some freakish twist of circumstance, you&#39;ll be here long enough.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;You&#39;ll be here, with us, oh I&#39;ll still be here, and so -&quot;&lt;br /&gt;
&lt;br /&gt;
[gestures around room]&lt;br /&gt;
&lt;br /&gt;
&quot;So will a good three quarter of these, believe it or not. Quite long enough.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;Long enough to feel the cold of the world. And if perhaps, and I&#39;m speaking to all of you, if perhaps you&#39;re one of those with enough spending coin to be immune to the more common depredations of the flesh, don&#39;t you worry. Don&#39;t worry one bit. The cold will find you too.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;You&#39;ll feel it in others, in your various disappointments, and most certainly in your interactions with the bloody gears of the machine, and by the machine I mean not just capitalism, or the West, but humankind. The whole lot of us, lurching toward something, or away from something else, a runaway machine where anyone with enough cunning and evil in them can grab the controls, at least long enough to yank a few levers and pound on a few buttons and make things a lot worse for everyone else. You&#39;ll see, now and again, how the machine is just as glad to take your life for fuel as anyone else&#39;s, and how it can run on nothing but lives devoured, and how it mows across the whole earth, for the benefit of so few. So very few.&quot;&lt;br /&gt;
&lt;br /&gt;
[rubs eyes]&lt;br /&gt;
&lt;br /&gt;
&quot;All that, though, is like so many images in your picture books. Easily shrugged off, hardly an impediment at all to the truly vain. After all, you&#39;re the only real one, isn&#39;t that about right?&lt;br /&gt;
&lt;br /&gt;
[interrupted by a sudden coughing fit]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[slowly regains composure]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&quot;No, none of that will matter until the day your own body, the vehicle through which you travel the world, reveals its true nature as a brilliant flower, a firework, an exotic improbability that crests a tiny wavelet in the sea of time and is gone. A toy of nature, a thing as strange and brief as a rainbow.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;On that day, on that day you might think back.&quot;&lt;br /&gt;
&lt;br /&gt;
[chuckles]&lt;br /&gt;
&lt;br /&gt;
&quot;Or you might think forward. Age is a terrible thing for a drifter, for someone who has not made their place in the world. The machines of the world care very little for the old, and the point of entry for old age gets younger every year. If you reach a certain age without acquiring certain skills, your outlook may begin to look very dark. Very dark indeed.&quot;&lt;br /&gt;
&lt;br /&gt;
[begins walking back to front of room]&lt;br /&gt;
&lt;br /&gt;
&quot;Certain skills. What am I talking about, what skills? Well, pupils, that&#39;s entirely up to you. There is no magic skill that will ease your way through life. It will be a rough slog regardless, but you have it in your power to make everything immeasurably worse. It&#39;s a power I would beg you not to use.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;What I&#39;m saying is, as you advance, in this school, in your own studies, as a person, you will find certain things that enchant you, and drive you, and fulfill you. Those things will become the lodestones of your life, even if they are not the things you set out in your schooling or your work to achieve. Those real goals will determine who you, in actuality, are.&quot;&lt;br /&gt;
&lt;br /&gt;
[sits down at desk]&lt;br /&gt;
&lt;br /&gt;
&quot;Those true goals will be your mountains, your jungles and unexplored continents, those crafts and sciences and arts that call you to them and make you their servants, and that rush to fulfill that calling with hard work, let me tell you, is one of the greatest joys one can know in this little life.&quot;&lt;br /&gt;
&lt;br /&gt;
[looks over the room slowly]&lt;br /&gt;
&lt;br /&gt;
&quot;Those goals, those paths, being true, will be hard. There will be times when you are sorely tested. There will be nights exposed on the face of a glacier. Days when the sun is like a hammer, and you crawl along like an ant under glass. Weeks and months of dull white clouds and black lanes and grey grass. You may not seek death, but you&#39;ll sorely consider the idea of never having shown up here in the first place.&quot;&lt;br /&gt;
&lt;br /&gt;
[takes off and polishes glasses]&lt;br /&gt;
&lt;br /&gt;
&quot;When that day comes, when the ultimate failure of your vessel becomes real to you, you might wonder what&#39;s left. Unless you&#39;re one of the elect illuminated and have already made your peace with the divine, you might wonder what&#39;s expected of you. How to live out the remainder of your days. How to leave a mark, to provide for the future, to achieve immortality.&quot;&lt;br /&gt;
&lt;br /&gt;
[puts glasses back on]&lt;br /&gt;
&lt;br /&gt;
&quot;On that fine day, class, God help you if you&#39;re one of the ones who said &#39;I don&#39;t feel like it&#39;&quot;.&lt;br /&gt;
&lt;br /&gt;
&quot;Turn to page 53 in your books.&quot;</description><link>http://ballistictelegram.blogspot.com/2016/03/the-cranky-teacher-routine.html</link><author>noreply@blogger.com (Chris)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-4470400978800132743</guid><pubDate>Mon, 09 Mar 2015 04:10:00 +0000</pubDate><atom:updated>2015-03-08T22:08:41.686-07:00</atom:updated><title>Boxes Full Of Bones</title><description>&lt;a href=&quot;http://www.chrisklepac.com/builds/catalan/catalan_web/catalan_web.html&quot;&gt;Project_catalan&lt;/a&gt; is still a game that doesn’t really know what it wants to be when it grows up, but that hasn’t prevented me from using it as a platform on which to try out new things I’m learning to do. Once I had established the game board as a set of tiles of varying colors (representing terrain types like grass, sand, water, etc.) I became interested in the idea of generating a new version of the board each launch. This is less like sophisticated procedural generation and more like plucking hexagons from the &lt;i&gt;Catan&lt;/i&gt; box, but… baby steps.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIgsnjViIU3hj9ppB6IGdrX9bqnaLaGW4HNlQQNi9frGcNy2IKMwLcZIdT-GTzQ-uP_h2sES8rgGSVyWX6EFDMnu3ZSFM2Q2WcuStMVM3arOobfDkHWzRBxMAtPpAAlo6SkRhYKG05OFiU/s1600/river.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIgsnjViIU3hj9ppB6IGdrX9bqnaLaGW4HNlQQNi9frGcNy2IKMwLcZIdT-GTzQ-uP_h2sES8rgGSVyWX6EFDMnu3ZSFM2Q2WcuStMVM3arOobfDkHWzRBxMAtPpAAlo6SkRhYKG05OFiU/s1600/river.gif&quot; height=&quot;256&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
The method here takes place in three steps. First, a full grid of grass tiles is laid down. Then, starting from one edge, a line of river tiles is placed in a random meandering line, replacing grass as they go. Finally, the tiles on either side of each river tile are replaced with sandy banks. The whole thing is somewhat unwieldy but here’s the river function as an example of what’s being done:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;void MakeRivers()
{
 //this could get a little tricky
 //we want to make a river that cuts across the whole grid in a meandering fashion
 //we&#39;ll assume at the moment that we only ever want one river
 //first: is this a vertical or a horizontal river?

 int riverOrientation = Random.Range(0, 2);
 if (riverOrientation == 0)
 {
  Debug.Log (&quot;Vertical river&quot;);
 }
 else
 {
  Debug.Log (&quot;Horizontal river&quot;);
 }

 //now, where does the river start?
 //at a random point along either the top of the left side
 Vector2 riverStartTile;
 int startRow;
 int startColumn;
 if (riverOrientation == 0)
 {
  //start on final row, then randomize column
  startRow = rows - 1;
  startColumn = Random.Range(0, columns);
 }
 else
 {
  //start on final column, then randomize rows
  startColumn = 0;
  startRow = Random.Range(0, rows);
 }

 //now that we have the row/column index, we need to match that up with the index into 
 //tiles[] of the tile actually living in that spot
 //first let&#39;s get the world pos of where we think we actually are
 Debug.Log(&quot;starting our river at row &quot; + startRow + &quot; , column &quot; + startColumn);
 penPoint = new Vector3(startColumn * width -16f, 0f, startRow * length -16f);
 Debug.Log (&quot;penPoint is &quot; + penPoint);

 //since we&#39;re naming the tiles with their row/column numbers, we can use that to find and destory them
 //let&#39;s try a straight river first I guess
 int currentRow = startRow;
 int currentColumn = startColumn;

 if(riverOrientation == 0)
 {
  for(int i = startRow; i&amp;gt;= 0 ; i--)
  {
   string tileName = &quot;grassTile_&quot;+i+&quot;_&quot;+currentColumn;
   GameObject tileObject = GameObject.Find(tileName);
   //Debug.Log (&quot;Looking for &quot; + tileName);
   if(!tileObject)
   {
    break;
   }
   Vector3 replacePosition = tileObject.transform.position;
   Quaternion replaceRotation = tileObject.transform.rotation;
   Destroy(tileObject);
   GameObject waterTile = Instantiate(tileTemplate_water, replacePosition, replaceRotation) as GameObject;
   waterTile.transform.parent = tileMapObject.transform;
   waterTile.name = &quot;waterTile_&quot;+i+&quot;_&quot;+currentColumn;

   //bend?
   int bend = Random.Range(0, 5);
   if (bend == 3)
   {
    //ok, we&#39;re bending, let&#39;s determine how much
    int bendAmt = Random.Range(1, maxRiverBend+1);
    //find bend direction
    int coinFlip = Random.Range(0, 2);

    for(int k = 0; k &amp;lt;= bendAmt; k++)
    {
     //here&#39;s where we hop to another column
     //east or west?
     if (coinFlip == 1) //east
     {
      currentColumn++;
     }
     else //west
     {
      currentColumn--;
     }

     //now replace the bend tile 
     GameObject bendGrassTile = GameObject.Find (&quot;grassTile_&quot;+i+&quot;_&quot;+currentColumn);
     if(!bendGrassTile)
     {
      break;
     } 
     Vector3 bendReplacePosition = bendGrassTile.transform.position;
     Quaternion bendReplaceRotation = bendGrassTile.transform.rotation;
     Destroy(bendGrassTile);
     GameObject bendWaterTile = Instantiate(tileTemplate_water, bendReplacePosition, bendReplaceRotation) as GameObject;
     bendWaterTile.transform.parent = tileMapObject.transform;
     bendWaterTile.name = &quot;waterTile_&quot;+i+&quot;_&quot;+currentColumn;
    }
   }
  }
 }
 if(riverOrientation == 1)
 {
  for(int i = startColumn; i &amp;lt; columns; i++)
  {
   string tileName = &quot;grassTile_&quot;+currentRow+&quot;_&quot;+i;
   GameObject tileObject = GameObject.Find(tileName);
   //Debug.Log (&quot;Looking for &quot; + tileName);
   if(!tileObject)
   {
    break;
   }
   Vector3 replacePosition = tileObject.transform.position;
   Quaternion replaceRotation = tileObject.transform.rotation;
   Destroy(tileObject);
   GameObject waterTile = Instantiate(tileTemplate_water, replacePosition, replaceRotation) as GameObject;
   waterTile.transform.parent = tileMapObject.transform;
   waterTile.name = &quot;waterTile_&quot;+currentRow+&quot;_&quot;+i;
 
   //bend?
   int bend = Random.Range(0, 5);
   if (bend == 3)
   {
   
    //ok, we&#39;re bending, let&#39;s determine how much
    int bendAmt = Random.Range(1, maxRiverBend+1);
    //find bend direction
    int coinFlip = Random.Range(0, 2);

    for(int k = 0; k &amp;lt;= bendAmt; k++)
    {
     //hop to another row
     //north or south?

     if (coinFlip == 1) //north
     {
      currentRow++;
     }
     else //south
     {
      currentRow--;
     }

     //now replace the bend tile 
     GameObject bendGrassTile = GameObject.Find (&quot;grassTile_&quot;+currentRow+&quot;_&quot;+i);
     if(!bendGrassTile)
     {
      break;
     } 
     Vector3 bendReplacePosition = bendGrassTile.transform.position;
     Quaternion bendReplaceRotation = bendGrassTile.transform.rotation;
     Destroy(bendGrassTile);
     GameObject bendWaterTile = Instantiate(tileTemplate_water, bendReplacePosition, bendReplaceRotation) as GameObject;
     bendWaterTile.transform.parent = tileMapObject.transform;
     bendWaterTile.name = &quot;waterTile_&quot;+currentRow+&quot;_&quot;+i;
    }
   }
  }
 }
}
&lt;/pre&gt;
This was the only work I did on this over the winter, as &lt;a href=&quot;http://www.chrisklepac.com/builds/petrov/petrov_web/petrov_web.html&quot;&gt;petrov&lt;/a&gt; was monopolizing most of my time (see previous post). I returned to it late last month, as it seemed like a perfect test bed for my latest preoccupation: 3D modeling and animation.&lt;br /&gt;
&lt;br /&gt;
I had done some hands-on work with Maya and 3DS Max at various studios, mostly in the context of testing, and I managed to find my way around at a basic level, but these programs are a little too expensive for home use, so I approached Blender, and bounced off, hard. My first crack at it was probably about a year ago, and every so often I would return, a tutorial in hand, and try again, only to end up sliding face first down the learning curve like Wile E. Coyote. In a sense I had been spoiled, as Maya is quite friendly and sensible in terms of its user interface. Blender, by contrast, is full of obscure keyboard combinations, context-sensitive menus, and many different modes the main editor can be in, all of which respond differently to those commands and menus. Ultimately it’s like any other piece of complex software: if you bang your head against it repeatedly, you’ll eventually realize that there are one or two small techniques you&#39;ve absorbed and become comfortable with. You can then use those as a beachhead and campsite from which to explore more daunting areas. Eventually you may earn enough hard-fought victories to ascend the mightiest peaks, breathe that rarefied air, and proudly don the mantle of “beginner”.&lt;br /&gt;
&lt;br /&gt;
Jokes aside, 3D modeling (not to mention rigging, skinning, and the rest) is a discipline much like programming, in that it’s easy to fool yourself into thinking you know something about it, when you really don’t. A forum post I read somewhere described the gap between a bit of functional programming knowledge and the ability to contribute meaningfully in a programming role at a serious studio as being somewhat like the gap between being able to make yourself dinner and being able to work as a sous-chef at a busy high-end restaurant. I think this is spot on, it applies to many game studio roles, and it’s a good reminder not to get cocky. There is always much more to learn.&lt;br /&gt;
&lt;br /&gt;
My goal in this instance was to add another prototyping tool to my kit. Many of the game ideas I jot down in notebooks require animated 3D models, that is to say, little people moving around. If I couldn&#39;t at least rough in this sort of thing, there was no hope. So, I affixed my pitons to the face of Mt. Blender and started climbing.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnclGBYStOdRETmjhIEOa4MGo7E0iZlipIXysxAsTzpKRCT0H2P74s64IZ1tLeQcFLmb7poOuKaZQBXxZpt4BhRklozoaE_qUFi3CSqNJra3as-VzriP1wqWIqVUoMIwvRgmai0Gn0CGx9/s1600/boxman.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnclGBYStOdRETmjhIEOa4MGo7E0iZlipIXysxAsTzpKRCT0H2P74s64IZ1tLeQcFLmb7poOuKaZQBXxZpt4BhRklozoaE_qUFi3CSqNJra3as-VzriP1wqWIqVUoMIwvRgmai0Gn0CGx9/s1600/boxman.png&quot; height=&quot;224&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
This is boxman, a Blender model composed of a bunch of cubes joined together. Boneheadedly simple, not much to look at, and in this form totally useless except as a mannequin. I could import him into Unity, but he would just stand there motionless.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE34ew9PivwvAxp7elxRPqls9hcbdPXtH0XHGIUwlc9PECNwRy6uMa7E5RHAtawQDKMn1AOCbMLTVtgpQicCan1CupXhMasbmDpjITnKdvYsQdNEZs9tPJ9-qcYaFRWgpxx_I8nThwUUQc/s1600/armature.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE34ew9PivwvAxp7elxRPqls9hcbdPXtH0XHGIUwlc9PECNwRy6uMa7E5RHAtawQDKMn1AOCbMLTVtgpQicCan1CupXhMasbmDpjITnKdvYsQdNEZs9tPJ9-qcYaFRWgpxx_I8nThwUUQc/s1600/armature.png&quot; height=&quot;240&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
This is boxman’s armature, made of a series of “bones” that control his movements. The model is made up of vertices, points in 3D space, that together define the shapes of the boxes. Rigging and skinning a model means that each vertex must be assigned to a bone, so that when the bone moves, its assigned set of vertices are moved along with the bone, in a process called mesh deformation. Since boxman only has a couple dozen vertices, this is about the simplest case you could hope for. Making a realistic-looking character model move realistically involves assigning thousands and thousands of vertices and carefully “weighting” them to control how much deformation the bones can do, to say nothing of constructing the actual animations, transitioning seamlessly between them, and making them responsive to player input. I have a tremendous amount of respect and admiration for the people who do this work for AAA games. Have a look at something like the combat moves in &lt;i&gt;Shadow Of Mordor&lt;/i&gt; and it’s quite clear that that this is as painstaking and complex a combination of skill and art as anything a programmer might face.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt1DRttum0D_pxOAKfMq0crk1b4i5RFn_gvUgWgN2x19YPPk0K5RPh9aBK060XES5t3KF9hDZfGu6zSPErPTf1ZSUa5cF17SeG9lci_azwWBpksnRWHERde-tM0gXgP_FBpibZHBMYRCOy/s1600/walk.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt1DRttum0D_pxOAKfMq0crk1b4i5RFn_gvUgWgN2x19YPPk0K5RPh9aBK060XES5t3KF9hDZfGu6zSPErPTf1ZSUa5cF17SeG9lci_azwWBpksnRWHERde-tM0gXgP_FBpibZHBMYRCOy/s1600/walk.png&quot; height=&quot;227&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Here’s boxman getting his walk on via Unity’s Mechanim animation system, which uses a simple keyframe animation interface like you’d find in Maya or even Flash. Of course, you can animate in Blender, then import those animations in Unity and hope you can make them work, but I was quite relieved to discover I didn’t have to. Unity lets you move the bones around in Animation mode using the same transform and rotate widgets you’d use on any other object, so it was a joy to be back in familiar territory. Boxman’s walk cycle is as rudimentary as the rest of him, but the goal here was just to get the basic parts in motion. Pretty can wait. Mechanim also contains a handy state machine interface with variable-based transitions that can be called from script. That is to say, I can give the model a walking state and an idle state, which will flip back and forth depending on if the boolean “isWalking” is true. Then I can make that bool true or false from the movement control script, based on whether the player is touching a key.&lt;br /&gt;
&lt;br /&gt;
Keys bring up the topic of character control, a subject that most projects wrestle with. The original proto-prototype of catalan (known as benko at the time) had a control scheme where you simply clicked the mouse on the point where you wanted to travel, as I had been playing a bunch of &lt;i&gt;Path of Exile&lt;/i&gt;&amp;nbsp;at the time and basically wanted to rip off some of the feel of playing that game (no luck whatsoever on that front). I quickly ran into problems because the shooting mechanic involved clicking on monsters, so a slightly misplaced click would send you strolling blithely toward the enemy instead of engaging it, which got frustrating fast. The next iteration was straight-up WASD movement with mouse aim, which was great when the player was an orange cylinder because it didn&#39;t matter which way it was facing. To my horror, the box model totally broke this movement scheme.&lt;br /&gt;
&lt;br /&gt;
It’s an interesting and fundamental point of game design that when you introduce anything from the real world, the player expects (quite reasonably) that it will behave like that thing does in the real world. Players will forgive a lack of verisimilitude when controlling cubes or spheres or even spaceships (sometimes), but gosh darn it we all know how people move. The problem with my controls came about when I implemented the player model rotating based on mouse aim. Having the rotation disconnected from movement was no problem for a cylinder, but for a person, it just felt &lt;i&gt;weird&lt;/i&gt; that the right arrow was sometimes rightward movement, and sometimes forward or backward movement, depending on the model rotation. Now, this scheme is perfectly valid, and has a long and storied history in the “twin-stick shooter” genre, going all the way back to &lt;i&gt;Robotron 2084&lt;/i&gt;, but in most successful cases the movement is sold to the player as realistic in various ways, the most ingenious being to disconnect the upper half of the body from the lower, and orient the legs to the movement vector and the arms to the aim vector. Elegant, attractive, and still a bit over my head technically. I could see upgrading catalan to that scheme sometime in the future, but for now I needed something simpler.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
I had a really cute second idea to make the right and left
arrows move the player laterally to the facing direction, and even learned just enough about cross product math to make it work, but it turned out to also be a
really dumb idea. When the player was facing away from the camera, the arrows worked
beautifully; when the player faced the camera their motions were flipped, which was an
even queasier sensation than before.&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
In the end, I opted for a dirt simple approach: the forward
and backward arrows (or W and S) work, the side arrows do nothing, the mouse
controls aim and rotation. This still doesn&#39;t feel great, but it’s workable. I
punched up the visuals with some handmade, randomly placed trees and some
simple textures instead of solid colors. I animated the water and even replaced
the “purple refrigerator” enemies with some kind of bear giant thing that
toddles around amusingly.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWBF6qv0o-ve-41ss4rGgoS32i5_OJZhkkskeACsq-t9V2z18uDL1aHfEFAX8HLMPiVZm5LHMmtKmgG6ClrYu0thBLgTEsXaGfT81FMq89QCCrEbTn-AMyiEHg9D2zLP3IZHug1sIxoUfq/s1600/bears.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWBF6qv0o-ve-41ss4rGgoS32i5_OJZhkkskeACsq-t9V2z18uDL1aHfEFAX8HLMPiVZm5LHMmtKmgG6ClrYu0thBLgTEsXaGfT81FMq89QCCrEbTn-AMyiEHg9D2zLP3IZHug1sIxoUfq/s1600/bears.png&quot; height=&quot;135&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
The whole thing is still a far cry from being fun, there’s nothing much to do and it still lacks any kind of theme or character, but this is really the way I like building things. A lot of designers start with a high concept idea or story and then build the mechanics up underneath that, but I always start with a mental image of a small onscreen interaction. A video game is just a person in front of a screen with a manipulation device (at least until the VR revolution swallows us all whole). If the basic act of interacting with what’s on the screen isn&#39;t engaging second to second, then the best story in the world won’t be any use. Refine the gameplay loop, again and again, make that your primary focus, and don’t worry about whether the player is supposed to be a pirate, a cowpoke, an astronaut, or a QA contractor with dreams of glory. Make the fun, and the rest will come out in the wash.&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
Coming Up&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Oh, hello Unreal 4. Hello Source 2. Is this an embarrassment of riches or what?&lt;/li&gt;
&lt;li&gt;A radar for catalan&lt;/li&gt;
&lt;li&gt;More prototypes, and maybe I&#39;ll finish those design docs I keep been talking about&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</description><link>http://ballistictelegram.blogspot.com/2015/03/boxes-full-of-bones.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIgsnjViIU3hj9ppB6IGdrX9bqnaLaGW4HNlQQNi9frGcNy2IKMwLcZIdT-GTzQ-uP_h2sES8rgGSVyWX6EFDMnu3ZSFM2Q2WcuStMVM3arOobfDkHWzRBxMAtPpAAlo6SkRhYKG05OFiU/s72-c/river.gif" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-7105957454948695783</guid><pubDate>Sun, 22 Feb 2015 01:44:00 +0000</pubDate><atom:updated>2015-02-21T18:43:36.268-08:00</atom:updated><title>Always Crashing In The Same Car</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp56ifeNNRKKWvuqVFuR6G4693N1JtbMFgRtwj6fh2Xidp5eTKRmaNjFF2ZdAte19jgctDYYur8dX0YLK31tdBK0eCrlGQPuQDl69fIK5TtWQMRJf9Tb7cEPXUO8ZVbuoowaMUi4n3BbDX/s1600/crashing_img1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp56ifeNNRKKWvuqVFuR6G4693N1JtbMFgRtwj6fh2Xidp5eTKRmaNjFF2ZdAte19jgctDYYur8dX0YLK31tdBK0eCrlGQPuQDl69fIK5TtWQMRJf9Tb7cEPXUO8ZVbuoowaMUi4n3BbDX/s1600/crashing_img1.png&quot; height=&quot;155&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
It’s dangerous to go alone. The total freedom of solo game development can be its own worst enemy. With no one around to say “hey, maybe rough in feature X and move on”, you can end up caught between your best judgment and the stubborn, dogged perseverance that got you into this mess in the first place. The more of this I do, the more I find that the ability to scope from within a problem, to decide which solutions are good enough for now, to basically Produce oneself as mercilessly as a corporate publisher, that constantly updating self-reflection is the key difference between solo games that are in some way concluded and others that are simply abandoned.&lt;br /&gt;
&lt;br /&gt;
I spent most evenings and weekends of the dark months on &lt;a href=&quot;http://www.chrisklepac.com/builds/petrov/petrov_web/petrov_web.html&quot;&gt;project_petrov&lt;/a&gt;, often spinning my wheels, or more accurately watching a small model car flip onto its side over and over again.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3YwLm9F5UjuBYFovICOr_F6cOh0RHo12d_fnD7_zgw6ng-16Ytmu_9Y7S_Qh6qQhMY4SHnFIl5BD7KK_bdCwpWx3Edo8FRc3kL-Vt2mAVpAdah_PvwszMk4egh_MRpeM6lsa6IYEE5RNi/s1600/crashing_img2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3YwLm9F5UjuBYFovICOr_F6cOh0RHo12d_fnD7_zgw6ng-16Ytmu_9Y7S_Qh6qQhMY4SHnFIl5BD7KK_bdCwpWx3Edo8FRc3kL-Vt2mAVpAdah_PvwszMk4egh_MRpeM6lsa6IYEE5RNi/s1600/crashing_img2.png&quot; height=&quot;172&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
This whole racing project is a derail in itself. I’ve been working through this (really excellent) &lt;a href=&quot;http://holistic3d.com/&quot;&gt;Unity textbook&lt;/a&gt; which mostly consists of little example game projects where they give you some starter bits and then you complete the game. Everything was going great until I got to the &quot;generic racing game&quot; project. I got into it, then started getting irritated by things like the terrain being inappropriately mountainous (making camera movement in scene view difficult and lighting a chore), the track being punishingly long for the size of the models (making iteration on things like win condition code a chore) and various other minor annoyances. I decided the only way to complete the project to my satisfaction would be to remake it from the ground up, including all the assets. I figured I could whip up some new scripts, hit Turbosquid for some free cars, and maybe put some twists on it so I could have another minor portfolio piece. Expected turnaround time: a few days? This was in &lt;i&gt;November&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
My first hack at the track was an interesting idea, I found some outline images of famous race tracks at &lt;a href=&quot;http://linearedge.com/&quot;&gt;this cool site&lt;/a&gt;, and attempted to use some as height map files on Unity terrain objects. The primary problem with this was the dismal sense of racing in a WWI trench, but there were other problems, for instance I had no easy way to tell whether the cars were on the track or not. Eventually I realized I would need to use some kind of road objects that could send messages about whether a car was touching them. So, the racing trench and its associated materials went into the bin.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvXPT_LdlyeRy-9x_PVdRWI6ALXQ3TFbHjZBGRXi83MeLbCwWh1b1ADnsevSPHRqR0HznzoseRy63J4i-ZyUiawvRaU82138uprJHQKpQObrQHzSiNsintAxXsCNpEuA5D61_2XPf7Is2p/s1600/crashing_img3.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvXPT_LdlyeRy-9x_PVdRWI6ALXQ3TFbHjZBGRXi83MeLbCwWh1b1ADnsevSPHRqR0HznzoseRy63J4i-ZyUiawvRaU82138uprJHQKpQObrQHzSiNsintAxXsCNpEuA5D61_2XPf7Is2p/s1600/crashing_img3.png&quot; height=&quot;144&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Making modular track pieces with Blender was straightforward enough after watching a few relevant YouTubes. My UV mapping skills are still pretty basic, so the road curves look a little stretched and blurry, but I was able to make myself move on from that (which wasn’t hard, because another few nights in Blender was nothing to look forward to).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg_MKtAeKnNoF6leSHEUlisdgWYI1_LFtPQ29nKtCC-g0xEUNqj9jfa22YLPg0atbU_EUEa-sQTJ5x6OqarGwtYHrnqGBZ5jW9qIAv8F2CeV2rBfJkpAvGeNY5TyOFJCc4xWU58aLzq4AM/s1600/crashing_img4.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg_MKtAeKnNoF6leSHEUlisdgWYI1_LFtPQ29nKtCC-g0xEUNqj9jfa22YLPg0atbU_EUEa-sQTJ5x6OqarGwtYHrnqGBZ5jW9qIAv8F2CeV2rBfJkpAvGeNY5TyOFJCc4xWU58aLzq4AM/s1600/crashing_img4.png&quot; height=&quot;174&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
The muscle car model itself was also simple enough to work with, although the artist “posed” it with the front wheels turned insouciantly to the left, so I was constantly having to adjust them by around 9.6 units of rotation, a figure which grew to haunt me. It didn’t make much difference in the end as I wound up chopping the model into body, glass and wheel meshes and placing each individually as child nodes of either the car body or the car wheels, so I had an invisible cube and some invisible cylinders “wearing” the good meshes like a second skin. I painted each mesh with some basic colored materials, entertaining various dreams of a rainbow panoply of AI opponent cars, and a cel-shaded “Saturday morning cartoon” effect in post-processing, but both of these features turned out to be, thank Christ, out of scope.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir_tkGDw8eX4OCSyBODSCo033fWXbuAf4V73iv_Jnf3HuBJ-Qwt_7NuWnG4EQRtfDAok2GaebI-R_wPyDlq8TTu21FOGsVp0uKakL1DcrczzQc7dcYPeC0p_kD40vnjF-SzWMEKTO5ZsM2/s1600/crashing_img5.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir_tkGDw8eX4OCSyBODSCo033fWXbuAf4V73iv_Jnf3HuBJ-Qwt_7NuWnG4EQRtfDAok2GaebI-R_wPyDlq8TTu21FOGsVp0uKakL1DcrczzQc7dcYPeC0p_kD40vnjF-SzWMEKTO5ZsM2/s1600/crashing_img5.png&quot; height=&quot;190&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
Then it came time to make the car go. The book example
propels the vehicle by using AddForce on the car’s RigidBody, which works well
enough, but as a physical simulation is somewhat like towing the car along
behind another car with a cable – the movement force doesn’t come from the wheels,
so the simulation is not very car-like. I was determined to do things “the
right way”, which meant controlling the car with four WheelCollider objects by
applying MotorTorque and BrakeTorque. This was actually fairly intuitive and
even fun to implement, and the simulated springs gave the car a delightfully
realistic bounciness when dropped onto the terrain. Everything worked
beautifully until I attempted to turn the vehicle, at which point it flipped
over. Repeatedly. Every single time, in fact. &lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
Anyone who has done time in the murky woods of Unity vehicle physics is probably familiar with self-described Hardcore Developer &lt;a href=&quot;http://www.edy.es/dev/&quot;&gt;Edy&lt;/a&gt;, a towering genius of video game automobiles who has published
some &lt;a href=&quot;http://forum.unity3d.com/threads/how-to-make-a-physically-real-stable-car-with-wheelcolliders.50643/&quot;&gt;fascinating&lt;/a&gt; posts on the Unity forums, describing, among other things, how
to keep a car from flipping over. The answer he proposes is simulating stabilizer
bars. The idea is, you read data from the WheelCollider to determine how far
the spring is extended. When the car takes a turn, the springs on the inner
wheels will compress, while those on the outer wheels expand. So, as a spring expands,
you impose a downward force on the car body at the wheel location, and the more
the wheel threatens to leave the ground, the harder you push down on it.
Elegant in theory, but in practice there are more than a few things that can go
wrong, and in my case all of them did. &lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
I could not get the damned car to stop flipping over.
Some reasons my stabilizer bars might have failed: &lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The car may have been out of scale to the Unity physics
system&lt;/li&gt;
&lt;li&gt;The car’s rigidbody mass and center of gravity settings
may not be compatible with the stabilizer code&lt;/li&gt;
&lt;li&gt;The car model exported from Blender may have some
qualities that don’t play well with the physics system and/or the stabilizer code&lt;/li&gt;
&lt;li&gt;My WheelCollider settings may be incompatible with how
the stabilizers work&lt;/li&gt;
&lt;li&gt;I may not be applying the downward force effectively,
with the right amount and at the right location&lt;/li&gt;
&lt;li&gt;Despite extensive visual debugging to make sure X really
is X, I may be misunderstanding what the stabilizer code is actually doing&lt;/li&gt;
&lt;li&gt;My math deficiencies may have gotten the best of me (the
stabilizer code uses Transform.InverseTransformPoint, which I can’t honestly
claim to completely understand)&lt;/li&gt;
&lt;li&gt;The WheelColliders themselves may be in some way suspect.
I have nowhere near the knowledge to takes sides on Edy’s post about a purported &lt;a href=&quot;http://forum.unity3d.com/threads/wheel-friction-curve-revealed.153340/&quot;&gt;scandal in wheel town&lt;/a&gt;, but nobody from the Unity dev community has come along to tell
him he’s wrong, so who can really say?&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;br /&gt;
All interesting lines of inquiry, for someone with half a
dozen spare lifetimes to spend faffing about with wheel physics, but I had
already squandered too much time on the problem. Finally, I found a brutal hack
and wielded it like a hatchet. Behold my shame:&lt;/div&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;downforce = -veloMag * rigidbody.mass * 3f; //sSHHH it&#39;s a MAGIC NUMBER son
downvector = new Vector3(0.0f, downforce, 0.0f);
rigidbody.AddForceAtPosition(downvector, transform.position);
&lt;/pre&gt;
&lt;br /&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
The faster the car goes (veloMag is the rigidbody’s
velocity.magnitude), the harder I press down on it at the center. It’s like
racing with the veritable Thumb of God on the car roof the whole time. Now, any
future development work would surely start here: I’m confident that I could
lower that value and tweak various other parameters until I reached a
compromise where the car would resist flipping, but retain some of the car-like
bounciness the WheelColliders provide. As it is, I’ve more or less come all the
way back around in terms of realistic simulation. This solution is hardly more “car-like”
than just applying force directly to the car, all the interesting wheel spring
behavior is getting squeezed out of existence, like the dynamic range on a Red
Hot Chili Peppers album. &lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
Regardless, this allows me to glue the car to the ground,
finish the scenery and UI, put some basic game logic in place, and close the
loop on the project as a portfolio tech demo. It’s a racer, just not a very
compelling or well-realized one, and it’s not exactly meant to be. Although I
have some interesting ideas on where it could go, and I may spend more time on
it later, I’m not taking this thing to Early Access.&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
Here&#39;s where I confess to not particularly loving racing
games. Oh, don&#39;t get me wrong. &lt;i&gt;Pole Position &lt;/i&gt;is just as iconic to me as &lt;i&gt;Galaga&lt;/i&gt;
or &lt;i&gt;Moon Patrol&lt;/i&gt;, and the arrivals of the&amp;nbsp;&lt;i&gt;Stun Runner&lt;/i&gt;&amp;nbsp;and &lt;i&gt;Hard Drivin&#39; &lt;/i&gt;cabinets at my local
arcade were earth-shaking events at the time. I just mean to say that I never planted a
stake in any modern racing franchises, never had a &lt;i&gt;Forza&lt;/i&gt; career or bought a
faux steering wheel. So why make one? Primarily due to being at the racing
chapter in the textbook I was working from, but just as importantly out of a
self-imposed need for portfolio diversity. For some dumb reason I feel like a
proper game designer should be able to whip up anything from a shooter to a
stealther to platformer, in 2 or 3D, in enough detail and with enough quality
so that it could convey whatever the cool new twist is without stumbling over
the set dressing. It&#39;s a fine notion, but it turns out that maybe racing is one
of the less trivial genres, from a gameplay design point of view.&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
And, without getting too grim, this work is hard enough
to justify as it is. When I wasn’t day jobbing on the fringes of the industry, I
spent the dark months flitting from studio to studio whenever a designer role
came open on the job boards, shaking hands and telling my life story over and
over, trying to convince someone, anyone, that yes, I am actually competent as a
game content designer, and not being able to convey that impression in the slightest.
I’m hoping that all this portfolio work will pay off, but it’s hard to believe
that anyone will care. The studios want, and in most cases can afford to wait
for, a designer with years of commercial experience on the exact subgenre they’re
putting out. I’ve been rejected on the basis that “we’re looking for someone
who lives and breathes subgenre X”, which, I suppose I’d want that too in their
position, but it points to a pretty dark future for someone whose resume looks
like it was written with a shotgun. I’m slowly trying to find a way to accept
that I may never be employed as a creator again, that the rest of my career
may be an endless string of exploitative and unrewarding QA contracts. I have
to make a conscious decision every day to not believe this, because the feeling
of believing it is like the feeling of being on fire. Nobody likes being on fire. &lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;b&gt;Coming Up &lt;/b&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;more prototypes&lt;/li&gt;
&lt;li&gt;project_catalan upgrades&lt;/li&gt;
&lt;li&gt;some non-Unity experiements&lt;/li&gt;
&lt;li&gt;some game design docs for larger projects&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNoSpacing&quot;&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;br /&gt;</description><link>http://ballistictelegram.blogspot.com/2015/02/always-crashing-in-same-car.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhp56ifeNNRKKWvuqVFuR6G4693N1JtbMFgRtwj6fh2Xidp5eTKRmaNjFF2ZdAte19jgctDYYur8dX0YLK31tdBK0eCrlGQPuQDl69fIK5TtWQMRJf9Tb7cEPXUO8ZVbuoowaMUi4n3BbDX/s72-c/crashing_img1.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-3764031787456329715</guid><pubDate>Mon, 13 Oct 2014 23:59:00 +0000</pubDate><atom:updated>2014-10-13T17:29:21.312-07:00</atom:updated><title>void EverythingThatRisesMust(Collision collision)</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9Ee7AimHK885ZYXx2MB4c4x7DWjd734oI9jOiZka1ybsy3Kt0-ZsCU2l4PKjUopsuZ9ZsQzuqwSiErwgWtqzusqmXIqxBTH2dnIO2SCdQBp_wlgyLRgwvla0ljscEZnoN7xoGMH3lBXep/s1600/catalan_blog.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9Ee7AimHK885ZYXx2MB4c4x7DWjd734oI9jOiZka1ybsy3Kt0-ZsCU2l4PKjUopsuZ9ZsQzuqwSiErwgWtqzusqmXIqxBTH2dnIO2SCdQBp_wlgyLRgwvla0ljscEZnoN7xoGMH3lBXep/s1600/catalan_blog.png&quot; height=&quot;232&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
In its resting state, the  &lt;a href=&quot;http://chrisklepac.com/catalan_web.html&quot;&gt;current build&lt;/a&gt; of project_catalan may not look much different from the previous one (a bit more red maybe), but a lot has changed under the hood. The changes, in my mind, are akin to standing in the doorway of the empty shell of a house and thinking &quot;all right, we&#39;re going to need to shape out the living room, so we&#39;ll need walls here, and a load-bearing column there, through which we&#39;ll route water and electricity...&quot; We haven&#39;t even gotten to the studs and sheetrock, much less the arguments about which of your friends&#39; paintings are going to hang near where people might be, like, eating. As in any self-impelled project, you&#39;re always glancing that far ahead from time to time, and it can be useful to attempt to anticipate what problems you may need to solve in the future, to the extent that it helps you choose the solutions to your current problems that make future you&#39;s life easier, but it would be a classic game development mistake to fall afoul of something so seductive and misleading as a &lt;i&gt;&lt;b&gt;plan.&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
This last sprint was about damage, death and communication. How does one character damage another, and how is that information communicated to everyone who needs it, including the player. I found Unity&#39;s new UI system (introduced in 4.3?) to be an absolute miracle, in the sense that it allowed me to do sensible things. My previous experiences with Unity UI involved making instances of things like GUI.Box in the OnGUI function of something attached to the camera, which seemed to mostly work for what I needed but had the usability flavor of writing a Windows GUI application in C# without the benefit of XAML, or doing web layout by changing numerical values in raw CSS files and then refreshing the page. It wasn&#39;t very IDE-integrated, is what I&#39;m saying, and the new version totally is. When I was contemplating how to implement MMO health bars for the enemies, I was at first thinking about scripted GUI.Texture instances translating and scaling based on a mathematical relationship between the enemy and the camera. You&#39;d have to be a masochist to write such a system, so I imagine the preferred solution was just some Doom-style billboarding on quad meshes attached as children of whoever gets a healthbar, all on some custom collision layer that ignores the rest of the game world. Unity recognized that not using the UI system was better than using it, so they fixed it. Now we can have world space Canvases as children of moving gameObjects, and a an enemy&#39;s health bar can be built with basically no code:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuqmJgNUJzD-2l0jV6SN498o9tJ5RarZqNnRuol2RHnJUKMm27BEMTFpFmnx6j9RV8_dkaO_u3Z7lNXFMvO1wkwbgwilXI7EguuriPFkddUBqaevpCd0Azf3dVROKDmGpML3HuYFrT3JVI/s1600/inline_1_512.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuqmJgNUJzD-2l0jV6SN498o9tJ5RarZqNnRuol2RHnJUKMm27BEMTFpFmnx6j9RV8_dkaO_u3Z7lNXFMvO1wkwbgwilXI7EguuriPFkddUBqaevpCd0Azf3dVROKDmGpML3HuYFrT3JVI/s1600/inline_1_512.png&quot; height=&quot;320&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Allowing for player damage was somewhat trickier. I wanted a standard player HUD, and using the new Canvas tools in combination with the main gameplay camera produced undesirable results. I ended up adapting a technique I had seen the &lt;a href=&quot;http://snuggletruck.com/&quot;&gt;Snuggletruck&lt;/a&gt; guys explain in a seminar: I created an orthograhic camera &quot;box&quot; far away from the action, and gave it a positive Depth so that it would render over the gameplay camera. This freed me to compose a UI in Scene view without feeling crowded by actual gameplay objects:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSXXsQ9rA-bcJ1vg64VaiME5lBl23gdN3yQg1aVVwEfqtuZpEaFcHiegHWsvaLQJLUcrFUIqZhW7qFTssRlklieTsiu2ysk7w1MWRJOWxk3h-bVynWAw6NjS_E0Hack9aX5FnCqWVuRYBt/s1600/inline_2_512.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSXXsQ9rA-bcJ1vg64VaiME5lBl23gdN3yQg1aVVwEfqtuZpEaFcHiegHWsvaLQJLUcrFUIqZhW7qFTssRlklieTsiu2ysk7w1MWRJOWxk3h-bVynWAw6NjS_E0Hack9aX5FnCqWVuRYBt/s1600/inline_2_512.png&quot; height=&quot;320&quot; width=&quot;316&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
The problem with this approach (Screen Space - Camera) is that it&#39;s not very forgiving to resizing / rescaling. Right now I&#39;m viewing all of my current projects as portfolio pieces aimed at a standard web browser, but not building in UI scaling functionality as you go is a recipe for &quot;platform prison syndrome&quot;. The new anchor system is quite elegant and only a little over my head, so this feels like a very solvable problem once it needs to get solved.&lt;br /&gt;
&lt;br /&gt;
The idea of implementing one last feature for this build, pushing a character away from a damage impact, turned out be much like Columbo un-mouthing his cigar, turning his head slightly, and asking about &quot;one more thing&quot;. The ur-idea here is of course from the NES &lt;i&gt;Legend Of Zelda &lt;/i&gt;&amp;nbsp;(yes, catalan is a &lt;i&gt;Zelda&lt;/i&gt; clone. I will also stay up all night with you argiung that the &lt;i&gt;Diablo&lt;/i&gt; games are&lt;i&gt; Zelda &lt;/i&gt;clones, provided you&#39;re buying). A character being melee&#39;d by an enemy should be slammed back, not far enough or long enough to disrupt gameplay, just enough to provide that sensation of &quot;yes, dumbass, you touched a hot stove. How bout you try to avoid doing that?&quot;&lt;br /&gt;
&lt;br /&gt;
Teaching in video games is not done thorough tutorials, which are not widely read or played or viewed or whatever. Teaching is done by presenting the player with a variety of hot stoves and inviting them to make like Buddy Rich on some bongos. See what you like! They&#39;ll figure it out. If not, they&#39;ll leave you a nasty review claiming the game is too hard. Look, all I can do here is make stoves and heat them to various degrees. It&#39;s up to you to decide what to touch, that&#39;s what our relationship is about.&lt;br /&gt;
&lt;br /&gt;
Trying to sort out combat, I worked through all the permutations of Unity colliders, triggers, rigidbodies... you can&#39;t just point at any of the onscreen characters and ask what collisions they&#39;ve experienced recently, it&#39;s all very dependent on what components the attacker and defender were sporting, the complexity got silly, I even used some joints (er, Fixed Joints, that is). One morning at about 3:40AM I realized part of one of my &quot;Push&quot; function involved assigning one variable&#39;s value to another variable that just had a different name. I was writing in circles. I called it off. 
&lt;br /&gt;
&lt;br /&gt;
The &quot;Zelda Push&quot; ended up not making use of colliders at all. It doesn&#39;t even require rigidbodies! It&#39;s dirty secret is performing a while loop inside a CoRoutine, and using &quot;yield return null&quot; at the end of each loop iteration. so the while loop actually updates at the same speed as the main game loop. Here&#39;s how the whole thing ended up looking (for context, this method lives in healthStates.cs, which is attached to any object whose health we care about:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;IEnumerator DoPush(GameObject pusher)
 {
  Vector3 startPoint = transform.position;
  Ray pushRay = new Ray();
  if(pusher.GetComponent&lt;weapon_melee_base&gt;())
  {
   //Debug.Log (&quot;melee push&quot;);
   pushRay = new Ray(startPoint, transform.position - pusher.transform.position);
  }
  else if(pusher.GetComponent&lt;bullet_base&gt;())
  {
   //in this case using the bullet for the ray origin gets wonky
   //so we get the gun location and start the ray there
   //Debug.Log (&quot;bullet push&quot;);
   bullet_base bulletScript = pusher.GetComponent&lt;bullet_base&gt;();
   Transform firearm = bulletScript.weapon;
   pushRay = new Ray(startPoint, transform.position - firearm.transform.position);                
  }
  else
  {
   Debug.Log (&quot;invalid pusher&quot;);
  }
  Vector3 flatPushDir = new Vector3(pushRay.direction.x, 0.0f, pushRay.direction.z);
  pushRay.direction = flatPushDir;
  Debug.DrawRay(pushRay.origin, pushRay.direction*1000, Color.red, 10.0f);

  float pushLength = 5.0f;
  Vector3 pushPoint; 
  pushPoint = pushRay.GetPoint(pushLength);
  //pushBall = Instantiate(pushBallTemplate, flatEndPoint, Quaternion.identity) as GameObject;

  float pushStartTime = Time.time;
  float distanceCovered = 0.0f;
  float fractionComplete = 0.0f;
  float pushSpeed = 50.0f; //this actually matters in relation to the pushLength
  while(fractionComplete &amp;lt; 0.9f)
  {
   distanceCovered = (Time.time - pushStartTime) * pushSpeed;
   fractionComplete = distanceCovered / pushLength;
   transform.position = Vector3.Lerp(startPoint, pushPoint, fractionComplete);
   //Debug.Log(&quot;fractionComplete = &quot; + fractionComplete);
   yield return null;
  }
 }
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Once I built the new version, befoe deploying it to the web I tested it locally and encounteerd this error:&lt;br /&gt;
&lt;i&gt;&lt;span style=&quot;color: red;&quot;&gt;Built with beta version of Unity. Will only work on your computer!&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;
which is pretty delightful. I guess as of 4.6.0, the games we&#39;re able to build at home are somehow ahead of the WebPlayer to the point where they could become dysfunctional? As a matter of fact when I ran the game under chrome, the healthbars were offset and didn&#39;t scale properly, as I&#39;m sure you&#39;ll see if you check the game out. I don&#39;t know how FF or IE deal, I didn&#39;t have the heart to find out. I mean, yes, it&#39;s my own fault for trying to create software to present to the public with beta tools, but I much would have preferred messages more specific to my situation:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;&lt;span style=&quot;color: red;&quot;&gt;Other computers may choke on your ridiculous, leaky algorithms!&lt;/span&gt;&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;&lt;span style=&quot;color: red;&quot;&gt;Other computers may just not have the CPU/GPU muscle to simultaneously lift and lower all the vertices of your tremendously detailed and natural game world which is not optimized in any significant way&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;&lt;span style=&quot;color: red;&quot;&gt;Your game world has, in defining its origins and boundaries, mishandled the spatial and memory assumptions of the machine you&#39;re working on so as to create some sort of novel geometric figure, somewhat like a turd the size of the universe spinning at (0,0,0).&lt;/span&gt;&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Just some decent error messages. That&#39;s all anyone should feel comfortable asking for.&lt;br /&gt;
&lt;br /&gt;
Coming Up:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;How bout them models&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;Some kind of hooky concept seems about ripe... this can only stay generic for so long&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;Models should perform some kind of death sequence&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;What&#39;s it all about, killing purple dudes? Do they drop money which allows you to buy better guns? From whom? The more solid your gameplay systems become, the more there is this need to commit to some kind of content interpretation in order to build more sophisticated sub-systems that enhance that interpretation. Generic gameplay engines are great, but you have to plant an conceptual / content-centric flag in order to make that into a game, and that&#39;s a process of walking through one of many doors and feeling a ton of other doors slam closed. You better hope you walked through a door you can live with! &amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2014/10/void-everythingthatrisesmustcollision.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9Ee7AimHK885ZYXx2MB4c4x7DWjd734oI9jOiZka1ybsy3Kt0-ZsCU2l4PKjUopsuZ9ZsQzuqwSiErwgWtqzusqmXIqxBTH2dnIO2SCdQBp_wlgyLRgwvla0ljscEZnoN7xoGMH3lBXep/s72-c/catalan_blog.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-3762567124857647839</guid><pubDate>Mon, 22 Sep 2014 00:29:00 +0000</pubDate><atom:updated>2014-09-21T18:00:13.922-07:00</atom:updated><title>Out On The Tiles</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf-tk8ex4FmHm_VHNANAUxWRvBAAqBLcFfPXKbaw-sgF2G8WQo-F6-ym0JsO1pYGo38WnTF-4UZhxLi476XaRNXOO01f_vdSpnR0LKqRsAncS5ti8TbcQSyPnR5GvJSTW_PPZ55IwtLCM5/s1600/bloggy.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf-tk8ex4FmHm_VHNANAUxWRvBAAqBLcFfPXKbaw-sgF2G8WQo-F6-ym0JsO1pYGo38WnTF-4UZhxLi476XaRNXOO01f_vdSpnR0LKqRsAncS5ti8TbcQSyPnR5GvJSTW_PPZ55IwtLCM5/s1600/bloggy.png&quot; height=&quot;237&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
Once a certain mega-game shipped, I found myself with a
little time in which to return to some Unity prototypes. Something about The &lt;b&gt;&lt;a href=&quot;http://chrisklepac.com/builds/benko/benko_web.html&quot;&gt;Benko&lt;/a&gt;&lt;/b&gt; isometric project kept drawing me
back, but I was frustrated by the control scheme. I wanted to control the main
character more directly, and I wanted to be able to use a gamepad to do it.
However, I also wanted the game to be playable in-browser by anyone with a
keyboard and mouse, which meant a back-up set of controls. Surely, I thought,
this would be a snap.&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
Unity did meet me more than halfway here, because rather
than having to plow through a bunch of GetKeyDown type functions, I could use
Input.GetAxis, which was automatically mapped to WASD for movement, and could
quickly be taught to recognize the trusty 360 gamepad. Getting parity in
movement was easy. Getting parity in facing was not quite so easy. &lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
The gamepad’s right thumbstick gave me a pair of clean,
normalized Vector3s right out of the box, so I was golden there. The interesting
part was getting that same result out of a mouse position. I knew that a
ScreenToWorld translation would be involved, but there was more to it. I fooled
around for many a Designated Leisure Period trying to covert Quaternions to
Vector3s using EulerAngles, exploring all the LookAt, LookTowards, and
TurnToLookAtThatGuy functions, and generally achieving jack all. I would find
solutions that had the right direction but the wrong magnitude, or solutions
that worked great until you moved the player away from the origin point, at
which point they broke down. Eventually I bumped my head or something and realized
that what I needed was a Ray. I guess I had unconsciously filed Rays away in
the part of my knowledge that dealt with collisions, and since I wasn&#39;t working
explicitly on the physics I didn&#39;t make the connection that this was an
available tool. But yes, when you need any information on where one point lies
in relation to another, and how one object might face another, at an arbitrary
distance from the origin, your best bet is to break out the Rays:&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;void HandleLookInput()
{
    //this func is how we set the lookDirection var every tick
 
    //MOUSE VERSION (first so gamepad can override if plugged in)
    mouseTarget = mouseScript.mouseTarget;
    //subtracting player pos from target gives us correct magnitude, which is then normalized to match gamepad
    Ray lookRay = new Ray(transform.position, (mouseTarget-transform.position).normalized);    
    Debug.DrawRay(transform.position, (mouseTarget-transform.position).normalized, Color.magenta);
    //force y to zero to avoid unwanted bullet fall
    lookDirection = new Vector3(lookRay.direction.x, 0.0f, lookRay.direction.z);

    //GAMEPAD VERSION
    if (isGamepad)
    {
        H_LookInput = Input.GetAxis(&quot;LookH&quot;);
        V_LookInput = Input.GetAxis(&quot;LookV&quot;);
        if (((H_LookInput &amp;gt;= 1) || (H_LookInput &amp;lt;= -1)
        || 
        (V_LookInput &amp;gt;= 1) || (V_LookInput &amp;lt;= -1))) 
        {
            lookDirection = new Vector3(H_LookInput, 0, V_LookInput);
        }
    }
    else
    {
        //don&#39;t change look dir if player released stick
        lookDirection = lastLookDirection;
    }
//Debug.Log(&quot;LOOKDIR : &quot; + lookDirection);
}
&lt;/pre&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;
The “bullet fall” thing is interesting, and leads into the
next part: I had a player and a big purple refrigerator (conceptually a bear)
and of course my next prototype impulse was to fire some sort of arrow or
bullet at the bear. I think the direction this is moving now is into a kind of “isometric
twin stick style action panic swarmer”, where the player fends of waves of
attackers, but we’ll see where it ends up.&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
As usual, I wildly underestimated the challenge of deriving
a projectile’s trajectory from a Vector3 representing a direction between two
objects. Seems like the same thing… but not on a flat plane where the bullet
has to come out of the muzzle of a weapon that could be rotated in any
arbitrary direction. This was the place for LookRotation, plus the
aforementioned &lt;b&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Euler_angles&quot;&gt;Euler Angles&lt;/a&gt;&lt;/b&gt;. &amp;nbsp;I won’t pretend to understand any of that
linked page, but I was able to find the examples I needed to rough in a working
implementation (this lives in the ranged_weapon script attached to the player’s
“bow”):&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;if (canShoot)
{
    //Debug.Log(&quot;yes&quot;);
    //make bullet
    //Debug.Log(&quot;BANG! &quot; + i);
    //Debug.Log(&quot;Creating a bullet at &quot; + transform.position);
    Vector3 targetVec = lookscript.lookDirection;
    Quaternion targetRot = Quaternion.LookRotation(targetVec);
    Quaternion flatTargetRot = Quaternion.Euler(new Vector3(90.0f, targetRot.eulerAngles.y, 0.0f));
    bulletClones[i] = Instantiate(bulletTemplate, transform.position, flatTargetRot) as GameObject;
    currentBulletsAlive++;
    //plant a reference to this weapon in the bullet when it is created
    bullet_base bulletscript = bulletClones[i].GetComponent&lt;bullet_base&gt;();
    bulletscript.weapon = transform;
    //throw bullet
    bulletPath = lookscript.lookDirection;
    //actually it makes more sense for the bullet to control its own movevemt
    //but will leave this variable in to ref from the bullet script
    //activating cooldown
    canShoot = false;
}
&lt;/bullet_base&gt;&lt;/pre&gt;
&lt;br /&gt;
The canShoot bool is to prevent bullet spam, and is made true on GetButtonUp. The bullet itself carries a script which throws it in the right direction (requiring that neat trick just above where we inject a value into a variable owned by something we just created, like inoculating an infant). The “bullet fall” mentioned above happens because for whatever reason the path to the target can sometimes have a y value of -0.1, which will cause it to fall through the ground plane somewhere in its flight time. The hack above led me to really understand the difference between a solution and a hack in a way that I never had before.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;A bug happens when some assumption you have about some data you have is wrong. If you trace the path by which you received the data backwards to where it diverged from your expectations, then re-derive the data from its sources so as to produce the desired result, you have solved the problem. If instead you take the data in your hand and say “well, regardless of what you think you are, you’ll conform to my expectations now so that I can proceed”, you have a applied a hack. It’s obvious why this is dangerous, and it’s equally obvious that there are any number of reasons why you’d do it anyway: maybe the source of the bug is deep within someone else’s code, or the exigencies of time and budget simply don’t allow for a proper solution. Hacking is about picking your battles, knowing when to do surgery and when to just use a bandage and cross your fingers.&lt;br /&gt;
&lt;br /&gt;
Some collider-based debug statements showed the bullet striking the bear, but the game didn&#39;t alert the player. I decided to flash the bear red by changing the material color, to my horror this was permanent after I hit the play button to stop the session. Turns out Materials can be instanced too, and a simple co-routinue times the flash effect:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;matInstance = Instantiate(baseMat) as Material;
baseColor = baseMat.color;
renderer.material = matInstance; 

[…]

void OnCollisionEnter(Collision collision)
{
    if (collision.collider.tag == &quot;playerBullet&quot;)
    {
        Debug.Log (&quot;enemy hit by player bullet&quot;);
        StartCoroutine(DamageFlash());
    }
}

IEnumerator DamageFlash()
{
    matInstance.color = Color.red;
    yield return new WaitForSeconds(0.25f);
    matInstance.color = baseColor;
}
&lt;/pre&gt;
&lt;br /&gt;
So the bear is hit, and everyone knows it. Coming up next:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Health, damage, and death&lt;/li&gt;
&lt;li&gt;GUI enemy health bars&lt;/li&gt;
&lt;li&gt;A GUI for the player&lt;/li&gt;
&lt;li&gt;Some proper character models??&lt;/li&gt;
&lt;li&gt;A proper “world” of tiles? (Maybe procedurally generated???)&lt;/li&gt;
&lt;/ul&gt;
The current build of Project Catalan can be played &lt;b&gt;&lt;a href=&quot;http://chrisklepac.com/catalan_web.html&quot;&gt;here&lt;/a&gt;&lt;/b&gt;.</description><link>http://ballistictelegram.blogspot.com/2014/09/out-on-tiles.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf-tk8ex4FmHm_VHNANAUxWRvBAAqBLcFfPXKbaw-sgF2G8WQo-F6-ym0JsO1pYGo38WnTF-4UZhxLi476XaRNXOO01f_vdSpnR0LKqRsAncS5ti8TbcQSyPnR5GvJSTW_PPZ55IwtLCM5/s72-c/bloggy.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-1679117386020205689</guid><pubDate>Tue, 24 Jun 2014 05:52:00 +0000</pubDate><atom:updated>2014-06-23T22:52:28.074-07:00</atom:updated><title>LETTER FROM THE FRONT: WRITING TIPS</title><description>I&#39;ve been writing. I stepped away from Unity and this blog to do a writing project, which is now over.&lt;br /&gt;
&lt;br /&gt;
A writing project is a menacing jungle full of traps and enemies. The enemies may be projected out from behind your eyeballs, but the traps are very real. I&#39;ve have spent years learning about all of them, and I have the closet full of horrific half-manuscripts to prove it. Lately I&#39;ve had to pass through some dark places I had hitherto managed to avoid, and now I&#39;m back with some simple tips that may help light your journey through that darkness. Some of these are surely either dead obvious, or so particular to my own process as to be useless, but maybe there&#39;s something here you can take with you.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
#1. MAP YOUR WAY OUT&lt;/h4&gt;
No, I don&#39;t mean actual drawn maps. I mean that when you dread sitting down to your story, because Mr. Jones has to get to the barber or whatever, and you don&#39;t know how the fuck he does it, and your last paragraph is about a bluebird, and jesus christ will this thing ever end, are you going MAD???&lt;br /&gt;
Calm down.&lt;br /&gt;
Set your actual current draft aside and open a new file called &quot;what_has_to_happen_for_this_chapter_to_be_over.txt&quot; A totally blank file. Now, picturing that awesome ending you&#39;ve already got basically DONE in your head, step yourself through how you get there, as though you were making a list ahead of going down to the grocery, drug and hardware stores the night before a hurricane. &quot;OK Fred has to get his passport photo taken, Rachel has to go to court and plead no contest..&quot; as you start to really articulate all the details that are holding you back in the story, you realize that some are either readily solvable or non-issues. Some are still problems, of course, but now you have a much clearer idea of where you want to go and how you want to get there, and what you need to spend energy giving to the audience versus what the audience is willing to take on faith.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
#2. AS YOU NEAR THE END &amp;gt; START A PROJECT NOTES FILE (IF YOU HAVEN&#39;T ALREADY)&lt;/h4&gt;
One of the things that will keep you from the finish line is that you&#39;ll have a cool idea, but think, &quot;oh, this means I have to go back and restructure some things to make this work, but I like this so much I want to make it work, so let&#39;s...&quot; and you pick up the shovel and your enthusiasm falls out of your butt.&lt;br /&gt;
Don&#39;t stop your forward momentum. If your new idea requires rewrites of earlier material, take a few sentences of notes in the alternate document of &quot;project_revision_ideas.txt&quot;, just to get the idea out of your head. Then, continue as you were, with the assumption that the work has already been done, the past has already been corrected. If you know where you are and where you are going, you can trust the past to explain itself later; do not go back to it and kick cans around while you still have work to do in the moment of the story. A great advantage of this technique is that when the time does come for you to gird your loins for the next draft, why look, you already have what&#39;s basically a roadmap to the weak spots. As an optional aside to this: &lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
#3. USE COLORS&amp;nbsp;&lt;/h4&gt;
You might be amazed at the power of this technique: when something is obviously not quite right, but difficult or impossible to make right at this very moment... write FIX THIS next to it and make it bright pink and bold. Then move on to the next paragraph and keep going. If you move far enough ahead, the next time you open the manuscript and see that, you&#39;ll be like, oh, right, and do a sentence or two that writes out your original half-assed flailing at an idea and replaces it with an actual idea that you worked out below in the meantime. This is preferable to spending hours banging your head on this one part because it had to be just right just then. Colors, shapes, pictures or links to pictures: if you can&#39;t the words you want on paper, it&#39;s OK to just put down a signpost or a reference, as long its clear enough that you&#39;ll know what it means later. This is a technique stolen from programming, where early code is studded with TODO and HACK FIX THIS. Don&#39;t let contemplation of tomorrow&#39;s work keep you from doing today&#39;s.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
#4. AS YOU NEAR THE END &amp;gt; ANTICTIPATE AND EMBRACE &quot;POST-PRODUCTION&quot;&lt;/h4&gt;
Making a complete first draft is like passing a god damned kidney stone, you definitely don&#39;t want to go back into that bathroom for at least a little while. However, whatever indexing, appendixing, formatting, and bow-wrapping details your particular project requires still stand between you and rung zero, which is the first person who is going to read it and tell you it sucks. Don&#39;t be passing around raw unformatted files of rambling text. You don&#39;t buttonhole people on the street and yell at them unceasingly, do you? Have some manners. Respect the potential person whom you are asking to read your work by presenting them with something that is not visually worse than what they already have to read during the course of the day. Going back over your work in various ways just to make it more visually presentable is a necessary part of finishing, and if you&#39;ve already adopted a grim death march attitude by three quarters through your first draft, you are just not going to have the stomach for it. As you near the end, anticipate what you are going to need to do so it&#39;s not a surprise, and recognize that writing THE END doesn&#39;t mean you can run out into the street with it. BUT, heed the corollary:&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
#5. DON&#39;T DO FORMATTING WORK IN THE MIDDLE OF A DRAFT&lt;/h4&gt;
More generally: don&#39;t do anything during a draft that could potentially result in multiple conflicting versions of a draft. If you catch yourself copying draft text from one program to another, slap yourself. How many problems are you trying to cause for yourself here? Seriously? You want to spend hours reconciling multiple versions of a second or third draft?&lt;br /&gt;
You can do pretty stuff between drafts. If you started in a spiral notebook, finish the draft in the damn notebook. If you started on a PC, finish on a PC and do the next draft on your new Mac or whatever. Never split a draft.&lt;br /&gt;
The reason this happens is because writing requires you to switch between states of intense concentration and kind of mind-wandering states, and it&#39;s gratifying in a masturbatory way to idly reformat your draft. You are walking down the devil&#39;s path if you do this. Find something else to do while daydreaming. I hear some people enjoy Sudoku.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
#6. GET TO THE PART YOU WANT TO WRITE TODAY (OR TONIGHT) AND WRITE THAT&lt;/h4&gt;
An example: in your story, Farmer Bob purchases and wrecks a Maserati. In order to do this, he has to fleece some bankers and relatives, and perform various identity sleight-of-hand tricks. You feel compelled to make that part real because this is a realistic story, but the story started in your mind with this dream of Bob hauling ass on a twisty Iowa two-lane, and that&#39;s all you can think about as you write him in the banker&#39;s office, submitting his loan application and twisting his cap in his hands... The point is, any of your precious god-given time you manage to carve out to sit down to do the work, write the part you want to write. It&#39;s the least you can do for yourself. If you feel a need to sketch out some justification for getting to that part, give it a sentence or two. That stuff you write when you are seized by an idea and write what you want is always going to be loved and admired and actually read the most of anything you do, because it has your fire and your heart. If instead you are always having to set up a tedious house of cards to push your characters to where you want them to be, like a desperate Axis general shuffling units around a mock battlefield with one of those little pushbrooms... well, you&#39;re fucked, you&#39;ve lost the thread. If you pursue the part you want to write, one of several things will happen: 1. Once your mind is free of the obsession of the part you wanted to write, it will naturally turn to other thoughts and any necessary exposition will fill that space. Then you write it and you&#39;re good. Or 2: if the part you wrote just isn&#39;t workable, you gained a deeper and necessary understanding of the story you really wanted to tell. Maybe the Maserati episode happens in a dream Bob has when he falls asleep driving the tractor. Maybe that dream never even makes it to the final draft, but your understanding of it informs Bob&#39;s character and makes your work better. Never fear that you are wasting time because you are writing the part you want to write, that&#39;s never the case.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
#7.YOUR AUDIENCE NEEDS LESS EXPOSITION THAN YOU THINK THEY DO&lt;/h4&gt;
A scene of two characters speaking about events in the present, if written skillfully and with the intent to do so, can cast strong light and shadow on any character&#39;s past, while never insulting the audience with a blunt disclosure that doesn&#39;t suit the conversations or the characters. An example: Billy has been in prison for five years. When his mother and his fiancee meet for the first time, for lunch, don&#39;t feel compelled to have either of them trumpet this fact just because it&#39;s the most important fact in their relationship. For this very reason, have them act like real people would, and tiptoe around the particulars of the subject, until the audience is wondering &quot;what happened to this guy, did he get sick, did he go visit a guru in Tibet?&quot; This segues nicely into:&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
#8. YOUR AUDIENCE WANTS TO DO SOME (EASY) WORK (THAT MAKES THEM FEEL CLEVER)&lt;/h4&gt;
Your audience did not come to your entertainment to have every question they might consider answered immediately. By the same token they probably did not come to sit through some inscrutable outpouring of free assosciations. They probably came to participate in a give-and-take with you, that is enetrtaining, intellectually stimulating, and emotionally rewarding. They want to leave your work feeling like they know the world a little better, and they can&#39;t do this if you don&#39;t give them anything to think about. Conceal and reveal. Exposition and (ugh) &quot;world-building&quot; are not things you do at the beginning of a story, like the yellow Star Wars text crawling up the screen, to ground your audience in the self-imposed rules of your fiction, unless you are the worst kind of hack. If your fictional world (be it Castle Azgoth or 1973 Jersey City) has boundaries, and common knowledge, and things that mean certain death, let the reader learn about those things alongside the characters that they have become invested with (if you reach page 2, you are probably invested with a character). Don&#39;t profess: let characters experience the world, and bring the reader along. The same goes for realism: don&#39;t tell us the husband suspects infiedlity, show us late nights alone while the wife is at the office, and callers that hang up when they hear a man&#39;s voice. Trust the reader a little bit and the reader will be more interested. Treat the reader like a moron and they will hang up on your story.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
#9 EMBRACE GENRE, REJECT GENRE, COMMENT ON GENRE&amp;nbsp;&lt;/h4&gt;
Cliches get a bad rap. cliches are the Jungian archetypes of colloquial speech. Don&#39;t be afraid of an idea because it seems too familiar. There is nothing new under the sun... except you and your perspective on the stories we&#39;ve all heard a thousand times already. If you have a new way to tell it, the whole world might listen.&lt;br /&gt;
</description><link>http://ballistictelegram.blogspot.com/2014/06/letter-from-front-writing-tips.html</link><author>noreply@blogger.com (Chris)</author><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-2142563975569098943</guid><pubDate>Thu, 16 Jan 2014 05:21:00 +0000</pubDate><atom:updated>2014-02-23T21:24:13.373-08:00</atom:updated><title>The Terrible Twos</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFPy2WgkfcwecMQMzKikjYBNePFvLHhDlFyjQZQHRLbjnpeFcbitiEKYwS4GwdfDfPbCSdyJiIguDJoDVq-RdwlN_hKA5M-D1qIjOMj3wVIc5GRMPxSVilNKNzB4hJ2E1_N4LC0XxzZ-uN/s1600/twos.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFPy2WgkfcwecMQMzKikjYBNePFvLHhDlFyjQZQHRLbjnpeFcbitiEKYwS4GwdfDfPbCSdyJiIguDJoDVq-RdwlN_hKA5M-D1qIjOMj3wVIc5GRMPxSVilNKNzB4hJ2E1_N4LC0XxzZ-uN/s1600/twos.png&quot; height=&quot;188&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I think level two is looking pretty good, and I&#39;m only about a month and a half behind schedule and have just a few major features to implement, and I have plenty of time and mental energy after my psychically non-demanding job to pour into all my portfolio projects...&lt;br /&gt;
&lt;br /&gt;
Well I do think it looks alright, compared to the opening level. I&#39;m learning. When designing level one, I had just discovered some tutorials on making grids of tiles in Unity, and was enraptured by this idea of a &quot;tile engine&quot; and all the games I was going to make with it, and somehow got it into my head that the various buildings all had to be made of tiles, and somehow all the tiles had to draw from a single 256x256 sheet, so all those brick buildings in the first level are made up of instances of like BRICK_BLDG_LOWER_LEFT_WINDOW tiles and it&#39;s horrible. The great joke is that I thought this was somehow saving me memory as I blithely constructed fifty different materials all drawing from the same tile sheet. In the end I don&#39;t think it matters much but I made a lot of extra work for myself to produce something that could have looked better.&lt;br /&gt;
&lt;br /&gt;
In a way, though, I did make a bit of a tile engine, because when it was time for level two, I duplicated level one and just took everything out, save for the backgrounds and a single tile for the player to land on when I pressed start. I wanted to sculpt out a shape for the walkable areas of the level, and I started duplicating that tile and moving it around. Soon, I found I wanted images of the mid-ground scenery, I think of these in my mind as &quot;flats&quot;, the is from theater, where it means a large frame built from plywood, with canvas stretched over it, on which is painted something like a castle battlement, or a storefront, or a brick wall.&lt;br /&gt;
&lt;br /&gt;
A flat here is just a gameObject with a Mesh Filter and Mesh Renderer components. The Mesh is a Quad, and the renderer&#39;s material is made to point at a Texture of X by X (powers of two, please) and you have onscreen whatever it is you drew in your favorite &quot;draw stuff&quot; program. Just place these further away on the z-axis than your player and the ground he or she must collide with, and you have 2d scenery.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Glossing quickly over the quality of the art itself (yyyyeah), we come to the matter of the ghost, who presented a particular problem. Enemies in WAFHGame execute a function called &quot;Patrol&quot;, and enemies are a sub-species of character, that is to say the script WafhEnenmy.cs is a class which inherits from WafhChar.cs. The problem is that WafhChar only executes the Patrol function during its update if the Char in question is Grounded.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Being &lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/CharacterController-isGrounded.html&quot;&gt;Grounded &lt;/a&gt;in Unity is a particular state, like being flat-footed in D&amp;amp;D. (if you get that reference, I&#39;m sorry). The Character Controller is Unity&#39;s answer to one of the common beginner game dev problems: &quot;I need some object that represents the player than can listen for all sorts of input, and respond naturally to all sorts of things, and inteact with both the environment and anyone else around, in all possible types of games.&quot; A lot of people seem wary of the Character Controller, but for a lot of us it&#39;s a godsend and we wouldn&#39;t be here without it, honest to Bob. Code low-level game controller input systems? Are you out of your mind?&lt;br /&gt;
&lt;div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
So here we had a ghost who would not Patrol, because since I set his character&#39;s gravity to 0, to keep him from falling, he never acquired the property of being Grounded, so he would never Patrol. First thought was to allow Patrol to fire when not Grounded. Now, as I&#39;m writing this, I wonder &quot;why didn&#39;t I just remove the Patrol check from the conditional of being Grounded? Let falling skeletons Patrol in the air for a few fractions of a second when they fall off a platform, they&#39;re not hurting anyone.&quot; A noble thought, and yet my baser natures won out. My memory grows dim. I can say for sure I ended up extending WAFHGhost from WAFHChar:&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;
public class wafhGhost : WafhEnemy {
 //ghostly vars:
 float waverYVariance = 16.0f; //how spooky do we get
 float maxY;      //calcd from current position
 float minY;      //calcd from current position
 Vector3 currentPos;
 float InitialY;     //source for calcs
 float currentY;     //source for calcs
 float targetY;     //where we are going
 float targetDistanceDelta = 1.0f; //dunno
 CapsuleCollider capsule;
 Vector3 vertTarget;
 Vector3 myCenter;
 Vector3 ghostVelocity;
 float ghostYSpeed;
 
 //public GameObject debugCubePrefab;
 //GameObject debugCubeClone;
 
 public override void Start () {
  
  base.Start();
  gravity = 0.0f;
  InitialY = transform.position.y;
  maxY = InitialY + waverYVariance;
  minY = InitialY - waverYVariance;
  capsule = transform.GetComponent&lt;capsulecollider&gt;();
  //debugCubeClone = Instantiate (debugCubePrefab, transform.position, transform.rotation) as GameObject;
  ghostYSpeed = 50.0f;
  deathOffset = new Vector2(0, 0);
 }
 

 public override void Update () {
  base.Update();
  myCenter = new Vector3(transform.position.x + (controller.center.x), transform.position.y + (controller.center.y), transform.position.z + (controller.center.z));
  GhostlyShenanigans();
  ghostPatrol(patrolLimit);
  //Debug.DrawRay(myCenter, debugCubeClone.transform.position, Color.green, 0.1f);
  
 }
 
 void GhostlyShenanigans()
 {
  currentY = transform.position.y;
  AdjustGhostVelocity();
  GhostFloat(transform.position.y);
 }
 
 public override void Patrol(float patrolLimit)
 {
  base.Patrol(patrolLimit);
 }
 void AdjustGhostVelocity()
 {
  if (transform.position.y &amp;gt; maxY)
  {
   //Debug.Log(&quot;broke max, moving down&quot;);
   ghostYSpeed = -ghostYSpeed;
   
  }
  if (transform.position.y &amp;lt; minY)
  {
   //Debug.Log(&quot;broke min, moving up&quot;);
   ghostYSpeed = -ghostYSpeed;
  }
  ghostVelocity = new Vector3(0.0f, ghostYSpeed, 0.0f);
 }
  
 void GhostFloat(float currentY)
 {
  //transform.position = Vector3.MoveTowards(transform.position, vertTarget, targetDistanceDelta);
  controller.Move( ghostVelocity * Time.deltaTime );
 }
 


 void ghostPatrol(float patrolLimit)
 {
  state = CharacterState.Walking;
  patrolTime += Time.deltaTime;
  //print (&quot;patrol time &quot; + patrolTime);
  if (patrolTime &amp;lt; patrolLimit)
  {
   //the ifs in here are to handle enemies with flipped textures cause I suck at art asset generation
   if (facing == 1)
   {
    velocity.x = walkSpeed; 
    if (gameObject.tag == &quot;enemy&quot;)
    {
     ragePixel.SetHorizontalFlip(true);       //texture flip
    }
    else
    {
     ragePixel.SetHorizontalFlip(false);
    }
    ragePixel.PlayNamedAnimation(&quot;WALK&quot;, false);    //texture animation
   }
   if (facing == -1)
    {
     velocity.x = -walkSpeed;
     if (gameObject.tag == &quot;enemy&quot;)
    {
     ragePixel.SetHorizontalFlip(false);       //texture flip
    }
    else
    {
     ragePixel.SetHorizontalFlip(true);
    }
     ragePixel.PlayNamedAnimation(&quot;WALK&quot;, false);    //texture animation
   }
  }
  else
  {
   //print (&quot;FLIP FUCKER&quot;);
   patrolTime = 0.0f;
   facing = -facing;
  }
 }
}
&lt;/capsulecollider&gt;&lt;/code&gt;
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
We are Patrolling every Update, but this is really the same RagePixel code we use in the main Patrol function, it&#39;s a copy/paste. This, as far as I have gathered, is one of the sadder and more shameful sins you can commit writing code: having to write something out in more than one place. It is an invariable sign that you have failed to optimize, misaligned your architecture, fucked up in general.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
None of this is what I was meaning to write a post about. I meant to write about a particular revelation during the last phase, the placing of the bus transfers, the deciding which branches should have enemies walking (or floating) back and forth on them: I sat down to the business of level design and realized&lt;i&gt; I had already made most of the important decisions already&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&quot;Level Designer&quot; is the cap I like to picture myself wearing, and it&#39;s a role I&#39;ve made a decent living holding before, and I&#39;ve often thought of the level design &quot;parts&quot; of making WAFHGame as satanically delicious treats to gorge on when I had finished the Volga Boatman gruntwork of asset preparation. Well, as it turns out, when I decided the size of the house and store flats, that was level design, because that, combined with the speed of the player (also level design) determines how fast the scenery moves by, which affects how your eye registers it and both how much attention you pay to it and at least part of your emotional response. Drawing the trees, and deciding how far apart branches should be, that was level design, so is the scroll speed on the parallax skyscrapers. Anything that happens to you in the level is by definition a result of level design, at some level.&lt;br /&gt;
&lt;br /&gt;
Of course for tiny projects, level and gameplay design are inseparable, but I think it&#39;s an easy thing to lose sight of as projects get bigger. The size of the tile and the length of the jump are bigger level design factors than anything else in WAFHGane, and it&#39;s impossibl to make any level design decisions that don&#39;t depend omn those. I keep trying to adjust &amp;nbsp;the jump as I go, and it often feels unsalvageable and floaty and tedious, and I want to start over, but of course that&#39;s insanity. It just has to get done, but every decision, even the most frivolous-seeming art decision (sorry artists) has direct effects on gameplay and are a core component of level design. As someone like Timothy Leary might have said: &quot;The more I get into it, the more it&#39;s &lt;i&gt;all one thin&lt;/i&gt;g&quot;.&lt;br /&gt;
&lt;br /&gt;
Three levels, with different art. Each level has a pair of enemy types. Some enemy types repeat, but pairs don&#39;t. There are a few unlocks you can get by beating levels in particular ways. The experience flows smoothly, from menu to gameplay, with appropriate UI popups, without crashing.&lt;br /&gt;
&lt;br /&gt;
That&#39;s it, not even a leaderboard, no points even! How hard could it be. And yet here I sit, blogging. Not working! Not drawing skeletons! Shame on me for reals. I&#39;m 2/3 done. &amp;nbsp; &amp;nbsp; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2014/01/the-terrible-twos.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFPy2WgkfcwecMQMzKikjYBNePFvLHhDlFyjQZQHRLbjnpeFcbitiEKYwS4GwdfDfPbCSdyJiIguDJoDVq-RdwlN_hKA5M-D1qIjOMj3wVIc5GRMPxSVilNKNzB4hJ2E1_N4LC0XxzZ-uN/s72-c/twos.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-5797731489307443566</guid><pubDate>Sun, 15 Dec 2013 19:36:00 +0000</pubDate><atom:updated>2013-12-15T11:36:07.644-08:00</atom:updated><title>Better</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjorcNZ3B9bZfTYHy1uIAVotQNtT1lwqHItCdbSnGzYZyufujlv6XO4RYr-n3L3UvyCDTboxbNJ5l4UsPLmglp3kW77cu0V44Qtq7gFUNMHbnY1IoImcmS-9l9leEMGGEzlD8_rzRviIG2/s1600/rays.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;99&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjorcNZ3B9bZfTYHy1uIAVotQNtT1lwqHItCdbSnGzYZyufujlv6XO4RYr-n3L3UvyCDTboxbNJ5l4UsPLmglp3kW77cu0V44Qtq7gFUNMHbnY1IoImcmS-9l9leEMGGEzlD8_rzRviIG2/s320/rays.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I&#39;m now controlling the layer collision by use of a raycast, and the results are better but not perfect. I cast from about knee level down to a bit past foot level, and if there&#39;s a collision there I turn the branches on, otherwise they are off. This does neatly solve the problem of the player banging into the sides of colliders on the down arc of a jump, but it introduces another problem: some of the branches are close enough together vertically that when the player jumps, his head hits the branch above before the ray leaves the branch below, and thus the overhead branch doesn&#39;t get turned off. I&#39;ve tried tweaking the length of the ray but it has to be at least a certain length, otherwise certain slanted platforms have trouble registering and the player falls through.&lt;br /&gt;
&lt;br /&gt;
The best thing to do here is probably to raise the problem branches so that they don&#39;t cause as much head-bumpage. It&#39;s an interesting lesson in that everything has to react to everything else, the movement mechanisms and the environment design are totally interdependent. Well, it was about time for an art push on this level anyway, so I guess it&#39;s not too much trouble to move some tree branches around. Here&#39;s the final version of the raycast script:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
using UnityEngine;
using System.Collections;

public class footShooter : MonoBehaviour {
 RaycastHit info;
 CharacterController controller;
 Vector3 center;
 float floorDist;
 CapsuleCollider cap;

 Vector3 lowCenter;
 void Start () 
 { 
  cap = gameObject.GetComponent&lt;capsulecollider&gt;();
  controller = gameObject.GetComponent&lt;charactercontroller&gt;(); 
  floorDist =  controller.height/3;
 }

 void Update () {
  center = new Vector3(transform.position.x + (controller.center.x), transform.position.y + (controller.center.y), transform.position.z + (controller.center.z));
  lowCenter = new Vector3(center.x, center.y - (controller.bounds.size.y/3), center.z);
  Ray footRay = new Ray(lowCenter, Vector3.down);

  if ((controller != null) &amp;amp;&amp;amp; (cap != null))
  {
   if (!controller.isGrounded)
   { 
    Debug.Log(&quot;centre = &quot; + center);
    if(Physics.Raycast(footRay, out info, floorDist))
    {
     Debug.Log(&quot;red ray&quot;);
     Debug.DrawRay(footRay.origin, footRay.direction*floorDist, Color.red);
     Debug.Log(&quot;hitting branches&quot;);
     Physics.IgnoreLayerCollision(10, 13, false);
    }
    else
    {
     Debug.Log(&quot;blue ray&quot;);
     Debug.DrawRay(footRay.origin, footRay.direction*floorDist, Color.blue);
     Debug.Log(&quot;ignoring branches&quot;);
     Physics.IgnoreLayerCollision(10, 13, true);
    }
   }
  }
  else
  {
   Debug.Log(&quot;controller is NULL&quot;);
  }
  
 }
}
&lt;/charactercontroller&gt;&lt;/capsulecollider&gt;&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;</description><link>http://ballistictelegram.blogspot.com/2013/12/better.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjorcNZ3B9bZfTYHy1uIAVotQNtT1lwqHItCdbSnGzYZyufujlv6XO4RYr-n3L3UvyCDTboxbNJ5l4UsPLmglp3kW77cu0V44Qtq7gFUNMHbnY1IoImcmS-9l9leEMGGEzlD8_rzRviIG2/s72-c/rays.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-3503806848804755042</guid><pubDate>Sun, 08 Dec 2013 19:35:00 +0000</pubDate><atom:updated>2013-12-08T11:43:13.399-08:00</atom:updated><title>The Cult Of Ray</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpkNiyTJqoT53-1Lp3qmnA3NB571rU3dhRTYa9_piWZLZ7lS1nGoS3h7De50r_KTWb_3FltGywuP9KZuIYCWc7iU3_p7T9vGzoC2kT_Xzlo9LjDj3N9ar1LMIjGAgOzve2WXKkdo-OVWoO/s1600/rays.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;163&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpkNiyTJqoT53-1Lp3qmnA3NB571rU3dhRTYa9_piWZLZ7lS1nGoS3h7De50r_KTWb_3FltGywuP9KZuIYCWc7iU3_p7T9vGzoC2kT_Xzlo9LjDj3N9ar1LMIjGAgOzve2WXKkdo-OVWoO/s320/rays.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Raycasting is a common, essential technique in modern game making that I had until now more or less avoided. I&#39;d need it in order to make my one-way platforms work as intended, but I was having trouble in the context of the platformer so I decided to back up and go to a blank project, and to kill two birds it seemed like a good moment to set up something I&#39;ve had in my notes for awhile: a template for experimenting with FPS gameplay in Unity.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
As laid out by &lt;b&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=bXrCMwtNaTk&quot;&gt;this tutorial&lt;/a&gt;&lt;/b&gt;, a basic fps setup is no further away than a plane, a camera, and a First Person Controller dragged out of the Standard Assets folder and into scene view. Before I could get to the raycasting though I needed to scratch a different itch: I had become spoiled by modern PC FPS titles into expecting gamepad support as a seamless option to mouselook.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Before you invite me to turn in my PC gamer badge and graphics card, consider a game like the excellent &lt;i&gt;Metro: Last Light&lt;/i&gt;, which I&#39;m currently playing through thanks to the fall Steam sale. I&#39;ve experimented with both control schemes, and while, yes, you can&#39;t beat a mouse for combat turning and aiming speed, when you&#39;re involved in an &quot;adventure FPS&quot; with a lot of different player verbs, it just feels really natural to have something like &quot;wipe condensation from gas mask&quot; on a shoulder button. Maybe this goes back to my lack of skill as a typist, but unless we&#39;re talking about WASD I&#39;m never quite certain of my keyboard execution in a twitch situation. The controller is also just more interesting to me for whatever reason.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
So I had to have my 360 controller, and I did it by replacing the script MouseLook (part of that Standard Assets character package) with StickAndMouseLook, which goes something like this:&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;
using UnityEngine;
using System.Collections;

[AddComponentMenu(&quot;Camera-Control/Stick and Mouse Look&quot;)]
public class StickandMouseLook : MonoBehaviour {

 public float sensitivityX = 15F;
 public float sensitivityY = 15F;

 public float minimumX = -360F;
 public float maximumX = 360F;

 public float minimumY = -60F;
 public float maximumY = 60F;

 float rotationY = 0F;
 string[] jNames;
 
 bool isGamepad;
 
 void Update ()
 {
  jNames = Input.GetJoystickNames();
  if (jNames.Length &amp;gt; 0)
  {
   //Debug.Log(jNames[0]);
   isGamepad = true;
  }
  else
  {
   //Debug.Log(&quot;no gamepad&quot;);
   isGamepad = false;
  }
  
  if (isGamepad)
  { 
   float rotationX = transform.localEulerAngles.y + Input.GetAxis(&quot;rightStickX&quot;) * sensitivityX;
    
   rotationY += Input.GetAxis(&quot;rightStickY&quot;) * sensitivityY;
   rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
    
   transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
  }
  else
  {
   float rotationX = transform.localEulerAngles.y + Input.GetAxis(&quot;Mouse X&quot;) * sensitivityX;
    
   rotationY += Input.GetAxis(&quot;Mouse Y&quot;) * sensitivityY;
   rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
    
   transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);   
  }
 }
 
 void Start ()
 {
  // Make the rigid body not change rotation
  if (rigidbody)
   rigidbody.freezeRotation = true;
 }
}
&lt;/code&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
Of course you need for those axes to actually exist, so you set them up in the Input settings like this:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBThGR704nCi3jgQ6uN2EMWYJR9J1y_mpiS0LO5W4g-O_LsKJp506amXEdq2NNV4NR_Ev_qNDs0Kg25IjhE4FJyvrGHcmAvuvPagz9RC2GL4K7MXR7hPwq0XNs8IPkp65DKtHn6-98G1hJ/s1600/sticks.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBThGR704nCi3jgQ6uN2EMWYJR9J1y_mpiS0LO5W4g-O_LsKJp506amXEdq2NNV4NR_Ev_qNDs0Kg25IjhE4FJyvrGHcmAvuvPagz9RC2GL4K7MXR7hPwq0XNs8IPkp65DKtHn6-98G1hJ/s320/sticks.png&quot; width=&quot;268&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Now you can use the mouse, plug in a gamepad, play that way, unplug it and you&#39;re back to mouselook. Movement gets handled automatically by the character motor because it uses the horizontal / vertical input axes, which the sticks already do as well. Interesting to note that the triggers are read as axes themselves rather than buttons, requiring some fiddling elsewhere to get semi-auto behavior, and that the Invert checkbox is required to get &quot;move up to look up&quot; behavior (you know, Normal Person style) out of the Y stick. Either I set something up backwards or one of the coders behind this is one of those sickos who thinks Inverted Y controls should be the status quo. I&#39;ll give them the benefit of the doubt and assume the mistake is mine.&lt;br /&gt;
&lt;br /&gt;
So, raycasts. The vexing stumbling block for me was always this: rays are invisible. Physics.Raycast takes as parameters an origin, a direction, and a distance. Debug.Ray can be used to draw rays, but its parameters only have an origin and a direction, no distance. The reason behind this involves some of that spooky math stuff, wherein a vector can contain both a direction and a distance. There&#39;s some &lt;b&gt;&lt;a href=&quot;http://www.fundza.com/vectors/normalize/&quot;&gt;normalization math&lt;/a&gt;&lt;/b&gt; that could be involved here but of course once I saw that I ran in the opposite direction.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
As it turns out, if you have the ray you have all the info you need to draw it. Take this ray:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;
Ray shotRay = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0.0f));
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Since that&#39;s just specifying a point on the main camera, from which it will travel until it hits something, it was far from clear initially how I would get the position and direction/distance information. Luckily, the Ray object itself contains some information, so &lt;code&gt;shotRay.origin&lt;/code&gt; can be used as the originating point. The second variable can be got by subtracting the Vector3 from which the shot came from the Vector3 at which the shot hit. So, assuming this script lives on the shooter, you can do this:&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;
Ray shotRay = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0.0f));
    RaycastHit info;
    if (Physics.Raycast(shotRay, out info))
    {
     Debug.DrawRay (shotRay.origin, info.point-transform.position, Color.blue, 3.0f);
      
    }
&lt;/code&gt;&lt;span style=&quot;font-family: Times New Roman;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
And for three seconds you&#39;ll get a visual image of your raycast in scene view. I was emboldened enough by this to wonder if I could send hit particles out at an angle relative to the incoming angle, and sure enough there&#39;s a Vector3.Reflect. the RaycastHit info variable above comes back into play as \you can get the incoming hit direction like this:&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;
inDir = info.point - player.transform.position;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
and that same handy info variable contains the normal I need for the reflection, that is to say a line straight out of the plane we hit. Since I don&#39;t care where this line ends I was able to cheat in a magnitude for the debug line by multiplying it with an int, which is a little crazy but I&#39;m just gonna go with it:&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;
Vector3 reflectionDirection = Vector3.Reflect(inDir, info.normal);
Debug.DrawRay(info.point, reflectionDirection*100, Color.cyan, 3);
&lt;/code&gt;&lt;span style=&quot;font-family: Times New Roman;&quot;&gt;&lt;span style=&quot;white-space: normal;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;
This gives us the rays depicted at the top of this post. I&#39;m thinking (hoping) that armed with this I can turn back to the platformer and easily get the collision behavior I want. As soon as I&#39;m done with this other idea I have about making these big blocks destructible. Shouldn&#39;t take but a few minutes...&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/12/the-cult-of-ray.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpkNiyTJqoT53-1Lp3qmnA3NB571rU3dhRTYa9_piWZLZ7lS1nGoS3h7De50r_KTWb_3FltGywuP9KZuIYCWc7iU3_p7T9vGzoC2kT_Xzlo9LjDj3N9ar1LMIjGAgOzve2WXKkdo-OVWoO/s72-c/rays.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-2932512228537409471</guid><pubDate>Fri, 29 Nov 2013 20:32:00 +0000</pubDate><atom:updated>2013-11-29T12:35:00.857-08:00</atom:updated><title>In The Trees, In The Weeds</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiejBy1wzhxoRHBJgMBnSirb5dZaWKsJf7l8hutaOveJ6RLsYzD3T7oVmPm4hifEINZQKhZdBaJ4In8iBy1BVMbi-RBCbpBOxuP6VDUvwA2ne5pTiBJLEgTAxCa9K6BBZbSITXcsaPaDPNA/s1600/TREES.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;191&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiejBy1wzhxoRHBJgMBnSirb5dZaWKsJf7l8hutaOveJ6RLsYzD3T7oVmPm4hifEINZQKhZdBaJ4In8iBy1BVMbi-RBCbpBOxuP6VDUvwA2ne5pTiBJLEgTAxCa9K6BBZbSITXcsaPaDPNA/s320/TREES.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I&#39;ve entered some impossible place where every task takes twice as long as the previous task. The goal was and is still three playable levels, with a few neat unlocks and a couple more enemies. Level 2 is supposed to represent Seattle&#39;s Queen Anne neighborhood, with its imposing hill spreading up the right side of the screen. There&#39;s not much platformer action to be had on a single steep hill, so what to make platforms out of?&lt;br /&gt;
&lt;br /&gt;
Pioneer Square had the easy visual metaphor of that big iron lattice pergola (yeah I had to look up what the hell that thing&#39;s called), but nothing so obvious exists in QA. Trees were an obvious solution, I remember planning to have a few in one area or another, and they are about as classic a platform-disguise trope as you can get. One problem that arose quickly is that I can&#39;t draw a convincing tree. &lt;br /&gt;
&lt;br /&gt;
The method I ended up with is far from ideal but somehow the appearance was able to barely pass my internal editor. After all, I had to come up with &lt;i&gt;something&lt;/i&gt;. I drew out the trunk and each branch, as well as four squiggly bare &quot;sub-branches&quot;. I flipped each of the sub-branches for a total of 8, then took a green 32x32 &quot;leaf&quot; and used it as a stamp across all of those, as shown here:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3QfNKmnR9qRP6oxQL21vsM9HuAHsxYFMEy5-cxXLMkLRMgK0u72Q_BJ9uw1H936DiOYTxJsm5QmCKxJZuR5oKiQtzSNrMvJJfioc7fRYPvkGLCofYGlL-TuQSRaf_K5TGn2OiOQqQGZ1H/s1600/branches.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;74&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3QfNKmnR9qRP6oxQL21vsM9HuAHsxYFMEy5-cxXLMkLRMgK0u72Q_BJ9uw1H936DiOYTxJsm5QmCKxJZuR5oKiQtzSNrMvJJfioc7fRYPvkGLCofYGlL-TuQSRaf_K5TGn2OiOQqQGZ1H/s320/branches.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Then each individual branch of the tree gets stamped with a selection of these sub-branches and attached to the trunk. I made each branch its own gameObject because I had this idea of scripting them all to sway gently in the breeze, which I may still do but whenever I picture it now it looks like it would be unsettling, which is maybe a point for and not against. I&#39;ve thought also about doing a lighter green semi-transparent globe of leaves behind each tree to give them a more traditional tree-like appearance, but I&#39;m not sure I could really get it right.&lt;br /&gt;
&lt;br /&gt;
The tree branches also presented an opportunity for varied routes through the level, something more interesting than flat planes, so I rigged up the hinged box colliders shown at the top. Now, to do this kind of platforming right, you need for the player to be able to pass through these colliders when jumping from beneath. You can&#39;t make them go to the end of each branch and then try to reach the one above, it wouldn&#39;t work. There are many ways to do this.&lt;br /&gt;
&lt;br /&gt;
One important point is that each face of a collider only works in one direction. So theoretically the easiest solution would be to use, instead of box colliders, mesh colliders with a single quad sprite mesh, facing up. Player passes through from the bottom, collides on the way down.&lt;br /&gt;
&lt;br /&gt;
I didn&#39;t go with this, because some early experiences and research led me to understand that single plane collision with a 3d object in a 3d environment is inherently just a bad idea. You&#39;re subject to &quot;tunneling&quot;, where the surface area that records a hit is so narrow that your colliding object can pass through it between the high-speed snapshots your physics simulation is taking of the game state.&lt;b&gt; &lt;a href=&quot;http://answers.unity3d.com/questions/192420/plane-mesh-collider-doesnt-stop-capsule-sometimes.html&quot;&gt;This Unity Amswers user sums it up.&amp;nbsp;&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Another solution, likely quite easy for many, would be to take the standard Unity box collider, import into Blender or what have you, remove the bottom, and export back to Unity. Custom collision mesh, very nice. Problem is I don&#39;t have any skill points in 3D modeling.&lt;br /&gt;
&lt;br /&gt;
&quot;It&#39;s free, there are tutorials, you could learn to do that much in an afternoon!&quot; Yes but I have a series of goals here and I can&#39;t be endlessly sidetracked. Maybe my next game will involve custom 3D models but this one doesn&#39;t and I need to finish it with the tools at hand. That&#39;s the theory anyway: when everything is taking twice as long as you thought, don&#39;t go looking for hours of work to put between you and the next thing, just find a better way to solve the immediate problem. You spec the talent tree you&#39;re working with the XP you have and you play your class, you don&#39;t try to be All Things At Once.&lt;br /&gt;
&lt;br /&gt;
So it turns out Unity has a feature called Layer-Based Collision Detection that&#39;s actually more or less perfect for this. The tree branches go on one layer, the player goes on another, then we ask a question, is the player moving up?&lt;br /&gt;
&lt;div&gt;
&lt;pre&gt; &lt;code&gt;
void CheckForPassPlatform()
{
 if (!controller.isGrounded)
 {
  jumpThisPos = transform.position;
 
  if (jumpThisPos.y &amp;gt; jumpLastPos.y)
  {
   Debug.Log(&quot;ignoring branches&quot;);
   Physics.IgnoreLayerCollision(10, 13, true);
  }
  else
  {
   Debug.Log(&quot;hitting branches&quot;);
   Physics.IgnoreLayerCollision(10, 13, false);
  }  
  jumpLastPos = jumpThisPos;
 }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;
I probably don&#39;t need that isGrounded really. Like I said it&#39;s more or less perfect, but the less happens becuase of my hinged collider platforms. There are occasionally cases when the player is coming down from the apex of a jump that took them halfway through the platform above. The player won&#39;t hit the thing they are already in the middle of, but if the player is also moving sideways they will bump into the next piece of collider at the hinge. The player is heading down so the collision layers are reading each other, which we would want if the player were above the collider, but since the player is to the side, we don&#39;t want this.&lt;br /&gt;
&lt;br /&gt;
Well, I know there&#39;s an answer here, and I know it involves raycasting, so I&#39;ve been investigating that, but I find raycasting difficult to use. The ray is invisible, so you have to draw it using Debug.DrawRay, but Debug.DrawRay takes a different set of arguments than Phsyics.Raycast, so how do you know your debug line is really the same as your raycast line?&lt;br /&gt;
&lt;br /&gt;
I guess when the player is coming down from a jump, we raycast from the player&#39;s center to a point just beneath the player&#39;s feet. If there is a collision there, we allow the layers to collide, otherwise we don&#39;t. This should allow the player to pass through side collisions on the way down.&lt;br /&gt;
&lt;br /&gt;
I really hope I don&#39;t get any cool ideas like this for level 3.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/11/in-trees-in-weeds.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiejBy1wzhxoRHBJgMBnSirb5dZaWKsJf7l8hutaOveJ6RLsYzD3T7oVmPm4hifEINZQKhZdBaJ4In8iBy1BVMbi-RBCbpBOxuP6VDUvwA2ne5pTiBJLEgTAxCa9K6BBZbSITXcsaPaDPNA/s72-c/TREES.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-1813460545167284316</guid><pubDate>Wed, 06 Nov 2013 04:35:00 +0000</pubDate><atom:updated>2013-11-05T20:35:47.543-08:00</atom:updated><title>Detours</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhqtgO128ZCDUYKErs7WPZra-XESP7huV1C5p4I76XsfUOunDsEBAUgVSbowhZhK9WTFR8jaRySP3Vy6smiPT73B8KcZPPVIabGxQcUdEsG6wN70mFOfKWvuLAKEseWbqPILHAJLj4LpoY/s1600/detours.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;151&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhqtgO128ZCDUYKErs7WPZra-XESP7huV1C5p4I76XsfUOunDsEBAUgVSbowhZhK9WTFR8jaRySP3Vy6smiPT73B8KcZPPVIabGxQcUdEsG6wN70mFOfKWvuLAKEseWbqPILHAJLj4LpoY/s320/detours.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I knew I should get some work done over the weekend, but I couldn&#39;t bring myself to fire up the old platformer so, still slightly hungover from a marathon Path of Exile session, I set myself this question: what could I do in Unity to cobble together the basics of a 3/4-top-downish, click to move-or-kill-or-loot type game? I&#39;ve been daydreaming of various lo-fi recombinations of Zelda DNA for a long time, and a cold grey Sunday seemed like the proper time to take a swing at it.&lt;br /&gt;
&lt;br /&gt;
Predictably, I didn&#39;t get far enough to call the result a game, but it&#39;s certainly something that can be clicked around in, which you can do &lt;a href=&quot;http://chrisklepac.com/builds/benko/benko_web.html&quot;&gt;here&lt;/a&gt; if you so desire. A few notes follow on how it went down, what I learned and what might come after.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
I flipped my tile grid from the platformer on its side, and was able to neatly arrange some colored quads as crude terrain. The tile map code will allow me to paint big maps easily, if that becomes something I&#39;d want to do. A third person follow camera was as easy as creating a camera, positioning the view where I wanted it, and making that gameObject a child of the player. Snap!&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
The Diablo cursor that travels all over a 3d map in response to a 2d mouse position also turned out to be a lot easier than I anticipated, and doesn&#39;t even require a bunch of funky juggling of world and screen coords. All it takes is a raycast through the player follow camera. The conveniently provided Ignore Raycast Layer also saved me some trouble. The entire thing is two lines:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;
screenPos = Input.mousePosition;
mouseRay = this.camera.ScreenPointToRay(screenPos);
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
transform.LookAt... seriously? You can do this? I&#39;m going to try to pretend all that time I wasted on older projects doing Quaternion math just never happened.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Vector3.MoveTowards is also pleasingly simple. You don&#39;t unfortunately get any easing this way, and poking around in the math library always gives me a headache, so I eventually hacked in something I could live with: if the player is within 1 or 2 units of the destination, their speed is halved. This almost looks like a lerp if you kind of squint at it.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Some weapon experiments quickly led me to the rigidbody system. The idea of a Zel-diablo-like with real physics projectiles is intriguing, though I&#39;m not sure it will ultimately be worth doing. My first attempts featured arrows that tumbled like poorly winged footballs, which is kind of interesting on its own.. what about a game where you start out as a completely inept archer?&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
The main idea I wanted to bring to life here was a mental image of the player confronted by something like a rampaging bear, which would continue to approach as the player peppered it with arrows, but the arrows would remain sticking out of the bear. The end result looks more like a purple refrigerator, and the arrows tend not to get &quot;captured&quot; until they&#39;ve passed entirely through the target, but some of the idea made it through. When an arrow hits the purple thing, its OnCollisionEnter function grabs the arrow&#39;s rigidbody and sets it to kinematic, which disables forces, then sets the arrow&#39;s transform as a child of the enemy. Instant porcupine effect!&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
There are unlimited possibilities here, beyond &quot;bair-baiting simulator&quot;, and I hope to eventually make this into something more impressive, but I think it stands as a good example of what you can do by stumbling around in Unity for a few hours with a vague idea or two. Time to shelve it and return, slightly refreshed, to the primary project. &amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/11/detours.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhqtgO128ZCDUYKErs7WPZra-XESP7huV1C5p4I76XsfUOunDsEBAUgVSbowhZhK9WTFR8jaRySP3Vy6smiPT73B8KcZPPVIabGxQcUdEsG6wN70mFOfKWvuLAKEseWbqPILHAJLj4LpoY/s72-c/detours.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-3423957017858546383</guid><pubDate>Sun, 13 Oct 2013 18:29:00 +0000</pubDate><atom:updated>2013-10-13T11:32:47.993-07:00</atom:updated><title>The Hard Truths of Hardware</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP1fgqTT7qP1WiKHCsa1n97Qopi5OSGD7p_Lj5beXPcsyx3RhxRVsLybTYlnlDgiRDd3OaJtQu6H7R5aaWXn9fto5v-MaENpqzDu2H9B5ppN6SqDxJS3UIz1o-qqHQnAFwVGPle-hEukNl/s1600/SS854809.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP1fgqTT7qP1WiKHCsa1n97Qopi5OSGD7p_Lj5beXPcsyx3RhxRVsLybTYlnlDgiRDd3OaJtQu6H7R5aaWXn9fto5v-MaENpqzDu2H9B5ppN6SqDxJS3UIz1o-qqHQnAFwVGPle-hEukNl/s320/SS854809.JPG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Here, on this rocky outcropping, where starving lizard-birds circle above, we shall call an end to the mobile development branch of this project. The controls work well enough for what they are, and you can beat the first level, although the experience leaves a lot to be desired.&lt;br /&gt;
&lt;br /&gt;
Merging the touch controls into the platformer project was educational in a bunch of ways. &amp;nbsp;First I learned about preprocessor directives, which allowed me to maintain a single version of the project with the same scripts for all platforms. Unity has some cool custom options here, so I was able to create #if MOBILE to enable touch controls for any arbitrary device.&lt;br /&gt;
&lt;br /&gt;
I also found some ways to improve the existing code, for example when calculating movement I was using Input.GetAxis(“Horizontal”) in every expression, so it was getting called half a dozen times every update. I changed it to call that once at the top of the update, store it in a float, and use that float to do calculations for the rest of the tick. I’m willing to bet that on a modern machine this makes exactly zero difference, but it’s the principle of the thing.&lt;br /&gt;
&lt;br /&gt;
I did find that I had made a few fundamentally good decisions. In the character control script I get input in one place, then immediately abstract it into values like float “velocity” and bool “attackInProgress” and use those to actually do stuff. This made adding a new input scheme really easy because I only had to touch one area of the code to get those initial values right.&lt;br /&gt;
&lt;br /&gt;
The real education, though, was getting under the hood of what it really means to have two buttons in combination with a d-pad style arrow option. The first problem I had was that running (hold green button and arrow) wouldn&#39;t work, and I eventually saw that since I had configured both buttons as tap inputs, the game didn&#39;t know or care if the green button was being held down. The WebPlayer version reads keyboard keys with both GetButton and GetButtonDown, and has different responses to each, so I needed to expand the touch controls example script to handle both taps and holds for each button. I’ll paste the results at the bottom of this entry. &amp;nbsp;It took a lot of trial and error and still has some big gaps in functionality. This is apparently a harder problem than I originally thought.&lt;br /&gt;
&lt;br /&gt;
The problem is bigger than just input logic. For example, the run/jump: I found in testing that regardless of how well it worked, the actual gesture the run/jump requires (depressing both green and yellow simultaneously) is awkward at best, I found myself bringing my hand around the device to use forefinger and middle finger, which made my other hand harder to use and just felt wrong.&lt;br /&gt;
&lt;br /&gt;
The run/jump came about because, when messing with basic character movement in the WebPlayer version, I unconsciously knew that there’s nothing more natural on a keyboard than augmenting a letter key with a simultaneous shift key. We sometimes do it Multiple Times in a Sentence. Transpose that motion to a touch screen, and it’s suddenly far less natural. I finally understand how the original NES controller, as clunky as it may look now, was an engineering marvel, affording a wonderfully tactile responsiveness between tap and hold combinations on those two nubs of cheap plastic. Multiple multi-million-dollar franchises owe their existence to the joy that developers were able to wring from that dance of tap-hold, discrete-continuous, now this and that, now that and not this, now both at once, many times a second, and that’s just the player’s right thumb! But I digress.&lt;br /&gt;
&lt;br /&gt;
“Transpose” is an apt word, “translate” also has some truth to it. A flat surface is not a controller, and any control scheme change involves reaching across a conceptual gap, trying to say something that’s not there to say, forgetting how many stairs there are and coming down hard on the landing.&lt;br /&gt;
&lt;br /&gt;
The decision of how far to try and take this was made for me, thank goodness, by a hardware limitation. My pokey old smartphone can only handle two simultaneous touch inputs. That means that if you are running, you can’t jump. This breaks the run/jump, but like I said, executing it isn&#39;t much fun in the first place. When I hit that wall, I stepped back for a better look at the project. What was I going for here? This was originally and essentially still is a portfolio piece, playable on a web site, and adding an optional downloadable .apk was just an additional bit of frosting. You’d still need a 3rd party .apk installer to use it, and I don&#39;t really expect anyone to do so. It was more a proof of concept to say that I could do that work as well, and I think I&#39;ve delivered that. I have a little more knowledge and a few more ideas for new projects. I’m very interested in the idea of mobile indie games, and now that world doesn&#39;t seem quite so foreign or daunting. I’m happy I took the time, and happier still to be shutting that tangent down in order to wrap the main game up once and for all.&lt;br /&gt;
&lt;div&gt;
&lt;pre&gt;using UnityEngine;
using System.Collections;

public class touchControls : MonoBehaviour {
#if MOBILE
 
 //assign 128px textures in inspector
 public Texture leftArrowTex;
 public Texture rightArrowTex;
 public Texture greenButtonTex;
 public Texture yellowButtonTex;
 
 //consumable button state values
 public bool leftFlag
 {
  get{return left;}
 }
 public bool rightFlag
 {
  get{return right;}
 }
 public bool greenTapFlag
 {
  get{return greenTap;}
 }
 public bool greenHoldFlag
 {
  get{return greenHold;}
 }
 public bool yellowTapFlag
 {
  get{return yellowTap;}
 }
 public bool yellowHoldFlag
 {
  get{return yellowHold;}
 }
 private bool left;
 private bool right;
 private bool greenTap;
 private bool greenHold;
 private bool yellowTap;
 private bool yellowHold;
 
 private Rect[] Arrows;
 private Rect[] Buttons;
 private Rect leftArrow;
 private Rect rightArrow;
 private Rect greenButton;
 private Rect yellowButton;

 private float sw; //screen width
 private float sh; //screen height
 private float bu; //boxUnit, default box measurement
 private float au; //arrowUnit, default arrow measurement 
 private Vector3 touchPos; //touch input gives us this
 private Vector2 screenPos; //gui rects need this
 
 private string debugStr;
 private WafhPlayer playscr;
 private int tCount;
 
 void Start () {
  
  sw = Screen.width;
  sh = Screen.height;
  bu = 256;
  au = 128; 

  leftArrow = new Rect(0, sh-au, au, au);
  rightArrow = new Rect(au, sh-au, au, au);
  greenButton = new Rect(sw-(au*2), sh-au, au, au);  
  yellowButton = new Rect(sw-au, sh-au, au, au);
  
  Arrows = new Rect[]{leftArrow, rightArrow};
  Buttons = new Rect[]{greenButton, yellowButton};
    
  playscr = GameObject.FindWithTag(&quot;Player&quot;).GetComponent&lt;wafhplayer&gt;();
  
  debugStr = &quot;LEFT =&quot; + leftFlag + &quot;\nRIGHT =&quot; + rightFlag
   + &quot;\nGREENTAP = &quot; + greenTapFlag + &quot;\nGREENHOLD = &quot; + greenHoldFlag 
    + &quot;\nYELLOWTAP =&quot; + yellowTapFlag + &quot;\nYELLOWHOLD = &quot; + yellowHoldFlag
    +&quot;\nhaxis = &quot; + playscr.pHaxis + &quot;\nisRunning = &quot; + playscr.isRunning
    + &quot;\nTCOUNT = &quot; + tCount;

 }

 void Update () {
  tCount = Input.touchCount;
  HandleArrows();
  HandleButtons();
  debugStr =&quot; LEFT =&quot; + leftFlag + &quot;\nRIGHT =&quot; + rightFlag
   + &quot;\nGREENTAP = &quot; + greenTapFlag + &quot;\nGREENHOLD = &quot; + greenHoldFlag 
    + &quot;\nYELLOWTAP =&quot; + yellowTapFlag + &quot;\nYELLOWHOLD = &quot; + yellowHoldFlag
    +&quot;\nhaxis = &quot; + playscr.pHaxis + &quot;\nisRunning = &quot; + playscr.isRunning
    + &quot;\nTCOUNT = &quot; + tCount;
 }
 
 void OnGUI () {
  GUI.Box(new Rect(sw/2-(bu/2), 0, bu, bu), debugStr); 
  GUI.Box (leftArrow, leftArrowTex);
  GUI.Box (rightArrow, rightArrowTex);
  GUI.Box(greenButton, greenButtonTex);
  GUI.Box(yellowButton, yellowButtonTex);  
 }
 
 void HandleArrows()
 {
  if (Input.touchCount &amp;gt; 0)
  {
   foreach (Rect rect in Arrows)
   {
    foreach (Touch touch in Input.touches)
    {
     touchPos = touch.position;
     screenPos = new Vector2(touchPos.x, sh-touchPos.y);
     if(rect.Contains(screenPos))
     {
      if (rect == leftArrow)
      {
       if (touch.phase == TouchPhase.Ended)
       {
        left = false;
       }
       else
       {
        left = true;
       }
      }
      if (rect == rightArrow)
      {
       if (touch.phase == TouchPhase.Ended)
       {
        right = false;
       }
       else
       {
        right = true;
       }       
      }
     }
     else
     {
      if (ButtonlessTouch(screenPos))
      {
       if (rect == leftArrow)
       {
        left = false;
       } 
       if (rect == rightArrow)
       {
        right = false;
       } 
      }
     }
    }
   }
  }
  else //no touches recorded this update
  {
   left = false;
   right = false;
  }
 }
 void HandleButtons()
 {
  if (Input.touchCount &amp;gt; 0)
  {
   foreach (Rect rect in Buttons)
   {
    foreach (Touch touch in Input.touches)
    {
     touchPos = touch.position;
     screenPos = new Vector2(touchPos.x, sh-touchPos.y);
     if(rect.Contains(screenPos))
     {
      if (rect == greenButton)
      {
       if (touch.phase == TouchPhase.Ended)
       {
        greenHold = false;
       }
       else
       {
             
        greenHold = true;
        if (touch.phase != TouchPhase.Began)
        {
         greenTap = false;
        }
        else
        {
         greenTap = true;
        }
       }
       
      }
      if (rect == yellowButton)
      {
       if (touch.phase == TouchPhase.Ended)
       {
        yellowHold = false;
       }
       else
       {
        yellowHold = true;
        if (touch.phase == TouchPhase.Began)
        {
         yellowTap = true;
        }
        else
        {
         yellowTap = false;
        }
       }       
      }      
     }
     else
     {
      if (ArrowlessTouch(screenPos))
      {
       if (rect == greenButton)
       {
        greenTap = false;
        greenHold = false;
       }
      
       if (rect == yellowButton)
       {
        yellowTap = false;
        yellowHold = false;
       }
      }
     }
    }
   }
  }
  else //no touches recorded this update
  {
   greenTap = false;
   greenHold = false;
   yellowTap = false;
   yellowHold = false;
  }
 }
 
 bool ButtonlessTouch(Vector2 screenPos)
 {
  bool buttonless = false;
  if  
    (!greenButton.Contains(screenPos) &amp;amp;&amp;amp;
    !yellowButton.Contains(screenPos))
  {
   buttonless = true;
  }
  return buttonless;   
 }
 
 bool ArrowlessTouch(Vector2 screenPos)
 {
  bool arrowless = false;
  if
   (!leftArrow.Contains(screenPos) &amp;amp;&amp;amp;
    !rightArrow.Contains(screenPos))
  {
   arrowless = true;
  }
  return arrowless;
 }
 
 
 
#endif
}



&lt;/wafhplayer&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/10/the-hard-truths-of-hardware.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP1fgqTT7qP1WiKHCsa1n97Qopi5OSGD7p_Lj5beXPcsyx3RhxRVsLybTYlnlDgiRDd3OaJtQu6H7R5aaWXn9fto5v-MaENpqzDu2H9B5ppN6SqDxJS3UIz1o-qqHQnAFwVGPle-hEukNl/s72-c/SS854809.JPG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-3577683198406398335</guid><pubDate>Sat, 05 Oct 2013 21:07:00 +0000</pubDate><atom:updated>2013-10-05T14:07:23.837-07:00</atom:updated><title>Not So Fast Buddy</title><description>After posting my touch controls script I was fooling around with it and of course found a huge bug. If you&#39;re holding down one of the arrows, and then tap one of the colored buttons, the cube will stop moving. The culpit was the code that set the arrow flags false on touches received outside those flags. This was required to support the fairly standard use case of dragging a finger from one arrow to the other; the first arrow needed to flip off in that case.&lt;br /&gt;
&lt;br /&gt;
The solution I went with was to do another layer of checking on any touch outide the rect we&#39;re currently looking at, and if this other touch is on a button, we can ignore it. This way we&#39;ll turn arrows off both if you drag a finger into the other arrow, and if you drag that finger out of the arrow area entirely. The only downside here is that a random tap, near the top of the screen for instance, will make both arrows false. But, I might reasonably ask, what were you doing tapping up there anyway, that&#39;s not where the controls are... the menu UI elements are already responding OK to touch, so hopefully this won&#39;t break those. I guess we&#39;ll find out. Anyway, the extra code is here:&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;bool OrphanTouch(Vector2 screenPos)&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;{&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;bool isOrphan = false;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;if&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&amp;nbsp;//don&#39;t count the other arrows for this&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt; &amp;nbsp;(!greenButton.Contains(screenPos) &amp;amp;&amp;amp;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt; &amp;nbsp;!yellowButton.Contains(screenPos))&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;{&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;isOrphan = true;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;}&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;return isOrphan; &lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;}&lt;/div&gt;
&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/10/not-so-fast-buddy.html</link><author>noreply@blogger.com (Chris)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-7384640113819966068</guid><pubDate>Thu, 03 Oct 2013 03:30:00 +0000</pubDate><atom:updated>2013-10-02T20:39:37.857-07:00</atom:updated><title>A Touching Story...</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvNmAnwda2UpU1A5B0OPwgCMF0E7GG9vlyfhdwelDd3GNKjyWOEIyEVNMjBF_ZNdfpMsRpEbwbeCc5QZTVmo49dkCyteXgLqglXIxLy0tK-K7uHXTSyCtkPkBA7Fw2_QoJzK9lmmRidzB5/s1600/touch.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;199&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvNmAnwda2UpU1A5B0OPwgCMF0E7GG9vlyfhdwelDd3GNKjyWOEIyEVNMjBF_ZNdfpMsRpEbwbeCc5QZTVmo49dkCyteXgLqglXIxLy0tK-K7uHXTSyCtkPkBA7Fw2_QoJzK9lmmRidzB5/s320/touch.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I eventually had to throw away my feverish rant about Cookie Clicker, as I felt it contained spoilers for both the video game industry and life Itself, so instead here&#39;s what I&#39;ve been up to Unity-wise these past weeks.&lt;br /&gt;
&lt;br /&gt;
With a few desultory mouse-clicks, I had ported my web-targeted 2d platformer to Android. Well, the appearance of it anyhow. It was still only set up to take keyboard input. No worries though, since the first step was such a breeze, implementing a simple set of onscreen controls should be a similar walk in the park, yes?&lt;br /&gt;
&lt;div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Well the first problem, when the touch input examples I copied didn&#39;t work, was that I was staring at a phone, one that wasn&#39;t responding to input, and I had no access to a debug console. That had to change first thing.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
I spent a good many hours trying to rig up live debugging with various IDEs, sdk versions, phone drivers, and even a third party Android phone Windows driver updater, which informed me that my phone&#39;s OS was &quot;not compatible with Windows 8 x64&quot; and since that&#39;s what they had at Fry&#39;s, even after I asked the guy to look in the back for any Windows 7 machines he might have overlooked, that&#39;s what we&#39;re rolling with.&lt;br /&gt;
&lt;br /&gt;
After a while Eclipse deigned to recognize my HTC Incredible, which I guess isn&#39;t all that incredible anymore, and I started hacking away at it. How could I set up a control scheme that would slot easily into the existing movement controls of the game I was already making? A quick check showed I was moving the player with Input.GetAxis(&quot;Horizontal&quot;) multiplied by some arbitrary speed value, so I was looking to replicate, with these two touchable arrows, a continuum between -1 and 1, which is what GetAxis(&quot;Horizontal&quot;) gives you.&lt;br /&gt;
&lt;br /&gt;
So I pictured a finely grained number line clamped at -1 and 1, and set about adding or subtracting tiny numbers to and from it, with lots of little special cases like snapping it to zero when you switch directions, and letting the value drift back toward zero when not being touched. I eventually had to start learning about touch phases, but that took a while to sink in.&lt;br /&gt;
&lt;br /&gt;
My first pass was full of very long functions full of if trees calling for specific global variables not mentioned elsewhere in the function, just a god awful mess, pure flailing.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Second pass was attempting to extend the Rect class as a custom UI object (lol why I dunno). This lead me to learn what Sealed means, and got a slightly better understanding of &quot;the Unity Way&quot;, which involves hanging scripts and components on GameObjects like baubles on a Xmas tree, so I was going about the whole thing backwards. The problem with this was that the Rects in which I was drawing the textures only existed as concepts, created by a few OnGUI.Box calls, nothing you could click on in the Inspector. The&amp;nbsp;Xmas&amp;nbsp;tree only gets put up at runtime, so anything you want to hang on it also has to be defined and described in script.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Eventually I had painted myself into a corner. I&#39;m finding as this goes on that one of the important skills to master (and boy can this ever be generalized) is understanding when you&#39;re at the end of a first draft and can, not set aside or abandon that work, but tape it up to the wall or throw it onto another monitor and refer to it when building your second draft, trying to incorporate its strengths while paring out its flaws. Iteration.&lt;br /&gt;
&lt;div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I started over and thought in bigger picture terms about what the thing was trying to do. I remembered one of the lessons from a videos I watched: when you&#39;re trying to perform a complicated operation, if you spend the right amount of time and effort figuring out what your individual functions should each be and do, the actual guts of any of them turn out to be not so complicated. Organization.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Unfortunately the third attempt quickly accumulated a bunch of variables and calculations that rightly should belong elsewhere, so eventually it had to be scrapped as well. I approached the fourth draft with a flinty-eyed stare. There would be four public bools, readable but not writeable by any and every class who cared to use them. Each bool would correspond to one UI button, and the bool would indicate whether right now, at this moment, that button is receiving something that we want to interpret as a touch. All this class does is sort through all the touches by phase and turn those bools on and off as needed. Here it is:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
using UnityEngine;
using System.Collections;

public class touchControls : MonoBehaviour {
 
 //assign 128px textures in inspector
 public Texture leftArrowTex;
 public Texture rightArrowTex;
 public Texture greenButtonTex;
 public Texture yellowButtonTex;
 
 //consumable button state values
 public bool leftFlag
 {
  get{return left;}
 }
 public bool rightFlag
 {
  get{return right;}
 }
 public bool greenFlag
 {
  get{return green;}
 }
 public bool yellowFlag
 {
  get{return yellow;}
 }
 private bool left;
 private bool right;
 private bool green;
 private bool yellow;
 
 private Rect[] Arrows;
 private Rect[] Buttons;
 private Rect leftArrow;
 private Rect rightArrow;
 private Rect greenButton;
 private Rect yellowButton;

 private float sw; //screen width
 private float sh; //screen height
 private float bu; //boxUnit, default box measurement
 private float au; //arrowUnit, default arrow measurement 
 private Vector3 touchPos; //touch input gives us this
 private Vector2 screenPos; //gui rects need this
 
 private string debugStr;

 void Start () {
  
  sw = Screen.width;
  sh = Screen.height;
  bu = 256;
  au = 128; 

  leftArrow = new Rect(0, sh-au, au, au);
  rightArrow = new Rect(au, sh-au, au, au);
  greenButton = new Rect(sw-(au*2), sh-au, au, au);  
  yellowButton = new Rect(sw-au, sh-au, au, au);
  
  Arrows = new Rect[]{leftArrow, rightArrow};
  Buttons = new Rect[]{greenButton, yellowButton};
   
  debugStr = &quot;LEFT =&quot; + leftFlag + &quot;\nRIGHT =&quot; + rightFlag
   + &quot;\nGREEN =&quot; + greenFlag + &quot;\nYELLOW =&quot; + yellowFlag;

 }

 void Update () {
  HandleArrows();
  HandleButtons();
  debugStr = &quot;LEFT =&quot; + leftFlag + &quot;\nRIGHT =&quot; + rightFlag
   + &quot;\nGREEN =&quot; + greenFlag + &quot;\nYELLOW =&quot; + yellowFlag;
 }
 void OnGUI () {
  GUI.Box(new Rect(sw/2-(bu/2), sh/2-(bu/2), bu, bu), debugStr); 
  GUI.Box (leftArrow, leftArrowTex);
  GUI.Box (rightArrow, rightArrowTex);
  GUI.Box(greenButton, greenButtonTex);
  GUI.Box(yellowButton, yellowButtonTex);  
 }
 void HandleArrows()
 {
  if (Input.touchCount &amp;gt; 0)
  {
   foreach (Rect rect in Arrows)
   {
    foreach (Touch touch in Input.touches)
    {
     touchPos = touch.position;
     screenPos = new Vector2(touchPos.x, sh-touchPos.y);
     if(rect.Contains(screenPos))
     {
      if (rect == leftArrow)
      {
       if (touch.phase == TouchPhase.Ended)
       {
        left = false;
       }
       else
       {
        left = true;
       }
      }
      if (rect == rightArrow)
      {
       if (touch.phase == TouchPhase.Ended)
       {
        right = false;
       }
       else
       {
        right = true;
       }       
      }
     }
     else //touches recorded outside this rect turn it off
     {
      if (rect == leftArrow)
      {
       left = false;
      }
      if (rect == rightArrow)
      {
       right = false;
      }
      
     }
    }
   }
  }
 }
 void HandleButtons()
 {
  if (Input.touchCount &amp;gt; 0)
  {
   foreach (Rect rect in Buttons)
   {
    foreach (Touch touch in Input.touches)
    {
     touchPos = touch.position;
     screenPos = new Vector2(touchPos.x, sh-touchPos.y);
     if(rect.Contains(screenPos))
     {
      if (rect == greenButton)
      {
       if (touch.phase == TouchPhase.Began)
       {
        green = true;
       }
       else
       {
        green = false;
       }
      }
      if (rect == yellowButton)
      {
       if (touch.phase == TouchPhase.Began)
       {
        yellow = true;
       }
       else
       {
        yellow = false;
       }       
      }      
     } 
    }
   }
  }  
 }
}

&lt;/code&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
the concept behind the two main sort of mirrored functions is that we want to record touches on the arrows if we are in any phase except TouchPhases.Ended, and we want to record touches on the buttons only if we are in TouchPhases.Began. This gives us the desired behavior where you can press and hold the arrows for continuous input, but the buttons must be tapped. 

&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
Here&#39;s the script on the cube in the middle of the screen that moves and shoots smaller cubes, as an example of how the flags are used. In both cases of course you&#39;d have to set up your assets in the inspector.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;
using UnityEngine;
using System.Collections;

public class moveCube : MonoBehaviour {
 
 private touchControls hud;
 private Vector3 cubeUpdate;
 private int vroom;
 public GameObject zapFab;
 private GameObject zapClone;
 private float nextCubex;
 private float recoilTimer;
 private float recoilCap;
 
 private float haxis;  //horizontal axis buckent
 private float haxunit; //unit for altering teh bucketprivate bool justShotFlag;
 
 
 // Use this for initialization
 void Start () {
  hud = GameObject.Find(&quot;Main Camera&quot;).GetComponent&amp;lt;touchControls&amp;gt;&lt;touchcontrols&gt;();
  vroom = 50;
  //justShotFlag = false;
  haxunit = 0.1f;
 }
 
 // Update is called once per frame
 void Update () {
  haxis = Round(haxis);

  if (hud.greenFlag){
    OnGreen();
  }
  
  if (hud.leftFlag)
  {
    if (haxis &amp;gt; 0){ haxis = 0; }
    haxis -= haxunit;   
  }
  if (hud.rightFlag)
  {
    if (haxis &amp;lt; 0){ haxis = 0; }
    haxis += haxunit;   
  }
  if (!hud.rightFlag &amp;amp;&amp;amp; ! hud.leftFlag){
    if (haxis &amp;gt; 0) {haxis -= (haxunit);}
    if (haxis &amp;lt; 0) {haxis += (haxunit);}
  }
  //clamp haxis at ends
  if (haxis &amp;gt; 1.0f){haxis = 1.0f;}
  if (haxis &amp;lt; -1.0f){haxis = -1.0f;}
  //clamp haxis to zero at very close values to avoid stutters
  if (haxis &amp;gt; 0 &amp;amp;&amp;amp; haxis &amp;lt; 0.001f){ haxis = 0;}
  if (haxis &amp;lt; 0 &amp;amp;&amp;amp; haxis &amp;gt; -0.001f){ haxis = 0;}  
  //move cube
  nextCubex = transform.position.x + haxis*vroom;
  if (nextCubex &amp;gt; 486.0f){ nextCubex = 486.0f;}
  if (nextCubex &amp;lt; -486.0f){ nextCubex = -486.0f;}
  cubeUpdate = new Vector3(nextCubex, transform.position.y, transform.position.z);
  transform.position = cubeUpdate;  
 }
 void OnGreen()
 {
  zapClone = Instantiate(zapFab, transform.position, transform.rotation) as GameObject;
 }
 //helpas
 float Round(float num)
 {
  float rum;
  rum = Mathf.Round(num * 1000)/1000;
  return rum;
 }
}

&lt;/touchcontrols&gt;&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;
OK, now we have a crude sort of Zaxxon clone, with no enemies, but we&#39;ve demonstrated the touch input setup, so we&#39;re ready to integrate this with our platformer, right? We can set this demo aside, correct? Damn, I forgot how fun Zaxxon is... even without any bad guys it&#39;s kind of awesome... I mean how long would it take, really, to plug in a few columns that explode when you shoot them, maybe an enemy or two... in fact, I think I may have some innovative ideas that could advance the whole Zaxxon-like genre... I could always jump back to the platformer any time... This is like that part in the novel writing process where you start getting all these amazing ideas for other novels. Discpline, they say, is its own reward. We&#39;ll see.&amp;nbsp;&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/10/a-touching-story.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvNmAnwda2UpU1A5B0OPwgCMF0E7GG9vlyfhdwelDd3GNKjyWOEIyEVNMjBF_ZNdfpMsRpEbwbeCc5QZTVmo49dkCyteXgLqglXIxLy0tK-K7uHXTSyCtkPkBA7Fw2_QoJzK9lmmRidzB5/s72-c/touch.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-1877406554085128667</guid><pubDate>Mon, 02 Sep 2013 20:35:00 +0000</pubDate><atom:updated>2013-09-02T13:37:13.904-07:00</atom:updated><title>Scaly</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPH-sfKNiO7oj56Wmsh3qPiFaUk16imNUEswkJdIK8Kl4GpjSGL7QNV495saZ4TJ_55JDbaSoBkyyzXM6tfPm7sWu7hO-WY10uNJp_lHLJqZE4WZyVC15lg-W6Zsksp9jcS5MBrOktO6ww/s1600/scaly.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPH-sfKNiO7oj56Wmsh3qPiFaUk16imNUEswkJdIK8Kl4GpjSGL7QNV495saZ4TJ_55JDbaSoBkyyzXM6tfPm7sWu7hO-WY10uNJp_lHLJqZE4WZyVC15lg-W6Zsksp9jcS5MBrOktO6ww/s1600/scaly.jpg&quot; height=&quot;79&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Not much to report lately, I&#39;ve been down in the weeds working on making all the UI elements scale and stretch properly for all possible aspect ratios, and it&#39;s been an utter pain, as I expected it would be. Nothing against Unity here, this is just one of those less-than-fun tasks that didn&#39;t seem necessary a while ago. Now that I plan to &quot;support&quot; mobile platforms, at least in a really basic way, this is just part of that process.&lt;br /&gt;
&lt;br /&gt;
The work is not brain-busting so much as tedious. I pondered various methods and here&#39;s what I came up with: pick one square UI element (the player head on the left side). Calculate what the length of one side of it would be in relation to the height of the screen in your standard aspect ratio, the one you already like the look of. In my case this would be a 64 pixel square on a 600 pixel high screen, giving me a basic value for &quot;headLength&quot; of screenHeight * 0.106. I then use that headLength variable to lay out all the rest of the elements. The health bars are maybe a quarter of a headLength wide, separated by a gap of 1/16 headLength, etc. For the bus passes I start at the value of screenWidth and walk backwards across the screen to the left by various fractions of a headLength to get things placed and spaced properly. This way, when the game is switched to a 5:4 or 16:10 aspect ratio, the game gets the current screen width, calculates how long our new solomonic foot of headLength will be, then draws everything in proportion onscreen. You end up with versions of the UI that look a little different each time, but are close enough that the basic layout works across platforms. I have no idea whether this is a standard kind of method or a wacky backwards solution, and most of the Unity UI guides I have read are somewhat beyond my grasp so I just went with something that worked for this project, as I tend to do.&lt;br /&gt;
&lt;br /&gt;
It is, if nothing else, a step up from the previous solution that I though was so elegant: arrange the UI objects in the scene view, far away from everything else, then create a UI-only camera that views them and layers that view on top of the game. This is still a cool strategy (I saw a talk by the Snuggletruck guys where they described something like this) but I&#39;ll be damned if I can get it to scale the way I need it to. In my version, the UI elements don&#39;t exist at all in scene view, they are only a collection of textures in a folder that are assembled and brought to life every tick with an OnGUI call.&lt;br /&gt;
&lt;br /&gt;
That &quot;every tick&quot; is a big warning flag of course, and I&#39;ve heard various rumblings about OnGUI being &quot;expensive&quot;, in the sense that it&#39;s going to murder my framerate. It&#39;s true already that my mobile version is significantly slower than my webplayer version, but at this point I am at least savvy enough to beware that specter on the battlements pointing a bony finger at me and whispering &quot;optimize prematurely!&quot; That guy can go soak his head, he&#39;s not my real dad.&lt;br /&gt;
&lt;br /&gt;</description><link>http://ballistictelegram.blogspot.com/2013/09/scaly.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPH-sfKNiO7oj56Wmsh3qPiFaUk16imNUEswkJdIK8Kl4GpjSGL7QNV495saZ4TJ_55JDbaSoBkyyzXM6tfPm7sWu7hO-WY10uNJp_lHLJqZE4WZyVC15lg-W6Zsksp9jcS5MBrOktO6ww/s72-c/scaly.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-837483495664131666</guid><pubDate>Wed, 21 Aug 2013 01:47:00 +0000</pubDate><atom:updated>2013-08-20T19:07:21.499-07:00</atom:updated><title>Square 1.2</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhst3T6XsgUe64qFsOnZRn2HggrU5jDOGX6w2noAdwfyRzHX8rqv-_P3fSoSYs_pyED-k6XMnjLJvAELVa42ULC4Qr-G4HKotp-yt35w_Vcucq-qIjJ4TWMbXfdfkwIzSLyMRpFDx5gwqQJ/s1600/SS854766.JPG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhst3T6XsgUe64qFsOnZRn2HggrU5jDOGX6w2noAdwfyRzHX8rqv-_P3fSoSYs_pyED-k6XMnjLJvAELVa42ULC4Qr-G4HKotp-yt35w_Vcucq-qIjJ4TWMbXfdfkwIzSLyMRpFDx5gwqQJ/s320/SS854766.JPG&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
As my old PC lay dying, I had the foresight to upload my Unity project files to a server where I could retrieve them later. A month or two passed.&lt;br /&gt;
&lt;br /&gt;
I got a new PC, downloaded and installed Unity, downloaded my game project from the server where I&#39;d stored it, and fired the whole thing up. I had lost all references.&lt;br /&gt;
&lt;br /&gt;
All references. Materials no longer referred to textures. Prefabs for players and props no longer referred to the scripts that gave them motion and logic (&quot;empty monobehavior&quot; said the inspector). Core game objects no longer displayed UI, or tracked time, or responded to events. Everything was bright pink. Not one stone remained atop another.&lt;br /&gt;
&lt;br /&gt;
If there was a way to protect against this, I still don&#39;t know what it was. The good news is that all my animations and calculations and pixel-nudges, all that information was still there. Not a single asset was lost. All the transfer did was sever every strand of the delicate spiderweb that held it all together.&lt;br /&gt;
&lt;br /&gt;
Thoughts I had, working on Humpty Dumpty:&lt;br /&gt;
&lt;br /&gt;
&quot;I wonder if my increased ability to resolve common errors is less true learning and more memories of a series of brute force tricks used against the problem previously. It&#39;s not really like I understand computers a whole lot better than I used to.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;Once again I have lost work due to making changes while the game is running, and forgetting that when the game stops running all those changes go away. You would think I would remember that after a while. Unity&#39;s greatest prototyping asset is my Achilles heel.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;It&#39;s continuously weird how computer processes can echo the natural world, at least in the way things decay. Somewhere in this process something went wrong with some sprite sheets (import settings? Still don&#39;t know) and now there are blotches of discoloration on the player sprites, looking for all the world as though I&#39;d moved them in cardboard boxes which got rained on.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;I wonder there&#39;s a difference between true learning and memories of a series of brute force tricks used against the problem previously.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;I wonder (and this is uncharitable and tinfoil-hatty I admit) if&amp;nbsp;all these broken references are an unnecessary, deliberate feature, supported in order to drive users into the arms of Unity&#39;s for-pay version control system. Like the performance monitor, it&#39;s one of those things you won&#39;t notice isn&#39;t free until you&#39;re invested to a point where it&#39;s painful to live without.&quot; (Or maybe, says a contrary voice, you lack the skills to control the integrity of your own file systems! This is the curse of the semi-educated techie: we never know for sure whether it&#39;s all our own fault, but by some definition it almost always is).&lt;br /&gt;
&lt;br /&gt;
&quot;I should just chuck this and go make some simple games that use squares and circles or whatever and then I wouldn&#39;t have these kinds of problems.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;Perhaps this pain will finally make real to me those abstract concepts of OOP hygiene like encapsulation and abstraction. The player holds a reference to the hud for updating the score. Pick ups hold a reference to the scene manager object so they can flips the scene state when enough are collected. I know that somehow this is all wrong, and the way I know is that I can&#39;t get anything back online in isolation. It&#39;s like a beach-ball sized knot of Christmas tree lights with a few bad bulbs.&quot;&lt;br /&gt;
&lt;br /&gt;
&quot;Huh, the Unity folks released their Android support features for free? That shit was four hundred dollars! I wonder what it would take to put this thing on my phone?&quot;&lt;br /&gt;
&lt;br /&gt;
Not much, as it turns out. Sure, there are no onscreen controls so nothing actually works, but just the fact of this game I&#39;ve been fooling around with suddenly being available&lt;i&gt; in my hand&lt;/i&gt; is enough to give this project a much-needed adrenaline boost. This is actually kind of cool, and I applaud Unity for making it so easy. Still a little touchy about the broken references, but let&#39;s just move past it.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/08/square-12.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhst3T6XsgUe64qFsOnZRn2HggrU5jDOGX6w2noAdwfyRzHX8rqv-_P3fSoSYs_pyED-k6XMnjLJvAELVa42ULC4Qr-G4HKotp-yt35w_Vcucq-qIjJ4TWMbXfdfkwIzSLyMRpFDx5gwqQJ/s72-c/SS854766.JPG" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-5886423416266266416</guid><pubDate>Sun, 30 Jun 2013 18:56:00 +0000</pubDate><atom:updated>2013-06-30T11:56:24.175-07:00</atom:updated><title>Crash</title><description>The great borrowed warhorse desktop PC first slowed, then froze, then&amp;nbsp;constantly&amp;nbsp;needed a restart, then failed to start at all. Could be anything from a bad C drive to the CPU finally failing under the first real heat of the year.&lt;br /&gt;
&lt;br /&gt;
I&#39;m back on my trusty laptop, and Unity project progress will have to hang until I can get a decent replacement. I was in the middle of saving for something else so I&#39;m not inclined to rush down to Fry&#39;s and take care of the problem immediately.&lt;br /&gt;
&lt;br /&gt;
I&#39;ll continue to post here about other projects in the meantime, I&#39;m sure I&#39;ll keep something going.&lt;br /&gt;
&lt;br /&gt;</description><link>http://ballistictelegram.blogspot.com/2013/06/crash.html</link><author>noreply@blogger.com (Chris)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-6496863557101493308</guid><pubDate>Sun, 09 Jun 2013 22:53:00 +0000</pubDate><atom:updated>2013-06-09T15:54:32.055-07:00</atom:updated><title>One Thing Leads To Another</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjywkYFBOXv41I5d2Oe0Qj_f1BENw0Kk0CAipMrH9tzymFNLEku8pnPaSXWmWbLl7fuj4hyi1-woS6NXcMl8c0Uk7K3OFudJ1cLgUah39m2hx2S2ORWteLRz9KVW6Nsj7W4Q08WfsVYYpIc/s1600/waves.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;201&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjywkYFBOXv41I5d2Oe0Qj_f1BENw0Kk0CAipMrH9tzymFNLEku8pnPaSXWmWbLl7fuj4hyi1-woS6NXcMl8c0Uk7K3OFudJ1cLgUah39m2hx2S2ORWteLRz9KVW6Nsj7W4Q08WfsVYYpIc/s320/waves.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I&#39;ve managed to completely avoid my backlog for a couple of weeks, due to some combination of&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;60 hr work weeks&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Dark Souls&lt;/li&gt;
&lt;li&gt;Arrested Development&lt;/li&gt;
&lt;li&gt;making Counter-Strike maps&lt;/li&gt;
&lt;li&gt;working on music&lt;/li&gt;
&lt;li&gt;teaching myself to use Twine&lt;/li&gt;
&lt;li&gt;helping a friend with a screenplay&lt;/li&gt;
&lt;li&gt;&quot;social life&quot;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
and whatever sleep I could fit in there. Today I made myself sit down and crank out some tasks, and I ended up wrapping the sprint, plus something interesting happened.&lt;br /&gt;
&lt;br /&gt;
I had a long running note on my list that the player was too robust, too hard to kill. One easy improvement was to drop the number of lives from 4 to 3, but that didn&#39;t really do it. I had set the player up with a sort of health bar system, and no enemy was likely to bump into a player more than once, so you had to kind of deliberately let enemies hit you in order to even test the health system. It looked like one of those tasks I might have to shrug at, and compensate by making the game harder in later levels.&lt;br /&gt;
&lt;br /&gt;
At the same time I was finally getting around to drawing three different bullet types for the three playable characters. The bullet, as I may have mentioned, was a total freebie, all I did was draw a very small texture on it and then I scale the object up as it moves, bounce it off things, and it looks moderately OK, at least in context with the other graphics.&lt;br /&gt;
&lt;br /&gt;
When I had plugged these in and was messing around in-game to see how they looked (I eventually ended up darkening the background tile spritesheet so they would stand out more), I was brought uneasily back to another design problem from earlier in the project: I had this sort of neat feature of sound-wave like bullets bouncing off things and each other, but apart from the fun visual you get when you spam a bunch of these, there&#39;s not really any point to it, and the player can just wander around the map spewing these cones of death that obliterate any enemy in sight. I had turned over the idea of limiting the player&#39;s shot frequency or introducing some kind of &quot;energy&quot; mechanic that shots would deplete, but that all felt pretty half-assed and I was loathe to go there.&lt;br /&gt;
&lt;br /&gt;
Now, these two problems came together in my mind and I impulsively made two changes: I added the player bullet to the list of things that would damage the player, and I made it so that the player would lose their weapon when damaged, rather than when killed.&lt;br /&gt;
&lt;br /&gt;
Suddenly, I had a different game. The character could still greet every threat with a massive fusillade of sound waves, but when those waves bounced back the player could get hit, which would remove their weapon. The player can pick up another weapon, but that means finding the right platform and making it there without being touched by an enemy, and doing so will eat up precious time ... suddenly there is some gameplay where there wasn&#39;t any before. It&#39;s not the most compelling experience in the world, sure, but now there&#39;s something to do, there are risks, there are potential strategies even.&lt;br /&gt;
&lt;br /&gt;
There are two things that I intend to take away from this:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;You don&#39;t have to solve every problem right now. If I had forced my way to a solution to the &quot;player too robust&quot; issue earlier, I might not have had the opportunity to try out this new mechanic. Because I trusted I&#39;d be able to improve it eventually, and kept my mind open, I was able to recognize a solution when it presented itself&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;You do have to keep all the various aspects of your project in mind, as much of the time as you can. This &quot;problems solving each other&quot; thing only happens when you are simultaneously down in the weeds and looking around at the bigger picture. It&#39;s easy to put blinders on and just chip away at a single feature until its finished, but it might make more sense, and produce better results, to see all features as co-dependent, and allow changes in one to suggest possible refinements to any or all of the others.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/06/one-thing-leads-to-another.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjywkYFBOXv41I5d2Oe0Qj_f1BENw0Kk0CAipMrH9tzymFNLEku8pnPaSXWmWbLl7fuj4hyi1-woS6NXcMl8c0Uk7K3OFudJ1cLgUah39m2hx2S2ORWteLRz9KVW6Nsj7W4Q08WfsVYYpIc/s72-c/waves.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-8524895162055849800</guid><pubDate>Mon, 27 May 2013 21:33:00 +0000</pubDate><atom:updated>2013-05-27T14:33:07.913-07:00</atom:updated><title>Lerps of Faith</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1STPY8MKuDtRTn77am4oJR_pn8hLXU7_cPg55zjNkcKGcxiQxG7MnIC-MftMftwL5AZ6az62enp3YEkSVTYYDRukVvWNYwA6Y2di4FFarKOIOHx-KUZQEJoVUB5Ge60LbVWM0SOrX-YHv/s1600/boxx.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;183&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1STPY8MKuDtRTn77am4oJR_pn8hLXU7_cPg55zjNkcKGcxiQxG7MnIC-MftMftwL5AZ6az62enp3YEkSVTYYDRukVvWNYwA6Y2di4FFarKOIOHx-KUZQEJoVUB5Ge60LbVWM0SOrX-YHv/s320/boxx.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I&#39;ve been stuck in a test level for weeks - weeks! I finally got something together that I&#39;m willing to live with, but I still don&#39;t like it much. The simple-sounding problem was that I needed, in various places, to move an object from point A to point B, in some cases speeding up as it leaves A, in other cases slowing down as it approaches B. Thank Christ I didn&#39;t need both at the same time or I&#39;d still be working on it.&lt;br /&gt;
&lt;br /&gt;
Several game development environments support this sort of thing natively with easing functions, but Unity is apparently not among them. Seems like an odd thing to leave out, but the Unity philosophy seems to be that if people want something badly enough, some user will eventually code it up and offer it to everyone else, possibly for a profit, and for this use case one need look no further than&lt;b&gt; &lt;a href=&quot;http://itween.pixelplacement.com/index.php&quot;&gt;iTween&lt;/a&gt;,&lt;/b&gt; or if one&#39;s pockets are empty one could conceivably go to the community and base a solution on something like &lt;b&gt;&lt;a href=&quot;http://wiki.unity3d.com/index.php?title=Mathfx&quot;&gt;MathFx&lt;/a&gt;.&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Granted, there&#39;s also the option of hooking my objects up to Unity&#39;s animation system, but that felt like using a bazooka on a mosquito, and I&#39;m not sure the kind of easing I want is easy to get to. I had a hunch that I could probably get close enough to what I needed without anything so complex. Turns out I was sort of right, the Lerp function took care of me on the slowing down side, but the speeding up side took a little more head-scratching. Below is what I came up with, you&#39;d attach it to a cube or whatever and then flip the bool to switch between modes.&lt;br /&gt;
&lt;br /&gt;
This was one of those weird little bottleneck problems that is pretty unimportant in the grand scheme of things, but somehow had the power to bring my project to a grinding halt because it felt like it ought to be easy, and not being able to solve it had cascading negative effects on my confidence and motivation. This solution still looks a little weird, but no weirder than anything else in my project, so I&#39;m calling it good.&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;
using UnityEngine;&lt;br /&gt;
using System.Collections;&lt;br /&gt;
&lt;br /&gt;
public class test_smoothlerp : MonoBehaviour {&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;GameObject cube;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;Vector3 beginPoint;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;Vector3 endPoint;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;float startTime;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;float tripDist;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;float acc;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;bool speedUp = true;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;void Start () {&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;cube = GameObject.Find(&quot;Cube&quot;);&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;print (&quot;cube = &quot; + cube);&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;tripDist = 150.0f;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;beginPoint = cube.transform.position;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;print (&quot;beginPoint = &quot; + beginPoint);&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;endPoint = new Vector3(cube.transform.position.x + tripDist, cube.transform.position.y,&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;cube.transform.position.z);&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;print (&quot;endPoint = &quot; + endPoint);&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;acc = 0.01f;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;}&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;void Update () {&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;if(speedUp)&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;{&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;//speed up&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;if (acc &amp;lt; 1.0f)&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;{&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;    &lt;/span&gt;acc += 0.01f;&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;}&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;Vector3 nextPos = new Vector3(cube.transform.position.x + (tripDist*acc), 0.0f, 0.0f);&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;print (nextPos);&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;if (nextPos.x &amp;lt; endPoint.x)&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;{&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;    &lt;/span&gt;cube.transform.position = Vector3.Lerp(beginPoint, nextPos, Time.time);&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;}&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;else&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;{&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;    &lt;/span&gt;print (&quot;done&quot;);&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;}&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;}&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;else&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;{&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;//slow down&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;   &lt;/span&gt;cube.transform.position = Vector3.Lerp(cube.transform.position, endPoint, Time.time);&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt;  &lt;/span&gt;}&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;}&lt;br /&gt;
}&lt;/code&gt;</description><link>http://ballistictelegram.blogspot.com/2013/05/lerps-of-faith.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1STPY8MKuDtRTn77am4oJR_pn8hLXU7_cPg55zjNkcKGcxiQxG7MnIC-MftMftwL5AZ6az62enp3YEkSVTYYDRukVvWNYwA6Y2di4FFarKOIOHx-KUZQEJoVUB5Ge60LbVWM0SOrX-YHv/s72-c/boxx.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-8195926764166136994</guid><pubDate>Sun, 05 May 2013 19:46:00 +0000</pubDate><atom:updated>2013-05-05T13:05:13.453-07:00</atom:updated><title>Float Downstream</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjCeeUD3j3Ti6uDxKcgpWZgeFSlolU3VLsWVfLRq_-Al0FRyYq5a2I1RtMBtXggyZCNeE4J1lpvUsTiYuVSrcuknRRrRi0LNyZMwpznDY3rZ8-ePj5jFUY0umGtDfMsiI88YTYkyQ-wXbv/s1600/blognow.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;193&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjCeeUD3j3Ti6uDxKcgpWZgeFSlolU3VLsWVfLRq_-Al0FRyYq5a2I1RtMBtXggyZCNeE4J1lpvUsTiYuVSrcuknRRrRi0LNyZMwpznDY3rZ8-ePj5jFUY0umGtDfMsiI88YTYkyQ-wXbv/s320/blognow.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Fear - fear gripped my heart in its clammy fist. After making a new WebPlayer build to replace the somewhat outdated one on my &lt;b&gt;&lt;a href=&quot;http://www.chrisklepac.com/WebPlayer/game.html&quot;&gt;webpage&lt;/a&gt;&lt;/b&gt;, I fired it up and found that it didn&#39;t work. I realized I hadn&#39;t tried playing the game in an external build for quite some time. The game worked when played in the Unity Editor&#39;s play mode, and that should just be exactly the same as a built version, right? RIGHT??&lt;br /&gt;
&lt;br /&gt;
The game&#39;s main menu and&amp;nbsp;auxiliary&amp;nbsp;screens seemed to work fine, but when starting a new game, the player would be stuck at the character input screen, as no amount of clicking would actually select a character and launch the first level. This worked perfectly fine in the editor. The setup is, a UI script that lives on the Main Camera in this scene Instantiates all three of the player prefabs at positions based on the screen size, and hangs a scipt called UI_dummyPlayer on each of them. That script just has an OnMouseDown event that fires whenever someone clicks on the GameObject that the script lives on, loading the next level with the appropriate character as the player.&lt;br /&gt;
&lt;br /&gt;
A platform inconsistency is by nature a painful problem. I started looking for diagnostic tools. The first was the fact that you can right-click on your game in the WebPlayer and bring up a crude development console, pictured above, which in my case read&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;MethodAccessException: Attempt to access a private/protected method failed.&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
and helpfully pointed me to the very function causing the problem. The two potential culprits in there are the DontDestroyOnLoad call and my XML Serialization stuff... I started to get a sinking feeling. I quickly narrowed the problem down to these two lines:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;
seattle = City.Load(Path.Combine(Application.dataPath, &quot;City.xml&quot;));&lt;br /&gt;
seattle.Save(Path.Combine(Application.dataPath, &quot;seattle.xml&quot;));
&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;
and with some searching online I started to piece things together. Unity&#39;s WebPlayer has some built in security features that stop you from reaching into code that is stored in certain ways. I did a quick test on Path.Combine alone, as I hadn&#39;t used that before either, but the WebPlayer was fine with it. It was balking at my City.Load function, which I talked about in a previous post. It&#39;s another case of using some code I don&#39;t understand well, but I understand well enough that the WebPlayer is blocking me from access to the game&#39;s underlying file structure, which would most likely disallow things like&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;using (var stream = new FileStream(path, FileMode.Open))&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
and there are plenty of threads online about this and they all die out pretty quickly when a senior user steps in to say No, you can&#39;t do this in WebPlayer, it would in fact be a glaringly dangerous security flaw if you could.&lt;br /&gt;
&lt;br /&gt;
One post suggested a potential solution: if I stored my xml files in the same directory as my game on the website, I could use Unity&#39;s WWW functions to read that xml into a Unity object without touching the internal filesystem. The effect would be the same. Unfortunately, the example code for this employed XmlReader, where I was using XmlSerializer. Also, the process outlined involved junking all of my Xml code, and one of the other posts I read seemed pretty confident that I could still use the XmlSerializer class from within WebPlayer. If the FileStream was indeed the problem I might be able to keep most of my code.&lt;br /&gt;
&lt;br /&gt;
The breakthrough finally came as a result of &lt;b&gt;&lt;a href=&quot;http://answers.unity3d.com/questions/43778/accessing-arbitrary-files-within-a-web-build.html&quot;&gt;this post&lt;/a&gt;,&amp;nbsp;&lt;/b&gt;where the suggestion was to use XmlSerializer in connection with Resources.Load and something called a TextAsset to bypass use of the prohibited FileStream class. Other exotic tools in play include MemoryStream and Encoding.UTF8 ... we&#39;re somehow&amp;nbsp;simulating&amp;nbsp;a streaming file operation within the game&#39;s runtime memory, which I find baffling and kind of magical. We have replaced this:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;
var serializer = new XmlSerializer(typeof(City));&lt;br /&gt;
using (var stream = new FileStream(path, FileMode.Open))&lt;br /&gt;
{&lt;br /&gt;&amp;nbsp; return serializer.Deserialize(stream) as City;&lt;br /&gt;&amp;nbsp; stream.Close();&lt;br /&gt;
}&lt;/code&gt;&lt;br /&gt;
with this:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;
City loadedCity = null;&lt;br /&gt;
TextAsset myAsset = (TextAsset)Resources.Load(fileName, typeof(TextAsset));&lt;br /&gt;
byte[] bytes = Encoding.UTF8.GetBytes(myAsset.text);&lt;br /&gt;
using (MemoryStream stream = new MemoryStream(bytes))&lt;br /&gt;
{&lt;br /&gt;&amp;nbsp; loadedCity = (City)(new XmlSerializer(typeof(City))).Deserialize(stream);&lt;br /&gt;
}&lt;br /&gt;
return loadedCity;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
and lo and behold, the version built for the webplayer runs without error, characters are selectable, xml is deserializable, the sun is shining, and all is right with the world. I&#39;m taking the rest of the day off.&lt;br /&gt;
&lt;br /&gt;</description><link>http://ballistictelegram.blogspot.com/2013/05/float-downstream.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjCeeUD3j3Ti6uDxKcgpWZgeFSlolU3VLsWVfLRq_-Al0FRyYq5a2I1RtMBtXggyZCNeE4J1lpvUsTiYuVSrcuknRRrRi0LNyZMwpznDY3rZ8-ePj5jFUY0umGtDfMsiI88YTYkyQ-wXbv/s72-c/blognow.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-7505128784109242833</guid><pubDate>Fri, 03 May 2013 05:56:00 +0000</pubDate><atom:updated>2013-05-02T23:14:05.747-07:00</atom:updated><title>Orange You Happy Now</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOXKblxIw8jTjRBCnqsD43gHBwgDLhATkdZkkRqxHJ4wDxM5kFLuGXAgicP5b7unywYIY5hQJTzG8-NjSZPPYP0hVXEBBdKuxIRC79RINaTiIsKWNHpT7igUAIS09B-U-3WZbUTMjqhqJw/s1600/orange.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;223&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOXKblxIw8jTjRBCnqsD43gHBwgDLhATkdZkkRqxHJ4wDxM5kFLuGXAgicP5b7unywYIY5hQJTzG8-NjSZPPYP0hVXEBBdKuxIRC79RINaTiIsKWNHpT7igUAIS09B-U-3WZbUTMjqhqJw/s320/orange.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Everything was going fine until I hit the color orange.&lt;br /&gt;
&lt;br /&gt;
A little background here. In order to complete a level, the player needs to pick up five bus passes. Each bus pass has&amp;nbsp;associated&amp;nbsp;with it two particle effects, one a rising stream of particles for the at-rest state, as pictured above, and one a sort of blooming effect on the player when the thing is picked up. Both of these are the same color as the bus pass.&lt;br /&gt;
&lt;br /&gt;
The particle systems are attached to GameObjects which are then stored as prefabs. The bus pass itself is placed in the scene view with a pickup script on it, and I toggle which color this particular pass will be via the Inspector, as the list of bus pass colors is an enum within that script. When the game starts and the bus pass script runs, it looks at that variable to find out what color it ought to be, then switches to the appropriate frame of its&#39; RagePixel sprite. Each bus pass uses the same sprite, which just has five frames of the same image in different colors. &lt;br /&gt;
&lt;br /&gt;
I made the ambient particles first, and I just set the color of each directly in the particle system before making the prefab, so I ended up with five different ones like &quot;prefab_particle_buspass_orange&quot; and &quot;prefab_particle_buspass_green&quot;. Each prefab was assigned to its corresponding bus pass through an inspector variable, and each pass Instantiated that prefab during its Start function. Doing it that way once was, I felt, an acceptable level of laziness, but when it came time to do the bloom effect, I decided I had better just make one, &quot;prefab_particle_buspass_pickup_any&quot;, and then programatically change the color. After all, each bus pass knew its own color, so it should be easy enough to use a blank white material and just throw RGB colors at it at runtime.&lt;br /&gt;
&lt;br /&gt;
My first &quot;huh&quot; moment was getting the message &quot;UnityEngine.Color does not contain a definition for &#39;purple&#39;.&quot; I must be spoiled by Unity&#39;s easy access to so many MSDN libraries, but I figured a robust suite of crayola colors in the API would be more or less &lt;i&gt;de rigueur&lt;/i&gt;. Not the case this time, but no big deal. Since I&#39;m using C# and Color is a Struct like Vector3, I have to remember to replace&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;code&gt;Color purple(128.0f, 0.0f, 128.0f, 1.0f);&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
with&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;code&gt;Color purple = new Color(128.0f, 0.0f, 128.0f, 1.0f);&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
but again, all is well, and my purple looks purple in-game! Well, a little pink but whatever. Let&#39;s try a classic Cadmium Orange:&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;code&gt;Color orange = new Color(255.0f, 97.0f, 3.0f, 1.0f);&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
This comes out yellow.&lt;br /&gt;
Undeniably, unsquint-at-ably, absolutely damned yellow.&lt;br /&gt;
I thought for a while, and I spent maybe a bit too much time at Wikipedia&#39;s unusually fascinating &lt;b&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Orange_(colour)&quot;&gt;page for the color orange&lt;/a&gt;,&amp;nbsp;&lt;/b&gt;and I thought some more, and eventually I did the right thing, which is to resort to googling ever more plaintive rephrasings of one&#39;s problem and clicking on Unity Answers links until something gives.&lt;br /&gt;
&lt;br /&gt;
...No, I&#39;m kidding, the right thing to do is check the documentation, which in my case would have easily shown this, for example:&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;code&gt;Yellow. RGBA is (1, 0.92, 0.016, 1), but the color is nice to look at!&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Unity doesn&#39;t use RGBA values of 0-255, it uses normalized values of 0-1. Maybe that&#39;s a Scandanavian thing? I do like the consistency of it, Alpha is usually going to be 0-1 anyway... I tried to learn a bit more about this but I soon wandered into a &lt;b&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Color_normalization&quot;&gt;forbidding land of shadows&lt;/a&gt; &lt;/b&gt;and had to turn back. Not tryng to be incurious here, but your basic safety orange should not require post-graduate math.&lt;br /&gt;
&lt;br /&gt;
Unfortunately my &quot;what if this works&quot; first stab of just dividing each of the values by 255.0f gives us roughly&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;code&gt;Color orange = new Color(1.0f, 0.3803f, 0.5019f, 1.0f);&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Which renders onscreen as a sort of ill salmon color. Then suddenly, in the next tab, &lt;b&gt;&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/Color32-operator_Color.html&quot;&gt;a light shone upon me&lt;/a&gt;,&lt;/b&gt; for the good people of Unity had, by their own divine providence, thought to include a built-in function to do this exact thing.&lt;br /&gt;
&lt;br /&gt;
Moments later I had&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;code&gt;Color orange &amp;nbsp;= new Color32(255, 97, 3, 255);&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Which pops out blazing orange. I believe it was Ben Franklin who said, &lt;i&gt;&quot;I only try to understand something complicated until I figure out something simpler that will allow me to stop trying to understand the more complicated thing.&quot;&lt;/i&gt; As for the mystery of why my totally wrong purple was somehow sort of purple, I guess if you overflow the bounds of whatever kind of structure Color is, it just holds the max value, like a cup of coffee being filled by someone who has fallen asleep. (128, 0, 128, 1) is to Unity the same as (1, 0, 1, 1), which is Magenta, which looks sort of like purple, in a certain light. &lt;br /&gt;
&lt;br /&gt;</description><link>http://ballistictelegram.blogspot.com/2013/05/orange-you-happy-now.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOXKblxIw8jTjRBCnqsD43gHBwgDLhATkdZkkRqxHJ4wDxM5kFLuGXAgicP5b7unywYIY5hQJTzG8-NjSZPPYP0hVXEBBdKuxIRC79RINaTiIsKWNHpT7igUAIS09B-U-3WZbUTMjqhqJw/s72-c/orange.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-8741113370568418836</guid><pubDate>Sun, 14 Apr 2013 16:58:00 +0000</pubDate><atom:updated>2013-04-14T10:00:28.691-07:00</atom:updated><title>T</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXz00CRUG4Bkd-ZHB2Eodbc4AE09KfIOU-iuJ2lo1CvdcuUqNh2MSsUxWLBKsh2Cick6WzdVM4krmSXULVa0ktp43dTA3BIEiMW7bnIvkbuDvoI_ngQ-2gPlqrmIMeHW5MOS4jcP5Xbshf/s1600/T.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXz00CRUG4Bkd-ZHB2Eodbc4AE09KfIOU-iuJ2lo1CvdcuUqNh2MSsUxWLBKsh2Cick6WzdVM4krmSXULVa0ktp43dTA3BIEiMW7bnIvkbuDvoI_ngQ-2gPlqrmIMeHW5MOS4jcP5Xbshf/s1600/T.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
I wanted to get a little deeper into some methods for storing and retrieving information. With some research, I found that in CS terms I was thinking about data structures, so I hopped on my favorite internet book ordering behemoth and in a few days I had a copy of Ron Penton&#39;s &lt;i&gt;Data Structures for Game Programmers&lt;/i&gt;. It comes highly recommended from folks at work, some of whom are even thanked in the front pages, so I know I&#39;m on the right track with this one.&lt;br /&gt;
&lt;br /&gt;
One tiny concern was that the book&#39;s examples are in C++, while I&#39;m working with Unity in C#. Well, how big a deal could it be? I&#39;ll just re-write the example code and Bob&#39;s your uncle. It took me about a dozen pages to get in trouble.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Ron wants you to be sure and understand a few things up front. The first is big-O algorithm complexity analysis (which I&#39;ll tackle in another post .. someday) and the other is templates. These are functionally equivalent to C#&#39;s generics, right? No problem. The first example I tried to port over was a C++ function for adding either floats or ints together, depending on which was passed in. Well, it turns out in C#, things like this&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;code&gt;
public T &amp;nbsp;Sum&amp;lt;T&amp;gt;( T p1, &amp;nbsp;T p2)&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&amp;nbsp;{&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; T sum;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; temp = p1 + p2;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; return sum;&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&amp;nbsp;}&amp;nbsp;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
just straight up &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/c6cyy67b.aspx&quot;&gt;&lt;b&gt;don&#39;t work&lt;/b&gt;&lt;/a&gt;. Why not? further research led me to an &lt;a href=&quot;http://www.artima.com/intv/generics.html&quot;&gt;&lt;b&gt;interview&lt;/b&gt;&lt;/a&gt;&amp;nbsp;with lead C# architect Anders Hejlsberg, who I will quote on this very topic:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&quot;...in C# generics, we guarantee that any operation you do on a type parameter will succeed. C++ is the opposite. In C++, you can do anything you damn well please on a variable of a type parameter type. But then once you instantiate it, it may not work, and you&#39;ll get some cryptic error messages. For example, if you have a type parameter T, and variables x and y of type T, and you say x + y, well you had better have an operator+ defined for + of two Ts, or you&#39;ll get some cryptic error message. So in a sense, C++ templates are actually untyped, or loosely typed. Whereas C# generics are strongly typed.&quot;&lt;/blockquote&gt;
&lt;div&gt;
&lt;div&gt;
Undaunted (the book is big and wasn&#39;t cheap), I dove further online, turning up a set of C# files called the &lt;b&gt;&lt;a href=&quot;http://www.yoda.arachsys.com/csharp/miscutil/&quot;&gt;Miscellaneous Utility Library&lt;/a&gt;,&amp;nbsp;&lt;/b&gt;put together by a Google engineer named Jon Skeet. He and Marc Gravell (one of the Stack Overflow guys) put together &lt;a href=&quot;http://www.yoda.arachsys.com/csharp/genericoperators.html&quot;&gt;&lt;b&gt;this solution&lt;/b&gt;&lt;/a&gt;&amp;nbsp;for doing what they call &quot;maths&quot; on their side of the pond in the context of generic classes in C#. A small download and a using statement later, I was stuck again, as the Unity compiler didn&#39;t want to recognize the construction Operator&amp;lt;T&amp;gt;, for reasons that still hover slightly beyond my understanding.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
The MiscUtil pages reference &lt;a href=&quot;http://www.codeproject.com/Articles/8531/Using-generics-for-calculations&quot;&gt;&lt;b&gt;an article&lt;/b&gt;&lt;/a&gt; by one Rüdiger Klaehn, a &quot;freelance developer in the space industry&quot;, which sounds like the coolest job ever. He articulates the problem succinctly:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&quot;To constrain type parameters in C#/.NET, you specify interfaces that the type has to implement. The problem is that interfaces may not contain any static methods, and operator methods &lt;i&gt;are&lt;/i&gt; static methods.&quot;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Rüdiger presents two solutions, one of which I sort of understand and the other, which is far more performative, I don&#39;t understand at all. Fortunately I doubt I&#39;ll need to use so many numerical generics every frame to cause a slowdown in Unity (how many would that take I wonder) so I felt confident going with the first option.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I was mildly dumbstruck by the idea that you could just declare a function without a body like this:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;code&gt;public abstract T Add(T a, T b);&lt;/code&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;br /&gt;
as long as it&#39;s something abstract that you plan to override. I was even more nonplussed by the idea that I could use&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;code&gt;
namespace Int32&lt;br /&gt;
{&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;//custom calculation function&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
to just reach into the guts of how Unity deals with basic numbers, and just scribble in the margins as it were. That&#39;s really cool. Finally, when I got to the following, my brain broke:&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;code&gt;
public class CalcMethods&amp;lt;T&amp;gt; where T: new()&lt;br /&gt;
{&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;//a generic adding method + whatever else you need&lt;br /&gt;
}&lt;br /&gt;
&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;
I&#39;ve seen cases of putting code in a function definition, with what they call a lambda, and I suspect this is something similar, but it&#39;s still blowing my mind.&lt;br /&gt;
&lt;br /&gt;
In any event, I now have a function that takes a List of either floats or ints, and adds them together, and its easily extensible to whatever other kinds of numbers might come up, so I guess I&#39;m ready to continue. At this rate my side-quest through this data structures book will probably take about a decade. Better brew another pot.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/04/i-wanted-to-get-little-deeper-into-some.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXz00CRUG4Bkd-ZHB2Eodbc4AE09KfIOU-iuJ2lo1CvdcuUqNh2MSsUxWLBKsh2Cick6WzdVM4krmSXULVa0ktp43dTA3BIEiMW7bnIvkbuDvoI_ngQ-2gPlqrmIMeHW5MOS4jcP5Xbshf/s72-c/T.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-6665706078073169115</guid><pubDate>Sat, 13 Apr 2013 06:10:00 +0000</pubDate><atom:updated>2013-04-12T23:14:37.426-07:00</atom:updated><title>Eat Your Serial</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCX3MbbuENa1OTC4kbCCZEcFL7U7wA-9SMSmqvIsZVhyJ26Fcx-n9XdfXDjn6dce5_xoxYcB0hUVhMhg4Mr7TjV2tP3xJx-bga_17uklwm3cPv9zOq42ashBUAB5ccfrbAKjaC7RIVCiVr/s1600/bloggy.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCX3MbbuENa1OTC4kbCCZEcFL7U7wA-9SMSmqvIsZVhyJ26Fcx-n9XdfXDjn6dce5_xoxYcB0hUVhMhg4Mr7TjV2tP3xJx-bga_17uklwm3cPv9zOq42ashBUAB5ccfrbAKjaC7RIVCiVr/s320/bloggy.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Starting in on the process of making Level Two is a big wrenching moment, kind of like seeing my 2D game in perspective view. It becomes obvious how much is assumed, hardcoded, made of magic numbers. Wires must be pulled out. Questions as simple as &quot;where does the player start&quot; might have different numerical answers for each level. This is one of the most common questions on public game dev forums: &quot;I have a bunch of information I need to put in the game, like a long list of magic spells with all their damage and cooldown numbers, how do I represent it?&quot; In my case it&#39;s a fairly small list of things like the scene&#39;s loadable path, where the bus should pause to pick the player up, etc. but the principle is the same. The actual process I still don&#39;t really get, it&#39;s mostly cribbed from a few different tutorials, who have a few implementation bits in common but diverge otherwise.&lt;br /&gt;
&lt;br /&gt;
I used an XML file and the System.Xml.Serialization namespace. One of the funny things about Unity is that as often as not when I&#39;m leveraging its powers to do something I&#39;m actually just leveraging the standard MSDN libraries, which hey, System.Xml has more things you can do with an XML file than I&#39;ll ever want or need, so why reinvent the wheel? Like I said, the tutorials I checked all have their own take. There&#39;s always an XmlSerializer and a FileStream, but sometimes there&#39;s an XmlTextReader (which I didn&#39;t end up needing), sometimes an XmlNodeList is employed (didn&#39;t use that either), but the end result is what matters, and what I got works. Also kind of cool that I have to use stream.Close() because I&#39;m in one of the few corners of C# where memory isn&#39;t fully managed. It&#39;s like, retro vintage, man! The only annoying bit is that classes that are derived from UnityEngine.Object do not appear to be serializable, so if you need to pull something like a Vector3 you&#39;re stuck hacking in translation functions that will grab three float nodes and smoosh them together or something equally ugly. &lt;br /&gt;
&lt;br /&gt;
I&#39;m really grappling with the metadata syntax as well, and I&#39;m getting a mental picture of them as sort of magnets that allow you to attach properties in your program to external data that may change outside the scope of the program in ways you don&#39;t want to worry about. Probably not exact, but a good enough image for now.&lt;br /&gt;
&lt;br /&gt;
The sudden possibility of storing and using large amounts of easily tweaked data is of course leading me to all sorts of other ideas, but no, for now we will stick to the plan and the schedule. Last sprint wrapped, a few things got punted. Inevitable.&lt;br /&gt;
&lt;br /&gt;
I am starting to understand enough coding to sometimes sense that I am making a poor decision, although not enough to understand what the preferable course might be. My options / death / audio menu is a flying carpet made out of GuiLayout.BeginArea and transform.position.y, where I&#39;m doing a three-way switch in the Update() to decide which of three sets of (crudely laid out) text buttons to show. I&#39;ve always had trouble with &quot;layout languages&quot; like CSS, or basically anytime I have to think in interconnected scaling squares with various interdependent attributes ... makes my head hurt. I&#39;ve hacked it up enough to work, but I don&#39;t know, I might return to it.&lt;br /&gt;
&lt;br /&gt;
Mostly though it&#39;s been sweeping up stuff like the transitions from one level phase to another - making sure we don&#39;t let the player move and shoot when the level end animation is playing, stopping some bugs where bullets got huge and lived forever, trying slightly to improve the art, various little tweaks.&lt;br /&gt;
&lt;br /&gt;
It&#39;s going to be that way for a while, I&#39;m looking down the list and it&#39;s a lot of menu this and the skeleton dies wrong that, and move the camera when you do the other thing. It&#39;s the long bleak desert of the real, Neo, it&#39;s game development.&lt;br /&gt;
&lt;br /&gt;
No, once I get the structure set up to slip between levels I can plow through the art and design for the other neighborhoods and that will be a lot of fun. I just need to work a little faster...</description><link>http://ballistictelegram.blogspot.com/2013/04/eat-your-serial.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCX3MbbuENa1OTC4kbCCZEcFL7U7wA-9SMSmqvIsZVhyJ26Fcx-n9XdfXDjn6dce5_xoxYcB0hUVhMhg4Mr7TjV2tP3xJx-bga_17uklwm3cPv9zOq42ashBUAB5ccfrbAKjaC7RIVCiVr/s72-c/bloggy.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8980299626399938734.post-5041065374041334957</guid><pubDate>Tue, 26 Mar 2013 04:09:00 +0000</pubDate><atom:updated>2013-03-25T21:15:13.434-07:00</atom:updated><title>Back in the Triple Digits</title><description>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRlRDMJ9sr0lU-2zT1lHWH7TEAeyyeADNpQsNNBuI-TrkwLwrJRnV4Yb-yLM46ep520oetw0qHWpuTy2BJjyyCvdJ1C9LFGa91PKXJevgsrffsFgAGNAA4g41DRi31XGlJ7CTZ-SoeNa-C/s1600/pud.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;205&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRlRDMJ9sr0lU-2zT1lHWH7TEAeyyeADNpQsNNBuI-TrkwLwrJRnV4Yb-yLM46ep520oetw0qHWpuTy2BJjyyCvdJ1C9LFGa91PKXJevgsrffsFgAGNAA4g41DRi31XGlJ7CTZ-SoeNa-C/s320/pud.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Just truckin through my backlog, on my way to full vertical slice, and not that far off either. The shooting and jumping aren&#39;t exactly ... inspiring, but at least they work. I spent a lot of time fooling with gravity when I was making the floor and platform tiles, trying to find that right scale for the &quot;running jump&quot; mechanic. The way I wanted it to work, you could complete the level just walking, like if you didn&#39;t ever realize holding the fire button makes you go faster (I do change the animation, I tried to make it obvious), you should be able to get all five bus transfers just by jumping normally, although you&#39;d have to take some circuitous routes and it would be a pain in the ass. At the same time the running jump couldn&#39;t be too powerful, or since the platforms are so close together you get this queasy thing where the player just jumps toward the side of a platform, slides up, and ends up standing on top, which isn&#39;t very jump-like. I tried adding a RigidBody component for physics jumps in the hopes of getting something springier, but the intersection of the RigidBody and character controller was causing some Exorcist-like behavior so I bailed on that one. I&#39;m not thrilled with where it&#39;s at now, but I can live with it a while longer.&lt;br /&gt;
&lt;br /&gt;
Anything the player can touch is a primitive 32x32 cube displayng a frame (via a scaled and offset material) of one of two 256x256 tile sheets. The buildings and clouds are big textures (the clouds are 4096 wide) painted on scaled up quads, and scripted to move in parallax to the player. Most of the collision volumes are cubes the size of the tiles, but platforms have scaled down collision boxes, as do some of the objects. I&#39;m still using the old pickups but I&#39;ll probably make them tiles too eventually. The frame rate hangs reliably in the triple digits. This concludes, knock on wood, the technical implementation of the guts of the game. The rest is window dressing, oh and&amp;nbsp;&lt;i&gt;design&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
I re-learned some things about instantiating and destroyng prefabs. I spent a little too much time re-learning that a switch/case runs on break; statements and yes, they mean it, and any code you had in that function below the switch/case is not getting run, which is probably why it is not as effective as you thought it would be. At least, I think that&#39;s what happened ... regardless, it works now. I re-learned that your first level design instincts are often too big. This level is actually pretty small for a platformer now, but only because I wanted everything to feel closer together. In a sense all the objects really are kind of tetris-jammed together, but it&#39;s really the same set of elements from the larger draft of the level, just brought in tighter, I think I only deleted like two objects. It&#39;s odd that I got a lot of stuff right the first time but I got the scale totally wrong.&lt;br /&gt;
&lt;br /&gt;
The actual design of the level, given the constraints imposed by the grid, the jump tuning, and the five bus passes (plus a bus stop), was dirt simple. Figure out how to make a bus pass hard to get to, then do four variations. One is on a catwalk, another is tucked behind a roving skeleton, one is in a corner. None require run jumps but all are made easier by run jumps, run jump is frankly a little OP right now but it feels better than it did. I even started to polish a little by adding particle effects to the bus passes, but of course now I&#39;ll need particle effects for everything...&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicxlH-Fxzp9elCuFoua6vJCKBhg1PXuYKIaaJ1QidSlG55ZdaQ6QePIyNRnryimX9rvVNJgCQIcG7T7T7N04kHwYNV7ShTjghOpxyIO98hsSJflJajCJNVfQOoJ6SioE0_R4pnVzZ5Js3_/s1600/sauce.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicxlH-Fxzp9elCuFoua6vJCKBhg1PXuYKIaaJ1QidSlG55ZdaQ6QePIyNRnryimX9rvVNJgCQIcG7T7T7N04kHwYNV7ShTjghOpxyIO98hsSJflJajCJNVfQOoJ6SioE0_R4pnVzZ5Js3_/s320/sauce.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Next is the level-end bus-pickup &quot;experience&quot;, the fail/restart, maybe some options geegaws, and another say three levels, all built with similarly small tilesets, maybe one extra enemy per level and that&#39;s about it. With my schedule the end is still months away, but I can see it, coming ever more clearly into focus. Gotta get this puppy out the door! &lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</description><link>http://ballistictelegram.blogspot.com/2013/03/back-in-triple-digits.html</link><author>noreply@blogger.com (Chris)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRlRDMJ9sr0lU-2zT1lHWH7TEAeyyeADNpQsNNBuI-TrkwLwrJRnV4Yb-yLM46ep520oetw0qHWpuTy2BJjyyCvdJ1C9LFGa91PKXJevgsrffsFgAGNAA4g41DRi31XGlJ7CTZ-SoeNa-C/s72-c/pud.png" height="72" width="72"/><thr:total>0</thr:total></item></channel></rss>