Popcorning Guinea Pig
Search Results for

    Discord Integration

    The Popcorning Guinea Pig engine provides Discord Rich Presence integration through the IDiscordService, allowing games to display rich status information in Discord.

    Overview

    Discord Rich Presence allows your game to:

    • Show current game status and activity
    • Display custom artwork and images
    • Show elapsed time or time remaining
    • Enable "Join" and "Spectate" buttons for multiplayer games
    • Display party information and player counts

    IDiscordService Interface

    public interface IDiscordService
    {
        void Initialize(string clientId);
        void SetActivity(DiscordActivity activity);
        void ClearActivity();
        void UpdateActivity(Action<DiscordActivity> updateAction);
        void SetPartySize(int currentSize, int maxSize);
        void SetTimestamps(DateTime? start, DateTime? end);
        void Dispose();
    }
    

    Setting Up Discord Integration

    1. Create Discord Application

    First, create a Discord application at the Discord Developer Portal:

    1. Click "New Application"
    2. Enter your game name
    3. Note the Client ID - you'll need this for integration

    2. Upload Rich Presence Assets

    Upload images for your Rich Presence:

    1. Go to "Rich Presence" → "Art Assets"
    2. Upload images (recommended: 1024x1024 PNG)
    3. Note the asset keys - use these in your code

    3. Initialize Discord Service

    public class MyGame : Game
    {
        private readonly IDiscordService _discord;
        
        public MyGame()
        {
            _discord = GetService<IDiscordService>();
            
            // Initialize with your Discord Client ID
            _discord.Initialize("YOUR_CLIENT_ID_HERE");
            
            // Set initial activity
            SetMenuActivity();
        }
        
        private void SetMenuActivity()
        {
            var activity = new DiscordActivity
            {
                State = "In Main Menu",
                Details = "Selecting game mode",
                LargeImageKey = "game_logo",
                LargeImageText = "Popcorning Guinea Pig",
                SmallImageKey = "menu_icon",
                SmallImageText = "Main Menu"
            };
            
            _discord.SetActivity(activity);
        }
    }
    

    DiscordActivity Properties

    The DiscordActivity class contains all the information displayed in Discord:

    public class DiscordActivity
    {
        public string State { get; set; }           // What the player is currently doing
        public string Details { get; set; }        // What the player is doing in detail
        public string LargeImageKey { get; set; }  // Key for large image asset
        public string LargeImageText { get; set; } // Tooltip for large image
        public string SmallImageKey { get; set; }  // Key for small image asset
        public string SmallImageText { get; set; } // Tooltip for small image
        public DateTime? StartTimestamp { get; set; } // When activity started
        public DateTime? EndTimestamp { get; set; }   // When activity will end
        public int PartySize { get; set; }         // Current party size
        public int PartyMax { get; set; }          // Maximum party size
        public string PartyId { get; set; }        // Unique party identifier
        public string JoinSecret { get; set; }     // Secret for join button
        public string SpectateSecret { get; set; } // Secret for spectate button
    }
    

    Common Usage Patterns

    Menu State

    private void ShowMenuActivity()
    {
        var activity = new DiscordActivity
        {
            State = "In Main Menu",
            Details = "Navigating menus",
            LargeImageKey = "game_logo",
            LargeImageText = "Popcorning Guinea Pig",
            StartTimestamp = DateTime.UtcNow
        };
        
        _discord.SetActivity(activity);
    }
    

    Gameplay State

    private void ShowGameplayActivity(string levelName, int currentLevel)
    {
        var activity = new DiscordActivity
        {
            State = $"Level {currentLevel}",
            Details = $"Playing {levelName}",
            LargeImageKey = "gameplay",
            LargeImageText = "In Game",
            SmallImageKey = "level_icon",
            SmallImageText = levelName,
            StartTimestamp = DateTime.UtcNow
        };
        
        _discord.SetActivity(activity);
    }
    

    Multiplayer State

    private void ShowMultiplayerActivity(int playersInGame, int maxPlayers)
    {
        var activity = new DiscordActivity
        {
            State = "Multiplayer Match",
            Details = "Battle Royale",
            LargeImageKey = "multiplayer",
            LargeImageText = "Multiplayer Game",
            PartySize = playersInGame,
            PartyMax = maxPlayers,
            StartTimestamp = DateTime.UtcNow
        };
        
        _discord.SetActivity(activity);
    }
    

    Paused State

    private void ShowPausedActivity()
    {
        var activity = new DiscordActivity
        {
            State = "Game Paused",
            Details = "Taking a break",
            LargeImageKey = "paused",
            LargeImageText = "Paused",
            SmallImageKey = "pause_icon",
            SmallImageText = "Paused"
            // Note: No timestamp to avoid showing elapsed time while paused
        };
        
        _discord.SetActivity(activity);
    }
    

    Advanced Features

    Timed Activities

    Show countdown timers or elapsed time:

    // Show elapsed time since game started
    private void ShowElapsedTime(DateTime gameStartTime)
    {
        _discord.SetTimestamps(gameStartTime, null);
    }
    
    // Show countdown to event
    private void ShowCountdown(DateTime eventTime)
    {
        _discord.SetTimestamps(null, eventTime);
    }
    
    // Update activity with timestamps
    private void UpdateGameActivity()
    {
        _discord.UpdateActivity(activity =>
        {
            activity.State = "In Combat";
            activity.Details = "Boss Fight";
            activity.StartTimestamp = DateTime.UtcNow;
        });
    }
    

    Party Management

    Handle party/lobby information:

    public class MultiplayerManager
    {
        private readonly IDiscordService _discord;
        private readonly List<Player> _players = new();
        
        public void UpdatePartyInfo()
        {
            _discord.SetPartySize(_players.Count, 4); // Current/Max players
            
            _discord.UpdateActivity(activity =>
            {
                activity.State = $"In Lobby ({_players.Count}/4)";
                activity.Details = "Waiting for players";
                activity.PartyId = GetCurrentLobbyId();
            });
        }
    }
    

    Join/Spectate Buttons

    Enable players to join games through Discord:

    private void EnableJoinButton(string lobbySecret)
    {
        _discord.UpdateActivity(activity =>
        {
            activity.JoinSecret = lobbySecret;
            activity.State = "In Multiplayer Game";
            activity.Details = "Join to play together!";
        });
    }
    
    // Handle join requests (implement in your networking code)
    private void OnDiscordJoinRequest(string secret)
    {
        // Connect to game using the secret
        JoinGameBySecret(secret);
    }
    

    Activity Management

    Scene-Based Activity Updates

    Automatically update Discord status based on current scene:

    public abstract class Scene
    {
        protected virtual DiscordActivity GetDiscordActivity()
        {
            return new DiscordActivity
            {
                State = GetType().Name,
                Details = "Playing game",
                LargeImageKey = "game_logo"
            };
        }
    }
    
    public class MainMenuScene : Scene
    {
        protected override DiscordActivity GetDiscordActivity()
        {
            return new DiscordActivity
            {
                State = "In Main Menu",
                Details = "Navigating menus",
                LargeImageKey = "main_menu"
            };
        }
    }
    
    public class GameplayScene : Scene
    {
        private readonly string _levelName;
        
        protected override DiscordActivity GetDiscordActivity()
        {
            return new DiscordActivity
            {
                State = $"Playing {_levelName}",
                Details = "In game",
                LargeImageKey = "gameplay",
                StartTimestamp = DateTime.UtcNow
            };
        }
    }
    
    // In your scene manager
    public void ChangeScene(Scene newScene)
    {
        _currentScene = newScene;
        
        var discord = GetService<IDiscordService>();
        discord.SetActivity(newScene.GetDiscordActivity());
    }
    

    Activity Helper Class

    Create a helper class for managing common Discord activities:

    public static class DiscordActivities
    {
        public static DiscordActivity MainMenu()
        {
            return new DiscordActivity
            {
                State = "In Main Menu",
                Details = "Selecting options",
                LargeImageKey = "main_menu",
                LargeImageText = "Main Menu"
            };
        }
        
        public static DiscordActivity Playing(string level, DateTime startTime)
        {
            return new DiscordActivity
            {
                State = $"Playing {level}",
                Details = "In game",
                LargeImageKey = "gameplay",
                LargeImageText = level,
                StartTimestamp = startTime
            };
        }
        
        public static DiscordActivity Multiplayer(int current, int max)
        {
            return new DiscordActivity
            {
                State = "Multiplayer Game",
                Details = $"Players: {current}/{max}",
                LargeImageKey = "multiplayer",
                PartySize = current,
                PartyMax = max,
                StartTimestamp = DateTime.UtcNow
            };
        }
        
        public static DiscordActivity Settings()
        {
            return new DiscordActivity
            {
                State = "In Settings",
                Details = "Configuring game",
                LargeImageKey = "settings",
                LargeImageText = "Settings Menu"
            };
        }
    }
    
    // Usage
    _discord.SetActivity(DiscordActivities.Playing("Forest Level", gameStartTime));
    

    Best Practices

    Asset Management

    1. Image sizes: Use 1024x1024 PNG images for best quality
    2. Asset naming: Use descriptive, lowercase names with underscores
    3. Fallbacks: Always provide fallback text for images

    Activity Updates

    1. Update frequency: Don't update too frequently (max once per second)
    2. Meaningful states: Provide useful information to other Discord users
    3. Timestamps: Use appropriate timestamps for activities with duration

    Performance

    1. Initialize once: Call Initialize() only once at game startup
    2. Batch updates: Use UpdateActivity() for multiple property changes
    3. Cleanup: Call Dispose() when shutting down the game

    Example: Complete Integration

    public class MyGame : Game
    {
        private readonly IDiscordService _discord;
        private DateTime _gameStartTime;
        
        public MyGame()
        {
            _discord = GetService<IDiscordService>();
            _discord.Initialize("123456789012345678"); // Your Client ID
            
            _gameStartTime = DateTime.UtcNow;
            UpdateDiscordActivity();
            
            // Update Discord activity when scenes change
            SceneManager.OnSceneChanged += OnSceneChanged;
        }
        
        private void OnSceneChanged(Scene oldScene, Scene newScene)
        {
            UpdateDiscordActivity();
        }
        
        private void UpdateDiscordActivity()
        {
            var currentScene = SceneManager.CurrentScene;
            
            switch (currentScene)
            {
                case MainMenuScene:
                    _discord.SetActivity(DiscordActivities.MainMenu());
                    break;
                    
                case GameplayScene gameplay:
                    var activity = DiscordActivities.Playing(gameplay.LevelName, _gameStartTime);
                    _discord.SetActivity(activity);
                    break;
                    
                case SettingsScene:
                    _discord.SetActivity(DiscordActivities.Settings());
                    break;
                    
                default:
                    _discord.ClearActivity();
                    break;
            }
        }
        
        protected override void OnClosing()
        {
            _discord?.Dispose();
            base.OnClosing();
        }
    }
    

    Discord integration adds a social element to your game, helping players share their gaming experience with friends on Discord.

    • Edit this page
    In this article
    Back to top © 2024 Popcorning Guinea Pig Game Engine. A custom C# game engine for indie developers.