Reset Frame

I’ve got a game where each level is contained in its own frame. I was hoping that if I leave a frame, and then go back to it, the frame would have reset. Instead, everything stays as it was when I left the frame. Is there any sort of built in function that can reset the frame, or will I have to reset everything in the frame manually?

Thanks for any help!

2 Likes

I think it’s actually a cool feature that you can leave a frame and then come back to it the way it was, as long as there’s a function to reset it.

I agree, it has a lot of potential, but still if there’s a built-in way to reset the frame that would be great!

3 Likes

A very long time ago, there was actually a checkbox for frames in the inspector for this. The option was “save frame state”, and by default it was checked iirc.

Putting this checkbox back is definitely an option. We’ve also had a few requests to be able to do this through code with something like frame.reset() for example.

Thoughts? :open_mouth:

2 Likes

I actually,on a whim, tried using

frame.reset()

and a number of similar variations, all of course to no avail. I’d love to have a function like that, it would be perfect not just for my project, but especially for projects with mechanics reminiscent of old arcade games!

Seems like a great idea to me!

2 Likes

I agree with @GoodL, the function’s a great idea! In that case, there wouldn’t really be a need for a “Save Frame State” checkbox since you could just add the reset code to Load() if you want the frame to reset every time it’s accessed.

Two questions:

  • Would resetting a root timeline frame change all variables (whether tied to a Clip/Button or not) to whatever they were the last time frame was entered? If so, someone making a simple arcade game would need to store stuff like scores or lives using sessionStorage or localStorage. (Assuming she has the frame reset every time the player loses a life.)

  • Would Clips be able to reset their frames? In Flash, the root object is basically a big MovieClip, so MovieClips and _root have similar abilities. I think it makes sense for Wick to work like this as well. I sometimes wrap a lot of elements within a symbol/Clip so it’d be great to still access the reset functionality.
    That means I don’t have to use sessionStorage or localStorage, because I can put the arcade game within a Clip and reset THAT when I need to, and it wouldn’t affect the root timeline’s properties.

Examples of how this could look in the API:
project.resetFrame();
project.resetAllFrames();
clip.resetFrame();
clip.resetAllFrames();

1 Like

Any chance someone could help me setting up my manual reset? I’m trying to reset each of my game object’s positions. It’s working great when I put this in the update for each object that needs to be reset:

if(resetting === true){
var dirX = startX - this.x;
var dirY = startY - this.y;
this.x += dirX;
this.y += dirY;
}

(I set the startX and startY variables at runtime). The issue here is that I really don’t want every single object to be running an update function. I have each object stored in an array called levelObjs, and I figure I should be able to do the resetting with that but I’m having issues. I’ve tried two things.

For the first method, in my frame’s script I tried doing the same as the above method but using the array like this:

if(resetting === true){
for (let i = 0; i < levelObjs.length; i++) {
levelObjs.forEach(reset);
}
}

function reset(obj){
var dirX = obj.startX - obj.x;
var dirY = obj.startY - obj.y;
obj.x += dirX;
obj.y += dirY;
}

This method makes all of the objects in levelObjs disappear. Logging their positions in the console gives me “NaN”.

Next, I tried putting the reset logic in a function in each object called “resetMe()” and tried this in the frame script instead:

if(resetting === true){
for (let i = 0; i < levelObjs.length; i++) {
levelObjs.resetMe();
}
}

This feeds me an error saying that “resetMe()” doesn’t exist… even though it does exist in each level object. I tried doing it like the last method too, with a “forEach” function, then calling it with obj.resetMe() in there, but the same thing happens. I don’t know if I need to do something differently in order to make the resetMe() function to be “public” or something.

Any advice helps, thank you!

Is resetMe(); defined in the same scripting tab as the place where you call it? There is currently a bug where a function defined in one tab cannot be called in others. The bug also applies to frames, meaning a function declared in frame 1 can’t be used in frame 2. More details here.

Edit: You might find the Wick scripting tips from these articles useful. The first one primarily applies to the legacy version.


4 Likes

@kryptot7, great idea linking those psychogoldfish tutorials. They are extremely helpful!

@GoodL, I put together a quick Wick Editor 1.0 project that resets several named objects on a frame that were added to a list. Let me know if this is good enough for your needs! Happy to edit/update this with you.

ResettingNamedObjectsOnAFrame.wick (14.3 KB)

All of the main logic code is on the first frame. You can just copy what I have in there to save and reset x,y,scaleX,scaleY, and rotation.

