Josh Sager Media: Creative Technologies Blog

Josh Sager Media: Creative Technologies Blog
Creative Technologies Blog
Home | Portfolio |Blog | Presentations | music | About

Archive for the ‘Technology’ Category

iPhone Blogging

Saturday, August 15th, 2009

I just set up my iPhone as a publishing device for my blog. It’s pretty cool. I find it funny that my laptop isn’t mobile enough for me anymore.

What About the Blog? Did Twitter Steal It?

Friday, August 14th, 2009

I’ve just finished another year of semi-pro football, which keeps me very busy, and during that time I relied heavily on social networking tools like Facebook and twitter as my way to share cool links, information, and other random tidbits. It got me thinking about the role of blogs vs twitter and other micro blogging tools.

The Blog Evolution

Initially I used my blog to share my opinions about technology and all things creative, then it moved into a re-posting stage where I wasn’t really providing anything new, but I still wanted to share or aggregate the information as a resource for others and honestly for me as well. After a while I felt that I was more of a distributor rather than a contributor so I evolved toward generating new content. I vowed to only contribute new content.

I’ve realized a few things in this journey.  Creating new content takes time if it’s going to be accurate and worth while.  There were many little tidbits that I wanted to share but the moment passed and off it went.

Micro-Blog

Then I started using my status updates as a micro-blog and it satisfied my need to communicate all of the small things.  But as the topics grew in complexity micro-blogging lacked the ability for me to communicate my entire thoughts or reactions to a particular subject, question, or topic. Tweets will go from white hot to white noise in a matter of minutes.  Leaving interesting points, questions, and problems unresolved.

Etiquette of Digital Distribution

Which poses a question.  What role do these technologies play in your digital lifestyle? Have you ever thought about information distribution etiquette and what tools should be used?  When is a blog post really just a tweet and when does a tweet graduate into a full blown blog post beyond general commentary.

In my digital lifestyle my blog is a way to think in prose. An opportunity to put thought and compose an article, essay, rant, opinion or lesson. It takes more than a few minutes to write a blog post (which is probably why I post infrequently).  On the other hand I use my status updates as a micro-blog at least 3 or 4 times a day yet I’m reluctant to post these life updates and cool links to a blog.

As a result of this I’m going to move toward categorizing my posts into buckets.  At least internally. A bucket for opinions and commentary, links and resources, and original content. All three seem important and flexible.  I guess I have this idea that a blog should be more like a newspaper or magazine, but it’s not.  It’s a blog. It’s not entirely professional, but it’s still useful.  If for nothing else it’s a way for me to organize my thoughts.

But now I turn it over to you.  What is the etiquette of new media in your life?

Unit Testing With ActionScript 3.0

Tuesday, July 21st, 2009

Last week I gave a presentation on Unit Testing with ActionScript 3.0 using the new bright and shiny Flash Builder for the Pittsburgh Adobe Flash Users Group. The new tools in Flash Builder are amazing and make it 100 times easier than using Flex Unit by itself.  Flash Builder generates starter code that really helps the developer hit the ground running and begin writing test cases against their code.

I’m debating if I will have some time to put a screen cast together for it, but you can grab the source files below.

Source Files and Slides for Unit Testing

Timecode for FLVPlayback JSFL Style

Tuesday, May 26th, 2009

The Problem

A few weeks ago a co-worker of mine was grading video projects and wanted a way to see the time code of the FLV. He needed a way to communicate with his students so they understood where in the video the feedback applies  I told him, hey that’s not a problem sat down to write some code thinking it would be just an easy text box thing.

After a few more conversations I thought about the problem a little further and determined there were more things to consider.

  1. The video students aren’t too savvy with code or the actions panel
  2. The time code should display relatively in the same place depending on the selected skin
  3. They really needed something that had as few clicks, and prompts as possible

This was a perfect opportunity to mess around with JSFL.  JSFL stands for Java Script Flash and it allows a developer to create utilities that can interface with the Flash IDE and in this case I needed to place a FLVPLayback component on the stage as well as some actions in the actions panel.  I needed this to be as transparent to the intended user as possible.

