Tag Archives: happyfuntimes

More coming soon

I’ve spent some time getting a native phone app working. I don’t like the idea of an app because it can make things complicated for the user (attach to HFT WiFi, wait you didn’t download the app? Detach from HFT Wifi, download app, reattach to HFT wifi, launch app) Ugh! Or, if your HFT Wifi has internet then you probably get the problem of everyone using it to watch youtube videos and post images to fb/twitter/instagram and eating all your bandwidth making interacting with your installation really laggy 🙁

But, Eddo at UCLA can’t or won’t find creative solutions for the limits of the browser on iOS so he wants an app. So I’ve made one. It seems to work but will still take weeks to get on the app stores (iOS and Android). I’m worried it will ruin HappyFunTimes though. Devs will assume they should use the app. The experience will suck. No one will get it.

On the Android front though I made the non app (browser) version go fullscreen. At least on my tests it works. One of the problems with HappyFunTimes and phones it’s (a) it’s hard to test anything without more people and (b) it’s hard to find out what issues there will be without lots of phones.

Anyway, that removes some of the need for an app on Android. Once the browser has gone fullscreen there’s no more address bar, back button, etc and you can control the orientation (no more “please turn your phone” for landscape controllers.

The app also means I can prevent the phone from going to sleep. On the other hand you still have all the normal phone issues of different phones with different screen sizes and different versions of their internal webview so you still need to be conservative and/or creative in your designs.

One thing that’s killing me is all the testing required to get this stuff to work. Examples: Need to test launching the app on iOS and Android. Does it connect to your game. Need to test both apps, do they correctly disconnect if you exit the app. Need to test do they recover from a bug in the controller. Need to test they switch games correctly. Need to test if you use the browser to go to the game it switched you to the app. Need test if you use the auto-connect installation mode all those paths work. That adds up to hours of testing. People might say find an automated way to test but given there’s 3-4 moving parts (the phone or simulator, the phone’s browser, happyfuntimes running somewhere, happyfuntimes.net running locally, etc) and you need touch guestures on the phone and exiting and re-starting the app for certain tests I’m at a loss of how to test other than manually. Even if there was a way I suspect it would take 4-8 weeks of work to get it setup.

That doesn’t include the testing I need to do just for HappyFunTimes itself like testing OSX and Windows installers work, that the Unity plugin works on both platforms starting from a fresh install, and other things. I fact I shipped a broken version, 0.0.26, where I had quickly changed the buttons on several samples from text icons to svg images. At a glance it seemed to work but then it turned out of you long pressed both Android and iOS would pop up a “Save Image?” message. DOH!!! Preventing that required different workarounds for both browsers. 0.0.28 should be up that fixes that.

I’m also working on getting HTML5 Gamepad emulation working. Actually I have that working and am in the process of cleaning it up. With that, if you already have an HTML5 game with gamepad support you can just add a script to your page and get HappyFunTimes support. I’m mixed on if that’s a good idea because most games designed for the gamepad API probably need a full Xbox style controller with 12 buttons, 2 analog sticks and a d-pad. Using HappyFunTimes for that will probably make HappyFunTImes look bad because as we all know touch screen d-pads suck! On the other hand though if someone is at a gamejam and they’re using an HTML5 based game engine they can use HappyFunTimes with almost no changes, just design the game to handle as many players as possible, add the script, bam! It also means once Unity5 and Unreal start supporting the HTML5 gamepad API (assuming they don’t already) then you could use that too. …Although I’m just going to guess without looking that they put some artificial limit on the number of controllers in their API 🙁

The reason that came up is we had a short 2 button game jam at the Pico Pico Cafe in Tokyo where Lexaloffle Games is based. We decided to try to make it possible to interface Pico-8 with HappyFunTimes and in the process I realized it would be pretty easy to emulate the HTML5 Gamepad API. Of course if you use that you’re probably not really taking advantage of all the interesting creative ways you could use HappyFunTimes but I’d rather you use it then not. Maybe you’ll be inspired to take it to the next level 🙂

Why No NetGame Object?

It’s hard to know what the best way to design some API is. I have no idea if the designs I picked for HappyFunTimes are good or bad or what. There are a few minor things I’d change if I started over, mostly cosmetic but otherwise I’m mostly happy with it.

But, a few days ago I decided to add a feature to allow multiple computers in a single game. Up until this point HappyFunTimes has been about 1 computer running the game and a bunch of phones as controllers but there’s a project I wanted to make that used multiple machines, in particular I wanted to make an extremely large platform game where you’d walk down a wall or hallway with say 10-15 meters of screens and take your character from one screen to the next. Each screen would be controlled by a separate computer running the game on that screen.

For that all I needed as the ability to move a player from computer to computer. I added that feature in a few minutes, tested it and it worked. Awesome!

I’d done some other projects across computers before and in every case I’d just have to have a special URL for each computer that specified which part of a larger virtual display that computer represented. For example the WebGL Aquarium does this Doing it that way is great if you already know what the layout and dimensions of your monitors will be but I’d always wanted to make a monitor layout editor similar to OSX and Windows. To do that I needed to enable games to talk to each other so that they could all inform at least one of them their dimensions and so that at least one of them could send commands to the others about what part of the large display they were supposed to represent.

And so I set out to write that.

My first thought was I’d have some kind of sendMsgToGame function that took the msg you want to send and an id for the game you wanted to send it to. It would be up to you either make up an id yourself, probably from a url, or the system could make one up for you.

But then I thought maybe, just like players have a NetPlayer object that is used to handle the communication between a player and the game I should have a NetGame object that does the same thing for games. This would mean, just like a player, there would be a ‘gameconnect’ message and you’d get passed a NetGame object. If you wanted to send a message to that game you could use someNetGame.sendCmd and anytime a game sent you a message it would arrive on that object.

someNetGame.addEventListener(
    'someMsgIExpectThisGameToSendMe', 
    handleThisTypeOfMsg);

I got that all working, wrote tests, made sure you could send and receive messages, that a disconnect message would get emitted as well.

But… Then the last thing I did was try to implement a broadcast function, broadcastToGames. I knew this was a useful function because I’d used it in the WebGL Aquarium demo I’d linked above. I’d put some camera settings sliders on one computer and broadcast them to all the computers. Broadcasting in this way meant you’d get the same message send back to yourself so you didn’t need custom code. All the machines received their settings from the network, even the one deciding the settings. This was a great way to propagate the settings to all the computers. But, when I tried to implement on top of NetGame it I ran into a problem.

To broadcast you’d call someGameServer.broadcastToGames but given the way NetGame worked all the other games would receive the message on the NetGame object that represented the computer that sent the message but, the computer that sent the message would get the message back on its GameServer object, in this example someGameServer.

That meant it wasn’t at all symmetrical. For the camera settings example in order to accept settings from any computer you’d have to write code like

// when a new game connects
someGameServer.addEventListener('gameconnect', function(netGame) {
  // setup a listener to handle setting the fov
  netGame.addEventListener('setCameraFov', setFov);
});

// Setup yet another listener for when we broadcast 
// a new fov setting because that will
// come back to us here
someGameServer.addEventListener('setCameraFov', setFov);

function setFOV(data) {
  camera.fov = data.fov;
}

That just smelled bad to me. Why should you have to set things up twice? I didn’t have to in previous games. Plus, you had to track all these NetGame objects.

I ended up getting rid of the NetGame objects. There is no gameconnect message. Instead, messages to a game from another game always arrive on the GameServer for that game. So previous example of setting the camera fov removes the second case

someGameServer.addEventListener('setCameraFov', function(data) {
  camera.fov = data.fov;
});

Much simpler.

If you want other games to know you connected broadcast a message to them

var server = new GameServer({id: "foo", allowMultipleGames: true});
server.broadcastToGames('imAlive');

The other games will receive the message along with your id.

// some other game
var server = new GameServer({id: "bar", allowMultipleGames: true});
...
server.addEventListener('imAlive', function(data, id) {
  console.log("some game just joined. Its id is " + id);
}

This will print

some game just joined. Its id is foo

Of course when you broadcast that message will come back to you so you might need to filter out your own id

var ourId = "foo";
var server = new GameServer({id: ourId, allowMultipleGames: true});
server.broadcastToGames('imAlive');
...
server.addEventListener('imAlive', function(data, id) {
  if (id != ourId) {
    console.log("some game just joined. Its id is " + id);
  }
}

Of course depending on your needs maybe you don’t want to filter. For example if you made a screen position editor like I referenced above ideally you’d just display the id of each machine with a rectangle to represent it. If you created those in your imAlive message then not filtering would automatically give you an entry for yourself.

If you don’t supply an id it will be provided on connect.

server.addEventListener('connect', function(data) {
  console.log("my id is: " + data.id);
});

That id is also available on the GameServer object but it is not available until it has connected.

Good:

var server = new GameServer();
server.addEventListener('connect', function(data) {
  console.log("my id is: " + server.id);
});

Bad:

var server = new GameServer();
console.log("my id is: " + server.id);  // ERROR! id not available yet as server has not connected.

Finally you need some way to know when a game disconnects so there’s a gamedisconnect message

server.addEventListener('gamedisconnect`, function(data, id) {
  console.log("Some other game " + id + " disconnected");
});

I don’t know if this post made any sense. It kind of ended up being like docs. Partly I just wanted to document the iterations. I spent a lot of time making the NetGame implementation and testing it only to throw it all way. Even after I threw it away I went through a few more smaller refactorings.

The first one was I made up a gameid command to pass back the gameid. I didn’t like that at all though. It took me a while to figure out how to pass it back on the connect message where it seemed like it belonged. Another thing that happened at the start was I had a 2 ideas per game. The generated id AND a user assigned id. It took a while to come back to just 1 id. Either the on you assign or the one you let the system assign for you.

I’m feeling relatively confident that what I ended up with is a good solution. I guess one more thing though is that I didn’t push out a version until I felt good about it. Sure there aren’t lots of devs yet but taking this stuff seriously will hopefully more confidence that I won’t have to make future breaking changes.