Discord bot integration with pygame interface

I’m trying to build a discord bot that works together with a pygame window. The idea is to have buttons in the pygame interface that trigger the bot to send messages to discord channels.

import discord
import pygame
import asyncio

bot = discord.Client()
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
BLACK = (0, 0, 0)

selected_option = 0

@bot.event
async def on_message(msg):
    if msg.author == bot.user:
        return
    
    if msg.content.startswith('!start'):
        while True:
            if selected_option == 1:
                await bot.send_message(msg.channel, '!music https://example.com/song1')
            elif selected_option == 2:
                await bot.send_message(msg.channel, '!music https://example.com/song2')
            else:
                await bot.send_message(msg.channel, "Hello there!")
                pygame.quit()

def create_interface():
    pygame.init()
    screen = pygame.display.set_mode((400, 300))
    
    def draw_button(pos_x, pos_y, width, height, hover_color, normal_color, option_id):
        cursor_pos = pygame.mouse.get_pos()
        mouse_clicked = pygame.mouse.get_pressed()
        
        if pos_x + width > cursor_pos[0] > pos_x and pos_y + height > cursor_pos[1] > pos_y:
            pygame.draw.rect(screen, hover_color, (pos_x, pos_y, width, height))
            if mouse_clicked[0] == 1 and option_id != 0:
                global selected_option
                selected_option = option_id
        else:
            pygame.draw.rect(screen, normal_color, (pos_x, pos_y, width, height))
    
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
        
        screen.fill(WHITE)
        draw_button(100, 80, 60, 40, YELLOW, BLUE, 1)
        draw_button(200, 80, 60, 40, YELLOW, BLUE, 2)
        
        pygame.display.flip()

@bot.event
async def on_ready():
    print('Bot is online')
    print(bot.user.name)
    create_interface()

bot.run('your_token_here')

I’m having trouble getting the pygame button clicks to communicate with the discord bot properly. When I click a button in the pygame window, I want the bot to respond in the discord channel. Any ideas on how to make this work correctly?

The main issue here is that you’re mixing synchronous pygame operations with asynchronous discord.py operations. When you call create_interface() in the on_ready event, it blocks the entire event loop with its while running loop, preventing the bot from processing Discord events. I ran into this exact problem when building a similar project last year. The solution is to integrate pygame’s event handling into Discord’s async event loop using asyncio.create_task() and making your pygame loop async. You’ll need to replace the blocking pygame loop with something like await asyncio.sleep(0.01) to yield control back to the event loop. Also, bot.send_message() is deprecated - use channel.send() instead. Consider using a queue system to pass button click events from pygame to your Discord handlers, as this keeps the concerns properly separated and makes debugging much easier.

pygame’s main loop is blocking your discord bot completely. try running pygame in a seprate thread with threading.Thread() so both can work together. also that infinite while loop in on_message will spam the channel endlessly - add some delay or break condition there

You’re dealing with two event loops that don’t play well together. I faced something similar when integrating pygame with a trading bot last year. The core problem is pygame blocks everything when it runs its main loop. What worked for me was using asyncio queues to pass data between the interfaces. Set up an asyncio.Queue() that pygame writes to when buttons get clicked, then have your discord bot check this queue periodically with a background task. Move the pygame window to run with asyncio.run_forever() and replace pygame.time.wait() with await asyncio.sleep(). Also fix that infinite loop in on_message - it’ll crash your bot eventually. The selected_option approach won’t scale well either, consider using the queue to pass actual command data instead of just numbers.