Here’s a full explanation of what I’m doing.

First, I create an array of named objects

project._frame1Objects = [clip1, clip2];

Next, I go through each of these objects and store their original information. The if statement ensure that this is only done once (when I don’t have any info saved yet).

// If I haven't stored my object data yet...
if (project._frame1Objects.length > 0 && !project._frame1Objects[0].__startingInfo) {
    // Go through each objec and save that object's info...
    project._frame1Objects.forEach(function(object) {
        var objectInfo = {}; // Create a dummy to fill.
       
        // Store every value you want to remember...
        // CHANGE THIS IF YOU WANT TO RESET MORE OR LESS!
        objectInfo.x = object.x;
        objectInfo.y = object.y;
        objectInfo.opacity = object.opacity;
        objectInfo.rotation = object.rotation;
        objectInfo.scaleX = object.scaleX;
        objectInfo.scaleY = object.scaleY;
       
        // Store this info alongside the 
        object.__startingInfo = objectInfo;
    });
}

`
Then, in Load, I have a function which goes through each of the objects in my original array and resets all of the keys I’ve saved.

// Go through all of the info we saved and reset it...
project._frame1Objects.forEach(function(object) {
    // If we didn't save any info, just stop the operation.
   if (!object.__startingInfo) return;
   
   // Go through every item individually and reset it in the object.
   Object.keys(object.__startingInfo).forEach(function (key) {
       object[key] = object.__startingInfo[key];
   });
});

I use __ and _ in front of variable/property names to try and avoid collisions with internal wick editor stuff!

We will definitely be adding this reset feature in the future. so hopefully soon this will be entirely unnecessary. Thanks for your patience!

3 Likes

I’m aware of the issue with not being able to call functions between different tabs. I was a big supporter of bringing in the “Default” tab though, and I use it almost exclusively. I’ve yet to find a reliable way of calling functions between different objects though.

About the PsychoGoldfish newsposts - I’ve actually read them each a few times, and even shared em around with other people! I came here from Newgrounds actually, and yeah those write-ups are super helpful. I’d recommend anyone check them out. PsychoGoldfish is a great guy.

Thanks a lot for the recommendations! Luxapodular’s example project seems like it should work perfectly for me, so I’ll give that a shot next time I’m working on the game.

I appreciate it everyone!

5 Likes

Good news! The reset system you wrote up, along with some slight tweaks here and there to make it fit my project, is working great for what I needed. Thank you so much!

Bad news! I’m now experiencing my strangest issue yet. It seems like every time I leave the frame where my level is held, and then return to it the tick speed of the game engine speeds up? I’m not confident in the phrasing there so I’ll try to explain what’s going on.

I’ve got a character that the player controls, and some enemies that move around. If the player collides with an enemy, their health decreases. Upon reaching 0 health, the game goes to another frame saying “game over, try again?”, with a button that takes the player back to the previous frame where the gameplay takes place. That’s when the resetting occurs, which seems to be functioning as intended.

However, upon returning to the first frame, it seemed like all of the global variables were increased, possibly doubled. The player moves incredibly fast, as do the enemies. The player’s jump height is practically enough to send them into orbit. The gravity (which I use to control player jumps) is now exceptionally fast, to the point that it doesn’t look like the player is falling, so much as they’re phasing between planes of existence (and after a few “resets”, just falling straight through my ground objects and my “killzone” without detecting collision at all).

My first thought was that perhaps I had something that was adding to the global variables (something along the lines of speed += 5, or something to that effect) on load, but after digging around that doesn’t seem to be the case, so I decided in the update of my frame script I would console log the speed variable just to see what’s going on.

So, watching the speed variable get logged on every tick shows that it isn’t changing after resetting. Instead, it seems to be that every time I reset, the number of times the variable is logged in the console per second is rapidly increasing, as if the frame rate of the game was somehow increasing, causing the variable to be logged many more times per second with each reset, as compared to the first run.

I have no idea what would be causing this, and I’m not sure that there’s really anything anyone can do to help. I know it would be easier for people to figure out what’s going on if I uploaded my .wick file, but I’ll be totally honest, I don’t want to do that because I know that it’s absolutely atrocious. There’s all kinds of whacky code all over the place, none of it is commented, and it would probably cause anyone who saw it nightmares for decades. Frankly I’d just be too embarrassed to have people see it.

Anyway, I guess I’m mostly just posting this to vent about my own programming inadequacies. Hopefully I can find some work-around for this issue before the game jam deadline. Wish me luck, friends!

edit: Tried console logging the project frame rate. It is not increasing.

2 Likes

@GoodL THIS IS NOT YOUR FAULT, IT’S A BUG! Thank you for the detailed report as I have found the issue and a workaround.

You’ve just found a bug with the onEvent() system. We’ll put this on our board to get fixed.

(Also, don’t feel bad about your work. No matter how ‘bad’ you think it is, I know for a fact that since you were able to articulate the problem this well, you’ve been doing a good job organizing it for your own use :slight_smile:.)

Since objects and frames are not resetting, every onEvent('event', ()...) call is adding an additional event script to the object, adding multiple event handlers when you re-enter the frame.

As a stop-gap fix, you can do something like this.

FOR OBJECTS

// Only run events if we havent been here before.
if (!this._alreadyCreatedEvents) {
    onEvent('mousedown', function () {
      console.log("Mouse");
    });
    // Add all my onEvent functions.
}

// Keep this on the bottom, after adding the if statement!
this._alreadyCreatedEvents = true;

FOR FRAMES

// Only run events if we havent been here before.
if (!this.parentFrame._alreadyVisitedThisFrame) {
    onEvent('keydown', function () {
      console.log("key");
    });
    // Add all my onEvent functions.
}

// Keep this on the bottom, after adding the if statement!
this.parentFrame._alreadyVisitedThisFrame = true;

Let me know if this helps.

I bet your game is gonna be awesome. :metal:

3 Likes

Thanks for the kind words! I’m relieved to know it’s not just me being a goober. I’ll have to try playing around with this fix more after work, but so far just putting in what you’ve written above gives me this error:
error
Seems that the “parentFrame” of the frame that the scripts are housed in is null. Does a frame have a parent frame?

1 Like

Hmm, what frame is it (number) and what tab is this code being added to?

2 Likes

In this case it’s frame 5 and everything is under Default. I wrapped the if statement around the events (namely Update and Load, and it’s the one if statement wrapped around both).

1 Like

And this wraps just the onEvent calls correct? What do you get when you console log the this;

try adding console.log(this) right above the line that’s causing the issue.

2 Likes

I’m on mobile right now so I apologize if the formatting gets nasty or anything (the code is also likely to be syntactically incorrect as I’m typing it out here, it should be correct in the real code though since it all works without the if statement). Basically the script in my frame looks like this:

variable declarations
if (!this.parentFrame._alreadyVisitedThisFrame) {
onEvent(‘load’, function(){
some stuff happens here;
})
onEvent(‘update’, function(){
some stuff happens here;
})
}
this.parentFrame._alreadyVisitedThisFrame = true;
someMoreNonEventFunctions();

I’ll try logging it when I get home tonight but I don’t know what I’ll be looking for there. Logging objects and frames makes huge console outputs.

Edit: I threw the console.log(this) in there, and as expected, the console output is huge. It shows me the list of all of the objects on the frame and a bunch of collapsible categories, not really sure where I should begin looking for issues there.

Edit 2: To be clear, the line causing problems is not the if statement itself, but trying to set the variable afterwards. This:

this.parentFrame._alreadyVisitedThisFrame = true;

is what’s null.

Edit 3: It just dawned on me that I should be able to just assign that variable in the frame, right? I’m going to try it as just “_alreadyVisitedThisFrame” instead of “this.parentFrame._alreadyVisitedThisFrame” and see what happens.

Edit 4: no wait that just disables all of my game logic (like the gravity, for example) because the update only runs if “_alreadyVisitedThisFrame” is false, but it’s set to true right after that if statement, meaning it probably runs for a fraction of a second but then it’s disabled. :frowning:

Edit 5: The same happens for the objects as well. I’m able to run it normally once with the if statement wrapped around the events on the objects such as the player and the enemies, but then trying to run it again (even as in stopping the project and restarting it) causes everything to stop running, requiring me to refresh the editor to get another run.

1 Like

I think for now I’m just going to disable resetting. It’s unfortunate because if a player ever fails a level they will have to refresh the page to retry, but as soon as the reset level function is added to Wick I can go in there and fix it so it shouldn’t be a big deal.

I know how you feel, I faced the same problem in Flash. For some reason the variables caused some interactions to break whenever I tried to reset my little game, so I ended up just telling the user to refresh at the end :stuck_out_tongue:
I’m really glad Wick is innovating to fix Flash’s old shortcomings!

2 Likes

I’m really glad Wick is innovating to fix Flash’s old shortcomings!

I couldn’t agree more!

2 Likes