Schreiben von Penguin Daycare Simulator on Go (Google App Engine) und Lua (Corona SDK)

  • Tutorial

1. Einleitung


Dieses Projekt ist ein einfaches Beispiel für die Verwendung von Google App Engine in einer mobilen Anwendung.

Der Serverteil enthält eine Liste der Pinguine im JSON-Format. Der mobile Client fordert diese Liste über HTTP oder HTTPS an.
Außerdem zeichnet die Serverseite bestimmte Ereignisse in der Datenbank auf, nämlich die Anzahl der Besuche bei einem bestimmten Pinguin und die Anzahl der Tastendrücke: Füttern Sie den Fisch und kratzen Sie sich am Bauch.
Jeder Pinguin hat ein Beschreibungsfeld Name, Biound Feld Meter.

2. Feinheiten der Übersetzung


Ich dachte darüber nach, wie man Penguin Daycare Simulator ins Russische übersetzt, aber „Kindergarten“ als „Kindertagesstätte“ ist nicht geeignet, auch „Tagesbetreuung“. Daher blieb es ohne Übersetzung.

3. Vorbereitung


Wenn Sie das Google App Engine Go SDK nicht installiert haben, klicken Sie auf den Link Google App Engine , klicken Sie auf "Jetzt testen" und befolgen Sie alle Punkte. Geben Sie Ihrem Projekt einen Namen, wählen Sie Los, laden Sie das SDK herunter und installieren Sie es. Stellen Sie sicher , dass Sie richtig Umgebungsvariablen festgelegt haben ( PATH, GOROOT, GOPATH, APPENGINE_DEV_APPSERVER), für diesen Zweck in dem Terminal, sollten Sie das Team gesehen haben goapp. Mit Blick auf die Zukunft muss ich sagen, dass Sie den Befehl goapp deployim Projektverzeichnis ausführen müssen, um ein einfaches Projekt auf den GAE-Server hochzuladen und auszuführen . Sie fragt Sie nach der E-Mail-Adresse des Google-Kontos, auf dem sich das Projekt befinden soll. Es ist wichtig, dass der Projektname in app.yaml und auf der Site übereinstimmt. In diesem Projekt werden jedoch Module verwendet und der Ladevorgang ist etwas anders.

Als IDE für Go empfehle ichLiteIDE und für Lua und Corona SDK - ZeroBrane Studio . Sie können das Corona SDK auf ihrer Website herunterladen .

4. Clint Server


Das Bild unten zeigt ein sehr komplexes Kommunikationsschema zwischen dem Client (links) und dem Server (rechts).


Wie Sie sehen können, fordert der Client nur die Liste der Pinguine an und sendet nur drei Ereignisse. Die Kommunikation erfolgt über HTTP, Sie können HTTPS jedoch kostenlos verwenden. Dies kann auf einen der Vorteile der Verwendung von GAE zurückgeführt werden - es ist nicht erforderlich, ein SSL-Zertifikat zu bezahlen und die Arbeit damit zu konfigurieren.

Da alles über HTTP funktioniert, können Sie Anforderungen direkt im Browser ausführen, ohne einen speziellen Client zu verwenden.

penguin-daycare-simulator.appspot.com
Eine einfache Begrüßung, die vom mobilen Client nicht verwendet wird, mit der Sie jedoch feststellen können, ob der Dienst funktioniert. Sie können http durch https ersetzen und sicherstellen, dass dies auch funktioniert.

penguin-daycare-simulator.appspot.com/penguins
Dies ist die wichtigste Anfrage. Mit seiner Hilfe erhält der mobile Client eine Liste aller Pinguine, die derzeit unter Aufsicht stehen.
Für eine bequemere Anzeige dieser Daten empfehle ich die JSONview- Erweiterung für Chrome.

penguin-daycare-simulator.appspot.com/stat/visit
penguin-daycare-simulator.appspot.com/stat/fish
penguin-daycare-simulator.appspot.com/stat/bellyrub
Diese drei Abfragen erhöhen die entsprechenden Zählungen für einen Pinguin . IdPinguin wird als POST-Parameter übergeben. Der Server gibt keine Antwort zurück, aber Sie können der Antwort, wenn Sie möchten, die Zeichenfolge "OK" oder ein anderes Signal für einen erfolgreichen Betrieb hinzufügen.

