← Volver al listado de tecnologías
Integración con Redes Sociales y Game Center/Google Play Games
Integración con Redes Sociales y Game Center/Google Play Games
La integración social es clave para el engagement y la viralidad de tu juego móvil. Esta guía te enseñará a implementar un sistema completo de funciones sociales.
Configuración Base de Servicios Sociales
1. Game Center (iOS) Setup
Configuración iOS
# game.project
[ios]
bundle_identifier = com.miestudio.mijuego
infoplist = /bundles/ios/Info.plist
[project]
dependencies = https://github.com/defold/extension-gamekit/archive/main.zip
Info.plist
<!-- Game Center Configuration -->
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>gamekit</string>
</array>
<!-- Background modes for Game Center -->
<key>UIBackgroundModes</key>
<array>
<string>gamekit</string>
</array>
2. Google Play Games Setup
AndroidManifest.xml
<!-- Google Play Games Services -->
<meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="@string/app_id" />
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<!-- Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Strings.xml
<resources>
<string name="app_id">123456789012</string>
<string name="leaderboard_high_scores">CgkI123456789EAIQAQ</string>
<string name="achievement_first_win">CgkI123456789EAIQBA</string>
</resources>
3. Social Manager Core
Sistema Central de Gestión Social
-- social_manager.script
local M = {}
function init(self)
self.platform = sys.get_sys_info().system_name
self.authenticated = false
self.player_info = {}
self.achievements = {}
self.leaderboards = {}
-- Configuración
self.config = {
auto_authenticate = true,
show_welcome_banner = true,
cache_achievements = true,
offline_mode = false
}
-- Estados
self.authentication_in_progress = false
self.pending_operations = {}
print("Social Manager initialized for platform: " .. self.platform)
end
function M.initialize(self, callback)
if self.platform == "iPhone OS" then
self:initialize_game_center(callback)
elseif self.platform == "Android" then
self:initialize_google_play_games(callback)
else
print("Social features not available on this platform")
if callback then callback(false, "unsupported_platform") end
end
end
function M.authenticate(self, callback)
if self.authentication_in_progress then
table.insert(self.pending_operations, {type = "authenticate", callback = callback})
return
end
self.authentication_in_progress = true
if self.platform == "iPhone OS" then
self:authenticate_game_center(callback)
elseif self.platform == "Android" then
self:authenticate_google_play_games(callback)
end
end
function M.initialize_game_center(self, callback)
if gamekit then
gamekit.set_callback(function(self, message_id, message)
M.handle_game_center_callback(self, message_id, message)
end)
-- Autenticar automáticamente si está configurado
if self.config.auto_authenticate then
self:authenticate_game_center(callback)
end
else
print("GameKit extension not available")
if callback then callback(false, "gamekit_not_available") end
end
end
function M.authenticate_game_center(self, callback)
if not gamekit then
if callback then callback(false, "gamekit_not_available") end
return
end
gamekit.authenticate(function(self, result)
self.authentication_in_progress = false
if result.success then
self.authenticated = true
self.player_info = {
player_id = result.player_id,
display_name = result.display_name,
alias = result.alias
}
print("Game Center authentication successful")
print("Player: " .. (result.display_name or result.alias))
-- Cargar logros y leaderboards
self:load_game_center_data()
if callback then callback(true, result) end
else
print("Game Center authentication failed: " .. (result.error or "Unknown error"))
if callback then callback(false, result.error) end
end
-- Procesar operaciones pendientes
self:process_pending_operations()
end)
end
function M.handle_game_center_callback(self, message_id, message)
if message_id == gamekit.MSG_AUTHENTICATION then
-- Manejar cambios en autenticación
if message.authenticated then
print("Game Center: Player authenticated")
else
print("Game Center: Player signed out")
self.authenticated = false
self.player_info = {}
end
elseif message_id == gamekit.MSG_ACHIEVEMENT then
self:handle_achievement_response(message)
elseif message_id == gamekit.MSG_LEADERBOARD then
self:handle_leaderboard_response(message)
end
end
return M
Achievements System
1. Achievement Manager
Sistema de Logros
-- achievement_manager.lua
local M = {}
function init(self)
self.achievements = {}
self.local_progress = {}
self.social_manager = require "main.social_manager"
-- Definir logros del juego
self:setup_achievements()
end
function M.setup_achievements(self)
self.achievements = {
first_level = {
id = "first_level",
ios_id = "com.miestudio.mijuego.first_level",
android_id = "CgkI123456789EAIQBA",
name = "Primer Nivel",
description = "Completa tu primer nivel",
points = 10,
hidden = false,
incremental = false
},
score_1000 = {
id = "score_1000",
ios_id = "com.miestudio.mijuego.score_1000",
android_id = "CgkI123456789EAIQBB",
name = "Puntuación Alta",
description = "Alcanza 1000 puntos",
points = 20,
hidden = false,
incremental = false
},
level_master = {
id = "level_master",
ios_id = "com.miestudio.mijuego.level_master",
android_id = "CgkI123456789EAIQBC",
name = "Maestro de Niveles",
description = "Completa 50 niveles",
points = 50,
hidden = false,
incremental = true,
steps = 50
},
coin_collector = {
id = "coin_collector",
ios_id = "com.miestudio.mijuego.coin_collector",
android_id = "CgkI123456789EAIQBD",
name = "Coleccionista",
description = "Recolecta 10,000 monedas",
points = 30,
hidden = false,
incremental = true,
steps = 10000
},
secret_finder = {
id = "secret_finder",
ios_id = "com.miestudio.mijuego.secret_finder",
android_id = "CgkI123456789EAIQBE",
name = "Explorador Secreto",
description = "Encuentra la sala secreta",
points = 100,
hidden = true,
incremental = false
}
}
end
function M.unlock_achievement(self, achievement_id, progress)
local achievement = self.achievements[achievement_id]
if not achievement then
print("Unknown achievement: " .. achievement_id)
return false
end
progress = progress or (achievement.incremental and 1 or 100)
-- Actualizar progreso local
if not self.local_progress[achievement_id] then
self.local_progress[achievement_id] = 0
end
if achievement.incremental then
self.local_progress[achievement_id] = self.local_progress[achievement_id] + progress
local total_progress = self.local_progress[achievement_id]
-- Verificar si se completó
if total_progress >= achievement.steps then
self:report_achievement_complete(achievement)
else
self:report_achievement_progress(achievement, total_progress)
end
else
self.local_progress[achievement_id] = 100
self:report_achievement_complete(achievement)
end
-- Guardar progreso localmente
self:save_achievement_progress()
return true
end
function report_achievement_complete(self, achievement)
print("Achievement unlocked: " .. achievement.name)
-- Reportar a plataforma social
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" then
self:report_ios_achievement(achievement.ios_id, 100)
elseif self.social_manager.platform == "Android" then
self:report_android_achievement(achievement.android_id)
end
end
-- Mostrar notificación local
self:show_achievement_notification(achievement)
-- Trackear para analytics
msg.post("main:/analytics", "track_event", {
event = "achievement_unlocked",
properties = {
achievement_id = achievement.id,
achievement_name = achievement.name,
points = achievement.points
}
})
end
function report_achievement_progress(self, achievement, progress)
local percent = math.floor((progress / achievement.steps) * 100)
print(string.format("Achievement progress: %s - %d/%d (%d%%)",
achievement.name, progress, achievement.steps, percent))
-- Reportar progreso a plataforma social
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" then
self:report_ios_achievement(achievement.ios_id, percent)
elseif self.social_manager.platform == "Android" then
self:report_android_achievement_progress(achievement.android_id, progress)
end
end
end
function report_ios_achievement(self, achievement_id, percent_complete)
if gamekit then
gamekit.report_achievement(achievement_id, percent_complete, function(self, result)
if result.success then
print("iOS achievement reported successfully")
else
print("Failed to report iOS achievement: " .. (result.error or "Unknown"))
end
end)
end
end
function report_android_achievement(self, achievement_id)
if gpgs then
gpgs.achievement_unlock(achievement_id, function(self, result)
if result.success then
print("Android achievement unlocked successfully")
else
print("Failed to unlock Android achievement: " .. (result.error or "Unknown"))
end
end)
end
end
function report_android_achievement_progress(self, achievement_id, steps)
if gpgs then
gpgs.achievement_increment(achievement_id, steps, function(self, result)
if result.success then
print("Android achievement progress updated")
else
print("Failed to update Android achievement progress: " .. (result.error or "Unknown"))
end
end)
end
end
function show_achievement_notification(self, achievement)
-- Mostrar UI de achievement
msg.post("main:/ui", "show_achievement_unlocked", {
name = achievement.name,
description = achievement.description,
points = achievement.points,
icon = achievement.icon or "default_achievement_icon"
})
end
function M.show_achievements_ui(self)
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" and gamekit then
gamekit.show_achievements()
elseif self.social_manager.platform == "Android" and gpgs then
gpgs.show_achievements()
end
else
-- Mostrar UI local de achievements
msg.post("main:/ui", "show_local_achievements", {
achievements = self.achievements,
progress = self.local_progress
})
end
end
-- Helper functions
function save_achievement_progress(self)
local save_data = json.encode(self.local_progress)
sys.save(sys.get_save_file("main", "achievements"), save_data)
end
function load_achievement_progress(self)
local save_file = sys.get_save_file("main", "achievements")
local save_data = sys.load(save_file)
if save_data then
local ok, progress = pcall(json.decode, save_data)
if ok then
self.local_progress = progress
end
end
end
return M
2. Achievement Triggers
Sistema de Triggers para Logros
-- achievement_triggers.lua
local M = {}
function init(self)
self.achievement_manager = require "main.achievement_manager"
self.game_stats = {
levels_completed = 0,
total_score = 0,
coins_collected = 0,
enemies_defeated = 0,
power_ups_used = 0,
playtime_seconds = 0
}
-- Cargar estadísticas guardadas
self:load_game_stats()
end
function M.on_level_complete(self, level_number, score, time)
self.game_stats.levels_completed = self.game_stats.levels_completed + 1
self.game_stats.total_score = self.game_stats.total_score + score
-- Trigger achievements
if self.game_stats.levels_completed == 1 then
self.achievement_manager:unlock_achievement("first_level")
end
if self.game_stats.levels_completed >= 50 then
self.achievement_manager:unlock_achievement("level_master", 1)
end
if score >= 1000 then
self.achievement_manager:unlock_achievement("score_1000")
end
-- Achievement por tiempo
if time <= 60 then -- Completar en menos de 1 minuto
self.achievement_manager:unlock_achievement("speed_runner")
end
self:save_game_stats()
end
function M.on_coin_collected(self, amount)
self.game_stats.coins_collected = self.game_stats.coins_collected + amount
-- Achievement incremental de monedas
self.achievement_manager:unlock_achievement("coin_collector", amount)
self:save_game_stats()
end
function M.on_enemy_defeated(self, enemy_type)
self.game_stats.enemies_defeated = self.game_stats.enemies_defeated + 1
-- Achievements específicos por tipo de enemigo
if enemy_type == "boss" then
self.achievement_manager:unlock_achievement("boss_slayer")
end
-- Achievement por cantidad total
if self.game_stats.enemies_defeated >= 1000 then
self.achievement_manager:unlock_achievement("enemy_destroyer")
end
self:save_game_stats()
end
function M.on_secret_area_found(self, area_id)
-- Achievement secreto
self.achievement_manager:unlock_achievement("secret_finder")
-- Achievement por encontrar todas las áreas secretas
local secret_areas_found = self:get_secret_areas_found()
if secret_areas_found >= 10 then
self.achievement_manager:unlock_achievement("master_explorer")
end
end
function M.on_perfect_level(self, level_number)
-- Nivel completado sin morir y recogiendo todos los items
self.achievement_manager:unlock_achievement("perfectionist")
end
function M.on_daily_login(self, consecutive_days)
if consecutive_days >= 7 then
self.achievement_manager:unlock_achievement("daily_player")
end
if consecutive_days >= 30 then
self.achievement_manager:unlock_achievement("dedicated_player")
end
end
function M.check_playtime_achievements(self, session_time)
self.game_stats.playtime_seconds = self.game_stats.playtime_seconds + session_time
local hours_played = self.game_stats.playtime_seconds / 3600
if hours_played >= 10 then
self.achievement_manager:unlock_achievement("veteran_player")
end
if hours_played >= 100 then
self.achievement_manager:unlock_achievement("master_player")
end
self:save_game_stats()
end
-- Helper functions
function save_game_stats(self)
local save_data = json.encode(self.game_stats)
sys.save(sys.get_save_file("main", "game_stats"), save_data)
end
function load_game_stats(self)
local save_file = sys.get_save_file("main", "game_stats")
local save_data = sys.load(save_file)
if save_data then
local ok, stats = pcall(json.decode, save_data)
if ok then
self.game_stats = stats
end
end
end
function get_secret_areas_found(self)
-- Implementar conteo de áreas secretas encontradas
return 0
end
return M
Leaderboards System
1. Leaderboard Manager
Sistema de Leaderboards
-- leaderboard_manager.lua
local M = {}
function init(self)
self.leaderboards = {}
self.local_scores = {}
self.social_manager = require "main.social_manager"
-- Configurar leaderboards
self:setup_leaderboards()
end
function M.setup_leaderboards(self)
self.leaderboards = {
high_scores = {
id = "high_scores",
ios_id = "com.miestudio.mijuego.high_scores",
android_id = "CgkI123456789EAIQAQ",
name = "Puntuación Más Alta",
score_format = "numeric",
order = "descending"
},
fastest_times = {
id = "fastest_times",
ios_id = "com.miestudio.mijuego.fastest_times",
android_id = "CgkI123456789EAIQAR",
name = "Tiempos Más Rápidos",
score_format = "time",
order = "ascending"
},
levels_completed = {
id = "levels_completed",
ios_id = "com.miestudio.mijuego.levels_completed",
android_id = "CgkI123456789EAIQAS",
name = "Niveles Completados",
score_format = "numeric",
order = "descending"
},
weekly_challenge = {
id = "weekly_challenge",
ios_id = "com.miestudio.mijuego.weekly_challenge",
android_id = "CgkI123456789EAIQAT",
name = "Desafío Semanal",
score_format = "numeric",
order = "descending",
reset_period = "weekly"
}
}
end
function M.submit_score(self, leaderboard_id, score, callback)
local leaderboard = self.leaderboards[leaderboard_id]
if not leaderboard then
print("Unknown leaderboard: " .. leaderboard_id)
if callback then callback(false, "unknown_leaderboard") end
return
end
-- Guardar score localmente
self:save_local_score(leaderboard_id, score)
-- Verificar si es un record personal
local is_personal_best = self:is_personal_best(leaderboard_id, score)
if is_personal_best then
print("New personal best! " .. leaderboard.name .. ": " .. score)
-- Mostrar celebración de record personal
msg.post("main:/ui", "show_personal_best", {
leaderboard_name = leaderboard.name,
score = score,
previous_best = self:get_previous_best(leaderboard_id)
})
end
-- Enviar a plataforma social si está autenticado
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" then
self:submit_ios_score(leaderboard.ios_id, score, callback)
elseif self.social_manager.platform == "Android" then
self:submit_android_score(leaderboard.android_id, score, callback)
end
else
-- Solo guardar localmente
if callback then callback(true, {local_only = true}) end
end
-- Trackear para analytics
msg.post("main:/analytics", "track_event", {
event = "score_submitted",
properties = {
leaderboard_id = leaderboard_id,
score = score,
is_personal_best = is_personal_best
}
})
end
function submit_ios_score(self, leaderboard_id, score, callback)
if gamekit then
gamekit.report_score(leaderboard_id, score, function(self, result)
if result.success then
print("iOS score submitted successfully")
if callback then callback(true, result) end
else
print("Failed to submit iOS score: " .. (result.error or "Unknown"))
if callback then callback(false, result.error) end
end
end)
end
end
function submit_android_score(self, leaderboard_id, score, callback)
if gpgs then
gpgs.leaderboard_submit_score(leaderboard_id, score, function(self, result)
if result.success then
print("Android score submitted successfully")
if callback then callback(true, result) end
else
print("Failed to submit Android score: " .. (result.error or "Unknown"))
if callback then callback(false, result.error) end
end
end)
end
end
function M.show_leaderboard(self, leaderboard_id)
local leaderboard = self.leaderboards[leaderboard_id]
if not leaderboard then
print("Unknown leaderboard: " .. leaderboard_id)
return
end
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" and gamekit then
gamekit.show_leaderboard(leaderboard.ios_id)
elseif self.social_manager.platform == "Android" and gpgs then
gpgs.show_leaderboard(leaderboard.android_id)
end
else
-- Mostrar leaderboard local
self:show_local_leaderboard(leaderboard_id)
end
end
function M.show_all_leaderboards(self)
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" and gamekit then
gamekit.show_leaderboards()
elseif self.social_manager.platform == "Android" and gpgs then
gpgs.show_all_leaderboards()
end
else
msg.post("main:/ui", "show_local_leaderboards", {
leaderboards = self.leaderboards,
scores = self.local_scores
})
end
end
function M.get_leaderboard_scores(self, leaderboard_id, callback)
local leaderboard = self.leaderboards[leaderboard_id]
if not leaderboard then
if callback then callback(false, "unknown_leaderboard") end
return
end
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" then
self:get_ios_leaderboard_scores(leaderboard.ios_id, callback)
elseif self.social_manager.platform == "Android" then
self:get_android_leaderboard_scores(leaderboard.android_id, callback)
end
else
-- Devolver scores locales
local local_scores = self:get_local_leaderboard_scores(leaderboard_id)
if callback then callback(true, {scores = local_scores, local_only = true}) end
end
end
function get_ios_leaderboard_scores(self, leaderboard_id, callback)
if gamekit then
gamekit.load_leaderboard_scores(leaderboard_id, function(self, result)
if callback then callback(result.success, result) end
end)
end
end
function get_android_leaderboard_scores(self, leaderboard_id, callback)
if gpgs then
gpgs.leaderboard_get_scores(leaderboard_id, function(self, result)
if callback then callback(result.success, result) end
end)
end
end
-- Local score management
function save_local_score(self, leaderboard_id, score)
if not self.local_scores[leaderboard_id] then
self.local_scores[leaderboard_id] = {}
end
table.insert(self.local_scores[leaderboard_id], {
score = score,
timestamp = os.time(),
player_name = "Jugador"
})
-- Mantener solo los mejores 10 scores
local leaderboard = self.leaderboards[leaderboard_id]
table.sort(self.local_scores[leaderboard_id], function(a, b)
if leaderboard.order == "descending" then
return a.score > b.score
else
return a.score < b.score
end
end)
if #self.local_scores[leaderboard_id] > 10 then
table.remove(self.local_scores[leaderboard_id])
end
self:save_local_scores()
end
function is_personal_best(self, leaderboard_id, score)
local scores = self.local_scores[leaderboard_id]
if not scores or #scores == 0 then
return true
end
local leaderboard = self.leaderboards[leaderboard_id]
local best_score = scores[1].score
if leaderboard.order == "descending" then
return score > best_score
else
return score < best_score
end
end
function get_previous_best(self, leaderboard_id)
local scores = self.local_scores[leaderboard_id]
if scores and #scores > 0 then
return scores[1].score
end
return 0
end
function save_local_scores(self)
local save_data = json.encode(self.local_scores)
sys.save(sys.get_save_file("main", "leaderboards"), save_data)
end
function load_local_scores(self)
local save_file = sys.get_save_file("main", "leaderboards")
local save_data = sys.load(save_file)
if save_data then
local ok, scores = pcall(json.decode, save_data)
if ok then
self.local_scores = scores
end
end
end
return M
Social Sharing
1. Share Manager
Sistema de Compartir en Redes Sociales
-- share_manager.lua
local M = {}
function init(self)
self.share_providers = {
native = true,
facebook = false,
twitter = false,
instagram = false
}
-- Verificar disponibilidad de providers
self:check_available_providers()
end
function M.check_available_providers(self)
-- Verificar Facebook
if facebook then
self.share_providers.facebook = true
end
-- Native sharing siempre disponible en móviles
if sys.get_sys_info().system_name == "iPhone OS" or
sys.get_sys_info().system_name == "Android" then
self.share_providers.native = true
end
end
function M.share_score(self, score, level, image_path, callback)
local share_text = string.format("¡Acabo de conseguir %d puntos en el nivel %d! ¿Puedes superarlo?", score, level)
local share_url = "https://miapp.com/challenge/" .. score
local share_data = {
text = share_text,
url = share_url,
image = image_path,
hashtags = {"gaming", "highscore", "mobile"}
}
self:show_share_options(share_data, callback)
end
function M.share_achievement(self, achievement_name, achievement_description, image_path, callback)
local share_text = string.format("¡Desbloqueé el logro '%s'! %s", achievement_name, achievement_description)
local share_url = "https://miapp.com/achievement/" .. achievement_name
local share_data = {
text = share_text,
url = share_url,
image = image_path,
hashtags = {"achievement", "gaming", "mobile"}
}
self:show_share_options(share_data, callback)
end
function M.share_level_complete(self, level, time, score, image_path, callback)
local share_text = string.format("¡Completé el nivel %d en %d segundos con %d puntos!", level, time, score)
local share_url = "https://miapp.com/level/" .. level
local share_data = {
text = share_text,
url = share_url,
image = image_path,
hashtags = {"levelcomplete", "gaming", "mobile"}
}
self:show_share_options(share_data, callback)
end
function show_share_options(self, share_data, callback)
-- Mostrar opciones de compartir disponibles
local options = {}
if self.share_providers.native then
table.insert(options, {
id = "native",
name = "Compartir",
icon = "share_icon"
})
end
if self.share_providers.facebook then
table.insert(options, {
id = "facebook",
name = "Facebook",
icon = "facebook_icon"
})
end
if self.share_providers.twitter then
table.insert(options, {
id = "twitter",
name = "Twitter",
icon = "twitter_icon"
})
end
if #options == 1 then
-- Solo una opción disponible, usar directamente
self:execute_share(options[1].id, share_data, callback)
else
-- Mostrar selector de opciones
msg.post("main:/ui", "show_share_options", {
options = options,
share_data = share_data,
callback = function(selected_provider)
self:execute_share(selected_provider, share_data, callback)
end
})
end
end
function execute_share(self, provider, share_data, callback)
if provider == "native" then
self:share_native(share_data, callback)
elseif provider == "facebook" then
self:share_facebook(share_data, callback)
elseif provider == "twitter" then
self:share_twitter(share_data, callback)
end
end
function share_native(self, share_data, callback)
-- Usar sistema nativo de compartir del SO
local platform = sys.get_sys_info().system_name
if platform == "iPhone OS" then
-- iOS Activity View Controller
self:share_ios_native(share_data, callback)
elseif platform == "Android" then
-- Android Intent
self:share_android_native(share_data, callback)
end
end
function share_ios_native(self, share_data, callback)
-- Implementar usando extension nativa o webview
local share_text = share_data.text
if share_data.url then
share_text = share_text .. " " .. share_data.url
end
-- En una implementación real, usarías una extensión nativa
print("iOS Native Share: " .. share_text)
if callback then callback(true, "shared_native") end
end
function share_android_native(self, share_data, callback)
-- Implementar usando Android Intent
local share_text = share_data.text
if share_data.url then
share_text = share_text .. " " .. share_data.url
end
-- En una implementación real, usarías una extensión nativa
print("Android Native Share: " .. share_text)
if callback then callback(true, "shared_native") end
end
function share_facebook(self, share_data, callback)
if not facebook then
if callback then callback(false, "facebook_not_available") end
return
end
local fb_params = {
link = share_data.url,
quote = share_data.text
}
facebook.show_dialog("share", fb_params, function(result)
local success = result and not result.error
if success then
print("Facebook share successful")
-- Trackear share
msg.post("main:/analytics", "track_event", {
event = "content_shared",
properties = {
platform = "facebook",
content_type = "score",
success = true
}
})
else
print("Facebook share failed: " .. (result.error or "Unknown"))
end
if callback then callback(success, result) end
end)
end
function M.invite_friends(self, callback)
local invite_data = {
title = "¡Únete a la diversión!",
message = "¡Descarga este increíble juego y vamos a competir!",
url = "https://miapp.com/download",
image = "/assets/invite_image.png"
}
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" and gamekit then
-- Usar Game Center para invitar amigos
self:invite_game_center_friends(invite_data, callback)
elseif self.social_manager.platform == "Android" and gpgs then
-- Usar Google Play Games para invitar
self:invite_google_play_friends(invite_data, callback)
end
else
-- Fallback a compartir normal
self:share_native(invite_data, callback)
end
end
function invite_game_center_friends(self, invite_data, callback)
if gamekit then
gamekit.show_request_dialog({
message = invite_data.message,
recipient_players = {}, -- Vacío para mostrar lista de amigos
}, function(result)
if callback then callback(result.success, result) end
end)
end
end
function invite_google_play_friends(self, invite_data, callback)
if gpgs then
gpgs.show_invite_dialog(invite_data.message, function(result)
if callback then callback(result.success, result) end
end)
end
end
-- Screenshot sharing
function M.share_screenshot(self, callback)
-- Tomar screenshot
msg.post("@render:", "capture_screen", {}, function(self, message_id, message)
if message_id == hash("screenshot_captured") then
local image_path = message.path
local share_data = {
text = "¡Mira mi progreso en el juego!",
url = "https://miapp.com/download",
image = image_path,
hashtags = {"gaming", "mobile", "screenshot"}
}
self:share_native(share_data, callback)
end
end)
end
return M
2. Friend System
Sistema de Amigos
-- friend_system.lua
local M = {}
function init(self)
self.friends = {}
self.friend_requests = {}
self.social_manager = require "main.social_manager"
self.leaderboard_manager = require "main.leaderboard_manager"
end
function M.load_friends(self, callback)
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" then
self:load_game_center_friends(callback)
elseif self.social_manager.platform == "Android" then
self:load_google_play_friends(callback)
end
else
-- Cargar amigos locales
self:load_local_friends(callback)
end
end
function load_game_center_friends(self, callback)
if gamekit then
gamekit.load_friends(function(self, result)
if result.success then
self.friends = result.friends or {}
print("Loaded " .. #self.friends .. " Game Center friends")
else
print("Failed to load Game Center friends: " .. (result.error or "Unknown"))
end
if callback then callback(result.success, result) end
end)
end
end
function load_google_play_friends(self, callback)
if gpgs then
gpgs.load_players(function(self, result)
if result.success then
self.friends = result.players or {}
print("Loaded " .. #self.friends .. " Google Play friends")
else
print("Failed to load Google Play friends: " .. (result.error or "Unknown"))
end
if callback then callback(result.success, result) end
end)
end
end
function M.compare_scores_with_friends(self, leaderboard_id, callback)
if #self.friends == 0 then
self:load_friends(function(success, result)
if success then
self:get_friends_scores(leaderboard_id, callback)
else
if callback then callback(false, "no_friends_loaded") end
end
end)
else
self:get_friends_scores(leaderboard_id, callback)
end
end
function get_friends_scores(self, leaderboard_id, callback)
local leaderboard = self.leaderboard_manager.leaderboards[leaderboard_id]
if not leaderboard then
if callback then callback(false, "unknown_leaderboard") end
return
end
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" then
self:get_game_center_friends_scores(leaderboard.ios_id, callback)
elseif self.social_manager.platform == "Android" then
self:get_google_play_friends_scores(leaderboard.android_id, callback)
end
else
-- Simular comparación local
local mock_scores = self:generate_mock_friend_scores(leaderboard_id)
if callback then callback(true, {scores = mock_scores, local_only = true}) end
end
end
function get_game_center_friends_scores(self, leaderboard_id, callback)
if gamekit then
gamekit.load_leaderboard_scores(leaderboard_id, function(self, result)
if result.success then
-- Filtrar solo scores de amigos
local friend_scores = self:filter_friend_scores(result.scores)
if callback then callback(true, {scores = friend_scores}) end
else
if callback then callback(false, result.error) end
end
end)
end
end
function filter_friend_scores(self, all_scores)
local friend_scores = {}
local friend_ids = {}
-- Crear lookup table de IDs de amigos
for _, friend in ipairs(self.friends) do
friend_ids[friend.player_id] = true
end
-- Filtrar scores
for _, score in ipairs(all_scores) do
if friend_ids[score.player_id] then
table.insert(friend_scores, score)
end
end
return friend_scores
end
function M.challenge_friend(self, friend_id, challenge_type, challenge_data, callback)
local challenge = {
type = challenge_type,
data = challenge_data,
challenger_id = self.social_manager.player_info.player_id,
challenger_name = self.social_manager.player_info.display_name,
timestamp = os.time()
}
if self.social_manager.authenticated then
if self.social_manager.platform == "iPhone OS" then
self:send_game_center_challenge(friend_id, challenge, callback)
elseif self.social_manager.platform == "Android" then
self:send_google_play_challenge(friend_id, challenge, callback)
end
else
print("Cannot send challenge - not authenticated")
if callback then callback(false, "not_authenticated") end
end
end
function send_game_center_challenge(self, friend_id, challenge, callback)
if gamekit then
local challenge_message = string.format(
"¡%s te desafía! Tipo: %s",
challenge.challenger_name,
challenge.type
)
gamekit.send_challenge(friend_id, challenge_message, challenge.data, function(result)
if callback then callback(result.success, result) end
end)
end
end
function M.show_friends_leaderboard(self, leaderboard_id)
self:compare_scores_with_friends(leaderboard_id, function(success, result)
if success then
msg.post("main:/ui", "show_friends_leaderboard", {
leaderboard_id = leaderboard_id,
scores = result.scores,
friends = self.friends
})
else
print("Failed to load friends scores: " .. (result or "Unknown error"))
end
end)
end
-- Helper functions
function load_local_friends(self, callback)
-- Cargar lista de amigos local (para testing)
self.friends = {
{player_id = "friend1", display_name = "Ana", alias = "Ana"},
{player_id = "friend2", display_name = "Carlos", alias = "Carlos"},
{player_id = "friend3", display_name = "María", alias = "María"}
}
if callback then callback(true, {friends = self.friends, local_only = true}) end
end
function generate_mock_friend_scores(self, leaderboard_id)
local mock_scores = {}
for _, friend in ipairs(self.friends) do
table.insert(mock_scores, {
player_id = friend.player_id,
display_name = friend.display_name,
score = math.random(100, 10000),
rank = math.random(1, 100)
})
end
return mock_scores
end
return M
Custom Social Features
1. Clan/Guild System
Sistema de Clanes
-- clan_system.lua
local M = {}
function init(self)
self.current_clan = nil
self.clan_members = {}
self.clan_leaderboard = {}
self.analytics = require "main.analytics_manager"
end
function M.create_clan(self, clan_name, clan_description, callback)
local clan_data = {
name = clan_name,
description = clan_description,
founder = self:get_player_id(),
created_at = os.time(),
member_count = 1,
level = 1,
experience = 0
}
-- En una implementación real, esto iría a tu backend
self:send_to_backend("create_clan", clan_data, function(success, result)
if success then
self.current_clan = result.clan
print("Clan created successfully: " .. clan_name)
self.analytics:track_event("clan_created", {
clan_name = clan_name,
founder_id = self:get_player_id()
})
end
if callback then callback(success, result) end
end)
end
function M.join_clan(self, clan_id, callback)
local join_data = {
clan_id = clan_id,
player_id = self:get_player_id(),
player_name = self:get_player_name()
}
self:send_to_backend("join_clan", join_data, function(success, result)
if success then
self.current_clan = result.clan
print("Joined clan: " .. result.clan.name)
self.analytics:track_event("clan_joined", {
clan_id = clan_id,
clan_name = result.clan.name
})
end
if callback then callback(success, result) end
end)
end
function M.contribute_to_clan(self, contribution_type, amount, callback)
if not self.current_clan then
if callback then callback(false, "not_in_clan") end
return
end
local contribution = {
clan_id = self.current_clan.id,
player_id = self:get_player_id(),
type = contribution_type, -- "coins", "experience", "trophies"
amount = amount,
timestamp = os.time()
}
self:send_to_backend("contribute_to_clan", contribution, function(success, result)
if success then
print(string.format("Contributed %d %s to clan", amount, contribution_type))
self.analytics:track_event("clan_contribution", {
clan_id = self.current_clan.id,
contribution_type = contribution_type,
amount = amount
})
-- Mostrar feedback
msg.post("main:/ui", "show_clan_contribution", {
type = contribution_type,
amount = amount,
total_contributed = result.total_contributed
})
end
if callback then callback(success, result) end
end)
end
function M.start_clan_challenge(self, challenge_type, duration_hours, callback)
if not self.current_clan then
if callback then callback(false, "not_in_clan") end
return
end
local challenge = {
clan_id = self.current_clan.id,
type = challenge_type,
duration_hours = duration_hours,
start_time = os.time(),
created_by = self:get_player_id()
}
self:send_to_backend("start_clan_challenge", challenge, function(success, result)
if success then
print("Clan challenge started: " .. challenge_type)
self.analytics:track_event("clan_challenge_started", {
clan_id = self.current_clan.id,
challenge_type = challenge_type,
duration_hours = duration_hours
})
end
if callback then callback(success, result) end
end)
end
-- Helper functions
function get_player_id(self)
return self.social_manager.player_info.player_id or "local_player"
end
function get_player_name(self)
return self.social_manager.player_info.display_name or "Jugador"
end
function send_to_backend(self, endpoint, data, callback)
-- Implementar comunicación con backend
-- Por ahora, simular respuestas
timer.delay(1.0, false, function()
if callback then callback(true, {success = true, data = data}) end
end)
end
return M
Mejores Prácticas
1. User Experience
- Autenticar de forma no intrusiva
- Ofrecer funcionalidad offline
- Explicar beneficios de conectarse
- Respetar privacidad del usuario
- Hacer sharing opcional y valioso
2. Technical
- Manejar errores de red gracefully
- Implementar retry logic
- Cache datos sociales localmente
- Usar authentication callbacks
- Testear en múltiples cuentas
3. Engagement
- Crear challenges significativos
- Recompensar participación social
- Mostrar progreso de amigos
- Facilitar comparaciones sanas
- Celebrar logros sociales
4. Platform Guidelines
- Seguir guidelines de Game Center/Google Play
- Usar APIs oficiales
- Respetar términos de servicio
- Implementar achievement guidelines
- Mantener consistencia con platform UX
Esta implementación completa te proporciona un sistema social robusto que mejora significativamente el engagement y la retención de usuarios en tu juego móvil.