augmented reality flartoolkit rotation - actionscript-3

I'm trying to do some augmented reality projects with flartoolkit . I can now put simple 3d objects on my marker and it works fine , but I wanna give my project some events that the user can interact with . I'm trying to trace the rotation of the marker. there's a container:DisplayObject3D which my application uses to add the 3d objects , I traced this :"trace(container.rotationZ)" but it's just returning 0 . I studied another AR application's source code and it was using the rotation of it's container object without problem .and I think I should mention that I'm using the exercise file of seb lee delisle papervision3d course from lynda.com . anyone has any experience with flartoolkit? the main functions of my my code is as below:
public function AR_AlchemyBase()
{
super(640,480, false);
cameraParams = FLARParam.getDefaultParam(WIDTH * 0.5, HEIGHT * 0.5);
marker = new FLARCode(16, 16);
marker.loadARPattFromFile(new MarkerPattern());
init();
}
public function init():void
{
video = new Video(WIDTH, HEIGHT);
webCam = Camera.getCamera();
webCam.setMode(WIDTH, HEIGHT, 30);
video.attachCamera(webCam);
video.smoothing = true;
camBitmapData = new BitmapData(WIDTH *0.5, HEIGHT * 0.5,false, 0x000000);
camBitmap = new Bitmap(camBitmapData);
camBitmap.scaleX = camBitmap.scaleY = 2;
addChildAt(camBitmap,0);
raster = new FLARRgbRaster(WIDTH *0.5, HEIGHT * 0.5);
detector = new FLARSingleMarkerDetector(cameraParams, marker, 80);
result = new FLARTransMatResult();
viewport.x = -4;
_camera = new FLARCamera3D(cameraParams);
container = new FLARMarkerNode();
scene.addChild(container);
addSceneObjects();
stage.addEventListener(Event.ENTER_FRAME, enterFrame);
}
//the function to put our objects in
public function addSceneObjects() : void
{
var wmat:WireframeMaterial = new WireframeMaterial(0xff0000, 1, 2);
wmat.doubleSided = true;
var plane : Plane = new Plane(wmat, 80, 80);
container.addChild(plane);
var light:PointLight3D = new PointLight3D();
light.x = 1000;
light.y = 1000;
light.z = -1000;
var fmat:FlatShadeMaterial = new FlatShadeMaterial(light, 0xff22aa, 0x0);
var cube : Cube = new Cube(new MaterialsList({all: fmat}), 40, 40, 40);
cube.z = -20;
container.addChild(cube);
}
public function enterFrame(e:Event):void
{
var scaleMatrix:Matrix = new Matrix();
scaleMatrix.scale(0.5, 0.5);
camBitmapData.draw(video, scaleMatrix);
raster.setBitmapData(camBitmapData);
counter++;
if(counter == 3) counter = 0;
var imageFound : Boolean = false
currentThreshold = threshold+ (((counter%3)-1)*thresholdVariance);
currentThreshold = (currentThreshold>255) ? 255 : (currentThreshold<0) ? 0 : currentThreshold;
imageFound = (detector.detectMarkerLite(raster, currentThreshold) && detector.getConfidence() > 0.5) ;
if(imageFound)
{
detector.getTransformMatrix(result);
container.setTransformMatrix(result);
container.visible = true;
threshold = currentThreshold;
thresholdVariance = 0;
if(onImageFound!=null) onImageFound();
}
else
{
if(counter==2) thresholdVariance +=2;
if(thresholdVariance>128 ) thresholdVariance = 1;
if(onImageLost!=null) onImageLost();
}
singleRender();
}

I might not be able to help with the main problem but If you want users to interact with the models you need to set their materials to be interactive, otherwise they don't receive mouse events. Regarding the rotation...I might be missing something but it's the instances inside the container thar you're applying the rotation to, not the the container itself?
This helped me with getting a simple PV3D example running:
PV3D Tutorial for basic interactivity

Related

How do I adjust drag speed of an object?