5. Mehr Screenshots, mehr Screenshots!




Bereits vor der Veröffentlichung des Artikels erinnerte ich mich an diesen Pinguin:
Beobachten Sie das Positive

6. Server - Google App Engine


Jetzt können wir direkt zum Code gehen. Betrachten Sie die Dateistruktur eines Go-Projekts.
PenguinDaycareSimulatorServer/
├── default/
│   ├── app.go
│   ├── default.yaml
│   └── penguins.json
├── static/
│   ├── favicon.ico
│   └── static.yaml
└── dispatch.yaml

defaultund static- das sind Module. Ein Projekt für GAE kann in Module unterteilt werden oder ohne diese funktionieren. In diesem Fall müssen nur drei Dateien: app.yaml, app/app.gound penguins.json. Anfangs war es in meinem Projekt (Sie können das erste Commit auf GitHub sehen), aber ich wollte eine Einstellung hinzufügenmax_concurrent_requestsDies ist dafür verantwortlich, wie viele gleichzeitige Anforderungen eine Instanz Ihrer Anwendung verarbeiten kann. Der Standardwert ist nur 10. Go kann eindeutig mehr. Der Maximalwert beträgt 500. Wenn die Last diesen Wert erhöht und überschreitet, werden zusätzliche Kopien Ihrer Anwendung gestartet und die Last zwischen ihnen verteilt. Wenn Sie nur in kostenlose GAE-Kontingente passen möchten, ist die Verwendung dieser Einstellung äußerst wünschenswert. Wenn die Anwendung mit einer solchen Belastung nicht fertig wird, reduzieren Sie diesen Wert und wechseln Sie zur bezahlten Abrechnung.

Diese Einstellung ist also nur für Module verfügbar. Und Ihre Anwendung muss mindestens 2 Module enthalten, damit GAE sie als modular betrachtet.

static- Ein sehr einfaches Modul, auf das verzichtet werden könnte (ohne die oben genannte GAE-Einschränkung). Seine Aufgabe besteht nur darin, eine Datei statisch anzugeben favicon.ico.

default- Das Hauptmodul, das die ganze Arbeit erledigt.

Dateien *.yamlsind Einstellungen und Beschreibungen. Eine für jedes Modul und eine Datei dispatch.yaml, die beschreibt, welche URLs welches Modul verarbeitet.
dispatch.yaml
application: penguin-daycare-simulator
dispatch:
- url: "*/favicon.ico"
  module: static
- url: "*/"
  module: default

static.yaml
application: penguin-daycare-simulator
module: static
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /favicon.ico
  static_files: favicon.ico
  upload: favicon.ico

default.yaml
application: penguin-daycare-simulator
module: default
version: 1
runtime: go
api_version: go1
automatic_scaling:
  max_concurrent_requests: 500
handlers:
- url: /.*
  script: _go_app

Beachten Sie, dass zur static.yamlLaufzeit Python angegeben ist, nicht Go. Dies liegt daran, dass GAE schwört, wenn Sie versuchen, ein Modul auf Go ohne Go-Dateien zu laden. In dieser Situation schwört er jedoch nicht auf Python und PHP.
Off Topic
Ein aufmerksamer Leser hier mag argumentieren, dass "was PHP schlechter macht als Python, um statische Dateien zu rendern" und versuchen, Holywar zu lösen, aber Python ist mir persönlich näher, deshalb habe ich es gewählt. Jeder andere kann PHP für diese Zwecke verwenden. Dies ist natürlich alles sinnlos, da weder Python noch PHP an diesem Prozess beteiligt sind.

