ForumSite Announcements ► <crayon> tag tutorial
UPDATE: Games are now browsable on the Games page. This will list your game if you mark it as 'public'

These are some very rough instructions on how to use the <crayon> tag to post your own games on the forum. This is all very experimental and rough, so please bear with me as this page will likely change a lot over a short period of time.

I'll try to post a few example games that use the TwoCans SDK. The API itself is fairly wonky right now, so please give feedback.

If you encounter problems, please drop by in the IRC channel Slack channel for TwoCans game dev or the Telegram chatroom.

  • Download the latest version of Crayon (0.2.1) and set it up according to the instructions
  • Download the latest version of the TwoCans SDK. There's no installation, just extract the zip file somewhere.
  • Download the sample project.
  • Add the location of the TwoCans SDK to your .build file
    • For example, <crayonpath>C:\MyStuff\TwoCansSDK</crayonpath>. This folder that you list here should directly contain the TwoCansAlpha2 directory.
  • Modify the title and description of your game in the .build file
  • From the command line, navigate to your project and run crayon
  • A window with a bunch of circles flying around should appear.

  • At this point, Crayon and the TwoCans SDK are correctly configured.
  • After writing your game, go to and create a new project.
  • Click Edit for your project
  • Click Upload new version
  • Upload a zip file of your codebase. Generally this should include both the build file, source, and assets directories. (You can include output but it is ignored)
  • Go back to the project page and refresh the page until compilation completes.
    • If this process takes more than 15 seconds, the compiler is down. Please poke Blake.
    • As a matter of etiquette, please do not use the server to debug problems as this slows down the queue for others and cosumes bandwidth. Make sure your project runs successfully on your machine before uploading.
  • Once compilation is successful, you can click View to view that version.
  • If everything is to your liking, click edit and set the release status to "Public".
  • Create a forum post with <crayon id="YourGameId"></crayon> in it.

Please note that TwoCans Crayon projects do not support all libraries. Particularly Games, Graphics2D, Gamepad, Audio, etc are not support. Use the TwoCans API instead, which wraps, simplifies, and streamlines most of the functionality that you need to make a game.

Very Very Lightweight documentation (TwoCansAlpha2)

The sample project is probably a better way to figure things out than this, but...

The API itself is based on the notion of Scenes. One Scene can be active at a time. To create a scene, extend the AbstractScene class and override the following methods:
  • function update(inputManager, events) { ... }
  • function render() { ... }

From the render function, you can make calls to Graphics2D, Graphics2DText, etc.

The only initialization you need to do is make sure that your starting scene is indicated in the build file. If you don't rename the class that's already there, the Sample project already has this done for you. Do not make modifications to main.cry.

Images.get(path) will get an instance of an image. The path is the relative path from the root of your source code folder. Images must be in your source folder in order to get bundled with the final build.

To switch to another scene, invoke this.switchScene(nextScene) from any scene.

Each scene has both an update method and a render method that can be overridden. The update methods take in an input manager and a list of events. These methods are called automatically when the game is running. The game engine itself will provide these values. The input manager has a few useful methods, particularly isKeyPressed.

  • inputManager.isKeyPressed(key) - Pass in a KeyboardKey enum value to check its pressed state. The KeyboardKey enum is in the TwoCansAlpha1 namespace. It matches the built-in KeyboardKey enum, although it's missing several keys that are not recommended for use in a webpage, such as F1-F12 keys, Tab, CapsLock, Alt, etc.
  • inputManager.isShiftPressed() and isCtrlPressed() - returns true if shift/ctrl is pressed. Since tapping shift and ctrl are not recommended for input, their pressed states are exposed in this way.

The events list has Event objects which have the following fields:
  • .type - the type of the event. This is an enum value in the EventType enum with the following values: KEY, GAMEPAD, MENU, MOUSE_PRESS, MOUSE_RELEASE, MOUSE_MOVE.
  • .key - the keyboard key of KEY events.
  • .x and .y - the coordinate of mouse events
  • .down - true if a KEY event is a key press. Also true for MOUSE_PRESS events
  • .button - currently used by MENU events. These are values in the MenuCommand enum and its values are LEFT, UP, RIGHT, DOWN, CONFIRM, BACK.

MENU events are sent redundantly with their KEY and GAMEPAD counterparts. However, if you have a menu scene and are only interested in whether the user wants to navigate up or has pressed a key such as Enter or the gamepad-A button, these events are canonicalized into logical menu commands, rather than forcing you to write code for multiple inputs that basically mean the same thing. This also provides a consistent user experience across games.

If you'd like a smooth fade transition between scenes, you can create a scene called FadeTransitionScene and pass that to switchScene. This class is in TwoCansAlpha2 and the constructor takes 2 scenes (the before and after scene). There are additional parameters as well new FadeTransitionScene(beforeScene, nextScene, durationSeconds, blockUpdate, fadeColor).
  • beforeScene - the scene you're fading from. Typically you'll just pass in this.
  • nextScene - the scene you're fading to. Typically the scene you would have originally passed directly in to switchScene.
  • durationSeconds is the duration of the fade in seconds.
  • blockUpdate is a boolean that will prevent the invocation of the scenes' update methods during the transition.
  • fadeColor is a the color to fade to (in the form of a list of 3 integers).
These last 3 parameters are optional. The defaults are to fade to and from black over the course of 1 second without blocking update.
They told me you had died.
I'm trying to compile the sample project and I'm getting an error "File must be a CBX file." I didn't modify anything with the build file except adding the directory of the SDK.

Is this a dumb error? Have I embarrassed myself?
They told me you had died.

Eric-616 said:
I'm getting an error "File must be a CBX file."

