Adobe Air android with 2 swfs questions


#21

I DID IT!!! I managed to build with ANT!
I found an example build.xml and with help of ant manual and trial and error, I changed and added what I figured to be necessary.

Buildfile: D:\Projects\air\xromatopaixnidia_ANT\build.xml

clean:
[delete] Deleting directory D:\Projects\air\xromatopaixnidia_ANT\deploy
[mkdir] Created dir: D:\Projects\air\xromatopaixnidia_ANT\deploy

copy:
[copy] Copying 1 file to D:\Projects\air\xromatopaixnidia_ANT\deploy
[copy] Copying 1 file to D:\Projects\air\xromatopaixnidia_ANT\deploy
[copy] Copying 1 file to D:\Projects\air\xromatopaixnidia_ANT\lib

build:
[exec] Loading configuration: C:\Program Files\Adobe\Adobe Animate CC 2018\AIR32.0\frameworks\air-config.xml
[exec]
[exec] 10813688 bytes written to D:\Projects\air\xromatopaixnidia_ANT\deploy\xromatopaixnidia.swf in 7,623 seconds

airi:
[exec] Warning: Using default implementation for native extension ‘com.myflashlab.air.extensions.dependency.overrideAir’

package-release:
[exec] NOTE: The application has been packaged with a captive runtime.

release:

BUILD SUCCESSFUL
Total time: 44 seconds

OK back to work now…

TODO:
-fix perfomance
-fix preloader
-figure out how to include the icons


#22

good stuff :slight_smile:

sorry if I was a bit too pushy to use Ant
but really you will see with time it help a lot

now Ant like anything else, you can do simple things and more advanced things

so try to make it work for you

for ex: you could add a variable to your build

C:\work\xromatopaixnidia> ant.exe -Dsomething=true

and that would not only build the SWF, the AIR app etc.
but then it would launch the app with ADL, or launch it with an emulator, etc.

keep at it, it will get better and easier with time

is it more or less same that when you were building with Animate CC or is it much slower?

this is basically organising which is built in which order and use the good seqeucnes or arguments for the compiler

probably just a path issue

so now that you have a build, and if those problems above persists, now you can share the build here (using triple backtick and indicating xml)

  ```xml
  <xml> stuff </xml>
  ```_ <- not the underscore

it should show as

<xml> stuff </xml>

#23

Well, the game is pure vector based, with very heavy shape tweens, and I have the framerate of stage at 30fps. I managed to keep the frame rate average at 27fps when I build with Animate cc. Building with ant now is very slow something like 4-5fps. I deactivated the Event.DEACTIVATE, Event.ACTIVATE, just in case, but again same 4-5fps…

NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, appDeactivate);
NativeApplication.nativeApplication.addEventListener(Event.ACTIVATE, appActivate);

I will post again this afternoon with details about the preloader and the other issues…


#24

where and how to you test this “frame rate average at 27fps” ?

it is a release build or a debug build?

do you test on the desktop or on a mobile device?

does the test that gives “something like 4-5fps” is happening in the same conditions?

ideally if you could put the screenshots of the UI settings you have for compiling with Animate CC
and the XML of the Ant build, I could compare if “some things” are missing in the Ant build


#25

I am using Hi-ReS-Stats to check frame rate.

I am using the -target apk-captive-runtime argument on adt, so I suppose it is considered as release. For a debug build the correct argument is -target apk-debug, am I correct?

Because of the ANEs I prefer to test on mobile device

After some testings I conclude that the very low frame rate is happening only when I use
the arguments -frame=0,Preloader -frame=1,Main at amxmlc

I also tried the variations:
-frames.frame=0,Preloader -frames.frame=1,Main
-frames.frame+=0,Preloader -frames.frame+=1,Main
-frames.frame+=1,Preloader -frames.frame+=2,Main
-frames.frame+=one,Preloader -frames.frame+=two,Main

but without any success. I even added the argument -default-frame-rate=30 just in case…

But if I remove completely the -frame arguments, then the ant build is as good as is the build from animate cc. I can say the ant is maybe 2 times faster to complete the build that animate cc.

