tag:blogger.com,1999:blog-26800655265731428352024-03-14T02:56:27.490+00:00Crushy's devblogRandom ramblings of an Independent game developerCrushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.comBlogger28125tag:blogger.com,1999:blog-2680065526573142835.post-61820923444260819512019-11-07T07:49:00.005+00:002020-10-26T18:00:06.250+00:00A couple of shadersWow, it's been a long time since I put anything here. I haven't had much time for quality long-form articles but here's a couple of really simple shaders I recently did (Unreal Engine but the logic here should be applicable to anything really). Click on the titles for details. <br />
<br />
<h2><a href="https://imgur.com/a/VbPjWWi">Simple LOS shader</a></h2>
<blockquote class="imgur-embed-pub" data-id="rqseSOT" lang="en">
<a href="https://imgur.com/rqseSOT">View post on imgur.com</a></blockquote>
<script async="" charset="utf-8" src="//s.imgur.com/min/embed.js"></script><br />
<h2><br /><a href="https://imgur.com/a/gYd1a5u">Show silhouettes when a mesh is behind something</a></h2>
<blockquote class="imgur-embed-pub" data-id="3xJdKPH" lang="en">
<a href="https://imgur.com/3xJdKPH">View post on imgur.com</a></blockquote>
<script async="" charset="utf-8" src="//s.imgur.com/min/embed.js"></script>Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-9635265877676462862017-06-01T14:28:00.001+01:002019-11-10T22:20:51.689+00:00The player death cycleSome time ago I wondered if the game mechanics in most of today's games have become standardized. Occasionally we find some innovation here and there but most games in the industry follow the same tropes, specifically when we're talking about failure.<br />
<br />
I've recently started playing "Shadow of Mordor" (way overdue, I know) and upon my first death I was amazed at the elegant way in which it was handled in the overall game loop.<br />
<br />
In most games there is a quite simplistic risk/reward mechanism that relies in player avatar death. In order to keep the player engaged there is a risk - failure leads to restarting a section of the game - which usually can be simplified as player death. The reward is progress and the feeling of accomplishment.<br />
<br />
This is a classic mechanism for game design: you can see it on anything from RTSs, where you have to restart the mission, to platformers where you have to redo anything from a specific section, level or even the entire game (for more "old-school" titles) once all the lives run out. You can see this failure - go back - repeat concept in most games you can get your hands on.<br />
<br />
Of course, there have been attempts at subverting this. "Wario Land 2" for instance, completely removes player death but still relies on the same formula of failure leading to repetition. It does this in extremely ingenious ways but the end result is still the same. The most notable level pattern being failure to clear a vertical platform section will make you fall and have to repeat parts of it, but not too much. This mechanic can also be seen in titles so disparate as mainstream Mario games and the Assassin's Creed series.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-y7v5juVpgOxxb_mp9g0ep5IFvfhg9-_x87LWSHadQUCOmQxAvIcaBv_Ye_PEuvtcJU5kLvjmnQkAX3hQu_sN1CAkFKbu7apphanQVAxTgTemGN8QxmstDefmQRAYjdS-FRnijg_IeSA/s1600/index.jpg" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="213" data-original-width="237" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-y7v5juVpgOxxb_mp9g0ep5IFvfhg9-_x87LWSHadQUCOmQxAvIcaBv_Ye_PEuvtcJU5kLvjmnQkAX3hQu_sN1CAkFKbu7apphanQVAxTgTemGN8QxmstDefmQRAYjdS-FRnijg_IeSA/s320/index.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A good example of the Warioland II mechanics at play: being set on fire by an enemy will make you break the "flame" blocks and inevitably fall. The player will then need to climb up again.</td></tr>
</tbody></table>
<br />
So-called "open" or "sandbox" games have an easy cop-out of this mechanism. The non-linearity leads to more interesting approaches - enemies may not be there and force you to take a different approach. Bioshock handles player death and failure as a simple consequence, the player is recreated elsewhere, but the world remains as he left it. Yet some players have said this removes some of the challenge - after all, where lies the enjoyment of the game if failure has no consequence? The entire game experience becomes busywork.<br />
<br />
Curiously, Roguelikes are an interesting subversion of all this. By some definitions of Roguelike, the player literally shouldn't have a chance at repeating a section he has just failed at. Failures are permanent and openly embraced. The fun is derived from the potential of doing better next time by taking better choices when faced with similar situations.<br />
<br />
There's also other interesting approaches to player failure: "Life Goes On" uses it a mechanic. The remnants (corpses) and consequences of your failures are used to (sometimes literally) build a path towards success.<br />
<br />
Coming back to "Shadow of Mordor", every time the player dies - that is, every time he fails - he isn't forced to repeat gameplay sections, he comes back, the world left as it was, but his failure will lead to consequences in the world, usually punishing. The enemy you fought against and failed, is now stronger. It's an ingenious concept: failure isn't rewarding yet isn't punishing in itself. Yet even his failure has changed the world in noticeable ways. Failure can just be a part of progress after all.Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com1tag:blogger.com,1999:blog-2680065526573142835.post-89473691635834485532017-03-19T05:48:00.001+00:002019-11-07T07:46:24.488+00:00My problem with most F2P gamesI've been meaning to write this article for some time and I'm never happy with how it flows. I think it's time I just poured it out and maybe do some adjustments later.<br />
<br />
I've seen a few people throw around that if you want a successful game (especially if it's online or for mobile) it should be Free to Play (or Freemium if you want). I think this is inherently true, but most people I've asked don't seem to understand what's going on to make this business model so prevalent for those two cases.<br />
<br />
Lets define the success of a game. For most this could be some sort of formula that could relate profit with (for those of us that actually care) some amount of critical praise, player count and the desired impact on the target audience.<br />
<br />
All of these goals more or less depend on making people want to play your game. So what's the easiest way to get people to play you game? Just make it free, now all you have to do is convince people to try it rather than the much harder process of getting them to actually put money into something. But wait, you say. I'm no longer making any money from people trying out my product. How am I supposed to make money out of it? There's thing thing called monetization and it's an entire discipline which could be (very horribly) summed up as finding a solution to the problem of having lots of players yet no money coming in.<br />
<br />
For most companies this has an inherent tendency to become a really shady practice rather easily. You're luring people in with a premise (free game) and trying to make the game fun so they keep playing, yet not so fun so they actually feel comfortable not purchasing anything. So you're compromising the most important part of your game (the fun part) because you followed the F2P model. I'm not even going into the balance issues you'll have if your game is competitive. Soon you'll be designing your game in a way that will lure players into associating microtransactions with dopamine drips: the waiting games with instant gratification if you pay, the powerup slot machines that get you another roll for a few extra cents, the instant energy refill that lets you play for 20 more minutes today.<br />
<br />
Note that I'm lumping convenience purchases like Path of Exile's extra slots as a compromise due to the fact that you will also have to consider convenience as a factor that affects the gameplay. Lumping content behind paywalls also falls into this category. The only alternative to this (that I'm aware of) is to sell purely aesthetics items.<br />
<br />
In short, picking a F2P model for your game should be a carefully considered decision. Its main advantage is that it will net you a ton of players (very useful if you're going for a multiplayer title where player count is extremely important) but then you will have to shift your gameplay efforts into making sure some percentage of your player base is spending money.<br />
<br />
And this is the part that scares me. You're shifting your design efforts to extracting as much money as possible from your fans. Usually some extremely low percentage of players that spend thousands of dollars on things like hats and slightly faster movement speeds. I could never get behind this practice as it feels intellectually dishonest and the best results seem to be appealing to basic human emotions like gambling and immediate gratification. You're making your product successful not by making a good game that people will purchase, but by luring as many people as possible into downloading it and then convincing some small percentage of players to spend as much money as possible.<br />
<br />
Can you do F2P in a way that doesn't make me want to take several showers? Kind of (my moral compass is extremely sensitive). Both Path of Exile and Warframe seem to have found a balance where the F2P model helps keep player counts high, and the benefits for paying are designed for the most dedicated fans in such a way that it doesn't give them competitive advantages or make the game simply more enjoyable for them (game design is hard to quantify).Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-45947497685823873992015-11-18T16:21:00.000+00:002019-11-10T22:28:02.788+00:00Low-poly water on UE4<div style="text-align: center;">
<span style="font-family: inherit;">Note: For some reason, the original videos disappeared from blogger and I've had to create new ones.</span></div>
<br />
<br />
Here's how to achieve a cool retro-style water effect using UE4<br />
<br />
First of all, we need a suitable plane. While Unreal comes with one we can use straight out of the box, I prefer having one that's just right for my purposes. <a href="https://drive.google.com/folderview?id=0ByQcEaZwrQ-WQVVNcUFCcmxJZFk&usp=sharing">Here's one I made using Blender</a>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs3KP8wldLrepMtnEkaXVaDThuFOXm-94x8u-U9qkNd9pVUbm7JSXY8k2IihyphenhyphenbYU24SdabEFNPM7NabXyYSC2yQwxWiYr5WQZUQ1PeCsV68wNCVdoqr4N6vb6wYdQaSRRTLnuNvRgIrD8/s1600/blenderWater.PNG" style="margin-left: auto; margin-right: auto;"><img border="0" height="307" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs3KP8wldLrepMtnEkaXVaDThuFOXm-94x8u-U9qkNd9pVUbm7JSXY8k2IihyphenhyphenbYU24SdabEFNPM7NabXyYSC2yQwxWiYr5WQZUQ1PeCsV68wNCVdoqr4N6vb6wYdQaSRRTLnuNvRgIrD8/s400/blenderWater.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The UV map (to the left) is rather important to get right, or you'll just get wonky results. Make sure it maps the corners to 0,0 and 1,1.</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody></tbody></table>
And because I know you're in a hurry, here's the final shader (<a href="https://gist.githubusercontent.com/Crushy/c2482432e2b740e263fe/raw/a81e9f69f20fd9a3191d4fea9e6ead73972da566/WaterShader.txt">you can copy and paste this into an empty material to save you a lot of work</a>):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTvyWMnGBEKwxa23iS6WZDbxxwQWakzHqWCubEs5ZXqGlN9ejjsE36Gk40NvCs7HXBMxEWdxJ8P1DWihGqrkmKnfrj5TiEDzAnSoMS4Mg8-hRQhir7BlfJhhN7N18DhC2R7383dwYiq4/s1600/WaterShaderDiagram.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="324" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTvyWMnGBEKwxa23iS6WZDbxxwQWakzHqWCubEs5ZXqGlN9ejjsE36Gk40NvCs7HXBMxEWdxJ8P1DWihGqrkmKnfrj5TiEDzAnSoMS4Mg8-hRQhir7BlfJhhN7N18DhC2R7383dwYiq4/s640/WaterShaderDiagram.PNG" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<h2>
How it works:</h2>
Firstly we take the current time and use it as UV coordinate modifiers to sample a nice, smooth and tiled noise texture. I found "LowResBlurredNoise" (make sure you're allowed to view engine assets in order to select it) perfect.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
To avoid most issues with occlusion culling I then "normalize" the values between -0,5 and 0,5. Why is this important? It allows us to increase <b>and </b>decrease the vertices' height relative to their original position rather than just adding to it (and thus always skewing them upwards). You could multiply this by 2 to make the values range from -1 to 1 but you can achieve the same thing by tweaking the wave scale value.<br />
<br />
Finally, with a suitable noise map, all we have to do it modify the original vertex position. We take the normal (which would point up in the case of your plane), multiply it by the noise values and as time pans the noise texture forward through all the vertices in our plane, we get a wave.<br />
<br />
<br />
Why use the vertex normal instead of just a global "up vector" (like 0,0,1)? It allows us to place water sideways and so some weird stuff with other shapes, like this:<br />
<br />
<div style="text-align: center;">
<blockquote class="imgur-embed-pub" data-id="0caGiht" lang="en">
<a href="https://imgur.com/0caGiht"></a></blockquote>
<br /></div>
<br />
The bits connected to the "normal" part of the material are a bit of "dark math magic" which recalculates the vertex normals after we modify their position. If it wasn't there, the lighting on our water would be constant and look completely hideous. I may go into more detail on this one day.<br />
<br />
<h2>
Usage Notes:</h2>
<ul>
<li>You <b>CAN </b>put several of these planes beside each other. They will cleanly fit and should have no seams if you've done the uv mapping properly.</li>
<li>As with all vertex-deforming materials, this one will become a bit iffy with occlusion culling, especially with huge "Wave Height Scale" values.</li>
<li>Make sure the water plane isn't casting shadows on itself or is otherwise baked by Lightmass</li>
<li>Keep in mind that due to oscillating height, it may clip through the ground if you're not careful.</li>
<li>Unfortunately, due to the way Unreal handles flat shading, this leaves us with a rather high poly count for a simple flat shaded plane. But this has nothing to do with the Water Material itself.</li>
</ul>
<br />
<br />
<b>Addendum</b>: If you're into Unity3D, <a href="https://www.reddit.com/user/Ro9AM">/u/Ro9AM</a> has posted a <a href="http://www.battlemaze.com/?p=153">neat little tutorial (with source code)</a> that does pretty much the same thing :)<br />
<br />Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-33692188960845280582015-10-14T23:54:00.002+01:002020-10-26T18:05:08.435+00:00There is such a thing as too much compiler optimizationI spent my University years using antiquated subsets of C and C++, so I decided to try my hand at the latest Standards and Proposals.<br />
<br />
After some time I found this weird... Bug? I had a GetNeighbours function that would fill out an array which was passed by reference. It spent a few days as an empty placeholder. Once I filled out the function so it would actually return the neighbours, I started getting compiler errors because std:array was undefined. How could this be? The function had been there for ages, and had always received an std:array parameter. Why was it only throwing out errors now?<br />
<br />
The answer was simple but it took a bit of lateral thinking: The compiler had figured out GetNeighbours was performing no useful work and simply ignored it, not even caring that the type of argument was undefined. The function call had been removed and the code had never been compiled.<br />
<br />
I'm ashamed to say this took me a few minutes to figure out. <br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img alt="" src="data:image/png;base64,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" style="margin-left: auto; margin-right: auto;" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This works</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAhMAAAEwCAYAAAANc/MhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAADFnSURBVHhe7Z1djCTXeZ6nQQQIkrvEAgIskiC5IyQERgAFyQ3jJAxHMaALx9LeWKEuDAlQpNzaluOdlSKsAMlCQhsGmEQWpFDLMSmQCHwhAxLEpYNdjhOBSLJOLJEWhOWOsKFEkRQpiqTk3Z1Kvd3zzXzzzTmnTnV1T/89D/Biuur81PmpOuetUzXdW00FX33tq83H9j92QtoHAAAAgJkAAACAQWAmAAAAYBCYCQAAABgEZgIAAAAGgZkAAACAQWAmAAAAYBCYCQAAABjEws3E7q2DZufidnNwsHe455hSWArFHyn+9Z3DPcMYPbHXbH1ia6xp8+xbBwAAgFVj4WZi+8p+s39l+3DrJDFs/6CdmB/eHU/MCtt7YnQYMmHWZkLomCMdEzMBAACQZKFmYq+dqLcv7jQHt3YP9xyTCtO+He07NBM5EzJLltFMpIzUsnBW/QIAAMvDQs3EzvWD7KQYwzRJ2SMHr92HR+1EvZ99JGEGZPvK7lF4nOx82p2Lyu944k+ZCW9qRDQMtkKSyjOG9TUpKqvV2fDlj3mO41/ZOTqmL0tXWCpP9YM/vrWPb9NUGQEAYH1ZmJnQJLStSTqxKpEL00S8+7Am7Yl5iBNxbuIftRO/GROZlDhplu7yc3nuZMyEHc/ixzCfTtu5lZmI5dt11++PJ+LE7tutFOaJdfBljsczZDqiMQMAgPVkYWZCk3ru7jUXZqsVObMxzcTfNZn3zTOW3Yfps1+VkLY14XaYCUuXmuiFjunzjGYpl64U1pWnmZrSYw3lUVM/AABYbRZmJvpMcjah+8nN5CeyZTcTMawPOqZfYTFiHfzxxDRmoitPbWuFaK+th28HDysTAACbw0LMhE1GqUm1FGZ3wXEyN/pO/BZ/msccNtlauE2cyn9b+SfClM4/ApkGGYBoVux4QuFDVya68hTb2ncl3XaxjAAAsN4sxExossktjXeFafKLhsMm7bhqobglMyFiWps0S3kKGRvbt9uW1x/Dh+218ePx/aOOaSZd5e8ncbXLUX6hLNZmKbrCcnkKewwS05vhAwCAzeHMzUSczD2lMFguhjyyAQCA9WJh70zA6jKLxzUAALA+YCagF/b4g0cZAABgYCYAAABgEJgJAAAAGARmAgAAAAaBmQAAAIBBYCYAAABgEJgJAAAAGARmAgAAAAaBmQAAAIBBYCYAAABgEJgJAAAAGARmAgAAAAaBmQAAAIBBYCYAAABgEJgJAAAAGARmAgAAAAaBmQAAAIBBYCYAAABgEJgJAAAAGARmAgAAAAaBmQAAAIBBYCYAAABgEJgJAAAAGARmAgAAAAaBmQAAAIBBYCYAAABgEJgJAAAAGARmAgAAAAaBmQAAAIBBYCYAAABgEJgJAAAAGARmAgAAAAaBmQAAAIBBYCYAAABgEJgJAAAAGARmAgAAAAaBmQAAAIBBrJyZ2N0/aEaju83B3t3DPadRnB3FOcjHWVYm9dtu67dzuKfM3oHqutPWde9wzzGlsEUz2tmrrmMtk35v224J67tK1Fxj82AW1+3knF/Na99j48DW1laztzM63Lt8qJy727rm9g/39EPjwLLXEeqYiZl49NFHOzUraga6PoPSfjv4jLZ3xye0qWaSs3Qx7s7ewTiP/d3t8XYuXg4bRNbZTGzv7vcaPGrbcNLvmImh1Fxj86DPdZtjWc2EzvlpxhbVZ1vX8P7uYWiZW238iw9faQ6uP3G4ZzhdecoQTGMGuF7Xi5mZiRKzNBM11A5KdtFOcyGUzMT29ujIrfc1E31ZNTMxzQCCmZjQ14StGutqJjQm7LRjwmi7vRbdOaz+tJsOj873bZ3vrYHoO34swkz0NTyG2mW3bZdpVzVguThzM7G9e7c9gU5e7KOdu+1FNdnWgKK7otbEj+XvjhQvtV/EdDUDyvgiH+lkTk8+kzwnS43+rsLuMry2lU97MdkFsr07WcaPg0EuT2FLfnG/UL4WZtJAZIZhZ+84rQ1QpTCRK0s0IYrnJ2mVc3d35yitb8OYZxwslTY1gObSldpaxHSxP63dYnuKXNg7v/rd5p2/81+PdPBnx/kp7PFre807H/r6OOyzDz3ZHu+7VWGpPD947eXm8S8r3svj7Rfatn/nl683L1z7+njbGLe5G3jjpDnpo8m2helaa6s3ll1fYtJm6bDSNTZpr0mYSWn7Hs/nG8NqrlvDlzXWfac9hoXl6ifF8WW3jWvl6VOWHCqPJtr99nxNmYLYr4b2yziqzUtjlOfhK7eaT3ziEyf08MWLzcGtK+PwK7daU3Dx4aMwbw5i2K0rD4/3d+VpTGN0VTfMxPrQXjLdzNJMTC6u9iLdn1ykdvHrotXA4sPitphMzu0+NwgoDw0Atk/pagYCfwH4SUsX/KRcxxOqDQo2ieXuGOwC2d1X3tsn4nXlKVL5xnj+IlTYqA2zevjBJ4ZN2rM1BW0+/nMMi+WctGcwE24Q0LaV13+OpOprlNLl2trqZ/tjOYXao6+Z8Dz+4kFrCr7e5ukMg5v8tW3GoBTm8XmqDh98qK37i9dPhQmrYzRgkz46PscndZ9sT9K0f9vJUUzOieO4mjSjUfDkrjF/LU7Owe7jxXL6fCxd3+tWqA52PE+pLJF4vLGZcDc6Xe1Ug85r9V3uHBYae6JhUNlkkmuNhJFbRbje7n/i4hNtXpPzTNsPa/vQFFx84np25aFmtSN17XWhvulrQGB5mamZeP/7339KIpoNXaR2t6C7Gbvw/WcjXtCpgc4PbKJ2UIpu2l/wdjGbwZD8HXFucJiUZTLRbmsgaePX5ilS+U4G4LyZyE38McznnbqTsAm9lKcoTfxmylKDRMzXU0pX09YilnNaPvtnBydWEeIKQ8ogiFJYV562EqGVCvts50uqrSdtmT7nS2HCVhBSk7GYtHcbv4eZyB1vUoeTqwGWz7TXbSyLp6vuOqYviw+bhXnw6Fh2PufOYUNxbSxQmWXsd3Yn73IpTema8+Qm/rjyEFcYbAXi+hMXx9ueGjMx6ZPjMaqE4vqbHFgP2supm1muTAhdLBpE9tuLeFuDyeGgcNZmYpLueDLyF3wMi9RMcOPP7QVTm6fI5avBJGVAJoPn8pgJQ3WN5iDmmyKVrqatRSznNKiMpZWCacxEV57afvzLX2/jvdzub+Md7hdKmxp4J22ZPudLYZ5JW7d5hWtu0t5t/DCx6lpUfMlP5qXjTfro9LFFDMuVM6LjTWMmYrp4vFmaCTtn7Zr1imOArkW/AqHryz/m0/W+rXewKibq3MT/xPWD5srDrXk4uHW4J43iRVMxazNhpMYgWF0WYiZ0oclE7LYXbhxM4sUeB43UQOfjWXjtoOSXkG0AsAnVL6Gn8Be94Se4ST21MjG5u6zJ05fBUP1y/36lPGvNhMpmg9akzY4HKL+tdDYwWHniYFeqg+HLIny+JWI6kWprX+ZUOcVkwqx/zKGJ/YOa6A8nfhmEoSsTXXmKD2rftevN3lefPNxzEtXfT0KTtkyf85N+Pz7/J+2Zvh5SYZZfvMZypqB0PIX5RxmeSf+1YT2vW4ubWlkplcUfT8g8+LhdZqJ0LnVh52dMG/tVxEk2FaeEHlnYOw+GHmtc1GONgiEwtIrxxMWH2+NNzleRytMzaeeT12wXfqyE1WchZkJMLszyS17+wrcBxMJMlt6//LXX7qsZlMRksNtp052+69cF4h9LxBPfh1u6eIHEASiXpw02tt9k6TSg+P02aU4Gz7yZyNVNWNlSYRrQLGy3ncT9MVSW1ICaqkNq8IymoCZdqq2FL+demyaufMT29+TCNNnb44jHr339xGrBNGZClPIU9hgkl17EScaf83px0M750oSauo7sGuq6xvzKhFRzPNv2jzq8KZn2uo1lrS2Lr4NvMwsrmQk7B6e5m7Zz3J9r6s94LYh4PdjqZu3E6x9plF7AtJUKW3mw/VLpMQkvYEKK9pLqpsZMdAmmRxddvONOTcqrwGRw73cHswnITPiXN5eNyTl4PPEKTb7+PyXWHTPnKWO6yahd+j7iEJiJ9WImZgLmSzQTqz6oTXMXs86oP9+plYrCqsSiiWZicg6W7+TXCVsBW0UDP290YzPN9cyNxXoxNzPBasTsiMue6zCo5R6VbBr2+CN+r8SykXoEskmrEpBGJnPIjYGZNG4uVh/MBAAAAAzizMzEq6++ihBCCKE1FGYCIYQQQoN05mYCAAAA1gvMxByIL0zWvmiol5ksTd9/mXr25kHzyDt+uT3Wpw731DFtOgAAAGMjzETN18H2pZSnzIT9hHDEvvhGhiF+UZShOLlvvMzx5+0xH3nHp3qbgmnTAQAAGJiJKZnGTMTvh8j9n/W0ZuIPZQpu/sHhnjqmTQcAAGCsvZlYxG/858xE/MY3+x/r+BhkGjOR45FP7TVffsc7jtRnBcIeu/B9EAAAUGKjVybm9Rv/OTPhv/lRX9okYzHa2T31BVTRTGjb/56Hqe8kr/cjntb7EZXfOIeZAACAGjbaTMSVh7jCMO1v/HeZCf/1s6nf2JjlysTTrSHwKxNPa3WCr68FAIAZstFmYl6/8V96zKE7fTMPihd/SVDMamUivg/Rd2UCAACgho0wE+Isf+M/Zybir+vJXMRfAxWzWpmQefhDmYdDM6H3J/qsTETzAwAAkGJjzETu9/jjo45Z/MZ/zkwIv8owy38NzeFfwHz2D365NROfqjYTVlZ+hAcAAEpsjJk4S0pmooZZmokh2GMYViYAAKAEZmIO7P/qrzbbf+3e5uAf/72muX37cG89y2Am7N9WMRIAANDFmZuJddePXnih+e4v/mIz+if/8ehFyVe+9mvNa3/6p8n4Xr/2tVeO0nz+n46aV175P8l4CCGE0DIJMzFjvfbtbzc/+t73JtsvvdT8xfZ287Pz55vXr1w5FRchhBBaB52ZmQAAAID1BDMBAAAAg8BMAAAAwCAwEwAAADAIzESByfcs3G0O9u4e7gEAAIAIZqIAZgIAAKCbjTATo527ze7u3WY0uttstTXeaf8eHEwMwuQroyf7JTMO221822faVrr9u+Pf2Ih5+O3c8Sydz3u//ezhZ78BAGDVaKezbtbCTGiFwU32Mg3RFEx+iKvdbg2DyK1MVJmJzPFkMPbabTH5oa/jeAIzAQAAq8bGmInUo4q4KiHNykykjteVDgAAYBXZaDOhVQC/ghDBTAAAAHSz0WbCHjukwgylje81KJ2tYJjhmJWZsMcc/MAWAACsChttJoQmdP+oI65U+HD/CMS/RKmXLWdlJibH2272dkaHewAAAJabdirsZtXNxCoxWenYZWUCAABWBszEErG9u9/wiAMAAFYNzAQAAAAMAjMBAAAAg8BMAAAAwCAwEwAAADAIzAQAAAAMYiFmwv5rge9SAAAAWH0WtjIx+RbJneZgf/dwDwAAAKwiC33MMdrZa/h1TAAAgNUGMwEAAACDWLiZ4NseAQAAVpuFmgmhlzG3RyPenQAAAFhRWJkAAACAQfDOBAAAAAwCMwEAAACDwEwAAADAIBZmJvjSKgAAgPVgIWaCr9MGAABYH+ZqJrwAAABgPZmbmQAAAIDNADMBAAAAg8BMAAAAwCAwEwAAADAIzAQAAAAMAjMBAAAAg8BMAAAAwCAwEwAAADAIzAQAAAAMAjMBAAAAg8BMAAAAwCAwEwAAADAIzAQAAAAMYuupZ55rFqnvf/9lhBBCCK2wtu7cudMsSpgJhBBCaPWFmUAIIYTQIGEmEEIIITRIK2MmPv2Z/5TcL/3v699GCCGE0II0NhOP3rjd7Nzznub27WvJSX9eqjUTMhKYCYQQQmg5NTYT9+xca25fvZCc8OepGjNhRgIzgRBCCC2ntrQqcfk9WpW4kZzw56kuM+GNBGYCIYQQWk5tzXNVYufTv9ucu/e+E9I+Cy+ZiWgkMBMIIYTQcmpLqxLXbt9o7rlnp9U9zU6rWb474Q2FNxISKxMIIYTQ6mvr9o3Lzc61283VC/eMJ/h7Llxtbl/bOTHpD5VMRDQSEu9MIIQQQquv8QuYF67KTIzGE/xIZuKMXsasMRMSZgIhhBBaXo3NxNXbt5t77rkwfsxx+T16zHE2L2PWmgkJM4EQQggtp1bmS6sQQgghtJzCTCCEEEJokDATCCGEEBqkLU3oi1SqUAghhBBaHW39+89/o0EIIYQQmlZb7/4X/7pBCCGEEJpWmAmEEEIIDRJmAiGEEEKDhJlACCGE0CBhJhBCCCE0SJgJhBBCCA0S/xqKEEIIoUHaan78hQYhhBBCaFphJhBCCCE0SJgJhBBCCA0SZgIhhBBCg4SZQAghhNAgYSYQQgghNEinzMTe67/fbI/e2xx868Mn9u9+S/vfdWo/QgghhDZb1WaiS9OmQwghhNBqCzOBEEIIoUHa2hmNmoPXf/NoR84U+P377efR/R9utra2xtr7xnubURt2tP0boxNpEUIIIbS+ql6Z8Pt3vvH7pwwDKxMIIYTQZmoqM6GXMUejdzX7X3hXZzqEEEIIrbemMhO2b/sLvz1+rHHwjfdiJhBCCKEN1SAzIclQaIUCM4EQQghtppJmwr9MKUWzoHcmLMy/wDn6jd8c7+MFTIQQQmhzdMpMIIQQQgj1EWYCIYQQQoOEmUAIIYTQIGEmEEIIITRImAmEEEIIDRJmAiGEEEKDtPW/vnWrQQghhBCaVpgJhBBCCA0SZgL10q2rH0IJpdrKK5UGzV6ptvdKpUHzUar90fpq66lnnmvQZit1YuSkQeLuT55GTjUDJ+02f9EPy6OavvBKjUtotbR1586dBm2udBKkLm7p0u880nzrOz84sY/B+LTiwEm7LUb0w/Kopi+8NA6lxie0OsJMbLhmaSZuv/l/m7ff/H7z1ltvnZD2KSyVZh00q0lMbWRtts7tNS8N7YdNPX/noZq+8MJMrL4wExuuWZiJOz/Za3761svNj698rXnpV97b3Pq5rRPSPoUpjuLG9KuuoZOY6e23ftQcXP/bY+lzKg7Ka9p+sPP36ZuvNx/8xvebc/9l/4S0T2Hrev7OQzV94YWZWH1hJjZcQ82EBte333qj+eFHPnDKRES9/OsfG8ddtwF52knMS3e+P/t//7lpnt0aS5+5G+6nafrBzt9/899eOmUiov7t3g/X8vydh2r6wgszsfrCTGy4hpoJ3a3JJMgsvPQLPz9WNBF+v+Iqjc/Da/Tx3zv6efsXvvjuU+HX3rjSjEYPHsWR7jz14Kl4Z6lpJrEoW5UwM9F3deLCU1eK7aZ29e2kdtxu2/HOc791tE95XPv46Gh7iB59Tvm/+0T+89Y0/aBzUSYhGgcj7lfc0vnb1Q92/ubaefuLj7ftNjrTdpuHavrCCzOx+tq6fON288Dogeb2jcvJCDW6cPX20QV0ob0Qbt++moxnunpbx7zQ+5izKCs6qSFmQnfOenxhhuHua+3k18obitR+pUnddWsCuvPUZBBNTXal/YvUNJOYV1yVMNWuTqhNLqhN3vi9bPtEo6C2HrWTvZ/wNJGlJsBVUd9+UNvq8UU0DJKRClOaVL/U9IPt377/tNFSmIwGZmIyR4zaOcLmFen21Qsn4qTk54jSPDPtHOSlPC4oj475rla+TP5znPf6zrdnpcErE6roBVX0sELavn213EG1HTmLDkdlDTETejHN3pEw0yDMOKT2jeO2aZTWDz5RL2jQvf+3soPxMg22fSexKL8qYYOEPteuTkSjkDIFMg+PagJ74/GjOI9+UXfIk3i59l4l9e0HnYOpdyS6pDSp87emH47MxMcfPBWm9Bfa9Mt2fk+jmr7wSpkJP/bHeaZGpfljFnOL8qgxE7XH8vFyaaaZb89Kg82EXNLlB+SObiTDU5qmcVPhaLiGmAm96W4rEClDkTISJqX1g0+UBl27y4v7i3d87SAtt36tTee3lY/djduEbcv+Me0LbdxRO7HGeDn1ncS84qqEHdO2a1Yn4qQVJzXJmwX7fK397O+kfXv7x02WV66NL3zxuK2sHL6f7HMqnuT75dF2v6VTOefZDzoHU2ZBMlJhUur8rekHawvf9trv+8Tqr/2+bew8TrVLrq1S/Rjz9W3e55iWV0o1feHVZSammQtKaWYxtyiPszYT08y3Z6WtVAUeuHBhfBKpkeR8Rq0TshMrNpzSaDnqxuUHTuyXfFrJlqlKjWbbV9ttv8x19cLoVNyu/C9cvnwUlirfumvn07/bnLv3vhPSPh9nlmZC8oZCpIyE1GUmNAjGOzdJg7F/Z8IGO9vvJ7PUtg2CGjDtmX6Mm5oESuo7iXnFdyWsXrZdszpRM4lJ9t6E6vvo/ZrIHm+NQbtPE1smjeLaRJNrU0unPHx/xHS5eL5fVBdb5p93PyzSTKh+/j0WnY9aObqmPnHt5id55af8U/l2tVWqP1Jt3ueYJdX0hVeXmdAkqjkgFea3c58Vz88Xl9v5wIdF3WjTXnjgctEoKH8zE3asOOdof5zHlDY1r+bKHj/XzLcxz9RcqDqO2jrafps/U/n44+R0ykz4gvowbatDU5XwhfITuvLyBUw9y4rH6BNWyl9h1nEqd59GWSd5QxGNhLRsZsLugPyg7BUHu9z+uK3B+oLMQzuBWRo/uca4ujPLlSGq7yRmiqsSKTMhda1O1JoJ2+/DLW0qDytLbqIpbec+x3g2idrjlxg2z35YtJnwdU+di1Z/6wdJ+aXaJddWqX70x1WcaY9ZUk1feKXMhMZwK4Mfv7vmhdxnP188cPlGG9bmeZhH1DRmIjfn+HJYOr9t86rfn/us+Ln5Npdnrlz6bPtNuXx8nJySKxOWkXcopnhwL4uvCupzfMY1unB1HFY6Zm1Ybf4xncXdJMlEpIyENEsz4Y2E/vrP0VCkBmNb6tWgFsNMfuAr7Y/bGgxrzYRJk4POebuDy6nvJGaKqxKSXWd+X9fqRJy04qRmsklk+4vhjvjj7T7X7r6tfJ90tbHfzn2O8axMqYlN29K8+mHWZqKmH3z9rG0ffarVYRvEtonnrFeqXfy+XD+W2nyaY6ZU0xdeXSsT8WYxN77nPiv95Qc0X0weD8Q8TDaHqY5eNml7KY+4MtFVJoWljqF5NZcmpjdZPjbfduUZy2VpvFnI5WPhJXWaib4vvcjx6eCptJiJ5dMQMzHrFzBTd3JRqckmtT+17Zd2/aCZy1NKTQhRfScxKbUqUVJpdaK2Lrbq4/9bwNpFdys2gagfHr1f24+P8/aPg7ra2LZzn1Pxckvu2jbNox9KL2AaqbDcC5g1/RD328qB1S3VNqV6p9rF9pX6sfSYY5pjRtX0hVeXmbC78a7xPfdZ80WNmTBNszJRUyaF5ebVXJqY3qs030oxbSov5aFz0ExJ3znfVDQT2tYSSWmZ4/LV20fxrcP98ooKOI7nCumP408SxdOyii0/pcrjy1qTf0ynbXSsIWZCk9ss/zVUg5R3xH6QNdlgF+P4QdjixcFcA6ot4cYJNTXAS36SzanvJCalViUkO27cX7M6YWlLd41qY5tgbJ9WaLyJM9Mxrn8bd1vvVxxONKU29tu5z6l0vuz+ZcB594POwVn+a6jU1Q+x7mrrC1oxOKxbDPfnrKR+SrVLal+uH5Vvrs37HFNxc6rpC68+KxO1c0b87OeLeTzmyM05qbDUvJpL4z93zbelPFPbJrVHKZ8aFc2EpE70yx5xycMOngr3aX3HxePoZLD0F9r0PkyrDZZvTFebf6peaKIhZkLSF/jYt1/KLHgjYfL7u760ahU1zSSWW5Ww6yAV1vXuxDrI392nwkvq2w+SzsXUt18acX/Xl1atooa0eU41feGVMhN+XokTf27O8GN9HPd9mq4XMGuk/GvMhLb9PKbt1LyaK3v8XDPfpvKM5TrRhmrfQ+PUNefnxDdgbriGmgn7OmL7FsyS+DrtSfzcqkSXulYn1kFaJYkrJ7Xq2w+Snb+pb8GMWtev0x7S5jnV9IVXNBNo9YSZ2HANNROSBlfdrenxhb1D4aV9ClOcdRuIpb6T2E/fvNnrfQmT0iitP/aqyy/F2x3StHfIffvBZOevHl+k3qHQPoWty/k7yzbPqaYvvDATqy/MxIZrFmbCpCV4vZimN929tG+dl+enmcRkCmI7dWndjMSsNU0/eG3q+TsP1fSFF2Zi9YWZ2HDN0kxsqoZOYmg2oh+WRzV94YWZWH1tqRPRZit1cefEYHxaceBMiXabv+iH5VFNX3ilxiW0WtpKdSxCOWmQQKeVaiuvVBo0e6Xa3iuVBs1HqfZH6yvMBEIIIYQGCTOBEEIIoUHaOvxuFgAAAICp2Ir/BjUPPfs/v5Pcv2pal3oghBBCsxRmoocwEwghhNBpYSZ6CDOBEEIInRZmoocwEwghhNBpYSZ6CDOBEEIInRZmoocwEwghhNBpYSZ6CDOBEEIIndZCzcTzb77ZnPvAY825e+8b65EP3Ne8+ebzybg5XWnzeN+9n2vefP6xZPgsFeuhY59rj23ll56//JETcWatR55XfT/Su77TpkMIIYS6tDAzocntnCa3pz93Yt+bT/eb7BZtJvyxzVxcuXTfiXiL0Fm2C0IIoc3WQsyErUh4IzGtlslMSDJEn5RJevOPT8Q9a2EmEEIInZUWYiZqJlxbubDHB3EFw8IeufyRE5OmD/uk0s1wUq8xE9EopcoTH+9Y3NR+O8b7Ln1unP5Km96OaWGPPK00k2PoMYv2+8cvWimJZc21r8X75OXjcsz70Q1CCKHV1sLMxCMfkJlIvx9hk6GfkO15fwx73+Xn27B2MnSTq02Yn3z6zZlOhH3NRK48+hsfhVi6WF6rr+33eVqYvWsS28kfO5Wu1L5WPpV11qYMIYTQemkpVyZS4ecu/fF48lOYNyJ+klSYv9uWZvn+Qq2ZeJ/MRKE8tt8bh1SdpXgMv506vrVTKV3qWDXpLC5CCCHktZTvTJQmO4WVzETJpAxVjZnwZegqj1ZVZDCsXqm4pck9hpVWRfx26liYCYQQQtNqIWZC0vK5TaS2T5Oc/ptDE1hchrfJL4bFxxwKm+WjDa8uMxHLVlMelV/hpcccuck95h/bqStdrn1z6bSNEEIIRS3MTEiaxPxjAP89Ez7MzIKlMyMyTtNOpH6yi3nO+zGHJmU7ViynlCqPL79/HyHmp8m+NLnbZ72c6dPYsbXaoH06Zswn176l41m+CCGEkNdCzcSqadnqwUSPEEJoGYSZ6CHMBEIIIXRamIkewkwghBBCp4WZ6KF1qQdCCCE0S2EmeggzgRBCCJ0WZqKHMBMIIYTQaWEmeggzgRBCCJ3WliZIhBBCCKFptdUAAAAADAAzAQAAAIMomok7d+40P/3pT089G9E+hQEAAAAkzcTBwcHYMPz4yteal37lvc2tn9s6Ie1TmOIoLgAAAGwup8yEzMHbb7/d/PAjHzhlIqJe/vWPjeNiKAAAADaXU2ZCqw0yCTILL/3Cz48VTYTfr7hKU8N+azpGl240Wx9+dqzdS99sjcjr47DRl1482r//R9fH+wwL2/5QG/97N5rtP3r9KK5pR2EHLybjz4pn2vKfv/eh5uDmk4d7jnnspsI+mgybFyrPYw+25Tm4Of58ri3b+XvvG5fBh+WoiVOi1B7rzFn2dd82nmefnP/KzfZ8ac+vivOl9txah3Ootg6X9nSN3jduw8du3pzbOVQqzyLGKVgMZ93XJ8yE3oPQ4wszDHdf+9FY3lCk9itN1zsUu99rjcSHrjcHzz53uGey7+DZG0d/xV57IWx/6LkjEyBjEM1FRObC4tTEn5ZlG/j8gK3Pl1S2gz85FZajK05XfbvCYTh923hefaJ8ZVY3xUz0KVdNXGu/g72HDvfMjnj8ZW3TWla9/JvKCTOhFQZ7R8JMgzDjkNo3jtumKa1O2IqENxI5FHdbcVszIWOxe6k1FoerFykUZ0fm4+DFqvhDWLaTXOXBTOQ5/5k/WfkBqW8bz6tPxqsSX5GZaO902vPlZnucSw8+eXS+RbrOLWNZz6E+5aqJO896xryXtU1rWfXybyonzIT+U8NWIFKGImUkTEqbQysPO1qVOHwMUcKbg51n289f+mYzarf12MI/FjEUx1YiauIPwU7yx/aebO8yPjpesrz5lY+eCNMFYJ8vfUXx7jsRT5xrJznb/8xn7hvvszTnPzN5VHFOg7a7i9ESaemuUOm9mfB0pRWaHM61k8NRudpj604qllNLZ1b3x9o6WZ39MeLxuup7Sfvbcvtt1SOmszJ2tYv2KY2P5/snbtvnVH/FdlGeMa9cm5TyFT6d1Tnu9/lFSmVLnaOipi/iOaTyPPOZj47/mpkQSqdzxPKppVQ/Hyb5PvRhVs5UG3j69IGlt3rZvlT9autg57bPT8e3cg05T0SqrJZf1zjV1XYi1T6idAyRKrOlKV3jqfrE/KRYjtK5O0261HUSybVf1zFjP1s+Fk/4ca2mLW+qLTNjQde1lStXX4pmQvKGQqSMhNRlJnYvyUx0T+z+MYXMgX/vIT7C8KsYoiv+UNToOtF9J9szKd9xFs9OQp0YqRM2lcY6UWn8SayT259sEaUfYibi8YQvn22rjFYO3a3aOxr+GLnjleobtz0+Xald7GJJXfw+j7htx071V1e7WNpUm5Ty9XlYmOpeys9jA1BsL0vv+6LvuefRcc5roGvjqX29mTB0DD84lSjVL4blri9h7aW/qf42LM9cH9QezxPTxTrk+tXv99uWX5/zxJPKW/mlzgEfV/tr2i7XPv4YNX1laVLnmU8T01u6UjlyeU6TzhPLYnRdf6Vjpvo59oWNa/H4ubZM9aVPO225+nBmZqJrZcIehfjJX+Zg70vfPNw6va18975UH38osWNFqtNjvLitzjIHmBuEtG3mQJ9rHlnkzEQNOrk0EfuLI5ZJceKdqQ/PUVvfmFcuXa5d1BcWL1I6Ximsq11KbVKTr9VP0sVc28aKd0mDQejv0jFFTV94NFFa3WPZDBtYawagUv1SdbLrS2G59or94ym1R+l4pTbpqkOqnKVylMJy+XlK6eN2Ku9c2/Vtn66+SqWpOR/7lsOYNp1IlcuTylv0Oabf1ufUuFbblhavNE5NU64+nMljjq53JuIKg9FlDvTipc/zrM2EX57yYaXO8Z3q7/pSHWgDuR/Qcyj9EDNh6Fg6YVMnmcpeM9F5auubOlYqnSi1S25iKx2vqywi1y6lNinl6+vnqW3jXPraY3ade0L7dcfiBzLJ7katrXMGLkWpfqk6+QkqVV/D94+ntj2M2kmqTx1EqRylsK56i1L6uB3DRK7t+rSPnQulvoppfLzS+dinHJ5ZpPPl8uTq2OeYcTs1ruWOkyt/aZyatly1nMkLmEITu95jSP03R27S9//ZEQ1JyoCU4s8CNbJfWvId5Dug1DlyvDVLg2KcfztonZdLdftTKH3OTPhj1mAnc6oefqlM8Wwi8cfIfS7VN27n0omadon5+cFOKP/cnVDcNlLtos+5Ninla+nsXDJK+XmsPqn0uWPW9kUOpbFJNDfIdlGqXwwb97O7vlLt5bH+8cS6+e2u4+XaJKZL1aFvObrKWKp3KX3cjmFGru1K7ePLVdNX8dh9xoZSOVL1EdOmK409Run6qz1m3B7Hba+vS+NVick4bvl1taXH+tLHsXymKVctJ8zEPP81VMg86N9DZSr8C5Kp742wxx0+jTcc/kVNTy7+LLBG1ksvdpdmnRM7Ltc5dhIq7aX2hLUJMdeBco9xWTOF0g8xE4pjdfJ39Tq+9lkZfLyaFzBr6xu3c+mM2nbxnKhjm9aOVypLql1i/FybdNVRF7Rfwuxq44jy0wBhcXUulo5Z2xe+/zwqr78jn5ZS/XybRBOVaq9U/3hK7SFKx4vnvqe2Dpa+VI4+ZbT8Ir6stcfqajuRax/LJzUWipo2KF3jse27ymHbkWnSdY09hvKI15+oPWauPWL/1rRlqi9jnGnLVcsJMyG0wmDffimz4I2Eye/v86VV0B9dVP4izaETYBaPOVaF2nY5a3TBmuNfVZa1bWF5mHbCgfXllJmwr9O2b8Esia/Tni+amGrvBHVxyyV7x7mu9GmXs0YTcdcq0DKzaaYUpgMzAZFTZkLIHGi1QY8v7B0KL+1TmOJgJGaPLXdtgjHowzK2i18S9UuMAOsMZgIiSTNh6D0IGQb9p4aX9tW8IwEAAADrT9FMAAAAAHSBmQAAAIBBYCZg6Sg9j13Us9plfEZcWyb7tzG9GDrrn77m2TkACMxED+Y5cG7CoFxbx1K8vu00bbvGdNPmM09qyqQ4/stqZs2ytcsy9hPAJoCZ6ME8B6pNGARr61iK17edpm3XmG7afOZJTZnmXe5la5dl7CeATQAzUYkGKf9tZ6lvZpNyd4D2jW4+rRHzfqwN178b+ry0VK1l6mcOtEz9UK+f/o3kyhL/zdGOn9ufOpYN5rF8ufZLlSWXhw+zyaJU39wxu/osla5UJtHV7jV18j+HnMvP7y9986LSzOunr0tl8Ph4krXzNG2ZaqN47ihOn/5O5QkA04GZ6IENPjZw2uDlJ9eu59ExDyPul3mwwVBo4NRx7Jj2xUj+mKk8/CAd8fHNMMT4uf25Y/Upn8eH1eYR80vVN8axvLv6LJfOyqRjxYmuqxylOinM0uTys3hW9vibELk0sR62bfnZeVZTJ0uTKoMnxkvVt885bGmsjTw+TUxv6UrlSOUJAP3ATPQgDlQamOJXJ9ukH9GgaHdGucE3DoL2TYT6bD9JG+MJO6bK4+/AJG9IjFRZUnURpf2pY5XKlwpLlaU2j5r6xrxS9Un1WUxX2p6mHCLXLrn8tL/0a5U1/eG3S2HTlMGjeLl2TqWxsNp6iJpzp285AGA6MBM96DNQeXw83emnfm0xNbDZr7/5X/SL8WzlwAbiWJ5Iriy5tH33l8pXaj9flto8cmXwlI5ppPospittT1OO2nbxaH/JTKTSlMpdCpumDJ5U+twk7tuith4+Xunc6VMOAJgezEQP4uCj7biEmhoIdQeVWtL1pAa2cX7twO1/tc6OaebCHzOGpciVxQb0mDa3P3esrvL5OubKUptHrgyeeExL09VnqXS5bcuzqxy17ZLLz/Zb2eNjjlyaUrn71sn2p8rgifFifX3epTBD+31ZS+dOrFOpHD4uAEwPZqInuquxpVehwcmWZVODqrAJWXFKP2kb8xba57dtAOzz07+eUlls4I355vanjtVVPl/HXFlKeViYlbmrvmKaPhM+XTxu33L0qZPI5eeX9hf109elMnhy7WzH6XMOx7KVzuPa/o55AsD0YCaWHA2MfqBd9gGQAToN7XIMbQGwfmAmlhjdUcWf2sZMrCa0yzG0BcD6gZlYQmwJN/csGjOxetAux9AWAOsHZgIAAAAGgZkAAACAQWAmAAAAYBCYCQAAABgEZgIAAAAGgZkAAACAQVSbibfeeuvwEwAAAMAx1Wbi/vvvP/x0zM9+9rPDT7Ap6DsC9AumNw9uNpcefPLE7ynY92LY1y37n7OOaRbFWXzHAd+jcBLaA2D9yZoJmQdTaRtWg1kN6CljoH32c+mG35dKM2tq61cbrw8xz3kcY5WhPQDWn+LKRDQPqb+wGsxqQFc+mImTxDzncYxVhvYAWH+KKxPx7927d8d/79y5c7QtbQo2KF76yuTXCiX/U8nx1w79D3R5cvEs/8f2lP8kPJe/f4SgNPoFRttnv5oo2S8u+l/9TP2aohTL4fMsofglM9GFHc/XW2XRz1tb2Xw71NbP/7KkpDxTx+pq41Q+RurYszxGKm6kqx9nfT4Ji1dzLfhfFi21JQCsLjzm6IFNHDag6t0APwgrzE8C59vBNN6NleJZ2GMPKs+bp8JsQBY6tgZvS+MHcsOniektXakcqTxTKP5QM+Hrbe9c2PF9O3uULlc/m7RiHVLHihOp5WFtrL/W5yliulkdIxfXY8daxPmkeDXXgkyhf5+m1JYAsJpUv4AJ6UnDtjVQX9JA7Sa8+PPhohQv5i8sTOn83aekQTmVRgO2xbFBPMbrW44Sij+LlQk7Xtf2tPUTpbxzbWz7UxOs6CrvtMfIxfUozjKcT7GO/tduU/XPtSUArCaYiR50DaCzNhN2d22Df83k6OMp/Xmlb8NK8YxVMBND6idq805hj11in5byjNt9jtEVV6TiLOJ8inXMmQkj15YAsJqcMhN37txufvjgv2xePfeXm9ce+fx431vfeb558e//3VZ/Z/xZKOyVv/GXmh/+q18ap9kESgOoPsfl5txgnYtnYXbXVgozfBmE7iJrlrW7yhEH/xKKf1ZmorZ+NnF2tZff1udUG3s0CfbJM273OUZNXIuzDOdTrKOVSfWxFQ1Pqi0BYDU5ZSZe/Q+fbn7wz/9B85Nn/0fz6t/6q81P/vu15gcP/MPm1c9+cqxx2Df/pHn1b/6V9u9e84Ptf9S8+tv/rh1sDg5zWF9KA6jQYGtLx6nB08jFs/z08pvC4p2bTyellqVtElX4pXYSOP/gcZjuWC2d6CpHrvwRxT8rM9GnfkqnSU37JLVl17FSbeyX+VPvbgh/7FkeIxU30tWP8zifuuro6+NfwKxpSwBYPU6ZifHqw/PfHn/2qw/GS7/0z5pX/vrW2HSIt7775+NVi794443xNkxPHJBXBZV7iJmA+bCq5xMArB6nzETNCsPBBv076FmyymZCKwB2V2x3n9x5LhbMBACcFbyAuUQw+MMs4XwCgLMCMwEAAACDwEwAAADAIDATAAAAMAjMBAAAAAwCMwEAAACDwEwAAADAIDATAAAAMAjMBAAAAAwCMwEAAACDwEwAAADAIDATAAAAMAjMBAAAAAwCMwEAAACDwEwAAADAIDATAAAAMAjMBAAAAAwCMwEAAACDwEwAAADAIDATAAAAMAjMBAAAAAwCMwEAAACDwEwAAADAIDATAAAAMAjMBAAAAAwCMwEAAACDwEwAAADAAJrm/wMaiKsM2VvNcQAAAABJRU5ErkJggg==" style="margin-left: auto; margin-right: auto;" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This doesn't (std::array is not a defined type)</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img alt="" src="data:image/png;base64,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" style="margin-left: auto; margin-right: auto;" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This works. Wat?</td></tr>
</tbody></table>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-61949743935295033262015-09-10T22:48:00.000+01:002017-03-26T04:44:10.133+01:00On moving from Unity to Unreal<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVcBVytPcNCR09_QzhRV76RRMYZ4ZSfaT0kg7NhSUG0LY4DpmxPD60RQORObbdX3HYEluXhaQLf1uyH4rUIyr2H3Kkj8iAYkkvRckPO4DzG3zFpRdvc7RdI8SwEbvDKViMk4wZico7H4M/s1600/UnityToUnreal.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="104" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVcBVytPcNCR09_QzhRV76RRMYZ4ZSfaT0kg7NhSUG0LY4DpmxPD60RQORObbdX3HYEluXhaQLf1uyH4rUIyr2H3Kkj8iAYkkvRckPO4DzG3zFpRdvc7RdI8SwEbvDKViMk4wZico7H4M/s320/UnityToUnreal.png" width="320" /></a></div>
The team at Titan is working on a soon-to-be-announced Top Secret Project. We've recently changed from Unity to Unreal and here are some things we've thought about sharing with other Devs that are thinking of making the jump.<br />
<br />
<br />
<h2>
<span style="font-size: x-large;"><span style="font-family: inherit;">The good stuff: </span></span></h2>
<ul>
<li>Unreal let's you easily alter the aesthetics of your project. The drag and drop material editor, the huge amounts of built-in high quality content let you easily reach AAA levels of quality, even for small prototypes. </li>
<li>Blueprints are amazing for quickly prototyping concepts! Beware: any non-trivial math expressions will be a mess of wires, but thankfully there's a handy <a href="https://docs.unrealengine.com/latest/INT/Engine/Blueprints/UserGuide/MathNode/index.html">math expression node</a> to help you avoid turning your code into a spaghetti mess.</li>
<li>The community has a lot of experienced developers, which makes useful content and non-trivial tutorials easier to find.</li>
<li>The architecture and the way everything is structured encourages newbie developers to write more robust code. Contrary to Unity, there's already a game state, game modes, an Actor-Controller model...</li>
<li>Epic's experience has led to so much high quality content that you can easily pick up something like the FPS Tutorial and merely have to tweak a few values to suit your needs - We recreated the movement style of our first Unity game (<a href="http://titanforgedgames.com/games/slinki/">Slinki</a>) in a matter of minutes.</li>
</ul>
<br />
<h2>
<span style="font-size: x-large;">The bad stuff:</span></h2>
<ul>
<li>The render pipeline is setup for realistic lighting, if you want something really stylistic illumination you can either "hack" your way around this with more complex materials or get down and dirty with the rendering pipeline. </li>
<li>Don't get me wrong, Unity can be a bit of a resource hog sometimes. But Unreal seems to be an expert at making even our reasonable Gaming PCs suffer. Compile times will be measured in minutes for anything but the smallest projects.</li>
<li>The way Unreal handles project files is simply not as robust as Unity's. Every time you move something, a file a redirector is created. </li>
<li>You can't just drop a png file and use it as an asset, there's always going to be some sort of pipeline to get assets into your game. </li>
<li>As a sidenote to the previous point, you will have to export your blender models as an fbx. Many things can and will go wrong with this process. I would write a tutorial but I found it changes a lot between versions of both programs and none of our solutions have been ideal so far.</li>
<li>C# is gone. You will be using C++. This can be a curse or a blessing but overall C++ is not as great for quickly prototyping.</li>
<li>It's not very stable. Seriously, it's not. The update to 4.9 broke transparent sprites on the UI. This is not a trivial and easily-ignored bug.</li>
<li>The huge ingress of novice game developers has made communication with the Epic team and experienced members slightly harder due to a sea of (mostly) trivial questions.</li>
</ul>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-19993777328269286772015-07-29T15:41:00.004+01:002015-08-10T00:44:23.502+01:00Chocolatey is awesome and you should use it<br />
<div center="" text-align:="">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmAVrI2HH9xOrtCGThyphenhyphenIxaSOuBOs4QzwK8TQHRN-3bAY7FmCexnt8iO40JonqJiXYIMPvGCTBH9-LK07FWDY4ZO0qwDfXm8NtgkHpE3IZJ7MMrnSmBdvY_vTyHJxgDFqDvzSSAEV66djA/s1600/nugetlogo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmAVrI2HH9xOrtCGThyphenhyphenIxaSOuBOs4QzwK8TQHRN-3bAY7FmCexnt8iO40JonqJiXYIMPvGCTBH9-LK07FWDY4ZO0qwDfXm8NtgkHpE3IZJ7MMrnSmBdvY_vTyHJxgDFqDvzSSAEV66djA/s1600/nugetlogo.png" /></a></div>
</div>
<br />
<div style="text-align: justify;">
I've recently started using <a href="https://chocolatey.org/">Chocolatey</a>. While the thought of a package manager for Windows has crossed my mind (oh, my long gone Linux fanboy days), I always relegated it to something that would be too hard to maintain and work with.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
For anyone who hasn't used a package manager, here's what makes it better than the classic install/uninstall babble.</div>
<ul style="text-align: justify;">
<li>The endless cycle of "Go to website, navigate to download link, wait, double click, click next, uncheck the 'install malware option', press next 2 more times, wait again, press finish" is gone.</li>
<li>Update <b>ALL </b>your software with no user input</li>
<li>Got a new machine? Run a single-line command and all your favourite programs are now installed.</li>
<li>A lot less annoying popups saying an update is available </li>
<li>I think avoiding Adobe Flash updates deserves an entire bullet point. </li>
</ul>
<div style="text-align: justify;">
So how does it work? Suppose you want to install git and Flash. Easy, launch the command line as an administrator and run this command.<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: white;"><span style="background-color: black;"> choco install Git flashplayerplugin -y </span></span></span></blockquote>
After some time both Git and flash will be installed.<br />
<br />
Firefox's giving you warnings that your version of Flash is unsafe?<br />
<blockquote class="tr_bq">
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: white;"><span style="background-color: black;"> choco upgrade all -y </span></span></span></blockquote>
Now both flash and Git are up to date with (nearly) no user input.<br />
<br /></div>
<div style="text-align: justify;">
<a href="https://chocolatey.org/packages/ChocolateyGUI">There's also a GUI available for people that are afraid of command line interfaces</a>.<br />
<br />
<br /></div>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com1tag:blogger.com,1999:blog-2680065526573142835.post-55997021102664743192015-05-27T14:34:00.003+01:002015-05-27T14:34:57.359+01:00Unity's new event systemDespite being very poorly documented, Unity's new event system can be incredibly useful. Here's a really simple script that I keep using over and over.<br />
<br />
<script src="https://gist.github.com/Crushy/5b190f0d4f06717f1e76.js"></script><br />
<br />
<br />Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-63115183612045079462014-03-20T01:25:00.003+00:002014-05-13T02:09:45.716+01:00Just a bit of fooling around with shaders and Fourier Transforms<a href="https://dl.dropboxusercontent.com/u/12755420/soundVis/soundVis.html">Made this quite a while ago but only now got around to posting it</a>Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-45650629887745334782014-02-15T02:17:00.000+00:002015-05-19T18:00:03.947+01:00Regarding Meshes in UnityMaybe it's just my OpenGL (1.1) background but here's a few roadblocks I've hit while doing procedural Mesh generation in Unity, along with a few tips not many people seem to know of. Some of this knowledge has been useful even outside my procedural experiments. <br />
<br />
<h2>
Quick Overview (stuff you really should know)</h2>
<ul>
<li><a href="http://docs.unity3d.com/Documentation/ScriptReference/Mesh.html">You will read this until your eyes bleed</a></li>
<li>Mesh.vertices contains your vertices. Mesh.triangles contains <b>indexes </b>to the <b>vertices</b> array. </li>
<li>Normals (and UVs) are per Vertice. E.g.: Mesh.normals[i] has the normal for Mesh.vertices[i] (Blender uses normals for each face, which sometimes confuses people)</li>
<li>Different materials means different submeshes (or a new Mesh if that's what you're into).</li>
</ul>
<h2>
A few pitfalls and tips</h2>
<ul>
<li><b>Mesh.uv1 != Mesh.uv</b> (WHY AREN'T MY TEXTURE COORDINATES DOING ANYTHING?)</li>
<li>If your mesh has more than one material, you have to use submeshes to define which area has a certain material. When copying meshes, I've found that I have to manually SetTriangles() as no other way of copying submeshes seems to work.</li>
<li>The backface is determined by the order of the vertices in each triangle,<b> NOT</b> its normal. If your mesh looks like it's inside out this is probably why.</li>
<li>Some of Unity's built-in shaders (namely the bump mapped ones) do not calculate their own tangents. Each Mesh has their own tangent array for this specific purpose. Unfortunately they can't be auto-calculated. </li>
<ul>
<li>Blender files do not have these by default but fortunately Unity can calculate them automatically. Sadly, we don't have access to their algorithm for this. </li>
<li>Fortunately there's some code floating around that works. </li>
</ul>
<li>Don't generate a new Mesh() every time. Use the same mesh instance and .Clear() it. New meshes will get fed to the GPU but won't replace the old data there, causing memory leaks.</li>
<li>99% of the time you can just call Mesh.RecalculateNormals() at the end
instead of reinventing the wheel and calculating your own normals. As
far as I know this calculates the normals based on the order of the
vertices. </li>
<li>Don't forget to Mesh.RecalculateBounds() if having decent bounds is important to you. </li>
<li>When you add a collider Unity will automatically fit it to the current Meshfilter's bounds.</li>
</ul>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-87343859038204882342014-02-03T21:19:00.002+00:002014-05-13T02:09:24.432+01:00What a good F2P model looks like<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: justify;">
Out of all the F2P games I've tried, Warframe has by far the best microtransactions I've seen. So much so that I've been meaning to write this article so I know what to do if I ever find myself in a similar position. However, let me just say this is not a review, just an overview of their Business Model and why I think it's great:</div>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_0KFLjJk-wWZ2FkOsasTXX5PdkKi757Q5Sxh_pRw3a_l8Fx8mny7X2mYqodbG7YbBMjN-bO_T-z5Cd5f9K9B7az5IZQ1EXUt2wyYH7_KxWMtuvGPI0G0DPRviK6jlL2WU6Y2yHRvQ6Rw/s1600/byThePower.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_0KFLjJk-wWZ2FkOsasTXX5PdkKi757Q5Sxh_pRw3a_l8Fx8mny7X2mYqodbG7YbBMjN-bO_T-z5Cd5f9K9B7az5IZQ1EXUt2wyYH7_KxWMtuvGPI0G0DPRviK6jlL2WU6Y2yHRvQ6Rw/s1600/byThePower.jpg" height="360" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">An Excalibur Warframe proudly proclaims: "I have the poweeeer!"</td></tr>
</tbody></table>
<br />
<h1>
The paid exclusives</h1>
<div style="text-align: justify;">
In Warframe there's only 2 things where you need to spend money: Slots and Colours. The free currency you're given at the start can get you quite a few of either and you start out with a decent (but small) selection of colours to give your character a unique look. Everything else has a chance to show up in random "alerts" or invasions. These events are quite common, however it might take some time until you're lucky and find what you need (I didn't say it was perfect). </div>
<div style="text-align: justify;">
You can also purchase boosters but I will get to those later on.</div>
<br />
<h1>
Purchases are permanent</h1>
<div style="text-align: justify;">
No "renting" costumes or any such bullshit. What you buy is yours forever. When you're purchasing a virtual product you shouldn't have the added insult of having them fade away after some time. The mods system is also amazing and you don't lose anything by trying out new builds.</div>
<br />
<h1>
It's (always) fun</h1>
<div style="text-align: justify;">
Digital Extremes is an
experienced game company. The game looks great and has a lot of
"crunchiness". There's a great feeling when your properly modded machine
gun is blowing chunks out of the heavily armoured Grineer. Or when your
saw-launcher slashes infested into (literal) pieces. All the weapons
feel useful in some way (although the community swears some are
considered overpowered, as some always are). The game is also based on
PvE fights and doesn't have many of the issues of the more competitive
games in it's genre. Even so, an experienced game company can turn their amazing game into a grindy, boring mess when trying to get the average free player to give them their money.</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-c7tIKAg2JtnZFq4BOCVg774wi94xVhklf4ZOTRPjbEuvYFP3uLCcz0zcwWUupSGm7uDpM9IL2osBHzUdcmN6ngRzNNkzOIp_kX-4ky6juZcrUtVGYerBeqEndyzXPYOgQH4tgrO-M_w/s1600/warframe-.png" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-c7tIKAg2JtnZFq4BOCVg774wi94xVhklf4ZOTRPjbEuvYFP3uLCcz0zcwWUupSGm7uDpM9IL2osBHzUdcmN6ngRzNNkzOIp_kX-4ky6juZcrUtVGYerBeqEndyzXPYOgQH4tgrO-M_w/s1600/warframe-.png" height="360" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Defence missions are basically seeing hundreds of these flying everywhere while a Nova does all the work</td></tr>
</tbody></table>
<h3>
No grinding</h3>
<div style="text-align: justify;">
Sure there's <b>some</b> grinding. Without wanting to go too in-depth into the mechanics, you'll need to level your Suit and your weapons to level 30 to guarantee maximum effectiveness, but a single day's effort is all you'll need to fully level an entire set. You can buy boosters to drastically speed this up if you just want to spend <b>a few hours</b> levelling your gear.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
There's always a new reward around the corner. This mission you did just levelled your Pistol. You can now put a slightly better mod on it. How about sticking that multi-shot you got 2 missions ago? Or maybe you now have enough nano-spores to craft that new gun... I rarely find myself looking at the end mission screen and not having anything new to fiddle with. You'll never hit a point where the game will push premium content in order to make it less tedious (I'm looking at you World of Tanks).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Weirdly enough (in the F2P industry), they're also moving AWAY from tedious farming and some extremely rare resources have been made more common or easier to obtain. Eg. : When I started out, Warframe parts used to be rare drops from bosses that you had to pick up once you killed them. You now always get warframe piece every time you kill a boss and you don't have to go around looking for his corpse in case you missed it.</div>
<br />
<h3>
Insignificant timers</h3>
<div style="text-align: justify;">
Crafting guns takes between 12 and 24 hours and putting together new Warframes (classes/suits) usually takes 3 days. You can rush these for real money but, besides the 3 day wait (along with time to craft each piece that makes up the warframe), it's pretty managable. You'll most likely still be levelling your current gun when the new one's ready at the forge (I currently have around 5 primary weapons ready to be picked up). </div>
<h1>
Reaching out to the players</h1>
<div style="text-align: justify;">
<a href="https://forums.warframe.com/index.php?/topic/128402-rng-algorithm-bugschanges/#entry1532002">I think the random number generator bug post speaks for itself</a> but I shall digress anyway.</div>
<div style="text-align: justify;">
Warframe has patches released relatively often (every 2-3 weeks I'd say) which add new content (like new tilesets, weapons or maybe an entire overhaul of the damage system). When there's a need a hotfix will be released ASAP. What does ASAP mean? Literally 3 hours after a patch. There's also the hilarious "red text" that always precedes these releases:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgePqXS7ljNB9zQLoOX3QDXQZjE_aIwFA0aGP9xMDhoIcxEP23XMm861nrqUis2DyW_pspxHpEbiMqEy9C7v-1A6obFuuz1b-9BRc2mEUWBBcMK76bVD7S2wabP1t7I4g7pE0v_4RTW1QQ/s1600/blogRedText.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgePqXS7ljNB9zQLoOX3QDXQZjE_aIwFA0aGP9xMDhoIcxEP23XMm861nrqUis2DyW_pspxHpEbiMqEy9C7v-1A6obFuuz1b-9BRc2mEUWBBcMK76bVD7S2wabP1t7I4g7pE0v_4RTW1QQ/s1600/blogRedText.png" /></a></div>
<br />
<br />
<div style="text-align: justify;">
In short, they tell the community what's wrong: when they screw, they work on fixing it and then tell everyone what just happened instead of compiling a changelog and running it through QA for a few weeks (I honestly envy their ability to do this and still have an incredibly bug-free game). They invite everyone in-game to watch their live Twitch livestreams so they can know what's up and there's even a reward for everyone afterwards.</div>
<br />
<br />
<h1>
Overview</h1>
That being said, here's a rundown along with some bad things:<br />
<br />
<b>The good:</b><br />
<ul>
<li>Levelling/grinding is quick and constantly rewards you</li>
<li>You only need to pay if you want to. There's nothing that affects gameplay which you can't craft.</li>
<li>Decent aesthetic customization by default</li>
<li>Developers that feel like human beings</li>
</ul>
<b>The meh:</b><br />
<ul>
<li>I don't get why there's an extremely rare item that doubles your mod points for any object. It ensures that you only use it on weapons you really like but I really don't see why there's a weird item that can double the efficiency of any gun or suit.</li>
</ul>
<ul>
<li>Market for buying and selling things. Nothing to add here, it's still limited to only a few types of items and the real-money currency.</li>
</ul>
<b>The bad:</b><br />
<ul>
<li>That 3 day wait for crafting a Warframe. Ugh. I can take it once I have several to choose but when you're starting out, it just sucks.</li>
<li>The weird rare item that can double the efficiency of a weapon is on the "meh" heading because I don't care that much for it. But it is available for purchase with real money. The PvE nature of the game limits the consequences of this. <b>However</b>...</li>
<li>They have recently-introduced PvP duels. I would like PvP to remain a side-feature so the P2W threat doesn't ever rear it's ugly head but we shall have to wait and see what they do with it.</li>
<li>Getting a particular item that only drops from the Void missions can be a serious pain in the neck.</li>
</ul>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Phew that was hard to write, I kept having to stop myself from writing a review several times. Nevertheless, Warframe is quite enjoyable and I think anyone that's slightly interested in the shooter genre (or multiplayer game design) should give it a go.</div>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-8898585356615369012013-10-09T22:01:00.001+01:002013-10-09T22:08:47.648+01:00Easy Paralax scrolling on a 2.5D gameClassic 2D sidescrollers used a technique called parallax scrolling to make their backgrounds more realistic. Classically it was done by making background sprites move at different speeds, thus creating the illusion that some of them were closer to our eyes. While making Slinki we've done some experiments on this and developed a simple way to replicate this technique that will work in any (most?) 3D engines without too much work.<br />
<br />
This article may also be useful if you want to make some part of your game "purely" 2D and have other bits be more realistic 3D meshes. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp0pjy54DZWTJJFtHnul9Qo8ada2nSB9D_mWuGVqEfc9L5KrNuPpsyYH0ov7wbdsDrVeSm-l4BYn0KJ8trmDg6PLAXb8wFBspl9ELQHCzqD7XRSHiZOCfYviWbBTYq9SiWJRytPTqossk/s1600/url.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Sonic 4 paralax" border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp0pjy54DZWTJJFtHnul9Qo8ada2nSB9D_mWuGVqEfc9L5KrNuPpsyYH0ov7wbdsDrVeSm-l4BYn0KJ8trmDg6PLAXb8wFBspl9ELQHCzqD7XRSHiZOCfYviWbBTYq9SiWJRytPTqossk/s400/url.jpeg" title="" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Unfortunately you'll still have a lot of work ahead of you to make backgrounds this gorgeous *sigh*</td></tr>
</tbody></table>
<br />
<br />
First we need 2 cameras: <br />
<ul>
<li> A main camera (the orthogonal one) - This one will render nearly all the game</li>
<li> A second camera, a perspective one - This will render just our backgrounds</li>
</ul>
Setup your background items, and put them on a special layer (we call ours "Backgrounds". Here's an example, the large panels are all part of this layer and they're ordered according to distance:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQJrd8z64twE2BOQ0mPiICBhNQNVOYwK9l-gzoaUoWsVpZXNcaUrjDkCIQr9tcYQBAOXkhZxRpFrB2uSh0xEOmCgcnqT2wzuHnR4BZQC4Gdn2vXZ_McFWtfSZoPEa3FuzdS9X45LvPjTA/s1600/backgroundsSetup.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQJrd8z64twE2BOQ0mPiICBhNQNVOYwK9l-gzoaUoWsVpZXNcaUrjDkCIQr9tcYQBAOXkhZxRpFrB2uSh0xEOmCgcnqT2wzuHnR4BZQC4Gdn2vXZ_McFWtfSZoPEa3FuzdS9X45LvPjTA/s400/backgroundsSetup.PNG" width="400" /></a></div>
<br />
<br />
<br />
<br />
Make the second camera follow the main camera. In Unity3D you can simply make it a child GameObject to save yourself a small amount of coding. Also make sure the main camera is drawn first. In Unity this is done by adjusting their depths (0 for the main camera, -1 for the background).<br />
<br />
Now the fun part: The main camera should NOT draw the background. This may vary depending on the engine you're using. In Unity you can simply put the backgrounds on a different layer and tell the main camera not to draw it using an occlusion mask. Make sure any empty space rendered by the gameplay camera will fail the depth-test (on Unity this means setting the Clear flag to "Don't Clear").<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr-m7mF2AShhGl9jPEMjIPk90kWXyDsb8rzRNoekMEOHsGNWKvlDvsv3z41wVXrRAaI1RMfaQ-kSoqXcZSBwez2Q9O4zSDj431T1ImHvCL5my4VFc_8V9l6yK6afxgy9d2JHysOe8Py9Q/s1600/gameCamOnly.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="367" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr-m7mF2AShhGl9jPEMjIPk90kWXyDsb8rzRNoekMEOHsGNWKvlDvsv3z41wVXrRAaI1RMfaQ-kSoqXcZSBwez2Q9O4zSDj431T1ImHvCL5my4VFc_8V9l6yK6afxgy9d2JHysOe8Py9Q/s640/gameCamOnly.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
Make the second camera draw nothing EXCEPT objects in the background layer.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikHRJN6d5wxpWo8oty3EBEyfeDnv_9C-pq3VZvPx9xibpemxnsu9tK1NiI1fxXI5igNEjdp-Mqitfrw1ixIaJiRcWnjSiM9AC6r-XwCdyhyphenhyphenAOLXnNcdXbuL8IZ_YBhRM78bwGtEA-KH30/s1600/backCamOnly.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="382" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikHRJN6d5wxpWo8oty3EBEyfeDnv_9C-pq3VZvPx9xibpemxnsu9tK1NiI1fxXI5igNEjdp-Mqitfrw1ixIaJiRcWnjSiM9AC6r-XwCdyhyphenhyphenAOLXnNcdXbuL8IZ_YBhRM78bwGtEA-KH30/s640/backCamOnly.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<h4>
How this works</h4>
The first camera will be set to draw all the foreground items and will leave empty space for the second camera to draw on. The second camera will draw the backgrounds in that empty space, using perspective, doing precisely what a parallax scrolling effect tries to replicate.<br />
<br />
<br />
Here's a couple of animations showing the game in pure orthogonal mode and with our "paralax scrolling".<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-D2ZhV-guF5k1m0niBrwd-_Ch-v3UZYOsPLj5A0DhC0nvtCS7TPEaiy7xVxG45BGkFuvOg4BZhiXfDqws5x3kuzEQ3LIBHB98ChoB3_u9EqapZq4Qf8sYX8hEfx5HU2cEM8-IVDkjJEY/s1600/pureOrtho.gif" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-D2ZhV-guF5k1m0niBrwd-_Ch-v3UZYOsPLj5A0DhC0nvtCS7TPEaiy7xVxG45BGkFuvOg4BZhiXfDqws5x3kuzEQ3LIBHB98ChoB3_u9EqapZq4Qf8sYX8hEfx5HU2cEM8-IVDkjJEY/s400/pureOrtho.gif" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Entire game in orthogonal projection </td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqzJcaDTAeftXqE3BcU1asCBd5c4dU88MxX-DZ6dQ7U0Lo1x5Smfuoy6FbX8cdQfzVm98rTQS2saQrdmzRnMvMyv7h9A29c5t9G054SwZDUieSpBQg0x6ge6lsYPdxcj3uOLESBIPGId4/s1600/paralax.gif" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqzJcaDTAeftXqE3BcU1asCBd5c4dU88MxX-DZ6dQ7U0Lo1x5Smfuoy6FbX8cdQfzVm98rTQS2saQrdmzRnMvMyv7h9A29c5t9G054SwZDUieSpBQg0x6ge6lsYPdxcj3uOLESBIPGId4/s400/paralax.gif" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Backgrounds using perspective camera</td></tr>
</tbody></table>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-D2ZhV-guF5k1m0niBrwd-_Ch-v3UZYOsPLj5A0DhC0nvtCS7TPEaiy7xVxG45BGkFuvOg4BZhiXfDqws5x3kuzEQ3LIBHB98ChoB3_u9EqapZq4Qf8sYX8hEfx5HU2cEM8-IVDkjJEY/s1600/pureOrtho.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-51602709990695005202013-09-09T00:59:00.001+01:002014-02-15T01:55:35.028+00:00Simple AI in Unity3DHere's a short writeup on how we're doing the enemy AI for our most recent game, Slinki. I recommend you read up on <a href="http://msdn.microsoft.com/en-us/library/ms173171%28v=vs.90%29.aspx">C# delegates</a> and <a href="http://docs.unity3d.com/Documentation/Manual/Coroutines.html">Unity coroutines</a> if you're not familiar with either.<br />
<br />
We decided early on that the enemies should have really simple behaviours. For instance, here's an example of how the <a href="http://slinkarang.titanforgedgames.com/2013/07/fourth-day-log.html">Shorg</a> works on the newest version:<br />
<ol>
<li>Wait until Slinki comes close</li>
<li>Appear and jump out once he's close enough</li>
<li>Wait for 2 seconds</li>
<li>Jump towards slinki a certain small distance</li>
<li>Go to 3</li>
</ol>
Things like these are really easy to implement using easy AI techniques such as state machines. <br />
<br />
<h1>
The method</h1>
Create a new MonoBehaviour for your AI. It should look like this:<br />
<pre class="prettyprint">//this is like a template for all our states
public delegate IEnumerator State();
//the current state
private State stateFunc;
//seconds between AI updates
public float AIupdateFrequency = 0.1f;
void OnEnable() {
//Sets the first State
stateFunc = StateWait;
StartCoroutine (Action());
}
public IEnumerator Action() {
while (true) {
//Waits untill stateFunc is done before proceeding
yield return StartCoroutine(stateFunc());
//Waits for AIupdateFrequency so we don't busy-run our AI logic
yield return new WaitForSeconds(AIupdateFrequency);
}
}
</pre>
<br />
Here's an example of a possible state method. This one just makes Shorg stand still for 2 seconds before changing to the "Hop" state.<br />
<pre class="prettyprint">IEnumerator StateWait() {
yield return new WaitForSeconds(2);
//next state
stateFunc = StateHop;
yield return null;
}
</pre>
<br />
Here's another state method, this one applies gravity while Shorg is airborne. Once he lands he goes back to waiting.<br />
<pre class="prettyprint">IEnumerator StateAirborne() {
kinController.jumpSpeed = -kinController.gravity * AIupdateFrequency;
if (kinController.isGrounded) {
stateFunc = StateWait;
}
yield return null;
}
</pre>
<h1>
Guidelines</h1>
The "rules" for writting new states are simple: Following the delegate - they should be functions that return <span style="font-family: courier new,monospace;">IEnumerator</span> , they should end in <span style="font-family: courier new,monospace;">yield return null</span>, and they need to have one or more conditions for changing the <span style="font-family: "Courier New",Courier,monospace;">stateFunc</span> variable (i.e. change to another state).<br />
<h2>
</h2>
<h2>
<span style="font-size: large;">Summary</span></h2>
<h2>
</h2>
Advantages of this method:<br />
<ul>
<li>Simple</li>
<li>Easy to create new states</li>
<li>Very easy to debug just using prints</li>
<li>Self destructs cleanly if the GameObject is destroyed or disabled</li>
</ul>
Disadvantages<br />
<ul>
<li>Can get complicated as the AI gets more complex</li>
<li>No way to enforce the guidelines due to the way Unity and C# work</li>
<li>Coroutines can get a bit funky to use for an inexperienced programmer</li>
<li>State is lost if the gameObject is temporarily disabled</li>
</ul>
<br />
Special thanks to David Craft for this<a href="http://www.craftyfella.com/2010/01/syntax-highlighting-with-blogger-engine.html"> amazing hack</a> that allows code syntax highlighting on blogger<br />
<br />
<br />
<b>Note:</b> If you need to temporarily run the AI logic more often than <span style="font-family: "Courier New",Courier,monospace;">AIupdateFrequency </span>will
allow, all you need to do is <i>yield</i> inside a cycle. This probably sounds confusing so here's another version of the
Wait state. In this one Shorg turns towards the player before waiting:<br />
<br />
<pre class="prettyprint">IEnumerator StateWait() {
//Facing wrong way?
while (Vector3.Dot(transform.forward, slinkiDirection.x * Vector3.right) < 0) {
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), Time.deltaTime * 100);
Debug.Log("Turning around");
yield return null;
}
//Debug.Log("Waiting for 1 second");
yield return new WaitForSeconds(1);
stateFunc = StateHop;
}
</pre>
<br />
That <i>while </i>cycle will make the coroutine run
every frame update. Without it, Shorg would only try to face the player
once every 0.1 seconds, producing a very jerky animation.<br />
<ul>
</ul>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-46869840580610080812013-07-22T17:02:00.005+01:002022-01-21T01:24:25.075+00:00Poultron: BonusSince a new version of unity came out today with realtime shadows I figured I might as well make a new version with them on.<br />
<br />
<a href="https://dl.dropboxusercontent.com/u/12755420/Poultron/Bonus%20shadows/Bonus%20shadows.html">Shadows!</a><br />
<br />
EDIT: Now actually with shadows as of the 22nd of August Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.comtag:blogger.com,1999:blog-2680065526573142835.post-40552973953094691592013-07-21T21:26:00.002+01:002013-09-02T02:42:57.826+01:00Poultron: Final day<div style="text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixWeZ0adWZAnPphRPjuxBPJiRLb_7Y2elprIghGa2npTK4C3IOn7PopRAelnrT_iQniNZKtisI1VDu9OtWfqw08l_utI4v9qib_nSD8SMq6d_sjbiJVibs4ci1xaaChnYwYNZzT2MkA6c/s1600/final.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixWeZ0adWZAnPphRPjuxBPJiRLb_7Y2elprIghGa2npTK4C3IOn7PopRAelnrT_iQniNZKtisI1VDu9OtWfqw08l_utI4v9qib_nSD8SMq6d_sjbiJVibs4ci1xaaChnYwYNZzT2MkA6c/s400/final.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">And to think it looks so small from up here...</td></tr>
</tbody></table>
<br />
The main problem with making a game that's designed to be frustrating to play is that playtesting is hell. In the end I think I made it too easy and removed most of the ramps as I couldn't figure out if they were actually climbable. Oh well...<br />
<br />
The credits sequence ended up taking up most of my spare time. It was basically just my name and a list of assets used but a neat little thing to figure out nonetheless.<br />
<br />
In the end I think this was a neat little experiment and I might do a post-mortem soonish. I might even compile a list of issues I had with Unity (like the fact prefabs are not clearly marked, which might result in you changing a lot more things than you'd hope when tweaking certain values).<br />
<br />
<a href="https://dl.dropboxusercontent.com/u/12755420/Poultron/Day%207/Day%207.html">Here's hoping you'll enjoy it.</a>Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-76096663578560997502013-07-20T23:23:00.000+01:002013-07-20T23:24:16.286+01:00Poultron: Day 6 <b> </b>Been very busy, can't remember most of the things I've done today.<br />
<br />
<br />
<b>Features:</b><br />
<ul>
<li>More slight graphical tweaks</li>
<li>New flying enemy! (took up most of my time)</li>
<li>Landscape is slightly more interesting</li>
<li>Keep walking and you'll find new enemies (eventually)</li>
</ul>
<br />
<b>Current issues:</b><br />
<ul>
<li>Still no endgame :(</li>
<li>Enemies pop up in front of you. The level will be tweaked tomorrow.</li>
</ul>
<br />
<b>Tomorrow:</b><br />
<ul>
<li>Ending and credits</li>
<li>Finish the level</li>
</ul>
Abandon all hope ye who enter <a href="https://dl.dropboxusercontent.com/u/12755420/Poultron/Day%206/Day%206.html">here</a>. <br />
<ul>
</ul>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-31145425157481728772013-07-20T01:04:00.000+01:002013-07-20T01:06:53.983+01:00Poultron: Day 5<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYq0srivxH7UZiiAcTwUfx-8nL9tQlUYsf9iZNf4FC0UzwkJ_E9W7_34kR35T67KtKaxX48cpgeD3-35iM5ag_5ESIqELSMW5kAXj6LMrF05ajrqepDGb_N0CcAFKLt-dk64alBHWIK_M/s1600/ride.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYq0srivxH7UZiiAcTwUfx-8nL9tQlUYsf9iZNf4FC0UzwkJ_E9W7_34kR35T67KtKaxX48cpgeD3-35iM5ag_5ESIqELSMW5kAXj6LMrF05ajrqepDGb_N0CcAFKLt-dk64alBHWIK_M/s400/ride.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">I just noticed my pilot looks eerily similar to the default minecraft dude</td></tr>
</tbody></table>
<br />
Time's starting to run out! I still have no flying enemies and the level's still mostly empty! That being said, the game now has a menu of sorts and a second robot to choose from.<br />
<br />
<b>Features:</b><br />
<br />
<ul>
<li>An interactive menu and intro sequence</li>
<li>A new robot to fall in love with (not recommended for people with low self-esteem)</li>
<li>LASERS!</li>
<li>Slight graphical tweaks here and there</li>
<li>Wobbly feet</li>
<li>I'm starting to lose track to be honest</li>
</ul>
<br />
<b>Current issues:</b><br />
<ul>
<li>Footstep detection is a bit wonky</li>
<li>We need an endgame </li>
<li>You can hear the tank trying to shoot outside the hangar (will be fixed tomorrow) </li>
</ul>
<br />
<b>Tomorrow:</b><br />
<ul>
<li>Make the level!</li>
<li>Hopefully put in the flying enemy </li>
</ul>
<br />
Embark on an adventure of a lifetime by clicking <a href="https://dl.dropboxusercontent.com/u/12755420/Poultron/Day%205/Day%205.html">this</a> link Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com1tag:blogger.com,1999:blog-2680065526573142835.post-26598326338945561142013-07-18T21:54:00.001+01:002013-07-20T00:57:00.415+01:00Poultron: Day 4<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhNvEASgAXLjQ_6uoojb5A3W-mebjrMRpyU4Rt053HNyCbGb7c7McYqwhgTdVOVrO0oS9_YE-y1baQ95zn-VC5aFgxPVDzKU5UBn_pDstvRVPNI1eaG8nc_j7BPc_WT6gJGVZb2YBuAhA/s1600/pilop.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhNvEASgAXLjQ_6uoojb5A3W-mebjrMRpyU4Rt053HNyCbGb7c7McYqwhgTdVOVrO0oS9_YE-y1baQ95zn-VC5aFgxPVDzKU5UBn_pDstvRVPNI1eaG8nc_j7BPc_WT6gJGVZb2YBuAhA/s320/pilop.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The closest you'll ever be to his pretty face</td></tr>
</tbody></table>
<br />
I tried to go with no health system and I like the results. However, this made me spend most of the day rewriting the projectile system into something a lot more physics-based. I also spent some time polishing up the robot and some other features.<br />
<br />
<b>Features:</b><br />
<br />
<ul>
<li>Enemy bullets can now hit you and will make it harder for you to keep walking</li>
<li>Footstep sounds!</li>
<li>Rate of fire limitations on your own mech (the huge cannon is no longer semi-automatic) </li>
<li>The robot looks 20% cooler and features a tiny pilot (which I might animate if I feel like it)</li>
<li>Dings!</li>
</ul>
<br />
<b>Current issues:</b><br />
<ul>
<li>Footstep detection is a bit wonky</li>
</ul>
<br />
<ul>
</ul>
<b>Tomorrow:</b><br />
<ul>
<li>I might make the "shoot" button a keyboard key if it doesn't make the game too easy. I intended to keep it on the screen as an added challenge.</li>
<li>Maybe make the feet separate parts to make walking seem smoother and more realistic (also should help polish the footstep sounds)</li>
<li>Begginings of robot number 2 (aka hard mode)</li>
<li>Make the menu.</li>
<li>Put flying enemy into the game if we're very lucky </li>
</ul>
<br />
<a href="https://dl.dropboxusercontent.com/u/12755420/Poultron/Day%204/Day%204.html">This link over here</a> should take you on today's adventure. <br />
<br />
<br />
<br />Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-80950117513751649182013-07-17T22:22:00.003+01:002013-07-17T22:29:20.765+01:00Poultron: Day 3<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWh9cguGI7eMgF-Lez7yKVlXl0S83oljs4cEKWs0-GL6YZfSypoI2t3qz4Ama2DLrO-SYCTAdr7aN7W_OglHvIfeoc6bDgJHj1oAOLoTU3LEwNfVr3hAlWaVzXn4yoND-gmnbhbvKTSmM/s1600/biggerGun.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="162" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWh9cguGI7eMgF-Lez7yKVlXl0S83oljs4cEKWs0-GL6YZfSypoI2t3qz4Ama2DLrO-SYCTAdr7aN7W_OglHvIfeoc6bDgJHj1oAOLoTU3LEwNfVr3hAlWaVzXn4yoND-gmnbhbvKTSmM/s400/biggerGun.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">My gun is slightly bigger</td></tr>
</tbody></table>
<br />
<br />
Spent most of the day doing other non-game related things like going to the dentist and such. Despite this I think I made quite a bit of progress. Most of it can be summed up as "cleaning up" the messy code and fixing lesser issues.<br />
<br />
<b>Features:</b><br />
<br />
<ul>
<li>Cool special effects for the bullets!</li>
<li>Graphical tweaks, sort of... Well at least everything should look shinier now .</li>
<li>The tank now runs away from you!</li>
<li>It also shoots back (<span style="font-size: xx-small;">bullets hitting the robot may not actually do anything yet. Batteries sold separately.</span>)</li>
<li>Made the gun mount more "rigid" (it now doesn't wobble every time you shoot). This means it's now harder to use the recoil as an improvised jetpack (sorry) </li>
<li>Did you know the tank had moving tracks? Well now you'll notice they exist.</li>
</ul>
<br />
<b>Current issues:</b><br />
<ul>
<li>THE BULLETS, THEY DO NOTHING. Should I make the mech have a health bar or just make the shots move it back a bit and make it harder to move?</li>
<li>The tank dies in one shot</li>
<li>The tank explosion's effect disappears suddenly. This won't be trivial to fix unfortunately.</li>
<li>Bullets still do nothing when they hit the ground</li>
<li>As you can see from the screenshot, that shell might be slightly bigger than it should </li>
</ul>
<b>Tomorrow:</b><br />
<ul>
<li>Consider implementing a health system or not.</li>
<li>Make a menu?</li>
<li>Tweak the interface?</li>
<li>More graphical tweaks?</li>
<li>Model a flying enemy. </li>
</ul>
As usual, amazing fun awaits thee <a href="https://dl.dropboxusercontent.com/u/12755420/Poultron/Day%203/Day%203.html">here</a>.<br />
<br />Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com1tag:blogger.com,1999:blog-2680065526573142835.post-21090962050322771522013-07-16T21:00:00.001+01:002013-07-16T21:04:09.300+01:00Poultron: Day 2Added a decent sky (from the awesome SkyBox valume 2 found on the Unity store), made a geodesic dome for scenery and decided on going for a WE'RE IN SPAAAACE theme.<br />
<b> </b><br />
I spent most of my day implementing the ballistics system. What I currently have is probably not the best solution but it works.<b> </b>There's bullets, that can collide with level geometry (like the ground, buildings, etc) and there's Hitboxes, that can only collide with bullets. Once a bullet touches anything it checks to see if that object has a hitbox. If it does, it triggers a death effect.<br />
<br />
<b>Features:</b><br />
<ul>
<li>A small tank that walks up to you and says "Hi" (ok, it doesn't really say "Hi" but you get the idea)</li>
<li>Longer legs for the mech (it was hard aiming down and it made the controls a bit easier but not too much)</li>
<li>Bullets that do things</li>
<li>Explosions!</li>
<li>SKY! (the moon was my own personal addition, boy do I feel proud)</li>
</ul>
<br />
<b>Current issues:</b><br />
<ul>
<li>The effects should be tweaked to make them more coherent (and cooler)</li>
<li>Bullets impacting the ground just disappear. This simply cannot do</li>
<li>The poor little tank doesn't fight back</li>
<li>The tank was programmed to keep his distance but that doesn't seem to work</li>
<li>In related news, you can walk right over the tank and nothing happens</li>
</ul>
<b>Tomorrow:</b><br />
<ul>
<li>Fix all the tank issues</li>
<li><b>Maybe </b>make the tank shoot back </li>
<li>Improve the explosion effects (graphics and sound)</li>
<li>More things to prettify the scenery (maybe a small corridor uniting several domes, that would be nice)</li>
</ul>
You may make fun of my accomplishments for the day <a href="https://dl.dropboxusercontent.com/u/12755420/Poultron/Day%202/Day%202.html">here</a>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxv_SPRzdK6IWMTcAnJUGRzq7Yrig2eNd2V6HAHVHJLrMTfdfb5VJN389YEwVDcd-8GUvg4Ol72P2NsaclgrelN1dx0CHq-_XDNoaH_j9B_krkomMe4FlqK6GUJUwZbLKHV4imLrBWJHc/s1600/tank!.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxv_SPRzdK6IWMTcAnJUGRzq7Yrig2eNd2V6HAHVHJLrMTfdfb5VJN389YEwVDcd-8GUvg4Ol72P2NsaclgrelN1dx0CHq-_XDNoaH_j9B_krkomMe4FlqK6GUJUwZbLKHV4imLrBWJHc/s320/tank!.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">I modelled it after a Panther and a Leopard 2.</td><td class="tr-caption" style="text-align: center;"><br /></td></tr>
<tr><td valign="top">Yes I'm aware only tank geeks will know what those are.</td><td valign="top"><br /></td></tr>
</tbody></table>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-70100100789897360222013-07-15T20:57:00.003+01:002013-07-16T21:00:40.964+01:00Poultron: Day 1I expected to have more done in the first day but all thing's considered it wasn't that bad.<br />
<br />
You can move the little robot around and shoot. It's still a bit glitchy and I'm not sure if I'll be able to iron out all the kinks without churning out my own physics system.<br />
<br />
<b>Features:</b><br />
<ul>
<li>Walking!</li>
<li>Shooting with animations and recoil</li>
<li>Screen shakes if you hit the ground going too fast</li>
</ul>
<br />
<b>Current issues:</b><br />
<ul>
<li><strike>Sometimes the foot gets stuck in an awkward position and we have to lift it up again.</strike> (should be fixed now)</li>
<li>Nothing to do besides walking</li>
</ul>
<b>Tomorrow:</b><br />
<ul>
<li> Stuff to shoot! (can't promise any AI)</li>
<li>More things to prettify the scenery</li>
<li>A decent sky I hope</li>
</ul>
Click <a href="https://dl.dropboxusercontent.com/u/12755420/Poultron/Day%201/Day%201.html">here</a> if you're feeling brave and want to see how it plays out.Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-41057189641301016132013-07-15T16:20:00.000+01:002013-07-15T17:18:52.254+01:00Poultron: IntroTo unwind a bit from working on Brian Storm for almost a year, the guys at Titan Forged Games decided to do a small one-week (starting today) game jam with the least busy members of the team. It was originally meant to be one artist and one programmer but due to the intricacies of fate I now find myself alone working on a small prototype I call Poultron.<br />
<br />
<h3>
But what is Poultron?</h3>
Let's start with where the idea came from. For some reason I was thinking of Power Rangers and realized it must have been hard to have each person in the team control a different part of the robot. I imagined it would be something like multiplayer <a href="http://www.foddy.net/Athletics.html">qwop</a>.<br />
Obviously such an idea can't go to waste. I quickly wrote up a small story (I'm weird like that):<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">The peaceful people of the planet Pa'inis realized the universe was eventually going to be attacked by an evil empire of anthropomorphic aliens (and by anthropomorphic I mean humans with a slightly blueish skin, but that's beside the point here). In order to defeat them they did what an ancient people focused on saving the universe usually do: build a huge modular robot which has to be assembled by different parts, each driven by a different teenager.</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">Soon, the rest of the universe followed suit and built there own robots just in case. </span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">Eventually the evil guys came (they were pink) and the defence robots were activated. However by this point no one was entirely sure which parts belonged to which robot. Not to mention teenagers are not famous for their driving skills...</span></blockquote>
<br />
Eventually I found myself with no artist and had to lower my expectations: instead of a friendship crushing game I would have to settle for single player one (as I had no one to play with for every iteration I made).<br />
<br />
<h3>
The art style (or lack thereof) </h3>
While the decision to make this single-player (for now) fixed some of my immediate concerns, this still left me with another problem: the art style. I'm a <strike>programmer</strike> guy that writes code, not an artist. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYR2RZ1EtXWUnO9H9zGuqIuAOxughq-0qj2-WdkMLE384oHo_JS-sOtBZA6J6GynInGSABcP-JMmH9ZdVumjLKRnmVRuAtoIQDspZrUGOIFPlw9OUM8rJ140qQkC6RarozPW9beHn3a9k/s1600/20062013617.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYR2RZ1EtXWUnO9H9zGuqIuAOxughq-0qj2-WdkMLE384oHo_JS-sOtBZA6J6GynInGSABcP-JMmH9ZdVumjLKRnmVRuAtoIQDspZrUGOIFPlw9OUM8rJ140qQkC6RarozPW9beHn3a9k/s320/20062013617.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">As you can see, this proves I'm indeed a programmer</td></tr>
</tbody></table>
<br />
I started doing some sketches (slightly better than the one above) when it hit me: I could try going for an intentionally bad "made of paper" look for the whole game. I mean the whole idea was to make goofy looking robots doing goofy things. It took me around 5 entire seconds to sketch the parts of a robot and a couple of hours to crop the pieces, build some 2D shaders and put it together. <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivG89mDNJoFsizs6D-hf2ETa_BYKzsaJi7HyVcObI6HDTl5PIe58_QXxMJMsaLEi0dRmmzfTEsuzWV9x5_VXe_r4JC9orLb3CyONFaZrI2wjrIRshFYRwA9IVkajt5_D8hJNY8-ftw7hA/s1600/papertest.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="319" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivG89mDNJoFsizs6D-hf2ETa_BYKzsaJi7HyVcObI6HDTl5PIe58_QXxMJMsaLEi0dRmmzfTEsuzWV9x5_VXe_r4JC9orLb3CyONFaZrI2wjrIRshFYRwA9IVkajt5_D8hJNY8-ftw7hA/s320/papertest.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">OH GOD KILL ME NOW</td></tr>
</tbody></table>
This led to some other problem: if the mech was made of paper this would lead to some expectations that the universe would be entirely made of paper: soon I had a grid paper sky, with paper menus that floated away softly when you clicked on them and... That was it. I had no idea where to keep going with the paper motif. How could I make firing a projectile interesting without non-papery particle effects? When I was testing out hit sounds nothing felt natural - I couldn't just pretend the robot was a huge construction made of steel when the player could clearly see it was made out of pieces of paper.<br />
<br />
<br />
So I went back to the drawing board and settled on another approach: I am fairly decent at making 3D models and animation but I suck at texturing. Maybe I can get by with a plastic-y/cartoonish look without too much effort.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLhm-gq-3JWl1oo3fYyfIrYpJsm1_GrRMAu1Oo4xWA3WnpGWdf_HpRixjhPLd4sebw3TDOM-Gs3zyo-F-sEwmqqZyTdfiDjAaxIU3ucUlEHW6191D__-Ggckeel44AoWRA9aEGwdErMjY/s1600/pretty.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="261" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLhm-gq-3JWl1oo3fYyfIrYpJsm1_GrRMAu1Oo4xWA3WnpGWdf_HpRixjhPLd4sebw3TDOM-Gs3zyo-F-sEwmqqZyTdfiDjAaxIU3ucUlEHW6191D__-Ggckeel44AoWRA9aEGwdErMjY/s320/pretty.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Hopefully by the end of the day this thing will be doing things already</td></tr>
</tbody></table>
Despite looking like the least practical design ever, it will probably the easiest robot you'll be able to pilot in Poultron :)Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com1tag:blogger.com,1999:blog-2680065526573142835.post-21953807441205369162013-04-06T18:49:00.004+01:002013-04-06T19:12:18.035+01:00Unity3D Version control with Dropbox and Mercurial<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;">After a few months I think we're ready to share our Unity3D (free) version control setup. Keep in mind this is not ideal and it was designed to hack some sort of code tracking into the free version of Unity. We are using mercurial but there isn't (shouldn't be) any reason it wouldn't work with any other type of version control system. <b>Always be aware you shouldn't have more than one person editing the files that are not on your VCS. </b></span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;">I'll assume everyone reading this has a basic knowledge on Mercurial and Aliasing/Symlinking and go straight to the point. If you need anything more specific feel free to comment and I'll consider adding it.</span><br />
<span style="font-size: small;"><br /></span>
<br />
<h3>
<span style="font-family: Verdana,sans-serif; font-size: small;">
The concept:</span></h3>
<span style="font-family: Verdana,sans-serif; font-size: small;">There's 2 types of files in our project: binaries which we don't/can't synchronize (Unity Pro and the asset server solves this somewhat) and code (text) files. We don't want to do version control for binary files. Let's begin by putting all our binary files into a separate folder. This is what our project's hierarchy looks like:</span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Verdana,sans-serif; font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_WgbgHkwtaBDDPWUOL6wrh8Gv6aEg8xqHT-Km-3zkR4bsYDMRRHCHSnyiAsmHGAnedFfiKMlptTEv-tMl0TO8cJ9VGbKRsCvHs5-6grcN4Z6URzXwlqFXd1DiGRXozdQ2M6D0MNqo-d4/s1600/hierarchy.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_WgbgHkwtaBDDPWUOL6wrh8Gv6aEg8xqHT-Km-3zkR4bsYDMRRHCHSnyiAsmHGAnedFfiKMlptTEv-tMl0TO8cJ9VGbKRsCvHs5-6grcN4Z6URzXwlqFXd1DiGRXozdQ2M6D0MNqo-d4/s320/hierarchy.PNG" width="209" /></a></span></div>
<h3>
<span style="font-size: small;">
<span style="font-family: Verdana,sans-serif;">
</span></span></h3>
<h3>
<span style="font-family: Verdana,sans-serif; font-size: small;">Setup:</span></h3>
<span style="font-family: Verdana,sans-serif; font-size: small;">First thing's first, launch your project and go to <span style="font-family: "Courier New",Courier,monospace;">Edit->Project Settings-> Editor</span>. In the inspector change the version control mode to meta files and Asset Serialization to Mixed mode. This means from now on all the data on your Prefabs, materials, scripts, etc will be store in .meta files in their respective folder instead of clumped up in the Library folder.</span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Verdana,sans-serif; font-size: small;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7AB_mqbWW-JpmFCQqUILO3-zg9hSEM40DJVPLNQ9ywIlS0O1PpKScgjI1N0ORqJgh6zXrwBL6Qk4Jd0EPAjgOYgfeXCh7Wk_wAWOdIh9mRLUPq5hRHMDrWElET-H4D9lm15NRkCoAYhQ/s1600/editorsettings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7AB_mqbWW-JpmFCQqUILO3-zg9hSEM40DJVPLNQ9ywIlS0O1PpKScgjI1N0ORqJgh6zXrwBL6Qk4Jd0EPAjgOYgfeXCh7Wk_wAWOdIh9mRLUPq5hRHMDrWElET-H4D9lm15NRkCoAYhQ/s320/editorsettings.png" width="320" /></a></span></div>
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;">Basically we just shove everything that's not a text file into the Binaries folder. Close unity, take this folder and put it's contents into a Dropbox folder (we'll be using </span><span style="font-family: Verdana,sans-serif; font-size: small;"><span style="font-family: Verdana,sans-serif;"><code>"\Titan
Forged Games\Brian Storm\Unity Project\Assets\Binaries").</code></span></span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;">Create the repository. This is the contents our .hgignore file (aka the files and folders our repository should ignore):</span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace; font-size: small;">syntax: glob</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> Library/</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> Temp/ </span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> Assets/Binaries</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"><br /></span><span style="font-size: small;">
<span style="font-family: "Courier New",Courier,monospace;"> *.userprefs </span></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> *.pidb</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> *.unityproj</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> *.csproj</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> *.asset</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> *.cache</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"><br /> Assembly-CSharp-vs.csproj </span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> Assembly-CSharp.csproj</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> ourProjectNameGoesHere.userprefs</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"><br /> *.orig</span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"> *.orig.meta</span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;"><b>The Library folder should never be synced.</b> Doing so is a recipe for disaster. It has local data regarding the project and will always be regenerated based on the .meta files. The library folder will ALWAYS be unique for every person so DON'T even try to sync it and always make sure it's not being shared (we almost lost an entire project due to a silly mistake with the Library folder being corrupted on a single machine).</span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;">The rest of the list exists mostly to keep useless binary data or personal preferences from our repository. The .orig are files generated by mercurial if you wish to store backups of files before a merge operation - feel free to ignore that line (it's just personal preference).</span><br />
<h2>
<span style="font-size: small;">
<span style="font-family: Verdana,sans-serif;"><b><span style="font-weight: normal;">
<b> </b></span></b></span></span></h2>
<h3>
<span style="font-family: Verdana,sans-serif; font-size: small;"><b><span style="font-weight: normal;"><b>How to use it:</b></span></b></span></h3>
<span style="font-family: Verdana,sans-serif; font-size: small;">Clone the repository.</span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;">Create a symlink (or shortcut) for the binary files in the Dropbox folder<i>.</i></span><br />
<span style="font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;">In our most current project we're using the dropbox folder <i>"Titan Forged Games\Brian Storm\Unity Project\Assets\Binaries"</i> to "place" binaries into our repo's <i>"Assets\Binaries"</i></span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;">On windows 7 (and 8) you can launch the command console and type: <code>mklink
/J "YOUR REPO PATH\Assets\Binaries" "C:\Users\YOUR NAME\Dropbox\Titan
Forged Games\Brian Storm\Unity Project\Assets\Binaries"</code></span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /></span>
<span style="font-family: Verdana,sans-serif; font-size: small;">From now on, everything that is on <span style="font-family: "Courier New",Courier,monospace;"><code>"C:\Users\YOUR NAME\Dropbox\Titan
Forged Games\Brian Storm\Unity Project\Assets\Binaries" will be identical to </code></span></span><br />
<span style="font-family: "Courier New",Courier,monospace; font-size: small;"><code>"YOUR REPO PATH\Assets\Binaries"</code></span><br />
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /><code><code></code></code></span>
<br />
<h3>
<span style="font-family: Verdana,sans-serif; font-size: small;">Notes:</span></h3>
<ul>
<li><span style="font-family: Verdana,sans-serif; font-size: small;">Don't ignore the newly created .meta files when commiting a new code file. They are what allows Unity to know if your GameObjects use a certain script (otherwise you'll just get missing script Errors on GameObjects that use them).</span></li>
<li><span style="font-family: Verdana,sans-serif; font-size: small;">When testing things out and doing drastic changes it's best to avoid people tweaking an editor scene (besides not being able to work on the same scene at the same time, it's also likely he's messing with inspector attributes that will no longer exist once you commit your code).</span></li>
<li><span style="font-family: Verdana,sans-serif; font-size: small;">The silly mistake I mentioned earlier deleted all our binaries on the dropbox folder. Don't be silly and do regular backups of the Binaries - in fact, just backup your entire project once in a while, you'll be thankful for it some day.</span> </li>
</ul>
<span style="font-family: Verdana,sans-serif; font-size: small;"><br /><code><code></code></code></span>Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-22205483285736915082012-10-17T19:27:00.000+01:002012-10-17T19:33:47.176+01:00Just a little side project<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.blogger.com/blogger.g?blogID=2680065526573142835" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
Here's something I'm working on as a side project to Brian Storm.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQsFM9UWi88MUwFmzmQtoCcR_dvSvAMqt2sGhc7gpTRix6_DTvqI2MAJh3JrXuqhyxVkYNEGp9UPoV89FSpAaLwQS01qEzQOpQQcmhTjxE8bUA4IONiBkMYrbwLBQ9W8EYyCpxGk41v48/s1600/screenshot1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQsFM9UWi88MUwFmzmQtoCcR_dvSvAMqt2sGhc7gpTRix6_DTvqI2MAJh3JrXuqhyxVkYNEGp9UPoV89FSpAaLwQS01qEzQOpQQcmhTjxE8bUA4IONiBkMYrbwLBQ9W8EYyCpxGk41v48/s400/screenshot1.png" width="400" /></a></div>
<br />
As awesome as things like <a href="http://forum.unity3d.com/threads/102511-HexTech-Hexagon-Tile-Based-Map-Framework-available-on-Asset-Store">Hextech</a> are, I'm afraid I don't have the 100$ to dish out for it so I'm building my own hex grid framework from scratch. Currently on the lookout for intuitive ways to access the grid's tiles through XY coordinates - there's got to be something more efficient than Bi-dimensional arrays.Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0tag:blogger.com,1999:blog-2680065526573142835.post-88765907452179604662012-08-25T18:01:00.003+01:002012-08-25T21:01:19.714+01:00Level workflow in Brian StormHere's how we're currently doing our Blender-Unity3D level design workflow for the Brian Storm project. This is a result of several experiments we've done and our experience with level design. We're open to suggestions and if you're trying it out yourself and have some doubts on how it's done, feel free to ask me.<br />
<br />
This is meant to be short and isn't a Blender or Unity3D tutorial of any sort. Though I might go more in depth later if there's a demand for it. <br />
<br />
Also, keep in mind none of these images contain final art and are mostly placeholders while we programmers are still figuring things out.<br />
<br />
<br />
<h2>
Here we go</h2>
First we make a level segment: some geometry for the player to see and some collision meshes.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgakash_JI5RG9Lf5ILhh33akhuvu_5QKysQL_RcBidhuAJRO1CnLX7-5Cgwk-HBpZa_PV1ubnbgE-UUDLdEtAVuFLoZbDa9oITGpWx5zO1EdURHYKs7eEW5-ZI9QTLMwUoktLRjkrUnfE/s1600/singleobject.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="260" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgakash_JI5RG9Lf5ILhh33akhuvu_5QKysQL_RcBidhuAJRO1CnLX7-5Cgwk-HBpZa_PV1ubnbgE-UUDLdEtAVuFLoZbDa9oITGpWx5zO1EdURHYKs7eEW5-ZI9QTLMwUoktLRjkrUnfE/s320/singleobject.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The actual mesh we see and it's collision mesh, shown in wireframe</td></tr>
</tbody></table>
<br />
We make sure to add "_collision" to the collision meshs' name. I'll explain this in more detail later on.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxf02tG-PG173HvI_S53B-OlPtMMVC70z3HkwfA1ueffuRJ8hyvYCx2GyE20HR_Py9SNMplYnXwjy8C15tcnezAj7Z5_BG35hFFNcqM-tcciKjW7rW8D7b0Gw0wf2n1wJO0Ma2Imxahgo/s1600/objects.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxf02tG-PG173HvI_S53B-OlPtMMVC70z3HkwfA1ueffuRJ8hyvYCx2GyE20HR_Py9SNMplYnXwjy8C15tcnezAj7Z5_BG35hFFNcqM-tcciKjW7rW8D7b0Gw0wf2n1wJO0Ma2Imxahgo/s1600/objects.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">_collision just means the mesh is just a collision and should not be rendered.</td></tr>
</tbody></table>
<br />
<br />
We then put both types of geometry into the same group. Usually we use the file's name for consistency's sake.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3w-geyAw-cfsx_9VrFLNkPUw05kpMrNZD-6gTREx6BvPV1zC5QRUNq6JbFQ5cpEQNRWF8LJW0TtBk_drn008Gfj0G_w_TVWUxNO6L4_CtsYxLlbxntq2XY-rpYVwDUuDW8plwJ1li8Vc/s1600/groups.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3w-geyAw-cfsx_9VrFLNkPUw05kpMrNZD-6gTREx6BvPV1zC5QRUNq6JbFQ5cpEQNRWF8LJW0TtBk_drn008Gfj0G_w_TVWUxNO6L4_CtsYxLlbxntq2XY-rpYVwDUuDW8plwJ1li8Vc/s1600/groups.png" /></a></div>
<br />
We then create a level.blend file which appends (links) the groups in the other files as building blocks to create the level.<br />
<br />
<b>Tip:</b> if you hide a mesh in it's original file, it will stay hidden after you import it. Very useful if you don't want to see your collision meshes while previewing the level here. <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEfcaY7WAvBlls2x3bSbn6-kbgrBkWLyIzv67R0b0tqYV9tBdUtkA30HuSPsIK6xKHXs-oUlWKLhrWZD5F4PZ7Eas8hGE1JUitvhj6E2RJIFx-B83o0mndX3wrAZssT9YmRQpQQHt1qE8/s1600/level.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEfcaY7WAvBlls2x3bSbn6-kbgrBkWLyIzv67R0b0tqYV9tBdUtkA30HuSPsIK6xKHXs-oUlWKLhrWZD5F4PZ7Eas8hGE1JUitvhj6E2RJIFx-B83o0mndX3wrAZssT9YmRQpQQHt1qE8/s400/level.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Two LongCorridors making up a longer corridor</td></tr>
</tbody></table>
<br />
Now we just import level.blend directly on our Unity scenes and all the meshes linked in it are correctly presented in our level. However, we have no collision yet - adding it manually would be a lot of work for levels of even smaller sizes.<br />
<br />
A custom script, extended from <a href="http://docs.unity3d.com/Documentation/ScriptReference/AssetPostprocessor.html">AssetPostprocessor</a> checks if we're importing a "level" file. We then go through every GameObject that we imported and check if it's name contains "_collision" - in which case we remove it's renderer and create a mesh collider for it using it's own mesh.<br />
Another option we have so far is "_canhide", which adds a box collider to the mesh and configures it in such a way that it can be hidden if it obstructs the player's view.<br />
<br />
We then use the Unity3D editor to add waypoints (paths our characters follow during gameplay),
along with other extras we didn't import from the blender file and we're
set.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgzEEOI2h5B-gyvRI865UuP4kRYyt6MVBP2-xm650Y6W4HBUDltD0JmHHNii0V6usN3f3ecz2dImMKRiECPWnDQGY9dzeweRuHA4vMPclqDbvVDgJqo8mvsr8pRqyTSyRBSSIhtDDVD6k/s1600/unity.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgzEEOI2h5B-gyvRI865UuP4kRYyt6MVBP2-xm650Y6W4HBUDltD0JmHHNii0V6usN3f3ecz2dImMKRiECPWnDQGY9dzeweRuHA4vMPclqDbvVDgJqo8mvsr8pRqyTSyRBSSIhtDDVD6k/s400/unity.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">VoilĂ , a complete placeholder level</td></tr>
</tbody></table>
<br />
<br />
<h2>
Issues</h2>
Here's some concerns we have with this method:<br />
<ul>
<li>Waypoints have to be setup after importing the level. We should find a way to automate this as it get's very annoying to update huge clusters of waypoints after even slight changes to level layout.</li>
<ul>
<li>The same is valid for enemies, player start position, checkpoints, lighting and other non-geometry objects </li>
</ul>
<li>Having the level split up in "blocks", each with their own collision meshes might make the game suffer performance wise.</li>
</ul>
<br />
<b>Note</b>: We disabled importing of animations for the level file, as unity has some issues with Default takes on Blender. <br />
<ul>
</ul>
Crushyhttp://www.blogger.com/profile/12917335562719142065noreply@blogger.com0