What exactly did you type to run it and from which directory? Which directory is the .build file in?
I extracted the project in its own folder called TwoCansSampleProject exactly as it came in the zip and tried to run "crayon" in that folder from the command line. I'm pretty sure I followed exactly what this guide told me to do. What's weird is I did the same thing on my laptop and it compiled just fine.
HYPE. I like the new API.

I am however confused at a couple steps. I tried adding the crayonpath (pointing to my TwoCansSDK folder) to my existing Reversi project, expecting it to fail to compile since I'm not using the new API. But when I ran "crayon.exe .\", it ran just fine.

I'm also confused at this step:
Blake said:

  • Click Upload new version
  • Go back to the project page and refresh the page until compilation completes.

What should we be uploading? I arbitrarily tried compiling the sample project and uploading output/UntitledGame.cbx. But now it's stuck in the compiler queue. 🙁 Did I break everything?
I didn't leave the compiler running this morning, but you need to upload a zip of the source code. I'll update the instructions when I get home from work and restart the compiler service.

Also, right now the Game/Graphics2D libraries are allowed. Soon, I'll be banning them so the game will have to be written with the TwoCans API exclusively.
Gotcha. I love replacing my own code with standardized libraries (less stuff for me to maintain), and it seems I can eliminate my input manager and color type. 👍

Looks like I missed the compiler boat again though. 😢 Is it running on a machine that's not always online or something?
Yes, now that the runner is a little more stable, I need to set up the laptop I don't pack up and carry around to run this. Sometimes it'll just crash in the middle of the night.
Is the compiler ported to Crayon yet?
That probably won't happen for a while. There's two major projects preventing me from doing that:

  • Adding C as a target for export (otherwise there will still be awkward dependencies)
  • Adding a new frontend language that compiles to the same bytecode. This new language will likely be a clean subset of C# such that I can still use the VS debugger for development and there will be little to no changes to the actual compiler codebase.
Is there (or will there be) a replacement for the functionality of Graphics2DText? I.e., is there any way to render text with the TwoCans SDK?
Not yet.

I'm a little afraid of throwing in a bunch of functionality without designing it properly since API's are hard to change. I'm currently migrating one of my more complicated former PyWeek games to use the TwoCans API as a test to make sure that it's actually useful and not wonky to use. I'll be completing that this weekend.
From error message:
source/main.cry, Line: 1, Col: 1, Unrecognized namespace or library: 'TwoCansAlpha1'
From the server or when running locally?

From the server! Fix imminent. Fixed.

I reset the compilation status on the last version you uploaded. It is now ready for public consumption.
Couple of major things I'm planning on doing soon:
  • Changing the TwoCans API. I'm starting to realize that radically diverging from the built-in API's is probably not a good idea, since basically it becomes 2 API's I have to maintain and online references would be like JavaScript where there's always a jQuery answer and a normal JavaScript answer. I'm going to wrap the Game/Gamepad API's, but allow direct access to the Graphics2D and Audio libraries. This especially makes converting non-TwoCans to TwoCans difficult. Since I chose the scene management approach for the SDK, what I'll do is still include it as an optional (and highly encouraged library) for those writing code from scratch directly for TwoCans.
  • I'm going to change the build file format from XML to JSON. This has been a pain point for a while, and it seems like the sort of change that's better to fix now than before too many people start creating projects.
Cool! Is the compiler server up still? I want to upload a better version.

And 👍 for JSON!
It is right now, but it's still the laptop I carry around, so there are sometimes periods of radio silence.
Would it be possible to specify the window size in the build file or something? It's currently hard-coded at 640 x 480. (I actually want to reduce the window size, in case you're worried I'll explode the forum formatting.)
Yeah, I can do that.

From the new API:
const SCREEN_WIDTH = $var['screen_width'] ?? 640;
const SCREEN_HEIGHT = $var['screen_height'] ?? 480;


width = Math.floor(SCREEN_WIDTH);
height = Math.floor(SCREEN_HEIGHT);
if (width > 640|| height > 480) throw new InvalidArgumentException("Game screen size must be smaller than 640 x 480 to fit site UI");
if (width < 256|| height < 224) throw new InvalidArgumentException("This screen size is too small");
if (width / height < .5) throw new InvalidArgumentException("This screen size is too tall.");
if (width / height > 2) throw new InvalidArgumentException("This screen size is too wide.");

This will be in TwoCansAlpha2, which will remove all layer silliness and just rely on Graphics2D calls directly.
TwoCansAlpha2 SDK is now out! Same download links. Documentation has been updated. Sample project has been updated as well.

Notably layers have been removed entirely. Just make calls to the built in Graphics2D and Graphics2DText libraries.
Another couple pretty-please feature requests for the SDK:

1) Access to mouse input via the inputManager (as opposed to only through events)
2) A function that reports whether a given key/mouse button was pressed this frame

Currently we have to keep track of which buttons were pressed last frame if we want to do something upon a button press.
New TwoCansAlpha2 SDK uploaded! I didn't change the name/version, but it has these new methods in InputManager.

New InputManager methods:
  • isKeyPressedThisFrame(key) --> boolean
  • isKeyReleasedThisFrame(key) --> boolean
  • getMousePosition() --> returns coordinates as a list of two integers
  • isMouseOver(left, top, width, height) --> boolean, true if mouse is over the given rectangle
  • didMouseClickHere(left, top, width, height) --> boolean, true if mouse clicked in the rectangle in the current frame

Old methods are still there:
  • isKeyPressed(key) --> boolean
  • isShiftPressed() --> boolean
  • isCtrlPressed() --> boolean
Games is now one of the main links at the top of the page. It lists all the games that have a public version.
I greatly anticipate playing them. Will you add the old ones to that section?
Forum > Site Announcements > <crayon> tag tutorial