handlersin default.yamlzeigt an, welche ausführbaren Dateien bestimmte URL behandeln. In unserem Fall verarbeitet app.go alle eingehenden Anfragen (unter Berücksichtigung dispatch.yaml). Die URL-Beschreibung ist sehr flexibel und verwendet reguläre Ausdrücke. Wenn Sie jedoch für Python und PHP unterschiedliche Dateien verwenden können, um unterschiedliche URLs innerhalb desselben Moduls zu verarbeiten, sollte es für Go eine einzelne Datei sein, die als "_go_app" bezeichnet wird. Darüber hinaus können Sie bereits im Go-Programm Handler für verschiedene URLs auswählen und die gesamte Anwendung bei Bedarf in mehrere Dateien aufteilen.

Weitere Informationen zu Konfigurations- und Yaml-Dateien finden Sie hier .

penguins.json- eine JSON-Datei mit den Namen und Beschreibungen aller verwendeten Pinguine.
penguins.json
[
	{"id": "1",
	"name": "Tux",
	"bio": "Beloved Linux mascot"
	},
	{"id": "2",
	"name": "Skipper",
	"bio": "Small combat squad leader"
	},
	{"id": "3",
	"name": "Lolo",
	"bio": "Russian adventurer"
	},
	{"id": "4",
	"name": "Gunter",
	"bio": "The darkest character in Adventure Time"
	},
	{"id": "5",
	"name": "The Penguin",
	"bio": "Na, na, na, na, na, na, na, na, na, na... The Penguin! "
	}
]

Das Hinzufügen und Bearbeiten von Pinguinen erfolgt über diese Datei.

Jetzt kommen wir zum app.goKern der gesamten Anwendung. Eine vollständige Liste ist bequem direkt auf GitHub zu sehen - app.go .

Die vereinfachte Struktur dieser Datei:
package app
Перечисление всех используемых библиотек.
import (...)
Структура каждого пингвина: Id, имя, описание, счётчики.
type penguin struct {...}
Слайс (массив) всех пингвинов.
var penguins []penguin
Структура записи в базу данных.
type penguinEntity struct {...}
Инициализация.
func init() {...}
Чтение penguins.json в слайс penguins.
func loadPenguinsJson() {...}
Обработчик / - вывод простого сообщения.
func rootHandler(w http.ResponseWriter, r *http.Request) {...}
Обработчик /penguins - вывод всех пингвинов со статистикой в формате JSON.
func penguinsHandler(w http.ResponseWriter, r *http.Request) {...}
Обработчик события /stat/visit - посещение пингвина.
func visitHandler(w http.ResponseWriter, r *http.Request) {...}
Обработчик события /stat/fish - кормление пингвина рыбкой.
func fishHandler(w http.ResponseWriter, r *http.Request) {...}
Обработчик события /stat/bellyrub - почёсывание пингвина по животику.
func bellyrubHandler(w http.ResponseWriter, r *http.Request) {...}

Beim Starten der Anwendung wird zuerst die Funktion init () gestartet, die aus der Datei penguins.json liest und festlegt, welche Funktion für verschiedene Anforderungen vom Client verantwortlich ist. Sie können sie bereits unter den Links am Anfang des Artikels verwenden.

penguinsHandler()serialisiert Slice-Pinguine nach Funktion in das JSON-Format json.Marshal()und gibt sie an Clients weiter fmt.Fprint().

visitHandler(), fishHandler(), bellyrubHandler()Acting auf einer Logik - Pinguin nehmen Sie von der Datenbank durch einen entsprechenden Parameter und geschrieben in die Datenbank zurück erhöht wird. Die Datenbank - Datenspeicher - ist nicht SQL-kompatibel, dh es handelt sich um eine NoSQL-Lösung. Die Beschreibung ihrer Arbeit verdient einen gesonderten Artikel.

Da viele Vorgänge mit GAE separat berechnet werden, einschließlich des Zugriffs auf den Datenspeicher, sollte ein übermäßiger Ressourcenverbrauch vermieden werden. Wenn Sie beispielsweise Statistiken für alle Pinguine anfordern, ist es völlig optional, relevante Daten anzugeben. Sie können diese Anforderung mit einer Cache-Lebensdauer von beispielsweise 10 Minuten zwischenspeichern. Zu diesem lastUpdateTimeZweck habe ich eine zusätzliche Variable eingeführt - den Zeitstempel der letzten Aktualisierung des Slice penguins. Und mit jeder Anfrage /penguinsrufe ich eine Funktion auf updatePenguinsStatistics(), die prüft, ob der Cache abgelaufen ist, und im Zyklus den Zähler für jeden Pinguin im Slice aktualisiert penguins.