Sure! here is xromatopaixnidia-app.xml I use for Animate CC build
and here is the xromatopaixnidia-app.xml I use for the ant build! The differences are, that I removed the icons temporarily and changed to the appropriate path at line 33 ().

Here is a screenshot with animate cc air settings

and actionscript settings

and finally here is ant’s build.xml

Thank you for your time, and tell me if you need more info

EDIT: I forgot to upload the publish settings screenshot


#26

so just to be clear

xromatopaixnidia.swc is your app sources you compiled from Animate CC
but that you’re re-using compiling the app with Ant right ?

so my guess at what’s happening is

  • you compile the target ${src.dir}/Preloader.as
  • with the lib -library-path ${lib.dir}/${swc.file}
    which is all your source code pre-compiled
  • so when it come to frames it does not work
    because you use pre-compiled sources instead of actually compiling the sources

so let review the compiler stuff

you do not want to use -library-path ${lib.dir}/${swc.file}
for your main source code, even if it can work somehow, it is prone to errors and complications

each time you compile your app you do want to compile it from sources (not from pre-compiled sources aka a SWC)
and for that you need 2 things

  • a main class
    for ex: ${src.dir}/Main.as
  • a source path
    eg. -source-path ${src.dir}

now about compiling you need to understand also how linking works

when you compile against a library you have two choices

  • compile against and link the library
    that means the final binary contains your code and the library code merged into it
  • compile against but omit to link the library
    your code will compile without error because it knows about a dependency
    but the final binary will contain only your code, not the library code

when you use -external-library-path according to the doc

-compiler.external-library-path [path-element] [...]
    alias -external-library-path
    list of SWC files or directories to compile against but to omit from
    linking (repeatable)

so best example is airglobal.swc
you want to compile against it but not embed its code in your final output
because its code is already embedded in the AIR runtime
for that one you would use -external-library-path

another example would be a “normal” SWC library
like starling.swc, uanalytics.swc, etc.
those are basically AS3 sources pre-compiled into a SWC
so for those you want to use -library-path
eg. you want to merge their code into your final output

now when it comes to ANE

  • when you compile the SWF you use -external-library-path
    so your source compile against the ANE library but without embedding it
  • and only when you compile the Android app with ADT
    there you embed the ANE library

so this part

    <target name="build" description="Compiles the project SWF">
        <exec executable="${air.amxmlc}" failonerror="true">
            <arg line="${src.dir}/Preloader.as"/>
            <arg line="-library-path ${lib.dir}/${swc.file}"/>
            <arg line="-external-library-path+=${ane.dir}/${ane1}"/>
            <arg line="-external-library-path+=${ane.dir}/${ane2}"/>
            <arg line="-external-library-path+=${ane.dir}/${ane3}"/>
            <arg line="-external-library-path+=${ane.dir}/${ane4}"/>
            <arg line="-external-library-path+=${ane.dir}/${ane5}"/>
            <arg line="-external-library-path+=${ane.dir}/${ane6}"/>
            <arg line="-external-library-path+=${ane.dir}/${ane7}"/>
            <arg line="-external-library-path+=${ane.dir}/${ane8}"/>
            <arg line="-external-library-path+=${ane.dir}/${ane9}"/>
            <arg line="-frames.frame+=1,Preloader"/>
            <arg line="-frames.frame+=2,Main"/>
            <arg line="-default-frame-rate=30"/>
            <arg line="-swf-version=43"/>
            <arg line="-output ${deploy.dir}/${swf.file}"/>
        </exec>
    </target>

change it to something like that

    <target name="build" description="Compiles the project SWF">
        <exec executable="${air.amxmlc}" failonerror="true">
            <arg line="-output ${deploy.dir}/${swf.file}"/>
            <arg line="-strict=true"/>
            <arg line="-warnings=true"/>
            <arg line="-optimize=true"/>
            <arg line="-swf-version=43"/>
            <arg line="-target-player=32"/>
            <arg line="-debug=false"/>
            <arg line="-verbose-stacktraces=false"/>
            <arg line="-default-frame-rate=30"/>
            <arg line="${src.dir}/Main.as"/>
            <arg line="-source-path ${src.dir}"/>
            <arg line="-external-library-path+=${ane.dir}/"/>
        </exec>
    </target>

