Hayolee

Villager
Member
Joined
Jan 18, 2015
Messages
28
Reaction score
0
First Language
English
Primarily Uses
Here is some code I've written:
(function(){
var dayLength = 5;
var nightLength = 500;
var currentTime = 0;
var tint_speed = 30;

var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command) {
_Game_Interpreter_pluginCommand.call(this, command);
if(command == "run"){
$gameMessage.add("Trying to work ;-;");
while(True){
currentTime = 0;
$gameScreen.startTint([0,0,0,0], tint_speed);
while(currentTime < dayLength){
currentTime ++;
print("Day-ing")

}
currentTime = 0;
while(currentTime < nightLength){
currentTime ++;
}
$gameScreen.startTint([-136,-136,-35, 70], duration);
}

}
})();
I have a parallel process event that sends the plugin command "run". I want it to be an incredibly simple day and night cycle just to get the hang of creating plugins, running them, etc. I can't seem to get this to run.
 

ShadowDragon

Veteran
Veteran
Joined
Oct 8, 2018
Messages
1,148
Reaction score
374
First Language
Dutch
Primarily Uses
RMMV
if you want to make a simple day and night cycle, you miss also initilize to be reconize what the function need to do.
the code you have is just a simple plugin command.

you have plugin command "run" but run for what?
you dont have that kind of code yet.

there are time cycles plugin with day and night, why not take a look at those?
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,048
Reaction score
10,279
First Language
Czech
Primarily Uses
RMMV
I really don't understand why wrapping plugins in self-invoking functions is so popular when it's so error prone!

Anyway, the problem is, you wrapped the plugin in a self-invoking function. So anything outside of that plugin is unable to touch it or the code inside it. Including parallel process events.

Also, you have a typo in there, Javascript doesn't use True, but true.
 

Hayolee

Villager
Member
Joined
Jan 18, 2015
Messages
28
Reaction score
0
First Language
English
Primarily Uses
if you want to make a simple day and night cycle, you miss also initilize to be reconize what the function need to do.
the code you have is just a simple plugin command.

you have plugin command "run" but run for what?
you dont have that kind of code yet.

there are time cycles plugin with day and night, why not take a look at those?
I don't want to use already created plugins because I'm trying to learn how to make them myself.

There aren't a lot of good tutorials that explain how to create plugins (like what is important to have, how to trigger them, how they should be set up), so I've just been looking at the documentation and trying to mimic code I see in other plugins.

When I said command "run" I think I was slightly confused --which might be because I started learning this yesterday at 6 o'clock. I was going into an event, pressing the command plugin, and typing in "run" and then trying to get it to work. I'm not entirely sure on the in-betweens, but it looks like I can put a function there in order to get it to start. Like, instead of putting run, have my code in a run function and typing in run(); in that command plugin box.

I'm not entirely sure on initialization because I'm not incredibly familiar with Javascript or Javascript classes. I'll look into Javascript classes and such, though, because it seems to be really useful.
 
Last edited:

Hayolee

Villager
Member
Joined
Jan 18, 2015
Messages
28
Reaction score
0
First Language
English
Primarily Uses
I've since updated the code, and this is what I have:

Code:
var tint_speed = 60;
var dayLength = 3600;
var nightLength = 1800;
var timePassed;
var startingTime = Date.now();
var isDay = true;

function update(){
    timePassed = Date.now() -startingTime;
    if (isDay = true){
        if (timePassed > dayLength){
            $gameScreen.startTint([-136, -136, -35, 70], tint_speed);
            isDay = false;
            startingTime = Date.now();
        }
    }
    else {
        if (timePassed > nightLength){
            $gameScreen.startTint([0, 0, 0, 0], tint_speed);
            isDay = true;
            startingTime = Date.now();
        }
    }
}

function run(){
    while(true){
        update();
    }
}
So, correct me if I'm wrong, but I would make this code run by doing this? Or would I need something along the lines of the game interpreter plugin commands that I had before? : upload_2019-7-27_16-5-34.png



EDIT: I found out I can do run(); in script, but now my screen is black. Why would this be happening?
 
Last edited:

Aloe Guvner

Walrus
Veteran
Joined
Sep 28, 2017
Messages
1,627
Reaction score
1,066
First Language
English
Primarily Uses
RMMV
EDIT: I found out I can do run(); in script, but now my screen is black. Why would this be happening?
It's because your plugin has:
Code:
while(true){
     update();
}
true is never false, so the loop never ends. Because the loop never ends, your "update" function is literally the only code being executed. The rest of the game code that draws the map, listens for player input, etc. never has a chance to execute.

