jedimasta

Help creating Jackbox-like game with html5, nodes and sockets

Recommended Posts

I posted a response in a thread that had some applicable information to it, but it never got a response and I have questions, so this is sort of a re-post.

I've created an HTML5 clone of a game I saw in a casino recently wherein players "grab" cards as they are dealt in order to reach a target score determined randomly before the game starts. I specifically created it to be played using physical buttons around a TV embedded into a table. I used the EaselJS APIs and I'm pretty happy with the results. The next level, so to speak, would be in allowing players to use their mobile devices to grab cards from a main play area (i.e. the TV). If you've played any of the Jackbox Party games, you'll know what I mean.

I've gathered that in order to do this I'll need to leverage node.js and sockets.io to get players' mobile devices talking to the main game screen, but that's where my understanding ends. I don't really intend on releasing this to the public or anything, more for just me and my gambling friends, so I wan't to spend as little as possible, ideally nothing, on server usage. I've already setup a webserver in my home, strictly to serve internal IPs, using XAMMP on Windows. I created a basic node js server and I'm able to send messages back and forth, basically culling information from tutorials.

What I'm looking for is how to best approach having players, using their mobile devices, interact with a separately rendered "main" screen.

So, for example, the main screen displayed on the TV flips over a 10 of hearts. If a user wants that card, they tap a button on their device to add it to their hand. Unless I've missed my mark, the client (the player's mobile phone) sends a request to the node server, which then pings the main screen to give it info regarding which card is showing. While the main screen then locally stores that information into it's arrays (tracking players and their points), it sends a ping back to the server, which in turn sends a ping back to the client to animated the card image to their device and updates a score display.

Do I have all that right or is there some far easier way to do this? I can't have the node server file the same as the main screen because it doesn't know how to process any of the other stuff going on, but I could be wrong. How do I tell the node server to get the card value from the main table and send it back to the client in one elegant function? There are other things I need to do, but this is the central piece to the entire project.

Share this post


Link to post
Share on other sites

If it were me i'd create an object on the node server called "gamestate" for example... Then when the game is started or updated I'd use a socket/ajax request to the server which would then update the gamestate and send it to any other devices connected to the server.

Basically you'd create a little API based around updating and getting this gamestate from the server.

Then just write 2 separate clients, 1 for the table and 1 for the phone - the only similarities will be the fact they call the same API to get and set data.

Just imagine the server as holding the data in memory, and allowing other devices to get and set that data with your API.

Share this post


Link to post
Share on other sites

I appreciate the response. Based on your suggestion though, I think all this may be over my head. Admittedly, my experience with Javascript is novice at best. Node and Socket are literally things I only started looking into a few days ago thinking they might make this thing a little bit cooler, but I feel like this is already ahead of my pay grade.

Is this not doable with the three files I'm working with:

nodeserver.js
maingame.js/html
player.js/html

player --> node: gimme that card
node -->maingame: this player is taking that card, store it for him
maingame-->node: done, here is that card's information
node-->player: the card is yours, here's its info

Share this post


Link to post
Share on other sites

So I made a bit of progress after more trial and error than I care to admit, but here's what I did.

Node server code:
 

var express = require('express');  
var app = express();  
var server = require('http').createServer(app);  
var io = require('socket.io')(server);


server.listen(3000);


// handle incoming connections from clients
io.sockets.on('connection', function(socket) {
    // once a client has connected, we expect to get a ping from them saying what room they want to join
    socket.on('room', function(room) {
        socket.join(room);
		console.log(socket.id+" in "+room);
    });
	
	socket.on('sendCardInfo',function(theCard){
	io.sockets.in("players").emit('sendCardInfo',theCard);
	//console.log(theCard);
	});
	
});

My intention here is to set up two different rooms so I can address them seperately. That part seems to work well enough. The second bit of that is supposed to take info gathered from the client and, at some point, send it to other clients. I'd just be happy to get it to log to the console, but it won't do that. Here's a look at the client setup, that places this client into the room "casino"

