Going to use Observable for the Global Game Jam at 25-27 January and looking for tips

So I’m thinking of using Observables for the GGJ, which is coming the weekend after this one. For the simple reason that It’s great fun to develop in, I don’t have grand ambitions (read: requiring native code for performance and such), and once done I can immediately share the results via the web very easily.

Maybe others would like to do the same?

EDIT: Here is the template notebook I have settled on for now. It has

  • Tom McWainwright’s function to easily load (multiple!) p5.js sketches
  • good fullscreen support (thanks to Mike Bostock),
  • a demo of how to use Howler to play back sounds
  • example code of checking if touch input is inbounds of the p5.js canvas
  • example code of triggering fullscreen when touching the p5.js canvas (convenient on mobile)
  • esample code for detecting whether or not the sketch is fullscreen (could be useful for freezing the sketch until running fullscreen, for example)

That should cover the most essential functionality for making games :slight_smile:.

As some prep-work, maybe we could make a list of useful tricks, frameworks and ideas? For example, a bit of quick searching turned up these existing Observable notebooks that could be useful:

If you see any other notebooks you think make sense to add to this list, please reply!

I also still have some unanswered questions:

  • I what is an easy way to create a full-screen canvas?
  • Can I just load p5.js libraries? (have to try this out tonight, I know it’ll just be a dangerous rabbit hole if I try it now) answer: nope

EDIT: Updated lists


Here’s a fullscreen canvas demo:


Thanks! If I can find the time I’ll try to combine it with @tom’s p5 notebook to make a kind of “template” p5js notebook with easy fullscreen support, and optionally p5-sound and p5-play libraries, so others can fork it and get started quickly!

(also so that I’ll have all the scaffolding in place to get going myself :wink: )

Cool. Needed that.

However, when I copy and paste the fullscreen code into one of my notebooks and click it, the background reverses from white to dark grey/blackish. Eg. https://beta.observablehq.com/@martien/x-matrix

Also, seems not to work in Safari (12.0.2).

The background issue is due to the fact that the cell has transparency, and it can be fixed by adding a white background rect to the sheet in showX:

function showX(h) {
  const sheet = d3.select(DOM.svg(canvas.port.width, canvas.port.height));
    .attr('height', '100%')
    .attr('width', '100%')
  highlight(sheet, "lightblue");
  drawMatrix(sheet, h);
  return sheet;

For safari support, you’ll have to use webkitRequestFullScreen instead of requestFullScreen. See my fork of the “Fullscreen Canvas” notebook:

Thanks! The background issue is solved (still wondering where the black background comes from).

Re Safari: the navigator.userAgent test is not specific enough (see below). Trying to find a more robust way to distinguish between user agents. navigator.userAgent fails us here.

Re Safari full screen: Tried your code and it works. But I am very disappointed by its performance: it goes full screen in a very rocky way, and then the image freezes; luckily I can still escape). Running this on a 27" iMac.

Safari returns Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.2 Safari/605.1.15

Chrome returns Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36

Firefox returns Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0

Thanks for pointing out the issue! I’ve updated my fork so that it detects the method directly rather than attempting to parse the userAgent.

I’m not able to reproduce the performance issue in Safari on my MacBook, unfortunately. I do notice that in Safari I see the gray “cell is working” bar on the left in fullscreen but I don’t in Chrome or Firefox.

1 Like

So there is some issue with resizing p5js sketches at the moment:


p5js has a built in method of resizing its canvas, but what I think happens is that it ends up with an infinite resizing loop with its parent cell so it keeps growing.

Try this?

You shouldn’t need to handle window resizing if you use Observable’s built-in reactive width.

1 Like

Almost works the way we want it! Portrait mode on mobile seems to have some issues:

You got me to figure out a work-around though. Basically, I test for the existence of a fullscreen element using fullscreenElement

Same notebook, updated: https://beta.observablehq.com/d/bb4f3e6763187737/

You shouldn’t need to handle window resizing if you use Observable’s built-in reactive width

Ideally not, no, but apparently there are some browser quirks :stuck_out_tongue:. More importantly though, I didn’t want the sketch to restart when entering full-screen.

(Also, it’s apparently one year since you joined this community. Is Observable really that young?)

Well, this doesn’t work on my notebooks. Investigating it, I assume—because I’m still an apprentice in this area—that it works on your notebook because you’re using a canvas (hence canvasDV is available), while I’m using SVG.

So I added an id on creating the svg with d3:

d3.select(DOM.svg(canvas.port.width, canvas.port.height))
  .attr("id", "WhatEverMakesSense")

Next, I can use that id in fullscreen():

const container = document.querySelector('#WhatEverMakesSense').parentElement;

Bonus: you can now use the full screen button anywhere in your notebook.

A more robust implementation should probably use DOM.uid().

Also, I assume this technique can be used to full screen any cell, provided it has a unique and known id?

Hmmm… new issue. On https://beta.observablehq.com/@martien/flower/2 it immediately flips back out of full screen to normal view. Actually, it’s now broken on Safari, Chrome, and Firefox now.


It works if you trigger fullscreen on the closest HTML parent instead of the SVG:

immediately flips back out of full screen

@mootari has already given the fix, but let me point out that avoiding this behavior is the whole reason the “trick” is needed in @mbostock 's original notebook. I tried to explain this in my fork: “Selecting the canvas element [svg element in your case] directly is no good since the canvas element is destroyed and recreated after each yield.”

[Feel free to correct me if that’s not quite what’s going on.]

Close. The show() function accesses width which is an external variable updated by the Observable runtime. When fullscreen is triggered the width changes, causing a reevaluation of the show cell and all dependent cells. As a result, the content of the mainChart cell is destroyed and recreated.


If you want to avoid restarting the sketch when the window resizes and instead use P5’s windowResized hook, here’s an updated approach:

This function computes the desired canvas size:

function canvasSize() {
  return [
    document.body.clientWidth * screen.height / screen.width

This is the same definition of width that the Observable standard library uses, and the height is computed based on the screen’s aspect ratio. For devices that don’t let you use the entire screen you may want to use screen.availWidth and screen.availHeight instead.

1 Like

Happy Cake Day, Mike! :tada::smiley:

This solution still breaks, also with availWidth/availHeight:


Could it be that document.body.cliendWidth includes padding for the scrollbar somehow?