Stream Asteroids (Twitch game)

This week I finished ‘Stream Asteroids’, a co-operative stream game for my Twitch channel. When I go BRB, my viewers can each control a little spaceship. Players input commands in the chat to move their ship on a 10x10 grid (e.g. a3, c7, etc). Their ships automatically fire on the nearest asteroid. When asteroids are destroyed, they drop xp. If collected, this can be spent on upgrades (damage, ship speed, fire rate, etc). The hard part is moving out of the way of asteroids when stream latency means movement commands are delayed by multiple seconds.

The game was made in 10-14 days. It relies on reading and parsing new chat lines in BotChatLog.txt generated by the Streamlabs Chatbot. So no API calls! Probably a very unorthodox solution, but if it works - why not?

The game has proven a success! My viewers have provided valuable feedback, and I find them still playing the game even after I have left the stream for 10+ minutes.

16 Likes

Awesome! Really clever!

3 Likes

Absolutely amazing. I love the idea!

This is part of the charm if you ask me. Changing the course of a huge chunk of metal in outer space should take a bit of time. It reminds me of Objects in Space and the way it more resembles almost a turn based strategy game than a real time space sim.

4 Likes

Thank you! And good point - I’ll bring that up next time somebody complains when crushed by an asteroid!

3 Likes

This is really cool. You could try contacting Twitch devs and ask if you can write an article for them talking about the implementation / features then publish on their blog (maybe do the multiple game idea below first).

This seems like a viable business opportunity. You could make branded games for Twitch channel AFK / breaks and sell that for $50+ a license.

You could make a whole bunch of these games, and then make a dedicated channel for them with leaderboards. Kind of like Mario Party. Leaderboards and other stats over multiple games. You could sell cosmetics (like killing particles / death particles / skins where appropriate / in game avatars). Lots of possibilities. Think big!

7 Likes

You’ve got some nice ideas!

I don’t know how much you know about Twitch, but I think they’d not be interested. There already is a stream game ecosystem with a full API, and my implementation effectively sidesteps it entirely. I don’t think I’m breaking any rules, but they’re unlikely to want to promote it either.

The thought had crossed my mind, but I’m not sure there would be sufficient demand. Custom branding is a good idea though as it could justify a higher price point. I would also probably not consider selling a game that relies on something as janky as parsing a chatbot’s log. A minor change from Twitch or Streamlabs could break it! I’d need to do a proper Twitch API implementation.

Unfortunately the Twitch Plays category is a bit of a disappointment, as there aren’t usually many people there (unless it’s something like Twitch Plays Pokemon). That could also be due to the quality of the games on offer, not sure. It’s funny because the lack of people there either means it’s a non-starter, or that it’s an unexploited segment.

Microtransactions are of course a key part of the Twitch API, but I am actually also able to do it using my chatbot implementation.

I am probably at some point going to make another game like this, but something more suitable for the stream latency. Thinking a basic turn based procgen dungeon crawler (will need to have a look at @WhiteBoxDev’s tutorials for some of it!). At that point I can evaluate whether it’s a niche worth exploring.

6 Likes

@Alex_8BitSkull did you end up taking this any further?

1 Like

I did not! I’ve given up streaming for the time being due to childcare. Happy to share my approach if anyone wants to do something similar though.

1 Like

It sounds like you did a work around with the chatlog bot? Do you think that added significant latency to it for you vs just using the API?

From how another user described it the twitch API can be somewhat thorny, do you agree with that?

If you could share any code or thoughts in regards to approach I would appreciate it.

1 Like

The latency is basically because I fed the output of the game back through my streaming software. If the game was HTML5 and overlayed directly on Twitch then there would be negligible latency. So it’s not the chatbot solution per se that caused an issue. On my computer (i.e. getting rid of the stream delay) there was no noticeable latency at all (entering command in Twitch chat → chat logged by bot → chat log scraped by my game).

I haven’t gotten far enough into the Twitch API to be able to assess it. I found it very overwhelming to even find the footing to start anywhere. For someone comfortable working with APIs it might be easier, but I just couldn’t wrap my head around converting the given examples to Lua/Defold.

Here’s my script for scraping usernames and messages from the chat log:

local filename = [[C:\Users\[yourusername]\AppData\Roaming\Streamlabs\Streamlabs Chatbot\Services\Twitch\Logs\BotChatLog.txt]]
local line_number = 0
local num_lines_per_call = 10

--define pattern to identify username
local username_start_str = "display-name="
local username_start_str_len = string.len(username_start_str)
local username_end_str = ";"
local username_end_str_len = string.len(username_end_str)

--define pattern to identify chat message
local message_start_str = "PRIVMSG #yourtwitchusernamehere:"
local message_start_str_len = string.len(message_start_str)

--ignore chats from previous stream (i.e. start at end of chat log)
local command = io.input(filename, "r")
line_number = command:seek("end")

--catch and consume new lines
timer.delay(0.1, true, function()

	local command = io.input(filename, "r")
	command:seek("set", line_number)
	if command then
		
		for i=1,num_lines_per_call do

			local command_contents = io.read("*l")
			line_number = command:seek()
			if not command_contents then
				break
			end

			local username_start = string.find(command_contents, username_start_str, 1, true)
			local username_end = string.find(command_contents, username_end_str, username_start, true)
			
			--no username found check
			if not username_end or not username_start then
				break
			end

			local username = string.sub(command_contents, username_start+username_start_str_len, username_end-username_end_str_len)


			local message_start = string.find(command_contents, message_start_str, 1, true)
			
			--no message found check
			if not message_start then
				break
			end

			local message = string.sub(command_contents, message_start+message_start_str_len)

			print(username .. ": " .. message)

            --pass identified username and message to function so it can be interpreted by the game
			commands.process_command(username, message)

		end

	end

end)
4 Likes

Thank you for the reply, I’m really interested in understanding if there is a potential value proposition to what was discussed earlier, RE a service to offer.

If you were to reapproach it from scratch would you do the same methodology?

Were ther any “gotchas” that you didn’t expect during the development?

Were I to try and sell something like it to others there would be a few areas of concern.

  1. Latency - I expect most streamers use the low latency setting on Twitch, but for those that don’t, the latency issues discussed already would be amplified.

  2. Requirement to use the desktop version of the Streamlabs Chatbot. I know there is a cloud version now so the risk is that Streamlabs stop supporting the desktop version entirely, even if you never update. I don’t think there are any TOS implications, because all we’re doing is parsing a .txt file stored on our own system. Effectively we are relying on Streamlabs playing by the API rules, then just piggybacking on their output.

  3. Monetisation. I’ve figured out ways to use the chat log to detect subs and bit donations. It gets a bit janky though, because there’s no way to tie a specific bit donation to a specific in-game purchase, other than by bit amount (e.g. “12 bits for armour, 13 bits for sword”). The Twitch API would handle this much better I’m sure. Furthermore, this might be getting into TOS violation areas. I don’t know.

I’m a big fan of variations of “it’s not stupid if it works”. But it’s one thing to do something for myself, another to try to sell the result. If it were me, I would invest a lot of time into trying to learn the Twitch API (and inevitably end up asking for help here) so that I could do it “properly”.

2 Likes