BI-PGA Programování grafických aplikací
Jdi na navigaci předmětu

Rodičovské a odvozené aplikace

Rodičovské a odvozené aplikace

Tvorba aplikace

Podíváme se na Rodičovské a odvozené aplikace a jejich interakce na příkladu hry "Námořní bitva"

Pro interakci použijeme následující funkce:

Pošleme požadavek na server za účelem spuštění odvozené aplikace

launchAppWithValues: function(appName, paramObj, x, y, funcToPassParams)
  • appName - název programu, který se má spustit ze seznamu aplikací
  • paramObj - volitelný parametr, který bude předán jako argument funkci 'funcToPassParams'. Musí to být typ Object!
  • x, y - souřadnice, kde bude aplikace spuštěna
  • funcToPassParams - název funkce, která bude volána po inicializaci aplikace ve formátu řetězce

Funkce pro inicializaci proměnné na serveru

serverDataSetValue: function(nameOfValue, value, description, shouldRemoveValueFromServerWhenAppCloses = false)
  • nameOfValue - název proměnné. Pokud proměnná již existuje, přiřadí jí novou hodnotu
  • value - hodnota, která má být přiřazena proměnné.
  • description - popis proměnné
  • shouldRemoveValueFromServerWhenAppCloses - měla by být proměnná odstraněna ze serveru po ukončení aplikace

Pro kontrolu změny hodnoty proměnne na serveru

serverDataSubscribeToValue: function(nameOfValue, callback, unsubscribe = false)
  • nameOfValue - název proměnné
  • callback - funkce, která bude volána, když se proměnná změní a vezme její novou hodnotu jako argument
  • unsubscribe - zapnout nebo vypnout sledování

Pokud potřebujeme přímo zavolat funkci z rodičovské aplikace

sendDataToParentApp: function(nameOfFunction, data)
  • nameOfFunction - nazev funkce ve formátu řetězce
  • data - hodnota předaná funkci

Rodičovská aplikace

Ukázka 1. instructions.json
{
  "main_script": "Game.js",
  "width": 100,
  "height": 20,
  "animation": true,
  "title": "BattleShip",
  "author": "Oleksandr Khokhych"
}
Ukázka 2. Game.js
var Game = SAGE2_App.extend({

    init: function (data) {

        this.SAGE2Init("canvas", data);
        this.ctx = this.element.getContext("2d");
        this.resizeEvents = "continuous";

        // inicializace proměnných pro předání podřízeným aplikacím
        var num1 = new Object();
        var num2 = new Object();
        // přiřazení indexů
        num1.val = 1;
        num2.val = 2;

        // spuštění první aplikace
        this.launchAppWithValues("Board", num1, this.sage2_x, this.sage2_y + 40, "setNum");
        // spuštění druhé aplikace
        this.launchAppWithValues("Board", num2, this.sage2_x + 300, this.sage2_y + 40, "setNum");

        this.ctx.lineWidth = 2;
        this.ctx.strokeStyle = "grey";
        this.ctx.font = "16px serif";

        // aktuální stav hry
        this.statement = 0;
    },

    resize: function (date) {
        this.refresh(date);
    },

    draw: function (date) {

        this.ctx.fillStyle = "black";
        this.ctx.fillRect(0, 0, this.element.width, this.element.height);

        this.update(date);
    },

    // funkce volaná z nadřazené aplikace
    nextstate: function (date) {
        // měníme aktuální stav hry
        this.statement = (this.statement === 4 ? 3 : this.statement + 1);
        this.refresh(date);
    },

    update: function (date) {

        this.ctx.fillStyle = "red";

        // v závislosti na aktuálním stavu hry
        switch (this.statement) {

            case 0:
                // přiřazení proměnné "FirstPlayerState" hodnotu "waiting"
                this.serverDataSetValue("FirstPlayerState", "waiting", "First player statement variable", true);
                // přiřazení proměnné "SecondPlayerState" hodnotu "waiting"
                this.serverDataSetValue("SecondPlayerState", "waiting", "Second player statement variable", true);
                this.ctx.fillText("Press R to start the game", 20, 20);
                break;

            case 1:
                // přiřazení proměnné "FirstPlayerState" hodnotu "waiting"
                this.serverDataSetValue("FirstPlayerState", "waiting", "First player statement variable", true);
                // přiřazení proměnné "SecondPlayerState" hodnotu "preparation"
                this.serverDataSetValue("SecondPlayerState", "preparation", "Second player statement variable", true);
                this.ctx.fillText("Preparing Second Player", 20, 20);
                break;

            case 2:
                // přiřazení proměnné "FirstPlayerState" hodnotu "preparation"
                this.serverDataSetValue("FirstPlayerState", "preparation", "First player statement variable", true);
                // přiřazení proměnné "SecondPlayerState" hodnotu "waiting"
                this.serverDataSetValue("SecondPlayerState", "waiting", "Second player statement variable", true);
                this.ctx.fillText("Preparing First Player", 20, 20);
                break;

            case 3:
                // přiřazení proměnné "FirstPlayerState" hodnotu "waiting"
                this.serverDataSetValue("FirstPlayerState", "waiting", "First player statement variable", true);
                // přiřazení proměnné "SecondPlayerState" hodnotu "turn"
                this.serverDataSetValue("SecondPlayerState", "turn", "Second player statement variable", true);
                this.ctx.fillText("First Player Turn", 20, 20);
                break;

            case 4:
                // přiřazení proměnné "FirstPlayerState" hodnotu "turn"
                this.serverDataSetValue("FirstPlayerState", "turn", "First player statement variable", true);
                // přiřazení proměnné "SecondPlayerState" hodnotu "waiting"
                this.serverDataSetValue("SecondPlayerState", "waiting", "Second player statement variable", true);
                this.ctx.fillText("Second Player Turn", 20, 20);
                break;

        }
    }
});

