Making a Game With Discord's Bot API

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Unity, as a game engine, is going downhill. New features are getting locked behind paywalls, even for pro members, and each update just brings more bugs and division into the engine. So, as a professional game developer, I knew I had to switch to a far more capable game engine: Unrea— Discord. Okay, so I don't actually dislike Unity, and Discord's not actually a game engine, but that doesn't mean you can't make games with it. If you don't know, Discord has an API that allows you to create bots that can take Discord functions, like messages and reactions, as input, and return Discord functions as output. I was thinking about what I could create with this that hadn't been done yet, and then it hit me. Just about any game that could be played in a terminal could be made into a Discord bot. And, a few months ago for my final project for my AP Computer Science class, I actually made a game that's designed to be played in a Java console. It's a clone of a really fun puzzle game called Sokoban where you have to push boxes around to get them to certain destinations. I made it in class in a few days, so it's pretty simple, but it's surprisingly pretty fun. It has infinite levels with somewhat of a difficulty curve. And, to control the game you just type commands, so I decided I would try to turn it into a Discord bot using Discord's API. And, to make things more interesting, I gave myself only 24 hours to do it, since... you know, it's not a gamedev video without an arbitrary deadline. The code is written in Java, so I needed a way to interact with Discord's Bot API in Java. I found a really helpful wrapper library to do this called JDA, which literally just stands for Java Discord API, and with that it was time to get started. Before I could make the game work with Discord I had to... you know, learn how to use the API with JDA. I found two resources that were pretty helpful: an article by Oliy Barrett that goes over the basics of setting up and running a bot, as well as somewhat outdated but more in-depth video series by techtoolbox. I'll leave a link to both of these in the description. And, after a little while, I had set up a bot that could listen for commands and return messages. Basically, with JDA you can create methods that run when certain events happen, such as the bot receiving a message. Then, within the method you can access the content of the message, which means you can check if the message contains a certain keyword or command, and do something based on that. And this was pretty much all I needed to start working on the actual game. So, I started off by copying all the classes from my Sokoban game into my Discord bot project. None of the game logic needed to be changed, but obviously I did need to change the way the game handled user input and returned the updated grid. The original game was constantly running but stopped at certain points to wait for the user to type a valid command. But, for the Discord bot, since I'll probably have multiple instances of the game running at once, having each one constantly running and waiting for user input didn't seem like the best approach. So, basically, I turned my game's update loop into a method that would run only when a command is received that starts with a certain prefix, which for me is just an exclamation point, and the command you used is pass into the method in a string called userInput, and the game's existing code responds to it accordingly. Then, instead of printing the resulting grid and game information to the console, I send it as a Discord message in the channel that the bot received the command in. So now it should be possible to play the game. Just type the play command, and— Okay, so the problem is that my code returns unicode characters that my compiler isn't encoding properly. I tried changing my IDE's encoding settings, but I couldn't get anything to work, so I decided to just ignore the problem and use Discord's emoji tags instead of unicode characters. This is when I made the impulse decision that probably ended up being the best design choice for this project: making the player character a flushed emoji. Anyways, now the game works pretty well. All of the commands work properly and you can play the game without any issues, but there are obviously improvements that can be made. For starters, typing in long commands with prefixes to do something as simple as moving makes the game slow and tedious to play. Since I was already planning on adding reaction controls to the game, I figured implementing that would just fix the issue. The way reaction commands work is that, as soon as a bot sends a message, it adds certain reactions to it. And, at the same time, the bot is also listening for when a user adds a reaction, and will perform a certain action based on that. So, from the user's perspective, all they're doing is pressing a button to make something happen, which is much more convenient than typing a command. So, in my code, whenever the bot receives a message sent by itself, it adds four reactions to it: left, right, up, and down arrows, and this reset button. Then, when the bot receives a reaction from the user, it creates a new empty string, sets the value of the string to the text command associated with the reaction, and calls the game method with the newly created string. Everything is obviously going to work fine on the first try, but let's test it just to make sure. Oh fri*k... I forgot to check who was adding the reaction before starting the command, so the bot was responding to its own reactions, which creates an infinite loop. But, after fixing that and also doing some unrelated unicode character debugging, you could now control the game with reaction commands. I also made the walls purple... if you didn't notice... But there are two problems with the current reaction system that need to be fixed. The bot adds reactions to every message it receives when they only need to be on the message that has the updated game information. And, it seems like reactions are being slowly added to the message one by one, so hopefully there's a way to speed up the process. To fix the first issue, I store the content of the message in a string called gameText right before sending it, and when a new message is received I check if the sender is a bot and if the contents of the message are equal to gameText. Now the reactions are only added to the correct messages, but sadly there wasn't really a solution for the second issue. I don't think there's a way of asynchronously adding reactions to a message with JDA, so you kind of just have to add reactions one by one. So, I kept reaction commands as an option, but I still wanted there to be a faster, more natural way of controlling the game. Something the original game included to make playing feel more natural was the ability to control the player with WASD commands, but, in the Discord bot, this feature is kind of made redundant, since each command starts with a prefix. So, I decided to keep prefixes for commands like !play and !stop, but get rid of prefixes on the actual gameplay commands that the user will be frequently inputting. But right now the game only checks user input and is updated when the bot receives a message that starts with its prefix. I could just make the game check input and update every time the bot receives any message but that's not only unperformant, but also unnecessary, and probably the worst idea I've ever heard. So, I decided to create an ArrayList of strings of all valid commands and only update the game loop if the first word of a user's message is a command in the ArrayList. Now you can control the game by just typing WASD or R, which is definitely the most natural way to play... well, if you're a gamer, at least. Now the gameplay is good but look how UGLY this is! Like, no offense or anything, but this bright white background and basic text formatting is not acceptable. Ew! So, the first thing I did to improve the visuals was make the bot return embeds, instead of normal disgusting messages. If you don't know what an embed is, it's just a nicely formatted message that can be sent by Discord bots that can have a title, text fields, and lots of other cool stuff. So, I made a method that takes a title. description. and footer as input. builds it into a JDA embed, and sends it as a message. And then, in my game class's update method, instead of sending a big string with the current level, grid, and controls prompt as a message, I call my sendEmbed() method with the level as the title, the grid as the description, and the controls as the footer. And now things are already looking a lot better. I also created an embed that's sent after completing a level. But, this background is still ugly, so I made it black. I also made the color of the walls random, with a new color being chosen after each level. Now, if I do say so myself, the game is looking pretty epic now. But I think it's time to get rid of the default skin. I mean, I mean— DEFAULT PROFILE PICTURE! So, I made an icon for the bot in GIMP. I think it turned out pretty well. Now, we're pretty much done, but there's one last thing I want to add to the bot. Right now, if multiple users try to use the bot, they each control the same game, since the bot applies the commands to a single instance of the game. Since my game is a class though, I can just create multiple instances of the game and use HashMaps to link them to users. So, I created a HashMap, which is just like a dictionary in something like C# or Python, that maps users to games. Then, I got rid of my singular game object, and, instead, whenever a user calls a command, I create a new game and map it to the user, if they don't already have one, and instead of calling methods on the old, single, game object, I call them on the game mapped to the user who sent the command. And now, just like that, multiple users can use the bot at once without interfering with one another. HashMaps are so OP. But, since the current color is stored in the bot object, rather than each game object, the color of the game is the same for all users, but this wasn't a big problem. To fix it, I just had to change the way color was stored and assigned. It did lead to this weird bug where the walls turned into flushed emojis. I think I fixed it, but if this happens to you it's definitely an intended feature. It's like a little quirky Easter egg. But now, at a little before 2 AM, Sokobot was finished. I guess the 24ihour deadline didn't really matter. I did add a few things to the bot the next morning, after the 24 hours had passed, like this !info command that tells you how to play and some other details about the bot, as well as making my API token read from an external text file so I can distribute the bot without it getting taken over by edgy hackers. But, those things are unrelated to the actual game, so I guess it's okay. If you want to test out the bot or add it to your server, a link to its GitHub repository will be in the description. To use it, just download the latest .jar file, create a bot on Discord's Developer Portal, then copy the bot token and paste it into a file named token.txt in the same directory as the .jar. Then, just run the .jar file and, if everything works correctly, the bot should turn online. If enough people are interested I may host the bot online with a service like Heroku in the future, so you can add it to your server in one click, without having to host it yourself. So yeah, that's everything. I hope you enjoyed watching me try to use Discord as a game engine. As always, if you have any feedback or suggestions for future videos, feel free to leave a comment. And, we hit 1,000 subs a few days ago, which is pretty cool, so I just want to say thanks to everyone who's subscribed and watches my videos. Anyways, thanks so much for watching, and I'll see you in the next video.
Info
Channel: PolyMars
Views: 1,846,657
Rating: undefined out of 5
Keywords: discord, bot, game, sokoban, sokobot, polymars, java, jda, api, javadiscord, discord bot, rest api, discord api, game dev, gamedev, indie dev, dev, development, devlog, challenge, making a game in, 24 hours, code, eclipse, intellij, idea, behind the scenes, making of, bot api, game bot, discord game
Id: 0fWdU8JCT6Y
Channel Id: undefined
Length: 10min 39sec (639 seconds)
Published: Fri Jun 19 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.