the arguments -strict, -warnings, -optimize
configure the compiler

-swf-version and -target-player let you control the AIR API version

-debug and -verbose-stacktraces
is what will produce a debug build or a release build
if both are true you ll produce a debug SWF and so get a debug build
if both are false you ll produce a release SWF and so get a release build

you don’t need to add each ANE individually with -external-library-path
just indicate the directory containing all the ANE

and only once you got that working, then you will go into using the -frames option


#27

I will explain briefly how my project is constructed.

The project is a game for preschool children and help them in a fun way to learn the colors. Is only in Greek language for now.

Project spine:

  • Mini games, ui and parents section are pre-compiled into individual swcs.
  • Minigames has dependencies from ui.swc, the code of ui.swc is not merged into each minigame
  • finally I was building the project in animate cc from a fla file that contains Main.as, main menu, settings, choose mini game menu. That fla file has in actionscript settings all the swcs and anes. From that fla file I was building the final apk.

Every symbol that I wanted interaction is a movie clip. Various graphical elements like eyes, mouths, teeths etc are graphic symbols attached to movieclips. Every movieclip is exported at frame 1, and has a Class .as attached to it, except if shares common logic with other movieclips so it has base Class.

Now with ant, I understood (maybe mistakenly) that I need my project precompiled in a big swc, and then I compile with preloader using ant.

Now to my questions
Should I put all swcs seperatly into final build with ant, using -external-library-path?
Do I remove Main.as as document class to create the xromatopaixnidia.swc (the one the connects everything) and the I compile with ant with Main.as class? If yes, how will I implement the preloader.as?
Maybe should I rename source folders and compile swc files without source? I thing the animate will put emty classes in that case…

EDIT: I saw you removed the line completely

<arg line="-library-path ${lib.dir}/${swc.file}"/>

did you wanted to be replaced to something like this?

<arg line="-external-library-path+=${lib.dir}"/>

PS. I learnt already so many things in a few days. Thank you!


#28

yeah maybe we should have started there

well … at first look it seems you’re building a mobile app as if it was like an online SWF

I get you use a lots of SWC, but I don’t really see what you gain by doing that

I would say at this point you build everything around a specific design or way of doing
and it’s too late to remodel everything into something else

so yeah … whatever the design, good or bad, you are kind of stuck with it now
I guess you don’t to restart from scratch, so you gonna have to accept the limitations of the design

I’ll few comments, but bare in mind from how it is structured it’s not jsut adding a couple arguments on the command-line that can change a lot

In the general idea of a SWF file, a stream of bytes, you can use -frames to spread the load of your codes / dependencies / assets / etc. over multiple frames

from this

         |*|
frames:   1
          |
          all the code and assets here

to that

         |*|*|*|*|*|*|
frames:   1 2 3 4 5 6
          | | | | | |
          | | | | | main app code
          | | | | etc.
          | | | etc.
          | | assets
          | fonts
          preloader only

Except, there are big parts of your code that are pre-compiled into SWC

and this conflict totally with how the compiler can spread different part of the code over different frames

-frames.frame [label] [classname] [...]
    alias -frame
    A SWF frame label with a sequence of classnames that will be linked
    onto the frame. (advanced, repeatable)

at compile time if you tell the compiler
-frame N classname
it knows on which frame to compile it, but for this to works it needs to be at compile time

if it is already compiled into a SWC, from the top of my head I don’t think it will work

And now the “design” is

so with that, if you need to modify a game, that is assets or code, you basically have to recompile it from Animate CC, so it is not in the logic of compiling it all from the command-line

that part “Minigames has dependencies from ui.swc” is more problematic
if ui.swc change then you do have to recompile all the minigames depending on it, and again you need to go through Animate CC

it works for you but it put you in a position where compiling the main app from the command-line or Animate CC does not change much

that other part

again force you in a particular corner

you see, it’s one thing + a second thing + a third thing + etc. it is a “design”

if I was to tell you now: well no you do this and that instead, you will have to restructure everything
it is a bit counter-productive

so I would say “stop”, deal with what you have and go with it
and well if the problem is you can not have a splash screen because the design of how the thing is built force you in a particular corner, well … let’s call it a limitation of the design

