Deployment

Deploying PICO-8 Cartridges with Electron

This article uses Linux. If you aren't running linux, there's a good chance you can still follow along if you have some command-line-fu.

There has been a lot of discussion about deploying PICO-8 cartridges to a native desktop application. Don't get me wrong, I think it's awesome that folks distribute the *.p8.png file format, but as most game developers know, most gamers honestly just want a double click format. I've done this with Vi8 using PICOLOVE and a bunch of hacks. It's dirty, painful and no one really wants to do that anyway.

I have found a way to do this using Electron.

Note to Reader: I'd like to think this article is a joke for the most part. I mean, we're taking about ~1.3MB of data, and we're making a deployable that's ~40MB. Reader beware, but I think it's reasonable to document this process anyway.

For this article, I will be exporting The Career of Peter to desktop!

1. Get your cartridge ready for electron

So, there's going to be some steps that need to be done, before we can even start.

Load and save please

Here we load our cartridge as we normally do with load foo.p8 and then we use PICO-8's export foo.html feature to make a website version of the game.

Here's the files we now have:

seppi@seppi7:~/TheCareerOfPeter♠ ls -lah
total 1.4M
drwxr-xr-x   2 seppi seppi 4.0K Oct 21 20:04 .
drwx------ 134 seppi seppi  20K Oct 21 20:00 ..
-rw-r--r--   1 seppi seppi 4.5K Oct 21 20:04 thecareerofpeter-v18.html
-rw-r--r--   1 seppi seppi 1.3M Oct 21 20:04 thecareerofpeter-v18.js
-rw-r--r--   1 seppi seppi  72K Oct 21 20:01 thecareerofpeter-v18.p8

Now we need to "clean up" the cartridge for deployment.

I. Update the title of the cart

     <head>
         <meta charset="utf-8">
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
-        <title>PICO-8 Cartridge</title>
+        <title>The Career of Peter</title>
         <meta name="description" content="">

 <STYLE TYPE="text/css">

II. Get rid of the body padding.

 canvas#canvas { width: 512px; height: 512px; }

+body {
+  padding: 0px;
+  margin: 0px;
+}
+

III. Get rid of the .pico8_el stuff.

 .pico8_el {
    float:left;
    width:92px;
    font-size: 9pt;
    cursor: pointer;
    cursor: hand;
+   display: none;
 }

IV. Destroy those <br> tags with extreme prejudice.

 <body bgcolor=#303030>

-   <br><br><br>

    <center><div style="width:512px;">


    </script>

-   <br>

    <div class=pico8_el onclick="Module.pico8Reset();">
```


    Carts</a></div>

-   <br>    

    </div></center>
-   <br><br>

 </body></html>

Awesome! Now the PICO-8 export should show up nicely in electron!

2. Set up Electron, Prebuilt and Packager

I then installed globally npm and updated it with:

sudo npm install npm@latest -g

I then install electron globally:

sudo npm install electron -g

Finally in the working directory, I run:

npm install electron-prebuilt and npm install electron-packager

This provides a back-end to getting binaries for every platform and the packaging system that will build the binary. You will now notice a big honking node_modules/ folder. Fun.

Now that we have that, we need to set up the required package.json for electron. Just put it in your working directory. Here's what I have (it seems to work ...):

{
    "name": "the-career-of-peter",
    "version": "1.18.0",
    "description": "The Career of Peter by Missing Sentinel Software",
    "main": "main.js",
    "scripts":{
        "start":"electron .",
        "build":"electron-packager . TheCareerOfPeter --all"
    },
    "author":"Josef Patoprsty <josefnpat@gmail.com> (http://josefnpat.com)",
    "license":"Josef Patoprsty",
    "devDependencies": {
        "electron-packager":"^8.1.0",
        "electron-prebuilt":"^1.3.8"
    },
    "electron-packager":"^8.1.0"
}

3. Set up main.js

So, now we need to inform electron how it's supposed to work. I modified an example main.js I found, and this one works for me.

const {app, BrowserWindow} = require('electron')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({
        width: 512,
        height: 512,
        title: "The Career of Peter",
        resizable: false,
        maximizable: false,
        fullscreenable: false
    })
    win.setMenu(null);

  // and load the index.html of the app.
  win.loadURL(`file://${__dirname}/thecareerofpeter-v18.html`)

  // Open the DevTools.
  //win.webContents.openDevTools()

  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

With this in place you can now test your application before building it with electron .

4. Build your application

Now we use our nifty build script defined in package.json:

seppi@seppi7:~/TheCareerOfPeter♠ npm run build

> the-career-of-peter@1.18.0 build /home/seppi/TheCareerOfPeter
> electron-packager . TheCareerOfPeter --all

Packaging app for platform linux ia32 using electron v1.3.8
Packaging app for platform win32 ia32 using electron v1.3.8
Packaging app for platform darwin x64 using electron v1.3.8
Packaging app for platform linux x64 using electron v1.3.8
Packaging app for platform mas x64 using electron v1.3.8
WARNING: signing is required for mas builds. Provide the osx-sign option, or manually sign the app later.
Packaging app for platform win32 x64 using electron v1.3.8
Packaging app for platform linux armv7l using electron v1.3.8
Wrote new apps to:
/home/seppi/TheCareerOfPeter/TheCareerOfPeter-linux-ia32
/home/seppi/TheCareerOfPeter/TheCareerOfPeter-win32-ia32
/home/seppi/TheCareerOfPeter/TheCareerOfPeter-darwin-x64
/home/seppi/TheCareerOfPeter/TheCareerOfPeter-linux-x64
/home/seppi/TheCareerOfPeter/TheCareerOfPeter-mas-x64
/home/seppi/TheCareerOfPeter/TheCareerOfPeter-win32-x64
/home/seppi/TheCareerOfPeter/TheCareerOfPeter-linux-armv7l

With that we have tons of builds! You could run one of them like this:

./TheCareerOfPeter-linux-x64/TheCareerOfPeter

The Career of Peter running in Electron!

And just for "science", let's check out how big these files are:

seppi@seppi7:~/TheCareerOfPeter♠ ls -lah
total 442M
drwxr-xr-x  10 seppi seppi 4.0K Oct 21 20:37 .
drwx------ 134 seppi seppi  20K Oct 21 20:36 ..
-rw-r--r--   1 seppi seppi 1.7K Oct 21 20:31 main.js
drwxr-xr-x 187 seppi seppi 4.0K Oct 21 20:15 node_modules
-rw-r--r--   1 seppi seppi  482 Oct 21 20:07 package.json
drwxr-xr-x   3 seppi seppi 4.0K Oct 21 20:34 TheCareerOfPeter-darwin-x64
-rw-r--r--   1 seppi seppi 116M Oct 21 20:36 TheCareerOfPeter-darwin-x64.zip
drwxr-xr-x   4 seppi seppi 4.0K Oct 21 20:34 TheCareerOfPeter-linux-armv7l
-rw-r--r--   1 seppi seppi  36M Oct 21 20:36 TheCareerOfPeter-linux-armv7l.zip
drwxr-xr-x   4 seppi seppi 4.0K Oct 21 20:34 TheCareerOfPeter-linux-ia32
-rw-r--r--   1 seppi seppi  43M Oct 21 20:36 TheCareerOfPeter-linux-ia32.zip
drwxr-xr-x   4 seppi seppi 4.0K Oct 21 20:34 TheCareerOfPeter-linux-x64
-rw-r--r--   1 seppi seppi  41M Oct 21 20:36 TheCareerOfPeter-linux-x64.zip
drwxr-xr-x   3 seppi seppi 4.0K Oct 21 20:34 TheCareerOfPeter-mas-x64
-rw-r--r--   1 seppi seppi 114M Oct 21 20:36 TheCareerOfPeter-mas-x64.zip
-rw-r--r--   1 seppi seppi 4.5K Oct 21 20:32 thecareerofpeter-v18.html
-rw-r--r--   1 seppi seppi 1.3M Oct 21 20:04 thecareerofpeter-v18.js
-rw-r--r--   1 seppi seppi  72K Oct 21 20:01 thecareerofpeter-v18.p8
drwxr-xr-x   4 seppi seppi 4.0K Oct 21 20:34 TheCareerOfPeter-win32-ia32
-rw-r--r--   1 seppi seppi  42M Oct 21 20:36 TheCareerOfPeter-win32-ia32.zip
drwxr-xr-x   4 seppi seppi 4.0K Oct 21 20:34 TheCareerOfPeter-win32-x64
-rw-r--r--   1 seppi seppi  52M Oct 21 20:37 TheCareerOfPeter-win32-x64.zip

To check out the final result for yourself, mosey on over to The Career of Peter

About Seppi

Howdy; my name's Seppi, and I'm an indie game developer. I am an active member of the LÖVE community. I've been making games for years now, and I'm always interested in helping prospective indie developers out.

One of the paradoxes I've learned over the years, especially as a software developer, is the more I know, the more I realize I don't know. I quote;

Only a fool would take anything posted here as fact.

Questions, comments or insults? Feel free to leave in the comments section, or contact me; you can hit me up on twitter @josefnpat

Subscribe to RSS - Deployment