as3 Using resized information to scale my movieclip - actionscript-3

I am working on an air mobile app in Flash CS5.5 and am fairly new at this.
So here is my problem: I placed all of my content inside of a movieClip called base. I have written code to resize my movieClip based on the device it is running on and the devices orientation. That part works fine, the problem is when I tried to create a zoom function.
The base movieClip scales but I am having trouble getting the minimum boundary to work so that my content never scales less than the width of the device. I believe it is referring to the original base width instead of the resized base width. Any ideas on how to call on the new base width after the resize function? Refer to my code below and thank you in advance for any help :)
import flash.geom.Rectangle;
stop();
base.play();
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
var guiSize:Rectangle = new Rectangle(0, 0, 480, 800);
var appScale:Number = 1;
stage.addEventListener(Event.RESIZE, handleResize);
function handleResize(e:Event):void {
var deviceSize:Rectangle = new Rectangle(0, 0, stage.stageWidth,
stage.stageHeight);
appScale = deviceSize.width / guiSize.width;
base.width = appScale * guiSize.width;
base.height = appScale * guiSize.height;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
base.addEventListener(TransformGestureEvent.GESTURE_ZOOM , onZoom);
function onZoom (e:TransformGestureEvent):void{
if (base.scaleX * e.scaleX < 1)
{}
else if (base.scaleX * e.scaleX > 5)
{}
else {
base.scaleX *= (e.scaleX+e.scaleY)/2;
base.scaleY *= (e.scaleX+e.scaleY)/2;}
}
}

After playing around with the code and trying many different solutions I came up with the code below and it seems to work fine. The problem was that my base movieClip was scaled up after the resize function which threw off the base.scaleX variable for my zoom function. This is because base.scaleX equals more than one. You can see the problem here:
if (base.scaleX * e.scaleX < 1)
The code was causing my base movieClip to scale down less than my device window. My solution is to use the new base.width instead to determine minimum and maximum scaleing for my zoom function. As noted below.
function onZoom (e:TransformGestureEvent):void{
if (base.width * e.scaleX < deviceSize.width )
{}
else if (base.width * e.scaleX > deviceSize.width * 2 )
{}
else {
base.scaleX *= (e.scaleX+e.scaleY)/2;
base.scaleY *= (e.scaleX+e.scaleY)/2;}
}
}

Related

Cant place item according to device's screen height

I am trying to add a child at the bottom of the screen.
I am using stage.stageHeight, but it doesn't seem to be able to get the height of the device properly.
It is leaving a very wide gap between the child (s6) and the bottom of the screen.
Code:
addEventListener(Event.ADDED_TO_STAGE, onadded);
function onadded (event:Event):void{
addChild(s6);
s6.y = stage.stageHeight - s6.height;
s6.width = width - 20;
s6.x = stage.x+10;
}
Edit:
addEventListener(Event.ADDED_TO_STAGE, onadded);
function onadded (event:Event):void{
addChild(s7);
s7.width = stage.stageWidth;
stage.align = StageAlign.TOP_LEFT;
addChild(s6);
trace(stage.fullScreenWidth);
trace(stage.fullScreenHeight);
s6.y = stage.fullScreenHeight - s6.height;
s6.width = width - 20;
s6.x = stage.x+10;
s6.account.addEventListener(MouseEvent.CLICK, fl_ClickToGoTomyaccount);
s6.automatch.addEventListener(MouseEvent.CLICK, fl_ClickToGoToAAA);
s6.search.addEventListener(MouseEvent.CLICK, fl_ClickToGoTosearchpage);
s7.myaccount.addEventListener(MouseEvent.CLICK, fl_ClickToGoTomyaccount);
s7.autmatch.addEventListener(MouseEvent.CLICK, fl_ClickToGoToAAA);
s7.sssearch.addEventListener(MouseEvent.CLICK, fl_ClickToGoTosearchpage);
}
you can use the screen resolution property and use them in your code.
I have done one example like this and it varies on different screen resolutions.
var screenWidth:int = Capabilities.screenResolutionX;
var screenHeight:int = Capabilities.screenResolutionY;
this.width= screenWidth - (screenWidth / 2);
this.height=screenHeight - 200;
Hope it will work for you
I think you should use fullScreenHeight instead of stageHeight: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Stage.html#fullScreenHeight
This is very true especially when working with mobile devices. stageHeight and stageWidth are not very reliable then.
You may also want to wait for RESIZE event which will occur shot after your app initialized, and then you can again use stageHeight instead.

