Monday, August 18, 2008

The Sliding Button Class

I recently finished a new Flash game called Trig Spinner. A couple ActionScript 3.0 classes developed over the course of the project, so I've decided to share them with the curious.

Today's class is the oh-so-neat sliding button:


The sliding piece on the button gets dragged by the mouse and when let go, locks to either the left or right side. In Trig Spinner's case, it sets the game mode into either degrees or radians. I made a sample file to demonstrate how the button works:





The class's code goes as follows:

package {

import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.geom.Point;

//Algorithm
//on mouse down
//if mouse is touching slider
//start dragging it
//on mouse up over the button or stage
//if I am dragging the slider, stop dragging it
//release and autolock the slider to closest edge
//left = true
//right = false

public class SlideButton extends MovieClip {
//For a cool sliding button that gets dragged by the mouse and locks into place when let go
//if the piece isn't dragged, the it will also autolock on the closest side the mouse releases inside the button boundaries
//NOTE: slidePiece1 is an instance variable name inside my library movieclip

//generic variable describing the boolean state of the button,
//access it through myBoolState and interperet it
private var myBool:Boolean;
//assists dragging accuracy, difference between mouseX and slidePiece1's x
private var xDiff:Number;
private var initWidth:Number;
private var rightEdge:Number;
//constructor
public function SlideButton() {
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownState);
slidePiece1.mouseEnabled = false;
//true by default, be careful!
myBool = true;
xDiff = 0;
//width changes during runtime when the slide piece is dragged too far, need it constant
//scaling the SlideButton instance is also a factor
initWidth = width/scaleX;
//the farthest x-coordinate the slide piece can go,
//do not confuse with the edge of the button graphic
rightEdge = initWidth-slidePiece1.width;
}
public function get myBoolState():Boolean {
return myBool;
}

public function mouseDownState(event:MouseEvent) {
//convert local points to global so hitTest will work
var clickPoint:Point = new Point(mouseX, mouseY);
clickPoint = localToGlobal(clickPoint);
if (slidePiece1.hitTestPoint(clickPoint.x, clickPoint.y, true)) {
xDiff = slidePiece1.x - mouseX;
addEventListener(Event.ENTER_FRAME, dragHandler);
} else {
xDiff = -slidePiece1.width/2;
}
//let the stage listen for the mouseUp since the mouse can be dragged anywhere
this.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpState);
}
public function dragHandler(event:Event) {
//don't drag beyond the button boundaries
if (mouseX + xDiff < 0) {
slidePiece1.x = 0;
} else if (mouseX + xDiff > rightEdge) {
slidePiece1.x = rightEdge;
} else {
slidePiece1.x = mouseX + xDiff;
}
}
public function mouseUpState(event:MouseEvent) {
removeEventListener(Event.ENTER_FRAME, dragHandler);
if (mouseX + xDiff <= rightEdge/2) {
slidePiece1.x = 0;
myBool = true;
} else if (mouseX + xDiff > rightEdge/2) {
slidePiece1.x = rightEdge;
myBool = false;
}
event.target.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpState);

}
}
}


Download the sample .fla file here.

You are free to use this code however you please (without any warranty whatsoever, not even an implied one), but crediting me would be a nice gesture. ;)

(Learn about ActionScript 3.0 classes here.)

No comments: