DaVikingCode / Citrus-Engine

Modern AS3 Game Engine
http://citrusengine.com/
Other
549 stars 231 forks source link

Multi res / easy viewport managment, for next release (?) #142

Closed gsynuh closed 10 years ago

gsynuh commented 10 years ago

ideas:

gsynuh commented 10 years ago

Hi ! I'ved made some changes to the example, if you want to try those on your devices.

Again all the code here would be hidden in StarlingCitrusEngine, we would only define base dimensions and viewportMode. I've added a ViewportMode class to list modes (different from ScaleMode.)

so far public static const LETTERBOX:String = "LETTERBOX"; public static const NO_SCALE:String = "NO_SCALE"; public static const FULLSCREEN:String = "FULLSCREEN"; public static const MANUAL:String = "MANUAL";

letterbox for letterbox, no scale for 100 centered view, manual does basically what we had up to now - the viewport = flash stage.

Now the important bit , fullscreen. You have to try that for me (are the resolutions ok and so on)

Because what happens now, is I use the RectangleFit SHOW_ALL output - which gives us the letterbox rectangle. I get the viewport width/height ratio to the base dimensions. Then I set the viewport to the screen size instead of keeping it to the letterbox size.

Effectively this should be the same as extending the stage to hide the black borders : now of course, I fix the stage size to keep the aspect ratio otherwise we've got a distorted stage.

Now I'm not sure if that's what you'd expect anyway, your advice is really welcome - I've just implemented that idea of expanding the viewport and stage over the black borders... which is different from having everything the same size as the screen.

We need to put ui elements maybe to see what would happen?

gsynuh commented 10 years ago

I've just added a citrus sprite with a quad that has the same dimensions as the base dimensions. This helps us visualize how the base game dimensions fits in the new screen.

(apparently everything is fine - and it seems to replace the camera.zoomFit technique correctly which is great news!! now perhaps the viewport mode names could be re-considered, you decide. Aymeric, using MANUAL will not change the way we did things up to now so if we do the change now, current projects should stay the same as long as we put ourselves in manual.)

gsynuh commented 10 years ago

I moved most of the test code to CE now.

to set up a project with automatic viewport setup, you just need this :

_baseWidth = 480; _baseHeigth = 320; _viewportMode = ViewportMode.LETTERBOX;

in the StarlingCitrusEngine constructor . Of course I'm using LETTERBOX a lot. But you could use NO_SCALE, or FULLSCREEN ... these three of course require base dimensions logically.