I’m not saying it is hopeless, but you are at the end of a cycle, not a the beginning of a new one
so end the cycle with what you have and try to keep it as sane as possible

on a later update or “version 2”, there you can break everything apart and start fresh with a new design (I’m talking about code and how code is organised).

this “break things apart” not gonna take just few days, it’s not impossible but
you already have something working, almost done, I think it is better to just finish it
even if the small features (like a splash screen) can not be done.

My advice so far would be to “forget” about the command-line for now

  • consider your current project as “version 1”
    keep doing what you do with Animate CC, a lot of mini games pre-compiled as SWC etc.
    maybe some workaround can be found for splash screen or whatnot, but keep it together
  • in parallel, for later, start to build a “version 2”
    where you reorganise things differently and where you build everything from the command-line
    in short you will break up apart what you have in “version 1” and use a “different” design or organisation for that “version 2”, just be aware that it will take some time

Use that “version 2” to test things, for ex: “how would I got at building minigames 1 and having a dependency on UI without pre-compiling SWC and building it all in one go from the command-line?”

The exercise is to understand and control how things connect.

The command-line can allow to do more and maybe more efficiently but it is not magic, there is no silver bullet, so take the time to master it.

that’s very hard to say right now, “as is” all those SWC: UI, mini game 1, mini game 2, etc.
are not part of the build, so because they are SWC build from Animate CC I think they are exported on frame 1 by default.

Another design would be to

  • only export an assets.swc from Animate CC
    this one containing your symbols “Various graphical elements like eyes, mouths, teeths etc”
  • but build the mini game from source code .as file and compile them during the build
    not pre-compile them as SWC
  • and there you could use the -frames

eg. frame1.as

package
{
    // for a reference to the assets so there are embedded in this class
    import com.foobar.assets.eyes; eyes;
    import com.foobar.assets.mouths; mouths;
    import com.foobar.assets.teeths; teeths;
    //etc.

    public class frame1
    {

    }
}

and at compilation time -frames 1 frame1
will make the compiler embed the bytecode of the class frame1 exactly on frame 1

it is the same logic as this how to force compiler compile all classes in my project?

package
{
public class IncludeClasses
{
    import com.abc.db.Database;Database;
    import com.abc.logs.KBRemoteLogTarget; KBRemoteLogTarget;
    import com.abc.logs.KBLocalLogTarget; KBLocalLogTarget;
    import com.abc.exception.GlobalExceptionHandler; GlobalExceptionHandler;
    import com.abc.utils.NetConnectionMonitor;NetConnectionMonitor;
}
}

by doing the import followed by the reference of the class you force it to be exported in the code even if it is not used by reference in the code yet

so for symbols and other graphical assets where you use animations etc.
that you want to dynamically change like eyes01, eyes02, eyes03, eyes04, etc.
you force the code to “embed it all”

another way to do it is to keep those symbols as external SWF assets
so when you want to use it in the application you dynamically load the SWF
with the little trick of loading the SWF into an already existing class or interface

so the logic stay the same only the “skin” change

yet another way, if for example there are no animations is to use [Embed] with SVG files

but all that it is a design or an architecture of code, depending on how you do it,
some other things can be easier or harder

so that part -external-library-path vs -library-path I would say is something that need time to understand fully

so let’s try that

from Animate CC you generate
assets.swc that contains

synbol: com.foobar.assets.eyes.Eye01 extend flash.display.MovieClip
synbol: com.foobar.assets.eyes.Eye02 extend flash.display.MovieClip
synbol: com.foobar.assets.eyes.Eye03 extend flash.display.MovieClip

we use MovieClip because the eyes are some kind of :crazy_face: animation built on a timeline

now our Main.as
will use those eyes assets

package
{
    import flash.display.Sprite;
    import com.foobar.assets.eyes.*;

    public class Main extends Sprite
    {
        public function Main()
        {
            if( stage )
            {
                onAddedToStage();
            }
            else
            {
                addEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
            }
        }

        private function onAddedToStage( event:Event = null ):void
        {
            removeEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
            _main();
        }

        private function _main():void
        {
            var eye:MovieClip = new Eye01() as MovieClip;

            addChild( eye );
        }
    }
}

