UserApp-Entwicklung/Tutorials/HTML-UI: Unterschied zwischen den Versionen

(Persönliche Anrede entfernt, Nutzer => Mitglied)
(Änderung 143817 von mrs fabelhaft (Diskussion) rückgängig gemacht.)
Markierung: Rückgängigmachung
 
Zeile 1: Zeile 1:
== Einleitung ==
== Einleitung ==


In diesem Tutorial lernt man, wie man eine grafische Oberfläche in der UserApps verwenden kann, um z. B. grafische Spiele für Knuddels zu programmieren. Man sollte schon einmal etwas mit HTML und JavaScript gemacht haben, um folgen zu können.
In diesem Tutorial lernst du, wie du eine grafische Oberfläche in deinen UserApps verwenden kannst, um z.B. grafische Spiele für Knuddels zu programmieren. Du solltest schon einmal etwas mit HTML und JavaScript gemacht haben, um folgen zu können.


== Der Server ==
== Der Server ==


Der Server-Code der UserApp steht in der '''main.js'''. Wenn man nur in der '''main.js''' programmiert, läuft der ganze Code der UserApp ausschließlich auf den Servern von Knuddels.<br>
Der Server-Code deiner UserApp steht in der '''main.js'''. Wenn du nur in der '''main.js''' programmierst, läuft der ganze Code deiner UserApp ausschließlich auf den Servern von Knuddels.<br>
Damit kann man zwar schon viel machen, aber für mehr Interaktionsmöglichkeiten braucht man eine grafische Oberfläche.
Damit kann man zwar schon viel machen, aber für mehr Interaktionsmöglichkeiten brauchst du eine grafische Oberfläche.


== Der Client ==
== Der Client ==


Der Code für den Client befindet sich im '''www'''-Unterordner der UserApp.
Der Code für den Client befindet sich im '''www'''-Unterordner deiner UserApp.
Den Einstieg bildet eine HTML-Datei, die man nennen kann, wie man will. Dort kann man dann auch JavaScript-Dateien einbinden, um Code auf dem Gerät des Besuchers auszuführen.
Den Einstieg bildet eine HTML-Datei, die du nennen kannst, wie du willst. Dort kannst du dann auch JavaScript-Dateien einbinden, um Code auf dem Gerät deines Besuchers auszuführen.


Die Struktur der UserApp könnte dann so aussehen:
Die Struktur deiner UserApp könnte dann so aussehen:


<!--
<!--
Zeile 57: Zeile 57:
</pre>
</pre>