Ok, I am developing a game that requires the player to drag an object and place it inside of a jar. I found it to be much easier to designate an x coordinate limitation in order to determine when the object they are dragging should simulate dropping into the jar. The code that I have so far works perfectly. However, the action script that is initiated when the object crosses the x coordinate limit is ignored when the players move the object too fast over the x limit. I think that I can fix this problem by limiting how fast the object can be dragged. Does anyone have any direction on how this can be accomplished?
Here is my code:
jarFront.mouseEnabled = false; jarFront.mouseChildren = false;
// animate buttons in
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
import flash.events.Event;
var objArray:Array = new Array;
objArray.push(obj1);
objArray.push(obj2);
objArray.push(obj3);
var objPosition:Point;
function dragobj(e:Event):void {
e.currentTarget.startDrag();
objPosition = new Point( e.currentTarget.x, e.currentTarget.y);
}
function dragobjStop(e:Event):void {
e.currentTarget.stopDrag();
e.currentTarget.x = e.currentTarget.x;
e.currentTarget.y = objPosition.y;
objPosition = null;
}
for (var i:uint = 0; i < objArray.length; i++) {
objArray[i].addEventListener(MouseEvent.MOUSE_DOWN, dragobj);
objArray[i].addEventListener(MouseEvent.MOUSE_UP, dragobjStop);
}
// Drop in jar
var HighH:int=400;
var HighW:int=400;
var LowH:int=-200; var LowW:int=0;
var HighyH:int=170;
var HighyW:int=170;
var LowyH:int=0; var LowyW:int=0;
this.addEventListener( Event.ENTER_FRAME, goJar)
function goJar( e:Event ):void
{
if (obj1.x > 400 && obj1.x < 440) {
obj1.stopDrag();
//set back or tween position
obj1.x = 83;
obj1.y = -300;
this.setChildIndex(obj1,1)
var ct1_1:Tween = new Tween(obj1, "y", None.easeNone, obj1.y, obj1.y=Math.floor(Math.random()*(1+HighyH-LowyH))+LowyH, .2, true);
var ct1_2:Tween = new Tween(obj1, "rotation", Bounce.easeOut, 0, 180, 1, true);
var ct1_3:Tween = new Tween(obj1, "x", None.easeNone, obj1.x, obj1.x=Math.floor(Math.random()*(1+HighH-LowH))+LowH, .2, true);
} else {
// keep inside jar
if (obj1.x > -330 && obj1.x < -260) {
obj1.stopDrag();
//set back or tween position
obj1.x = 83;
obj1.y = -300;
this.setChildIndex(obj1,1)
var ct1_4:Tween = new Tween(obj1, "y", None.easeNone, obj1.y, obj1.y=Math.floor(Math.random()*(1+HighyH-LowyH))+LowyH, .2, true);
var ct1_5:Tween = new Tween(obj1, "rotation", Bounce.easeOut, 0, 180, 1, true);
var ct1_6:Tween = new Tween(obj1, "x", None.easeNone, obj1.x, obj1.x=Math.floor(Math.random()*(1+HighH-LowH))+LowH, .2, true);
}
}
}
Also, it would be VERY helpful if there was a way to include everything below "//Drop in jar" in the array functions above so that this action script can be automatically applied to obj2 and obj3.
You have no code in there that limits the movement of the dragged object whatsoever. If you want to limit the object position simply pass a Rectangle object to the startDrag method.
Thanks BotMaster, based on your direction I modified my code like so:
var rectangle1:Rectangle = new Rectangle(400, -665, 1156, 1052);
var rectangle2:Rectangle = new Rectangle(-376, -665, 721, 1052);
var candyPosition:Point;
function dragCandy(e:Event):void {
if (e.currentTarget.x > 400) {
e.currentTarget.startDrag(false, rectangle1);
candyPosition = new Point( e.currentTarget.x, e.currentTarget.y);
} else {
e.currentTarget.startDrag(false, rectangle2);
candyPosition = new Point( e.currentTarget.x, e.currentTarget.y);
}
}
Basically, what happens here:
If the object is at an x position greater than 400, then dragging will be constrained to rectangle1
Once the object has been dragged to a specific x position outside of the jar, it will be tweened inside of the jar.
Now that the object is in the jar, its new x position will be less than 400 and dragging will now be constrained to rectangle2.
Now, when the object is dragged up our of the jar and on top of the hitTestObject, it will be tweened back to a random position out side of the jar.

Using the Feathers ScreenNavigator with Starling and Signals

