SHOW_ALL gets too big instead of scaling - actionscript-3

I want to run a two screen application with AIR on my Macbook Pro with Retina display.
On my left screen (the retina) there is kind of a console, with which you select a movie, on the right screen, there is the selected movie playing.
As usually, I use the StageScaleMode.SHOW_ALL to bring it nicely to fullscreen. But this time, it gets scaled way too big. Maybe 100 times too big. I see only a small top left corner of the movie. It only shows the correct size if I choose StageScaleMode.NO_SCALE;
Has anyone a guess why its like this?
here is the portion of the code, where I bring up the two windows and try to show it fullscreen.
public function setToFullscreen(e:Event):void {
startTimer.stop();
startTimer.removeEventListener("timer", setToFullscreen);
windowBig = new NativeWindow(new NativeWindowInitOptions());
windowBig.width = 1870;
windowBig.height = 468;
windowBig.stage.displayState = StageDisplayState.FULL_SCREEN;
windowBig.stage.scaleMode = StageScaleMode.SHOW_ALL;
windowBig.stage.align = StageAlign.TOP_LEFT;
windowBig.title = "Second Screen Window";
windowSmall = stage.nativeWindow;
windowSmall.width = 1280;
windowSmall.height = 1024;
windowSmall.stage.scaleMode = StageScaleMode.NO_SCALE;
windowSmall.stage.align = StageAlign.TOP_LEFT;
windowSmall.title = "First Screen Window";
ScreenManager.openWindowFullScreenOn(windowBig,2);
loader.load();
}
Thank you for your help!

Like OP said it is not possible automatically with SHOW_ALL, but you can do it manually (here it's not exactly as SHOW_ALL: I'm only fitting content to window height, so it works for a window aspect ratio equal or wider than the content ratio, else content will be cropped):
newWindow.addEventListener(Event.RESIZE, onResize);
function onResize(e:Event):void
{
content.height = newWindow.stage.stageHeight; // fit to height
content.scaleX = content.scaleY; // keep width ratio
// Extra: equivalent of StageAlign.TOP => centers horizontally
// (assuming a content registration point at top-left)
var contentRatio = 4/3; // in case content is wider than necessary, e.g. wide background
content.x = newWindow.stage.stageWidth/2 - (content.height * contentRatio )/2;
}

Related

Pixi.js - Unable to set sprite width to full width of canvas

Ultimately I want to have a canvas that fills the entire viewport width of the browser and have an image on the canvas fill the entire width of that canvas. I'm taking advantage of pixi.js's displacement filter so that I can create a pseudo 3d effect using a depth map underneath it. The code I'm currently using is
let app = new PIXI.Application();
var w = window.innerWidth;
var h = w / ratio;
app.view.style.width = w + 'px';
app.view.style.height = h + 'px';
document.body.appendChild(app.view);
let img = new PIXI.Sprite.from("images/horses.png");
img.width = w;
img.height = h;
app.stage.addChild(img);
depthMap = new PIXI.Sprite.from("images/horses-depth.png");
depthMap.renderable = false;
depthMap.width = img.width;
depthMap.height = img.height;
img.addChild(depthMap);
app.stage.addChild(depthMap);
displacementFilter = new PIXI.filters.DisplacementFilter(depthMap, 0);
app.stage.filters = [displacementFilter];
Here's a screenshot of it in action.
I even tried manually setting the width to the viewport pixel width on the canvas and the sprite to the actual pixel width of the viewport width and it still wasn't the right size. Manually setting the width for the viewport and sprite to the exact same number also doesn't work; the sprite is inexplicably smaller than the canvas.
I tried to look at the documentation of the sprite class and see if there is something unusual about how sprites handle widths but I couldn't find anything https://pixijs.download/dev/docs/PIXI.Sprite.html
How can I create a pixi.js sprite that fills the entire width of the canvas in order to make both the canvas and the sprite fill the entire viewport width?
pixijs.download
PixiJS API Documentation
Documentation for PixiJS library

How to create a resolution "Independent" implementation of Stage for scene2d ui of LIBGDX

