StarWarsMod4AirMash

Ships

StarMash - Extensions and Themes - Part 4 - Themes

This is a guide for the creation of extensions and themes for the StarMash Mod for AirMash.

Read this if you are interested in creating your own features and themes for AirMash.

This is part 4 of a multi-part tutorial.

StarMash - Extensions and Themes - Part 1 - Introduction.

StarMash - Extensions and Themes - Part 2 - Basic Extension.

StarMash - Extensions and Themes - Part 3 - Settings.

StarMash - Extensions and Themes - Part 4 - Themes

StarMash - Extensions and Themes - Part 5 - Advanced Themes.

 

In part 4, you will learn:

 

Themes with almost no coding?

If you are planning on making the most simple Themes for StarMash, you shouldn’t worry too much about how AirMash’s internals work.

All you need to do is replace a few image files, use a Theme template I will provide and be done with it.

Let’s start with that and then, if you are interested in building something more advanced, or you are just curious about how AirMash works, keep reading the following sections.

First of all, we need to know the assets used by AirMash. Those are the image files that AirMash code loads when the game starts. AirMash then divides those images in smaller parts, called Textures that are in turn used to create Sprites (which are objects composed of Textures, that can be moved and interacted with on the screen).

The images are:

aircraft.png

items.png

shadows.png

gui.png

map_forest.jpg
map_rock.jpg
map_sand.jpg
map_sea.jpg

map_rock_mask.jpg
map_sand_mask.jpg

map_sea_mask.jpg

mountains.png

particles.png

flagsbig.png

So, in order to create your own themes, you need to decide which file you want to modify.

The most common files to edit are: aircraft and shadows, items, gui and map_forest/rock/sand. That’s why I will leave you here some images that you can use as guides when editing those files.

aircraft-guide.png
gui-guide.png
items-guide.png
shadows-guide.png

When editing an image (like aircraft.png) using an application like Photoshop or Gimp, you can load those images as layers, to have a reference for the limits of each texture.

Also, in the case of aircraft.png, you can see with this reference image the circles used by AirMash’s server for collision detection. While it’s not required to keep your own planes perfectly within those circles, it’s better to at least preserve the general dimensions and shape. That’s because those collision circles are checked on the server, so we can’t edit them.

 

In this tutorial, we will use two special themes as a very simple examples:

Example: Christmas Theme - Replacing all image files

If you have some knowledge about Object Oriented Programming, you most probably know terms like inheritance, derived classes and extension. But if not, I’ll just leave you a super short paragraph from Wikipedia:

Inheritance in most class-based object-oriented languages is a mechanism in which one object acquires all the properties and behaviours of the parent object. Inheritance allows programmers to: create classes that are built upon existing classes, to specify a new implementation to maintain the same behaviour (realizing an interface), to reuse code and to independently extend original software via public classes and interfaces. An inherited class or derived class is called a subclass of its parent class or super class.

Why do I mention this now? Because this is how new Themes are created in StarMash. Inheriting from a base Theme class.

StarMash provides four base Theme classes that you can inherit from:

Let’s take a look at Christmas 2017 Theme’s code:

// ------------------------------------------------------------------------
//   Christmas Theme for StarMash
// ------------------------------------------------------------------------
"use strict";

!function()
{
    // Returns the filename part of an AirMash's image URL
    function getFileName(str)
    {
        str = str.substring(str.lastIndexOf('/')+1);
        if (str.indexOf("?")>-1)
            str = str.substr(0, str.indexOf("?"));
        return str;
    }

    // ------------------------------------------------------------------------

    // Theme Function
    // This theme inherits from VanillaTheme, so we call VanillaTheme's constructor
    // when this theme is instantiated.
    class Christmas2017Theme extends VanillaTheme
    {
        //constructor() {
            //super();
            //my initialization code goes here, after calling super()
        //}

        // This method called by StarMash when the game is loading
        injectTextures(files, textureInfo, flagTextureInfo, spriteInfo, textures) 
        {
            for(let i in files)
            {
                //files[i] = "//localhost/Christmas/" + getFileName(files[i]);
                files[i] = "//raw.githubusercontent.com/Molesmalo/AirMashChristmasMod/master/assets/" + getFileName(files[i]);
            }
        }
    }

    // We add some metadata to our theme class
    $.extend(Christmas2017Theme, {
        themeName: "Christmas 2017 Theme",
        description: "A christmassy theme for StarMash!!",
        author: "Bombita"
    });

    // ------------------------------------------------------------------------

    // Register our extension and theme
    SWAM.registerExtension({
        name: "Christmas 2017 Theme Extension",
        id: "Christmas2017",
        description: "Happy holidays and merry Christmas!",
        author: "Bombita",
        version: "1.0",
        themes: [ Christmas2017Theme ]
    });
}();

Download the file

If you followed Parts 1, 2 and 3, I hope this code will be easy to follow.

It starts by creating our module. Inside our module, we create a helper function called getFileName that takes a url, and returns the file part.