the default is MANUAL, which should (as far as I've tested now) behave the same as everything did prior to those updates.

in MANUAL mode, if you define in that constructor a rectangle for the viewport :

_viewport = new Rectangle(100,100,100,100);

it should be using that viewport to set starling up (or just send that rectangle to setUpStarling. this works only in MANUAL and that is to be expected.

Anyway, I think that's a bit of a step forward, I'm just asking you to test on your screens, maybe give me feedback on usage / names ... I also fixed StarlingArt to position the debug views correctly on stage - test NO_SCALE for example for that.

edit1 :also, some vars could be moved , or we could leave access to them (screen rectangle and base rectangle maybe? and sorry if some things are not optimized, this is really something I'm doing so we can go forward into the conversation, not really caring about how it looks - though I still don't like sending out code I'm not proud of but so far I think I've done it plenty of times anyway so nevermind

edit2: there are two ways to fullscreen. The fullscreen as it is now, which is using starling to scale up or down - what we were going for from the very beginning, and the fullscreen at a 1:1 ration with the stage, looks like the manual mode, although in manual mode and on resize, the viewport and stage are not updated - we can't leave out on resize just because we're not going to use it. so I've got a problem thinking of names for that way to fullscreen to separate it from MANUAL. FULLSCREEN_NOSCALE? that's ugly. FIT ? EXPAND? taking any suggestions !

alamboley commented 10 years ago

Hey, what a nice work!!

I will need time to test everything... ;)

However if I remove the camera, and try all the viewport modes, I'm not able to see the tiles at 0, 0 like they should be rendered, it's start at the center. Any thought?

gsynuh commented 10 years ago

when I remove the camera completely everything starts from 0,0... What I don't understand is they go down like steps

you might have everything centered if you left the camera code in the states' update that updates camera offset to be the center which of course puts the 0,0 at the center. In fact when I tried I forgot about those lines and I did get everything centered - except for the base quad which stays always at 0,0 because of his parallaxX/Y being 0.

Is what I see (the tiles going down in steps) normal? is this part of the map?

--- I'm thinking anyway that camera should be setup with states automatically, with enabled = false (no update), offset to the center of the screen (the most used setting I think) and no bounds.

so then we'd just have to enable it, change selectively whatever we want. - writing setup is sometimes a pain when all we went is a camera centered on a simple target.

alamboley commented 10 years ago

Wow got it, it was in the update method ;)

Yes this is the correct behavior, open the tmx if you wanna have a look.

gsynuh commented 10 years ago

good, I was really worried !! (just installed a tile editor, the older version I found of tiled just wouldn't run at all so I never tried again for months)

mcapraro commented 10 years ago

this is looking great guys!

ok, so dumb question: to implement a HUD, has that changed now? there doesnt seem to be any built-in HUD container in Citrus, and getting the right x and y seems unclear to me. I've tried creating shapes and using add() but none appear on screen because they are rendering in the coordinate space of the actual tiled map.

gsynuh commented 10 years ago

Hi @mcapraro ,

Well it did change because previously you would need to scale your ui with your scale factor manually (I never had to do that, that's what I got from @alamboley)

Now, since the stage is already being scaled, the camera trick is no longer needed but anything added via addChild() for example would have the corrected scale needed for the current resolution.

see : https://github.com/alamboley/Citrus-Engine-Examples/commit/c3e1874a4055ffb7103f82c7368ae1f2cb18e0f9

I've added a function that sets up a grid of elements (tiles) and you could do the same for any kind of ui (hud or menus...) they are positioned dynamically - this is necessary anyway. In LETTERBOX mode, the stage width/height are the same as the base width and height, so if you want something on bottom right, you'd put it at baseWidth,baseHeight. to be sure I'm using Starling.current.stage.stageWidth/stageHeight. which are the same in LETTERBOX but not in FULLSCREEN which should be the most popular mode I assume, since in this mode, we expand either vertically or horizontally the base dimensions to fit the stage so the dimensions are no longer the same. Doesn't really matter however since we can get those new dimensions the same way, and position things dynamically as I did here. so the major benefit here is you don't have to scale up or down if you are going to put your ui outside of the camera/game world !

So @alamboley and @mcapraro , if any of you can just try running LETTERBOX/FULLSCREEN on your device and check that the "ui elements - tiles" are of the correct scale as you would expect - I see that they are, but all I want is feedback , if you think this would be fine with your workflow, if it makes things easier and everything.

I'm using the really sexy alignPivot() function on elements. with this, you could easily have your own layout system for your ui. This depends on you of course.

I hope, @mcapraro , that this little update will clear up your question on getting the right x/y. Any UI should be out of the game world, so out of the camera.

However, if you do want your ui to be CitrusSprite for some reason, set parallaxX and parallaxY to 0, the CitrusSprite will now be as if it was infinitely far away - so it won't move with the camera and if set at 0,0 in the game coordinates, it will be at 0,0 on screen which could be like having a ui made of citrus objects - put them in front of everything using the group parameter. Not a big fan of having ui elements be CitrusSprite and everything but it can be done this way as well and its actually not a problem

edit: I thought , StarlingStates could have an overlay property which would simply be added on to of the state, and get disposed (or just removeChildren and removeFromParent) automatically on state destroy for easier management. to destroy your custom ui sprites you would just listen to the removed event that would be called as the starling state changes because the overlay would remove its children. in the listener for that event you would simply 'unlink' listeners from their respective dispatchers and destroy whatever you have to destroy. doesn't feel like a CE way of doing things though. but its one that would work without too much trouble + I don't know what a universal ui layout manager would be like for everyone to be happy anyway.

alamboley commented 10 years ago

Hey,

That's perfect for the UI!

The LETTERBOX works perfectly!

The Fullscreen:

I tried the no scale mode, not sure if it would be used by someone one day, or maybe I missed the point.

Concerning the StarlingState overlay: when a Starling Sprite is removed and disposed, all its children are removed/disposed too! However I can't remember if the listeners are removed also. Personally I dispose everything myself... If you think that creating a Starling Sprite "uiSpriteElements" for the UI/HUD would help people to understand they should addChild things, it sounds great to me!

When this 3.1.8 release will be out I will try to refocus on the wiki/documentation...

gsynuh commented 10 years ago

Hi Aymeric !

Its ok to do your Ui in CitrusSprite, but its no use to build it in flash cause it won't position itself. But maybe we could have a specific class for that, along with a function that helps position the sprite automatically at any position that I used in that example + a center position so you wouldn't have to worry about that... something like align("right","bottom"); (maybe using HAlign/VAlign from starling rather than strings) would automatically set up its pivot point at its right/bottom + put the sprite at stageWidth stageHeight. for any special position this would have to be extended that's all but I'm sure the most usefull positions for a ui are already represented ? I'll think about it, but in what package should that class be? (I guess I can do that fast and just update the example with it)

for the documentation I'll help, I'll let you decide on the navigation structure of the wiki, but send me links to the pages you'd rather have me draft out and when done I'll tell you and you can validate the whole thing

Good day :D

alamboley commented 10 years ago

At 1024 x 768, I can see only 5 tiles. 7.5 for 2048 x 1536, however I need to test on my iPad Retina to confirm.

I'm getting trouble adding "new VirtualJoystick("gre");" to the StarlingState... normally this line would add the VirtualJoystick, however here it deso'nt appear on screen! Does anything changed?

Yes, you would have to remove manually listeners, signals, etc. Right, I think the most useful positions are already there. What could be nice later is to add UI layout: set up 5 Elements horizontally with the same space between starting at 0 and taking until stage.stageWidth, etc. Using HAlign/VAlign from Starling is perfect I think. Concerning the package, we already have a ui/starling package ;)

Concerning documentation, I'm sure that there is already tons of thing you did that you want to add to the wiki :D http://wiki.starling-framework.org/citrus/start

InputManager, Camera, SoundManager, ObjectPooling... also we've to be sure that they will be in their final state, so we won't have to update it often...

On an other hand, we need to figure out this FRIM topic one day. Since it will change all the platformer kit object, I think it will be for the V3.2. I may see with Nape author, if he can help us on that, and if there is an affordable cost, pay him.

gsynuh commented 10 years ago

Ok I fixed VirtualButton/Joystick

Now using scalefactor in the textures I create for the default graphics of virtual joystick/virtual button - in theory so they would look the same on every device.

I was using _ce.stage for position starling objects, which worked fine, when starling stage was like the flash stage, but I guess its better to get rid of that confusion now

alamboley commented 10 years ago

Tested on my iPad retina, everything works perfectly :+1:

mcapraro commented 10 years ago

this is working really well guys! wow!

FULLSCREEN is great and really feels like that would be the common case for most situations. I guess NO SCALE would be used if you wanted to maybe show a game on a web page and simulate the ideal width and height for it.

for UI, i think it would be awesome to have those helper functions you mention. ideally, if Citrus had a recommended way to easily add UI - like a hud property that you just assign things to, like you do for hero.

for menus and such, it would also be nice to have a recommended way of doing it and then offer helpers for that. some people are making MenuStates, others are just adding DisplayList objects. Whatever is ideal it would be nice to have it in the engine ready to be created.

alamboley commented 10 years ago

We need to have a look on: https://github.com/BenoitFreslon/benoitfreslon-layoutmanager ;)

Also notice depending the game, we may need to have a display list UI or Starling. The choice isn't always easy to make!

mcapraro commented 10 years ago

this is very cool, thanks for the link @alamboley

agreed, you should be able to choose display list or starling. i also wonder if there is any advantage to supporting feathers? i imagine for more complex controls it would be nice to leverage what feathers has already done rather than recreate starling buttons, etc.

alamboley commented 10 years ago

I'm not a huge fan of Feathers, I found it very complex and hard to start with, anyway it makes sense to use it if it's needed.

I think we can close this issue, the prototype is working fine. We should make the demo a bit more sexy.

mcapraro commented 10 years ago

hi @alamboley, thanks for your input. to be honest, i have yet to use feathers myself ;). my instinct is to actually use display list for menus and such, since simple things in display list still perform really well, but maybe the link you sent has the right approach. i was mainly thinking feathers for scrolling list views and stuff, but even that can work efficiently on the display list or in a simpler way. i will investigate.

i had one question about this new great functionality: the AnimationSequence still uses DynamicAtlas.fromMovieClipContainer with a scalefactor hard-coded to 1. Would there be a way to let developers change that to be dynamic with this new system?

alamboley commented 10 years ago

Done: https://github.com/alamboley/Citrus-Engine/commit/ff8aeb87d9570b17d47abec423873ad1c3f75136 ;)

mcapraro commented 10 years ago

@alamboley awesome! So, right now, that scalefactor is set with some code in the Utils class in the demo. do we have any code in Citrus that offers this scalefactor utility?

alamboley commented 10 years ago

Not yet. The thing is: this Utils class is very arbitrary, depending of your game you may want to create more scaleFactor, or change the switch value. However we could figure what would be the best default values.

gsynuh commented 10 years ago

best default is the starling reported scale factor which we could use and set in _ce.scaleFactor

And then everywhere we use the dynamictextureatlasgenerator, or even in StarlingArt where we create textures from loaded images , use _ce.scaleFactor (which can be user defined)

alamboley commented 10 years ago

Hmm that sounds good however, I'm afraid that the final user will think he has to create assets size for every Starling.contentScaleFactor values and we know they are boundless... so he would be on the wrong way.

mcapraro commented 10 years ago

hi @alamboley & @gsynuh, yeah, it would be good to provide some smart defaults like maybe rounding the starling.contentScaleFactor to logical stops, like in the multiresolution test. maybe developers can override this if they want ultimate control but i would personally like to just jump in and have something work in a smart way right off the bat.

one thing i noticed is that when i test, if i remove the width and height specified in the SWF embed tag, the scalefactor calculated in the Main.as is not totally correct. basically it sometimes takes a second for AIR to get the right width and height and so sometimes i get the wrong scalefactor. will this be an issue on mobile? i dont seem to get the right stage width and heigh consistently until _context3DCreated, which is too late to create the textures

EDIT: starling gets the right scalefactor however

gsynuh commented 10 years ago

Please check out the example now (needs testing)

in Main, I provide the sizes/scales I have for assets : _assetSizes = [1,1.5,2,4,5];

internally when the viewport is setup ,

scaleFactor = findScaleFactor(_assetSizes);


protected function findScaleFactor(assetSizes:Array):Number { var arr:Array = assetSizes; arr.sort(Array.NUMERIC); // not sure if necessary. var scaleF:Number = starling.contentScaleFactor; var closest:Number; var f:Number; for each (f in arr) if (!closest || Math.abs(f - scaleF) < Math.abs(closest - scaleF)) closest = f; return closest; }


which finds, according to the "official"content scale factor returned by starling

the closest number in that array to it.

So If I'm missing scale 3 but have 2 and 4, it will get either one that is closer

and by default assetSizes is [1]

mcapraro commented 10 years ago

i'll test this @gsynuh . looking into the scalefactor issue more, i think that we need to be able to get the proper scalefactor first before deciding if baseline_extended is the right Context3DProfile because we may not have the proper scalefactor set by then, since if i remove width/height form the SWF embed tag, and let FDT (my editor) set the size of the test movie to the selected test device, i wont get the right width and height in the handleAdeedToStage callback. does that sound right?

gsynuh commented 10 years ago

ok, I just want to be sure any CE app can also run in windowed mode with the adobe air player (so no fullscreenWidth/fullscreenHeight can be used in that context unless the app itself wants to go in fullscreen mode)

alamboley commented 10 years ago

Hey guys,

Nice job @gsynuh ! However I think we should have the lowest value. For example if it returns 3.5, it should be 2. It would really be hard to everything into the screen with Assets size 4, right?

gsynuh commented 10 years ago

only for the memory yes (I was just aiming for quality though and didn't think of it)

Check this out, I'd be very happy to have that and basically just use by default the best available profile for context3D : https://github.com/PrimaryFeather/Starling-Framework/issues/337

mcapraro commented 10 years ago

@gsynuh that is super funny, i was just reading that page in reference to this LOL!

i think its a good approach

alamboley commented 10 years ago

Math.floor should be good I think.

Good approach right.

mcapraro commented 10 years ago

looks like this might work, and it sounds like with the latest AIR SDK we dont need to use a delayed call

https://github.com/PrimaryFeather/Starling-Framework/issues/337#issuecomment-20620689

gsynuh commented 10 years ago

< -- edit, doesn't solve the problem --.>

mcapraro commented 10 years ago

hi @gsynuh, if we use the approach in that starling thread, then we wont have to worry about setting the context3dprofile and we wont need the scalefactor until later when we create teh asets, at which point we can query the scalefactor from starling and use the array method you listed. does that make sense?

alamboley commented 10 years ago

Yes it sounds great to me. Do you have an iPad 1 to make tests? I've the iPad retina which is great for testing the BASELINE_EXTENDED ;)

mcapraro commented 10 years ago

i do. here's the code i am testing, i'll test on the ipad 1 now

public function setUpStarling(debugMode:Boolean = false, antiAliasing:uint = 1, viewPort:Rectangle = null, profile:String = "auto"):void {

            if (Mobile.isAndroid())
                Starling.handleLostContext = true;

            if (viewPort)
                _viewport = viewPort;

            _debugMode = debugMode;
            _antiAliasing = antiAliasing;
            _profile = profile;

            stage3D = stage.stage3Ds[0]; 
            stage3D.addEventListener(flash.events.Event.CONTEXT3D_CREATE, onExtendedComplete);
            stage3D.addEventListener(ErrorEvent.ERROR, onExtendedComplete);

            try { //Try and request EXTENDED profile.
                stage3D.requestContext3D("auto", Context3DProfile.BASELINE_EXTENDED); 
            } catch (e:Error) { onExtendedComplete(); }
        }

        protected function onExtendedComplete(event:* = null):void 
        {
            var success:Boolean = (event != null && !(event is ErrorEvent));
            stage3D.removeEventListener(flash.events.Event.CONTEXT3D_CREATE, onExtendedComplete);
            stage3D.removeEventListener(ErrorEvent.ERROR, onExtendedComplete);
            if(stage3D.context3D){ stage3D.context3D.dispose(false); }

            var detectedProfile:String = success? Context3DProfile.BASELINE_EXTENDED : Context3DProfile.BASELINE;

            _starling = new Starling(RootClass, stage, null, null, "auto", _profile == "auto" ? detectedProfile : _profile);

            _starling.antiAliasing = _antiAliasing;
            _starling.showStats = _debugMode;

            _starling.addEventListener(starling.events.Event.CONTEXT3D_CREATE, _context3DCreated);
        }   
gsynuh commented 10 years ago

Well, I'm late - I just implemented jeff's version (not the shortest one) So I'll discard all of it cause I can't really test it anyway, I hope it works on your side!

gsynuh commented 10 years ago

also, when context3D is created, we then have the starling content scale factor (manually its stage.width/viewport.width) - assuming the findScaleFactor function works as expected, one would just override _context3DCreated , call its super, and use scaleFactor for the assets right?

(I'll add the Math.floor or maybe just something to round down when its exactly at *.5 before looking for the closest available 'asset factor' )

I just want to be sure I'm understanding things correctly : that if this thing works then we're done or almost.

gsynuh commented 10 years ago

@mcapraro , don't you think we should leave the option to delay anyway just for previous air versions?

Additionally, being able to have an array of context profiles to test for is good - maybe we just need baseline, or want to force baseline. This will also remove the profile argument from setUpStarling as we'll already be able to force a profile if we need to by ressetting the default array if we want to _context3Dprofiles = [Context3DProfile.BASELINE] ;

mcapraro commented 10 years ago

hi @gsynuh, @alamboley, i tested the context 3d profile code and @gsynuh you are correct in that the timer must remain, for the first gen iPad and also for android. here is a pic i took after the adjustment of it running on an iPhone5, iPadMini (1st gen) iPad 1, Nexus 7, and Kindle Fire HD

img_20131030_102101

here's the final adjustments i made to it. you may want to add this yourself and rename some stuff as i just sloppily pasted it into your code

        public function setUpStarling(debugMode:Boolean = false, antiAliasing:uint = 1, viewPort:Rectangle = null, profile:String = "auto"):void {

            if (Mobile.isAndroid())
                Starling.handleLostContext = true;

            if (viewPort)
                _viewport = viewPort;

            _debugMode = debugMode;
            _antiAliasing = antiAliasing;
            _profile = profile;

            stage3D = stage.stage3Ds[0]; 
            stage3D.addEventListener(flash.events.Event.CONTEXT3D_CREATE, onExtendedComplete);
            stage3D.addEventListener(ErrorEvent.ERROR, onExtendedComplete);

            try { //Try and request EXTENDED profile.
                stage3D.requestContext3D("auto", Context3DProfile.BASELINE_EXTENDED); 
            } catch (e:Error) { onExtendedComplete(); }
        }

        protected function onExtendedComplete(event:* = null):void 
        {
            var success:Boolean = (event != null && !(event is ErrorEvent));
            stage3D.removeEventListener(flash.events.Event.CONTEXT3D_CREATE, onExtendedComplete);
            stage3D.removeEventListener(ErrorEvent.ERROR, onExtendedComplete);
            if(stage3D.context3D){ stage3D.context3D.dispose(false); }

            var detectedProfile:String = success? Context3DProfile.BASELINE_EXTENDED : Context3DProfile.BASELINE;

            setTimeout(function():void{
                _starling = new Starling(RootClass, stage, null, null, "auto", _profile == "auto" ? detectedProfile : _profile);

                _starling.antiAliasing = _antiAliasing;
                _starling.showStats = _debugMode;

                _starling.addEventListener(starling.events.Event.CONTEXT3D_CREATE, _context3DCreated);
            }, 200);

        }   
gsynuh commented 10 years ago

\o/

I have to reboot, I was putting the code in (with timer and also the possibility to select which profiles you want to test using an array) but adl.exe just crashes on me constantly. be back soon - thank you very much for testing !!!!!!

alamboley commented 10 years ago

Great! Will test on my iPad retina tomorrow.

Envoyé de mon iPhone

Le 30 oct. 2013 à 18:29, Thomas Lefevre notifications@github.com a écrit :

\o/

I have to reboot, I was putting the code in (with timer and also the possibility to select which profiles you want to test using an array) but adl.exe just crashes on be. be back soon - thank you very much for testing !!!!!!

— Reply to this email directly or view it on GitHub.

mcapraro commented 10 years ago

@alamboley do you have a hi rez or vector Citrus logo? i wanted to make some generic splash screens for testing this on iOS

gsynuh commented 10 years ago

here you go http://citrusengine.com/logo/

mcapraro commented 10 years ago

thanks @gsynuh

ok, so i will try to find time to put those together and get them to you. also, off topic but do you guys have a component set you like to use for your apps? specifcally, i want to create a utility that lets me design my menu screens in flash and converts them, but i will need a list component of some sort (want to mock up a store UI). do you use feathers or custom starling controls, or Display List UI (any specific components or frameworks for the Display List that you like?).

The apps i have are all pretty custom and display-list based so far so they arent good examples. it will be a lot of work to support both starling-based and displaylist based UI, and it may not be worth it (i tend to think starling is the way to go, but display list is so easy ;) )

mcapraro commented 10 years ago

ok, went back through the feathers demos and it is actually really tight and performs well. i will target starling/feathers first. then we can see how this translates to the display list

gsynuh commented 10 years ago

I never used it myself, tried once though. I will someday of course, but for now I never had use for complex ui/hud so always made up my own little setup - I just uploaded a basic 9 grid layout in citrus.ui.starling which could be ported to display list

mcapraro commented 10 years ago

Awesome Thomas, will look into it

alamboley commented 10 years ago

Kudos guys, it works perfectly on my iPad retina!