Zooming and translate in as3 AIR Android

I am developing an android app with Adobe Flash cs6 and actionscript3. I have multiple moviclips at various locations on stage. Now I need to add a zoom feature that will zoom all movieclips as one movieclip. I cannot combine all movieclips together into one movieclip. My zoom feature works but it does not translate the movieclips to a new position. (Meaning they zoom at their original positions only) How can I accomplish this? Following is my zooming code :
/* ZOOM FEATURE */
Multitouch.inputMode = MultitouchInputMode.GESTURE;
zoomer.addEventListener(TransformGestureEvent.GESTURE_ZOOM , onZoom);
function onZoom (e:TransformGestureEvent):void{
mc1.scaleX *= (e.scaleX+e.scaleY)/2;
mc1.scaleY *= (e.scaleX+e.scaleY)/2;
mc2.scaleX *= (e.scaleX+e.scaleY)/2;
mc2.scaleY *= (e.scaleX+e.scaleY)/2;
mc3.scaleX *= (e.scaleX+e.scaleY)/2;
mc3.scaleY *= (e.scaleX+e.scaleY)/2;
}
Not the cleanest code I've written, but it should do the trick. scaleInPlace() accepts 4 arguments, 2 required, two optional:
obj: the display object you want to scale
scaleFactor: just as it sounds, how big/small do you want it?
fromX: the X coordinate where you want to scale from. Left, middle, right? If omitted, it operates from the middle of the compiled stage size.
fromY: same as the previous, but for top, middle, bottom.
This will preserve your DisplayList hierarchy while allowing you to scale to your heart's desire. If you had a lot of objects to scale, I'd probably parent all of them to the container first, and then run the scale and reparenting operations. While it works, this is the reason I feel it's not the "cleanest" solution. In my own classes, I've written a purely mathematical solution that doesn't include adding/removing DisplayObjects, but it's fairly tied up in my own classes I couldn't pull it out here and have it work.
Cheers!
// Let's scale myObject to 50% of its original size.
scaleInPlace(myObject, 0.5);
function scaleInPlace(obj:DisplayObject, scaleFactor:Number, fromX:Number = NaN, fromY:Number = NaN):void {
// If no coordinates from where to scale the image are provided, start at the middle of the screen
if (isNaN(fromX)) { fromX = loaderInfo.width/2; }
if (isNaN(fromY)) { fromY = loaderInfo.height/2; }
var father:DisplayObjectContainer = obj.parent;
var rect:Rectangle; // Coordinates for tracking our object
var index:int = getChildIndex(obj) // Where this object should go when we put it back
// Create the container
var container:Sprite = new Sprite();
father.addChild(container);
// Place the origin of the scale operation
container.x = fromX;
container.y = fromY;
// Get the coordinates of our object relative to our container
rect = obj.getRect(container);
// Parent and move into place
container.addChild(obj);
obj.x = rect.x;
obj.y = rect.y;
// Scale
container.scaleX = container.scaleY = scaleFactor;
// Get the coordinates and size of our scaled object relative to our father
rect = obj.getRect(father);
// Cleanup the display list
father.addChildAt(obj, index);
father.removeChild(container)
// Apply the new coordinates and size
obj.x = rect.x;
obj.y = rect.y;
obj.width = rect.width;
obj.height = rect.height;
}

AS3 MovieClip resize