Während der Entwicklung wird man allerdings oft Änderungen an dem Script machen. Da Knuddels das Script zwischenspeichert, wenn man es einfach mit dem '''<script>'''-Tag einbindet, werden die Änderungen oft nicht übernommen. Um Knuddels dazu zu zwingen immer die aktuellste Version des Scripts zu laden, muss man das Knuddels stattdessen mit [https://developer.knuddels.de/docs/classes/Client.html#method_includeJS Client.includeJS()] mitteilen:
Während der Entwicklung wirst du allerdings oft Änderungen an deinem Script machen. Da Knuddels dein Script zwischenspeichert, wenn du es einfach mit dem '''<script>'''-Tag einbindest, werden deine Änderungen oft nicht übernommen. Um Knuddels dazu zu zwingen immer die aktuellste Version deines Scripts zu laden, musst du das Knuddels stattdessen mit [https://developer.knuddels.de/docs/classes/Client.html#method_includeJS Client.includeJS()] mitteilen:


<!--
<!--
Zeile 88: Zeile 88:
=== AppContent senden ===
=== AppContent senden ===


Die HTML-Datei und der restliche Inhalt des '''www'''-Unterordners wird [https://developer.knuddels.de/docs/classes/AppContent.html AppContent] genannt. Das ist die grafische Oberfäche der UserApp.<br>
Die HTML-Datei und der restliche Inhalt des '''www'''-Unterordners wird [https://developer.knuddels.de/docs/classes/AppContent.html AppContent] genannt. Das ist die grafische Oberfäche deiner UserApp.<br>
Der AppContent erscheint aber nicht automatisch bei dem Besucher des Channels! Man muss den AppContent erst an den Besucher (den Client) senden.
Der AppContent erscheint aber nicht automatisch bei dem Besucher deines Channels! Du musst den AppContent erst an den Besucher (den Client) senden.
In der Regel macht man das direkt wenn der Besucher den Channel betritt, also in '''App.onUserJoined''':
In der Regel macht man das direkt wenn der Besucher den Channel betritt, also in '''App.onUserJoined''':


Zeile 119: Zeile 119:
   Hinweis: [https://developer.knuddels.de/docs/classes/HTMLFile.html new HTMLFile()] sucht die angegebene Datei im '''www'''-Unterordner.
   Hinweis: [https://developer.knuddels.de/docs/classes/HTMLFile.html new HTMLFile()] sucht die angegebene Datei im '''www'''-Unterordner.


'''Damit ist dieses Tutorial eigentlich fertig:''' Die Besucher sehen jetzt eine grafische Oberfläche, wenn sie den Channel betreten und man kann wie auf Webseiten Scripts einbinden. Ein paar wichtige Hinweise kommen aber noch!<br>
'''Damit ist dieses Tutorial eigentlich fertig:''' Deine Besucher sehen jetzt eine grafische Oberfläche, wenn sie deinen Channel betreten und du kannst wie auf Webseiten Scripts einbinden. Ein paar wichtige Hinweise kommen aber noch!<br>


<br>
<br>


Der AppContent kann verschiedene '''ViewModes''' annehmen, je nachdem welche Methode man verwendet:
Der AppContent kann verschiedene '''ViewModes''' annehmen, je nachdem welche Methode du verwendest:


* '''Overlay''' mit [https://developer.knuddels.de/docs/classes/AppContent.html#method_overlayContent AppContent.overlayContent()]
* '''Overlay''' mit [https://developer.knuddels.de/docs/classes/AppContent.html#method_overlayContent AppContent.overlayContent()]
Zeile 130: Zeile 130:


<br>
<br>
'''Tipp:''' Nicht alle Geräte können jeden '''ViewMode''' anzeigen. Daher ist es gute Praxis, wenn man mit [https://developer.knuddels.de/docs/classes/User.html#method_canSendAppContent User.canSendAppContent()] entscheidet, welchen AppContent man sendet:
'''Tipp:''' Nicht alle Geräte können jeden '''ViewMode''' anzeigen. Daher ist es gute Praxis, wenn du mit [https://developer.knuddels.de/docs/classes/User.html#method_canSendAppContent User.canSendAppContent()] entscheidest, welchen AppContent du sendest.
'''Beispiel:'''
'''Beispiel:'''


Zeile 186: Zeile 186:
=== Events senden ===
=== Events senden ===


Der Code auf dem Server und der Code auf dem Client laufen jetzt praktisch unabhängig voneinander. Meistens ist es aber hilfreich, wenn Server und Client miteinander kommunizieren können.
Dein Code auf dem Server und dein Code auf dem Client laufen jetzt praktisch unabhängig voneinander. Meistens ist es aber hilfreich, wenn Server und Client miteinander kommunizieren können.


==== Client → Server ====
==== Client → Server ====


''' Beispiel:''' Wenn das Mitglied auf der grafischen Oberfläche einen Knopf drückt, soll der AppBot eine öffentliche Nachricht in den Channel schreiben.<br>
''' Beispiel:''' Wenn der Nutzer auf der grafischen Oberfläche einen Knopf drückt, soll der AppBot eine öffentliche Nachricht in den Channel schreiben.<br>
Man kann aber nur von der '''main.js''' (also vom Server aus) Chat-Nachrichten schicken. [https://developer.knuddels.de/docs/classes/BotUser.html#method_sendPublicMessage BotUser.sendPublicMessage()] funktioniert im Client nicht.<br>
Du kannst aber nur von der '''main.js''' (also vom Server aus) Chat-Nachrichten schicken. [https://developer.knuddels.de/docs/classes/BotUser.html#method_sendPublicMessage BotUser.sendPublicMessage()] funktioniert im Client nicht.<br>


Der Client muss also dem Server mitteilen, dass das Mitglied einen Button gedrückt hat. Das ist mit [https://developer.knuddels.de/docs/classes/Client.html#method_sendEvent Client.sendEvent()] möglich:
Der Client muss also dem Server mitteilen, dass der Nutzer einen Button gedrückt hat. Das ist mit [https://developer.knuddels.de/docs/classes/Client.html#method_sendEvent Client.sendEvent()] möglich:


<pre>
<pre>
Zeile 238: Zeile 238:
''' Beispiel:''' In der '''main.js''' wird eine zufällige Zahl generiert. Diese Zahl soll an alle Besucher des Channels geschickt werden, sodass diese dann in der HTML-UI angezeigt werden kann.<br>
''' Beispiel:''' In der '''main.js''' wird eine zufällige Zahl generiert. Diese Zahl soll an alle Besucher des Channels geschickt werden, sodass diese dann in der HTML-UI angezeigt werden kann.<br>


Mit [https://developer.knuddels.de/docs/classes/AppContent.html#method_sendEvent AppContent.sendEvent()] kann man ein Event an alle Besucher schicken, bei denen dieser AppContent aktiv ist:
Mit [https://developer.knuddels.de/docs/classes/AppContent.html#method_sendEvent AppContent.sendEvent()] kannst du ein Event an alle Besucher schicken, bei denen dieser AppContent aktiv ist:


<pre>
<pre>
Zeile 245: Zeile 245:
</pre>
</pre>


Im Client kann man mit [https://developer.knuddels.de/docs/classes/Client.html#method_addEventListener Client.addEventListener()] auf die Events vom Server reagieren:
Im Client kannst du mit [https://developer.knuddels.de/docs/classes/Client.html#method_addEventListener Client.addEventListener()] auf die Events vom Server reagieren:


<!--
<!--
Zeile 269: Zeile 269:
==== Server → ein bestimmter Client ====
==== Server → ein bestimmter Client ====


'''Beispiel:''' Man wählt einen Besucher zufällig aus und möchte, dass sich bei diesem Besucher die Farbe der HTML-UI ändert.<br>
'''Beispiel:''' Du wählst einen Besucher zufällig aus und möchtest, dass sich bei diesem Besucher die Farbe der HTML-UI ändert.<br>


Dazu muss man vom Server aus (also in der '''main.js''') diesem Client ein Event senden.<br>
Dazu musst du vom Server aus (also in der '''main.js''') diesem Client ein Event senden.<br>
Man kann aber nicht einfach ''User.sendEvent()'' aufrufen (diesen Befehl gibt es nicht). Eine UserApp kann nämlich verschiedene '''ViewModes''' auf einmal verwenden (sogenannte '''AppContentSessions'''). Man muss der API also sagen, an welche '''AppContentSession''' man das Event senden möchte.<br>
Du kannst aber nicht einfach ''User.sendEvent()'' aufrufen (diesen Befehl gibt es nicht). Eine UserApp kann nämlich verschiedene '''ViewModes''' auf einmal verwenden (sogenannte '''AppContentSessions'''). Du musst der API also sagen, an welche '''AppContentSession''' du das Event senden möchtest.<br>


Wenn man weiß, welchen '''ViewMode''' der Besucher verwendet (z.B. weil man sowieso immer nur ein Popup sendet), kann man einfach mit dem Befehl [https://developer.knuddels.de/docs/classes/User.html#method_getAppContentSession User.getAppContentSession] die AppContentSession erhalten und dann das Event senden. '''Beispiel:'''
Wenn du weißt, welchen '''ViewMode''' der Besucher verwendet (z.B. weil du sowieso immer nur ein Popup sendest), kannst du einfach mit dem Befehl [https://developer.knuddels.de/docs/classes/User.html#method_getAppContentSession User.getAppContentSession] die AppContentSession erhalten und dann das Event senden. '''Beispiel:'''


<pre>
<pre>
Zeile 283: Zeile 283:
<br>
<br>


Wenn der Client allerdings gleichzeitig mehrere aktive '''AppContentSessions''' haben könnte (z.B. eine Headerbar und ein Popup), kann man eine Liste aller aktiven AppContentSessions eines Besuchers mit [https://developer.knuddels.de/docs/classes/User.html#method_getAppContentSessions User.getAppContentSessions()] erhalten. '''Beispiel:'''
Wenn dein Client allerdings gleichzeitig mehrere aktive '''AppContentSessions''' haben könnte (z.B. eine Headerbar und ein Popup), kannst du eine Liste aller aktiven AppContentSessions eines Besuchers mit [https://developer.knuddels.de/docs/classes/User.html#method_getAppContentSessions User.getAppContentSessions()] erhalten. '''Beispiel:'''


<!--
<!--
Zeile 302: Zeile 302:
</pre>
</pre>


Auch hier kann man im Client wieder mit [https://developer.knuddels.de/docs/classes/Client.html#method_addEventListener Client.addEventListener()] auf die Events reagieren.
Auch hier kannst du im Client wieder mit [https://developer.knuddels.de/docs/classes/Client.html#method_addEventListener Client.addEventListener()] auf die Events reagieren.


==== Limits ====
==== Limits ====


Für die Daten, die man mit den Events zwischen Client und Server sendet, gibt es gewisse [[Limits]]. Diese Limits werden [[Limits|hier]] beschrieben.
Für die Daten, die du mit den Events zwischen Client und Server sendest, gibt es gewisse [[Limits]]. Diese Limits werden [[Limits|hier]] beschrieben.


[[Kategorie:UserApp-Entwicklung]]
[[Kategorie:UserApp-Entwicklung]]

Aktuelle Version vom 10. Oktober 2021, 12:18 Uhr

Einleitung

In diesem Tutorial lernst du, wie du eine grafische Oberfläche in deinen UserApps verwenden kannst, um z.B. grafische Spiele für Knuddels zu programmieren. Du solltest schon einmal etwas mit HTML und JavaScript gemacht haben, um folgen zu können.

Der Server

Der Server-Code deiner UserApp steht in der main.js. Wenn du nur in der main.js programmierst, läuft der ganze Code deiner UserApp ausschließlich auf den Servern von Knuddels.
Damit kann man zwar schon viel machen, aber für mehr Interaktionsmöglichkeiten brauchst du eine grafische Oberfläche.

Der Client

Der Code für den Client befindet sich im www-Unterordner deiner UserApp. Den Einstieg bildet eine HTML-Datei, die du nennen kannst, wie du willst. Dort kannst du dann auch JavaScript-Dateien einbinden, um Code auf dem Gerät deines Besuchers auszuführen.

Die Struktur deiner UserApp könnte dann so aussehen:

KnuddelJumper/
    www/
        game.html
        game.js
        player.png
        enemy.png
    main.js

Die HTML-Datei kann dann z.B. so eine Struktur haben:

<html>
    <head>
        <script src="game.js"/>
    </head>
    <body>
        <button>Hier klicken</button>
    </body>
</html>

Während der Entwicklung wirst du allerdings oft Änderungen an deinem Script machen. Da Knuddels dein Script zwischenspeichert, wenn du es einfach mit dem <script>-Tag einbindest, werden deine Änderungen oft nicht übernommen. Um Knuddels dazu zu zwingen immer die aktuellste Version deines Scripts zu laden, musst du das Knuddels stattdessen mit Client.includeJS() mitteilen:

<html>
    <head>
        <script>
            Client.includeJS("game.js");
        </script>
    </head>
    <body>
        <button>Hier klicken</button>
    </body>
</html>

Kommunikation zwischen Server und Client

AppContent senden

Die HTML-Datei und der restliche Inhalt des www-Unterordners wird AppContent genannt. Das ist die grafische Oberfäche deiner UserApp.
Der AppContent erscheint aber nicht automatisch bei dem Besucher deines Channels! Du musst den AppContent erst an den Besucher (den Client) senden. In der Regel macht man das direkt wenn der Besucher den Channel betritt, also in App.onUserJoined:

var App = (new function() {

    let htmlFile = new HTMLFile("game.html");
    let appContent = AppContent.overlayContent(htmlFile, 640, 480);

    this.onUserJoined = function(user) {
        user.sendAppContent(appContent);
    }
}());

Der AppContent wird so nur einmal von der App geladen und dann einfach an jeden Besucher mit User.sendAppContent() gesendet.

 Hinweis: new HTMLFile() sucht die angegebene Datei im www-Unterordner.

Damit ist dieses Tutorial eigentlich fertig: Deine Besucher sehen jetzt eine grafische Oberfläche, wenn sie deinen Channel betreten und du kannst wie auf Webseiten Scripts einbinden. Ein paar wichtige Hinweise kommen aber noch!


Der AppContent kann verschiedene ViewModes annehmen, je nachdem welche Methode du verwendest:


Tipp: Nicht alle Geräte können jeden ViewMode anzeigen. Daher ist es gute Praxis, wenn du mit User.canSendAppContent() entscheidest, welchen AppContent du sendest. Beispiel:

var App = (new function() {

    let htmlFile = new HTMLFile("game.html");
    let overlay = AppContent.overlayContent(htmlFile, 640, 480);
    let popup  = AppContent.popupContent(htmlFile, 640, 480);
    let headerbar = AppContent.headerbarContent(htmlFile, 480);

    this.onUserJoined = function(user) {

        if (user.canSendAppContent(overlay)) {
            user.sendAppContent(overlay);

        } else if (user.canSendAppContent(popup)) {
            user.sendAppContent(popup);

        } else if (user.canSendAppContent(headerbar)) {
            user.sendAppContent(headerbar);

        } else {
            user.sendPrivateMessage("Die UserApp kann auf deinem Gerät leider nicht angezeigt werden.");
        }
    }
}());

Events senden

Dein Code auf dem Server und dein Code auf dem Client laufen jetzt praktisch unabhängig voneinander. Meistens ist es aber hilfreich, wenn Server und Client miteinander kommunizieren können.

Client → Server

Beispiel: Wenn der Nutzer auf der grafischen Oberfläche einen Knopf drückt, soll der AppBot eine öffentliche Nachricht in den Channel schreiben.
Du kannst aber nur von der main.js (also vom Server aus) Chat-Nachrichten schicken. BotUser.sendPublicMessage() funktioniert im Client nicht.

Der Client muss also dem Server mitteilen, dass der Nutzer einen Button gedrückt hat. Das ist mit Client.sendEvent() möglich:

Client.sendEvent("buttonPressed", {});

Dabei können noch zusätzliche Daten in Form eines JavaScript-Objekts mitgegeben werden.

Der Server kann dann in der main.js in App.onEventReceived() reagieren:

var App = (new function() {
    
    //...
    
    this.onEventReceived = function(user, type, data, appContentSession) {
        
        if (type == "buttonPressed") {
            let bot = KnuddelsServer.getDefaultBotUser();
            bot.sendPublicMessage(user.getProfileLink()+" hat den Knopf gedrückt!");
        }
    }
}());


Server → alle Clients

Beispiel: In der main.js wird eine zufällige Zahl generiert. Diese Zahl soll an alle Besucher des Channels geschickt werden, sodass diese dann in der HTML-UI angezeigt werden kann.

Mit AppContent.sendEvent() kannst du ein Event an alle Besucher schicken, bei denen dieser AppContent aktiv ist:

let randomNumber = Math.floor(10 * Math.random());
appContent.sendEvent("showNumber", {randomNumber: number});

Im Client kannst du mit Client.addEventListener() auf die Events vom Server reagieren:

Client.addEventListener("showNumber", function(event) {
        
        let number = event.data.number;
        
        document.open();
        document.write("Die magische Zahl heißt: "+number);
        document.close()
});

Server → ein bestimmter Client

Beispiel: Du wählst einen Besucher zufällig aus und möchtest, dass sich bei diesem Besucher die Farbe der HTML-UI ändert.

Dazu musst du vom Server aus (also in der main.js) diesem Client ein Event senden.
Du kannst aber nicht einfach User.sendEvent() aufrufen (diesen Befehl gibt es nicht). Eine UserApp kann nämlich verschiedene ViewModes auf einmal verwenden (sogenannte AppContentSessions). Du musst der API also sagen, an welche AppContentSession du das Event senden möchtest.

Wenn du weißt, welchen ViewMode der Besucher verwendet (z.B. weil du sowieso immer nur ein Popup sendest), kannst du einfach mit dem Befehl User.getAppContentSession die AppContentSession erhalten und dann das Event senden. Beispiel:

let appContentSession = user.getAppContentSession(AppViewMode.Popup);
appContentSession.sendEvent("changeColor", {red:255, green:0, blue:255});


Wenn dein Client allerdings gleichzeitig mehrere aktive AppContentSessions haben könnte (z.B. eine Headerbar und ein Popup), kannst du eine Liste aller aktiven AppContentSessions eines Besuchers mit User.getAppContentSessions() erhalten. Beispiel:

let appContentSessions = user.getAppContentSessions();

for (let i = 0; i < appContentSessions.length; i++) {
    let appContentSession = appContentSessions[i];
    appContentSession.sendEvent("changeColor", {red:255, green:0, blue:255});
}

Auch hier kannst du im Client wieder mit Client.addEventListener() auf die Events reagieren.

Limits

Für die Daten, die du mit den Events zwischen Client und Server sendest, gibt es gewisse Limits. Diese Limits werden hier beschrieben.