liveops para games usando o firebase

40
LiveOps para games usando Firebase Vítor Bruno de Almeida Senior Software Engineer @vb

Upload: vitor-bruno-de-almeida

Post on 22-Jan-2018

170 views

Category:

Software


0 download

TRANSCRIPT

LiveOps para games usando Firebase

Vítor Bruno de AlmeidaSenior Software Engineer

@vb

Live Game Operations

Testes passando

Backlog vazio

App publicado

Android Dev Conference 2017

CHURN

Source: Quettra, Average retention for Google Play Apps - 2016

Android Dev Conference 2017Source: Quettra, Average retention for Google Play Apps - 2016

Android Dev Conference 2017Source: AppsFlyer, The State of App Engagement 2017

Android Dev Conference 2017

“Retention is the king.”Bria Balfour, VP Growth @ HubSpot

Android Dev Conference 2017

Retention

Lifetime Value

Tempo de payback

Viralidade

Android Dev Conference 2017Source: Quettra, How do the best apps perform - 2016

Conteúdo é essencial

Jogadores ficam engajados por mais tempo

Tempo é dinheiro

Alto engajamento e retenção levam a um melhor LTV

=

Android Dev Conference 2017

Distribuição de conteúdo

Ofertas especiais

Eventos e competições

Firebase

PlataformaFirebase

Remote Config

Android Dev Conference 2017

Remote Config

Cloud Storage

Android Dev Conference 2017

Remote Config

Cloud Storage

Realtime Database

Android Dev Conference 2017

Remote Config

Cloud Storage

Realtime Database

Cloud Messaging

Android Dev Conference 2017

Remote Config

Cloud Storage

Realtime Database

Cloud Messaging

Cloud Functions

Android Dev Conference 2017

Android Dev Conference 2017

Mãos à obra!

Android Dev Conference 2017

1. UPDATE FORÇADO

OK

fun hasLatestVersion(): Boolean {return FirebaseRemoteConfig.getInstance()

.getLong("latest_version")

.toInt() == BuildConfig.VERSION_CODE}

fun onCreate() {if (hasLatestVersion()) {

launchGameActivity()} else {

launchForceUpdateDialog()}

}

2. Caixa de notícias

fun onGameStart() {val latestNewsId = FirebaseRemoteConfig.getInstance()

.getLong("latest_news_id")if (latestNewsId > loadLastNewsFromDb().id) {

loadNews(latestNewsId, { news -> displayNews(news) })}

}

fun loadNews(newsId: Long, callback: (newsTitle: News) -> Unit) {FirebaseDatabase.getInstance().getReference("news")

.child(newsId.toString())

.addListenerForSingleValueEvent {data -> data.getValue(News::class.java)?.let(callback)

}}

3. Sincronização de relógio

const functions = require('firebase-functions');const moment = require('moment');const cors = require('cors')({origin: true});

exports.date = functions.https.onRequest((req, res) => {cors(req, res, () => {res.status(200).send(moment().format());

});});

https://us-central1-meujogo.cloudfunctions.net/date

fun onGameStart() {getServerTime({ serverTime -> setGameTime(serverTime) })

}

fun getServerTime(callback: (serverTime: Instant) -> Unit) {"https://us-central1-meujogo.cloudfunctions.net/date".httpGet()

.responseString { request, response, result ->when (result) {

is Result.Success -> {callback(Instant.parse(result.getAs()))

}}

}}

https://github.com/kittinunf/Fuel

4. Eventos 4. Eventos

fun onGameResume() {FirebaseDatabase.getInstance().getReference("events")

.orderByChild("fim")

.limitToLast(5)

.addListenerForSingleValueEvent { data ->val now = Instant.now()data?.children?.find {

val event = it.getValue(EventConfig::class.java)event.fim.isAfter(now) && event.inicio.isBefore(now)

}?.let {startNewEvent(it.getValue(EventConfig::class.java))

}}

}

fun onVictory(gold: Long, xp: Long) {val event = gameState.currentEventplayer.earnGold(if (event != null) (gold * event.multGold).toLong() else gold)player.earnXp(if (event != null) (xp * event.multXp).toLong() else xp)

}

5. Ofertas

class Item(val sku: String, val image: String)class Shop {

val items = ArrayList<Item>()}

private fun onShopOpened(shop: Shop) {FirebaseDatabase.getInstance().getReference("shop")

.addListenerForSingleValueEvent { data ->data?.children?.forEach { itemConfig ->

val itemDbKey = FirebaseRemoteConfig.getInstance().getString(itemConfig.key)

addItemToShop(itemDbKey, shop)}

}}

private fun addItemToShop(dbKey: String, shop: Shop) {FirebaseDatabase.getInstance().getReference("items")

.addListenerForSingleValueEvent { data ->data?.child(dbKey)?.getValue(Item::class.java)?.let {

shop.items.add(it)}

}}

PLANEJAMENTO É ESSENCIAL

Android Dev Conference 2017

Obrigado pela presença!

Contato:

[email protected]

Imagens e ferramentas:

● https://unsplash.com/● https://www.pexels.com/● http://typicalhope.tumblr.com/● http://www.thokamaer.com/● http://jonasmosesson.se/● https://romannurik.github.io/SlidesCodeHighlighter/