Next, create a new class called Christmas2017Theme that inherits from VanillaTheme. We could have inherited from BaseTheme if we wanted a more basic parent so we could define for example our own SettingsProvider and tinting/coloring for missiles and players. But for now, VanillaTheme is best for us.


Theme constructor

Now, check these lines:

    //constructor() {
        //super();
        //my initialization code goes here, after calling super()
    //}

Those are the lines for the constructor method of our class. In our example we don’t need any initialization code for this theme, that’s why those lines are commentated.

But here is the place to put our initialization code in case we need it. We would need it, for example, to create our own SettingsProvider for the theme (both the theme and the extension can have their own SettingsProvider). It’s similar to what we learned in Part 3, but instead of offering settings for the whole extension, it offers for the theme (and it’s not show when the theme is not loaded). It would look something like this:

    constructor() {
        super();

        let sp = new SettingsProvider(
            {  /* some default values here */ }, settingsApplied);
        
        // *** we then add all the fields like we saw in Part 3 ***

        // We assign a custom settingsProvider to our theme
        this.settingsProvider = sp;
    }

Just in case you forgot, or you didn’t read Part 1, Part 1 - StarMash Life Cycle, I’ll remind you that a Theme instance is created even before any code for the game is loaded and executed.

But again, those lines are commentated because our class does not need any initialization code. So, it’s super() (the constructor for VanillaTheme in this case) is automatically executed.


Continue reading the example code. Our theme class then defines a method called injectTextures that takes the following parameters:

Inside this method, we iterate over all the URLs of the images that are going to be loaded, get their file name using our helper function getFileName, and change the URL to point to another file that we have previously uploaded to some server.

Note: In the example above, we set the URLs to //raw.githubusercontent.com/...... Pay attention to the start of that URL. The // indicates that we want to preserve the protocol used by the page. As airma.sh is served using HTTPS, we are telling the browser that we will also use HTTPS. But sometimes, when developing on a local server, you might not want to enable HTTPS locally. In those cases, make sure to provide the protocol in the URL, e.g.: http://localhost/assets/. Just remember that is advisable to serve under HTTPS when deploying your files to other users. Otherwise, some security warnings will be displayed by the browser.

Then, we add some metadata to our Theme class. Here, I’m using jQuery’s extend method for brevity, whose use (for this case) is similar to doing:

// We add some metadata to our theme class
Christmas2017Theme.themeName = "Christmas 2017 Theme";
Christmas2017Theme.description = "A christmassy theme for StarMash!!";
Christmas2017Theme.author = "Bombita;

And finally, we register our extension like we did in the previous articles, but with one new element, this line:

themes: [ Christmas2017Theme ]

Here, we are telling StarMash that our extension wants to register a new Theme, by passing a reference to the Theme function itself. Note that the themes property of the object we pass to registerExtension is an Array. This is because we could define several Themes in a single extension. All could sharing some common code, but have some differences between them to make them ‘unique’.

For example, imagine a “World War 2” extension, that adds the following themes:

We could define something like, assuming that we have declared the classes for those Themes:

themes: [ WW2_Eastern_Front, WW2_Western_Front, WW2_Pacific_War ]

And that’s it. You can test this theme in StarMash and have some fun with the Christmas Theme.

Example: St. Patrick’s Theme - Replacing only some files

In the previous example, the Christmas Theme worked by replacing every single file, and providing its own version hosted somewhere else.

In this example, the St. Patrick’s Day Theme changes only the following files:

Basically, it adds clovers to the background (brighter clovers in replace of the sand, and darker clovers in replace of the rock), and tints the planes with a golden hue. The rest of the files are the default AirMash files.

So, what happens if we wanted to change only some files, and leave the rest untouched, like this theme needs?

Simple! We can alter the injectTextures method of our theme class, to something like this:

injectTextures(files, textureInfo, flagTextureInfo, spriteInfo, textures)
{
    const toChange = [
        "map_forest.jpg",
        "map_rock.jpg",
        "map_sand.jpg",
        "map_sea.jpg",
        "aircraft.png"];

    for(let i in files)
    {
        let fileName = getFileName(files[i]);

        if ($.inArray(fileName, toChange) > -1)
        {
            files[i] = "//molesmalo.github.io/StarWarsMod4AirMash/assets/themes/StPatricksDay2018/" + getFileName(files[i]);
        }
    }
}

Here, we create an array that contains the files we need to change, and then we proceed to iterate over the files. If the current file name is in the list, we change its URL.

Also, in this example we do use the constructor, because the theme changes the color of the main screen window when the instance is created.

You can view the full code for this example here: Download the file

 

Rounding up

In this lesson, you learned how to build some simple themes for AirMash, using StarMash Extensions.

Just by inheriting from one of the base themes provided by StarMash, you can do a lot.

I hope you liked this article. On Part 5, we will dig deeper, learning how AirMash Graphics module works, to create more advanced themes. Be warned though: it will be a little more technical. But if you are interested in going beyond the most simple themes, I hope it will help you get started. See you there!

Continue to Part 5

 

Go back to Part 3