Odvozená aplikace

Ukázka 3. instructions.json
{
  "main_script": "Board.js",
  "width": 300,
  "height": 300,
  "animation": true,
  "title": "Board",
  "author": "Oleksandr Khokhych"
}
Ukázka 4. Board.js
var Board = SAGE2_App.extend({

    init: function (data) {

        this.SAGE2Init("canvas", data);
        this.ctx = this.element.getContext("2d");

        this.resizeEvents = "continuous";

        //...

        // aktuální stav herního pole
        this.statement = "waiting";
    },

    // vymaže obrazovku
    clean: function () {
        //...
    },

    drawLine: function (x0, y0, x1, y1) {
        //...
    },

    // označíme herní mřížku
    drawgrid: function () {
        //...
    },

    // kreslení pole pro umístění lodí
    drawpreset: function () {
        //...
    },

    // kreslení pole pro střelbu
    drawmap: function () {
        //...
    },

    draw: function (date) {

        this.clean();

        // v závislosti na aktuálním stavu
        switch (this.statement) {
            //pokud tah jiného hráče, na vlastní obrazovku nic nekreslíme
            case "waiting":
                break;

            // jestli je řada na nás umístit lodě
            case "preparation":
                this.drawpreset();
                break;

            // jestli je řada na nás střílet
            case "turn":
                this.drawmap();
                break;
        }
    },

    resize: function (date) {
        this.refresh(date);
    },

    // funkce zpětného volání ke změně stavu
    setState: function (val) {
        this.statement = val;
    },

    // funkce, která vezme svůj index a přihlásí se k aktualizaci odpovídající proměnné na serveru
    setNum: function (num) {
        if (num.val === 1) this.serverDataSubscribeToValue("FirstPlayerState", this.setState);
        if (num.val === 2) this.serverDataSubscribeToValue("SecondPlayerState", this.setState);
    },

    contain: function (tmp, [y, x]) {
        //...
    },

    // funkce k určení, zda byla loď zcela zničena
    bfsfill: function (ty, tx) {
        //...
    },

    event: function (eventType, position, user_id, data, date) {

        // pokud bylo stisknuto levé tlačítko myši
        if (eventType === "pointerPress" && (data.button === "left")) {

            var x = parseInt(position.x / this.size);
            var y = parseInt(position.y / this.size);

            // pokud je fáze umístění lodi, změníme hodnotu buňky na opačnou
            if (this.statement === "preparation") this.presetboard[y][x] = !this.presetboard[y][x];
            // pokud je fáze palby na lodě
            if (this.statement === "turn") {
                // pokud je v této buňce nepřátelská loď
                if (this.presetboard[y][x]) {
                    // označíme buňku
                    this.gameboard[y][x] = 2;
                    // zkontrolujeme, zda byla loď úplně zničena
                    this.bfsfill(y, x);
                }
                // pokud není
                else {
                    // označíme buňku
                    this.gameboard[y][x] = 1;
                    // změníme stav nadřazené aplikace, čímž předáme tah dalšímu hráči
                    this.sendDataToParentApp("nextstate", date);
                }
            }
        }

        else if (eventType === "keyboard") {

            if (data.character === "r") {
                // změníme stav nadřazené aplikace, čímž předáme tah dalšímu hráči
                this.sendDataToParentApp("nextstate", date);
            }
        }
    }
});
img1
img2

Odkazy

Zdrojový kód: Game

Zdrojový kód: Board