now we compile to merge all the code and assets

$ amxmlc -library-path assets.swc Main.as -output myapp.swf

the myapp.swf will contains all the classes

but if we compile against it but omit the linking

$ amxmlc -external-library-path assets.swc Main.as -output myapp.swf

the compiler will not generate any errors when it sees import com.foobar.assets.eyes.*;
in the sources, it knows it is compiling against that library with -external-library-path assets.swc
but the generated myapp.swf will not contains the code of assets.swc

so when you run myapp.swf you will probably get a runtime error

to make it work you will need to

  • either embed the assets.swc before the code of Main.as is executed
  • or load an external assets.swf file containing the code definitions

load an external assets.swf is what we call an import loading
see Loading display content dynamically
see LoaderContext class

package
{
    import flash.display.Sprite;
    import com.foobar.assets.eyes.*;

    public class Main extends Sprite
    {
        public function Main()
        {
            if( stage )
            {
                onAddedToStage();
            }
            else
            {
                addEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
            }
        }

        private function onAddedToStage( event:Event = null ):void
        {
            removeEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
            _preload();
        }

        private function onComplete( event:Event ):void
        {
            var urlloader:URLLoader = event.target as URLLoader;
            var loader:Loader       = new Loader();

            var AD:ApplicationDomain = ApplicationDomain.currentDomain;

            var context:LoaderContext = new LoaderContext( false, AD );
                context.allowCodeImport = true;
              //context.allowLoadBytesCodeExecution = true;

                loader.loadBytes( urlloader.data, context );

                /* Note:
                   from that point the bytes of `assets.swf`
                   have been loaded in-memory
                   using the same Application Domain
                   and the same Security Domain

                   that means all code definitions from the loaded file
                   are now available to the current context of code
                */
               _main();
        }

        private function _preload():void
        {
            var urlloader:URLLoader = new URLLoader();
                urlloader.dataFromat = URLLoaderDataFormat.BINARY;
                urlloader.addEventListener( Event.COMPLETE, onComplete );
                urlloader.load( new URLRequest( "assets.swf" ) );
        }

        private function _main():void
        {
            var eye:MovieClip = new Eye01() as MovieClip;

            addChild( eye );
        }
    }
}

so you compile with

$ amxmlc -external-library-path assets.swc Main.as -output myapp.swf

-external-library-path assets.swc allow your code to reference such classes as com.foobar.assets.eyes.* without generating an error

and then loading the assets.swf make the code definitions available

or
you can embed the assets.swc before the code of Main.as is executed
and for that you use -frames

frame1.as

package
{
    // for a reference to the assets so there are embedded in this class
    com.foobar.assets.eyes.Eye01; Eye01;
    com.foobar.assets.eyes.Eye02; Eye02;
    com.foobar.assets.eyes.Eye03; Eye03;
    //etc.

    public class frame1
    {

    }
}

and you compile as

$ amxmlc -library-path assets.swc -source-path src/ -frames 1 frame1 -frame 2 Main -output myapp.swf

the code of “assets.swc” will be embedded in frame 1
that means when the code in frame 2 of the Main class will need it
it would have been already “loaded” in memory

Dynamically loading code while being able to compile against it without generating errors can get complicated, even more so on mobile (vs online SWF), personally I find it easier to just embed everything in 1 SWF

Now, changing the way your organise things “after the fact” can be in some case difficult.


#29

I see… But even so, I feel like it’s a win-win situation for me. I managed to get started and finish my first project which even if it is bad designed, it “works fine” for the intended target audience (children under the age of 5). I also learnt a lot of knowledge, especially from here, thanks to you!

Well, that was an advice I got from an as3 group in facebook, before I found out this forum here. “In order to avoid the library to flood with symbols so I will have better compilation time and better organized library and to debug each mini game individually” When the told me about swc files, i did not even know that swc files are exist.

I red carefully every piece of information and advice you game me and before I move on, I see if understand correctly what I should have done.

If understood correctly, I put inside a (or more) swf or swc only the assets without any code. But in order to be able to reference the assets some actions required on the swf/swc side, correct? That might be to enable export classes for actionscript? With or without exporting at frame X?
I think that info is an essential missing piece of the puzzle for me.

