logo
468x60-2-495


  • Home
  • Privacy Policy
  • About
search
top
Jun 6, 2012 Posted on Jun 6, 2012 in Hints and Tips | 10 comments

Workshop: Teamup Calendar – Critique

Last time I did a critique, I suggested that Google Calendar was by far one of the last standing dedicated calendar web apps out there. This time around we look at a probable competitor: Teamup Calendar. Like Google’s offering, Teamup Calendar aims for the calendar-based scheduling app domain. Let’s see how this web based calendar app stacks up and whether it stands on its own as a viable alternative.


Getting In

Once I set out to give the app a try, the first hurdle I had to cross was figuring out how to get in. Unlike the standard “Sign Up” or “Register” links, the home page starts with three main “call to action” buttons: “Login with Facebook” (which I usually breeze past for a whole bucketful of reasons), “Live Demo” and “Create Calendar”. Now the Live Demo is pretty clearly going to be a dummy setup, and I don’t know if the app will let me create my own Calendar without first logging in – which is a well understood norm in web apps.

Assuming you brave it and hit the “Create Calendar” button, the next page asks you to name your calendar and provide your e-mail ID. I assumed – again based on my experience with web apps in general – that I was going to be sent a password in mail which I could use to log into my new calendar. Turns out, all you get are a couple of links and a warning not to lose them. The links are to an administrator version and a user version of the calendar. What’s the difference, you ask? None explained at this point. Looks like I’m going to have to dig deeper.


Familiarities Galore

Let me get this out of the way right off the bat: if you have used Google Calendar before, you are going to feel right at home with the Teamup Calendar interface. The same mini month calendar on the left, list of calendars below it, views at the top-right and the actual calendar in the rest of the space. If anything, the Teamup version seems more optimized because it utilizes the space Google wastes in its monstrous header. Also, I found the overall color scheme and visual hierarchy much clearer than Google Calendar.

One thing I did find very weird is that the calendar name I entered when creating the calendar appears at the top, while the actual calendar name defaults to “Calendar 1″. Sure, I can edit the name and add more calendars, but since I got here through a “Create Calendar” workflow, I expected the same of my calendar to be that. The way it works right now, I should have been asked to “Create a Context” for my calendars – like my company’s name, personal space, etc. – a superset that contain multiple calendars.

What I sorely missed right away was a way to quickly add events to the calendar using a text field and natural language parsing. The only way to add an event is to click the right location on the calendar and add the necessary details in the box. To its credit, Teamup makes the event entry box much clearer than Google’s version. Inside is the same old “what, when, who, where” routine. There is a “More…” in this box that I expected would give finer control over the event details; instead it just opens up a text area to add notes for your event. So basically the “More…” button opens up a “Notes” section.


A Simplistic Approach to Collaboration

Teamup takes a very different approach to most other collaboration apps out there. There is no registration involved, so pretty much anyone can join in almost seamlessly. Remember how I mentioned about the two links you get when you create a calendar? Turns out, everyone with access to those links can collaborate on a calendar either as an administrator or a regular user. Admins have the ability to add or remove calendars, change display settings and create or edit user groups with specific access restrictions. Users, on the other hand, can only view events, or add/edit them based on what privileges have been assigned to the URL they have.

I like this approach because it completely gets rid of the registration process for each individual user making it dead simple to add new team members to a calendar. For a small team like mine, this makes perfect sense. On the downside, you don’t get the usual perks associated with the system knowing each individual user. For example, there is no way to tell which team member added a certain task, and there is nothing preventing a miscreant on the team from messing around with the schedule of the rest of the team for whatever reason.


Missing Touches

Despite how optimized the interface is, the app itself does not feel as snappy as it should. Adding and editing calendars, for example, takes up an entire page, forcing a page refresh every time I want to do either. Ideally, it should be something one can do within the context right there on my calendar view. The app also lacks a number of subtle interface touches that could make the experience so much more seamless. Here are a few things I was surprised to see in an app in this day and age of dynamic, snappy user experiences:

  • When editing the time for an event, the dropdown always starts from the first hour of the day instead of the currently selected time slot.
  • There is no indication of the current time on the Week & Day calendar views. Just a small red line to state what the current time of day is can make a huge difference in a user’s ability to quickly glance through their events for the day.
  • In the Event Details box, hitting Enter after typing something does nothing. I found myself doing this often by practice.

When working with others on the same calendar, updates made by one user do not reflect for others till one manually refreshes the page. This means multiple team members could end up editing an event with only the last one to change having it their way. This could be a trivial issue for some teams, but a deal breaker for others, depending on their particular use cases.


Wrapping Up

Teamup Calendar brings a very interesting frictionless approach to collaboration on calendars, along with a minimalistic feature set that might be just enough for small teams looking for a quick way to manage meetings and schedules. Although it has its downsides in terms of the overall user experience, nothing stands out as a show stopper unless you need ironclad control for mission critical situations. Also, in this era where smart phones are becoming an integral part of people’s information management routines, the use cases for a web-only app are pretty limited.

I am myself going to give the app a fair try with my team at work. It seems to have just what we need and nothing more. How well it works for us and whether we are able to look through its limitations as a team, only time will tell.



View full post on Activetuts+

banner ad