var socket = io.connect('http://172.0.0.2:3000');
var room = "casino";
socket.on('connect', function() {
   socket.emit('room', room);
});

Later on, cards are dealing out an I do the following:

//this comes from an array not shown here
var valCard = centerDeck.cards["0"].value;

socket.emit("sendCardInfo", valCard);

Finally, here's the player/client side

var socket = io.connect('http://172.0.0.2:3000');
var room = "players";
socket.on('connect', function() {
   socket.emit('room', room);
});



//and its listener, which displays the card value in a text container on the screen:
socket.on('sendCardInfo', function(data){
			centerText.text=data;
});

I think I might be good here for the moment. It's not likely the most elegant or optimized solution, but it seems to be working so far. I imagine it will get much more complex when I'm sending data back to the one specific user. As it stands I need to set up a way to store the socket id and assign it a player number, but it's 1am here and I'm done thinking for today.

Thanks for having a look!

Share this post


Link to post
Share on other sites
10 hours ago, jedimasta said:

So I made a bit of progress after more trial and error than I care to admit, but here's what I did.

Node server code:

Thanks for having a look!

Looking good, so it looks like you're doing what I described but without one "overall gamestate object". As your game grows and so does your code it might get a bit difficult to track what state everything is in, if you imagine any changes you make to the game go into game state, then you could always redraw the entire game from the game state, simples.

It look like your approach will definitely work, I think it may just cause some headaches down the line if you don't think about one nice elegant method of handling your game state. Pretty much every digital game has a game state, its the right way to do things and can bring a lot of 'by product' benefits like saving, loading, crash handing, bug tracking

Some pseudo code for how I would start with handling game state:

Just imagine sendCardInfo would send newCard=7h

Then in node:

gamestate.newCard = 7h

UpdateAllClients(gamestate)

Then in clients:

gotNewState(gamestate) {

 if(gamestate.newCard !=lastcard) {

}}; ......

(When i say clients, I mean devices which can see the game)

Share this post


Link to post
Share on other sites

Been about a week since I've updated here. I added a lot to the project and learned a lot in the process. I'm not able to post code at the moment, but I thought I'd post another question.

I added unique room identification. While I was testing things out on different devices, it occurred to me that I was running into cross talk, cuz I had several "Tables" running at the same time and communicating different cards to different players. I solved this by causing the table to create and display a unique room code that players provide before connecting, so only that specific table sends cards and notifications to players connected to that room. This improved things, if not made them slightly more complicated code-wise. I worked it all out, but I want to create a check so that a client/player only connects to active rooms. I'm not looking for specific code here, more for a method to best handle it.

It might help to know the following: Players are directed by the NodeJS server to a player/device specific screen when they load up the URL. Two form fields are presented to them, Name and Table ID. After filling it out and submitting, it takes them to the requested room and the table (not the NodeJS server) stores their user names, socket IDs, etc.. Additionally, the NodeJS server adds each connection to it's own array that stores the socket ID, the room they are in and the type (i.e. player or table).

My initial assumption is when a socket connects, it should do a check and if it's a player type, it looks through the array to see if the table code provided already exists and its assigned to a table. If not, no connection is made, but I'm not quite sure how to kick that back to the client/player screen to unhide the form and send an alert because it's already connected to the NodeJS server already.

Or maybe I'm overthinking it (I do that more than I'd like to admit).

Share this post


Link to post
Share on other sites

Nevermind. Being stuck in traffic for over an hour gave me time to think about how to handle it. I don't fire the player init and room connect until it receives a socket "okay" that then hides the form and takes the user into the room.

I think that about covers all the fun stuff. My last concern is performance. This may have more to do with the way MS Edge is handled on the Xbox One than anything else. I wanted to be able to play this with friends on the big screen, but holy crap does it perform poorly on the Xbox browser. Anyone else experienced this? My pages aren't too image heavy. Even with sound effects and music, it isn't more than ~10 megs and all of that preloads anyway. Even when I'm doing this from my local network, Edge just chugs on the Xbox.

Share this post


Link to post
Share on other sites

I have seen the game video and I think the game looks very cool. Is it a gambling machine? I am very interested in this. Hope you don't mind telling me the rules.

With regards to the performance issues of your house-built game, I think the best you can do is to profile it, both on server side and client side to find out where the problem is. You can create some dummy players to play with you to simulate a multiplayer game. For me, the client side part could be not caching the resources or creating too many new objects in the animation loop. The server side slowness may be caused by sending too much traffic in the update loop. But you are not creating a real time game I guess the network payload is very low in your game. The problem you came across may not be a network code issue.

Share this post


Link to post
Share on other sites

I've been discussing this mostly in another thread and forgetting to update this one. To answer your questions:

Yes, it's a gambling machine. Basically kind of a social slot machine. The company that makes them also does a more traditional poker game, where you're pulling down cards that get flipped to make the best poker hand, as opposed to a target score. In my case the broad rules are 

  • Individual cards from multiple mixed decks are flipped to the center of the table
  • each card has a value the same as they would hold in Blackjack, except that Ace is always 11.
  • each round has a target score and from that, a base maximum hand size
  • players must react quickly to grab cards from the center in order to reach the target goal without going over
  • when one player reaches the max hand size, the game goes into a countdown, where only a limited number of cards are dealt based on the number of players in the game. 
  • the game ends when 
    • all but one player busts
    • all players fill their hands without going over
    • the deck runs out
  • the player closest to the target without going over wins. There can be and have been ties.

So now that I've given you all the rules, I guess there's nothing stopping you from stealing them and making a better game than I could hope to. :) 

Regarding performance issues, I blame this solely on the browser capabilities of the Xbox One. Instead of racking my brain trying to optimize it for the browser, I jumped head first into UWP development, converting the title and deploying it as a windows/xbox app which works BEAUTIFULLY. So much so that once I've done some live playtests with friends, I'm may consider putting in the cost and effort to making this an actual downloadable game to sell for a few bucks. I'm sure there's a lot more to doing that than I've discovered so far, but *I* think it has potential, assuming it's fun for people other than me. The one kinda puts the fear of the internet gods in me is the cost of hosting for a node server with sockets that can serve up the game. I'm really not passing much data back and forth, but when you push the scope up from 6 players on a local environment to potentially thousands it starts the boggle my mind, particularly since I've never done anything like this, like, ever.

Share this post


Link to post
Share on other sites

@jedimasta Thank you for the detailed explanation. They actually patented the game in the US so I think you need to make sure it's legit when you release your game to the public in the US.

You don't really need to worry about problems for thousands of players now. Actually, if you can go that far, you can hire somebody else to solve the technical problems for you. As far as I know Minecraft's multiplayer mode is also laggy and being complained a lot. For building a distributed networked game, I have heard Erlang is a very good language for the backend. It's easy to learn and it has built-in distributed environment support and can scale quickly.

 

Share this post


Link to post
Share on other sites
3 hours ago, caymanbruce said:

@jedimasta Thank you for the detailed explanation. They actually patented the game in the US so I think you need to make sure it's legit when you release your game to the public in the US.

 

From a strictly legal perspective, you can't patent the rules of a game. You can patent the mechanics, i.e. the code or any type of special mechanics used in making the whole thing work, but the concept of a game can't be copyrighted. That's why you see so many hundreds of Candy Crush knock offs (which itself is a knock off of Bejeweled). In my case, this is all scratch written, save for some of the APIs like Easel.

At any rate, I don't know how far I'm gonna take it. For now I've registered myself with Microsoft's ID program and I'm soaking up tutorials like a sponge.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.