I have been trying to create a "main menu" screen with a single button.This button however, is 'unclickable' if a Viewport is set for the stage.If the viewport is not set it becomes clickable.The problem with second approach is however that the images "change size" depending on the resolution of devices.So they become smaller on higher resolution devices and vice versa.
Here is the code for your reference:
mainMenu(Game mainGame){
camera = new OrthographicCamera();
menuCam = new OrthographicCamera();
allVariables.Graphics_viewport_height = (allVariables.Graphics_viewport_width*Gdx.graphics.getHeight())/Gdx.graphics.getWidth();
camera.setToOrtho(false, allVariables.Graphics_viewport_width, allVariables.Graphics_viewport_height);
camera.update();
menuCam.setToOrtho(false,allVariables.Graphics_viewport_width,allVariables.Graphics_viewport_height);
menuCam.update();
maingame = mainGame;
batch = new SpriteBatch();
stage = new Stage();
stage.setViewport(new StretchViewport(allVariables.Graphics_viewport_width,allVariables.Graphics_viewport_height));
stage.getViewport().setCamera(menuCam);
table = new Table();
ImageButton.ImageButtonStyle playButtonStyle = new ImageButton.ImageButtonStyle();
playButtonStyle.imageDown = AllAssets.instance.skin.getDrawable("play_up");
playButtonStyle.imageUp = AllAssets.instance.skin.getDrawable("play_dn");
playButtonStyle.pressedOffsetY = 10;
playButtonStyle.pressedOffsetX = 10;
play = new ImageButton(playButtonStyle);
table.setFillParent(true);
table.align(Align.top);
table.add(play).minSize(100, 200);
table.debug();
stage.addActor(table);
Gdx.input.setInputProcessor(stage);}
The resize method :
public void resize(int width, int height) {
stage.getViewport().update(allVariables.Graphics_viewport_width,allVariables.Graphics_viewport_height,true);
}
What should be done to make it resolution independent so that the button works on different resolutions with same relative size that is not dependent on actual pixels.
So the answer to this question lies in the fact that there are Two specific size aspects of Viewports in Libgdx.The first is the "part of your game world" you want to show and the second is "the part of your screen" onto which you want to show your world(rather part of your world).
To tell Libgdx the what part of the world you wish to show you can use the constructor of the viewports.Like so:
new StretchViewport(worldViewportwidth,worldViewportheight)
Now in order to tell Libgdx about which part of your screen (partial part of the screen,full screen,et al) use the update method on the viewport:
public void resize(int width, int height) {
stage.getViewport().update(width,height,true);
}
Now, the stage should be able to accept input (if everything else is also correct) with the stage properly visible on different devices

used preferred back buffer height and width intersection is not working properly

i wanted to develop a game which can support all types of display sizes,
so i am using following code to multiscale.
graphics.PreferredBackBufferHeight = 768;
graphics.PreferredBackBufferWidth = 1024;
shootrect = new Rectangle( 900,650 , 100, 100);
touchrect = new Rectangle(mouse.X, mouse.Y, 0, 0);
if (mouse.LeftButton == ButtonState.Pressed && !jump && shootrect.Intersects(touchrect))
{
jump = true;
}
using this code i am trying to intersect the mouse coordinates with shootrect (which is shoot button for make player to jump) if i touch in that rect intersection is working but somewhere else in the same width and height touch is working
when i remove graphics.PreferredBackBufferHeight = 768;
graphics.PreferredBackBufferWidth = 1024; those lines from code intersection is working fine but my scaling is not proper for other size of screens
You need to scale your logic by hand (rectangles for instance) if you use those magic numbers creating them. I suggest create those relative to the screen width and height.
actually graphics.PreferredBackBufferHeight = 768;
graphics.PreferredBackBufferWidth = 1024; because of this rectangle intersection is working properly if set my screens resolution to 1024 x768 then it works well but my resoolution is 1980x1020 so its not working

Loop an image in Flash

