Howto:Basic OOP Programming: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
First, we need to define some variables:
First, we need to define some variables at the very beginning of the nasal file. This improves performance, since if you use "var" inside a loop, it degrades performance: '''the variable is recreated every time the loop is run!'''.
 
<syntaxhighlight lang="nasal">
<syntaxhighlight lang="nasal">
# Define variables here to prevent them being recreated at every run of the loop() function
# Define variables here to prevent them being recreated at every run of the loop() function
Line 7: Line 8:
</syntaxhighlight>
</syntaxhighlight>


Then, we need to create the class for the screen:
Then, we need to create the class for the screen: we define some attributes, then add a function that calculates the power consumption. Finally, at the end we have the '''constructor''' which can be used to create the object over and over by simply running screen.new(); with the attributes defined inside the brackets.
<syntaxhighlight lang="nasal">
<syntaxhighlight lang="nasal">
var screen = {
var screen = {

Revision as of 20:50, 10 December 2017

First, we need to define some variables at the very beginning of the nasal file. This improves performance, since if you use "var" inside a loop, it degrades performance: the variable is recreated every time the loop is run!.

# Define variables here to prevent them being recreated at every run of the loop() function
var power_consumption = nil;
var screen_power_consumption = nil;
var screens = nil;

Then, we need to create the class for the screen: we define some attributes, then add a function that calculates the power consumption. Finally, at the end we have the constructor which can be used to create the object over and over by simply running screen.new(); with the attributes defined inside the brackets.

var screen = {
        # first, create the attributes of the screen
	name: "",
	type: "", 
	max_watts: 0,
	dim_watts: 0,
	dim_prop: "",

	power_consumption: func() { # next we have a function that measures the power consumption and returns it
		var dim_prop = me.dim_prop;
		if (getprop(me.dim_prop) != 0) { # if the screen is not off
			screen_power_consumption = (50 + (10 * getprop(dim_prop))); # y = 50 + 10d, where d = the value of the dimming property.
		} else { # if the screen is off, it consumes no power.
			screen_power_consumption = 0;
		} 
		return screen_power_consumption; # this means that when you run this function, you will get a value returned to you.
	}, # power_consumption()

	new: func(name,type,max_watts,dim_watts,dim_prop) { # finally the creator function, that creates instances of the class
		var s = {parents:[screen]};
		
		s.name = name;
		s.type = type;
		s.max_watts = max_watts;
		s.dim_watts = dim_watts;
		s.dim_prop = dim_prop;
		
		return s;
	}, # new() constructor 
};

Next, we create a new object called ELEC.

In the first part, we have a function called whenever the FDM initialization is complete: inside it, various instances of the screen class are created using the new() constructor. Then, in the second part, we have a loop function that actually does the hard work of calculating the power consumption per screen.

var ELEC = {
	init: func() { # initialization function
              # Create the instances of the screen class, and add them to a vector in order to use a foreach loop
              screens = [screen.new("DU1","LCD",60,50,"controls/lighting/DU/du1"),
			screen.new("DU2","LCD",60,50,"controls/lighting/DU/du2"),
			screen.new("DU3","LCD",60,50,"controls/lighting/DU/du3"),
			screen.new("DU4","LCD",60,50,"controls/lighting/DU/du4"),
			screen.new("DU5","LCD",60,50,"controls/lighting/DU/du5"),
			screen.new("DU6","LCD",60,50,"controls/lighting/DU/du6")]; 
        },
        loop: func() {
               foreach(var screena; screens) {  # note that we use a different variable, screena
			power_consumption = screena.power_consumption(); # call the power_consumption() for each instance of the screen class
			setprop("/systems/electrical/DU/" ~ screena.name ~ "/watts",power_consumption); # write the result to a property
	       }
        },
};

Finally, we add the updating function: the following code creates a maketimer and a setlistener that execute the loop(); and init(); functions respectively:

var Loop = maketimer(0.1, func {
ELEC.loop(); # runs the loop(); function every 0.1 seconds
});

var l = setlistener("/sim/signals/fdm-initialized", func { # listens to this property. When it changes, the following lines are run, then the listener is removed.
   ELEC.init(); # run the init loop to set things up
   timer.start(); # start the timer.
   removelistener(l); # ensure that the listener only runs once to improve performance
});


This is a basic example of OOP. This code should be reasonably standalone, in that it should work without depending on other code. For instance, to make a test of the code, you could setprop the DU dimming properties at the beginning of the file to reasonable values, as follows, then run it using the UFO. Or, in the Nasal console, you could just copy the first three code snippets and the maketimer to the console (ie skipping the setlistener), then add this at the bottom and execute.

ELEC.init();
timer.start();
setprop("/controls/lighting/DU/du1", 0.5);
setprop("/controls/lighting/DU/du2", 0.6);
setprop("/controls/lighting/DU/du3", 0.9);
setprop("/controls/lighting/DU/du4", 0.1);
setprop("/controls/lighting/DU/du5", 1.0);
setprop("/controls/lighting/DU/du6", 0.4);

If you then hooked up these properties to 3D knobs in any aircraft you could control the dimming and thus the power consumption by rotating the knobs.