10 Responses to “Workshop: Teamup Calendar – Critique”

  1. Ashish Bogawat says:
    June 6, 2012 at 9:06 pm

    Last time I did a critique, I suggested that Google Calendar was by far one of the last standing dedicated calendar web apps out there. This time around we look at a probable competitor: Teamup Calendar. Like Google’s offering, Teamup Calendar aims for the calendar-based scheduling app domain. Let’s see how this web based calendar app stacks up and whether it stands on its own as a viable alternative.


    Getting In

    Once I set out to give the app a try, the first hurdle I had to cross was figuring out how to get in. Unlike the standard “Sign Up” or “Register” links, the home page starts with three main “call to action” buttons: “Login with Facebook” (which I usually breeze past for a whole bucketful of reasons), “Live Demo” and “Create Calendar”. Now the Live Demo is pretty clearly going to be a dummy setup, and I don’t know if the app will let me create my own Calendar without first logging in – which is a well understood norm in web apps.

    Assuming you brave it and hit the “Create Calendar” button, the next page asks you to name your calendar and provide your e-mail ID. I assumed – again based on my experience with web apps in general – that I was going to be sent a password in mail which I could use to log into my new calendar. Turns out, all you get are a couple of links and a warning not to lose them. The links are to an administrator version and a user version of the calendar. What’s the difference, you ask? None explained at this point. Looks like I’m going to have to dig deeper.


    Familiarities Galore

    Let me get this out of the way right off the bat: if you have used Google Calendar before, you are going to feel right at home with the Teamup Calendar interface. The same mini month calendar on the left, list of calendars below it, views at the top-right and the actual calendar in the rest of the space. If anything, the Teamup version seems more optimized because it utilizes the space Google wastes in its monstrous header. Also, I found the overall color scheme and visual hierarchy much clearer than Google Calendar.

    One thing I did find very weird is that the calendar name I entered when creating the calendar appears at the top, while the actual calendar name defaults to “Calendar 1″. Sure, I can edit the name and add more calendars, but since I got here through a “Create Calendar” workflow, I expected the same of my calendar to be that. The way it works right now, I should have been asked to “Create a Context” for my calendars – like my company’s name, personal space, etc. – a superset that contain multiple calendars.

    What I sorely missed right away was a way to quickly add events to the calendar using a text field and natural language parsing. The only way to add an event is to click the right location on the calendar and add the necessary details in the box. To its credit, Teamup makes the event entry box much clearer than Google’s version. Inside is the same old “what, when, who, where” routine. There is a “More…” in this box that I expected would give finer control over the event details; instead it just opens up a text area to add notes for your event. So basically the “More…” button opens up a “Notes” section.


    A Simplistic Approach to Collaboration

    Teamup takes a very different approach to most other collaboration apps out there. There is no registration involved, so pretty much anyone can join in almost seamlessly. Remember how I mentioned about the two links you get when you create a calendar? Turns out, everyone with access to those links can collaborate on a calendar either as an administrator or a regular user. Admins have the ability to add or remove calendars, change display settings and create or edit user groups with specific access restrictions. Users, on the other hand, can only view events, or add/edit them based on what privileges have been assigned to the URL they have.

    I like this approach because it completely gets rid of the registration process for each individual user making it dead simple to add new team members to a calendar. For a small team like mine, this makes perfect sense. On the downside, you don’t get the usual perks associated with the system knowing each individual user. For example, there is no way to tell which team member added a certain task, and there is nothing preventing a miscreant on the team from messing around with the schedule of the rest of the team for whatever reason.


    Missing Touches

    Despite how optimized the interface is, the app itself does not feel as snappy as it should. Adding and editing calendars, for example, takes up an entire page, forcing a page refresh every time I want to do either. Ideally, it should be something one can do within the context right there on my calendar view. The app also lacks a number of subtle interface touches that could make the experience so much more seamless. Here are a few things I was surprised to see in an app in this day and age of dynamic, snappy user experiences:

    • When editing the time for an event, the dropdown always starts from the first hour of the day instead of the currently selected time slot.
    • There is no indication of the current time on the Week & Day calendar views. Just a small red line to state what the current time of day is can make a huge difference in a user’s ability to quickly glance through their events for the day.
    • In the Event Details box, hitting Enter after typing something does nothing. I found myself doing this often by practice.

    When working with others on the same calendar, updates made by one user do not reflect for others till one manually refreshes the page. This means multiple team members could end up editing an event with only the last one to change having it their way. This could be a trivial issue for some teams, but a deal breaker for others, depending on their particular use cases.


    Wrapping Up

    Teamup Calendar brings a very interesting frictionless approach to collaboration on calendars, along with a minimalistic feature set that might be just enough for small teams looking for a quick way to manage meetings and schedules. Although it has its downsides in terms of the overall user experience, nothing stands out as a show stopper unless you need ironclad control for mission critical situations. Also, in this era where smart phones are becoming an integral part of people’s information management routines, the use cases for a web-only app are pretty limited.

    I am myself going to give the app a fair try with my team at work. It seems to have just what we need and nothing more. How well it works for us and whether we are able to look through its limitations as a team, only time will tell.


  2. Vũ Hoàng Minh says:
    June 6, 2012 at 9:20 pm

    In this tutorial we’ll learn how to load and display a 3DS model file in Flash, using Away3D 4.0 beta and Stage3D’s GPU hardware acceleration.


    Final Result Preview

    Let’s take a look at the final result we will be working towards:

    Click to download the demo files.


    Introduction

    To use this tutorial you will need to have a 3D model (exported as a .3ds file) and its texture (as an image file).

    I created a simple 3D model of a teapot in Autodesk 3DS Max, and exported it to a file named Teapot.3DS along with its separate texture file, teapot.jpg. You can find both files in the source download.

    You will need to download a package SWC of Away3D 4.0.0 beta (you can also find this SWC in the source files).

    And you need to know that Away3D 4.0.0 beta version uses the new Stage3D features of Adobe Flash, meaning it can use the GPU for 3D graphics acceleration.

    We are going to build this demo using pure AS3, compiled in FlashDevelop (read more about it here). FlashDevelop is a free AS3 IDE, although it is Windows only. If you prefer to use another IDE, you will still be able to follow this tutorial.


    Step 1: Create a New Project

    If you don’t already have it, be sure to download and install FlashDevelop. Open it and start a new AS3 Project.

    Create a New Project in FlashDevelop

    FlashDevelop will create a blank AS3 template project for you. We’ll use the Main class for all our code.


    Step 2: Compiler Options

    Go into the Project menu, choose Properties and change a few options:

    1. Set the target platform to Flash Player 11.1.
    2. Change the SWF size to 550x400px.
    3. Set the background color to black.
    4. Change the FPS to 40.
    Target Flash 11

    If we want to run this tutorial from the HTML embed code, we have to include the parameter wmode=direct in the parameters of the Flash object in the HTML file. It’ll look like this:

    
    
    <object width="550" height="400" data="3DViewer.swf" type="application/x-shockwave-flash" wmode="direct">
    <param name="src" value="3DViewer.swf" />
    <param name="wmode" value="direct" />
    </object>
    

    In this tutorial we’ll load the 3DS file from local storage (rather than from a web server), so we must change some settings in the Compiler Options tab. Set Use Network Services to False.

    Local file load


    Step 3: Add Away3D Library

    Get away3d-core-fp11_4_0_0_beta.swc from the source files, or download it from Away3D’s site.

    Copy that file to your project’s lib directory.

    In FlashDevelop, right-click the SWC file, and choose Add to Library.

    Add Away3D Library


    Step 4: Imports

    Now let’s start coding with our Main.as file. To begin, we have to import the necessary library files for program to setup the Away3D engine and the Flash components. There are quite a few, so let’s get them out of the way:

    
    
    // 3DS Model Viewer Tutorial
    // by Vu Hoang Minh - http://www.3dgameflash.com
    // Created for active.tutsplus.com
    
    package
    {
    	//Away3D classes
    	import away3d.cameras.lenses.PerspectiveLens;
    	import away3d.containers.ObjectContainer3D;
    	import away3d.containers.View3D;
    	import away3d.entities.Mesh;
    	import away3d.events.LoaderEvent;
    	import away3d.loaders.Loader3D;
    	import away3d.loaders.parsers.Max3DSParser;
    	import away3d.materials.TextureMaterial;
    	import away3d.textures.BitmapTexture;
    
    	//General Flash classes for display and interaction
    	import flash.display.Bitmap;
    	import flash.display.MovieClip;
    	import flash.display.Shape;
    	import flash.display.Sprite;
    	import flash.events.Event;
    	import flash.events.MouseEvent;
    	import flash.geom.Vector3D;
    	import flash.text.TextField; 
    
    	//Classes for loading the 3DS file from the hard drive
    	import flash.display.SimpleButton;
    	import flash.events.IOErrorEvent;
    	import flash.net.FileFilter;
    	import flash.net.FileReference;
    	import flash.net.URLRequest;
    	import flash.system.Security;
    

    Step 5: Initialize Program

    Let’s get started. We’ll declare the variables that we’re going to need, initialise the 3D engine, and set up the “Browse” button and debug output text field.

    
    
    	public class Main extends Sprite
    	{
    		private var file:FileReference;
    		private var view3d:View3D;
    		private var loader:Loader3D;
    		private var labelDebug:TextField;
    		private var object3d:Mesh;
    
    		public function Main():void
    		{
    			//boilerplate loading code
    			if (stage)
    				init();
    			else
    				addEventListener(Event.ADDED_TO_STAGE, init);
    		}
    
    		private function init(e:Event = null):void
    		{
    			//allow us to load a local file
    			Security.allowDomain("*");
    
    			removeEventListener(Event.ADDED_TO_STAGE, init);
    
    			//init 3D engine
    			view3d = new View3D();
    			view3d.camera.lens = new PerspectiveLens();
    			view3d.camera.z = 100;
    			addChild(view3d);
    
    			//3D loader
    			initLoader();
    
    			//Button to open file browser
    			var mcBrowse:MovieClip = new MovieClip();
    			mcBrowse.graphics.beginFill(0xeeeeee);
    			mcBrowse.graphics.drawRoundRect(1, 2, 100, 25, 7, 7);
    			mcBrowse.graphics.endFill();
    			var labelBrowse:TextField = new TextField();
    			labelBrowse.text = "Browse";
    			mcBrowse.addChild(labelBrowse);
    			mcBrowse.mouseChildren = false;
    			mcBrowse.buttonMode = true;
    			labelBrowse.x = 25;
    			mcBrowse.addEventListener(MouseEvent.CLICK, onClick_mcBrowse);
    			addChild(mcBrowse);
    
    			//debug output
    			labelDebug = new TextField();
    			labelDebug.text = "...";
    			labelDebug.textColor = 0xff0000;
    			labelDebug.selectable = false;
    			labelDebug.y = mcBrowse.height / 2;
    			labelDebug.width = 600;
    			addChild(labelDebug);
    
    			//file
    			file = new FileReference();
    		}
    

    In lines 25-29, we initialise the Away3D graphics components. We create a new View3D (a container that stores the camera and objects), configure its lens and camera, and add it to the display list.

    After that we make a Browse button: we draw its background, add its label, configure it, and add it to the display list.

    To make it easy to keep track of the 3DS loading state, we make a debug label, which is a simple text field.

    Finally, we initialise a FileReference instance to handle browsing for the 3DS file.


    Step 6: Initialise 3D Loader

    The next important thing we must do is create a 3D model loader.

    
    
    	private function initLoader():void
    	{
    		//clear all
    		removeEventListener(Event.ENTER_FRAME, onEnterFrame);
    		while (view3d.scene.numChildren > 0)
    		{
    			view3d.scene.removeChild(view3d.scene.getChildAt(0));
    		}		
    
    		//init new 3D loader
            	Loader3D.enableParser(Max3DSParser);
    		loader = new Loader3D();
    		loader.addEventListener(LoaderEvent.RESOURCE_COMPLETE, onComplete_loader);
    		loader.addEventListener(LoaderEvent.LOAD_ERROR, onError_loader);
    		view3d.scene.addChild(loader);
    
       		//config camera
    		view3d.camera.lookAt(loader.position);
    	}
    

    This function has three sections:

    1. First, we clear everything out, in case our program has run before.
    2. After that, we initialise a new Loader3D instance, and add listeners to it which trigger when it fires an Error when a 3D file has completely loaded. To make it visible, we add it to the View3D‘s scene.
    3. To ensure that we can actually see the object once it has loaded, we tell the camera to look at it.

    Step 7: Handle All Events

    Next, we’ll add all the event handler functions, which all have something to do with loading the 3DS file.

    
    
    		private function onClick_mcBrowse(e:MouseEvent):void
    		{
    			file.browse([new FileFilter("3DS", "*.3ds")]);
    			file.addEventListener(Event.SELECT, onFileSelected);
    			file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
    			file.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
    		}
    
    		private function onSecurityError(e:Event):void
    		{
    			labelDebug.text += ".Security Error!";
    		}
    
    		private function onIOError(e:IOErrorEvent):void
    		{
    			labelDebug.text += ".File not found Error!";
    		}
    
    		private function onFileSelected(e:Event):void
    		{
    			labelDebug.text = "File :" + file.name;
    			file.removeEventListener(Event.SELECT, onFileSelected);
    			file.addEventListener(Event.COMPLETE, onFileLoaded);
    			file.load();
    		}
    
    		private function onFileLoaded(e:Event):void
    		{
    			file.removeEventListener(Event.COMPLETE, onFileLoaded);
    			initLoader();
    			loader.loadData(e.target.data);
    		}
    
    		private function onError_loader(e:LoaderEvent):void
    		{
    			trace("Error loading File...");
    			labelDebug.text += " .Loading Error";
    		}
    
    		private function onComplete_loader(e:LoaderEvent):void
    		{
    			trace("3D File loaded");
    			labelDebug.text += " .Complete.Rendering...";
    			loader.removeEventListener(LoaderEvent.RESOURCE_COMPLETE, onComplete_loader);
    			loader.removeEventListener(LoaderEvent.LOAD_ERROR, onError_loader);
    			object3d = Mesh(loader.getChildAt(0));
    			view3d.scene.addChild(object3d);
    			loader.dispose();
    			loader = null;
    
    			addEventListener(Event.ENTER_FRAME, onEnterFrame);
    		}
    

    When the user clicks the Browse button, we display the File Browse Dialog, which uses a FileFilter to restrict the files shown to those with a .3ds extension. We add several event listeners to this dialog, so that we can detect when a file is detected or if an error occurs.

    After a file has been selected, we load it to the FileReference instance that we initialised earlier. Once it has loaded, we call the initLoader() function that we defined in the previous step, which loads our 3D model.

    At this time, there are two possible states we can catch:

    • One is the “error” state, which implies that our program cannot load the 3D model file (perhaps the path is incorrect, or the map texture file is wrong…).
    • The other is the “loaded successfully” event, upon which we cast the loaded file to a Mesh and add it to the scene of View3D.

    To free up our memory and reuse it later, we should dispose of our loader.

    At the end of above code (assuming the file loaded) we add an ENTER_FRAME event, which we’ll use to render the object. We’ll write that handler now.


    Step 8: Start the Render Loop

    Now that everything has been initialized, we are ready to render it all. Every frame, we’ll make the 3D object yaw (rotate) and call the render() function of View3D to update the display.

    
    
    		private function onEnterFrame(e:Event):void
    		{
    			object3d.yaw(1);  //yaw by one unit
    			view3d.render();
    		}
    

    Step 9: Compile and Run!

    Almost done! Compile your SWF with F5, and see your final result. So interesting, right?

    You can do than just rotate the object – try calling object3d.moveFoward(10) or object3d.pitch(1). You could even do this in response to a mouse movement or a key press.

    Just for reference, and to ensure that you’ve used the correct filenames and locations for everything, here is what your FlashDevelop project should look like:

    Just for reference, and to ensure that you've used the correct filenames and locations for everything

    Conclusion

    We have finished first basic 3D tutorial on newest 3d Accelarate function of Adobe. I warmly welcome all readers to get in touch with me via the comments, or through my website, any time. Thanks for reading. See you next time. Good luck and HAVE FUN!


  3. Ashish Bogawat says:
    June 6, 2012 at 10:19 pm
    This entry is part 1 of 3 in the series Flash Tips and Best Practices for Designers

    The first time I used Flash was around 13 years ago. It was version 3 and Flash was hailed as the fancy new vector based animation tool that would soon take the web design world by storm. Over the years, Flash has grown into a fully-fledged rich application development tool, packed to the brim with ActionScript goodness.

    What a lot of people seem to be forgetting though, is how much Flash is still a designer’s tool, letting us create artwork and animations the old-fashioned draw-and-move-around way.

    May of 2011

    Let’s start with what pretty much anyone would start with in Flash (or any design application for that matter) – drawing. Be it drawing regular shapes or tracing lines, drawing is one of the most fundamental actions in Flash. What makes Flash unique though, is the way it handles shapes. It behaves quite unlike any other vector drawing tool out there, and is either loved or hated by many for it. Of course, there are advantages and disadvantages to segregating each part of an object for independent editing. Let’s take a look at some quirky little things that Flash does and how to use them to our best advantage.

    Although this post was written for Flash Professional CS5, most of the tips should work just fine in older versions. I will try and make it a point to highlight wherever something is very specific to the latest version of Flash.


    Regular vs. Primitive Shapes

    Typically, when you draw a regular shape (a rectangle or an ellipse) in Flash, it creates a patch with the selected fill and stroke properties. You can then select the fill and/or the stroke indidually and edit their properties. In Flash CS3, Adobe introduced what they call ‘primitive’ shape tools. Unlike the default shape tools, which separate the stroke from the fill, these create a shape that is selectable and editable as a whole.

    Primitive Shapes

    Although for veteran Flash designers this can be an irritating change, it brings with it a level of control that was unseen in Flash before this version. You can suddenly change properties of the object numerically through the properties panel, add rounded corners, and convert circles to pies with decimal point accuracy. There is very little reason to go back to the traditional shape tools once you have used the primitives, yet many designers I know continue to work the old-fashioned way. Part of the problem could be Adobe’s dumbfounding decision to retain the simple shapes as the default tools, burying the primitives inside a dropdown in the toolbar.

    Case study: Create an accurate pie chart using primitive shapes

    Let’s try using the primitive shapes in a real-life scenario where using the traditional shape tools would have proven to be an exercise in hair-pulling. Say you want to create an accurate pie chart using real numbers – market shares for mobile operating systems in 2010, for example.

    Once we have the percentages (that add up to 100), we will multiply each with 3.6 to equate them with the total 360 degrees in a circle. Then, it’s a simple matter of pasting six circles on top of each other and assigning the appropriate starting and ending angles for each one based on our calculations. See the math in the table below, as well as the properties for one of the pies, for a better idea.

    Pie chart using primitive the ellipse tool

    Freely Transform Shapes With the Mouse

    By their very nature, objects in Flash are freely editable in all kinds of ways. You can select a shape’s fill or outline, drag it around and it will affect all other shapes in that area as long as they are on the same plane. What happens when you select and/or drag an element though, depends on what you click and where. Let’s look at the various possibilities:

    Transform Types
    • Clicking and dragging a shape that is already selected will simply move it to wherever you let the mouse go.
    • Clicking and dragging inside a shape’s fill – even if it is not selected – will select and move it. Note that this will only move the fill and not the stroke. If you drop the fill on top of the stroke, any part of the stroke that comes under the fill will be deleted.
    • Clicking and dragging on a straight line will make it a curve. How long away you drag the line defines how steep the curve is.
    • Clicking and dragging on an existing curved line will alter its curvature.
    • Clicking and dragging a corner point will only move that point. If snapping is on, the point will snap to any other corner nearby.

    Case Study: Make waves the easy way

    Let’s try and apply this knowledge to make complex wavy lines the simple way – using straight zigzag lines. Start by simply drawing straight lines to define the approximate size and shape of the wave. Make sure the line is not selected. Then, click and drag each line segment to make a curve for the wave. Lastly, select the corner points and move them up or down till they snap to make the curve seamless on both sides.


    Smooth Rounded Corners

    For some reason best known to Adobe, they have never addressed an inherent problem with rendering rounded corners in Flash. If the outline of a rounded rectangle is an odd number (1, 3, 5, etc.), the corners tend to have these ugly artifacts that make the image look blurred. A typical hack I’ve used and have seen being used is to make sure the outlines on rounded rectangles are always 2, 4, 6 or any even number. It still doesn’t work if your shape is on a sub-pixel co-ordinate – either x or y co-ordinate is in decimals (2.6, 4.12, 98.57, etc.) – but that’s an easier problem to solve.

    Blurriness with rounded corners

    But what if I need the outline to be a single pixel? One workaround I recently found and have been extensively using since is this:

    1. Draw your rectangle using the primitive rectangle tool and set it to whatever size you need. Make sure the X and Y co-ordinates of the rectangle are each whole numbers without decimal points in them.
    2. Change the roundness to your preference.
    3. Fill this object with the color you need for your rectangle’s outline.
    4. Copy and paste the rectangle in place, then nudge it one pixel to the right and down.
    5. Reduce the height and width of the new rectangle to 2 pixels less than the original one, and change the fill to whatever color you need for the shape.
    6. We’re not done yet. Reduce the roundness of the new rectangle to one less than the outline. Because Flash assigns roundness by pixels and not by percentage, having the same roundness value for both rectangles causes minor inconsistencies towards the center of each curvature.
    Fixing the blurred rounded corners

    Although this technique should work in most cases, it is not without its pitfalls. It’s of no use, for example, in situations where you need an object to be translucent. Reducing the alpha of the fill rectangle will only show more of the outline color from the rectangle behind. A hack to get around it would be to break both rectangles (convert them to regular shapes).

    You might also consider using stroke hinting to guide you when drawing strokes on the stage.


    Distribute Gradients Across Objects

    Who doesn’t like gradients? Designs these days are pretty incomplete without at least a subtle hint of a gradient to give it a realistic and often contemporary feel. The problem with how Flash handles shapes though, is that each self-contained piece is a shape and has its own properties. You cannot apply gradient fills to groups of objects and there is no way to ‘connect’ two disparate shapes. What happens, then, when you need a gradient to span across multiple objects – say all words in a custom-made logotype?

    Well, ‘Lock Fill’ to the rescue. When using the ‘Paint Bucket’ tool, you will see an icon at the bottom of the tool palette with a gradient and a lock on it. Select the shapes you need to fill, toggle the ‘Lock Fill’ icon, select a gradient from the fill color palette on and click inside any of the selected shapes. Don’t worry if you don’t see the entire gradient applied. More often than not the locked fill spans way beyond the selected shapes and you need to use the ‘Gradient Transform Tool’ to resize the gradient the way you need it.

    Locked gradient fill applied to multiple objects

    This technique is not without its issues though. Here are some things to remember when using locked fills:

    • Locked fills only work with regular shapes. If you used primitive shapes, you will need to break them apart to be able to apply a gradient across multiple objects.
    • If you select one of a group of shapes with a locked fill, and then change its properties, that shape will be de-linked from the group.
    • Like I mentioned before, the bounds of a gradient in a locked fill tend to be way bigger than the area of the shapes. Just use the ‘Gradient Transform Tool’, select any one of the shapes and adjust the bounds of the gradient. You may need to zoom out a bit to be able to see the gradient controls.

    Play Around With Custom Strokes

    Flash comes with a set of stroke styles by default – Solid, Dashed, Dotted, Ragged, Stipples and Hatched – which work fine for the most part. For situations where you need more control over the stroke though, there is a pretty darn powerful stroke editor that comes with Flash. To really start playing around with your strokes, click the edit icon next to the ‘Style’ list in the ‘Properties’ panel of a selected stroke.

    Editing the dashed line with fine control

    Let’s say you needed a dashed line, but the dashes are currently way too close in the default ‘Dashed’ style. In the ‘Edit Stroke’ panel, simply increment the number in the second input field next to ‘Dash’ till you get the effect you need. And while you are it, check the ”Sharp corners’ box. If you’ve ever been bugged by the weird corners you get with the default dashed line in Flash, this fixes it.


    Helpful Hints

    Here are some more helpful hints to help optimize your workflow when working with shapes in Flash.

    • Because of the way Flash handles shapes, clicking an outline only selects a section of the line, not the whole thing. Double-click a section of the stroke to select all connected sections at once.
    • Double-clicking a fill selects the fill and all line sections around it.
    • If you would like to divide a shape with some space in between the two divisions:

      1. Draw a line where you need the division.
      2. Adjust the thickness of the line depending on how much space you need between the divisions.
      3. Make sure the line is selected; then go to ‘Modify > Shapes’ in the menu bar and select ‘Convert Lines to Fills’.
      4. Delete the line.

    • By default, lines have rounded ends and corners in Flash, but if you need the edges to be hard for some reason you can set them by changing the ‘Cap’ and ‘Join’ properties in the ‘Properties’ panel for a selected line.

    Conclusion

    And that’s a wrap for the first part of this series on Flash best practices for designers. I hope these tips will help you improve & optimize your workflow in Flash over the long term. Please feel free to share your own tips & best practices in the comments section. I will be back with the next part of this series with tips on how to manage your text and symbols in Flash.


  4. Michael James Williams says:
    June 6, 2012 at 10:29 pm

    Google I/O 2012 is less than a month away, so I thought it’d be appropriate to look back at a great talk from Google I/O 2010: Chrome Dev Tools Reloaded, presented by Paul Irish and Pavel Feldman. If you’re a JavaScript developer making games or apps for the browser, you should watch this.


    Watch the Video

    Paul Irish is, among many things, a member of the Google Chrome developer relations team, and Pavel Feldman is a Google software engineer on the Chrome team.

    In this talk, they cover the Chrome Developer Tools, which let you edit the DOM inline, alter CSS rules in a page on the fly, call JavaScript manually, set breakpoints, and more. If you’ve never used the tools before (or if you’ve just muddled your way through with them, discovering new tricks as you go), I recommend watching this video to help you get the most out of them.


    Further Resources

    Here are some other great resources along the same lines:

    • GoogleDevelopers on YouTube, which features plenty more videos for developers.
    • Paul Irish’s blog post about the talk.
    • Chrome Developer Tools Cheat Sheet on GitHub (it’s forkable).
    • Official overview and documentation for Chrome Developer Tools.
    • Chrome Canary, a build of Chrome with the latest features (beyond the current stable build).


  5. David Appleyard says:
    June 6, 2012 at 11:00 pm

    Each month, we bring together a selection of the best tutorials and articles from across the whole Tuts+ network. Whether you’d like to read the top posts from your favourite site, or would like to start learning something completely new, this is the best place to start!


    Psdtuts+ — Photoshop Tutorials

    • Quick Tip: Create a Metallic Copper Text Effect Using Layer Styles in Photoshop

      Quick Tip: Create a Metallic Copper Text Effect Using Layer Styles in Photoshop

      In this tutorial we will explain how to create a metallic copper text effect using layer styles in Photoshop. Let’s get started!

      Visit Article

    • How to Draw a Leica Camera in Photoshop

      How to Draw a Leica Camera in Photoshop

      Leica is considered one of the most prestigious camera brands. In this tutorial, we will draw one of the most notable Leica cameras in Photoshop, the Leica M1. Let’s get started!

      Visit Article

    • Create a Tasty 3D Typographic Illustration – Tuts+ Premium Tutorial

      Create a Tasty 3D Typographic Illustration – Tuts+ Premium Tutorial

      If you’ve got a sweet tooth, then we’ve got a mouth-watering tutorial for you. In this Tuts+ Premium tutorial, author Mark Mayers will show you how Photoshop CS6 Extended’s new 3D tools can be utilized to create a typographic illustration that includes lots of sugary treats. This tutorial is available exclusively to Tuts+ Premium Members.

      Visit Article


    • Nettuts+ — Web Development Tutorials

    • 10 Things I Learned While Interning at YUI

      Things I Learned While Interning at YUI

      For eight months, I had the opportunity to intern with the YUI Team at Yahoo, while I was completing my engineering degree. Today, I’d like to share the top ten things that I learned from my experience with YUI.

      Visit Article

    • Coda 2: Reviewed

      Coda 2: Reviewed

      Well, it happened; Panic finally released the long-awaited version two of their popular code editor, Coda. But does it live up to the hype? Well, that depends on what type of coder you are. Read the full review after the jump!

      Visit Article

    • 3 Key Software Principles You Must Understand

      Key Software Principles You Must Understand

      If you’re in software development, new techniques, languages and concepts pop up all of the time. We all feel those nagging doubts every now and then: “can I keep up with the changes and stay competitive?” Take a moment, and sum a line from my favourite movie, Casablanca: “The fundamental things apply, as time goes by.”

      Visit Article


    • Vectortuts+ — Illustrator Tutorials

    • Create a Vintage Vector Framed Silhouette Design

      Create a Vintage Vector Framed Silhouette Design

      In today’s tutorial I’m going to collaborate with a great friend of mine, Ashley Benson and show you how to create a Victorian styled Silhouette. She’s been great to give me this wonderful sketch specifically for our vintage vector art tutorial, so feel free to download it as part of your Tuts+ Premium membership to practice on. Learn basic techniques on creating a detailed, framed silhouette inspired by Victorian vintage postcard designs using scatter brushes, patterns and more. Using these techniques you can create your own vintage illustrations.

      Visit Article

    • Quick Tip: Microstock Illustrations with Corel Draw, Tricks and Tips

      Quick Tip: Microstock Illustrations with Corel Draw, Tricks and Tips

      With the vector software Corel Draw you are able to draw everything you can imagine. However, if you are using it to create illustrations for the microstock agencies – there are some issues that you must take into consideration. The problem comes with the industry requirement to provide an EPS (Encapsulated PostScript) file, which is mandatory for almost all agencies. See, EPS is Adobe standard and Corel developers don’t like Adobe standards very much…

      Visit Article

    • From a Logo to Business Card, How to Make a Self Promotion Set

      Logo and Identity Design Session

      Audiences identify with effective logos and well composed brand identities. Learn how to craft creative logo designs with impact. In this Creative Session, we have a compilation of inspiring logo design and branding material.

      Visit Article


    • Webdesigntuts+ — Web Design Tutorials

    • Quick Tip: Rounded Corners Done Right

      Quick Tip: Rounded Corners Done Right

      This is going to seem like a no-brainer to many of you, but I see it happening so often I figured it was worth bringing up. We’ll call this issue improperly nested corners; a small detail which can ruin an otherwise brilliant design!

      Visit Article

    • Create a Customized HTML5 Audio Player

      Create a Customized HTML5 Audio Player

      During this tutorial I’m going to be introducing you to HTML5 audio and showing you how you can create your own player.

      Visit Article

    • Employing AIDA Principles in Web Design

      Employing AIDA Principles in Web Design

      In this article we’ll discuss how we can use design to implement the principles laid out by AIDA (the marketing acronym, not the Italian opera) and help create sales-orientated web pages.

      Visit Article


    • Phototuts+ — Photography Tutorials

    • Simplify and Challenge Your Creativity Using a Single Lens – Tuts+ Premium

      Simplify and Challenge Your Creativity Using a Single Lens – Tuts+ Premium

      We have another Photo Premium tutorial exclusively available to Premium members today. In this tutorial, try going out on a shoot with only one lens to limit us and force us to think creatively. Luckily, we’ll be guided by professional photographer Simon Plant. Learn more after the jump!

      Visit Article

    • Easy Tips for Shooting the Moon

      Easy Tips for Shooting the Moon

      Pictures of a big moon over a landscape are many times the result of a double exposure. Even when the moon comes closer to Earth, as it did recently, it is too small to fill the frame with normal gear. Still, there are ways to get around the thousands of miles that separate us and our big nightlight.

      Visit Article

    • Building a Narrative Through Photojournalism

      Building a Narrative Through Photojournalism

      Telling visual stories is the work and craft of the photojournalist. I remember it from the first hard news story I covered, back in 1980: a bank robbery that completely defined my future.

      Visit Article


    • Cgtuts+ — Computer Graphics Tutorials

    • Building The Caterpillar 797 In 3D Studio Max – Creating The Tires, Rims, Cabin And Bridge

      Building The Caterpillar 797 In 3D Studio Max – Creating The Tires, Rims, Cabin And Bridge

      Today we’re kicking off an awesome new tutorial series by Sasa Posloncec where you’ll learn how to model the ridiculously huge Caterpillar 797B mining dump truck. Spanning three parts this series will give you an in-depth look at what it takes to create a fully realized vehicle model in 3D Studio Max using blueprints and photo reference. As Sasa walks you through the creation of each part, you’ll learn how to work with Max’s Edit Poly modifier, spline tools and much more!

      Visit Article

    • Image Based Lighting: The Complete Workflow with Maya, HDR Shop & Photoshop

      Image Based Lighting: The Complete Workflow with Maya, HDR Shop & Photoshop

      So Image Based Lighting…. What is it, and how can you use it to your advantage? Get the answers in this tutorial from James Whiffin where you’ll not only learn about implementing IBL into your projects, but how to setup and shoot your very own high dynamic range images, a topic rarely seen in tutorials.

      Visit Article

    • Modeling A Modern Interior Scene In Blender

      Modeling A Modern Interior Scene In Blender

      In this tutorial we will be modeling an interior scene from a reference photo. It is written for the complete beginner, you’ll learn how to setup a background image and how to match the camera to it, as we follow a very simple workflow for building up the scene with a variety of basic modeling techniques that will give you a very good basis on how to approach any kind of modeling.

      Visit Article


    • Aetuts+ — After Effects Tutorials

    • Fantastic Facial Motion Capture – Tuts+ Premium

      Fantastic Facial Motion Capture – Tuts+ Premium

      In this tutorial, I will be sharing with you how to achieve 2D facial motion capture in After Effects. The technique involves acquiring motion data from dots on a face, and using that motion data to manipulate the position of puppet pins on an image that you want to animate. It’s a very useful way of quickly creating detailed animations, and characterizing inanimate objects, like the rock face in the intro. It’s also possible to do face replacement.

      Visit Article

    • Muted Color Grading And A Vintage Film Burn Using Fractal Noise

      Muted Color Grading And A Vintage Film Burn Using Fractal Noise

      In today’s tutorial I’ll be showing how to take DSLR footage and give it the popular “Muted” color grade. After we cover the color grading, I’m gonna show you how to create a film burn effect from scratch using “Fractal Noise.”

      Visit Article

    • How To Create A Stupendous Stuttering Jumper Punch

      How To Create A Stupendous Stuttering Jumper Punch

      In this tutorial we will learn how to create an advanced and well composited Jumper Punch by using a matte, some displacement, and smoke to add style to the final effect. Throughout the tutorial, we will be using basic expressions. We’ll learn to position the jumps in time and space and give the illusion of a jumper disappearing and reappearing with a trajectory. Let’s “Jump” in… :)

      Visit Article


    • Audiotuts+ — Audio & Production Tutorials

    • 3D Mixing Part 7: Mastering, The Final Chapter (Part 2)

      D Mixing Part 7: Mastering, The Final Chapter (Part 2)

      In the final installment of the series, we are going to look at the final effects on the signal chain (Master EQ, Master Reverb, Master Limiter), and discuss the various final print options.

      Visit Article

    • Quick Tip: How to Make a Snare Roll Generator

      Quick Tip: How to Make a Snare Roll Generator

      Today I will show you my new gadget, and teach you how to make it. A snare roll is an important part of a song. It can be used in many situations: as a creative element of a song or introducing something important like a breakdown. My new toy will reduce the time it takes to create one.

      Visit Article

    • 10 Cures For A Songwriting Slump

      Cures For A Songwriting Slump

      Sooner or later, even the most inspired and prolific songwriter will stumble into that dreadful and frightening abyss known as writer’s block. To call it frightening is truly not an overstatement when one is attempting to land a writing deal, keep a publisher happy, or best-case scenario, keep the already lucrative royalties flowing. The voice of defeat stirs in every songwriter at some point, first as a murmur and then as a blood-curdling scream.

      Visit Article


    • Wptuts+ — WordPress Tutorials

    • The Complete Guide To The WordPress Settings API, Part 8: Validation, Sanitisation, and Input II

      The Complete Guide To The WordPress Settings API, Part 8: Validation, Sanitisation, and Input II

      We’ve reached the final article of the series. In the last post, we took a look at introducing validation, sanitization, and a couple of basic input elements that we can take advantage of when building option pages.

      Visit Article

    • Quick Tip: Conditionally Including JS and CSS With get_current_screen

      Quick Tip: Conditionally Including JS and CSS With get_current_screen

      As many stated before me: “A good WordPress citizen only loads their files where they’re needed”. This principle applies both to front-end and back-end (admin). There’s no justification for loading CSS and JS files on every admin page when you only need them on one single page you created. Thankfully doing things the right way is only one function call away.

      Visit Article

    • Adding Post Series Functionality to WordPress With Taxonomies

      Adding Post Series Functionality to WordPress With Taxonomies

      Ever wrote a “post series” on your blog? If you did, you probably needed to add the links of the other parts of the series into the latest post you wrote. Each time you finished a new part, you had to update the link list of the other parts. There has to be an easier way, right?

      Visit Article


    • Mobiletuts+ — Mobile Development Tutorials

    • iOS SDK: UIKit Theme Customization

      iOS SDK: UIKit Theme Customization

      Theme customization is a great way to stand out in the App Store, but it isn’t always easy to achieve. This tutorial will teach you several basic UIKit customization tricks that will help distinguish your applications and create more memorable user experiences.

      Visit Article

    • Introduction to Unity3D

      Introduction to Unity3D

      Unity3D is a powerful cross-platform 3D engine and a user-friendly development environment. Learn how Unity3D can help you create games in this article!

      Visit Article

    • Analyzing Android Network Traffic

      Analyzing Android Network Traffic

      Network traffic analysis can be a vital part of the software debugging and testing process. This tutorial will teach you how to monitor all incoming and outgoing traffic on an Android device in order to better debug your applications!

      Visit Article


  6. Carlos Yanez says:
    June 6, 2012 at 11:29 pm

    No, this game isn’t powered by oranges and lemons; it’s built using the Citrus Engine, a scalable Flash game engine that takes a lot of the tedious work out of coding a game. In this Premium tutorial, aimed at keen beginners, you’ll learn how to use it to build a simple platformer.


    Premium Preview

    Let’s take a look at the result we will be working towards:

    Ever wanted to make a platformer, but not too keen on writing all the code from scratch? The Citrus Engine doesn’t eliminate code entirely, but it makes it much simpler, with plenty of useful 2D game features built right in. In this tutorial, we’ll use it to build a simple platform game.

    Read the Full Tutorial

    Premium members can access the full tutorial right away!

    If you’re not yet a Premium member, you can still read the first few steps for free.


    Tuts+ Premium Membership

    We run a Premium membership system which periodically gives members access to extra tutorials, like this one, from across the whole Tuts+ network. If you’re a Premium member, you can log in and read the tutorial. If you’re not a member, you can of course join today!

    Also, don’t forget to follow @envatoactive on twitter, circle us on Google+, like us on Facebook, and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.


  7. Michael James Williams says:
    June 7, 2012 at 12:17 am

    It’s a pain to have to change the parameters of a function; you have to change every other call to that function in order to avoid errors. But you can get around this by using just one parameter: a configuration object.


    What It Looks Like

    Here’s a silly example of a function for creating a robot:

    
    
    function generateRobot(arms:int, personality:String):Robot {
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    	return robot;
    }
    
    generateRobot(2, "evil");
    

    Now, here’s the same example, using a configuration object:

    
    
    function generateRobot(conf:Object):Robot {
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < conf.arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (conf.personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    	return robot;
    }
    
    generateRobot({arms:2, personality:"evil"});
    

    I’ve highlighted the lines that require changing; you can see that there’s not much difference.


    Why Bother?

    So if there’s hardly any difference, why would we bother doing it the second way? After all, it actually makes the function a little harder to use; whereas before our IDE would be able to give us this information about the parameters the function expected:

    …now it can only give us this:

    Suppose you want to add a couple more parameters: one specifying the material to use and another to specify what color its laser should be. That’s not too hard, in either case:

    
    
    function generateRobot(arms:int, personality:String, material:String, laserColor:String):Robot {
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    
    	switch (material) {
    		case "wood":
    			//wooden robot
    		break;
    		case "steel":
    		default:
    			//steel robot
    		break;
    	}
    
    	robot.laser = new Laser();
    	robot.laser.color = laserColor;
    
    	return robot;
    }
    
    generateRobot(2, "evil", "steel", "red");
    
    
    
    function generateRobot(conf:Object):Robot {
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < conf.arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (conf.personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    
    	switch (conf.material) {
    		case "wood":
    			//wooden robot
    		break;
    		case "steel":
    		default:
    			//steel robot
    		break;
    	}
    
    	robot.laser = new Laser();
    	robot.laser.color = conf.laserColor;
    
    	return robot;
    }
    
    generateRobot({arms:2, personality:"evil", material:"steel", laserColor:"red"});
    

    So far, still not much of a difference. What if you want your robots to all have red lasers by default? Simple again. Without a configuration object, you just need to change the method signature (the function line), and then you can remove the last argument from the function call:

    
    
    function generateRobot(arms:int, personality:String, material:String, laserColor:String = "red"):Robot {
        //this is all the same
    }
    
    generateRobot(2, true, "steel");    //I removed the last argument
    

    With a configuration object, it’s a little trickier – though not much:

    
    
    function generateRobot(conf:Object):Robot {
    	if (!conf.laserColor) {
    		conf.laserColor = "red";
    	}
    
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < conf.arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (conf.personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    
    	switch (conf.material) {
    		case "wood":
    			//wooden robot
    		break;
    		case "steel":
    		default:
    			//steel robot
    		break;
    	}
    
    	robot.laser = new Laser();
    	robot.laser.color = conf.laserColor;
    
    	return robot;
    }
    
    generateRobot({arms:2, personality:"evil", material:"steel"});   //I removed the last argument
    

    Okay. Now suppose you find that you’re setting almost all of your robots to be evil (I mean, why not?), so it’s actually kind of a pain to write “evil” as a parameter every time. Naturally, you want to set “evil” as the default – but you don’t want to set a default material.

    The only way you can do this, with a regular set of function parameters, is to switch the order of the personality and material parameters:

    
    
    function generateRobot(arms:int, material:String, personality:String = "evil", laserColor:String = "red"):Robot {
    

    Ah, but now you have to switch the order of the arguments round on every single function call!

    
    
    generateRobot(2, "evil", "steel");    //no longer works
    

    A configuration object doesn’t give you this problem. Check it out:

    
    
    function generateRobot(conf:Object):Robot {
    	if (!conf.laserColor) {
    		conf.laserColor = "red";
    	}
    	if (!conf.personality) {
    		conf.personality = "evil"
    	}
    
    	//this is all the same
    }
    
    generateRobot({arms:2, material:"steel"});  //no "personality" parameter? no problem!
    

    Neat! All your old generateRobot() function calls will continue to work, but you can create new calls that don’t bother specifying personality.

    You can even decide to get rid of the personality parameter altogether:

    
    
    function generateRobot(conf:Object):Robot {
    	if (!conf.laserColor) {
    		conf.laserColor = "red";
    	}
    	if (!conf.personality) {
    		conf.personality = "evil"
    	}
    
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < conf.arms; i++) {
    		//create arm and add it to robot
    	}
    
    	robot.commands = "Destroy mankind.";
    
    	switch (conf.material) {
    		case "wood":
    			//wooden robot
    		break;
    		case "steel":
    		default:
    			//steel robot
    		break;
    	}
    
    	robot.laser = new Laser();
    	robot.laser.color = conf.laserColor;
    
    	return robot;
    }
    

    The above version of the function doesn’t refer to conf.personality at all – but you won’t get an error if you still have calls like this:

    
    
    generateRobot({arms:2, personality:"evil", material:"steel"});
    

    Of course, you might get a few confused users if you have calls like this:

    
    
    generateRobot({arms:2, personality:"good", material:"steel"});
    

    …since all robots are now evil. But at least the code will compile.

    For the same reason, you can change the order of the arguments without it mattering at all, and even add in new parameters that don’t do anything yet:

    
    
    generateRobot({material:"steel", laserColor:"green", arms:2, voice:"Mr. T"});
    

    Making It Easier to Set Defaults

    The code for setting the defaults is easy to understand so far, but is going to be very annoying to extend if we need to have lots of parameters:

    
    
    	if (!conf.laserColor) {
    		conf.laserColor = "red";
    	}
    	if (!conf.personality) {
    		conf.personality = "evil"
    	}
    

    Let’s write some more general code to cope with it:

    
    
    	var defaults:Object = {
    		laserColor:red,
    		personality: "evil"
    	}
    
    	for (var key:String in defaults){
    		if (!conf[key]) {
    			conf[key] = defaults[key];
    		}
    	}
    

    That for loop may be a little confusing, so I’ll break it down. First, look at this:

    
    
    	for (var key:String in defaults){
    		trace(key);
    	}
    

    This is a for...in loop, which will output the names of the keys inside the default object:

    
    
    laserColor
    personality
    

    Next, look at this line:

    
    
    trace(defaults["laserColor"]);
    

    This will output red – it’s the same as writing trace(defaults.laserColor).

    Following on from that, look at this example:

    
    
    var example:Object = { demo: "test" };
    trace(example["demo"]);
    trace(example["foo"]);
    

    What do you think this will output?

    Well, example["demo"] is the same as example.demo, which equals "test". But example.foo does not exist, so example["foo"] will return null. This means that !example["foo"] (note the exclamation mark) will be equivalent to true.

    Put that all together, and you should be able to understand why this code works:

    
    
    	var defaults:Object = {
    		laserColor:red,
    		personality: "evil"
    	}
    
    	for (var key:String in defaults){
    		if (!conf[key]) {
    			conf[key] = defaults[key];
    		}
    	}
    

    Give me a shout in the comments if you need a hand!

    I Want More!

    For an even quicker version, try this:

    
    
    function generateRobot(conf:Object = null):Robot {
    	var conf:Object = conf || {};
    	var defaults:Object = {
    		laserColor:red,
    		personality: "evil"
    	}
    
    	for (var key:String in defaults){
    		conf[key] = conf[key] || defaults[key];
    	}
    

    The change in Line 1 (and new Line 2) means that even the conf object itself is optional, so you can just call generateRobot(). (Of course, you’ll need to change the code to deal with the values that don’t currently have defaults.)


    Helping the IDE Help You

    As I mentioned above, the IDE can’t give you any tips about what parameters a function is expecting, if that function uses a configuration object. This is a major drawback, as it can make your code really hard to use; you have to remember which parameters go in the conf object, as well as all of their names and types.

    But we can still display this information to the coder when it’s needed; we just have to do so manually, like so:

    
    
    			/**
    			 * Generate a robot, based on the parameters given.
    			 * @param	conf	Configuration object. Expects:
    				 * arms 		(int)		Number of arms robot should have.
    				 * personality 	(String)	Personality of robot. Can be "evil" or "good". Defaults to "evil".
    				 * material		(String)	What the robot should be made out of. Can be "steel" or "wood" at this time.
    				 * laserColor	(String)	Color of the robot's laser. Defaults to "red".
    				 * voice		(String)	Vocal stylings of robot. Currently not implemented.
    			 * @return	The finished robot.
    			 */
    			function generateRobot(conf:Object):Robot {
    				//
    			}
    

    Now, if I start to write a call to this function in FlashDevelop (my IDE of choice), I see this:

    Sure, it’s a bit of a pain to keep this manually updated, but in many cases it’s worth it.


    Conclusion

    I’m not claiming that you should use a configuration object for every single function you create from now on; just think of it as another useful tool in your arsenal.

    Personally, I find it a particularly useful pattern whenever I’m building the first draft of some set of classes that all need to work together. The added flexibility of a conf gives me so much more flexibility, freeing me up to zip around all the different functions and changing how they call one another, without worrying about breaking the code by inserting or removing a parameter.

    Remember the benefits:

    • It’s easy to add and remove parameters (at either end).
    • It’s easy to set default values.
    • You don’t have to worry about the order of the parameters.

    There are drawbacks to using simple objects like I have, though – especially if you do so in a project that’s past the prototyping stage. Check out the great comments below for more details!


  8. Porter says:
    June 7, 2012 at 12:46 am

    In today’s game critique, Matt Porter takes a look at the new hit tower defense game, Keeper of the Grove, developed by BooblyC.


    Overview

    Tower Defense games have always been a popular genre, especially for the casual / web demographic. This popularity has lead me to playing some pretty amazing Tower Defense games, as well as some horridly bland ones (with more of the latter, unfortunately). I love any game that’s easy to play but hard to master, and a good Tower Defense game is just that. Needless to say, when a well developed TD game comes along, I’m all for it.


    Play the Game

    You can play the game at its full size here.


    Gameplay

    While many Tower Defense games look great, the majority of the non-amazing ones fall flat on their faces due to bland gameplay. It appears to be a popular recipe to use the absolute basic form of a Tower Defense game, and to then polish the hell out of it. Unfortunately, gameplay has, and always will make a game, so extreme polish alone can’t do even this genre any justice.

    Keeper of the Grove critique

    Fortunately, Keeper of the Grove is not only extremely polished, but also pretty well stacked in the gameplay department. It has some serious balancing flaws, in my opinion, but it builds well upon the basic recipe of a Tower Defense game.

    Skills and Upgrades

    Units can be upgraded, and can even branch off into new units as you progress throughout the game. The game uses a “Wisdom Tree” upgrade system, which is where you must first pay to unlock the ability to have each specific higher level unit (within each map, not just once). To my knowledge, this was first seen in the hit Android game “Jelly Wars”, although it could quite possibly have existed long before.

    This system creates a level of complexity where players must balance spending between getting higher level units right off, or taking a slow and steady approach. In addition to the upgrading of units, each stage awards up to three skill points, and unlocking achievements grants additional skill points. These can be spent as you please on upgrading the different types of units, and can even be reset if you’d like.

    Keeper of the Grove critique

    One potential flaw to this, is that players can reset and customize their skills for each stage, which detracts from the developer’s balancing of the map. It’s not a horrible flaw, and it’s one that doesn’t necessarily always get spotted and abused, but it’s definitely something to consider when developing similar systems in your own games.

    Flaws

    There are three major flaws with Keeper of the Grove, in my opinion.

    The first is that there’s a little too much luck involved for a game that should be obsessively balanced and rely mostly on strategy. Keeper of the Grove includes a magic system that allows you to use spells on foes – a nice addition one would think. While these magic spells are very neat, and fun to look at, they severely hurt the balancing of the game. Spells are dropped at random when enemies are defeated, and what spell you get is random as well.

    The spells are actually quite powerful, so having one is a game changer. Perhaps you want to pull off a poison tower within the first few waves (an upgraded, rather expensive unit). Quite often, this won’t work – that is, unless you get an item that helps throw the odds in your favor. Once this happens, you’ve got an early powerhouse setup, and there’s really no way for you to lose.

    To emphasize this as a weakness, even the official video walkthrough shows the player using magic spells early on in levels, thus giving them an advantage that viewers could not replicate without extreme luck.

    I like the magic system; I just think it should be less up to luck, and more controlled. A possible solution would be to show the player how to achieve getting a magic spell, such as by killing X enemies, or surviving Y rounds without losing a crystal. These sub goals would make gameplay interesting, and ensure that magical spells are still in the game, but in a controlled manner. I came up with this system literally as I typed this, so there are obviously better ways to handle the magic system than what made it into the game.

    Keeper of the Grove critique

    The second flaw, in my opinion, is the design of the tutorial levels. The first few levels introduce new units, and don’t allow you to upgrade many. This is fine, as introducing new elements slowly is highly encouraged in game design, but I dislike the way they go about it.

    I’m forced to use Unit X in a level, but the level isn’t really set up in a way that’s perfectly clear about how this new unit is beneficial to me, and in what scenarios. If you’re going to limit the player to using certain units, for the sake of a tutorial level, it should be very clear (especially to a veteran of Tower Defense Games) how that unit should be used in that level, and what its role is.

    I also found the number of waves for the tutorial levels to be a bit high. I don’t want the game to be short, but 20 waves on level four – a tutorial level – seems a bit too long. You want to speed things up at first, and show the player what awesome features your game has to offer. Slow things down too soon, and they may never experience what could have been your hook.

    Keeper of the Grove critique

    The last major flaw in my opinion, is the difficulty curve. Myself and many others reported that the difficulty spikes up pretty early, and out of nowhere. I personally found that the difficulty jumps greatly in level four. It wasn’t unbeatable, but there were new elements and units introduced, and perfecting it seemed nearly impossible (without getting upgrades and returning later) compared to the previous three levels.

    With so much more of the game yet to be exposed to players, I think it’s extremely important to be careful about easing players in. I hadn’t even seen all of my units yet, and I was already faced with something I found to be pretty challenging, and slightly unfair (due to getting magic spells or not).

    Polish

    As far as gameplay polish goes, there’s a lot. The game builds far beyond the original recipe of Tower Defense games, and gives the player a lot to work towards. There’s a nice collection of awards to unlock (achievements), all of which also grant bonus skill points when achieved. In addition, the game also awards a final level that is only obtained by getting all the achievements. Tying these all together is an absolutely fantastic idea, as the player now has incentive to gain achievements.

    Keeper of the Grove critique

    The game becomes potentially easier through the awarded bonus skill points (a chance for struggling players to catch a break), and the average play time of each player is likely increased as they attempt to collect all these achievements to unlock that final level. The game also offers a hard mode from the start, which will likely provide any Tower Defense veteran with a nice challenge. Last but not least, there’s a nice looking bestiary for you to slowly unlock with tower stats, enemy stats, and so on – all viewable from the pause menu: a very nice addition.


    Graphics

    The graphics in Keeper of the Grove are absolutely perfect. No shortcuts were taken in the making of the graphics for this game. They’re cute and casual, extremely polished, and full of charm. Menus are simple and clean as far as navigation goes, but they too are on par with the high quality seen throughout the game. Particle effects add great value to many of the animations, but aren’t overdone. Everything that should be animated is, including interfaces and screen transitions.

    Keeper of the Grove critique

    While the cute style may not be for everyone, there really is little room for improvement graphically. As far as casual web or mobile games go, this is the level of visual polish that developers should strive for.


    Audio

    Much like the graphics in Keeper of the Grove, the audio is extremely well done. It’s clear that the music was professionally made, specifically for this game, and not just grabbed from a random stock music site.

    The music compliments the mood of the game by being quirky, charming, and upbeat. It’s exactly what the developers were looking for, and that’s exactly what you get when you hire a professional to do this kind of work. Many people skip out on professionally done music, but I know from personal experience that it more than pays off, assuming the rest of your game is of a quality that warrants such a thing.

    The sounds effects are of equal quality and style. Everything has a sound, and the project as a whole feels very audio-complete. It’s clear to me that the developers know how to polish a game, and the audio backs this thought up.


    Conclusion

    While Keeper of the Grove isn’t going to break any records or earn too many hardcore fans, it is indeed a perfect example of a remarkably polished game. The game is visually and audibly exactly what players and sponsors alike want, which is a very good thing to take note of if you plan on pleasing both parties any time soon. The gameplay isn’t groundbreaking, but it is well done, and enjoyable.

    All in all, it’s far above your average web game, and that’s not due to luck, so do yourself a favor and take note of what worked here and what didn’t.

    On another note, it might be worth debating whether a game like this is worth polishing to the extreme, or if an original game idea would be a far better use of the effort that went into these amazing graphical and audio assets; what do you think?


  9. Sebastian Bratu says:
    June 7, 2012 at 1:14 am

    In this second part of this mini-series of Premium tutorials, you’ll learn how to use Flash to build a Facebook Graph API application that can create slideshows for your public pages. This second part covers loading album information, and generating and displaying the embed code.


    Premium Preview

    Click to try the app on Facebook.

    Welcome back to our Facebook Flash application tutorial! In this part, we’re going to continue building the Flash interface for building the Facebook slider. The interface will handle choosing an album for displaying in a Facebook tab.

    This application allows you to select a Facebook album or event list from one of your public pages (not your personal profile) and turn it into a slideshow for your page tab. When the users enter your page, they will see photos from your chosen album, with your photo title and description, or event name, date and invites (for the Event tab).

    In future parts of this series, we’ll create the actual Flash slider that does just that; meanwhile we’ll create the generator for the embed code that will reside at the Facebook application URL.

    You’ll need to be logged in to Facebook in order to see this demo: https://apps.facebook.com/activetuts_tabmaker/


    Read the Full Tutorial

    Premium members can access the full tutorial right away!

    If you’re not yet a Premium member, you can still read the first few steps for free.


    Tuts+ Premium Membership

    We run a Premium membership system which periodically gives members access to extra tutorials, like this one, from across the whole Tuts+ network. If you’re a Premium member, you can log in and read the tutorial. If you’re not a member, you can of course join today!

    Also, don’t forget to follow @envatoactive on twitter, circle us on Google+, like us on Facebook, and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.


  10. Michael James Williams says:
    June 7, 2012 at 1:56 am

    Got 15 minutes to spare? Watch Martin Jonasson and Petri Purho explain how to use the concept of “juiciness” to turn a boring old Breakout clone into something way more exciting.


    Watch the Video

    Martin Jonasson runs Grapefrukt, where he posts a selection of his games, webbfarbror, where you can contact him to do work on commission, and prototyprally, a blog about rapid prototyping games using Flash.

    Petri Purho created Crayon Physics Deluxe, and runs the blog Kloonigames, where he keeps an archive of games, each of which he made within seven days.

    The term “juice” was coined in How to Prototype a Game in Under 7 Days:

    “Juice” was our wet little term for constant and bountiful user feedback. A juicy game element will bounce and wiggle and squirt and make a little noise when you touch it. A juicy game feels alive and responds to everything you do – tons of cascading action and response for minimal user input. It makes the player feel powerful and in control of the world, and it coaches them through the rules of the game by constantly letting them know on a per-interaction basis how they are doing.


    More Resources

    You can play the game itself here, but I recommend you watch the video first. The source is available on GitHub.

    There are plenty of additional links on the YouTube page for the video as well:

    • Robert Penner’s Easing Equations
    • Game Feel, a book by Steve Swink
    • How to Prototype a Game in Under 7 Days
    • Make It Juicy! by Emily Short
    • Principles of Animation
    • The Art of Diablo III
    • GUI Design and Easing Functions
    • Transitions: The Importance of Curves
    • Tim Groleau’s Easing Function Generator

    Big thanks to Christer Kaitila for bringing this video to my attention!


Leave a Reply

Click here to cancel reply.

search search search search search
Find an Article
Categories
  • Flash Video Training
  • Hints and Tips
  • Recommended
Please Support Our Sponsors
Recent Posts
  • Tuts+ Community Meetup in New York!
  • HTML5 Canvas Optimization: A Practical Example
  • Recreate the Cover Flow Effect Using Flash and AS3
  • Drawing Activetuts+ to a Close
  • Intro to Dart: Creating a Marquee
Tag Cloud
2011 ActionScript Active Activetuts+ Adobe animation Basic Basix Best Build Button Character Code Create Creating Critique Custom design Effect Effects Files Flash from Game Guide HTML5 Introduction Macromedia Motion Muzzle part Player Premium Professional Quick Silverlight Simple Text Tool Tutorial Tuts+ Using Video website Workshop
About Our Site:

Hey there and welcome to "Flash Video Training Source", a resource for anybody interested in learning more about Adobe's great tool. We feature educational videos, which will help you master Adobe Flash and help you get to know all of its features. We at "Flash Video Training Source" believe that video training and video... more

Why don't you follow us on Twitter and get the latest video tutorials twitted to your account. Just click on the floating twitter bar to your right!

Go Back In Time
June 2013
M T W T F S S
« Jul    
 12
3456789
10111213141516
17181920212223
24252627282930
Pretty Blank Box
top

Blogroll

  • Development Blog
  • Documentation
  • Plugins
  • Suggest Ideas
  • Support Forum
  • Themes
  • WordPress Planet

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

Archives

  • July 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • June 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • January 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010
  • June 2010
  • May 2010
  • April 2010
Powered by WordPress  |  Designed by Elegant Themes  |  Lightning Fast Hosting by Site 5 Hosting