Udostępnij za pośrednictwem


Construct 2 Tip #4: Round Tripping With Event Variables

In a previous post, I showed how you could extend Construct 2’s generated Visual Studio project to add your own custom Settings flyouts. In this post, I’m going to take things one step further and show how to have controls on the Settings flyout interact with the game itself! After all the Settings Charm (along with the App Bar) are key differentiating features of Windows 8, and the apps that are able to leverage them the best are the ones that shine on the platform – and attract the users.

To be clear, Construct 2 has a rich plug-in ecosystem, including the Windows 8 plug-in that offers multiple integration points with the native capabilities of the platform, like sharing contracts, in-app purchases, roaming storage and more, but those mostly reach out to Windows 8, and sometimes you want to reach in to affect the game loop itself.Physics Puzzle template

In this simple exercise, I’m going to create a Settings flyout that allows the user to modify the background color of a running game (the Physics Puzzle template that’s provided “in-the-box” with Construct 2), but you should be able to take the technique and offer additional controls and customizations that are specific to your own game.

As you probably know by now, everything you write in Construct 2 is contained in a JavaScript file (c2runtime.js) and a simple HTML page (index.html) when you export the project to Visual Studio, one of the steps for publishing to the store.

The index.html file was the target of my previous customization, and for this one I cracked open the c2runtime.js file to see what some of the potential integration points are. While the file is large and the contents daunting, it was clear from the HTML file that there was a Construct 2 “runtime” object, and it didn’t take long to find a few valuable items in that file

  • cr_getC2Runtime is a global function that gets a handle to the runtime object that Construct 2 provides
  • all_global_vars, a property of the runtime object, is a collection of the global “event variables” in your Construct 2 event scripts
  • each event variable has a getValue and a setValue method

So armed with that information, it’s not difficult to write script that accesses the runtime and gets or sets variables that are defined within the Construct 2 game iself!

Create a (Global) Event Variable in Construct 2

First though, you need to expose the functionality you want to tweak as a global variable and include events in the Construct 2 game to react to potential changes.

For the physics puzzle template, the background layer had a default color provided as a property, so I simply created a new global variable (BackgroundColor) and set the layer color to it on every game loop iteration. This means the color will change “live,” but you could also have modifications only kick in when the game restarts (perhaps wiring to the On start of layout system condition ).

Script to wire layer color to event variable

Create a Settings Flyout HTML page

Next I created a SettingsFlyout page with a control to modify the color. There are a host of JavaScript color picker options out there, but I wanted something quick and lightweight for this sample, so I opted for JSColor, which is functional but does need a bit of tweaking for production use in Windows 8. That said, the markup for creating a new Customize flyout using the control couldn’t have been simpler:

 <!doctype HTML>
<html>
<head>
    <title>Credits</title>

    <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet">
    <script src="/jscolor/jscolor.js" type="text/javascript"></script>
    <script src="/customize.js" type="text/javascript"></script>

</head>
<body>
    <div id="divGamePreferences" data-win-control="WinJS.UI.SettingsFlyout"
        data-win-options="{settingsCommandId:'customize', width:'narrow',
            onbeforeshow: customizer.init }">

        <div class="win-ui-dark win-header">
            <button type="button" onclick="WinJS.UI.SettingsFlyout.show()" 
                class="win-backbutton"></button>
            <div class="win-label">Customize</div>
        </div>

        <div class="win-content">
            <p class=".win-type-x-large">Game Background Color</p>
            <input id="colorText" style="margin: 10px" />
        </div>
    </div>
</body>
</html>

Write the Code Behind the Settings Flyout

Key to the functionality of the HTML above is the code-behind script provided in customizer.js, specifically the init method that fires before the flyout is shown. Some sample code follows that demonstrates the technique. Warning: to keep things focused for this article, there is no error checking (which you should of course add); for instance, if the global variable named BackgroundColor does not actually exist in the Construct 2 game, you’ll get a null reference and crash!

