Home

Monthly Archives: September


Farms revisited  

Coobico: Farm

A farm is one of the first picks to grow your settlement as it acts the primary source of food-supply for a town—no changes so far, but we lately revisited the old model and replaced it with the above version, which features some nice and detailed touches.


Scholar  

Coobico: Scholar

A scholar leads a secluded life at a scholar’s quarter or at a university and devotes himself to teaching and studying and thus helps to raise the enlightenment of an associated settlement. Scholars help to counter the negative effects of nearby graveyards.


Structures: Scholar  

Coobico: Scholar

One of the key-characteristics of each settlement is its enlightenment, which in turn raises public order and the general happiness of all inhabitants. Enlightenment is “produced” by a either a scholar (see image, to the left) or by an upgraded university (to the right). A scholar is one of the structures which is going to be build at a later stage of the game, as it needs a guildhall as a prerequisite.


Guildmaster  

Coobico: Guildmaster

A guildmaster presides over workshops and guildhalls and raises the crafts-level of a settlement. He regularly issues temp-jobs and other quests.


Structures: Workshop  

Coobico: Guildhall

Introducing the workshop, industrial hub of almost each settlement. Even though a workshop increases the level of pollution of its city, it is nonetheless indispensable, because an upgraded workshop (called a “guildhall”) acts as a prerequisite for certain other important structures, like the healer. Also, a guildhall is the place where you can pick up temp-jobs.


Recommended Reads: debunking the stereotypical gamer  

International research-firm Wiley is currently offering their study “Who plays, how much, and why? Debunking the stereotypical gamer profile” for free, a very interesting read. While nearly every developer in the field of virtual worlds seems to be focussed on entering the teen- and pre-teen market, it is funny to read that the majority of all gamers are more than thirty years old.

By the way, we already assumed a year ago that this is the largest target-group when it comes to games and virtual worlds—it’s always nice to be proven right… smile


Back-end: a quick introduction on parsing VRML  

Let’s take a quick look on how to parse VRML for any of the open-source 3D-engines like Away3D, Papervision or Sandy3D. To be more specific, I am talking about VRML2 (.WRL), which can be exported with any standard 3D-software. Unfortunately, some 3D-packages translate VRML geometry-nodes as IndexedFaceSets only, which is basically just a long list of vertices and not suitable for this method of parsing—an example for such unsuitable encoding is Cinema4D. You will need a 3D-package which encodes appropriate geometry-nodes, like 3DMax. 

The actual parsing is no rocket-science—since VRML is a human-readable format, you mainly have to deal with string operations nested inside an array-filter loop. Let’s take a look at typical VRML-grammar first:


#VRML V2.0 utf8
# Produced by 3D Studio MAX VRML97 exporter, Version 9, Revision 1
# MAX File: level.max, Date: Sat Sep 6 8:00:00 2008

DEF myTestBox Transform {
  translation 317 100 -57
  children [
      Transform {
        translation 0 11.5 0
        children [
          Shape {
            appearance Appearance {
              material Material {
                diffuseColor 0.03137 0.2392 0.5412
              }
            }
            geometry Box { size 20 23 20 }
          }
    ] }
  ]
}

Above you can easily spot all necessary information to parse and recreate the according scene in Actionscript: primitives and their names, coordinates and dimensions. Here is some basic code as a starting-point:


private var container:TransformGroup;
/*for Away3D change TransformGroup to ObjectContainer3D*/
private var vrmlString:String;

/*return-type TransformGroup is for Sandy3D, 
for Away3D choose ObjectContainer3D instead*/
private function parseVRML( $vrmlString:String ) : TransformGroup
{
   this.vrmlString = $vrmlString;
   var nodesInclCamera:Array = vrmlString.split( ‘DEF ‘ );
   /* remove VRML-header */
   nodesInclCamera.shift();
  /*exclude camera-node*/
  var nodesExclCamera:Array = nodesInclCamera.filter( filterCamera );

  container = new TransformGroup( ‘container’ );
  /*Away3D: container = new ObjectContainer3D();*/
  /*iterate over all geometry-nodes*/
  nodesExclCamera.forEach( processNode );
  
  return container;
};