I am trying to find AS3 code for a MovieClip on my stage.
My stage resizes proportionally on different screens (different size monitors), but the MC gets too big for smaller screen laptops and some parts of it get cut off. Would appreciate for any help
You could restrict any scaling, and handle the sizing yourself:
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
Have a look at the docs for the scale mode and align properties available.
Put this before anything else. This code find's the scale size from your original layout to the re-sized. (NOTE: It's best if you use this when Event.RESIZE is happening)
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
var guiSize:Rectangle = new Rectangle(0, 0, 1024, 600); //original stage size, substitute this with your orginal size
var deviceSize:Rectangle = new Rectangle(0, 0,
Math.max(stage.fullScreenWidth, stage.fullScreenHeight),
Math.min(stage.fullScreenWidth, stage.fullScreenHeight));
var appScale:Number = 1;
if ((deviceSize.width/deviceSize.height) > (guiSize.width/guiSize.height)) {
appScale = deviceSize.height / guiSize.height;
}
else {
appScale = deviceSize.width / guiSize.width;
}
Than, use appScale to scale every MovieClip/Sprite you have, e.g. _mc.scaleX = _mc.scaleY = appScale.
Using this way, every time the stage get re-sized, the right and down border are moved. That means if you want your footer to be always 50px from bottom, you should use something like :
_footer.y = stage.stageHeight - (50 * appCale);

Endless repeating scrolling background