Here’s the code (using the JavaScript module pattern that’s prevalent in WinJS applications) followed by a line-by-line walkthrough; you might want to open a second browser page to correlate the code with the explanatory text.

    1:  var customizer = (function () {
    2:      "use strict";
    3:   
    4:      var t = {};
    5:   
    6:      //flip the RGB components 
    7:      function flipRGB(colorIn)
    8:      {
    9:          var part1 = colorIn & 0xFF0000;
   10:          var part2 = colorIn & 0xFF00;
   11:          var part3 = colorIn & 0xFF;    
   12:   
   13:          return (part3 << 16) | part2 | (part1 >> 16);
   14:      }
   15:   
   16:      // get reference to global by name
   17:      function getConstruct2Global(varName) {
   18:          var allGlobals = cr_getC2Runtime().all_global_vars;
   19:          for (var i in allGlobals)
   20:              if (allGlobals[i].name === varName) {
   21:                  return allGlobals[i];
   22:              }
   23:      }
   24:   
   25:      // get background color
   26:      t.getBackgroundColor = function () {
   27:          var backgroundColor = getConstruct2Global("BackgroundColor");
   28:          return flipRGB(backgroundColor.getValue());
   29:      };
   30:   
   31:      // set background color
   32:      t.setBackgroundColor = function (newColor) {
   33:          var backgroundColor = getConstruct2Global("BackgroundColor");
   34:          return flipRGB(backgroundColor.setValue(flipRGB(newColor)));
   35:      }
   36:   
   37:      // initialize flyout
   38:      t.init = function () {
   39:   
   40:          jscolor.init();
   41:   
   42:          var colorPicker = new jscolor.color(
   43:              document.getElementById("colorText"), {});
   44:          colorPicker.fromString(t.getBackgroundColor().toString(16));
   45:   
   46:          colorPicker.onImmediateChange = function () {
   47:              t.setBackgroundColor(parseInt(colorPicker.valueElement.value, 16));
   48:          }
   49:      }
   50:   
   51:      // required to allow function to be invoked in setting flyout event
   52:      t.init.supportedForProcessing = true;
   53:   
   54:      return t;
   55:  }());
Line 1 Create the customizer object referenced in the settings HTML page (customize.html)
Line 7 Implement a byte swapper since it appears that Construct 2 color values are in BGR form and WinJS is expecting RGB (or vice versa!)
Line 16 Wrap the Construct 2 runtime functions to get the Construct 2 event variable object with a given name. This is where the ‘magic’ is, but do note it’s a bit fragile, since it simply returns a null if the script variable isn’t found.
Line 26 Access the global variable BackgroundColor and return its value interpreted as a color that WinJS understands (i.e., run it though the byte flipper routine in line 7)
Line 32 Access the global variable BackgroundColor and set its value interpreted to a color that Construct 2 understands (i.e., run it though the byte flipper routine in line 7). Since the Construct 2 script has an event On every tick that changes the game background, it will pick up the new value on the next iteration of the game loop and update accordingly.
Line 38 Initializer for the settings flyout; this is the method referred to in the onbeforeshow property of the Flyout object in the HTML file shown above.
Line 40 Initialize the JSColor object. If using a different color input mechanism, substitute whatever that control requires.
Line 42 Create a JSColor picker using the colorText input tag provided in the HTML file. That input element will show the hexadecimal value of the color and spawn a palette control to select other colors.
Line 44 Get the current background color and set the current value of the color picker to it. This handles showing the right color when the settings flyout is opened.
Line 46 As the user interacts with the JSColor control set the BackgroundColor event variable in Construct 2. Given the Construct 2 script is checking that variable on every game loop iteration, the background color will update in real time. onImmediateChange is an event on the JSColor control, so if you are using a different way to modify the color value (or any value), you’ll need to decide how to trigger the call to set the Construct 2 variable.
Line 52 You’ll need this – trust me.

Take Your Victory Lap!

And here's what I ended up with. Now I could even tap into the system time, do a web service call to figure out how close to dawn/dusk it is and adapt the background of the game to my local environment - how cool would that be... or I could just change it to a lovely shade of fucshia, like below!

Construct 2 game customizable from Windows 8 Settings Charm