I want to have a scene where an image which is 5000 pixels high is moving up 5 pixels each frame-refresh. When the image is all up, I'd like to see the top of the image connected to the bottom of the image. This should be done untill the level is 'done'. How can I 'loop' such an Image?
You can create a copy of that image which you keep hidden/above and the trick is to update the position and loop accordingly so when one image goes bellow the screen it goes back on top and repeats.
Here's a basic snippet to illustrate the idea using the DisplayObject class and the scrollRect property:
//ignore this, you have your content already
var dummyContent:BitmapData = new BitmapData(100,100,false);
dummyContent.perlinNoise(10,10,8,12,true,true);
//important stuff starts here
var container:Sprite = addChild(new Sprite()) as Sprite;//make a container
container.scrollRect = new Rectangle(0,0,dummyContent.width,dummyContent.height);//set a scrollRect/'mask'
var part1:DisplayObject = container.addChild(new Bitmap(dummyContent));//add two copies
var part2:DisplayObject = container.addChild(new Bitmap(dummyContent));//of the same content
part2.y -= part2.height;//set the 2nd at the top of the 1st
addEventListener(Event.ENTER_FRAME,update);
function update(e:Event):void{
//move both
part1.y += 5;
part2.y += 5;
//check if any reach the bottom so they can be moved back up
if(part1.y >= part1.height) part1.y = -part1.height;
if(part2.y >= part2.height) part2.y = -part2.height;
//the above can also be nicely placed in a loop if you plan on using more seamless looping clips/images
}
Obviously you will have different content, but the principle is the same.
If you're working with images, you can simply use BitmapData's copyPixels method:
var s:int = 5;//scroll speed
//make some content
var w:int = 100;
var h:int = 100;
var dummyContent:BitmapData = new BitmapData(w,h,false);
dummyContent.perlinNoise(10,10,8,12,true,true);
//prepare for stiching
var renderPos:Point = new Point();//position to render the current image to
var prenderPos:Point = new Point();//position to render the previous image (the 'hidden' copy above)
var render:BitmapData = new BitmapData(w,h,false);//create a bitmap data instance to render updated pixels int
addChild(new Bitmap(render));//and add it to the stage
addEventListener(Event.ENTER_FRAME,update);
function update(e:Event):void{
renderPos.y = (renderPos.y+s)%h;//update the scroll position for the 1st part, % is used to loop back to 0 when the position gets to the content height
prenderPos.y = renderPos.y - h;//update the scroll position for the 2nd part (above)
render.lock();//freeze pixel updates
render.copyPixels(dummyContent,dummyContent.rect,renderPos);//copy pixels from the scroll position to the bottom
render.copyPixels(dummyContent,dummyContent.rect,prenderPos);//copy pixels from the top to the scroll position
render.unlock();//unfreeze/update ALL THE PIXELS
}
You can try to use a Rectangle object which changes height (height-scrollPosition) so you potentially access less pixels each time or you can manually work out single for loops using BitmapData's getVector method, but that's something to look into if performance is actually an issue for such a simple task and it's worth checking what's faster ( copy full bitmap rect vs copy partial bitmap rect vs manually copy values using vector )
Be warned, Flash cannot load an image greater than 16,769,025 pixels (or 4095x4095). The height of 5000 pixels will work as long as the width is not greater than 3353.
That said, I'd loop the image by keeping two copies of the image onstage, move both at the same time with a parent object, and reset to origin once your loop point is met.
Consider the following stage setup:
Stage ¬
0: MainTimeline:MovieClip ¬
0: Container:MovieClip ¬
0: img1:Bitmap
1: img2:Bitmap
Now moving container up, you'd just need to check that the looping second image reaches the origin point of the first image.
function onEnterFrame(e:Event):void {
Container.y = Container.y - 5;
if (Container.y < -5000) {
Container.y = -5;
}
}

AIR - set size of NativeWindow to include system chrome

How do you find out the size of the system chrome so that I can specify the window size to achieve the stage size I want?
If my main window is set at 800 x 600 (stage), and I create a second window as below, it will be smaller.
public function Main():void
{
var windowOptions:NativeWindowInitOptions = new NativeWindowInitOptions();
windowOptions.systemChrome = NativeWindowSystemChrome.STANDARD;
windowOptions.type = NativeWindowType.NORMAL;
var newWindow:NativeWindow = new NativeWindow( windowOptions );
newWindow.width = 800;
newWindow.height = 600;
newWindow.stage.scaleMode = StageScaleMode.NO_SCALE;
newWindow.stage.align = StageAlign.TOP_LEFT;
newWindow.activate();
}
I assume you increase both newWindow.width = 800; and newWindow.height = 600;to account for the chrome, but how do you find this value?
you can calculate the size of the chrome by substracting the windows size (that include the chrome) with the inner size (that exclude the chrome).
From the width help of NativeWindows :
The dimensions reported for a native window include any system window
chrome that is displayed. The width of the usable display area inside
a window is available from the Stage.stageWidth property.
So the inner size can be obtained with stage object ( stage.stageWidth and stage.stageHeight: )
hence :
var chromeWidth=newWindow.width-newWindow.stage.stageWidth;
var chromeHeight=newWindow.height-newWindow.stage.stageHeight;
When creating ActionScript projects with NO_SCALE the stage.stageHeight and stage.stageWidth cannot be used to calculate chrome in the main application window as they do not resize to conform to the inner width. You must reference the main window stage.
To find the main windows inner stage height and width you can use the stage.nativeWindow.stage references stageHeight and stageWidth properties which gives inner width.
e.g. for a 1280x720 desired inner size:
// width stage.nativeWindow.width = 1280 + (stage.nativeWindow.width -
stage.nativeWindow.stage.stageWidth);
// height stage.nativeWindow.height = 720 + (stage.nativeWindow.height
- stage.nativeWindow.stage.stageHeight);
For reference, as I feel the other answers aren't clear enough. To set a new window to the desired dimensions:
// first set the desired window dimensions to set the (smaller) stage dimensions:
newWindow.width = 1024;
newWindow.height = 768;
// then reset the window dimensions and add chrome dimensions:
newWindow.width = 1024 + (1024 - newWindow.stage.stageWidth);
newWindow.height = 768 + (768 - newWindow.stage.stageHeight);