I started by adding the component

fl.componentsPanel.addItemToDocument({x:0, y:0},"Video","FLVPlayback")

Then I created a test to add actions to the actions panel

fl.actionsPanel.setText("code");

Then I transformed my original time code actions so they would pass as the argument. Now I’m sure there’s an easier way to do what I did, but it totally works.

The Solution

fl.componentsPanel.addItemToDocument({x:0, y:0},"Video","FLVPlayback")

fl.componentsPanel.addItemToDocument({x:0, y:0},"Video","FLVPlayback")

var code

code ="import fl.video.VideoEvent;\n"
code +="import fl.video.FLVPlayback;\n"

code +="var bob:*\n"

code +="for (var j:int = 0; j<numChildren; j++){"
code +=	"if(getChildAt(j).toString()=='[object FLVPlayback]'){	\n"
code +=		"bob = getChildAt(j)\n"
code +=		"break;\n"
code +=	"}\n"
code += "}\n"

code += "\n"
code += "\n"
code += "var timeCodeBox:TextField = new TextField()\n"
code += "timeCodeBox.text =''\n"
code += "timeCodeBox.background=true\n"
code += "timeCodeBox.autoSize = TextFieldAutoSize.LEFT\n"
code += "addChild(timeCodeBox)\n"

code += "bob.addEventListener(VideoEvent.PLAYHEAD_UPDATE, onUpdatePlay)\n"

code += "function onUpdatePlay(e:VideoEvent){\n"
	code += "timeCodeBox.text = getTime(e.target)\n"
	code += "for(var i:int=0; i<e.target.getChildAt(1).numChildren; i++){\n"
	code += "if(e.target.getChildAt(1).getChildAt(i)=='[object SeekBarHandle]'){\n"
		code += "//trace(e.target.getChildAt(1).getChildAt(i).x)\n"
		code += "timeCodeBox.x = e.target.getChildAt(1).getChildAt(i).x+ e.target.x - (timeCodeBox.width/2)\n"
		code += "timeCodeBox.y = e.target.getChildAt(1).getChildAt(i).y + e.target.y-28\n"
		code += "}\n"
	code += "}\n"
code += "}\n"

code += "function getTime(obj:*):String{\n"
    code += "var tempS:Number = Math.floor(obj.playheadTime)\n"
	code += "var tempM:Number = Math.floor(obj.playheadTime/60)\n"
	code += "var tempH:Number = Math.floor(obj.playheadTime/3600)\n"
	code += "var seconds:String\n"
	code += "var minutes:String\n"
	code += "var hours:String\n"
	code += "tempS %= 60\n"
	code += "tempS<10?seconds = '0'+tempS:seconds=tempS.toString()\n"
	code += "tempM<10?minutes = '0'+tempM:minutes=tempM.toString()\n"
	code += "tempM<10?hours = '0'+tempH:hours=tempH.toString()\n"
	code += "//trace(hours+':'+minutes+':'+seconds)\n"
	code += "return hours+':'+minutes+':'+seconds\n"
code += "}\n"

fl.actionsPanel.setText(code);

Final Thoughts

Feel free to use this and modify it. It’s not designed to be pretty right now, just to allow our students to communicate about time code. If you have any questions let me know. Otherwise enjoy

Where’s the MovieClip in Flex?

Saturday, April 11th, 2009

The Transition

Making the transition from AS 3.0 Developer to Flex Developer has been a bumpy ride. I can best describe it like moving to another country that’s similar but different enough to feel not at home. My go-to tricks that were oh so reliable don’t exist. Common items have different names. Routine tasks have an extra wrinkle. From the outside it appears like it’s all the same, but the details are quite different. Similar results, but very different paths are traveled.

MovieCilp Love Story