Edit: You asked about tutorials, Poryg has some in his signature, I have one in mine, and I recommend this playlist: https://www.youtube.com/playlist?list=PLMcr1s5MjsiT4gvf-sWX8pc9VCHnHAZNS
Video #10 is creating plugin commands, so you should be familiar with the basics first (such as loops, conditionals, data types, etc.)
 
Last edited:

Hayolee

Villager
Member
Joined
Jan 18, 2015
Messages
28
Reaction score
0
First Language
English
Primarily Uses
true is never false, so the loop never ends. Because the loop never ends, your "update" function is literally the only code being executed. The rest of the game code that draws the map, listens for player input, etc. never has a chance to execute.
How can I consistently execute my update function, then? I'd like this to be running as the game itself runs.

I'm familar with loops, data types, conditionals, etc. and other logic related stuff. Maybe not entirely syntax wise in JS, though. I'm more used to Python and Java. Your tutorial had a nice bit on commands at the end that was useful.
 

Hayolee

Villager
Member
Joined
Jan 18, 2015
Messages
28
Reaction score
0
First Language
English
Primarily Uses
I'm going to call the run command in a parallel processing event and loop it there and see what happens.

I'd like to thank you guys for the help and replies. I'm at the border of knowing the basics of coding, and not knowing how to do anything at with specific APIs-- so I'm very easily lost. This is my first deep dive into writing code that's not my own from scratch. Everyone's gotta start somewhere though, so thank you for being patient. : )

Code:
var tint_speed = 60;
var dayLength = 3600;
var nightLength = 1800;
//var timePassed;
//var startingTime = Date.now();
var currentTime = 0;
var isDay = true;

function update(){
    //timePassed = Date.now() - startingTime;
    if (isDay = true){
        //if (timePassed > dayLength){
        if (currentTime > dayLength){
            $gameScreen.startTint([50, 100, 50, 70], tint_speed);
            isDay = false;
            //startingTime = Date.now();
            currentTime = 0;
        }
    }
    else {
        //if (timePassed > nightLength){
        if (currentTime > nightLength){
            $gameScreen.startTint([100, 10, 10, 10], tint_speed);
            isDay = true;
            //startingTime = Date.now();
            currentTime = 0;
        }
    }
    currentTime ++;
}

/* function run(){

    while(true){
        
        update();
        
    }
}
*/

const Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function (command, args) {
    Game_Interpreter_pluginCommand.call(this, command, args);
    if (command.toLowerCase() === "run") {
        update();
    }
 };
 

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
29,230
Reaction score
6,775
First Language
German
Primarily Uses
RMMV
How can I consistently execute my update function, then? I'd like this to be running as the game itself runs.
by not starting it yourself, but integrating it in the main game loop.
Everything that needs to happen in parallel in the game needs to become one element of that loop.

sorry, I can't tell you where that loop is in RMMV, you'll have to go through the code yourself
 

Hayolee

Villager
Member
Joined
Jan 18, 2015
Messages
28
Reaction score
0
First Language
English
Primarily Uses
by not starting it yourself, but integrating it in the main game loop.
Everything that needs to happen in parallel in the game needs to become one element of that loop.

sorry, I can't tell you where that loop is in RMMV, you'll have to go through the code yourself

I've got it working. Just have some bugs to sort out.
 
Last edited:

Zevia

Veteran
Veteran
Joined
Aug 4, 2012
Messages
622
Reaction score
330
First Language
English
Primarily Uses
RMMV
I really don't understand why wrapping plugins in self-invoking functions is so popular when it's so error prone!
It's less of a concern if you're using ES6 const and let, but a lot of Plugins are written using var declarations for compatibility with versions before 1.6.

The problem with using var outside of an IIFE is that it declares a global variable, polluting the window namespace with a lot of variables that you can't be sure someone else isn't also trying to use in their Plugin.

Best practice is to try and limit your variables to as small a scope as needed, which is exactly what the IIFEs do. If you want to expose a variable from one Plugin to another, common practice for RMMV is to declare a namespace object of the author's name and make it a property there.

For example:

Code:
(function(module) {
    'use strict';

    module.Zevia = module.Zevia || {};
    module.Zevia.someNamespacedVariable = 'I need to use this in another Plugin';

    var someLocalVariable = 'I only need this String for this Plugin and nothing else';
})(window);
Code:
(function(module) {
    'use strict';

    console.log(module.Zevia.someNamespacedVariable); // 'I need to use this in another Plugin'
    console.log(someLocalVariable); // ReferenceError: someLocalVariable is not defined
})(window);
The Zevia object is now globally available, but it's extremely unlikely that someone else is going to be adding methods, properties, or variables to it and overwriting anything I declared for my Plugins. Additionally, I'm not exposing someLocalVariable outside of my Plugin.

Using Hayolee's last posted version of the Plugin, tint_speed, dayLength, nightLength, currentTime, isDay, and the update function are now all globally declared, meaning they could be accidentally overwritten by another Plugin, or could be accidentally overwriting code from another Plugin.
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,048
Reaction score
10,279
First Language
Czech
Primarily Uses
RMMV
it's extremely unlikely that someone else is going to be adding methods, properties, or variables to it and overwriting anything I declared for my Plugins. Additionally, I'm not exposing someLocalVariable outside of my Plugin.
Your plugin maybe. But truth is, just like using var on a global level is not considered good programming practice due to the issues you've mentioned, IIFE is not considered good programming practice either, because even if it's unlikely in this particular case, you never know when someone might want to expand on it or debug it in console. I've encountered multiple plugins that I could not debug or expand, because they were wrapped in an IIFE (it was an easy fix, but still...). I have encountered multiple cases of crashes thanks to mere use of IIHF, which is not a good thing. Especially since it could be sorted out in a more concise way... Using namespaces. Or since in Javascript we don't have namespaces, using an object that holds all necessary variables inside and that we treat as a namespace. You're using Zevia namespace. So instead of var someLocalVariable you can do Zevia.pluginName.someLocalVariable. The code is cleaner, the local variable can be used outside of your plugin if need-be (I can't imagine what would I do if I couldn't do Imported.YEP_SaveCore = as I made a compatibility patch for my plugin and Yanfly's new game + plugin) and all we did was sacrifice 4 bytes of memory.
 
Last edited:

Zevia

Veteran
Veteran
Joined
Aug 4, 2012
Messages
622
Reaction score
330
First Language
English
Primarily Uses
RMMV
Making every variable publicly available is not good practice because it uses up unnecessary memory and runs a much higher risk of clobbering others' code or causing naming collisions. If you only need a variable within a function, it's better and more efficient to only cache it in memory for the duration of that function.

Caching every declared var as a property on a namespace object means more memory is being used - even if it's a small amount, it can add up over time. Declaring vars outside an IIFE or other function causes it to be a permanent property on the window.

Local variables are also quicker to type and easier to read. They clearly communicate what's a private property or local to some functionality and what's public and necessary to reference elsewhere. If you need to make a compatibility fix by changing something to be public, that's one thing, but simply exposing everything as public all the time is using up more resources to solve problems that don't exist.

I've done compatibility for several other authors' Plugins, as well, and it's never involved removing IIFEs and suddenly polluting the global namespace.
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,048
Reaction score
10,279
First Language
Czech
Primarily Uses
RMMV
Making every variable publicly available is not good practice because it uses up unnecessary memory and runs a much higher risk of clobbering others' code or causing naming collisions. If you only need a variable within a function, it's better and more efficient to only cache it in memory for the duration of that function.
It seems like you've misunderstood. I'm not really talking about every variable here. Only about variables that would be global if it wasn't for the IIFE that you've called "my local variables". Because even though they're local variables in the sense that they cannot be touched outside of the plugin, they're inside the memory at all times anyway, otherwise the plugin wouldn't be able to use them or change their values after it finished initializing.
If you put them inside a namespace, then the risk of naming collisions is rather low, because nobody is going to use your plugins and create a new namespace that has the same name as yours as long as they have a bit of sanity. The RAM consumption difference between a variable inside a namespace and a "global" variable under IIFE is 0, the only difference is the namespace, which in case of Javascript is 4 bytes if it's an object (and if it's just a prefix in the name, it's 0 again). You'd need 250 plugins, each with its own namespace, to let it be a mere 1 kb. 250.000 plugins to reach 1 MB of RAM consumption. And I think that with this amount of plugins in your game you have much bigger worries than memory.
Anyway, I think I'm going to stop here, it's off topic in relation to a thread. If you want to talk about it further somewhere else, I'm okay with it though.
 

Zevia

Veteran
Veteran
Joined
Aug 4, 2012
Messages
622
Reaction score
330
First Language
English
Primarily Uses
RMMV
Only about variables that would be global if it wasn't for the IIFE that you've called "my local variables".

