tag:blogger.com,1999:blog-52552865246252771612024-03-05T07:56:29.647-08:00Byte56 GameDevAnonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.comBlogger56125tag:blogger.com,1999:blog-5255286524625277161.post-84528243148041857462016-05-12T21:35:00.000-07:002016-05-12T21:35:55.736-07:00It's time to admit itIt's been a long time since I made any changes to Age of Goblins. The original Java code has gone untouched for three years. Code shouldn't be left in dark places too long. So I'm opening up the source for anyone to view. This is essentially the very beginning of a game with a custom engine that's not finished. Granted, this isn't something someone can just pick up and start using as-is, however, there are a lot of little and medium sized features that could be great for someone wanting to get started or learn how they don't want to code their features.<br />
<br />
<ul>
<li>Generating and manipulating a (cube) voxel terrain, built in chunks</li>
<li>Voxel lighting system, with static shadows</li>
<li>Entity component system</li>
<li>Entities defined in data files</li>
<li>3D pathfinding</li>
<li>Water ebb and flow simulation</li>
<li>A job system</li>
<li>Animation system that imports Blender animations with bone data</li>
<li>UI system</li>
<li>Camera system with in-world picking of objects</li>
<li>A screwy physics system that I eventually gave up on</li>
<li>And much more, it's been three years, I don't remember it all</li>
</ul>
<div>
So... Yes, this version of AOG is dead. I can't dedicate enough time or passion to writing my own engine in Java. I still have a faint hope that I'll continue work on the space game set in the same universe. Time will tell.</div>
<div>
<br /></div>
<div>
Find the source here:</div>
<div>
<br /></div>
<div>
<a href="https://bitbucket.org/byte56/age-of-goblins/">https://bitbucket.org/byte56/age-of-goblins/</a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
If you do end up using any of this, or find it useful, please let me know! I'd love to hear about it. If you have questions, I'll try to answer them as well.</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoxpRwyL8LXaPqsRdpuLqpVzl1VL7C_QZlcbuCqkFLhvxpsA0Lu-ZaqK1e3pei3NN5aFy7kUCatvoJYzzhfv2tc7iFZXG0zNnL9NBZfHT4oWNsf1RW5mx4tH6Ic1AhIrWkqeHIk4-7s1c/s1600/appletree_leaves_billboards.PNG" imageanchor="1"><img border="0" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoxpRwyL8LXaPqsRdpuLqpVzl1VL7C_QZlcbuCqkFLhvxpsA0Lu-ZaqK1e3pei3NN5aFy7kUCatvoJYzzhfv2tc7iFZXG0zNnL9NBZfHT4oWNsf1RW5mx4tH6Ic1AhIrWkqeHIk4-7s1c/s320/appletree_leaves_billboards.PNG" width="320" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipg7oIpqeRHkp4kOjoDT8RMUxlDhyphenhyphen6abTDKvGkO0_3IJVitA2MCoVvvhU2zGXrhX3CsOISeqYgj3xtgEIxmIuzKobR416RMYn68P6WWRV1aC048x31RQ9boM-Xo1b_COwIe1EcJ7-HxUE/s1600/activationzone.PNG" imageanchor="1"><img border="0" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipg7oIpqeRHkp4kOjoDT8RMUxlDhyphenhyphen6abTDKvGkO0_3IJVitA2MCoVvvhU2zGXrhX3CsOISeqYgj3xtgEIxmIuzKobR416RMYn68P6WWRV1aC048x31RQ9boM-Xo1b_COwIe1EcJ7-HxUE/s320/activationzone.PNG" width="320" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigOCjCyuGtvaelWLdW6N3C3xbtoOt2Akuq2EhBhUkCXiNTRRdEdnDIWPu9r-84FHDBCkTbes-xb55tiSDyGqFVDGcHPPPvndD8PLg35lhMtEdgBLMh5erOKD-OigGbaEiyGYbjifMSBUA/s1600/Pathing.png" imageanchor="1"><img border="0" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigOCjCyuGtvaelWLdW6N3C3xbtoOt2Akuq2EhBhUkCXiNTRRdEdnDIWPu9r-84FHDBCkTbes-xb55tiSDyGqFVDGcHPPPvndD8PLg35lhMtEdgBLMh5erOKD-OigGbaEiyGYbjifMSBUA/s320/Pathing.png" width="320" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhphTclgxGUiuIobZBLMEWLeFnPNfxC-KlBnQO6TrtHlkE_VrH4eZjcaxodTsT63vmVyRt3c2A3cjYw0HaCPC82lLRbBzIpViMZ4g2C8SsSl0By5_bRLuL-FAFxA9oejWPiDDWUkuSKTEk/s1600/materialInWorld.PNG" imageanchor="1"></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_FuJF26TK-gdfpKRyeHLwLWtsTpA8FC4u3T-HL_RAqnhKq0FQqb96h8tv-XuGLMdDKFpDoJRvwMCh-wcaRw956DPyIRkJVXK0hSX17Y-ERlzB0UbFl83DsemCzTYMg1a2CVEPkEtqp2M/s1600/updatedBounds.PNG" imageanchor="1"><img border="0" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_FuJF26TK-gdfpKRyeHLwLWtsTpA8FC4u3T-HL_RAqnhKq0FQqb96h8tv-XuGLMdDKFpDoJRvwMCh-wcaRw956DPyIRkJVXK0hSX17Y-ERlzB0UbFl83DsemCzTYMg1a2CVEPkEtqp2M/s320/updatedBounds.PNG" width="320" /></a><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhphTclgxGUiuIobZBLMEWLeFnPNfxC-KlBnQO6TrtHlkE_VrH4eZjcaxodTsT63vmVyRt3c2A3cjYw0HaCPC82lLRbBzIpViMZ4g2C8SsSl0By5_bRLuL-FAFxA9oejWPiDDWUkuSKTEk/s400/materialInWorld.PNG" /></div>
Michael Househttp://www.blogger.com/profile/02922597342361194456noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-50808012513758808492014-06-11T15:18:00.000-07:002014-06-11T15:18:37.139-07:00Unity3D programming courseI created a course on <a href="http://www.lynda.com/Unity-3D-tutorials/Advanced-Unity-3D-Game-Programming/160270-2.html?utm_medium=ldc-partner&utm_source=SSPRC&utm_content=524&utm_campaign=CD15496&bid=524&subID1=blog&aid=CD15496">Unity3D game programming</a>! Check out the intro video:<br />
<br />
<iframe allowfullscreen="true" frameborder="0" height="315" mozallowfullscreen="true" scrolling="no" src="https://www.lynda.com/player/embed/177237?fs=3&w=560&h=315&ps=paused&utm_medium=referral&utm_source=embed+video&utm_campaign=ldc-website&utm_content=vid-177237" webkitallowfullscreen="true" width="560"></iframe><br />
<br />Michael Househttp://www.blogger.com/profile/02922597342361194456noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-46876682911486455322014-02-16T21:19:00.000-08:002014-02-16T21:19:07.443-08:00Entity system differencesI was recently posed the question: <br />
<br />
<blockquote>In your opinion, what are the biggest advantages of system-driven entity component system (as described in <a href="http://gamedev.stackexchange.com/a/31491/7191">your answer here</a>) as opposed to putting logic right into components themselves (similar to how Unity does things)?</blockquote><br />
The advantages depend on the requirements of the game. The two styles are pretty similar really, so the biggest advantages are going to derive from personal style preferences. <br />
<br />
The main differences I can see are when and where things get processed. With the system approach, you know that processing will take place grouped by component type. With the Unity approach, processing will take place by entity. For example, a simple set of entities (E1 and E2) with their components:<br />
<br />
E1: C:Movement, C:Pathfinding, C:Attack<br />
E2: C:Movement, C:Pathfinding, C:Attack<br />
<br />
With Unity the overall processing order might look like:<br />
<br />
E1:C:Pathfinding<br />
E1:C:Movement<br />
E1:C:Attack<br />
---<br />
E2:C:Pathfinding<br />
E2:C:Movement<br />
E2:C:Attack<br />
<br />
Notice everything grouped by the entity. With a system like the one described in my answer everything would run grouped by system:<br />
<br />
E1:C:Pathfinding<br />
E2:C:Pathfinding<br />
---<br />
E1:C:Movement<br />
E2:C:Movement<br />
---<br />
E1:C:Attack<br />
E2:C:Attack<br />
<br />
So in the end, the same code gets run, but the order is different. While Unity does have some features to change the order, like using Update() vs LateUpdate(), it's not going to group things by components for all entities.<br />
<br />
As I said, the advantages of changing the order really depend on the requirements of the game. In a lot of cases, the design of a game could easily be adapted to work with either system. So when designing your own system, it's important to keep these differences in mind and make the design work appropriately for your style.<br />
Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com4tag:blogger.com,1999:blog-5255286524625277161.post-78600172551097183342013-10-01T08:03:00.001-07:002013-10-01T08:03:49.063-07:00Overview of basic features in AoG: New Korbly<div xmlns='http://www.w3.org/1999/xhtml'>See my latest video <a href='http://www.youtube.com/watch?v=cBJsfl96UNc'>here</a> or watch below. <object height='350' width='425'><param value='http://www.youtube.com/v/cBJsfl96UNc&feature=youtube_gdata_player' name='movie'/><br /><param value='transparent' name='wmode'/><br /><embed height='350' width='425' wmode='transparent' type='application/x-shockwave-flash' src='http://www.youtube.com/v/cBJsfl96UNc&feature=youtube_gdata_player'/> </object> Showing some of the basic features now implemented in Age of Goblins: New Korbly. Ship construction, energy management, module destruction, module physics and the ship FTL.</div>Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com1tag:blogger.com,1999:blog-5255286524625277161.post-20303821170844088762013-10-01T07:27:00.001-07:002013-10-01T07:27:14.819-07:00Ship modules breaking off<div xmlns='http://www.w3.org/1999/xhtml'>See my latest video <a href='http://www.youtube.com/watch?v=EZaczLyae6M'>here</a> or watch below. <object height='350' width='425'><param value='http://www.youtube.com/v/EZaczLyae6M&feature=youtube_gdata_player' name='movie'/><br /><param value='transparent' name='wmode'/><br /><embed height='350' width='425' wmode='transparent' type='application/x-shockwave-flash' src='http://www.youtube.com/v/EZaczLyae6M&feature=youtube_gdata_player'/> </object> An oddly configured ship, but it shows that you have to be a little careful not to blow yourself up and it shows modules breaking away from a ship then interacting with it.</div>Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-40918395285585126712013-08-11T19:56:00.000-07:002013-08-11T19:56:00.333-07:00A tangent demoAbout a month ago I wrote about a development tangent with a working title of <a href="http://www.byte56.com/2013/07/a-development-tangent.html" target="_blank">AoG: New Korbly</a>. Today I have a demo for you to try out. Starting from the fresh start at the refactor, this represents a little over a month of very part time work.<br />
<div>
<br /></div>
<div>
Multiplayer basics are in place, but it didn't get a lot of attention, so it's not quite ready to show off. We'll aim for that on the next demo. This demo has basic ship building, power management, radar and various other little features. We'll continue to improve on the game as long as it's of interest and as long as enough people are interested. Likely releasing a new demo when new features are introduced.</div>
<div>
<br /></div>
<div>
Without further ado, <b><a href="http://ageofgoblins.com/newkorbly/Web.html" target="_blank">the demo</a></b></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://ageofgoblins.com/newkorbly/Web.html" target="_blank"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo4WDE_mbEw-7ZT_6V5v8dhpPUecjX1rOpAP7Y-C5nlhnU7jvqkc5PDRe1XNmFOV-G7ycBC2Il7fl8KmR7e25eE0REJvpFwzuVAO14vme_vJ8iRRhoX4lFwyl7IA5Z_9y_xHQRkAt2UJk/s400/Capture.PNG" /></a><span id="goog_1527479657"></span><span id="goog_1527479658"></span><a href="http://www.blogger.com/"></a></div>
Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com3tag:blogger.com,1999:blog-5255286524625277161.post-85428064845913542062013-07-09T16:56:00.000-07:002013-07-09T16:56:04.283-07:00A development tangentConfession: For the last month or so I haven't been working on Age of Goblins. But don't worry! It's not dead or anything like that. I'm just taking some time to explore some other technologies and prototype a different game I've been thinking about. I got into game development to learn about the technologies and create fun things. Plus, I've had this idea for a game I thought might be a little easier to make good progress on in a short amount of time. After a few years of AoG, I needed the rush of new development :)<br />
<br />
I've been working on the prototype with another has-a-full-time-job-and-does-game-dev-on-the-side guy, Seth Battin (of <a href="http://itsobviously.com/pbaction/" target="_blank">PBAction</a> fame). Seth and I are both learning <a href="http://unity3d.com/" target="_blank">Unity3D</a> while developing this prototype. Since we dove into the project without much knowledge of Unity, we're currently doing a bit of a refactor to apply what we learned about how Unity works. Seth is a bit busier than me so he doesn't have as much time as I do, but it's been great just having someone else to bounce ideas off and check my work (I'm sure he'll check something in eventually). It's also nice experience for learning to work with someone remotely, which I haven't done much of in my career.<br />
<br />
The game we're making is a top down space game (3D rendered on a 2D plane of play). Players can build their own ships by snapping components together. For example, adding a bridge component and putting control thrusters on either side is enough to complete a small ship. Player space stations can be built in the same way. Ship and station components can be salvaged by trade, construction from raw materials or salvage (of existing wrecks or ones the player creates). See the "user story" below to see what the gameplay may be like:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGZDQ3-7qMy94L8HBnHAJL14tnwCscOECYU7E0XFyB7gyqhIrvG56hN-TiXQzs2taVPjhHLvBlfmU9Pavl2Wu1VL-b64B0PwcG3psmQD9HyLXyK0B4GuUVgno22HT93UuB6yUB8g-2ahk/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGZDQ3-7qMy94L8HBnHAJL14tnwCscOECYU7E0XFyB7gyqhIrvG56hN-TiXQzs2taVPjhHLvBlfmU9Pavl2Wu1VL-b64B0PwcG3psmQD9HyLXyK0B4GuUVgno22HT93UuB6yUB8g-2ahk/s1600/Capture.PNG" /></a></div>
<br />
<center>
<i><span style="font-size: x-small;">The numbered lists show different outcomes available.</span></i></center>
<br />
It's also <i>multiplayer. </i>I've never attempted a multiplayer game before (except "local" multiplayer), so it'll be an interesting experience. It also sounds like a super fun game to play with other people. Further grand plans include seamless landing on planets for resource collection/trade (space elevator delivery), somewhere from arcade to real-ish physics (needs playtesting) and space factories (for making ship components, not space). How much of that will get done? Who knows. It depends on how interested people are, how interested Seth and I are and who wants to give us a million dollars to make it.<br />
<br />
Interestingly, the game is actually set in the same universe as AoG. I don't have all the details yet, so I'll just leave it at that. Well, just one hint, the working title of the game is <b>AoG: New Korbly</b>. There will be a story for the game, but it'll likely be a loose story line, with open ended play.<br />
<br />
One thing I can say about Unity, after spending a few years building almost everything myself for Age of Goblins, it's been exciting to actually get to focus on<i> making a game</i>. Even after so long working on AoG, I'm still working on the engine. Let that be a lesson to all of you wanting to start making a game: Use a premade engine! Yes, I've learned a great deal about engine development in the last few years, but I have a lot more fun making games than engines.<br />
<br />
Within the next few weeks I'll post a demo up here of the prototype. (It's crazy easy to publish to the web with Unity). Feedback welcome.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com4tag:blogger.com,1999:blog-5255286524625277161.post-11150848141908092802013-05-14T09:56:00.000-07:002013-05-16T07:55:04.098-07:00The uphill physics pushI've been working on (and sometimes avoiding) physics improvements in AoG. I wanted to start turning on physics for more entities. I've had physics implemented for material blocks and the terrain for a while using the <a href="http://bulletphysics.org/wordpress/" target="_blank">Bullet Physics library</a>. Turning on physics for other entities showed me more issues with my physics that needed fixing and so the list of things to do grew.<br />
<br />
<a name='more'></a><br /><br />
One issue that showed up was ramps and stairs were not properly implemented in the terrain physics. After some drawn out attempts to get ramps and stairs working <a href="http://gamedev.stackexchange.com/a/27463/7191" target="_blank">with my previous strategy</a>. I found that my previous strategy for terrain physics wasn't cutting it. It was a bit too "hacky" to get consistent good results for terrain shapes that weren't cubes. So, I changed the terrain physics to use the <span style="background-color: #f0f0f0; color: #222222; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17px;">BvhTriangleMeshShape</span> in Bullet Physics. This has the benefit of using the same triangles that <b>visually </b>represent the terrain to also <b>physically </b>represent the terrain.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.stack.imgur.com/WrLrr.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="318" src="http://i.stack.imgur.com/WrLrr.png" width="640" /></a></div>
<br />
The yellow triangles represent the physics shape. More details on the implementation of that over on the <a href="http://gamedev.stackexchange.com/questions/27405/how-do-i-implement-a-bullet-physics-collisionobject-that-represents-my-cube-like" target="_blank">gamedev stackexchange</a>.<br />
<br />
Now that I had an accurate (and fast!) representation of the world in physics, I needed to implement some other features:<br />
<br />
<b>Collision filtering</b>- I wanted Goblins to be able to pass through some entities, or the player will be left watching their Goblins bump into everything (which makes me think of Supreme Commander when you're trying to get your commander to run away from the approaching <a href="http://supcom.wikia.com/wiki/Cybran_Experimental_Spiderbot" target="_blank">Spiderbot</a> and he's just bumping into the engineers around him and now the Spiderbot's Heavy Microwave Laser is cooking your commander and nuclear explosion, gah!). Now Goblins can pass through each other but still collide with structures and terrain.<br />
<br />
<b>Soft collisions- </b>I wanted Goblins to pass through each other, but I also wanted them to avoid each other. I don't want them all stopping in the same place and stacking up. This was kind of simple with collision filtering already implemented. Since collision filters still detect collisions but don't react, this was just doing some further filtering to react differently to some collisions. Now a small force is applied to entities that are soft colliding.<br />
<br />
<b>Ray casting- </b>I use rays to cast out in front of entities when they're moving to detect objects in front of them. I can use these rays to get repel vectors for steering away from obstacles before running into them. The neat thing is the rays can use the same filtering information from above, so entities can hard steer away from objects they collide with, and soft steer away from soft collisions.<br />
<br />
Along with new features I've been working on fixing weird physics bugs. Objects falling through the terrain, entities suddenly getting extreme velocity... regular stuff?<br />
<br />
So progress continues. It's been a little slower lately since other things have come up. Such is the progress of a "in my free time" game I suppose. Thanks for reading.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-2671245599378847462013-03-24T09:09:00.000-07:002013-03-24T19:15:57.358-07:00What's the gameplay like?The back story of the game is described in a previous post, <a href="http://www.byte56.com/2013/01/the-discovery.html" target="_blank">The Discovery</a>. Essentially, you're in charge of saving the goblin race (no pressure).<br />
<br />
Your goal is to settle a new colony on a strange and hostile land. Most of your resources and technology were lost in transit, so you're starting from almost nothing. You need to build a home for your goblins, defend it from the hostile creatures that inhabit this new land and create the infrastructure to produce the technology needed to return to space.<br />
<br />
<a name='more'></a><br /><br />
The game starts with three to five goblins who've just crash landed in an escape pod. You have minimal tools and limited resources. Your first goal will be to find a suitable base of operations, the location for your colony. Find somewhere defensible, with access to resources and enough room for outdoor structures and crops. Generally this comes in the form of a concave hillside or valley, but it can be anywhere that looks fun. You can always build walls later.<br />
<br />
Once you have a location chosen, you'll need to start getting the basic necessities, food and water. Food comes in a variety of forms, the easiest of which is harvesting food from local flora. This food is typically ready to eat off the plant <span style="font-size: x-small;">(unless it's poisonous, it is a dangerous land!)</span>. Other sources of food include hunting and farming.<br />
<br />
You can create a task for collecting food from local plants to start building a stockpile. When creating a general task like that, you can set the maximum number of goblins to be assigned to that task, for starters you can assign one or two goblins to the task. Much like Dwarf Fortress, you don't assign tasks directly to individuals. You create a task, then goblins will decide who among them has the time and skills to perform that task. Occasionally splitting the task into smaller parts, for example delivering the resources to a build site and the actual build job can be preformed by different goblins.<br />
<br />
Water can be collected with wells to underground water sources or straight from streams and lakes. Collecting from surface water sources away from the colony comes with the risks of venturing out into the open. Wells are the safest option in the beginning but take more time to set up.<br />
<br />
Once water and food are provided for at the basic level, it's time to start gathering the materials needed for structures and tools. These materials come in many forms. Wood from trees can be used in many constructions. Stone and metal from the ground, used in structures and tools. Finally, fur, skin, organs and bones from various creatures are used in clothing, armor, weapons, tools and some advanced gadgets (more on the organic-gadget interfaces later). The tools produced will help in accelerating the gathering of materials and allow the construction of more advanced structures. The structures will be used for shelter, defense and processing materials.<br />
<br />
Some of the first things you want to build will be for defense. Passive defenses, like traps, will be useful when resources are low. Active defenses, like auto turrets, will be far better at defending the colony, but they will be resource expensive. The easiest and most flexible defense are your goblins, however, in some ways, they are the most valuable resource you have, so they should only be used as the last line of defense to protect the colony. Goblins can train for combat and equip weapons and armor.<br />
<br />
You'll continue to build up your colony and gather materials. Build workshops to take raw materials and turn them into building components, tools and weapons. Some constructions require parts from multiple workshops and a variety of materials. Workshops range from working automatically to requiring the attendance of a skilled craftsgoblin. Examples of workshops include a furnace for smelting ore, a smithy for forging metal into tools and weapons, or a engineer's workshop for creating gadgets.<br />
<br />
Occasionally, there will be another escape pod that lands with more goblins. Each goblin comes with different skills and the bits of Eilliam tech they can carry, so every new member is a welcome addition. However, this introduces the challenge of continued expansion to support your growing population. Food production and living space must both be in continual growth to keep up.<br />
<br />
<b>You will fail, your goblins will die</b>. A lot. I'm not planning on making it easy to save the goblins. I really like the idea of "<a href="http://dwarffortresswiki.org/index.php/DF2012:Losing" target="_blank">losing is fun</a>". It will take a long time and a good amount of luck to "win". The game gets harder with progress. There are greedy inhabitants sharing the world with you, the more wealth you acquire (in the form of technology, food, valuable materials), the more you'll be targeted by your fellow inhabitants.<br />
<br />
If you've played Dwarf Fortress, the form of interaction is similar. However, I'm focusing on simple, but powerful interaction with your goblins. While I will have keyboard shortcuts for everything, I would like to enable the player to primarily use the tool they're most comfortable with, the mouse. Being able to use the mouse for in world selection/interaction along with a clean GUI, should open up the "entry cost" of the game to a lot more people. I don't want the challenge to be in using the game! I want the challenge to be in winning the game.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com2tag:blogger.com,1999:blog-5255286524625277161.post-59428851855098652462013-03-09T08:56:00.000-08:002013-03-09T18:15:07.448-08:00Fight or flight? Threat analysis<br />
A still very much in development system in AoG is the threat system. This system is primarily used in combat. It helps entities with their fight or flight decisions.<br />
<br />
Basically, the system takes two entities as inputs. The subject and the potential threat. The entities have some facts about them compared and a value is output determining the threat that the potential threat poses to the subject. The facts compared depend on the entities, but some common ones are:<br />
<br />
<a name='more'></a><br /><br />
<ul>
<li><b>Size.</b> Larger entities are threatening to smaller entities.</li>
<li><b>Species relationship.</b> Some species just have it out for each other. These relationships can even start neutral and turn sweet or sour depending on how the two species interact throughout the game. If the goblins are always stealing food from the Zanadingos, relationships are going to get rough.</li>
<li><b>Body threat analysis. </b>If an entity has a number of "weapon" type appendages (claws, spikes, poison pods, etc.), it will rate as more of a threat.</li>
<li><b>Speed. </b>Faster entities are more threatening because you can't get away from them if they turn out to be nasty. Scary.</li>
<li><b>Demeanor</b>. Entities have a base demeanor that can vary from species to species or individual to individual. </li>
<li><b>Equipment. </b>The tools, weapons, clothing and armor an entity has visible can be an indicator to their intentions.</li>
<li><b>Age</b>. With some creatures, power comes with old age, with others it's weakness. </li>
</ul>
<div>
A threat is also rated on its distance from the subject. With factors like speed and ranged attacks adding more threat than something like age. </div>
<div>
<br /></div>
<div>
Being able to calculate the exact threat, at whatever distance needed easily allows the path finding system to flee from threats, or find paths around known threats. For example, the goblin below is interested in getting to the cube highlighted on the left. Though, he hasn't discovered it yet, there's a spike spitter in-between him and the cube. The original path shows that the goblin was unaware of this threat:</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.imgur.com/HpU6NF9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="344" src="http://i.imgur.com/HpU6NF9.jpg" width="640" /></a><i><span style="font-size: x-small;">(Lines are for debugging purposes only, and won't show up in the final game)</span></i></div>
<span style="font-size: x-small;"></span></div>
<div>
<br /></div>
<div>
Now, the goblin has gotten closer and seen the threat. Goblins know they should void threats like this if they can, so he will find a new path that avoids the spike spitter:</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.imgur.com/v44kYEX.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="344" src="http://i.imgur.com/v44kYEX.jpg" width="640" /></a></div>
<br /></div>
<div>
The white and black lines show the A* algorithm at work. The more white the line, the higher the threat. The goblin chooses his path to avoid high threat. So you can see, the path finding algorithm didn't even try to get close to the spike spitter, since those threat values were getting so high, it wasn't worth exploring in that direction any further.<br />
<br />
In this case, the perception range of the goblin was high enough to avoid the threat. If the goblin were to be surprised by an enemy, and came under attack, this same system can be used to find a flee path from the threat. The path doesn't need to be very long, just enough to get out of danger, so the path can be recalculated multiple times without a significant performance hit.<br />
<br />
Additionally, this system is used for goblins to decide whether or not they should flee/avoid, engage in combat, or completely ignore a threat. The actual combat mechanics are what I'm working on next. My next blog post will be describing what I think an average game of AoG will play like. That topic was requested by a fan of the game. If you have something you'd like to read about AoG, post it in the comments. Thanks for your interest.</div>
<div>
<br /></div>
<div>
</div>
Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com2tag:blogger.com,1999:blog-5255286524625277161.post-37280272063293091012013-02-14T13:56:00.000-08:002013-02-14T14:02:21.688-08:00From data files to entities<div class="tr_bq">
Data files are just the start for <a href="http://www.byte56.com/2013/02/data-files-entities.html" target="_blank">creating entities</a> in Age of Goblins. Once the definitions are read into AoG, they're stored in a catalog of "blue prints" for generating entities and materials. Each blueprint holds information for each component that will be added to the entity.</div>
<br />
When the game requests that an instance of entity X be added to the game world, it refers to the blueprint stored for that entity. As an example, lets look at some parts of the goblin data file. The following will describe some attributes that each goblin entity will be generated with when it's added to the game world.<br />
<br />
<blockquote>
[Model]{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>meshname="Goblin"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>texturename="GoblinTextures.png"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>distantdrawtype="norender"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>selectionType="DynamicBone"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><span class="Apple-tab-span" style="white-space: pre;"> </span>[Motion]{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>maxvelocity=1.5:1.9<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>locomotion=Walk,Swim<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>[Skills]{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>ALL=0.01:0.05,Mine=8.3:8.8,Construction=8.3:8.8<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</blockquote>
<br />
<a name='more'></a><br />
Each goblin will have a `model` component, a `motion` component and a `skills` component (among others). The values defined in ranges show values that will differ from goblin to goblin. In this case, I've turned Mine and Construction kills up rather high for testing purposes. I'll likely expand the skills description in the future to just select 3-4 skills to be much higher than others, which will determine starting professions. Once all this data is loaded in, we're ready to start generating goblins.<br />
<br />
When an entity is created, some information is passed in with the creation.<br />
<br />
<ul>
<li>Species information: this is used for values that are common among all instances of a species, like mobility options (walk, fly, ooze, etc.), or life requirements (air breather, water breather, nutrition requirements, etc.)</li>
<li>The location its being created: obviously, so we know where to put it.</li>
<li>Lineage information: Entities/Entity that was responsible for this entity's creation. This is a neat idea that has potential, for example: body definitions contain family traits which can be passed from parents to children. Have big ears? Your kids probably will too. I hope to introduce traits that provide resistances/strengths/weaknesses with slight modifications on creation. This way, generations of entities can actually experience some minor evolution. The spike spitters at one colony could have some interesting properties compared to the spike spitters at another colony.</li>
</ul>
<div>
All that information is passed into the entity factory that will in turn, pass it to each component the entity will have. Each component will pick and choose the information it's interested in, and tailor its creation based on that information. The entity factory is looks something like this pseudo code:<br />
<div>
<br /></div>
<pre class="brush: java">Entity createEntity(String entityName, SpawnInfo info) {
Entity e = newEntity();
for(ComponentInfo ci : entities.getAttributes(entityName)) {
e.addComponent(ci.generateComponent(info))
}
return e;
}</pre>
</div>
<div>
<br /></div>
The `ComponentInfo` class is a neat one. It contains the parser for reading from the data file and the code for generating a new component based of the data read in. The `ComponentInfo` object <b>is </b>the blueprint for a component. So, for example, the creation code for the skills component would look something like this pseudo code:<br />
<br />
<pre class="brush: java">SkillsComponent generateComponent(SpawnInfo info) {
List<Skill> skills = new List<Skill>();
for(SkillLevelFactory slf : skills) {
skills.add(slf.generateSkill(info));
}
return new SkillsComponent(skills);
}
....
SkillLevelFactory {
SkillType skillType;
FloatRange skillRange;
Skill generateSkill(SpawnInfo info) {
Skill s = new Skill(skillType, skillRange.getRandomValue()));
s.applyLineageModifiers(info);
return s;
}
}
</pre>
Where `skills` was a list of `SkillLevelFactory` generated when the data file was read in. Essentially being a list of available base skills and their value ranges. The `ComponentInfo` objects are created for each entity, for each component they define.<br />
<br />
The entity/component system, paired with this scripting system creates a very powerful tool for generating entities. The entities created are similar enough to be in the same species\family, but unique enough to be called individuals. Thanks for reading.<br />
<br />
Is there something you want to know about the inner workings of Age of Goblins? Ask me about it, I may write a post about it :)Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com2tag:blogger.com,1999:blog-5255286524625277161.post-58005052650840631852013-02-05T17:56:00.000-08:002013-02-14T08:44:14.576-08:00Data Files: EntitiesFollowing up on my last post about the <a href="http://www.byte56.com/2013/01/data-files-materials.html" target="_blank">data files used for materials</a>. This post will tell you a bit about using data files for defining entities.<br />
<br />
First off, it's important to know that Age of Goblins uses and entity/component framework for all the entities in game, similar to the one <a href="http://gamedev.stackexchange.com/questions/31473/role-of-systems-in-entity-systems-architecture/31491#31491" target="_blank">described here</a>. The data files take advantage of that when defining entities. Basically, the data files for entities tells the entity component system which components to add and what values to give them.<br />
<br />
<a name='more'></a><br />
<br />
Note that I'll switch between components and attributes, for the purpose of this post, these terms are interchangeable. My entity/component/systems framework is a entity/attribute/behavior framework.<br />
<br />
Now, like everything in AoG right now, it's all under construction, so things are likely to change, but we can get a snapshot of what things are like right now. This will give you an idea of how things are defined. Let's look at the spike spitter definition for an example, I'll post the whole thing here, then talk about each section below. A lot of it should be somewhat self explanatory once you get the idea of what's going on:<br />
<br />
<br />
<blockquote>
ENTITY:"SpikeSpitter"<br />
{<br />
Description="A semi-sentient plant that defends its self by shooting spiked barbs or swatting with its spiked mouth pod"<br />
CommonName="Spike spitter"<br />
PluralCommonName="Spike spitters"<br />
EntityTags=Plant<br />
ColonyTags=Selectable<br />
baseAttributes="Common"<br />
<br />
[Information] {<br />
}<br />
<br />
[AnimationState]{<br />
defaultmeshname="SpikeSpitter"<br />
}<br />
<br />
[Model]{<br />
MeshName="SpikeSpitter"<br />
TextureName="spikespitterTexture.png"<br />
distantdrawtype="NoRender"<br />
selectionType="DynamicBone"<br />
}<br />
[LifeRequirement]{<br />
}<br />
<br />
[Inventory]{<br />
MaxItems=20<br />
Allow="Spiked Barb"<br />
Disallow=ALL<br />
}<br />
<br />
[ZoneActivator] {<br />
Zones{<br />
ActivatorReactionZone{<br />
Zone{<br />
Shape=Sphere<br />
Radius=3.0:4.0<br />
}<br />
ActivationTypes=Foe<br />
ZoneReactions{<br />
CombatZoneReaction{<br />
}<br />
}<br />
}<br />
}<br />
}<br />
<br />
[ProduceHarvest] { <br />
ProduceItems{<br />
ItemProduced{<br />
ItemName="Spiked Barb"<br />
TimeToProduce=12000:19000<br />
TimeToCollect=2000:5000<br />
WeightedChance=10<br />
ProductionActivity=Dawn,Day,Dusk<br />
ProductionResult=StoreStopWhenFull<br />
MinConditionToProduce=0.3<br />
MaximumPerCentadak=30<br />
Seasons=Sprungston,Smeltar<br />
}<br />
ItemProduced{<br />
ItemName="Spike plant seed"<br />
TimeToProduce=30000:120000<br />
TimeToCollect=200:500<br />
WeightedChance=2<br />
ProductionActivity=ALL<br />
ProductionResult=LaunchIntoWind<br />
MinConditionToProduce=0.0<br />
MaximumPerCentadak=50<br />
Seasons=Sprungston<br />
}<br />
}<br />
}<br />
}</blockquote>
All of that creates this, a spike spitter soaking up some sun:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-I_s6n550fcPQrDugfhsN4tuyae_hGYoS-euEl04EBldjh-6ts55MGOATbez4xZ0HFI4QPgDxOYEW26Hev1dHoySTDUkoNGvXQW0vdtscPxiP-B5Cri-l75JiFr0E_Nyaos8cWV_MMvw/s1600/spikespitter_sunning.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-I_s6n550fcPQrDugfhsN4tuyae_hGYoS-euEl04EBldjh-6ts55MGOATbez4xZ0HFI4QPgDxOYEW26Hev1dHoySTDUkoNGvXQW0vdtscPxiP-B5Cri-l75JiFr0E_Nyaos8cWV_MMvw/s400/spikespitter_sunning.PNG" width="280" /></a></div>
<br />
<br />
<br />
At the first level, we tell the parser we're reading an "ENTITY" and it's called "SpikeSpitter". Then we have some common information that applies to all spike spitters. This information will be stored in the the Lexicon and allow us to reference this entity by its name. The script also tells us some display strings for the entity and some tags. "Selectable" means that this entity will be selectable with the mouse, so we can click on it for more information in game. Then things get interesting. "baseAttributes" is like an "include" statement in C++. It references a defined set of common attributes that I didn't feel like writing over and over again for each entity. CommonAttributeGroups can be defined for any combination of attributes. The `Common` group referenced in SpikeSpitter is not very interesting:<br />
<br />
<br />
<blockquote class="tr_bq">
COMMONATTRIBUTEGROUP:"Common" {<br />
[Position]{<br />
}<br />
}</blockquote>
At the moment, it just contains a position attribute. The neat thing about CommonAttributeGroups is that they can actually be used even when you have that attribute defined again. For example, I could define a CommonAttributeGroup that had an Inventory attribute defined like so:<br />
<br />
<blockquote class="tr_bq">
COMMONATTRIBUTEGROUP:"Common" {<br />
[Inventory]{<br />
MaxItems=10<br />
Allow=ALL<br />
Disallow=ALL<br />
}<br />
}</blockquote>
Then, I could, later in the same entity, define the Inventory attribute again like so:<br />
<br />
[Inventory]{<br />
MaxItems=15<br />
}<br />
<br />
It would be a valid definition and the final result would be a merged definition of the two. Basically, you can create CommonAttributeGroups and <i>just override the values you want</i>. Pretty neat.<br />
<br />
If you remember, in <a href="http://www.byte56.com/2013/01/data-files-materials.html" target="_blank">the materials post</a>, there was some materials that had some EntityBaseAttributes defined. These are it. For example, some of the materials used the "Slow Decay" common group. That's just a [TimeEffect] attribute that will be applied to the material entity when it's created.<br />
<blockquote class="tr_bq">
COMMONATTRIBUTEGROUP:"Slow Decay" {<br />
[TimeEffect] {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> timeBetweenTicks=1000:1500<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> startingTick=0:0<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> maxTicks=1:1<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> numberOfTicksPerIncrement=1:1<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> effectType=Decay<br />
}<br />
}</blockquote>
The TimeEffect attribute is one that changes the entity over time. In this case, when the timer reaches the end, the item will decay from the world. This means that organic materials won't last forever, goblins will need to collect the materials before they go bad. Some minerals have Very Slow Decay rates. So materials like soil will eventually decay away when they're in item form. This is like a little clump of dirt being washed/blown away over time.<br />
<br />
Continuing on with the spike spitter definition, all the values like [Name] are naming an attribute. The entity component system will see those and know that when it creates an instance of this type of entity, it'll need to add an attribute of that type. Some of the attributes are just empty brackets. That's because they're either not implemented yet, or they don't require anything to be defined in the scripts. Like the Position attribute is empty because the position is defined at run time when the entity is created, not in the script beforehand.<br />
<br />
The "ProduceHarvest" attribute is similar to the "HarvestItems" value found in the materials, except this one is actively producing materials. As you can tell from the description, the spike spitter is actively producing new barbs to spit and it's producing seeds to spawn. You can see that it won't have an unlimited number of spikes to spit out at passing goblins. It can only hold 20 spikes and takes time to produce new ones.<br />
<br />
The "ZoneActivator" attribute is brand new. It defines the area in which this entity will "watch". The trigger is activated by any "Foe" and will result in the entity activating a "CombatReaction". As you can see below, with debug visuals turned on, the goblin has entered the spike spitters detection area.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx197BWFP95-Zq3BykbkUQUCa9abZ1va5lFshTUCas5hgTcemjWUYkKo0Y1ft2pABKG-dZ4pAbphqHlzNmjsvUo6oshL5QCi_evGK1ar1utbqxbd27s7ElfPRqkmmJ_VRCcBccCWPrFeo/s1600/activationzone.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="562" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx197BWFP95-Zq3BykbkUQUCa9abZ1va5lFshTUCas5hgTcemjWUYkKo0Y1ft2pABKG-dZ4pAbphqHlzNmjsvUo6oshL5QCi_evGK1ar1utbqxbd27s7ElfPRqkmmJ_VRCcBccCWPrFeo/s640/activationzone.PNG" width="640" /></a></div>
<br />
<br />
<br />
As you might have noticed, most of the numerical values are defined as ranges. That's because this script isn't defining just one spike spitter, it's defining them all. When an entity instance is generated, it'll choose a random value between the defined values for that entities value. I <a href="http://gamedev.stackexchange.com/questions/33453/how-smartly-implement-scripting-in-game/33483#33483" target="_blank">wrote an answer</a> on GDSE about this a while back that might give some more details too.<br />
<br />
The entity component framework is what really gives this scripting its power. Being able to easily tack on one attribute or another is not only useful in game, it makes creating a script that does that considerably easier.<br />
<br />Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com2tag:blogger.com,1999:blog-5255286524625277161.post-29141716371920557432013-01-28T10:56:00.000-08:002013-01-31T14:08:37.204-08:00Data files: MaterialsAge of Goblins stores a good deal of its data in script files. These files store everything from the blueprints for a goblin to the definitions for materials in the ground.<br />
<br />
For all the materials in game, be it a cube making up the terrain:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtFPpl7P5r20wNiNz2PKbMr7E4NlnZfj7MOgLmZiqYIQ0sFPOHjT6fdE77AiqkUVk0t4SahtrgxS-oOTjO-tYyICjNJ-g1pj9u-KP4aH8QfmipAtiHqTkECkO3n6sBtmkcz-KnGrY9b90/s1600/cubeInWorld.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="309" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtFPpl7P5r20wNiNz2PKbMr7E4NlnZfj7MOgLmZiqYIQ0sFPOHjT6fdE77AiqkUVk0t4SahtrgxS-oOTjO-tYyICjNJ-g1pj9u-KP4aH8QfmipAtiHqTkECkO3n6sBtmkcz-KnGrY9b90/s320/cubeInWorld.PNG" width="320" /></a></div>
<span id="goog_1141672454"></span><span id="goog_1141672455"></span><br />
Or the material it leaves behind when it's mined:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8anuY2il2BV7_eFuPmDdgclwbgM6Kho2eW0PvdwNbuSM95niSiT1cxWD5jHNqA30Rc-_Lqk2w3F48HC44lu9heGJcYUFhOHFVkS0vXB5IrVC7ONhCGGNM3fZkuFfChq_IL2iTmfb9tQE/s1600/materialInWorld.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8anuY2il2BV7_eFuPmDdgclwbgM6Kho2eW0PvdwNbuSM95niSiT1cxWD5jHNqA30Rc-_Lqk2w3F48HC44lu9heGJcYUFhOHFVkS0vXB5IrVC7ONhCGGNM3fZkuFfChq_IL2iTmfb9tQE/s1600/materialInWorld.PNG" /></a></div>
<br />
<br />
<a name='more'></a><br /><br />
Are all defined in data files. These definitions start in the "base definition" files. These files contain all the material base types. This is where some hard coded values get used. The game defines an enum list of base materials. For example, "WOOD" is a base material type. Then the data files extend that with "SoftWood", "Wood", "HardWood". Then they are extended in other data files with a variety of different types of each kind of wood. Most of which I haven't come up with yet :). But, you get the idea, it's a hierarchy of material types.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6mJk80FldsLRM9u_KhnckJgfHNWDoCg9i6O1dEZSKT5FwURLN-7k1DacFkjGKbrcQ6pxZS8OxTMGhBb0nyRMBZ6iNFjsGPdskssMYkxASp3DJMY4kfSIBtpB6lO6P0rLYA_YYULq7TFI/s1600/materialhierarchy.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6mJk80FldsLRM9u_KhnckJgfHNWDoCg9i6O1dEZSKT5FwURLN-7k1DacFkjGKbrcQ6pxZS8OxTMGhBb0nyRMBZ6iNFjsGPdskssMYkxASp3DJMY4kfSIBtpB6lO6P0rLYA_YYULq7TFI/s640/materialhierarchy.PNG" width="640" /></a></div>
<br />
<br />
It's more than just organic materials however. The same hierarchies exist for stone, sand, soil and so on. For example, the base file definition of "Top Soil" is:<br />
<br />
<br />
<blockquote class="tr_bq">
BASEMATERIAL:"Top Soil" {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>description="Soil found commonly on the surface of the world"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>materialtype=Soil<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>strata=surface:15<br />
}</blockquote>
<br />
Where "materialtype" is referencing the enum in code. There's a shared common description for all the soils that will extend this base type and the the strata definition. The strata definition tells the world generation where this material is most likely to show up. That attribute is only applied to materials that show up in the ground. Currently the stratum are arranged from top to bottom like so:<br />
<br />
<blockquote class="tr_bq">
<span class="Apple-tab-span" style="white-space: pre;"> </span>Surface<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>NearSurface<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>SuperSediment<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Sediment<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>SubSediment<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>SuperStone<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Stone<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>SubStone<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>SuperCondense<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Condense<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>SubCondense<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Adamastos<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Neutrpauli</blockquote>
<br />
Obviously, we'd want "Top Soil" to show up on the surface. The `15` following the strata definition is the weighted chance that this material will be chosen from among all the other materials that are defined to show up on the surface. The density of the material also matters, but that's defined later.<br />
<br />
The next level in the hierarchy defines the actual materials that will show up in game. For example, "Grassy Dirt" is a material that extends "Top Soil":<br />
<blockquote class="tr_bq">
<br />
MATERIAL:"Grassy dirt" {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>basetype="Top Soil"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>commonName="Dirt with grass"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>pluralCommonName="Dirt with grass"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>qualityrange=1.0:1.0<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>itemtextureindex=2<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>cubetextureindex=YP:4,SIDES:4,YM:1<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>value=3<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>density=75:0:90.0<br />
}</blockquote>
Everything from the textures to the value is defined here. In "cube form" (like the top most image above), the textures can be defined for each of the sides individually, or using shortcuts like "SIDES" or "ALL". The numbers define the index in the texture sheet to use for drawing that cube. In "item form" (like the second image down from the top), the texture is also defined using the index from a texture sheet. The density value is used in world generation, resistance to mining, and allows for limiting the structures that can be created with that material.<br />
<br />
Lets look at some organic materials, as they're a bit more interesting. How about fruit? Starting with the base type:<br />
<br />
<blockquote class="tr_bq">
<br />
BASEMATERIAL:"CulinaryFruit" {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>description="A fruit that is good for goblin eating"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>materialtype=CulinaryFruit<br />
}</blockquote>
Obvious enough. The looking at a material the extends this base type, the "Redbatan":<br />
<br />
<blockquote class="tr_bq">
<br />
MATERIAL:"Redbatan" {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>description="An redbatan, a tasty fruit"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>commonName="Redbatan"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>pluralCommonName="Redbatans"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>tags=Fruit,Edible<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>basetype=CulinaryFruit<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>qualityrange=0.2:1.0<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>itemtextureindex=10<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>value=15<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>density=20.0<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>entityBaseAttributes="Small Physics Item","Slow Decay"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>HarvestItems{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>HarvestItem{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>material="Redbatan seed"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>TimeToCollect=200:500<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>WeightedChance=1<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>MinConditionToProduce=0.3<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>OverrideQuality=1.0:1.0<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>HarvestItem{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>material="Redbatan core"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>TimeToCollect=200:500<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>WeightedChance=1<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>MinConditionToProduce=0.3<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
}</blockquote>
Now things are getting interesting. We see here that there's a few of the same attributes that the top soil had, however there's some notable exceptions. The "Tags" section helps the game identify the material, so when creatures are looking for something to eat, they'll know when they found it. The "EntityBaseAttributes" is kind of a macro. It talks to the entity component system. When creating the in world representation of this material, the entity component system needs to know some common attributes to give it. I'll get more into how the entity component system interacts with scripts in my next post, but for now, just know that we define everything about an entity in the scripts.<br />
<br />
One of the more interesting differences in this material description is the "HarvestItems" section. This section defines the <b>other </b>materials that reside <b><i>inside</i></b> this material. So when a goblin performs a harvest operation on this material, there's some materials you can expect to come out. Additionally, this defines the materials that might come out once a Rebatan were to decay. The materials referenced here are defined in the same file as the Rebatan:<br />
<br />
<blockquote class="tr_bq">
MATERIAL:"Redbatan seed" {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>baseType=CulinaryFruitSeed<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>commonName="Redbatan seed"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>pluralCommonName="Redbatan seeds"<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>qualityrange=0.5:1.0<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>itemtextureindex=14<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>value=10<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>density=2.0<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>entityBaseAttributes="Small Physics Item","Very Slow Decay"<br />
}</blockquote>
Overall this ability to create a hierarchy of materials and define everything we need to know about materials in script files makes it easy to dramatically change the game just by swapping out a few text files. With only a little complexity, it's a very powerful system for defining materials. It gets even more interesting when defining entities like goblins or spike spitters. In my next post I'll cover the data files used to create full entities. Until next time, thanks for reading!<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-80185751682702693392013-01-21T22:56:00.000-08:002013-01-31T14:15:46.032-08:00The Discovery<i>Presenting the first draft of the Age of Goblins back story, names and details may change. Enjoy, let me know what you think.</i><br />
<br />
<br />
<span style="font-size: large;">The Discovery</span> was easily considered the most important discovery in goblin history. Not only did it unify all of goblinkind with a single purpose, it pushed the bounds of known science to previously unfathomable extents. The goblins were simply born too late into Eilliam, the world they called home. The binary stars that gave them life, Qurat and Korbly were building a bomb that would outshine the galaxy. In just a few generations, Korbly would supernova; the goblins had to find a new home.<br />
<br />
<a name='more'></a><br /><br />
Goblin technology at the time of The Discovery wasn't more advanced than that of human technology in the late 1800s. The goblins had an immense amount of work ahead of them if they wanted to save their species. They needed to develop space travel, find a way to survive the vast distance to the nearest habitable planetary system and do it quickly.<br />
<br />
The years were tough; sacrifices were made. The whole of society was driven by the solitary goal of evacuation. The resources of an entire world were needed. After many years, the goblins had built themselves a massive colony ship in orbit. Being the salvation of their species, they named it Sal. Sal was a marvel to behold. The apex of goblin engineering. Sal was fit with an experimental FTL(Faster Than Light) drive and stasis pods for the nine month trip to the New Korbly system. This would allow the goblins to make several trips before the supernova. They would save themselves.<br />
<br />
The maiden voyage found Sal stocked with supplies, laborers, engineers and scientists. All that was needed to prepare a new world for colonists. The universe surely smiled on goblinkind this day. The whole world celebrated their achievement.<br />
<br />
The FTL crackled quietly, just audible over the hum of the cryo-pods housing the first passengers to New Korbly. It had been 3 months since Sal left orbit around Eilliam. Sal had just passed the one third mark towards their destination. That's when it happened.<br />
<br />
The warning lights only flashed once before the ship rattled in a violent explosion. The shuttle bay had been hit, it was ripped free from the ship. It took the FTL drive with it. The warp bubble collapsed and Sal tore back into normal space out of FTL. Deck zero took the brunt of the Cherenkov radiation and evaporated into blue mist. Goblins and supplies turned to atoms.<br />
<br />
Most of the crew had survived, most of the equipment was lost. Communications were down, long range viewers destroyed. The universe showed the goblins how much it cared.<br />
<br />
The uncontrolled re-entry into normal space had left them with precious few options. The pain of subluminal travel was sharp. Without the FTL drive it would take thousands of years to get back to Eilliam. Their home and any hope of help would be long dead by then. New Korbly was much too far, tens of thousands of years. The stasis pods were not designed to work that long, but theoretically they might. The only option was to go on and hopefully find something on the way.<br />
<br />
Sal could only save her current passengers. Just a small fraction of the goblin population. The crew set the autopilot to search for a new home and went into stasis, not sure if they would ever come out. None were awake to see the flash behind them.<br />
<br />
For 10,000 years Sal crossed through the void, getting close enough to stars to observe and look for signs of a habitable planet. Sal, unable to go on much longer, finally found a world suitable to support goblin life. Now an ancient ship, she limped into orbit around this bizarre rectangular world. The world is habitable, but hostile.<br />
<br />
Waking the crew in small groups, they are sent to the surface in escape pods, a one way trip. Without the shuttle bay, there's no way to get all the survivors down to the surface. With Sal failing overhead, barely able to hold atmosphere, the goblins need to get the remainder of the survivors down to the surface. The materials needed to build shuttles to return to Sal are deep below the surface. The goblins must first build the infrastructure required to recover the materials. Then build shuttles to evacuate the crew.<br />
<br />
They are the last of the goblins. They must build to survive. Thus begins The Age of Goblins.<br />
<br />Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com4tag:blogger.com,1999:blog-5255286524625277161.post-65569633225985283412012-12-28T07:56:00.000-08:002012-12-28T07:56:00.329-08:00Pre-Alpha demo 6: Age of Goblins - World Generation and Animation<iframe allowfullscreen="" frameborder="0" height="270" src="http://www.youtube.com/embed/u0uP04b2FRs" width="480"></iframe><br />
<br />
A new video!<br />
<br />
The GUI used in the video is <a href="https://bitbucket.org/byte56/bytegui/wiki/Home" target="_blank">ByteGUI</a>. I'll be releasing it as a stand alone library for other developers. It uses Slick2D and is written in Java. I'm sure it'll be prettier in the hands of someone more artistic. It has various effects, some of which are shown in the video with panels sliding in and out. More details on that when it's closer to release. Thanks for your interest!Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com5tag:blogger.com,1999:blog-5255286524625277161.post-48513335935673659632012-12-12T20:56:00.000-08:002013-01-31T14:16:03.575-08:00The Blender connection (part 2)I <a href="http://www.byte56.com/2012/12/the-blender-connection.html" target="_blank">previously introduced</a> loading models and rendering them in-game. Now I'll go over implementing animation for Blender models.<br />
<br />
First we have to add bones to the model. If you know pretty much anything about skeletons, this is fairly simple. Your mesh is the flesh. You want to add bones in places where you want the flesh to move. If you want this bit of the flesh to be able to move independently of that bit of flesh, you need to add multiple bones. Take, for example, the simple AutoCannon T230:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-dr6ZMa8uM9VAnbwGf9nCclrPLzHo2SyasbN8Kkxy3qXqvDLKZt5gr3SCa7ktsxQIeJYvKRx_U0DctaVxxo33DIPi2rk2kBxasU7mUYOlhIzVUotCAfG_qCK2XkTbO0JMdQGztc-9lyo/s1600/autocannon.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="217" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-dr6ZMa8uM9VAnbwGf9nCclrPLzHo2SyasbN8Kkxy3qXqvDLKZt5gr3SCa7ktsxQIeJYvKRx_U0DctaVxxo33DIPi2rk2kBxasU7mUYOlhIzVUotCAfG_qCK2XkTbO0JMdQGztc-9lyo/s320/autocannon.PNG" width="320" /></a></div>
<br />
<br />
<a name='more'></a><br /><br />
To create the bones, we first have to know what we want it to do. Well the AutoCannon T230 can sweep and pitch creating an decent kill zone in front of it. It can also, of course, accurately fire multiple rounds per minute with it's recoiling barrel. So knowing all that, we want to place bones for rotating around the vertical axis and the horizontal axes, as well as the ability to recoil the barrel. Something like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjztoMrA9FU21Q7AYMBDXgbKoWpIHVUL01T6SwrVkJL4bmq50_tSIqK-aDXmR8hatGl8s-xKEOZPdzEaFGPYvtleBsqXDBJ_LLijuBS1kjj4oR2SPPrjvhLvEgmpVVfYFgmveuxo0UxlpU/s1600/autocannon_bones.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjztoMrA9FU21Q7AYMBDXgbKoWpIHVUL01T6SwrVkJL4bmq50_tSIqK-aDXmR8hatGl8s-xKEOZPdzEaFGPYvtleBsqXDBJ_LLijuBS1kjj4oR2SPPrjvhLvEgmpVVfYFgmveuxo0UxlpU/s320/autocannon_bones.PNG" width="320" /></a></div>
<br />
The bottom one controls the rotation around the vertical axis, the itty bitty one controls the rotation around the horizontal axes and the larger horizontal bone controls the recoil and twist of the barrel. Learning how to properly rig a model is probably best left to a proper tutorial site. The model needs to have bones and vertices assigned to those bones with weights.<br />
<br />
Since I wanted to be able to animate some things dynamically, I do some special things in Blender when it comes to animation. First of all, I add tags to bones that I want to flag when importing. For example, I'll add the tag (LookY) to the base rotation bone. Since it's responsible for rotating the "head" around the Y axis, it's what I would use to dynamically apply a "look at" pose to have the turret track an entity in game. I additionally have named the itty bitty bone with the tag (LookX). It's going to be rotating the "head" around the X axis, so now we can look up, down, left and right.<br />
<br />
But introducing dynamic animation means we need constraints. Unfortunately the .x format does not export the bone constraints I can enter into Blender for it's IK solver. So what to do? Well I decided that key frames could serve that purpose well enough.<br />
<br />
First a bit of info on keyframes and animations. There wasn't a simple way to export multiple animations as discreet animations from Blender. There's not really even an easy way create separate animations in Blender, let alone export them that way. So every animation is packed into one animation. One after the other. Then I have a text file that describes where one animation starts and ends, as well as what frames are the loop frames. Loop frames are the start & end of the loop cycle for animations, for example, the walk cycle has a start walking from stop, walk and stop walking animation. If I want the animation to play longer than the single cycle I animated it for, I define the frames to use to wrap around the walk portion of it. This makes it dead simple to: start walking -> loop walk until we're near the stopping point -> seamlessly play through to the end of the walk animation with the stop.<br />
<br />
Anyway, so all my animations are packed into a single animation with the text file defining them. For example, the AutoCannon animation description file looks like this:<br />
<br />
<blockquote class="tr_bq">
<br />
0:0:6:6=SPECIAL_SETUP<br />
7:7:22:22=ATTACK_1_FireTurret<br />
23:23:44:44=IDLE_ANIMATION_1_Sweep<br />
45:45:55:55=IDLE_ANIMATION_30_Stationary</blockquote>
<br />
Where each line is defined like this:<br />
<blockquote class="tr_bq">
[Start frame]:[Loop start]:[Loop end]:[End frame]=Name of animation</blockquote>
The names also include tags for their purpose. Where each name is defined like:<br />
<br />
<blockquote class="tr_bq">
PURPOSE_WeightedChance_ReadableName</blockquote>
<br />
The weighted chance is taken into consideration when there are multiple animations for a given purpose. The animations will be chosen with a weighted random. For example, the Stationary animation is much more likely to be played than the Sweep animation when idle.<br />
<br />
As you can see the turret doesn't take advantage of any animation loops. Boring. The goblin walk animation does, and it's defined like this:<br />
<blockquote class="tr_bq">
145:151:163:165=WALK_1_Walk</blockquote>
It's a fairly short animation. Goblins had to walk really fast. Since their legs are short and I don't want the player waiting for-ev-er to watch the goblins walk around. But the start walking goes from 145 to 151, then I can loop 151 to 163 forever for a perfectly looped walk cycle, then when I'm ready to stop, I just keep stepping through frames to get to 165.<br />
<br />
Now, what's that first "Setup" animation all about? That gets back to the constraints for the dynamic animations. In those first 6 key frames I pose the model in all it's various extents. X, Y and Z extents get posed in their minimum then maximum rotations (or the maximum in both negative and positive directions) Those poses look like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4auERUv4IRCo7b5BIH7V52JGwzQHdUx_H53JGBYYQizIk47EVzpKmp9eJk50vJPoAaMCehpXRSaDxz2LQO3vVAKm-vBMKXwnm6P8m9jHM25yriJey5QnFz2Zil5l4D4fGAwW9tzRmd78/s1600/AutoCannon_Extends.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4auERUv4IRCo7b5BIH7V52JGwzQHdUx_H53JGBYYQizIk47EVzpKmp9eJk50vJPoAaMCehpXRSaDxz2LQO3vVAKm-vBMKXwnm6P8m9jHM25yriJey5QnFz2Zil5l4D4fGAwW9tzRmd78/s1600/AutoCannon_Extends.gif" /></a></div>
<br />
With the last two frames being the same, because there is no rotation around the Z axis.<br />
<br />
I like to create my animations so that they start and end on a standard "default pose". This is probably common in the animation world, but I admit I don't know a lot about the animation world. For example, we'll take the "Fire" animation for the AutoCannon.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHcqFMnUMlaOwvdF1XZc9J_0wEvcG7ACMtQDcdLH4Rmi41l8ZbtbbBbWT1kTIz34eI5KKG8XA08ysgvoS3NheX5fagfpxL_EHC7hQBCd2zFA5J5R6UczDtXguIE_kvSbIz2gRHSchQ3VA/s1600/autocannon_fire.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="244" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHcqFMnUMlaOwvdF1XZc9J_0wEvcG7ACMtQDcdLH4Rmi41l8ZbtbbBbWT1kTIz34eI5KKG8XA08ysgvoS3NheX5fagfpxL_EHC7hQBCd2zFA5J5R6UczDtXguIE_kvSbIz2gRHSchQ3VA/s320/autocannon_fire.gif" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><i>That bit sticking out the back is the bone (won't be rendered in game)</i></span></div>
<br />
That's a total of five keyframes:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieVyvX8HGM32XW3GkT-wb1e2mNxA78ftsn1RCVTjB6IGr6Q-HGrjjAlP9EnsD20AzlNMsZbOSjR9jOZqkvVB2FNPf8RX4KNN5q9WiHf2eLF6YhO0nvBC5L-e0dzmfVZ02v4-vHwZhJp14/s1600/autocannon_fire_keyframes.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="92" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieVyvX8HGM32XW3GkT-wb1e2mNxA78ftsn1RCVTjB6IGr6Q-HGrjjAlP9EnsD20AzlNMsZbOSjR9jOZqkvVB2FNPf8RX4KNN5q9WiHf2eLF6YhO0nvBC5L-e0dzmfVZ02v4-vHwZhJp14/s320/autocannon_fire_keyframes.PNG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><i>Including the default pose at start and end</i></span></div>
<br />
Now the setup is done and we have an animation to test out. We now know how to do pretty much everything we need to in Blender. The last step is to export. When exporting the animations, we just need to ensure that we check the boxes marked "Export Armatures" and makes sure the drop down box labeled "Animations:" is set to "Keyframes Only".<br />
<br />
The first thing we'll do is read in the animation definitions. Use those to generate some empty animation sets that have their animation ranges defined. Now we know what to look for when we read in the animation data from Blender.<br />
<br />
The animation data from Blender will come in the same .x file that we know and love from reading in our meshes. We actually already have a pretty good idea of how to import the armature. It's very similar to the nested format of the meshes that we found before. This time though there'll be some additional information. We'll have lists of which vertices that define which vertices are controlled by which bones, and how much they influence them (commonly called "skin weights").<br />
<br />
Those lists look like this:<br />
<br />
<br />
<blockquote class="tr_bq">
SkinWeights {<br />
"Armature_TurretTop_LookZ_";<br />
228; //number of indices to be read<br />
156, //indices<br />
157,<br />
.......</blockquote>
Each one corresponds to the order in which the vertices were read in from the mesh, or the index of the vertex controlled. Those should be saved so we know which vertices to manipulate for each bone. I like to just stuff those values into some vertex attribute arrays and store them in the VBO for quick access on the graphics card. I have a maximum of three bones controlling each vertex. Those are sorted from strongest to weakest, so if I have too many, the weakest bones are ignored. So the VBOs have two additional `vec3` components per vertex. They have a one for the bone indices and one for the bone weights. But, getting into the gritty details isn't much fun here.<br />
<br />
All together we have the animation definition, the skeleton and the mesh. Next up we need to get the actual animation data. Once again, the easy readability of .x animations helps us out a good deal.<br />
<br />
<blockquote class="tr_bq">
AnimationSet {<br />
Animation {<br />
{Armature_BaseRotator_LookY_}<br />
AnimationKey { //Position<br />
2; //Defines the type of key, 2=Position<br />
7; //The number of key frames we're about to read.<br />
6;3; 0.000000, 0.000000, 0.000000;;,<br />
7;3; 0.000000, 0.000000, 0.000000;;,<br />
22;3; 0.000000, 0.000000, 0.000000;;,<br />
23;3; 0.000000, 0.000000, 0.000000;;,<br />
44;3; 0.000000, 0.000000, 0.000000;;,<br />
45;3; 0.000000, 0.000000, 0.000000;;,<br />
54;3; 0.000000, 0.000000, 0.000000;;;<br />
}</blockquote>
The animation starts with AnimationSet and the defines the keyframes for each bone. Each bone will have a set of key frames for their position, rotation and scale. The comments above show what the numbers mean.<br />
<br />
The keyframe lines are in the format :<br />
<br />
keyframeNumber;number of components to read; component1, component2, component3;;,<br />
<br />
For position that's the x, y, z position. For something like rotation (below) that's the w,x,y,z components of a quaternion. Position is not a very interesting set of key frames for the baseRotator however. Lets look at rotation:<br />
<br />
<br />
<br />
<blockquote class="tr_bq">
AnimationKey { //Rotation<br />
0; //Defines the type of key, 0=Rotation<br />
15; //The number of key frames we're about to read<br />
0;4; -0.707107, 0.707107, 0.000000, 0.000000;;,<br />
1;4; -0.707107, 0.707107, 0.000000, 0.000000;;, </blockquote>
<blockquote class="tr_bq">
//frames 2 and 3 can be seen in the above animation showing the min/max rotations around the Y axis</blockquote>
<blockquote class="tr_bq">
2;4; -0.653281, 0.653281,-0.270598,-0.270598;;,<br />
3;4; -0.653282, 0.653281, 0.270598, 0.270598;;,<br />
4;4; -0.707107, 0.707107, 0.000000, 0.000000;;,<br />
5;4; -0.707107, 0.707107, 0.000000, 0.000000;;,<br />
6;4; -0.707107, 0.707107, 0.000000, 0.000000;;,<br />
7;4; -0.707107, 0.707107, 0.000000, 0.000000;;,<br />
22;4; -0.707107, 0.707107, 0.000000, 0.000000;;,<br />
23;4; -0.707107, 0.707107, 0.000000, 0.000000;;,<br />
30;4; -0.684901, 0.684901, 0.175814, 0.175814;;,<br />
37;4; -0.689064, 0.689064,-0.158715,-0.158715;;,<br />
44;4; -0.707107, 0.707107, 0.000000, 0.000000;;,<br />
45;4; -0.707107, 0.707107, 0.000000, 0.000000;;,<br />
54;4; -0.707107, 0.707107, 0.000000, 0.000000;;;<br />
}</blockquote>
<br />
OK, now we're getting somewhere. We read in all that data. We have the animations defined and filled. We have the meshes and armatures constructed. Now we just need to calculate the transforms for each bone and apply those transforms to the correct vertices.<br />
<br />
Each keyframe needs to have the bones processed in order from root to tip. Each child bone depends on the transform of its parent bone. So when processing each bone we need to know:<br />
<br />
<b>BindMatrix </b>- This is the root frame matrix multiplied by the model frame matrix<br />
<b>BoneMatrix </b>- This is dependent on the bone. This is a recursive get. So getBoneMatrix() returns (BindMatrix * ArmatureRootMatrix * CombinedMatrix) if it's the root bone, otherwise it returns (getBoneMatrix() * CombinedMatrix). I'll talk about the CombinedMatrix in a bit.<br />
<b>LookMatrix</b> - Derived from the direction the entity is looking. Applied only to the "look bones", ignore if not ready for dynamic animation.<br />
<b>SkinMatrix</b> - This is from the SkinWeight frame, found at the end of the list of weighted vertices.<br />
<br />
Now that we have all that, we need to calculate the new pose. The CombinedMatrix is the transform calculated from the rotation, scale and position of the keyframe. That information needs to be stored in the bone, so it can be accessed by all it's children bones when they are calculating their BoneMatrix as we see above. When there is no keyframe, the CombinedMatrix is set to the default matrix, which is found in the bone frame inside the armature definition. Each bone calculates their final transform with the following:<br />
<br />
CombinedMatrix * BoneMatrix * SkinMatrix * InvertedBindMatrix<br />
<br />
Luckily, after we compute this once, we can save it and just retrieve the stored value whenever something asks for the transform for that bone and that frame. Interpolating key frames is fairly simple too. I just do linear transformation between the surrounding position and scale keyframes. For the rotation I <a href="http://en.wikipedia.org/wiki/Slerp" target="_blank">Slerp </a>between the two quaternions. Then create a new frame transform using those interpolated values. Again, once those are calculated once we save them and all further calls for that frame and animation just return the pre-calculated value.<br />
<br />
All in all, it's kind of complex, but breaking it down into its component parts can make the task achievable. Remember if you're implementing your own system, take it steps. Get a model with a single bone showing, then two bones. Then add a single animation with two frames, both keyed. And so on until you've reached full interpolated animation with complex armatures.<br />
<br />
Thanks for reading! Probably a somewhat boring post for those who aren't interested in making their own game. But it is a development blog, so I get to talk nerdy every once-in-a-while. I'll be making a video to show off animations soon.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com2tag:blogger.com,1999:blog-5255286524625277161.post-56451794082646284242012-12-03T19:56:00.000-08:002013-01-31T14:16:16.936-08:00The Blender connection (part 1)I use <a href="http://www.blender.org/" target="_blank">Blender</a> for all my modeling and animations. I chose it because it was free, ubiquitous and appeared to produce good results. This post will describe exporting that information from Blender and importing it into AoG. This information will not only help those wishing to duplicate this in their own games, but also help future modders of AoG make their own models.<br />
<br />
I'll start with the most basic application, a static mesh.<br />
<br />
<b>Step one</b>: Make a model! I won't go into the details of making models here, as that's a process I haven't even mastered myself. We'll use a tree:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhozsmN5k812n0-hFOjpxNiKf4CpebbSoWb4K53JH5Y930zsmxg3MZI85-QswEzFJ74yd6I-mTl_3o7svtGTVm-qdBwek4WBa1_GAz_pB1nAUppfkSGeoJn8kKEV6V0T_FAODFmLvNHYqM/s1600/tree_full_leaves.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhozsmN5k812n0-hFOjpxNiKf4CpebbSoWb4K53JH5Y930zsmxg3MZI85-QswEzFJ74yd6I-mTl_3o7svtGTVm-qdBwek4WBa1_GAz_pB1nAUppfkSGeoJn8kKEV6V0T_FAODFmLvNHYqM/s320/tree_full_leaves.PNG" width="260" /></a> </div>
<div class="separator" style="clear: both; text-align: center;">
<i><span style="font-size: x-small;">Clear proof I have not mastered model creation.</span></i></div>
<br />
<a name='more'></a><br /><br />
<br />
<b>Step two</b>: Export the model in the DirectX (.x) format. What? But I thought AoG was using OpenGL? Keen memory you have there reader. I use the DirectX format because it's fairly plain, easy to understand and supports all the features I want.<br />
<br />
Things I want to export:<br />
<br />
<ul>
<li>Vertex info: position, color, normal.</li>
<li>Armature information: bones, their hierarchy and their weighted vertices.</li>
<li>Animation data: bone animation key frames</li>
</ul>
<div>
Things Blender will export in the DirectX format:</div>
<div>
<ul>
<li>See above list.</li>
</ul>
<div>
<b>Step three</b>: Place the .x model file in the appropriate directory (TBD where the modders directory will be located). All the .x files are read into the <a href="http://www.byte56.com/search/label/lexicon" target="_blank">Lexicon </a>and are ready to use in game. I wrote my own importer to read the DirectX format. It's actually fairly simple, because the .x files are written in plain text, easy to read and understand. The exported data is arranged in a hierarchy very similar to how the "Outliner" organizes the scene in Blender:</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxa5SZQp1ZlyUc_5Vvdbm6I935XvnCtbrozwzTf4iyW9w158wqQxzG0jebnLAwsgGGHORaqkvPhDqru8HKA91hsgB4p5WONQOHCAV0IB-rIA64YKFPtibkDWyikMpspXuEC6zkOsI6OAE/s1600/blender_hierarchy.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxa5SZQp1ZlyUc_5Vvdbm6I935XvnCtbrozwzTf4iyW9w158wqQxzG0jebnLAwsgGGHORaqkvPhDqru8HKA91hsgB4p5WONQOHCAV0IB-rIA64YKFPtibkDWyikMpspXuEC6zkOsI6OAE/s1600/blender_hierarchy.PNG" /></a></div>
<div>
<br /></div>
<div>
The difference is that it's arranged as a series of nested Frames. Each frame has a transformation matrix associated with it. Each child frame assumes that the parent matrix has already been applied. So for example, the output of our tree looks like this:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisk86Cj3dg4okUEJsNRrJao4cKleWpVOW7DkFguZiElZSlLYBhPpbkfnJ5PAa2w5_FKLiKJuR0wbhSrbc2p_9uVK_TmjjXSpU7pagRcnUGXhSRFYCDl5tmlBDWSDr3zkJU4jBSKxF4zFw/s1600/frames.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisk86Cj3dg4okUEJsNRrJao4cKleWpVOW7DkFguZiElZSlLYBhPpbkfnJ5PAa2w5_FKLiKJuR0wbhSrbc2p_9uVK_TmjjXSpU7pagRcnUGXhSRFYCDl5tmlBDWSDr3zkJU4jBSKxF4zFw/s1600/frames.PNG" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Where as you can see the Root frame matrix rotates everything by 90 degrees on the X axis. This takes care of the "in Blender Z is up/down where as in games Y is up/down" aspect. This will get applied to everything inside of the Root frame (which is the entire scene). Next frame is our model the Tree. Looks like it has a little translation going on. It's moved .5 units up the Z axis (remember that it's going to end up being .5 units up the Y axis because of the Root transformation). A child of the Tree model is the full leaves frame. This is the frame the contains the green leaves mesh. Meshes are defined by, you guessed it, `Mesh {`. It has 60 vertices defined. The vertex positions are all listed in X;Y;Z format. Then the primitives are listed. There are 20 primitives. The primitives are each defined like:</div>
<div>
<br /></div>
<div>
<b>3;0;1;2;,</b></div>
<div>
<br /></div>
<div>
which means:</div>
<div>
<br /></div>
<div>
<b>number of indices; first index; second index; third index;,</b></div>
<div>
<br /></div>
<div>
So we have a triangle that goes from vertices 0->1->2. Those vertex positions are defined above, their index is the order in which they're defined.</div>
<div>
<br /></div>
<div>
Once you understand the way these are laid out, it's fairly simple to parse the rest of the data. For example, the texture coordinates:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIUZIYBlOcGW632ISv115LyO-vsLL_osbmaCO_nIUrSzAUQLzLhNF0O4Sa9A7dEe66F6yIpVeUqqM4J0QIINAHy0A9mqgD1sOdg3mkbY2_GqSUQ07tY8EthDlYTmSrg0icQ7UNUdzhPfg/s1600/texture_coords.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIUZIYBlOcGW632ISv115LyO-vsLL_osbmaCO_nIUrSzAUQLzLhNF0O4Sa9A7dEe66F6yIpVeUqqM4J0QIINAHy0A9mqgD1sOdg3mkbY2_GqSUQ07tY8EthDlYTmSrg0icQ7UNUdzhPfg/s1600/texture_coords.PNG" /></a></div>
<div>
<br /></div>
<div>
I'm sure you can guess that there's 60 texture coordinates and they're ordered to be paired with the order of the vertices defined earlier. If I'm not explaining it well enough, you can take a look at <a href="http://paulbourke.net/dataformats/directx/" target="_blank">this site</a>. Or just try exporting your own simple model (like a cube) and seeing what gets spit out and making sense of it. </div>
<div>
<br /></div>
<div>
OK, so now we know where our vertices are located, the order we should draw them in, their texture information and normal information. That's everything we need to know. So stuff all that data into a VBO and check it out!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR6CtM1jjj_CA9EpMcvMIBJfVcEA37RIrog-E9d264jWAT8ktZDhiRfNnNkVNBh_nFJRilRcy7sLrC6FQ_pqt_6h-1NH2FrugSZ3vpFopU8_uua9skTFoWayJ9KmLrkY9dbx4SKJV49OY/s1600/tree_blooper.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR6CtM1jjj_CA9EpMcvMIBJfVcEA37RIrog-E9d264jWAT8ktZDhiRfNnNkVNBh_nFJRilRcy7sLrC6FQ_pqt_6h-1NH2FrugSZ3vpFopU8_uua9skTFoWayJ9KmLrkY9dbx4SKJV49OY/s320/tree_blooper.PNG" width="309" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><i>... Aw damn it. That's why the game is still pre-alpha.</i></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><i><br /></i></span></div>
<div>
OK, so I needed to use Ctrl+A in Blender to apply the transformation of the full leaves. Basically this sets most of the matrices to the identity matrix because it just shifts all the vertex positions by the appropriate amount. I shouldn't have to do that, there's a bug in my "accessories" drawing code. The full leaves are an accessory because given certain conditions (like the season), I don't want to draw the full leaves. I'll have to find that bug... Anyway, I applied the transformations and re-exported:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidLqI6AcWBEghuTuIpIvrzxcfnAAOYkPUyq8m_xbhI1yApIw1Hx73KJSi3UNIP4w0W569qtu_V8-IyZh_0KyuIdb9v0PzLPOldSi6ZpnUXk7gZZpk_wwxIvvEkdC1sZ7GOrBNQCXIcYNc/s1600/tree_blooperFixed.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidLqI6AcWBEghuTuIpIvrzxcfnAAOYkPUyq8m_xbhI1yApIw1Hx73KJSi3UNIP4w0W569qtu_V8-IyZh_0KyuIdb9v0PzLPOldSi6ZpnUXk7gZZpk_wwxIvvEkdC1sZ7GOrBNQCXIcYNc/s320/tree_blooperFixed.PNG" width="290" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><i>That's better.</i></span></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Next time I'll cover exporting and importing animation. Thanks for reading!<br />
<br />
See part two <a href="http://www.byte56.com/2012/12/the-blender-connection-part-2.html" target="_blank">here, covering animations</a>.</div>
Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-5925821821943993322012-11-26T20:56:00.000-08:002013-01-31T14:16:36.573-08:00The latest changes<b>Animation System</b> - After getting animation working, I needed to implement a system for displaying animations. That's now in place. The animation system simply uses an event system to pass messages for animation changes. The animations have a few parameters defined, like delayed start amount, maximum play time and whether they should loop or not. It also includes an idle animation pool for each model. When defining animations in the data file I can add "IDLE_ANIMATION" to the name and it will be added to the idle pool. Additionally I define a weighted chance value for that animation. Then, when a entity is idle, it will choose randomly from the idle pool, the animations with a higher weighted chance will be chosen more often. These animation pools can be used for other animation types too! So any animation can have a animation pool. This makes it possible to have multiple animations per action. This way, things don't look so robotic, allowing for subtle changes for the same action. Animation really brings the game to life. It makes the goblins walking around and performing tasks look so much better. I'll show it off in the next video. Along with a few animations (so far I have walking, mining, picking up and dropping. Plus five idle animations).<br />
<br />
<a name='more'></a><br /><br />
<b>Model billboards</b> - In Blender I can add an empty object and give it a name. Then, in the entity definition file, I can add a Billboard attribute and tell it to place such and such a sprite and the name defined in the model file. Thus I can add billboard sprites to models, or make a model in blender composed entirely of empty objects and easily define the placement for billboards for an entity. For example:<br />
<br />
Adding leaves to an apple tree (billboard + model):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUNoG1x1lp7aHFjvEIJI7MaXu3k3DKiaVuzqdhZp-8liR77cnUFncDLJMZvbnY9XX5fEujMWXui9pLVx6ztWkCUxcZRcDLUdlLVmPEobI1ZF-6d_MCuPSyU1WMdSNG22mAI2XhBUofXBQ/s1600/appletree_leaves_billboards.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUNoG1x1lp7aHFjvEIJI7MaXu3k3DKiaVuzqdhZp-8liR77cnUFncDLJMZvbnY9XX5fEujMWXui9pLVx6ztWkCUxcZRcDLUdlLVmPEobI1ZF-6d_MCuPSyU1WMdSNG22mAI2XhBUofXBQ/s320/appletree_leaves_billboards.PNG" width="320" /></a>
<i><span style="font-size: x-small;"><br />(note the nifty selection box, more on that in a bit)</span></i></div>
<br />
Or defining the leaf locations for a NiNi Shrub (just using empty positions in Blender)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja9r3s1rSunyjuTcOuySi3LeXV_iHaZ2CNwVs_sWAL-xoUXdmCGxRVlnqU4BGiElFBtTwlJUR5m_6GeWafOwkOkC5YE_9vnR4iMouHeSleNDKGklBj8rfrWl6osgRSP9qlW7sETDfHV6Q/s1600/ninishrub_billboard.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja9r3s1rSunyjuTcOuySi3LeXV_iHaZ2CNwVs_sWAL-xoUXdmCGxRVlnqU4BGiElFBtTwlJUR5m_6GeWafOwkOkC5YE_9vnR4iMouHeSleNDKGklBj8rfrWl6osgRSP9qlW7sETDfHV6Q/s320/ninishrub_billboard.PNG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Arguably the latter type doesn't look too interesting in Blender:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg54qSmyX1uMqeLepGsiGBP80aJsd03hMOf3KVXyyQNaUtiFC12PZJkmrXtK9Y2qpNkpcC8iOsxArlXfxG9jZeQQCPpQYRLAQkMYG4MjYkqZMpIunAHmVjxJfg0aR7cylj6MGvHVdoaYbs/s1600/BlenderViewOfShrub.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="138" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg54qSmyX1uMqeLepGsiGBP80aJsd03hMOf3KVXyyQNaUtiFC12PZJkmrXtK9Y2qpNkpcC8iOsxArlXfxG9jZeQQCPpQYRLAQkMYG4MjYkqZMpIunAHmVjxJfg0aR7cylj6MGvHVdoaYbs/s320/BlenderViewOfShrub.PNG" width="320" /></a></div>
<br />
But it's a pretty nifty way for me (and modders) to define the locations of billboards for entities easily.<br />
<br />
<b>Entity Picking</b> - When models are read into the game, a bounding box is generated based on the bounds of the vertices read. That works great with static models, however, if the entity is animated with bones, that bounding box quickly becomes obsolete. So how to solve it? One way would be to run through the transformed vertices and calculate the bounds again. That doesn't work so well for me because the model vertices are on the graphics card from the beginning and that's where all the transformations happen. So, a slightly less accurate method. Get the bounds for each bone when the model is loaded. Then transform the bounding boxes by the animated pose.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMLTUukKqhsdzBE1yGA2QyUNBdOsw-243BvzDqKJF2-F_4cJyau6U6LV2b7el8v6Y_yCj-u7Nlj-mcu3VtH39-g3uMy0bwdZoIZQbYofYlDgCJLqhhZ_94Q5lVBzZ5uVU88GE1kDdiVmw/s1600/bonebounds2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMLTUukKqhsdzBE1yGA2QyUNBdOsw-243BvzDqKJF2-F_4cJyau6U6LV2b7el8v6Y_yCj-u7Nlj-mcu3VtH39-g3uMy0bwdZoIZQbYofYlDgCJLqhhZ_94Q5lVBzZ5uVU88GE1kDdiVmw/s320/bonebounds2.png" width="233" /></a></div>
Then we can just go through all of those bounding boxes and find the maximum and minimum bounds of those bounding boxes. Works great. The bounding boxes of the bones can over represent the model slightly, but it's pretty close. This allows me to not only select the entity with a picking ray, but it also allows me to detect the specific location of the entity that was selected. This means location based damage (useful for the dynamic dismemberment plans). Sweet.<br />
<br />
<b>Other</b> - Some miscellaneous completed tasks include:<br />
- Distant render types: When a model is far away from the camera it can either be rendered with a lower resolution model, a 2D sprite or nothing.<br />
- GUI work: I added sub radial menus. For expanding radial menus out in a tree like fashion for easy navigation of options.<br />
- Enemy work: I'm adding a simple entity to work on all the related systems for entities that don't like each other. That includes detecting when an enemy gets near, attacking and fleeing behaviors and plenty of other related work.<br />
- And more stuff that's insignificant or not complete enough to share yet.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com4tag:blogger.com,1999:blog-5255286524625277161.post-49801714262927414672012-11-01T16:56:00.000-07:002013-01-31T14:17:46.472-08:00Implementing animation was like pulling my own teethThese are the latest things to be checked off my to-do list:<br />
<br />
<ul>
<li><b>Model Animation</b> - This one took a while and had me pulling my hair out. Most of this went quickly and easily. Turning each bone's translation, rotation and scale into a transform matrix for the bone's vertices took a while. I just kept running into problems. I'd just look at the mangled mess of triangles that was a goblin just a moment ago before I applied the animation. Was my order of operations wrong? It's so close now, but the rotations are backwards. It's nearly working now but the rotations are around where it was before it translated. This is all wrong, redo. Redo, redo, redo. Finally, a clean working implementation. In the end it was just a collection of small issues that had to be solved in the correct order. But that's no matter now, it's working. Now that it's out of the way, it opens up some other tasks on the to-do list:</li>
<ul>
<li>Creating animations: Yes, I need to get all artsy and make animations for my models.</li>
<li>Animation system: Creating a system that decides which animation to apply and when. I have the framework for this already in place from implementing the model animation, I just need to flesh it out.</li>
</ul>
</ul>
<div>
<a name='more'></a></div>
<ul>
<li><b>Tag system</b> - With all the entities in game being defined by script, tags give me a way of, well, tagging entities to have certain actions performed with them. For example, I can add the `Storage` tag to entities that I want the goblins to look to when they're looking for somewhere to store their goods. Or I can add the `Material` tag to any entity I want to be considered for a crafting material. These tags get processed by the world when they're created. So if an entity has the `Storage` tag, its entity ID is added to the material manager as a receptacle (more on that in a bit). And entities tagged with `Material` get added to the material manager as a loose material. Overall these tags are a way of categorizing entities outside of the Entity/Component system. It's a better way for the world to know more about them without the need to add a component that contains this information. I don't particularly want to add components unless they are going to be active in a system.</li>
<li><b>Material manager</b> - The material manager is just what it sounds like. When goblins want to store a material, the material manager knows where all their storage zones are and which zones are accepting what materials. It also serves the other side of the coin. When goblins are looking for materials to build a structure or craft a thing-a-ma-jig, they can query the material manager to find the nearest materials that meet their bill. The material manager is really just a interface to another recent addition to the game, the spatial manager. The spatial manger is a generic spatial management system that implements spatial partitioning algorithms to find what stuff is closest to other stuff. Of course this is all invisible to the player, as they'll just see goblins dropping things off and picking them up at the nearest place.</li>
<li><b>Zones </b>- Zones are used to define anything from meeting places to where to harvest flora to where to dump the rubbish. I've implemented pathfinding related to zones as well so goblins can either find a path into a zone, or out of one. The path finding into a zone is useful for returning to the "home" zone and the path finding out of a zone is useful for clearing the area for a structure or cube placement.</li>
<li><b>Storage Bins </b>- Needing something to test out the changes implemented above, I created a basic storage bin. If a bin is available, and goblins don't have something better to do, goblins will transport materials to the storage bin for easy access. There's a neat incentive for using storage bins that I'll reveal when I'm further along with implementing it.</li>
<li><b>Various job improvements</b> - Goblins now have a pool of idle tasks to pick up if they feel like it. They can postpone their current task if it's low enough priority compared to a new task. Adding cubes will now use the material manager to select the optimal materials for building. A building task can not be queued up if the materials are not available.</li>
<li><b>Defensive auto cannons</b> - Yeah, those are kind of in there. I added the ability to add tags to bone names in Blender for use in animation. For example the defensive auto cannons have a tag for `Look_X_Axis` on one of their bones. That bone is then used when creating a "look at" matrix for targeting. This is just one more feature for future player customization. </li>
</ul>
Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-37283861530646696662012-10-31T17:56:00.000-07:002012-10-31T17:56:00.938-07:00MovedYou may have noticed that my blog is no longer hosted at Tumblr. Well, Tumblr has issues sometimes that are annoying. Since I'm already using Google for everything else, I guess I might as well use them here too. Sorry for those of you that were following me at Tumblr. I'll post links on Tumblr so you can continue to get updates.<br />
<br />
Additionally, I'll have an update on my progress soon.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-19181697286957918862012-10-19T20:56:00.000-07:002013-01-30T09:37:48.555-08:00How do you do it?Someone asked me:<br />
<blockquote class="tr_bq">
How do you find the time/energy to work on your game and be so active on GDSE AND hold down a ‘real’ job? I love coding, but when I come home from work, I’m beat.</blockquote>
It’s just a passion I have. I enjoy contributing to the game development community and making my game. I love to learn. I love to create. I hope that doing this will someday lead to game development being my ‘real’ job. <br />
<br />
Energy is an attitude. If you give yourself the easy option of browsing the <strike>internet</strike> reddit or watching TV, you’re going to do that instead. Don’t let yourself be lazy. Sometimes the effective strategy is to remove the alternatives (unplug your network), sometimes it’s just pure willpower or even changing your <a href="http://www.jonsuh.com/blog/design/keep-calm-and-get-to-work-wallpaper/">desktop wallpaper</a>. If you do this long enough, it’ll become habit. Let yourself feel bad for being lazy and feel good for being productive.<br />
<br />
I’ve done it long enough that productivity is a requirement. If I’m not productive I feel it. That has it’s own pros and cons. It’s important to find a balance that you and the people in your life can be happy with. All of it is easily under your power to do, just make the decision and stick with it.<br />
<br />
Exercise regularly. I cycle 8 miles a day, 5 days a week (rain or shine) and I play ultimate frisbee twice a week (read run around a lot for an hour). Cut out soda. Eat healthy food. Mind over body. It’s all about attitude. Healthy body, healthy mind.<br />
<br />
Anyway, that’s enough preaching from me. How do I do it? I just decide to do it, then I do it. It’s really as simple as that. Once you learn to do that, you can apply it to many aspects of your life.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com2tag:blogger.com,1999:blog-5255286524625277161.post-77744606065358047382012-09-21T23:56:00.000-07:002013-01-21T17:16:04.519-08:00How to go from theory to practice?<br />
I was recently posed a question:<br />
<blockquote class="tr_bq">
I’ve seen your <a href="http://gamedev.stackexchange.com/questions/31473/role-of-systems-in-entity-systems-architecture/31491#31491">post on gamedevse</a> about the entity component system, I had my share of trying to make one by myself, and though your description is beautiful, I fail to see how to code that. Can you give some example on how to go from theory to practice?</blockquote>
There’s an excellent example of an entity component framework with <a href="http://gamadu.com/artemis/">Artemis</a>. Download and study the source code. It may be confusing at first, but stick with it. Artemis really helped me understand how EC systems worked and I’m sure it’ll help you as well.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-88752178315519397042012-08-31T21:56:00.000-07:002013-01-21T17:16:44.965-08:00<br />
<blockquote class="tr_bq">
By saying it is you first game. Do you mean that you have never programmed anything before? not even like a pong game?</blockquote>
<br />
<div>
<br /></div>
I do plenty of programming. As for games, I’ve made simple little things before, but they were simple enough to be contained to one or a few files. This is the first real game I’ve made. I’ve never done anything in 3D or anything so complex. This is orders of magnitude larger than any programming project I’ve done, game or otherwise. Thanks for the question.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-36092447887751673922012-07-01T17:56:00.000-07:002013-01-21T17:17:35.331-08:00<a href="http://gamedev.stackexchange.com/a/31491/7191"><span style="font-size: x-large;"><b>Role of systems in entity systems architecture</b></span></a><br /><br /><br /> In lieu of a blog post, a long winded answer about systems in entity/systems architectures. Age of goblins implements a entity systems architecture.Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0tag:blogger.com,1999:blog-5255286524625277161.post-9796379832299798092012-06-25T22:56:00.000-07:002013-01-21T17:17:55.061-08:00New goblin jobs video. Also showing off some changes in cubes and touching on the scripting work I’ve been doing.<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Geph11f6ySM?feature=player_embedded' frameborder='0'></iframe></div>
<span style="background-color: white; color: #444444; font-family: 'Helvetica Neue', HelveticaNeue, Helvetica, Arial, sans-serif; font-size: 14px; line-height: 19px;"><br /></span>Anonymoushttp://www.blogger.com/profile/06624340630711937187noreply@blogger.com0