One of the hardest things for me was adjusting to life without MovieClips. When I first started Flex development I liked the idea of components. I was drawn to the Horizontal and Vertical layout schemes that are oh so (wait for it…) very FLEXible. But I missed the MovieClip. It was my first love and it had it all. It had frames, it could be instantiated, and it was click-able. What more could you want? But now we’ve both graduated and have moved on to other things. I’m doing more development while she’s concentrating on time lines and animations.

Reunion

Well I’ve recently had a breakthrough and I can thank Joey Lott and Chafic Kazoun for helping me get there. I’ve been looking at Flex Development through the eyes of Flash instead of embracing the Flex way of life. My first steps was to let go of the name MovieClip and look for it’s functionality in other places.

At it’s core the Application tag is really just a 2 frame MovieClip with sub clips containing assets that can do all sorts of things. Frames are really similar to states. Instantiation of components is done much the same way. I was getting along okay, but I was still hung up on a few stupid little details.

Can I Draw In Flex?

Although I’m embarrassed to share this, I’ve been trying like hell just to draw a simple circle and add it to the display list in Flex for longer than it should have taken me. I thought I’ve tried everything, but my problem was that I was following the AS 3.0 diagram. I started at MovieClip. Ennnnnnnttttttt! Wrong answer. Then I progressed up the tree to Sprite. Sarrrrr-reeeey! Then up to DisplayObjectContainer… ummm graphics aren’t available here. DAMN! WTF? How can something built on top of AS 3.0 not allow me to create something simple like a circle?

Potaeyto Potahhto

Then I found it. Flex uses a different structure. Instead of MovieClip it’s called Container. See for yourself.

  1.  
  2.  
  3.         <![CDATA[
  4.         import mx.core.Container;
  5.         private var mc:Container = new Container();
  6.  
  7.         private function createCircle():void{
  8.                 this.addChild(btn);
  9.  
  10.                 mc.graphics.beginFill(0xFF0000)
  11.                 mc.graphics.drawCircle(0,0,40);
  12.                 mc.x=75
  13.                 mc.y=100
  14.                 this.addChild(mc)
  15.         }
  16.  
  17.         ]]>

Container is built on a similar structure that roots in something called a FlexSprite. The big differences stem from the fact that most objects in Flex generally have some sort of chrome. Flex is geared for prototyping functionality very quickly, not necessarily graphics and animation. Although you do have the ability to create graphics and animation… sort of. Flash is still best suited for that sort of thing. Flex’s makes it’s living on functionality though panels, widgets, components, and states. Container is one of the building blocks used to create anything from a Box, to a Canvas to even an Application.

Finding container was a big key piece to bridging my AS 3.0 and Flex development together.

### AMENDMENT ####
I’ve just recently found out about custom component development which bring Flex and AS 3.0 much closer together. You can have access to Object and instantiate it. I’ll post about it as soon as I can.

The Flash IDE Under the Hood

Saturday, April 11th, 2009

Reflection

In what seems like a lifetime ago I made the jump to AS 3.0, and along the way I’ve had all sorts of questions as to why things happen and what’s really going on behind the scenes.  Recently I’ve discovered something very interesting to me that has helped me better understand some how’s and why’s.

Flash From the IDE Perspective

So you’ve got a project. You open up your trusty version of Flash and create a new AS 3.0 document. You create a button, load some xml, toss some images in and pretty much do your thing.

ActionScript 3.0 From a Class Perspective

So you progressed with AS 3.0 and plunged into class development. Now all the xml, button, and event functionality you’ve taken for granted must be imported. If you’re like me you probably said to yourself “mmmm ookay, whatever…” and you moved on.  Well I’ve always wanted to know more about the default AS 3.0 .fla.

On a few occasions I got the crazy idea of tracing out it’s parent by opening up a default file and placing this code on the first frame.

  1. trace(root)
  2. // outputs [object MainTimeline]

What is this MainTimeline and more importantly what does it contain? Well just recently I came across some code that tells me.

  1.  
  2. trace(flash.utils.describeType(root))
  3.  

You get an xml output of extended classes and parameters.

Some interesting elements

  1.  
  2.   <extendsClass type="flash.display::MovieClip"/>
  3.   <extendsClass type="flash.display::Sprite"/>
  4.   <extendsClass type="flash.display::DisplayObjectContainer"/>
  5.   <extendsClass type="flash.display::InteractiveObject"/>
  6.   <extendsClass type="flash.display::DisplayObject"/>
  7.   <extendsClass type="flash.events::EventDispatcher"/>
  8.   <extendsClass type="Object"/>
  9.  

As I started to dig deeper I went above the Main Timeline to the Stage and rain the similar trace.

  1.  
  2. trace(flash.utils.describeType(parent))
  3.  

Conclusions

  1. Flash runs on xml… at least for preferences
  2. It’s pretty cool to see what the IDE is doing by default
  3. describeType can give me better insight into my objects

Flash Cart: Macgyver Style

Tuesday, March 31st, 2009

Have you ever been on a code mission? You know one of those stubborn solution quest where nothing else matters.  Time passes around you in slow mo like Zack Braff in Garden Sate.  And the one thing that keeps you going is you know in your heart that there’s an answer and that you refuse to let roadblocks, errors, and ignorance stop you from getting something accomplished.

I Don’t know about your but for me they always sneak up out of nowhere.  Like at 4:59pm on a Friday somebody asks you for something that you think is a piece of cake, then Sunday rolls around and you’re still plugging away only to blink you eyes and realize you just missed Family Guy.

Well I just got back from one of these pilgrimages. Afterwards I typically come out of them feeling triumphant, disappointed with the amount of effort I just gave, and yet little more wise.  Usually because I missed something small in the beginning and along the way I discover a neat technique that changes my outlook on development in some way.

Every now and again I get on these little missions. Code journeys where I’m determined to find a way to make something work regardless of what other options might exist. Sometimes these missions are created by my environment and sometimes they are created by me.

This particular code mission was basically the development of a faux shopping cart system.  Just a demo to add and remove products.  Pretty easy right?  Well that’s what I thought. To add a little more fun to the situation I wanted to avoid used components.  I know I know I know it would have been easier, but this is a proof of concept for a much larger piece and compoents were not an option.  If your curious why DM me sometime and I’ll give you the low down.

Anyway it’s not perfect but I’ve got the proof of concept working

  • Multidimensional arrays
  • MovieClips as my receipt placeholders
  • Methods to add, remove, display the cart as well as the total

As the infinitely wise Colin Mook says if it works it’s not wrong.

So have it folks

flashcart.fla
flashcart.swf

  1. // array creation
  2. var productsArray:Array = new Array()
  3. var cartArray:Array = new Array()
  4. var cartClipArray:Array = new Array()
  5. // total
  6. var total:Number = 0
  7. // products
  8. productsArray[0] = {price:3, name:"burger", qty:0}
  9. productsArray[1] = {price:5, name:"drink", qty:0}
  10. productsArray[2] = {price:2, name:"fries", qty:0}
  11. productsArray[3] = {price:10, name:"shake", qty:0}
  12. productsArray[4] = {price:1, name:"cookie", qty:0}
  13. productsArray[5] = {price:2, name:"coffee", qty:0}
  14. // cartClips — These are the movieclips on the stage that reprecent my items added
  15. // to the cart
  16. cartClipArray[0] = cartClip0
  17. cartClipArray[1] = cartClip1
  18. cartClipArray[2] = cartClip2
  19. cartClipArray[3] = cartClip3
  20. cartClipArray[4] = cartClip4
  21. cartClipArray[5] = cartClip5
  22. cartClipArray[6] = cartClip6
  23. cartClipArray[7] = cartClip7
  24. cartClipArray[8] = cartClip8
  25. // clearcart
  26. // a for loop wouldn’t work here — go figure :P
  27. cartClipArray[0].visible=false
  28. cartClipArray[1].visible=false
  29. cartClipArray[2].visible=false
  30. cartClipArray[3].visible=false
  31. cartClipArray[4].visible=false
  32. cartClipArray[5].visible=false
  33. cartClipArray[6].visible=false
  34. cartClipArray[7].visible=false
  35. cartClipArray[8].visible=false
  36.  
  37. // A D D  T O  T H E  C A R T
  38. function addToCart(id:Number){
  39.         // checks if nothing is in the array
  40.         if(cartArray.length<1){
  41.                 cartArray.push(productsArray[id])
  42.                 cartArray[i].qty++
  43.         }else{
  44.                 // check for similar products
  45.                 for(var i:int=0;i0){
  46.                 cartArray[id].qty–
  47.                 if(cartArray[id].qty==0){
  48.                         showTotal()
  49.                         cartArray.splice(id,1)
  50.                         showCart()
  51.                 }
  52.                 showCart()
  53.         }
  54. }
  55.  
  56. // B U T T O N  S T U F F
  57. add_btn.addEventListener(MouseEvent.MOUSE_DOWN, onAdd)
  58. add_btn2.addEventListener(MouseEvent.MOUSE_DOWN, onAdd)
  59. add_btn3.addEventListener(MouseEvent.MOUSE_DOWN, onAdd)
  60. add_btn4.addEventListener(MouseEvent.MOUSE_DOWN, onAdd)
  61. add_btn5.addEventListener(MouseEvent.MOUSE_DOWN, onAdd)
  62.  
  63. cartClip0.addEventListener(MouseEvent.MOUSE_DOWN, onRemove)
  64. cartClip1.addEventListener(MouseEvent.MOUSE_DOWN, onRemove)
  65. cartClip2.addEventListener(MouseEvent.MOUSE_DOWN, onRemove)
  66. cartClip3.addEventListener(MouseEvent.MOUSE_DOWN, onRemove)
  67. cartClip4.addEventListener(MouseEvent.MOUSE_DOWN, onRemove)
  68. cartClip5.addEventListener(MouseEvent.MOUSE_DOWN, onRemove)
  69. cartClip6.addEventListener(MouseEvent.MOUSE_DOWN, onRemove)
  70. cartClip7.addEventListener(MouseEvent.MOUSE_DOWN, onRemove)
  71. cartClip8.addEventListener(MouseEvent.MOUSE_DOWN, onRemove)
  72.  
  73. function onAdd(e:MouseEvent):void{
  74.  
  75.         switch(e.target.name){
  76.                 case "add_btn":
  77.                 addToCart(0)
  78.                 trace("button")
  79.                 break
  80.  
  81.                 case "add_btn2":
  82.                 addToCart(1)
  83.                 break
  84.  
  85.                 case "add_btn3":
  86.                 addToCart(2)
  87.                 break
  88.  
  89.                 case "add_btn4":
  90.                 addToCart(3)
  91.                 break
  92.  
  93.                 case "add_btn5":
  94.                 addToCart(4)
  95.                 break
  96.         }
  97.  
  98.         showTotal()
  99.         showCart()
  100. }
  101.  
  102. function onRemove(e:MouseEvent):void{
  103.  
  104.         switch(e.target.parent.name){
  105.                 case "cartClip0":
  106.                 trace("remove fired")
  107.                 removeFromCart(0)
  108.                 break
  109.  
  110.                 case "cartClip1":
  111.                 removeFromCart(1)
  112.                 break
  113.  
  114.                 case "cartClip2":
  115.                 removeFromCart(2)
  116.                 break
  117.  
  118.                 case "cartClip3":
  119.                 removeFromCart(3)
  120.                 break
  121.  
  122.                 case "cartClip4":
  123.                 removeFromCart(4)
  124.                 break
  125.         }
  126.  
  127.         showTotal()
  128. }

Actionscript 3.0 Brush Up in the Books

Sunday, March 29th, 2009

Thanks for a great brush up guys and gals!

I’m very pleased at how well all of you did and I hope it was helpful and can lead you toward your next actionscripting goals. We covered a lot of material and did almost everything exclusively with code!

If you’re still hungry for more actionscript Pittsburgh has a great Flash Users Group that meets the 3rd Thursday of every month.

Keep flashing and drop me a link of your work every now and again.

Dragging Made Easy

Thursday, March 26th, 2009

Drag and Drop has popped its head into my work week about a half dozen times this week which inspired me to post some code of a basic object oriented drag system.  It’s not perfect and hitTestPoint would give me a more accurate collision detecation against the circle, but I thought it would be nice to see a simple example.

Here’s a quick rundown

  • Array and Loop for setting up the listeners
  • Always set the dragging item on top
  • Check for the correct detection (Here’s a hint it’s the third box)
  • React to the detection

Using the MouseEvent reference defined as e, you can avoid calling the movie clip or button by their original instance name.  This gives you, the developer, a more flexible framework to add and delete drag-able items at will.

Source Code
dragdemoquestion
dragdemoquestion

  1.  
  2. // D R A G A B L E  C L I P S
  3. var dragArray = new Array()
  4. dragArray[0] = box1
  5. dragArray[1] = box2
  6. dragArray[2] = box3
  7. dragArray[3] = box4
  8.  
  9. // L I S T E N E R S
  10. for(var i:int=0; i<dragArray.length; i++){
  11.         dragArray[i].addEventListener(MouseEvent.MOUSE_DOWN, onDragClip)
  12.         dragArray[i].addEventListener(MouseEvent.MOUSE_UP, onStopDragClip)
  13.         dragArray[i].addEventListener(MouseEvent.MOUSE_OVER, onOverDragClip)
  14.         dragArray[i].addEventListener(MouseEvent.MOUSE_OUT, onOutDragClip)
  15.         dragArray[i].buttonMode=true
  16. }
  17.  
  18. // H A N D L E R S
  19. function onDragClip(e:MouseEvent):void{
  20.         e.target.startDrag()
  21.         // Make sure what I’m dragging is always on top
  22.         setChildIndex(MovieClip(e.target), numChildren-1)
  23. }
  24. function onStopDragClip(e:MouseEvent):void{
  25.         // stop the drag please
  26.         e.target.stopDrag()
  27.         // hey do I know you…
  28.         if(e.target.hitTestObject(circle1)){
  29.                 if(e.target.name =="box3"){
  30.                         // … if so do some stuff
  31.                         txt_box.text="Drag Me - Winner"
  32.                         centerClip(MovieClip(e.target),circle1)
  33.                 }else{
  34.                         // … nevermind I thought you were someone else
  35.                         txt_box.text="Drag Me - Loser fail"
  36.                         removeChild(MovieClip(e.target))
  37.                 }
  38.         }
  39. }
  40. function onOverDragClip(e:MouseEvent):void{
  41.         // Rollovers… Aren’t they fun :)
  42.         e.target.filters = [new GlowFilter(0xFFFF00,.5, 20.0,20.0,2,1,false, false)]
  43. }
  44. function onOutDragClip(e:MouseEvent):void{
  45.         // Peace out on the Roll out
  46.         e.target.filters = null
  47. }
  48. // C U S T O M  M E T H O D S
  49. function centerClip(mc1:MovieClip, mc2:MovieClip):void{
  50.         mc1.x =mc2.x+((mc2.width/2) - (mc1.width/2))
  51.         mc1.y =mc2.y+ ((mc2.height/2) - (mc1.height/2))
  52. }
  53.  
  54.  

Swap Depths for AS 2.0

Saturday, March 21st, 2009

Every now and again I get asked questions about ActionScript 2.0.  Although I would much rather give that person a hug and tell them that AS 3.0 will set them free I know that not everyone can make the jump instantly.

Today I was asked how to swap depths in AS 2.0.  No problem right? Wrong! It seemed like everything I tried was jut not working. After I stepped away for a bit I was able to solve the problem but for the life of me I don’t know what was initially wrong. Nevertheless here is the answer.

  1.  
  2.    // sets swapDepths
  3.    this.swapDepths(this.getNextHighestDepth())
  4.  

This will place a movieClip at the top of the display order.
Demo Files
ActionScript 2.0 Swap Depths Demo - Project File
ActionScript 2.0 Swap Depths Demo