Um das Update manuell zu erzwingen, habe ich eine zusätzliche Anforderung / Aktualisierung und den entsprechenden Handler eingeführt updateHandler().

Jede Anfrage wird in einer eigenen Goroutine verarbeitet, daher müssen Sie das Slice penguinsvor möglichem gleichzeitigen Schreiben oder Lesen während der Aufnahme schützen . Hierzu wird RWMutexein Mutex zum Lesen oder Schreiben verwendet. Seine Verwendung ist effektiver als einfach Mutex.

Um den bezahlten Ressourcenverbrauch zu vermeiden, können Sie auch einen verzögerten Datensatz in die Datenbank eingeben und die Werte aller empfangenen Ereignisse akkumulieren.

Um ein Projekt auf den GAE-Server hochzuladen, müssen Sie drei Befehle im Terminal im Projektverzeichnis ausführen:
goapp deploy default/default.yaml
goapp deploy static/static.yaml
appcfg.py update_dispatch .

Wenn Sie app.go ändern, muss es in Zukunft nur noch gestartet werden goapp deploy default/default.yaml.

Abschließend möchte ich auf der Serverseite sagen, dass ich zur Erhöhung der freien Limits empfehle, die kostenpflichtige Abrechnung zu verbinden, aber gleichzeitig die maximalen Kosten pro Tag auf 1 US-Dollar festzusetzen. Gleichzeitig steigen einige kostenlose Quoten, aber Sie geben immer noch nichts aus.

7. Client-Seite - Corona SDK


Das Corona SDK ist ein plattformübergreifendes Framework für die Entwicklung mobiler Anwendungen für Android, iOS, Windows Phone (in Kürze erhältlich) und HTML5 (in Entwicklung). Ich benutze dieses Produkt schon seit einiger Zeit und schreibe Spiele sowohl für Kunden als Freiberufler als auch für mich. Ich stelle fest, wie schnell und schnell Anwendungen erstellt werden.

Beginnen wir mit der Dateistruktur des Projekts. Es gibt hier mehr Dateien, hauptsächlich aufgrund von Symbolen und Bildern, also reinige ich sie unter dem Spoiler.
Dateistruktur
PenguinDaycareSimulator/
├── images/
│   ├── penguins/
│   │   ├── 1.png
│   │   ├── 1@2x.png
│   │   ├── 2.png
│   │   ├── 2@2x.png
│   │   ├── 3.png
│   │   ├── 3@2x.png
│   │   ├── 4.png
│   │   ├── 4@2x.png
│   │   ├── 5.png
│   │   └── 5@2x.png
│   ├── background.jpg
│   ├── background@2x.jpg
│   ├── button-over.png
│   ├── button-over@2x.png
│   ├── button.png
│   ├── button@2x.png
│   ├── dot-off.png
│   ├── dot-off@2x.png
│   ├── dot.png
│   ├── dot@2x.png
│   ├── fish.png
│   ├── fish@2x.png
│   ├── hand.png
│   ├── hand@2x.png
│   ├── popup.png
│   └── popup@2x.png
├── lib/
│   ├── api.lua
│   ├── app.lua
│   └── utils.lua
├── scenes/
│   ├── choose.lua
│   ├── menu.lua
│   └── penguin.lua
├── Default-568h@2x.png
├── Icon-60.png
├── Icon-60@2x.png
├── Icon-72.png
├── Icon-72@2x.png
├── Icon-76.png
├── Icon-76@2x.png
├── Icon-Small-40.png
├── Icon-Small-40@2x.png
├── Icon-Small-50.png
├── Icon-Small-50@2x.png
├── Icon-Small.png
├── Icon-Small@2x.png
├── Icon-hdpi.png
├── Icon-ldpi.png
├── Icon-mdpi.png
├── Icon-ouya.png
├── Icon-xhdpi.png
├── Icon-xxhdpi.png
├── Icon.png
├── Icon@2x.png
├── build.settings
├── config.lua
└── main.lua

