David J McClelland

eLearning Designer / Developer

Archive for the ‘Practice’ Category

What Does Experience Look Like? Closed Captioning.

I am in the process of publishing around 100 Captivate projects which came from a software vendor – I have never seen them before. At some point I hear that many learners will not be able to listen to the narration and will need to read the captions. Realizing that the courses have Closed-Caption text, I suggest setting the courses to display the captions by default. This will avoid the challenge of educating learners about the feature while ensuring it gets used. But Captivate Skin Editor doesn’t have a setting to display CC by default. I Google around and find a Flash animation that is supposed to provide the functionality. I try it and it doesn’t work. Time to crank up the custom actions and build a script! A minute later and I have the captions displaying – yay!

Since narration begins on the second slide I think “this looks more polished and professional if I raise the CC bar when the narrator starts talking.” Testing reveals that this change prevents the CC from appearing when returning to where I left off in the course.  Switch it back to slide one and the CC is back. Captivate always loads Slide one before resuming at a bookmarked slide.

Probably 99% of what I am doing is repetition – publish one couse after another. I suppose I could train a monkey and leave the gig. A trainer assigned to “do eLearning” may have shrugged when automatic CC display didn’t appear to be an option. But because of broad experience with Captivate and other tools, I was able to poke around for less than 20 minutes and come up with a significant improvement to the content.

Experience is valued in the abstract, but rarely makes tangible appearances where a client can say “That’s what I am paying for!” A lot of the value of experience is negative: not doing things that didn’t work before. Not wasting time. No one gets to see that, including the experienced practitioner. There are many habits and patterns that have become automatic through experience – not celebrated.

I am very conscious of this fact. I try to notice when I do something tangible in case it helps my client justify hiring my experience on a project. It can be a challenge to recognize when it happens. I am reminded of interviews where a reporter gushes about a heroic rescue, and the fireman says  ” I was just doing my job.” (Not to compare professions).

So I can relate to the uncelebrated Closed Caption bar that finally will make an appearance in a starring role.

Post to Twitter

  • 0 Comments
  • Filed under: Practice, Tools
  • Alignment Matters

    Alignment to client goals seems pretty abstract when there is work to be done to make the deadline and a clear path forward.

    For example, when a brief includes a requirement to support translation into unlimited languages it seems pretty clear that resource bundles need to be used. That master XML files will be delivered to translation and swapped at runtime or as needed.

    But what if the client is bound to an agreement to send out the entire project for translation to a “preferred vendor”? What if the translation service knows nothing about resource bundles, or pretends not to in order to continue to make its forecast profit on billings for Flash-savvy translation services?

    Well, that alignment thing becomes a painfully concrete when the PM realizes that they didn’t build in time to train the translation service to not touch the source. That the whole point is to NOT build n*languages source folders. That we aren’t ever going to get the XML containing the translated text. That we are completely out of the loop until everything falls apart and the blame for the disaster you don’t even know about comes in a plain text email.

    And particularly acute when the promise of substantial savings on translation evaporates in a cloud of unpaid work for (and simultaneous accusations from) the translation service.

    Post to Twitter

  • 0 Comments
  • Filed under: Practice
  • Finding PushButton Engine Tutorials for Version 1

    PBE provides some very simple, basic tuts on their docs page that will get you up and running quickly. After completing them I knew I needed to learn more about managing levels, spritesheets, projections, efficient ways to manage components, collisions, layer depths, and so forth.

    If you tried them and found them frustratingly unable to compile, try them again: they were updated recently to match the examples that are included in the distribution download.

    I was able to compile and build all of the tuts from a single project directory into Flex Flash and FlashDevelop. The Flex project is really an ActionScript project, but putting it in an MXML is trivial.

    Mathew Casperson Tutorials

    The next tutorial series I tried was very useful, because it starts a series demonstrating the use of a factory class to build game sprites. Unfortunately it was written before a refactor that changed a lot of things in the code.

    An initial compile attempt in Flex yields:

    1046: Type was not found or was not a compile-time constant: Scene2DComponent.
    1046: Type was not found or was not a compile-time constant: SimpleShapeRenderComponent.
    1119: Access of possibly undefined property instance through a reference with static type Class.
    1120: Access of undefined property Global.
    1180: Call to a possibly undefined method Scene2DComponent.
    1180: Call to a possibly undefined method SimpleShapeRenderComponent.

    To fix the MXML:

    replace script contents with this:

    import com.pblabs.rendering2D.ui.FlexSceneView;
    import com.pblabs.engine.*;
     
     protected function appComplete():void
     {
       PBE.startup(this);
     
       var sceneView:FlexSceneView = EntityFactory.createScene("scene");
       addChild(sceneView);
       EntityFactory.createPlayer("player", "scene");
     }

    To fix the EntityFactory class:

    import PBE and FlexSceneView

    Replace entire createScene method with this:

    static public function createScene(name:String):FlexSceneView
     {
     var sceneView:FlexSceneView = new FlexSceneView();                        // Make the SceneView
     sceneView.width = 800;
     sceneView.height = 600;
     
     PBE.initializeScene(sceneView);
     return sceneView;
     }

    Replace entire createPlayer with this:

    static public function createPlayer(name:String):IEntity
     {
     var entity:IEntity = allocateEntity();                                 
     
     var spatial:SimpleSpatialComponent = new SimpleSpatialComponent();   
     
     spatial.position = new Point(0,0);                                   // Set our hero's spatial position as 0,0
     spatial.size = new Point(50,50);                                     // Set our hero's size as 50,50
     spatial.spatialManager = PBE.spatialManager;                                
     
     entity.addComponent( spatial, "spatial" );                             
     
     var render:SimpleShapeRenderer = new SimpleShapeRenderer(); 
     
     render.isCircle = true;
     render.radius = 25;
     render.positionProperty = new PropertyReference("@spatial.position");
     render.scene = PBE.scene;
     entity.addComponent( render, "render" );
     
     entity.initialize(name);
     
     return entity;
     }

    The next tutorial introduces keyboard control, which is handled almost identically to the one in the PBE tutorials. To make it work add the component definition to EntityFactory verbatim.

    Replace the contents of  keyboardController.as with:

    package
    {
    	import com.pblabs.engine.PBE;
    	import com.pblabs.engine.components.*;
    	import com.pblabs.engine.core.*;
    	import com.pblabs.engine.entity.*;
     
    	import flash.geom.Point;
     
    	public class KeyboardController extends TickedComponent
    	{
    		public var positionReference:PropertyReference = null;
    		public var speed:Number;
    		protected var xMovement:Number = 0;
    		protected var yMovement:Number = 0;
     
    		public override function onTick(tickRate:Number):void
    		{
    			var position:Point = owner.getProperty(positionReference);
     
    		 	if (PBE.isKeyDown(InputKey.RIGHT))
    		 	{
                    position.x += 1*speed;                // Move our hero to the right
        		}
                if (PBE.isKeyDown(InputKey.LEFT))
                {
                    position.x -= 1*speed;                // Move our hero to the left
                }
                if (PBE.isKeyDown(InputKey.UP))
                {
                	position.y -= 1*speed;
                }
                if (PBE.isKeyDown(InputKey.DOWN))
                {
                	position.y += 1*speed;
                }
     
                if (position.x > 374)
                {
                    position.x = 374;                // Set our position at the wall edge
                }
                else if (position.x < -374)             {                 position.x = -374;               // Set our position at the wall edge             }             else if (position.y> 274)
                {
                	position.y = 274;
                }
                else if (position.y < -274)
                {
                	position.y = -274;
                }
                // Send our manipulated spatial variables back to the spatial manager
                owner.setProperty(positionReference, position);
    		}
    	}
    }

    The next tutorial shows how to embed a bitmap and animate it in place of the simple circle shape. Replace these lines:

    var Render:SpriteRenderComponent = new SpriteRenderComponent();
    Render.loadFromImage = "../media/idleright.png"; 
    

    with these:

     var render:SpriteRenderer = new SpriteRenderer();
     render.fileName = "../media/idleright.png";

    I tried several tutorials on spritesheets and none of them would both compile and work. The closest I got was an example that would compile and display the first frame in the sheet. Not giving up though – it will be my next post for sure!

    Post to Twitter

  • 0 Comments
  • Filed under: Practice, Tools
  • Dead PC After Power Outage

    green-power-button-150x150

    After a 3-hour power outage ended, my tower seemed completely dead when I tried to power back up. I chalked it up to the number of surges that preceded the final restoration and an old Surge protector.

    I congratulated myself on having a fairly robust off-site backup system in place, along with a laptop that is a close mirror to the tower. I removed the main drive and updated my laptop to the previous day’s work via a family PC.

    Today I was at a client’s office when I heard the same thing happened to them (they were affected by the same outage). Their main server wouldn’t come up after repeated attempts: bypassing the battery backup (which was drained), replacing the AC cord, taking covers off and fiddling, incantations… nothing.

    After scrambling to get some vital functions working without the server a final, last-ditch press on the power and “woosh!” Power on!

    What happened? Whatever it was, would it work for me and my tower too?

    The explanation I was given is that the clock battery on the motherboard had gone dead at some point, and it needed some time to get enough charge in it to allow the boot process to run.

    And yes, it worked for my tower too!

    Post to Twitter

  • 0 Comments
  • Filed under: Practice
  • Flash Tiled Backgrounds

    There weren’t many results for a search on “Flash Tiled Background”.

    I found a code library awhile back that has a decent implementation. The library, flashscript, can be found at http://www.flashscript.biz/.

    If you import biz.flashscript.background.TiledBack and create a TiledBack instance you can duplicate the familiar css background technique to fill the stage with a repeating pattern of a bitmap you provide.

    Here is an example class to try the class out:

    package
     
    {
     
        import biz.flashscript.background.TiledBack;
     
        public class TiledBackgroundMain extends MovieClip
        {
     
            public var background:TiledBack;
            public function TiledBackgroundMain()
            {
                init();
            }
     
            private function init():void
            {
                background = new TiledBack(stage, "exampleTile.png", stage.stageWidth,stage.stageHeight);
                addChild(background);
                addListeners()
            }
        }
    }

    Example Tile

    Example Tile

    Example Output

    Post to Twitter

    Shiny