forked from: flash on 2011-1-6
forked from flash on 2011-1-6 (diff: 222)
ActionScript3 source code
/**
* Copyright j2e ( http://wonderfl.net/user/j2e )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/36nO
*/
package
{
import com.greensock.TweenMax;
import com.greensock.easing.*;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.media.Camera;
import flash.media.Video;
import flash.trace.Trace;
public class MotionDetection extends Sprite
{
private var _camera:Camera; // camera class for webcam capture
private var _video:Video; // video class for displaying the camera class
private var _tracking:VideoTracker; // motion tracking class
private var _paddle:PaddleMC = new PaddleMC(); // table tennis paddle
private var _shadow:ShadowMC = new ShadowMC(); // table tennis paddle shadow
private var _ball:BallMC = new BallMC(); // table tennis ball
private var _ballShadow:BallShadowMC = new BallShadowMC(); // table tennis ball shadow
private var _bkgd:BackgroundMC = new BackgroundMC(); // table tennis table background
private var _scoreMC:ScoreMC = new ScoreMC(); // simple score text movie
private var _startPanel:StartPanelMC = new StartPanelMC(); // start game panel
private var _endPanel:EndPanelMC; // end game panel
private var _pos:Point = new Point(); // current position of motion detection
private var _w:uint = 320; // width of camera/video source
private var _h:uint = 240; // height of camera/video source
private var _ratioX:Number; // ratio of stage width over the video width
private var _ratioY:Number; // ratio of stage height over the video height
private var _maxRot:Number = 30; // the maximum amount the paddle will rotate when moving away from the center of the screen
private var _score:uint = 0; // keeps tracks of the amount of times the balls been hit
public function MotionDetection()
{
// setup
setup();
setupStage();
resize();
// events
addEventListener(Event.ENTER_FRAME, loop);
// add assets to the screen
addChild(_bkgd);
addChild(_scoreMC);
addChild(_shadow);
addChild(_paddle);
addChild(_startPanel);
}
// main setup
private function setup():void
{
// setup camera
_camera = Camera.getCamera();
_camera.setMode(_w, _h, 15);
// setup video and attach the camera
_video = new Video(_w, _h);
_video.attachCamera(_camera);
// setup the tracking class with the video as the source
_tracking = new VideoTracker(_video);
// position start panel
_startPanel.x = sW*.5;
_startPanel.y = sH*.5;
// add listener for button to start the game
_startPanel.start_but.addEventListener(MouseEvent.MOUSE_DOWN, startGame, false, 0, true);
// set default props on assets
_paddle.z = 0;
_shadow.z = 200;
_shadow.alpha = .5;
_scoreMC.x = sW*.5;
_scoreMC.y = sH-50;
}
// stage settings
private function setupStage():void
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addEventListener(Event.RESIZE, resize);
}
// reset/start game
private function startGame(e:MouseEvent=null):void
{
// reset score
_score = 0;
_scoreMC.tf_txt.text = "0";
// default the balls position to the center of the screen and hide it
_ball.x = sW*.5;
_ball.z = 0;
_ball.alpha = 0;
_ballShadow.x = sW*.5;
_ballShadow.z = 0;
_ballShadow.alpha = 0;
// add ball to the scene
addChild(_ballShadow);
addChild(_ball);
// if the start panel is showing then hide it
if (_startPanel != null) TweenMax.to(_startPanel, .5, { alpha: 0, onComplete: removePanel, onCompleteParams: [_startPanel] });
// if the end panel is showing then hide it
if (_endPanel != null) TweenMax.to(_startPanel, .5, { alpha: 0, onComplete: removePanel, onCompleteParams: [_endPanel] });
// set a delayed fade up animation for the ball and have a callback function to start the balls motion
TweenMax.to(_ball, 1, { alpha: 1, onComplete: moveBall });
}
// end game
private function endGame():void
{
// add end panel
_endPanel = new EndPanelMC();
// position it
_endPanel.x = sW*.5;
_endPanel.y = sH*.5;
// show it
_endPanel.alpha = 0;
TweenMax.to(_endPanel, 1, { alpha: 1 });
// update its score
_endPanel.tf_txt.text = String(_score);
// add listener for button
_endPanel.again_but.addEventListener(MouseEvent.MOUSE_DOWN, startGame, false, 0, true);
// remove ball to the scene
removeChild(_ballShadow);
removeChild(_ball);
// add the end panel to the display
addChild(_endPanel);
}
// remove the speicifed panel from the scene
private function removePanel(panel:Sprite):void
{
removeChild(panel); // remove the panel from the display
panel = null; // null it to remove from memory
}
// update motion detection and render all elements
private function loop(e:Event):void
{
// update tracking
_tracking.track();
_pos = _tracking.pos; // update current position
_pos.x *= _ratioX; // update the positions by the ratio we have set
_pos.y *= _ratioY;
movePaddle(); // update paddle movement
}
// update the movement of the paddle
private function movePaddle():void
{
// update tracker
_paddle.x += (_pos.x - _paddle.x) * .1;
_shadow.x += (_pos.x - _shadow.x) * .1;
// update rotation
// this is based on the position of the paddle in relation to the screen width
// we first set the the rotation to its lowest rotation and then use the
// ratio of the paddles position to add more rotation to it
var rot:Number = -_maxRot + (_paddle.x/sW)*(_maxRot*2);
_paddle.rotation = rot;
_shadow.rotation = rot;
}
// update balls motion
private function moveBall():void
{
var time:Number = Math.random()*1+1; // create a random time for the ball to bounce up with
var x:Number = Math.random()*(sW-200)+100; // create a random x position for the ball to bounce to
var z:Number = -200 * time; // use the time to dictate the height of the balls bounce
// create the animation
TweenMax.to(_ball, time, { x: x, ease: Sine.easeOut, onComplete: checkCollison });
TweenMax.to(_ball, time*.5, { z: z, ease: Circ.easeOut });
TweenMax.to(_ball, time*.5, { z: 0, ease: Circ.easeIn, delay: time*.5 });
TweenMax.to(_ballShadow, time, { x: x, ease: Sine.easeOut });
TweenMax.to(_ballShadow, time*.5, { alpha: .6/time, scaleX: 1/time, scaleY: 1/time, ease: Quad.easeInOut });
TweenMax.to(_ballShadow, time*.5, { alpha: .6, scaleX: 1, scaleY: 1, ease: Quad.easeInOut, delay: time*.5 });
}
// check ball collision with the paddle
private function checkCollison():void
{
// this is just a simple collision detection system where we are just checking the balls
// position comes back with a positive hitTest with the paddle
if (_paddle.hitTestPoint(_ball.x, _ball.y, true))
{
moveBall(); // we have hit the ball, lets send the ball on a new motion path
_score++; // increment score
updateScore(); // update score display
}
else
{
// we have missed the ball, lets show a prompt asking the user to start again
endGame();
}
}
// update score
private function updateScore():void
{
_scoreMC.tf_txt.text = String(_score);
}
// resize and reflow elements when the stage resizes
private function resize(e:Event=null):void
{
_ratioX = sW/_w; // update x / y ratios
_ratioY = sH/_h;
_paddle.y = sH*.5; // update paddle y position
_shadow.y = sH*.55; // update shadow y position
_ball.y = sH*.35; // update ball y position
_ballShadow.y = sH*.35; // update ball y position
}
// return stage width and height
public function get sW():uint { return stage.stageWidth; }
public function get sH():uint { return stage.stageHeight; }
}
}