Sie können vorerst nur auf Lua-Dateien achten.

config.lua, build.settings- Projekt-Setup-Dateien für das Corona SDK. Geben Sie an, dass eine Hoch- oder Querformatansicht die Anwendung, die Auflösung des Referenzbildschirms, die Zoommethode und andere unterschiedliche Einstellungen enthält. Wenn das Corona SDK für Sie neu ist, können Sie diese Dateien vorerst nicht beachten.

Ebenfalls im Stammverzeichnis finden Sie eine Reihe von Symbolen für iOS und Android sowie Default-568h@2x.pngfür den korrekten Betrieb auf dem iPhone 5. Im Bild- / Verzeichnis befinden sich reguläre Dateien und deren doppelte HD-Versionen @2x. Im Prinzip können Sie Geräte mit Bildschirmen wie dem iPhone 3GS nicht mehr unterstützen. Ihr Prozentsatz ist sehr gering, aber dennoch ungleich Null. Für die vollständige Unterstützung von iPad Retina benötigen Sie bereits @4xDateien und einen Line-In config.lua, aber die meisten Spiele funktionieren trotzdem einwandfrei.

Das Corona SDK startet die Anwendung ausgehend von der Datei main.lua, die erforderlichen Bibliotheken werden mit ihr verbunden, einige Variablen werden deklariert und die Szene wird mit der Schaltfläche „Enter the Daycare“ umgeschaltet. Alle Szenen (Bildschirme) der Anwendung werden in verschiedenen Dateien gespeichert und in einem Verzeichnis gesammelt scenes/, und ich habe alle Benutzerbibliotheken abgelegt lib/. Der Entwickler kann diese Dateien nach Belieben anordnen, ich bevorzuge es.

Das lib/ist app.lua, und utils.lua- zusammen das ist meine Sammlung von nützlichen Funktionen für die mit Corona SDK arbeiten. Die app.luaimplementiert bequeme Wrapper über Standardfunktionen Corona SDK Bilder, Text, Schaltflächen angezeigt werden , und andere.

Der Übergang von der main.luain scenes/menu.luadurch die Leitung
storyboard.gotoScene('scenes.menu')

Wo wiederum die Pinguinanforderung bereits auf dem Server ausgeführt wird. Hier ist der Hauptcode von menu.lua.
function scene:createScene (event)
    local group = self.view
    app.newText{g = group, text = 'Penguin Daycare', size = 32, x = _CX, y = _CY - 150}
    app.newText{g = group, text = 'Simulator', size = 32, x = _CX, y = _CY - 110}
    local pleaseWait = app.newText{g = group, text = 'Please Wait', size = 16, x = _CX, y = _CY}
    local button = app.newButton{g = group, x = _CX, y = _CY,
        text = 'Enter the Daycare',
        onRelease = function()
            storyboard.gotoScene('scenes.choose', {effect = 'slideLeft', time = app.duration})
        end}
    button.isVisible = false
    app.api:getPenguins(function()
            pleaseWait.isVisible = false
            button.isVisible = true
        end)
end

Es werden drei Textzeilen und eine Schaltfläche erstellt. Die Schaltfläche ist ausgeblendet, bis wir eine Antwort vom Server erhalten. Die Anforderung selbst wird von einer Funktion ausgeführt app.api:getPenguins()und verfügt als Argument über eine Rückruffunktion.