private function filterCamera( element:*, index:int, arr:Array ):Boolean 
{
  return ( element.match( ‘Camera’ ) == null ); 
};

private function processNode( element:*, index:int, arr:Array ) : void 
{
  var helperArray:Array = element.split( ‘geometry ‘ );
  var primitive:String = helperArray[ 1 ].substr( 0, helperArray[ 1 ].indexOf( ‘ ‘ ) );
  var properties:Object = new Object();
  properties.name = element.substr(0, element.indexOf( ‘ ‘ );

  /*parse size*/
  var sizeSub:String = element.substr( element.indexOf( ‘size’ )+5, element.length);
  var sizeSplit:Array = sizeSub.split( ‘ ‘ );
  properties.width = sizeSplit[ 0 ];
  properties.height = sizeSplit[ 1 ];
  properties.depth = sizeSplit[ 2 ];

  /*parse position*/
  var transSub:String = element.substr( element.indexOf( ‘translation’ )+12, 
   element.indexOf( ‘ children’ ) );
  var transSplit:Array = transSub.split( ‘ ‘ );
  properties.x = transSplit[ 0 ];
  properties.y = transSplit[ 1 ];
  properties.z = transSplit[ 2 ];	

  /*parse rotation*/
  /*properties are called rotateX, rotateY and rotateZ in Sandy
  Away3d: change to rotationX, rotationY and rotationZ*/
  if ( element.match( ‘rotation’ )  != null)
  {
    var rotSub:String = element.substr( element.indexOf( ‘rotation’ )+9, 
    element.indexOf( ‘ children’ ) );
    var rotSplit:Array = rotSub.split( ‘ ‘ );
    properties.rotateX= Number( rotSplit[ 0 ] ) * Number( rotSplit[ 3 ] ) * 100;
    properties.rotateY= Number( rotSplit[ 1 ] ) * Number( rotSplit[ 3 ] ) * 100;
    properties.rotateZ= Number( rotSplit[ 2 ] ) * Number( rotSplit[ 3 ] ) * 100;
  } 

  container.addChild( this[ ‘_create’ + primitive ]( properties ) ); 			
};

/*return-type for Away3D is Cube instead*/
private function _createBox( properties: Object ) : Box
{
  var shape:Box = new Box();
  /*Away3D: var shape:Cube = new Cube();*/
  for( var p:String in properties ) shape[ p ] = properties[ p ];
  return shape;
};

The first filter separates the camera-node from the other primitives. You can either delete this node (like in this case), or even use it to create your 3D-camera at this point:


var nodesExclCamera:Array = nodesInclCamera.filter( filterCamera );

private function filterCamera( element:*, index:int, arr:Array ):Boolean 
{
  return ( element.match( ‘Camera’ ) == null ); 
};

The second filter iterates over all geometry-nodes. Here you can add code to build the actual 3D. This example calls a dynamic function depending on the type of geometry-node (like Box, Sphere and so on)—of course this works only with the types of primitives supported by your 3D-engine of choice. Also keep in mind that the different engines have different names for their primitives; a cubic shape’s Class is called “Cube” in Away3D and “Box” in Sandy3D. Generally, Sandy3D is very conforming to VRML-grammar (good work, guys):


container.addChild( this[ ‘_create’ + primitive ]( properties ) ); 	

The function call passes an object which stores all according values. The function then returns the appropriate primitive:


/*return-type for Away3D is Cube instead*/
private function _createBox( properties: Object ) : Box
{
  var shape:Box = new Box();
  /*Away3D: var shape:Cube = new Cube();*/
  for( var p:String in properties ) shape[ p ] = properties[ p ];
  return shape;
};

That’s the general technique. I am not going to cover the rest here, like applying textures and so on. VRML stores texturing- and shading-information in Appearance- and Material-nodes, which can be parsed in a similar fashion, I think you get the point—happy coding… smile


Healer  

Coobico: Healer

Healers resides at a (big surprise) healer’s home or at a hospital. Their main duty is to raise the level of medical supply for the according settlement, but they will occasionally ask adventurers to accomplish quests (like fetching medicinal herbs).