If you put them inside a namespace, then the risk of naming collisions is rather low, because nobody is going to use your plugins and create a new namespace that has the same name as yours as long as they have a bit of sanity.
From Hayolee's post:
Code:
var tint_speed = 60;
var dayLength = 3600;
var nightLength = 1800;
//var timePassed;
//var startingTime = Date.now();
var currentTime = 0;
var isDay = true;

function update() {
...
Now no other Plugin can use those variables or that function name without causing problems. Your question was about why people use IIFEs to begin with, however.

Code:
(function(module) {
  'use strict';

  var tintSpeed = 60;
  var dayLength = 3600;
  var nightLength = 1800;
  var currentTime = 0;
  var isDay = true;

  function update() {
  ...
)(window);
Now those are all locally scoped to the IIFE. They might override other peoples' Plugins if they're not following good practices, but they cannot be overwritten by some other Plugin. It also clearly communicates they aren't intended to be used by other Plugins or to be changed by other peoples' Plugins.

Code:
'use strict';

var Hayolee = window.Hayolee || {};
Hayolee.tintSpeed = 60;
Hayolee.dayLength = 3600;
...
This pattern also makes it more likely that they won't clobber others' code and lowers the likelihood of others overwriting these values, but does a lesser job of preventing it. It also exposes variables and functions that others could change the value of that they normally wouldn't, as well as being ambiguous about whether they're particular to this Plugin or needed by another one.

Additionally, the latter pattern doesn't help prevent errors more than an IIFE would, except in the case of trying to reference variables you shouldn't be in the first place - which is not an issue with IIFEs, but mistakes by the developer.

In the case of the original post, the problem wasn't the use of an IIFE - the problem was not exposing the necessary functions outside it. Only the methods needed should've been visible to the window, instead of all variables and functions.
 
Last edited:

Hayolee

Villager
Member
Joined
Jan 18, 2015
Messages
28
Reaction score
0
First Language
English
Primarily Uses
Code:
/////Globals/////
var tint_speed = 60;
var dayLength = 10;
var nightLength = 5;

//////////////////////////////////////////////////////////////////

//////////////////////////DAYNIGHT CLASS//////////////////////////
//Creates DayNight Class
function DayNight(){
    this.initialize.apply(this, arguments);
}
//Initializes class variables
DayNight.prototype.initialize = function(){
    this._currentTime = this.setCurrentTime(0);
    this._isDay = this.setDay(true);
}
//Wrappers
DayNight.prototype.getCurrentTime= function(){
    return this._currentTime;
}

DayNight.prototype.setCurrentTime = function(time){
    this._currentTime = time;
}

DayNight.prototype.getDay= function(){
    return this._isDay;
}

DayNight.prototype.setDay = function(value){
    this._isDay = value;
}
//Update function

DayNight.prototype.update = function(){
    //$gameMessage.add("I'm in update");

    //Gets currentTime (should be between 0 and the value of dayLength)
    var timePassed = this.getCurrentTime();
    //Gets dayValue >>> aka is it day (dayValue= true)
    var dayValue = this.getDay();
    //If dayValue is true, meaning it's day, then...
    $gameMessage.add(timePassed);

    if ( dayValue == true){
    //Check to see if currentTime/timePassed is greater than the day length.
    //If it is greater than the dayLength, and it is day it means night should sooon fall
        if (timePassed > dayLength){
    //This tints the screen of the game to make it look like it is night
            $gameScreen.startTint([-136, -136, -35, 70], tint_speed);
    //This sets the isDay property to false, meaning it's not day anymore
            this.setDay(false);
    //We now set the currentTime to 0 because it is the 0th moment of the night
            this.setCurrentTime(0);
        }
    }
    //If it's not day, then it must be night
    else {
    //If the timePassed/currentTime is greater than the night length, then it's time for day
        if (timePassed > nightLength){
    //This tints the screen to make it look like it's day
            $gameScreen.startTint([0, 0, 0, 0], tint_speed);
    //This sets the isDay property to true because it's going to be day, now
            this.setDay(true);
    //This sets the current time to 0 because it is early in the day and we want the day to go on
            this.setCurrentTime(0);
        }
    }
    //If the timePassed is not greater than eitehr the night or day lengths, then
    //We set it the current time = to the currentTime + 1
    var newTime = this.getCurrentTime() + 1;
   
    this.setCurrentTime(newTime);
    $gameMessage.add(this.getCurrentTime());
}

/////////////////////////////////////////////////////////////////////////////////



//This is how we run the plugin command
const Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function (command, args) {
    Game_Interpreter_pluginCommand.call(this, command, args);
    if (command.toLowerCase() === "run") {
        //$gameMessage.add("In the run.");
        DayNight.prototype.update();
    }
 };
I was considering changing it to prototype inheritance, but it wasn't running or initializing I don't believe. I do plan on changing the globals, but.... for now I'd like to understand why this inheritance isn't initializing. The message of "timePassed" is NaN.
 
Last edited:

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,048
Reaction score
10,279
First Language
Czech
Primarily Uses
RMMV
I recommend you to take a C++ course to learn how object oriented programming works.
You cannot call a function from a class prototype, you have to call it from a concrete object that's an instance of a class.
So the
Code:
//This is how we run the plugin command
const Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function (command, args) {
   Game_Interpreter_pluginCommand.call(this, command, args);
   if (command.toLowerCase() === "run") {
       //$gameMessage.add("In the run.");
       DayNight.prototype.update();
   }
 };
is not going to run properly thanks to the
DayNight.prototype.upgrade.
 

Aloe Guvner

Walrus
Veteran
Joined
Sep 28, 2017
Messages
1,627
Reaction score
1,066
First Language
English
Primarily Uses
RMMV
this._currentTime = this.setCurrentTime(0);
this._isDay = this.setDay(true);
These line won't work as you expect, because the "setDay" function and "setCurrentTime" doesn't return a value.

What happens is you are assigning a variable to the return value of that function. But there is no return value. So the variable gets set to "undefined". Then when you try to do a mathematical operation on undefined, you get the NaN error.
Either return a value or don't do the variable assignment there.

Edit: added some more description
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,048
Reaction score
10,279
First Language
Czech
Primarily Uses
RMMV
Well, that's why I don't like to use getters and setters :D
 

Hayolee

Villager
Member
Joined
Jan 18, 2015
Messages
28
Reaction score
0
First Language
English
Primarily Uses
Javascript is upsetting.


Code:
DayNight.prototype.update = function(){
    $gameMessage.add("I'm in update");
  
    //If dayValue is true, meaning it's day, then...
    $gameMessage.add(this._currentTime);

    if ( this._isDay == true){
    //Check to see if currentTime/timePassed is greater than the day length.
    //If it is greater than the dayLength, and it is day it means night should sooon fall
        if (this._currentTime >= dayLength){
    //This tints the screen of the game to make it look like it is night
            $gameScreen.startTint([-136, -136, -35, 70], tint_speed);
    //This sets the isDay property to false, meaning it's not day anymore
            this._isDay = false;
    //We now set the currentTime to 0 because it is the 0th moment of the night
            this._currentTime = 0;
        }
    }
    //If it's not day, then it must be night
    else {
    //If the timePassed/currentTime is greater than the night length, then it's time for day
        if (this._currentTime >= nightLength){
    //This tints the screen to make it look like it's day
            $gameScreen.startTint([0, 0, 0, 0], tint_speed);
    //This sets the isDay property to true because it's going to be day, now
            this._isDay = true;
    //This sets the current time to 0 because it is early in the day and we want the day to go on
            this._currentTime = 0;
        }
    }
    //If the timePassed is not greater than eitehr the night or day lengths, then
    //We set it the current time = to the currentTime + 1
    this._currentTime ++;
}
Even after I took out the getters and setters entirely it still is NaN.


BUT, regardless of this one. The other less modularized version where I don't use any type of inheritance works. I absolutely hate inheritance in Javascript.


I also do plan on using along the lines of:


Code:
'use strict';

var Hayolee = window.Hayolee || {};
Hayolee.tintSpeed = 60;
Hayolee.dayLength = 3600;
I am just waiting until I get it completely functional before I improve it.
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Would you pay monthly for your pc if you'd get "free" upgrades every 2 years?
well, I definitely have a type, cute redheads with medusa piercings, met and hit it off with two of them in the last 72 hours, what does it mean lol?
Damian Floyd increased the grand prize for the Driftwood Jam to a $75 steam GC!!! Thank you Damion! :)
Is everybody using their imagination?
5th Annual Driftwood Jam! $25 Steam gift card grand prize :D https://itch.io/jam/5adj

Forum statistics

Threads
94,421
Messages
920,832
Members
124,219
Latest member
mrzo
Top