Nachdem wir auf die Schaltfläche geklickt haben, gelangen wir zur Pinguinauswahlszene. Ich werde auch nur den Hauptteil des Codes aus der Datei angeben choose.lua.
function scene:createScene(event)
    local group = self.view
    self.backButton = app.newButton{g = group, x = _L + 10, y = _T + 10, w = 48, h = 32, rp = 'TopLeft',
        text = 'Back',
        fontSize = 14,
        onRelease = function()
            storyboard.gotoScene('scenes.menu', {effect = 'slideRight', time = app.duration})
        end}
    local function gotoPenguin(ind)
        storyboard.gotoScene('scenes.penguin', {effect = 'slideLeft', time = app.duration, params = ind})
    end
    local slideView = newSlideView{g = group, x = 0, y = _CY, dots_y = 180, onRelease = gotoPenguin}
    for i = 1, #app.api.penguins do
        local p = app.api.penguins[i]
        local slide = display.newGroup()
        app.newImage('images/popup.png', {g = slide, w = 300, h = 335})
        app.newImage('images/penguins/' .. p.id .. '.png', {g = slide, w = 200, h = 256})
        app.newText{g = slide, x = 0, y = -140, text = p.name, size = 18, color = 'white'}
        app.newText{g = slide, x = 0, y = 140, text = p.bio, size = 14, color = 'white', w = 220, align = 'center'}
        slideView:addSlide(slide)
    end
    slideView:makeDots()
    slideView:gotoSlide(1)
end

Hier ist newSlideView()es eine Funktion, die ein einfaches Widget erstellt, mit dem Sie mit Pinguinen durch die Folien scrollen können. Der Code für dieses Widget befindet sich direkt choose.luaam Anfang der Datei.

Für jeden Pinguin wird eine Folie erstellt. Bilder von Pinguinen werden in der Anwendung gespeichert und entsprechen der ID von Pinguinen. Dies kann behoben werden, indem Bilder auf einem GAE-Server oder einem anderen Server gespeichert werden. Zum Herunterladen von Bildern aus dem Netzwerk verfügt das Corona SDK über eine Funktion display.loadRemoteImage()oder eine niedrigere Ebene network.download().

Durch Klicken auf die Folie wird eine Funktion aufgerufen gotoPenguin(), die die Nummer des (Nicht- Id) Pinguins im Array (Tabelle) aller empfangenen Pinguine empfängt . Diese Funktion springt zur letzten Szene penguin.luaund übergibt das gleiche Argument an diese Szene.
penguin.lua
function scene:createScene(event)
    local group = self.view
    local background = app.newImage('images/background.jpg', {g = group, w = 384, h = 640, x = _CX, y = _CY})
    self.backButton = app.newButton{g = group, x = _L + 10, y = _T + 10, w = 48, h = 32, rp = 'TopLeft',
        text = 'Back',
        fontSize = 14,
        onRelease = function()
            storyboard.gotoScene('scenes.choose', {effect = 'slideRight', time = app.duration})
        end}
    local ind = event.params
    local p = app.api.penguins[ind]
    local visitsLabel = app.newText{g = group, x = _CX, y = _T + 20, text = 'Visits: ' .. p.visit_count, size = 18, color = 'white'}
    local fishLabel = app.newText{g = group, x = _CX, y = _T + 40, text = 'Fish: ' .. p.fish_count, size = 18, color = 'white'}
    local bellyrubsLabel = app.newText{g = group, x = _CX, y = _T + 60, text = 'Belly rubs: ' .. p.bellyrub_count, size = 18, color = 'white'}
    local penguin = app.newImage('images/penguins/' .. p.id .. '.png', {g = group, w = 200, h = 256, x = _CX, y = _CY - 25})
    app.newButton{g = group, x = _CX - 80, y = _B - 50, w = 128, h = 48,
        text = 'Fish',
        fontSize = 14,
        onRelease = function()
            local fish = app.newImage('images/fish.png', {g = group, x = penguin.x, y = penguin.y + 200, w = 512, h = 188})
            fish.alpha = 0.8
            transition.to(fish, {time = 400, alpha = 1, y = penguin.y, xScale = 0.1, yScale = 0.1, transition = easing.outExpo, onComplete = function(obj)
                    transition.to(fish, {time = 400, alpha = 0, onComplete = function(obj)
                            display.remove(obj)
                        end})
                end})
            app.api:sendFish(p.id)
            p.fish_count = p.fish_count + 1
            fishLabel:setText('Fish: ' .. p.fish_count)
        end}
    app.newButton{g = group, x = _CX + 80, y = _B - 50, w = 128, h = 48,
        text = 'Belly rub',
        fontSize = 14,
        onRelease = function()
            local hand = app.newImage('images/hand.png', {g = group, x = penguin.x - 40, y = penguin.y + 30, w = 80, h = 80, rp = 'TopLeft'})
            transition.to(hand, {time = 1200, x = penguin.x + 40, transition = easing.swing3(easing.outQuad), onComplete = function(obj)
                    display.remove(obj)
                end})
            app.api:sendBellyrub(p.id)
            p.bellyrub_count = p.bellyrub_count + 1
            bellyrubsLabel:setText('Belly rubs: ' .. p.bellyrub_count)
        end}
    app.api:sendVisit(p.id)
    p.visit_count = p.visit_count + 1
    visitsLabel:setText('Visits: ' .. p.visit_count)