After making clear some essential things I thing I will be able to try my next project with starling. With starling, I suppose things going to be less forgiving and this time all graphic assets will be embed as Bitmap.

Thank you for your time!


#30

let me be clearer

it is not

it is A design, as you say it works, it allows you to publish an app, it is valid

there is no really bad or good, more like pros and cons

so sorry if my answer look like a let down but imho it is more important to finish a project (whatever the pros and cons) than to “restart it” just to change the design

ok, it seems valid and yeah having part of your app pre-compiled as SWC will make the compilation faster, but it will also force you to recompile those “by hand” if you need to update, so yeah pros and cons.

it is about that, but first let me ask, what are your assets?
do you have animations? not code at all not even a stop() somewhere?
or is it just vector drawing?
do you use like a clip container so you can easily switch different assets (eyes, mouths, teeths, etc.) to test the graphic design?

so remember I don’t know those assets and I don’t know your code
but I would say if you don’t have animations then most or all of those assets could

  • be exported as a SWF and loaded dynamically like you load an image
  • or even better be defined directly in classes with [Embed]

but this is mainly related to a “way of working” with the assets
for ex you could have an eyes.fla where you build your symbols in the Library
and yo export all of those on frame 1

but in the actual FLA you have your assets layout on the timeline in such a way
so you can visually edit/move/review/etc. them

my point is to say that as an asset those are at the end of the code chain, the leaf

the main app code can program and add logic, even work with placeholders
but then load dynamically those assets in the right place

image a Background class where you can load any .png image to actually fill the background
the class can have logic, like ratio-resize based on height or width, transparency, whatever
but the assets itself has no logic, you just load it “in place”

public class Background
{
    public var image:Bitmap;
    //...
}

when you create a var foobar = new Background()
you will reference the image with foobar.image all the time
if no asset loaded you work with a placeholder
and loading the assets allow to change/update the actual bitmap

so the part “be able to reference the assets some actions required on the swf/swc side, correct?”
you can do it a lot of different way but I would advise to not have to depends on code inside the asset itself

you can perfectly have an “advanced” AS3 class with a deep tree structure
of MovieClip or Sprite or Bitmap etc. and just load the assets into it

the AS3 code keep the logic the assets are just replaceable

yes good idea, you need to find your own way to balance the code and the assets

again there are no good or bad design, but depending on the pros and cons,
some things become “easy” or “hard”

try to look into Scout CC too, it will help you seeing a global picture of the whole thing running in term of performance, memory etc.


#31

I do not feel frustrated but more experienced! Even the wrong paths are giving valuable lessons!

Full of animations, some hand drawn dradigital style, many classic tweens, and many many shape tweens! If you try my app, you will see that is more interactive animation than a game. I manipulate the animation with code using frame labels. The very essence of my design, the core of the project is based on interactive animation. I was studying animation when I discovered actionscript. I visualised and created the whole app as animator, not programmer (remember I said new to actionscript and new in programming). To be precise, this project is part of a bigger project of animation and my next games will have the same characters and the same target audience!

Until halfway of developing I was putting everywhere stop(); but I red somewhere that is a bad practice, so I removed most of them. Here and there are still some stop(); in movieclips.

if by clip you mean movieclip yes. I also used empty movieclips in order to put inside other movieclips with code

So looks like at current project this option is off the table.

…And I did not know about scout. Another small useful piece of info I learned today…

In conclusion:

  • Well for sure I keep everything I learnt from you, and I am sure every new project it will be a bit better.
  • At my next projects I’ll try my best to follow the best practices and I will use ant from day 1
  • My current project must leave the beta and go to release version. I will try my final idea, I will compile in animate the fla files without any source code (I will rename the source folder temporarily) and I will copy all the source code into a singe folder and I try again to compile with ant. I think it worth the shot. Every source code I wrote I put in different packages (eg minigame.chameleongame, minigame.colorgame etc). If the compilation fails, then I will compile the release version and I will maintain this project with animate cc.
  • Lesson well learned…

For one more time, thank you very much for your time and effort to help me! I learnt A LOT! You made me get started with ant… I highly appreciate it, and as promised, I will credit you at every future project!