I'm new to Flash, Starling, and Feathers and am giving myself a kind of crash course, but am getting confused. I simply want my root starling class to initiate my game screen. I apologize if this is noobish. I really do want to understand.
I am not sure what dispatches FeathersEventType.INITIALIZE and I'm having trouble dispatching it manually. Any pointers in the right direction would be greatly appreciated.
In my Main.as (my Document Class), I instantiate starling, wait for the Root to be created, and then call its Start function (saw this in an example of how to show an initial background, not sure if it's best practice).
this.mStarling = new Starling(Root, this.stage, viewPort);
... //set background from embed
mStarling.addEventListener(starling.events.Event.ROOT_CREATED,
function(event:Object, app:Root):void
{
mStarling.removeEventListener(starling.events.Event.ROOT_CREATED, arguments.callee);
removeChild(background);
background = null;
var bgTexture:Texture = Texture.fromEmbeddedAsset(
backgroundClass, false, false);
//app.start(bgTexture, assets);
app.start(bgTexture, assets) // call the START on my root class
mStarling.start();
});
Here's my Root class (which is the root class passed to Starling)
public function Root()
{
if (verbose) trace(this + "Root(" + arguments);
super();
this.addEventListener(FeathersEventType.INITIALIZE, initializeHandler);
}
// this is not being called
private function initializeHandler(e:Event):void
{
this._navigator.addScreen(GAME_SCREEN, new ScreenNavigatorItem(GameScreen,
{
complete: MAIN_MENU
}));
}
public function start(background:Texture, assets:AssetManager):void
{
sAssets = assets; // assets loaded on document class
addChild(new Image(background)); // passed from doc class
this._navigator = new ScreenNavigator();
this.addChild(this._navigator);
var progressBar:ProgressBar = new ProgressBar(300, 20);
progressBar.x = (background.width - progressBar.width) / 2;
progressBar.y = (background.height - progressBar.height) / 2;
progressBar.y = background.height * 0.85;
addChild(progressBar);
// Progress bar while assets load
assets.loadQueue(function onProgress(ratio:Number):void
{
progressBar.ratio = ratio;
if (ratio == 1)
Starling.juggler.delayCall(function():void
{
gameScreen = new GameScreen();
trace("got this far" + gameScreen);
gameScreen.GAME_OVER.add(gotoGameOverScreen);
gameOverScreen = new GameOverScreen();
gameOverScreen.PLAY_AGAIN.add(gotoGameScreen);
progressBar.removeFromParent(true);
// This is where I'd like the GAME_SCREEN to show.
// now would be a good time for a clean-up
System.pauseForGCIfCollectionImminent(0);
System.gc();
}, 0.15);
});
This is part of my Root Class
public function start(background:Texture, assets:AssetManager):void
{
stageW= int(stage.stageWidth);
stageH = int(stage.stageHeight);
sAssets = assets;
bgIma=new Image(background);
bgIma.height=g.stageH * 0.4;
bgIma.scaleX=bgIma.scaleY;
bgIma.x=(g.stageW-bgIma.width)>>1;
bgIma.y=(g.stageH-bgIma.height)>>1;
addChild(bgIma);
var progressBar:ProgressBar = new ProgressBar(175, 20);
progressBar.x = (g.stageW - progressBar.width) >> 1;
progressBar.y = (g.stageH - progressBar.height) >> 1;
progressBar.y = g.stageH * 0.8;
addChild(progressBar);
assets.loadQueue(function onProgress(ratio:Number):void
{
progressBar.ratio = ratio;
if (ratio == 1)
Starling.juggler.delayCall(function():void
{
progressBar.removeFromParent(true);
removeChild(bgIma);
bgIma=null;
addedToStageHandler();
addSounds();
System.pauseForGCIfCollectionImminent(0);
System.gc();
}, 0.15);
});
}
protected function addedToStageHandler(event:starling.events.Event=null):void
{
this._navigator = new ScreenNavigator();
_navigator.autoSizeMode = ScreenNavigator.AUTO_SIZE_MODE_CONTENT;
this.addChild( this._navigator );
this._transitionManager = new ScreenFadeTransitionManager(_navigator);
this._navigator.addScreen( "Fluocode", new ScreenNavigatorItem(Fluocode));
this._navigator.addScreen( "Main", new ScreenNavigatorItem(AppMain));
this._navigator.showScreen("Fluocode");
this._transitionManager.duration = 0.5;
this._transitionManager.ease = Transitions.EASE_IN;
}

Add child + hittest?

AS3 Flash -
Hey, I made a game like "Flappy Bird".
Can someone help me how to check "character" hitted a wall?
This game generate every 2.5 seconds two walls. (Wall and Wall2)
How to check that character hitted it?
function newWall():void
{
var Wall:wall = new wall();
addChildAt(Wall, 1);
Wall.x = -350 + (-80 - -350) * Math.random();
Wall.y = 805;
Wall.name = "Wall1_Object";
TweenLite.to(Wall, 10, {y:-50, ease:Linear.easeNone});
var Wall2:wall = new wall();
addChildAt(Wall2, 1);
Wall2.x = Wall.x + Wall.width + 125;
Wall2.y = 805;
Wall2.name = "Wall2_Object";
TweenLite.to(Wall2, 10, {y:-50, ease:Linear.easeNone});
}
function checkDead():void
{
if (character.hitTestObject(Wall) || character.hitTestObject(Wall2))
{
trace("You dead!");
}
}
var newWallInterval:uint = setInterval(newWall,2500);
var checkDeadInterval:uint = setInterval(checkDead,500);
If the last walls can't be hit any more when the new walls created,Try to define Wall and Wall2 outside the new newWall function.,or you need create an array to save the walls, and do a loop to check if the role hit the wall.

AS3 return dropped object to initial location

I am using codes from http://hub.tutsplus.com/tutorials/create-a-drag-and-drop-puzzle-in-actionscript-30--active-2920 to make a drag and drop decoration game. I am trying to make it so that when the dropped object is dragged out of target location (which is an outline of the shape in my case), it goes back to initial location... basically reversing the drag and drop. I've been messing around with really random codes and so far this line is the closest to what I want but I don't think the code is right and also it doesnt return to initial location, it just goes to the side of the stage.
so, I added the else if line to stopDragObject which got the object to be removed from target location, but it randomly goes to the side of the stage, and not initial location:
private function stopDragObject(evt:MouseEvent):void {
if (evt.target.hitTestObject(getChildByName(evt.target.name + "Target"))) {
evt.target.x = getChildByName(evt.target.name + "Target").x;
evt.target.y = getChildByName(evt.target.name + "Target").y;
} else if (evt.target.x = null) {
evt.target.x = xPos;
evt.target.y = yPos;
}
evt.target.stopDrag();
}
Solved
after reading the lesson from below, I ended up with this and it works perfectly! (not exactly the way like the lesson but at least it works...)
private function stopDragObject(evt:MouseEvent):void {
if (evt.target.hitTestObject(getChildByName(evt.target.name + "Target"))) {
evt.target.x = getChildByName(evt.target.name + "Target").x;
evt.target.y = getChildByName(evt.target.name + "Target").y;
} else {
evt.target.x = getChildByName(evt.target.name + "Int").x;
evt.target.y = getChildByName(evt.target.name + "Int").y;
}
evt.target.stopDrag();
}
I added a initial object so the object could only be either at target or initial :)
I will try to teach neither provide code.
Lets draw two rectangles:
var s1:Sprite = new Sprite()
var s2:Sprite = new Sprite()
with (s1)
{
graphics.beginFill(0xfcaaaa, .7)
graphics.drawRect(0, 0, 400, 400)
graphics.endFill()
}
with (s2)
{
graphics.beginFill(0x00aaaa, .7)
graphics.drawRect(0, 0, 30, 30)
graphics.endFill()
}
addChild(s1)
addChild(s2)
Is't that simple? You see that s1 is much bigger than s2 (dimentions: 400, 400 vs 30, 30 ) Now place s2 to the center of our big s1:
s2.x = 200;
s2.y = 200;
We will use s1 for the boundaries of s2 movings.
This code is a simplest solution for dragging our s2 rectangle (Sprite):
s2.addEventListener(MouseEvent.MOUSE_DOWN, onDown)
s2.addEventListener(MouseEvent.MOUSE_UP, onUp)
function onDown(e:MouseEvent):void
{
(e.currentTarget as Sprite).startDrag();
}
function onUp(e:MouseEvent):void
{
(e.currentTarget as Sprite).stopDrag();
}
Now, the basic solution for returning our Sprite to the starting position: hitTestObject will return true, if Sprite s2 is still located in the area of Sprite s1. More helpful functions here. Lets check it. Change onUp function this way:
function onUp(e:MouseEvent):void
{
var s:Sprite = (e.currentTarget as Sprite);
s.stopDrag();
if (!s.hitTestObject(s1))
{
s.x = 200;
s.y = 200;
}
}
You see that now s2 gets returned to the starting position if it gets dragged out from the area of s1.
Now the main part:
What to do, if you can't predict the starting position of the object? Now, when we know how to deal with already known coordinates, this is the challange. I assume that there are several implementations of this functionality exist. One of the best way is to set additional parameters e.g. startingX and startingY for the dragging object when starting drag. E.g. in our example when onDown function gets called. I guess you dealing with Sprites or MovieClips and don't have the ability to do this.
Lets go another way and use Dictionary object. Dictionary is some kind of traditional Hash Map with the ability to use objects as keys.
Hash map is kind of storage, where you can put any value mapped by a key, provided by you. In actionscript 3 we have Object as a limited implementation of Hash Map. Why use it? In two words because it's simple and fast. But with Object we can't use other Objects as keys, only strings ints numbers etc..
var sites:Object = new Object();
sites['stackoverflow'] = "http://stackoverflow.com/"
trace(sites.stackoverflow) // outputs-> http://stackoverflow.com/
With Dictionary we can use Objects as keys.
Lets create it:
var startCoordinates:Dictionary = new Dictionary();
To save coordinates, we need x and y property.
FYI: new Object() is equivalent of {}
var capitals:Object = new Object();
capitals['Italy'] = 'Rome';
is equivalent of
var capitals:Object = {Italy: 'Rome'};
To save current position we will use this code:
var s:Sprite = (e.currentTarget as Sprite);
startCoordinates[s] = { x: s.x, y: s.y };
And the whole code in our example will look like this:
var s1:Sprite = new Sprite()
var s2:Sprite = new Sprite()
addChild(s1)
addChild(s2)
with (s1)
{
graphics.beginFill(0xfcaaaa, .7)
graphics.drawRect(0, 0, 400, 400)
graphics.endFill()
}
with (s2)
{
graphics.beginFill(0x00aaaa, .7)
graphics.drawRect(0, 0, 30, 30)
graphics.endFill()
}
s2.x = 200;
s2.y = 200;
s2.addEventListener(MouseEvent.MOUSE_DOWN, onDown)
s2.addEventListener(MouseEvent.MOUSE_UP, onUp)
var startCoordinates:Dictionary = new Dictionary()
function onDown(e:MouseEvent):void
{
var s:Sprite = (e.currentTarget as Sprite);
startCoordinates[s] = { x: s.x, y: s.y };
s.startDrag();
}
function onUp(e:MouseEvent):void
{
var s:Sprite = (e.currentTarget as Sprite);
s.stopDrag();
if (!s.hitTestObject(s1))
{
s.x = startCoordinates[s].x;
s.y = startCoordinates[s].y;
}
delete startCoordinates[s];
}

AS3 Multiple Webcams not showing 3rd webcam

Hi I'm trying to create a simple AIR 3 application that displays 3 Webcams on the stage. For some reason the 3rd webcam doesn't want to show, it doesn't even turn on the LED indicator on the webcam.
I have tried multiple webcams eg. microsoft, logitech, built in....
The following code doesn't work:
var videoWidth:int = 1000 / totalCols;
var videoHeight:int = 800 / totalRows;
for (var i:int = 0; i < Math.min(Camera.names.length, totalRows * totalCols); i++) {
var currRow:int = Math.floor(i / totalCols);
var currCol:int = i % totalCols;
var video:Video = new Video(videoWidth, videoHeight);
var cam:Camera = Camera.getCamera(i.toString());
if (cam) {
cam.setMode(videoWidth, videoHeight, 30);
video.attachCamera(cam);
video.x = currCol * videoWidth;
video.y = currRow * videoHeight;
StageObj.addChild(video);
}
}
Neither does this:
//camera settings
track_cam = new Camera();
track_cam = Camera.getCamera("1");
track_cam.setMotionLevel(100);
track_cam.setQuality(0, 100);
track_cam.setMode(1920, 1080, 30);
track_feed = new Video();
track_feed.width = track_cam.width;
track_feed.height = track_cam.height;
track_feed.smoothing = true;
track_feed.attachCamera(track_cam);
StageObj.addChild(track_feed);
player_one_cam = new Camera();
player_one_cam = Camera.getCamera("2");
player_one_cam.setMotionLevel(100);
player_one_cam.setQuality(0, 100);
player_one_cam.setMode(200, 200, 30);
player_one_feed = new Video();
player_one_feed.width = player_one_cam.width;
player_one_feed.height = player_one_cam.height;
player_one_feed.smoothing = true;
player_one_feed.attachCamera(player_one_cam);
StageObj.addChild(player_one_feed);
player_one_feed.x = 500;
player_one_feed.y = 500;
player_two_cam = new Camera();
player_two_cam = Camera.getCamera("0");
player_two_cam.setMotionLevel(100);
player_two_cam.setQuality(0, 100);
player_two_cam.setMode(200, 200, 30);
player_two_feed = new Video();
player_two_feed.width = player_two_cam.width;
player_two_feed.height = player_two_cam.height;
player_two_feed.smoothing = true;
player_two_feed.attachCamera(player_two_cam);
StageObj.addChild(player_two_feed);
Is there a limit on the amount of webcams you can use in AS3?
It seems that I ran out of USB Bandwidth, when using usb 3 on a seperate machine it started working.
Looks like it should work from the docs:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Camera.html#getCamera()
name:String (default = null) — Specifies which camera to get, as
determined from the array returned by the names property. For most
applications, get the default camera by omitting this parameter. To
specify a value for this parameter, use the string representation of
the zero-based index position within the Camera.names array. For
example, to specify the third camera in the array, use
Camera.getCamera("2").