end

Beim penguin.luaLaden des Hintergrundbildes wird das Bild des ausgewählten Pinguins, die Anzeige mehrerer Textbeschriftungen und zwei Aktionsschaltflächen angezeigt. Wenn Sie darauf klicken, wird die Aktion animiert und die Anforderung über die Funktionen app.api:sendFish()und an den Server gesendet app.api:sendBellyrub(). Und es app.api:sendVisit()wird direkt nach dem Erstellen der Szene aufgerufen. Nach dem Aufrufen jeder dieser Funktionen werden die entsprechenden Textbezeichnungen aktualisiert, auch wenn kein Internet vorhanden ist. Dies kann behoben werden, indem für jede Anforderung nach einer Antwort vom Server gesucht und Rückruffunktionen bereitgestellt werden.

Schließlich werden alle Arbeiten mit dem Server in einer Datei ausgeführt lib/api.lua.
api.lua
local _M = {}
local app = require('lib.app')
_M.hostname = 'http://penguin-daycare-simulator.appspot.com'
function _M:getPenguins(callback)
    local url = '/penguins#' .. math.random(1000, 9999)
    network.request(self.hostname .. url , 'GET', function (event)
        if not event.isError then
            local response = json.decode(event.response)
            if response then
                self.penguins = response
                callback()
            end
        end
    end)
end
function _M:sendVisit(id)
    local url = '/stat/visit'
    local request = {body = 'id=' .. id}
    network.request(self.hostname .. url , 'POST', function (event)
        if event.isError then
            app.alert('Network error')
        end
    end, request)
end
function _M:sendFish(id)
    local url = '/stat/fish'
    local request = {body = 'id=' .. id}
    network.request(self.hostname .. url , 'POST', function (event)
        if event.isError then
            app.alert('Network error')
        end
    end, request)
end
function _M:sendBellyrub(id)
    local url = '/stat/bellyrub'
    local request = {body = 'id=' .. id}
    network.request(self.hostname .. url , 'POST', function (event)
        if event.isError then
            app.alert('Network error')
        end
    end, request)
end
return _M 

Wie Sie vielleicht vermutet haben, erfolgt die Arbeit mit dem Server mit einfachen POST-Anforderungen. In diesem Fall getPenguins()wird die Antwort vom Server durch eine Funktion vom JSON-Format in ein Array (eine Tabelle) konvertiert json.decode()und in das Feld (Eigenschaft) des Moduls gestellt.

Wie Sie sehen können, ist das Senden von POST-Anfragen und das Beantworten ihrer Antworten im Corona SDK sehr einfach. Dementsprechend war die Integration in die Google App Engine selbst sehr einfach. Ich male nicht, was jede Zeile tut, ich hoffe, die Syntax ist intuitiv.

8. Referenzen


Die Quellen sind auf meinem GitHub:

Sie können den Client-Teil unter Android 2.3.3+ installieren. Hier ist die APK ( Spiegel ).
Oder laden Sie das Corona SDK herunter, laden Sie die Quellen von GitHub herunter und führen Sie es in Corona Simulator aus.

Vielen Dank an M0sTH8 für die Unterstützung beim Schreiben dieses Artikels.

Abonniere meinen Twitter @SergeyLerg

Das ist alles. Vielen Dank für Ihre Aufmerksamkeit!

Jetzt auch beliebt: