00:00
00:00
View Profile PsychoGoldfish

n/a, Male

NG Code Monkey

Hard Knocks

Ur Mom

Joined on 9/26/00

Level:
12
Exp Points:
1,566 / 1,600
Exp Rank:
29,116
Vote Power:
5.45 votes
Rank:
Town Watch
Global Rank:
51,945
Blams:
46
Saves:
109
B/P Bonus:
2%
Whistle:
Normal
Trophies:
33
Medals:
559

Wick Editor Thoughts/Ideas/Examples

Posted by PsychoGoldfish - April 26th, 2019


I've been playing with Wick Editor a bunch, trying to get some simple Newgrounds.io API widgets working in advance of the Wick Editor Game Jam.


Edit: The Newgrounds.io widgets are available for download now!


One of the appealing things about Wick Editor (besides being 100% free) is how similar it is to older ActionScript 2.0 versions of Flash, but it's definitely lacking a few things, and has a bunch of quirks.


So I wrote up a couple chapters/tutorials for using Wick Editor that may help people used to working a certain way in Flash, or other game frameworks.




Understanding "this" context


One of the most jarring things for me was figuring out what the 'this' scope refers to in different places.


In AS2 Flash, you could select a MovieClip and put code directly onto it with functions like onClipEvent(load) and onClipEvent(enterFrame). Within this code, if you used 'this', it would refer to your MovieClip instance.


In Wick Editor, you can do just about the same thing. You can put code directly on a Clip using 'function load()' and 'function update()'. Just like in Flash, using 'this' will refer to your Clip instance.


Now, if you were to try putting code on the timeline of your respective clips, you hit a major difference. If you add scripting to a key frame within a MovieClip, 'this' still refers to the MovieClip instance.


In Wick Editor, if you put code on a key frame, 'this' actually refers to the frame itself, not the Clip. To reference the clip from code on a keyframe, you instead need to use this.parentObject.


This is important to remember, especially if you put code on multiple key frames and expect it to reference code from older frames. Using 'this' on a Wick Frame literally only refers to that frame.


Let's say on frame 1, you use the following code:

this.alert_text = "Hello World";


Then on frame 2, we call:

alert(this.alert_text);


The alert will say 'undefined', because each Wick Frame is a separate object.


If you instead do this on frame 1...

this.parentObject.alert_text = "Hello World";


... and this on frame 2...

alert(this.parentObject.alert_text);


You will get the expected Hello World result.




Scoped Variables


Flash never really had global variables. If you wanted something to be universal, you would set it with _root.varName = "value";. Also, any variable not attached to an object, or _root, had to be declared with var varName = "value";


Because Wick Editor really just uses JavaScript, there's a bit of a difference in variable scopes and how to use them.


Any variable you set without a 'var' or 'let' declration, will be a global variable. (TECHNICALLY, it's attached to the Window object, but for all purposes, this is considered global).


If I write the following ANYWHERE in my code...

alert_text = "Hello World";


...I can access that value from any frame or object, no matter what (at least after it's been set).


If I write

var alert_text = "Hello World";


It's only accessible by whatever scope it's written in, or anything below that scope. If I wrote it at the top of a script on frame 2 of my timeline, only code in that frame could access it. If I put any functions in that same block of code, they can access it as well. If I put it within a function, code outside of that function would not be able to access it.


Examples:

var outer_value = "outer";

function test_inner() {
    var inner_value = "inner";

    alert(outer_value); // alerts 'outer'
    alert(inner_value); // alerts 'inner'
}

test_inner();

alert(outer_value); // alerts 'outer'
alert(inner_value); // alerts 'undefined'




Extending Clips


One big thing lacking from Wick Editor is a way to attach an external script to a clip, like Flash's 'Export for ActionScript' would let you do. There's lots of ways you could work around this, but you always want to keep duplicate code and memory management to a minimum.


One way to do this is to write single functions for controlling objects you intend to use in multiple places, such as a game enemy.


Because there's no support for external js files yet, I found the best way to do this, and keep things organized, is to create a layer and a single key frame for every object I want to write code for.


So I might add a layer and name it "Enemy1 Code". Then I'd add a keyframe on frame 1 and add this code to it:


Enemy1 = function() {

    // prevent this stuff from running more than once.
    if (this.extended) return;
    this.extended = true;

    // fires when the sprite is loaded
    this.load = function() {
        // start at the left side of the screen
        this.x = 0;
    };

    // fires every game tick
    this.update = function() {
        // move the thing sideways, just to show this works.
        this.x += 10;
    };

};

Now I would create a new Clip. It would have to be on a lower layer, or later frame to ensure the above code had a chance to run. I would double click the Clip to edit it, and on it's first frame, I would add this code:

Enemy1.call(this.parentObject);


If you test your game, your object should see your Clip slide across the screen.


One thing I figured out is any code you put in a Clip's first frame will execute before it's load and update methods. If you put the code on the clip itself, this isn't always the case.


So what we are doing is using JavaScript's call method to execute all of the code in the global Enemy1 function, using the Clip instance as the 'this' scope, before the Wick engine calls it's load or update methods. When the Clip has loaded, those methods are ready to go.


That worked pretty well, but I realized if I ever wanted to clone this Enemy1 clip, it would create new versions of the load/update functions for every instance. This could mean a potential memory leak, and we want to avoid that.


The next thing I did was move those into static functions attached to the Enemy1 function object, and just reference them in the main Enemy1 function. Since we're referencing static functions, they won't need to be created for each instance anymore:

Enemy1 = function() {

    // prevent this stuff from running more than once.
    if (this.extended) return;
    this.extended = true;

    // fires when the sprite is loaded
    this.load = Enemy1.load;

    // fires every game tick
    this.update = Enemy1.update;

};

// these always exist, and won't need to be re-created for every instance
Enemy1.load = function() {
    this.x = 0;
};
Enemy1.update = function() {
    // move the thing sideways, just to show this works.
    this.x += 10;
};




Faking a Library


One glaring omission to how Wick Editor currently works is the asset library only holds your image and media files. In Flash it contained all the Graphics, Buttons and MovieClips you created, and you could attach names to them so you could dynamically add them to your stage.


Wick doesn't have anything like that right now. The best you can do right now is make all of your clips, and hide them off-stage somewhere, cloning them as needed.


Using this method, you want to make sure your "library" of clips aren't executing any significant code, but make sure when you clone them that they behave as expected.


I figured a great way to do this is to create a master LibraryAsset function that could handle registering clips and creating new instances with a subclass attached.


I ended up making a little demo where a bunch of space ships fly across the screen at varying scales and speeds.


To start, I made my global LibraryAsset function:

/**
 * name - The string name you will use to get clones of the asset
 * clip - A reference to the actual Wick Clip
 * subclass - A reference to the subclass this asset will use when cloned
**/
LibraryAsset = function(name, clip, subclass) {
    
    // only add a clip once
    if (LibraryAsset.assets[name]) return false;

    // make a reference to the subclass we'll be using
    clip.subclass = subclass;
    
    // make me invisible, just to be safe
    clip.opacity = 0;

    // store a reference to the clip by name
    LibraryAsset.assets[name] = clip;
};


// stores references to our library assets
LibraryAsset.assets = {};


// Use this to get a cloned asset, by name, with it's subclass applied.
LibraryAsset.get = function(asset_name) {
    
    // throw an error if we try getting an undefined asset.
    if (typeof(LibraryAsset.assets[asset_name]) == 'undefined') {
        throw('Invalid asset name: ' + asset_name);
    }
    
    // get a reference to the asset clip we want
    var asset = LibraryAsset.assets[asset_name];
    
    // create a clone
    var clone = asset.clone();
    
    // make it visible
    clone.opacity = 1;
    
    // apply the subclass so the clone actually does stuff.
    asset.subclass.call(clone);
    
    return clone;
};


Then I made the subclass to control my space ships:

Ship = function() {
    // reference our static functions to save memory
    this.load = Ship.load;
    this.update = Ship.update;
};


// on load, we want to set a starting position, scale & speed.
Ship.load = function() {

    // set the starting position
    this.x = -100;
    this.y = randomInt(0, project.height);
    
    // scale our ship and set it's speed
    var scale = randomFloat(0.5, 1);
    this.speed = 30 * scale;
    this.scaleX = scale;
    this.scaleY = scale;
};


// on update, we make the ship move right until it's off-screen, then reset it
Ship.update = function() {

    // move the ship
    this.x += this.speed;

    // if it's off-screen, call our load function again
    if (this.x > project.width + 100) {
        this.load();
    }
};


Next I drew my space ship and made it into a Clip. I double clicked that to edit it, and on the first frame I added the following code:


LibraryAsset('ship', this.parentObject, Ship);

This basically told my LibraryAsset function that I want this Clip to be called 'ship', and to use my Ship subclass to control it.


If I test my game at this point, I basically have a blank screen because the LibraryAsset function hides my ship, and it isn't using the subclass at all right now.


To finis the demo, I added this code to the root timeline:

for(var i = 0; i < 20; i++) {
    var ship = LibraryAsset.get('ship');
}


This gets 20 copies of my ship asset WITH the subclass applied. When I test my game now, I have a screen full of ships zipping across as intended.


You can see my working demo and grab the .wick file at https://www.newgrounds.com/projects/games/1327369/preview




Hopefully somebody finds my experiences with Wick Editor useful and is inspired to make something cool for the game jam!


Tags:

11

Comments (5)

I am impressed; I just hope my computer can run it.

Wow

This is really helpful, thank you so much. Gave me some great ideas reading through this, so I really appreciate it. Also thanks for doing the legwork with the ngio api, that's something I definitely plan to play around with!

This is definitely super helpful! I know they have tutorials and such but couching it in these familiar terms makes it much easier to see how to do what I'm used to doing.

The one thing I haven't been able to figure out about Wick is whether there's an easy way/if they plan to add an easy way to integrate it with other engines. Like I think being able to use Wick as the editor for your Phaser 3 game would be incredible since Phaser already has solutions to all these common problems, it just doesn't have a good IDE/visual editor.

I posted that suggestion here on their forum but got no followup https://forum.wickeditor.com/t/accessing-the-underlying-pixi-stage/1415/3?u=omarshehata

Wick is built on the PIXI.js engine, so there's probably some ways to dive deeper with that if you get into it.

As for a good Phaser IDE, you should check out https://phasereditor2d.com/

This is a great post! I was playing around with wick during the week & figured out most things except for dealing with clones etc. I never would have figured out the stuff about the first frame executing code before load().

Thanks again, I will definitely be using this in my game for the jam!