I got a problem with AS3 and AIR. I'm working on a side-scrolling game for smartphones with a plane and I use different backgrounds as layers.
Before all other: I use GPU and only bitmaps, quality is set to low. So Performance settings are all set for smartphone use.
I putted them into a rectangle using the drawing API and move the background with a matrix:
protected var scrollingBitmap:BitmapData;
protected var canvas:Graphics;
protected var matrix:Matrix;
public function move(dx:Number, dy:Number):void {
matrix.translate(dx, dy);
if(dx != 0) matrix.tx %= scrollingBitmap.width;
if(dy != 0) matrix.ty %= scrollingBitmap.height;
drawCanvas();
}
protected function drawCanvas():void {
canvas.clear();
canvas.beginBitmapFill(scrollingBitmap, matrix, true, true);
canvas.drawRect(0, -scrollingBitmap.height, 1404, scrollingBitmap.height);
}
UPDATE2 (
Take a look at this: http://plasticsturgeon.com/2010/06/infinite-scrolling-bitmap-backgrounds-in-as3/
I used this to create my backgrounds.
With this I can simulate that my plane is flying to the right without moving the whole background and I can use a small single graphic which repeats every time (for the foreground layer).
For the background layer I use this method, too, but with a much larger graphic and I move it only with less the speed of my plane to simulate a far background.
My move-method is on an enterframe event. So I can update the background every frame with the "movement" of my plane.
)
The plane can exceed the height of the bitmaps. Everytime the bitmap comes back into the window/screen a real long lag occurs. And when the plane flies very fast, the game start to lag, too.
My first approach was to use .PNG files (but they are very big: 1-3MB size).
My next approach was to use .GIF files (much less size).
With both it's the same. So it can't be that.
I read about draw() and copyPixels() but I don't know, how I can use those to repeat the image.
UPDATE1:
protected var scrollingBitmap:BitmapData;
protected var canvas:Bitmap;
protected function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
canvas = new Bitmap(new BitmapData(1404, scrollingBitmap.height, true), "auto", true);
this.addChild(canvas);
drawCanvas();
}
public function move(dx:Number, dy:Number):void {
if(dx != 0) dx %= scrollingBitmap.width;
if(dy != 0) dy %= scrollingBitmap.height;
drawCanvas(dx, dy);
}
protected function drawCanvas(xPos:Number = 0, yPos:Number = 0):void {
canvas.bitmapData.copyPixels(scrollingBitmap, new Rectangle(0, 0, 1404, scrollingBitmap.height), new Point(xPos, yPos), scrollingBitmap);
}
I think you'd be better off with a Bitmap instead of using the graphics object with fill. copyPixels is very fast. So what you'd do is simply copyPixels over the top of whatever was there before, presuming everything is opaque. If everything is not opaque, you'll need to use your source bitmap as its own alpha data so previously drawn pixels don't show through.
Let's reframe your canvas so it is a Bitmap and not a MC. your new code will look like:
protected function drawCanvas():void {
canvas.bitmapData.copyPixels(scrollingBitmap, new Rectangle(0, 0, scrollingBitmap.width, scrollingBitmap.height), new Point(0,0), scrollingBitmap);
}
Oh, and look at that! Not only is this code faster, it's only one line of code!
EDIT: Added working code
package {
import flash.display.MovieClip;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.geom.Rectangle;
import flash.geom.Point;
public class EndlessBG extends MovieClip{
//this one stays stationary, we're getting the pixels for the right side of the pic from here
private var _source:BitmapData;
//this is the one moving to the left (the pixels for the right side are not visible except for once a cycle);
private var _movingPixels:BitmapData;
private var _canvas:Bitmap;
private var _xOffset:int = 0;
private var _rect:Rectangle = new Rectangle();;
private var _point:Point = new Point();
public function EndlessBG() {
super();
_source = new BathroomStillLife();
_canvas = new Bitmap(new BitmapData(_source.width, _source.height));
_canvas.bitmapData.draw(_source);
_canvas.x = stage.stageWidth/2 - _canvas.width/2;
_canvas.y = 5;
addChild(_canvas);
addEventListener(Event.ENTER_FRAME, gameLoop);
setGeometryDefaults();
_movingPixels = new BitmapData(_source.width, _source.height);
_movingPixels.copyPixels(_source, _rect, _point);
//turn this on to watch red pixels be drawn where the source pixels are coming in
//_source = new BitmapData(_source.width, _source.height, false, 0xFF0000);
}
private function gameLoop(e:Event):void {
_xOffset--;//where the background is moving to
if (_xOffset < -_source.width) {
_xOffset = 0;
//this doesn't seem to work correctly:
//_movingPixels.scroll(_source.width, 0);
_movingPixels = new BitmapData(_source.width, _source.height);
_movingPixels.copyPixels(_source, _rect, _point);
}
trace(_xOffset);
setGeometryDefaults();
_movingPixels.scroll(-1, 0);
//draw the moved part of the canvas
_canvas.bitmapData.copyPixels(_movingPixels, _rect, _point);
//If we stop here, we get a smear to the right
//so, get the remaining pixels directly from the source
//1) reset our rect and point to be to the right side
_rect.x = 0;
_rect.width = -_xOffset;
_point.x = _source.width + _xOffset;
//2) copy from the source
_canvas.bitmapData.copyPixels(_source, _rect, _point);
}
private function setGeometryDefaults():void {
_rect.x=0;
_rect.y=0;
_rect.width = _source.width;
_rect.height = _source.height;
_point.x = 0;
_point.y = 0;
}
}
}
Not ideal, and not polished enough yet for a blog post, but should get you started.
Edit:
Eventually I did write that blog post.
http://www.greensock.com/blitmask
This might help although not free

Flash object's size doesn't match the on screen size

I have created a small tile 64x64 for testing my tile engine and it is added like so in the loop
var grass:Grass = new Grass();
grass.x = (x * TILE_SIZE);
grass.y = (y * TILE_SIZE);
grass.width = TILE_SIZE;
grass.height = TILE_SIZE;
container.addChild(grass);
public class Grass extends MovieClip {
public function Grass() {
// constructor code
this.width = 64;
this.height = 64;
}
}
If i trace out the .width and .scale of my object they match the code as 64x64 and a scale of 1. But when i print screen the screen in the debugger and measure in Photoshop they are 94x84 and I can find out where it is going wrong?
Anything I'm missing? Thanks
Assure stage scale mode is not scaling:
import flash.display.StageAlign;
import flash.display.StageScaleMode;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
Perhaps your debugger streches your flash video to fullscreen, which would stretch your grass object out. A screenshot would help.
Is this actionscript3? where is the declaration of the Grass class? there can be some error with it