I'm trying to create a small flash-app, which needs to run as big as possible on the browser. For example regexr and Grooveshark work this way. However, if I use the File -> Publish Settings and there set the width and height 100%, it resizes to full browser, but...
When I use stageHeight and stageWidth, they don't change. I only have one frame in my animation, so should I fire a eventListener for something like "resize"?
I've just started actionscript 3 so please don't provide too advanced stuff, at least without explaining.
Thanks,
Martti Laine
You're right -- there is, in fact, a resize event to listen for. For the stage to resize properly, though, you'll want to set the stage's scaleMode and align properties.
stage.scaleMode = StageScaleMode.NO_SCALE; // Use NO_SCALE then resize your content manually to avoid stretching/pixelation
stage.align = StageAlign.TOP_LEFT; // So that (0, 0) is always in the top-left corner
stage.addEventListener(Event.RESIZE, resizeOccurred);
function resizeOccurred(e:Event):void
{
trace("New stage width: " + stage.stageWidth + "; new stage height: " + stage.stageHeight);
}
By full browser size do you actually mean fullscreen?
If yes add this listener to stage too:
stage.addEventListener(FullScreenEvent.FULL_SCREEN, resizeHandler);
Interestingly Flash doesn't consider going to fullscreen as a normal resize. And don't forget about imports on the top of your class:
import flash.events.Event;
import flash.events.FullScreenEvent;
Otherwise I agree with Cameron.
Related
Not sure if this is possible but going to ask: is there a way of being able to resize a symbol (in this case, a movie clip) in an swf file by clicking and dragging it with your cursor?
One of the things I need to do is have a rectangle within my published swf file that can be resized in height and width by clicking and dragging the sides or corner of the rectangle. Not sure at all how to do this, though. Any tutorials I could look at or maybe something that's somewhat easy to do/explain here? Right now from what little I've found on the subject, it seems like a complex thing to do.
Thanks.
There is no standard option for that, so you have to code it yourself. My suggestion:
You could add a small MovieClip, looking like an arrow, right next to your scalable item. Make this arrow horizontally draggable and whenever you drag this arrow, update the width of the scalable item according to the new position of the arrow. In this case you can scale your item horizontally, but you can use the same approach to make it vertically or diagonally scalable.
#Lodewijck - Your suggestion worked, thank you!!
This may not be the best way to write the code but it worked:
stop();
import flash.events.MouseEvent;
stage.addEventListener(MouseEvent.MOUSE_MOVE,resize1);
this.addEventListener(MouseEvent.MOUSE_DOWN, startDragging, true);
this.addEventListener(MouseEvent.MOUSE_UP, stopDragging, true);
function startDragging(e:MouseEvent) {
dragsquare.startDrag();
}
function stopDragging(e:MouseEvent) {
dragsquare.stopDrag();
}
function resize1(E:MouseEvent){
square1.width=dragsquare.x - square1.x;
square1.height=dragsquare.y - square1.y;
}
I want my application to automatically scale its size depending on the screen size. I want my application to fit any screen size automatically. I am making my application for mobile devices, how can I do this? I am fairly new at flash so please make it a bit simple!
Yes, there is no simple answer but the basics is:
stage.addEventListener(Event.RESIZE,onStageResize);
function onStageResize(e:Event):void {
// Use stage size for placing elements to their position..
// Position to left top
element1.x = 10;
element1.y = 10;
// Position to right top
element2.x = stage.stageWidth - element2.width - 10;
element2.y = 10;
// Position element to center and make it's width to scale with stage..
element3.width = stage.stageWidth - 20;
element3.x = 10;
element3.y = stage.stageHeight / 2 - element3.height / 2;
}
To scale elements place them inside on Sprite or MovieClip and scale that element like:
element.scaleX = 1.6; // scale 1 = 100% 2 = 200% etc
element.scaleY = element.scaleX;
I usually create public function "resizeElements(e:Event = null):void" for visual subclasses/components and call that from the main thread. In that function the object can resize it self.
In addition to #hardy's answer it's important to set the following variables on the stage:
// disables default 100% scaling of entire swf
stage.scaleMode = StageScaleMode.NO_SCALE;
// disables default align center
stage.align = StageAlign.TOP_LEFT;
Also, since the original question was regarding resize on launch, and this is mobile deployment it's important to call onStageResize(); once manually because the RESIZE event may not be fired initially. This would require changing:
function onStageResize(e:Event):void { ... }
to
function onStageResize(e:Event = null):void { ... }
Saying "automatically scale to screen" is too generic. The requirements this statement imposes is totally different between apps depending on what they need to do. There is no simple answer.
If your app has a main content canvas area, do you want to zoom to the content to fit the area? Do you want to keep the content the same size and show more of it? Maybe both - you could want to show more to a point, and then scale if there is still more room.
What do you want your UI to do? Dialogs could shrink/grow and remain central. Maybe you want to reflow them completely?
Do you have a slick UI? Maybe a menu with a set of buttons. Do the buttons need to be sized proportionally to the screen? What about the gaps between them? What if the screen ratio is different so if you scale them to fit they no longer work?
The point is, there isn't a simple answer. For basic layout there are UI frameworks that can assist you in placement and scaling, but you still need to decide how you want your app to behave. That totally depends on the app and what your intended design is.
What I need is take advantage of the all area of the screen, independent of user's screen proportions.
By default, Air apps scales proportionately from the inside out. This would be great if we hadn't so different screens sizes and proportions in Android.
Angry Birds is a good example of what I call of fluid layout, it always scales/zooms the three layers(front, game and background layer) accordinly.
My app is mostly a inteface based game, the user must see some info and click on some buttons. I think I could base my scale primarily in the user screen's width, and use a scroll if needed. The problem is how do that.
Fluid / liquid / responsive layouts would likely imply a layout manager of some kind.
This functionality is built in to Flex.
Per Flash, and more specifically to what you've noted per requirements it sounds like some basic scaling and positioning is what you desire.
Layers
As you've noted, different layers will have different requirements per scaling:
background
game play
interface / controls
Background and game play might be a single layer; however, you may want different constraints on the foreground user controls for readability and interaction.
Setting up the stage
If you want to control scaling, you should set:
import flash.display.StageAlign;
import flash.display.StageScaleMode;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
This also assists with orientation change of mobile devices swapping between portrait and landscape.
Browsers can be resized; so, you need to listen for resize events:
stage.addEventListener(Event.RESIZE, resizeHandler);
stage.dispatchEvent(new Event(Event.RESIZE));
function resizeHandler(event:Event=null):void
{
/* scale code ... */
}
Positioning
Top and left positioning are always easy, because top-left is 0x0 coordinate. Right and bottom require subtracting a DisplayObject width from stage.
Right align example:
mc.x = stage.stageWidth - mc.width;
Bottom align example:
mc.y = stage.stageHeight - mc.height;
Keeping something in the center of the stage:
mc.x = (stage.stageWidth * 0.5) - (mc.width * 0.5);
mc.y = (stage.stageHeight * 0.5) - (mc.height * 0.5);
Scaling
You need to determine what your constraint is to avoid blank / empty regions on the stage.
This can be implemented using a ratio variable:
var ratio:Number = 1.0;
Proportional scaling:
ratio = stage.stageWidth / gameMovieClip.width;
gameMovieClip.scaleX = ratio;
gameMovieClip.scaleY = ratio;
Stretch display object to fit stage:
gameMovieClip.scaleX = stage.stageWidth / gameMovieClip.width;
gameMovieClip.scaleY = stage.stageHeight / gameMovieClip.height;
Best fit algorithms require fitting the minimum constraint of your display object within a bounds. There are libraries that can assist with this, such as Greensock auto fit area.
Virtual Cameras
Virtual cameras have been popular in Flash. The concept is that you design your view then pan and zoom a camera to show a specific region.
O'Reilly ActionScript for Non-Coders
Example 1
Example 2
Example 3
Virtual camera FLA example:
http://bryanheisey.com/blog/wp-content/uploads/2009/02/vcam_as3.fla
Virtual camera example:
http://www.fluidanims.com/FAelite/phpBB3/viewtopic.php?f=43&t=3369
http://www.neoseeker.com/forums/87/t647746-cam-virtual-cam-for-flash-mx-lower-level-intermediate/
http://www.flashkit.com/movies/Components/Flash_V--_redesig-10378/index.php
Google "Flash virtual camera" or "Flash v-cam" for examples.
I'm new to AS3 and I'm doing some custom video player video project for AIR. While I was studying the simple examples (non-StageVideo) on how to play videos, I've encountered a unique situation where I got an awesome auto-scaling (stretch-to-fit) to window behavior from Flash.
Whenever I set the SWF directive's width and height equal to the width and height of the flash.media.Video object I'm creating. It does the auto-scaling, stretch-to-fit, resizable behavior. Like so:
// SWF directive placed before the class declaration of the main class
[SWF( width="1024", height="576", backgroundColor="000000", visible="true" )]
// somewhere in my initialization
myvid = new Video();
with( myvid )
{
x = 0;
y = 0;
width = 1024; // if I set this wxh equal to wxh in the SWF directive it auto-scales!
height = 576;
}
myvid.attachNetStream( myns );
addChild( myvid ); // must come after instancing of video and netstream, and attach to make the auto-scale work
myvid.play( "somevideo.flv" );
Even if I set the width to 16 and height to 9 on both it scales and fits perfectly on the size of my window. Can some explain me this behavior? None of what I read in the documentation mentioned this.
Don't get me wrong, I like this behavior! :) It made things easier for me. But code-wise I need to understand why is this happening as the code I set had nothing to do with auto-scaling.
Also, what the heck are directives for? Don't they just have pure ActionScript 3 equivalent? They look hackish to me.
I think the behavior you're describing is caused by the scale parameter in the HTML embed of the Flash. Generally this defaults to showAll, scaling the Flash up to fit the container.
There are two different sizes: the size of the container (the block in the HTML page) and the size of the Flash content (what you specify in the SWF tag). The scale mode decides the behavior when these sizes don't match. You can control this behavior either by tweaking that embed parameter, or from AS3 directly using stage.scaleMode:
import flash.display.StageScaleMode;
// scale the content to fit the container, maintaing aspect ratio
stage.scaleMode = StageScaleMode.SHOW_ALL;
// disable scaling
stage.scaleMode = StageScaleMode.NO_SCALE;
If you want to use the scale mode to your advantage, I would set the width of your Video to match the stage dimensions like so:
myvid.width = stage.stageWidth;
myvid.height = stage.stageHeight;
This way you avoid having to repeat the SWF width and height.
The directives mostly specify some metadata or instructions for the compiler. The SWF tag in particular specifies the info in the SWF header, such as desired width, height, framerate. Mostly these are just some suggestions to the player + container about how the file should be displayed. Some of them can be changed in code (stage.frameRate = 50;). Another metatag is Embed, which will bundle some assets into the SWF (particularly handy if you want to embed some binary data).
Is there a way to prevent the automatic change of the height property of a DisplayObject? It automatically resizes to match content, though my swf file is 32 pixels height. The code below can show prove of this, first frame enemy.height is 32 but later is 27.5, and this messes up my script.
getRect() and getBounds() return exactly the same. Also, I want to know why in the first frame it shows the correct height and in the second it changes, it should show 27.5 from the beginning.
package {
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite {
private var enemy:Sprite;
[Embed(source = '../lib/enemy.swf')] private var swf:Class;
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function update(e:Event):void {
trace(enemy.height);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
enemy = new swf();
addChild(enemy);
addEventListener(Event.ENTER_FRAME, update);
}
}
}
This has to do with the fact that you're instantiating a whole SWF, and 1 frame has to pass for it to be synced to the Main swf. What I would do is export the symbol in the .fla, then use the "embed symbol" syntax in Flex:
[Embed(source='enemy.swf#Symbol1')]
private var swf:Class;
In this case, the height will be consistent even in the first ENTER_FRAME. If it's not the height you want, you can use the invisible shape to set the bounds.
A "hacky" solution might be to add a shape to the enemy that has the max size you want, then set it to be invisible. I have created hit boxes for objects that way and it worked quite well.
One way would be to add it when creating the object in the Flash IDE. Just draw it and position it as you want the shape to be, then give it an instance name, like "sizeHolder". After you create the enemy you would then call
enemy.sizeHolder.visible = false;
In the Flash IDE you could place it on another timeline, then make that timeline invisible and lock it, so it wouldn't get in your way when editing the actual object.
The other way would be to add it by code. Draw the object in another DisplayObject, set it to invisible and then addChild it to enemy.
The enemy sprite animation sequence
will vary in height.This is part of
the animation process. Hence the
actual height per frame will vary
based on bounding box of the sprite.
As you very well observed this is the
default behavior.
The ways:
The One you are presently following storing height and using for calculations.(better)
As EyeSeeEm suggested if i understood him correctly having an invisible height sprite background with proper centering of the movie clip center point and centering of the sprite in each frame to be contained in the invisible height sprite bounds.
You will often find that you will come across features in action script not working the way you want it to.Whats important is that you adapt the coding to facilitate the solution . It is not hack y or inefficient when and coding/method allows for easily making further changes/extensions.
P.S:
This would depend on situation but personally i would rather the height be dynamic according to the sprite animation instance so any hits to the enemy just nearly over its head by projectiles doesn't actually kill the enemy.
Try
import flash.display.StageAlign;
import flash.display.StageScaleMode;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;