How to make a fluid/liquid Air application using Flash? - actionscript-3

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.

Related

Preffered viewPort to dealing with textButton libgdx

i work with a new game , i have create 2 camera one camera for real world and another (GUI) camera for a static resolution (800 x 480)
private void init () {
camera = new OrthographicCamera(16,9);
camera.position.set(0, 0, 0);
camera.update();
cameraGUI = new OrthographicCamera(800,480);
cameraGUI.position.set(0, 0, 0);
cameraGUI.update();
And i want to use a textButton in my game , so i've create a new stage using a new fitViewPort
fitViewPort=new FitViewport(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
gameController.stage=new Stage(fitViewPort);
then i create my textButtons using my bitmap font and i try it on the Desktop , and it's great
desktop
but when i try another device , the position is not the same
Tablet
then i think for using the cameraGui Width and height for my view port , the font is very bad stretched
any help please :(
Don't create a special camera for GUI, because viewport already has a camera.
Make your viewport width and height fixed, in your case:
fitViewPort = new FitViewport(800, 480);
gameController.stage = new Stage(fitViewPort);
And then just add actors to stage and draw it just by calling method
gameController.stage.draw();
Note: Remember to add gameController.stage.getViewport().update(width, height); in your resize method.
Edit: Using small fixed viewport (800x480 is small) will cause scaling, that is why the font is stretched. For example if you run a 800x480 layout on 1920x1080 display it will be scaled by 225%.
What you can do is generate a font with big size and the set scale to its data fe. bitmapFont20.getData().setScale(0.5F); (in this case font is generated by FreeTypeFontGenerator with size 40). Using this trick you will be able to get a great results. The proof is below. It is viewport of 640x360F * (float) Gdx.graphics.getHeight() / (float) Gdx.graphics.getWidth() scaled to 1920x1080. Font is generated with size 72 and then data scale is set to 0.5F
Here is the same text, but without modified data scale.

How to have an application to automatically scale when launched?

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.

Top-down game camera movement

I'm developing a top-down view game, and I've got a problem with the camera.
Currently camera simply follows the player entity - it seems fine to me, but people want another camera.
I'm using Starling, and StarlingPunk, but it shouldn't make much difference, its more theoretical question.
Camera works like this:
public function centerOnEntity(target:SPEntity):void
{
var newCameraX:Number = (target.x + target.width / 2) - SP.width / 2;
var newCameraY:Number = (target.y + target.height / 2) - SP.height / 2;
SP.camera.setPosition(newCameraX, newCameraY);
}
And basically, every frame, camera is centered on the user.
Following image will demonstrate the problem:
As you can see, I've got rectangular levels, and if level is small, or user is near to the level bounds a background image is displayed.
So, what kind of camera do I need?
I need a camera, that will show maximum level space, and minimum background image.
How can I achieve that?
Help would be appreciated!

Understand LibGDX Coordinate system and drawing sprites

So I am super stoked to start using LibGDX for my first android title for OUYA and PC, but I am running into some snags with LibGDX. (All of my questions can be answered by looking at source, but I am really trying to understand the design choices as well).
To start with, the coordinate system. I created a project using the Project Setup jar, and it creates an OrthographicCamera like so
camera = new OrthographicCamera(1, h/w);
From my reading, I understand that LibGdx uses bottom left corner for 0,0 and yUp. Fine.
I see that it is pretty easy to change to y down if I want to, but I am not understanding the next bit of code that was created.
For the default sprite that gets created the position is set like so.
logoSprite.setOrigin(logoSprite.getWidth()/2, logoSprite.getHeight()/2);
logoSprite.setPosition(-logoSprite.getWidth()/2, -logoSprite.getHeight()/2);
When I run this basic program, I see the logo image I have added is centered on the screen. What I am trying to understand is why the values are negative in set position, and why is it using the sprite width and height instead of the graphics w and h of the view port? If I change to the screen width and height, then the image is drawn in some odd position in the lower right hand side of the screen.
My next question is sprite.setSize vs sprite.setScale. Why is the difference between the two? (They appear to do the same thing, except setScale leaves getWidth and getHeight unchanged).
Since my game will be using a 2D camera heavily for panning, zooming and rotation, I am trying to understand as much as I can about the libgdx framework before I start writing any code.
As a side note, I have a game development and math background and I have made several 2D and 3D games using XNA. I am finding LibGdx a bit frustrating as it does not abstract away OpenGL as much as I was expecting it to, and so far the 2D drawing I have been experimenting with seems to be more confusing than it should be!
I also wanted to note that I am planning to use spine for my animations. Should that change my choice to use y-up or y-down?
If you want to draw a sprite in center of screen, do this in your create method
logosprite.setposition(scrw/2-logosprite.getwidth()/2,scrh/2-logosprite.getheight/2);
here scrw is your viewport's width,
and scrh is your viewport's height,
this way your sprite will be in center of screen
sprite.setsize is used for setting size of the sprite and sprite.setscale is used when we scale a large/small texture so that its quality remains good in all devices(hdpi.mdpi,xhdpi,ldpi)..
no need to worry if you are using spine it works smoothly in libgdx..
You can use just this code if possible
logoSprite.setPosition(Gdx.graphics.getWidth()/2 - image.getWidth()/2,
Gdx.graphics.getHeight()/2 - image.getHeight()/2);
To center the sprite into the middle of the screen Where "image" is the Texture you have loaded/declared initially.
As for why it is coming in a odd position is due to the fact that you are using a camera.
Which changes the view a lot just go through the documentations of libgdx about camera here
In my case, I needed to set position of camera and then call update() method.
Then never forget camera's (0,0) is its center. Everything is being placed that way. My camera code:
private void cameralariUpdateEt() {
cameraGame.position.set(cameraGame.viewportWidth * 0.5f,
cameraGame.viewportHeight * 0.5f, 0);
cameraGame.update();
cameraScore.position.set(cameraScore.viewportWidth * 0.5f,
cameraScore.viewportHeight * 0.5f, 0);
cameraScore.update();
}
Call this method from inside render();
Step 1: Set the sprite origin to the position you would like it to rotate around.
// camera center point is (c.x, c.y)
logoSprite.setOrigin(c.x, c.y);
Step 2: make sure to set your sprite center to origin
logoSprite.setOriginCenter();
Step 3: Rotate your sprite
logoSprite.setRotation(Angle);
Step 4: Set the sprite position, [subtract half the sprites width and height to center the sprite]
logoSprite.setPosition(c.x - logoSprite.getWidth() / 2, c.y - logoSprite.getHeight() / 2)

Can some one explain to me why the behavior of this ActionScript code is auto scale?

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).