Skip to content

Getting started

Steve Butler edited this page Aug 26, 2026 · 27 revisions

The following steps should help you get started with the HCJE. The HCJE has been designed to facilitate incorporation into a project as a Git submodule and contains build tools that run in a Node.js environment. No additional packages need to be added to the Node environment.

Note

In the code samples, function comments are minimal to keep the examples as short as possible. Also in some cases the code is deliberately not as efficient as possible in order to highlight certain features of the HCJE.

Add the HCJE to your project

This guide assumes that your current project structure looks something like this:

myProject
    package.json
    + source
        index.html
        + other source files and required folders

Tip

Although you can name the source folder to anything you like, src for example, keeping the name as above will make this guide easier to follow and reduce any necessary editing of the configuration files used by the project.

If you don't have a package.json file yet, you can run npm init from within your myProject folder.

To install the HCJE as a submodule in the project structure above, you can simple run the following command from within the myProject folder:

git submodule add https://github.com/henspace/html-css-js-engine source

The result should be:

myProject
    + source
        index.html
        + other source files and required folders
        + html-css-js-engine
            + all the hcje files

Warning

Make sure the HCJE submodule is installed in the same folder as index.html and the rest of the source, and that its name is not changed from its default of html‑css‑js‑engine as this name and location are required for the build script to operate correctly.

The HCJE should now be installed ready for use.

Add scripts to your package.json file

First ensure that package.json includes the following lines and that the main property has been removed. We are only using package.json as a build tool and not for publishing Node packages.

"type": "module",
"private": true,

To utilise some of the tools in the HCJE, you must modify your package.json file to facilitate running the scripts. Typically your scripts property should include the following:

  "scripts": {
    "prebuild": "npm run test",
    "build": "node ./source/html-css-js-engine/tools/build/build.js ./build-config.json",
    "test": "node ../source/html-css-js-engine/tools/testing/runner.js test-config.json",
    "serve-build": "node ./source/html-css-js-engine/tools/server/server.js 8080 ./build",
    "serve-source": "node ./source/html-css-js-engine/tools/server/server.js 8080 ./source"
  },

The build and test commands require JSON configuration files, build-config.json and test-config.json respectively. There are sample configuration files in the HCJE submodule in the folder resources_for_submodule_users. You can copy these into the root folder of your project alongside package.json.

Note

The default build configuration will not create a zip file of the resulting build. If you require a zipped version of the build, you will need to edit the build‑config.json file and set the zippedOutputDir property; if using Windows, you will probably need to alter the zipOptions.win32.cmd property as well.

Modify your game's index.html to load the HCJE

Your index.html page will need to load the HCJE style sheet, your style sheet, the HCJE scripts, and finally your own game scripts. The following code shows the way to do this.

<html>
  <head><link rel='stylesheet' href='html-css-js-engine/source/hcje/styles/style.css'>
    <link rel='stylesheet' href='styles/style.css'>
  <head><body>
    <p>Loading. Please wait.</p>
  </body>
  <script type = 'module' src='html-css-js-engine/source/hcje/scripts/hcje-lib.js'></script>
  <script type = 'module' src='scripts/index.js'></script>
</html>

Warning

The build tools automatically flatten the HCJE folder and place the HCJE's script files in a subdirectory named _hcje and modify the link and script lines above by replacing html-css-js-engine/source/hcje with _hcje. As such it is important to write the references to the HCJE style and script files as shown above.

The result of the build process is summarised below.

outputFolder
  + index.html
  + other source files and required folders
  + _hcje
<link rel='stylesheet' href='_hcje/styles/style.css'>
...
<script type = 'module' src='_hcje/scripts/hcje-lib.js'></script>

When we start writing our game code we will remove the content of the <body>. This means that index.html can contain any information we like to indicate to the user that we are loading.

Create the game area

We now need to use code in our index.js script to clear the loading information from the body and create the game area. Add the following code to your script. You can change the GAME_WIDTH_ and GAME_HEIGHT constants to your own preferred values.

/**
 * Load assets and set up the environment.
 */
function loadAssets() {
  const assets = {};
  return Promise.resolve(assets);
}

/**
 * Start the game.
 */ 
function startGame(assets) {
  const GAME_WIDTH = 672;
  const GAME_HEIGHT = 420;
  document.body.replaceChildren();
  const gameArea = new hcjeLib.domTools.GameArea({
    width: GAME_WIDTH,
    height: GAME_HEIGHT,
  });
  const title = new hcjeLib.domTools.createChild(gameArea, 'p', 'game-title');
  title.innerText = 'My game';
}

// execute the game
loadAssets()
  .then((assets) => startGame(assets));

At the very bottom of the example code we call the loadAssets function. This function currently does nothing and just returns a Promise that fufils to an empty object. Later on it may be used to load assets that take time but which we want to ensure have completed before starting the game. The startGame function is called once loadAssets has completed. The startGame function clears the existing body, creates the GameArea and adds a title. If you run it, you should see a rather boring grey rectangle appear.

Note

Information about the createChild and createGameArea methods can be found in the hcje/domTools module documentation.

Add a welcome dialog

Most games have music, but music can only be started in HTML games in response to a user action. So, in most games you will want to start with a button being clicked. In this code modification, we'll make the following changes:

  • Create a playGame function. This will hold our main game code when we get round to writing it.
  • Modify startGame to create a welcome dialog and then call the playGame function.
/**
 * Load assets and set up the environment.
 */
function loadAssets() {
  const assets = {};
  return Promise.resolve(assets);
}
/**
 * The main game loop.
 */
function playGame(gameArea) {
}

/**
 * Start the game.
 */ 
function startGame(assets) {
  const GAME_WIDTH = 672;
  const GAME_HEIGHT = 420;
  document.body.replaceChildren();
  const gameArea = new hcjeLib.domTools.GameArea({
    width: GAME_WIDTH,
    height: GAME_HEIGHT,
  });
  const title = new hcjeLib.domTools.createChild(gameArea, 'p', 'game-title');
  title.innerText = 'My game';
  
  hcjeLib.domTools.createDialog({
    title: "Welcome",
    markdown: "Click the *PLAY* button to get started.",
    children: [],
    buttonDefns: [
      {id: 'PLAY', label: 'Play'},
    ]
  })
    .then((id) => playGame(gameArea, assets)); 
}

// execute the game
startGame();

If you run this code, you should finish up with a welcome dialog appearing that closes when you click the play button.

Note

The loadAssets fulfils to an empty object at the moment, but this will be used later to return objects that are loaded in the function. This object is passed to the startGame function and then on to the playGame.

Note

information about the createDialog method can be found in the hcje/domTools module documentation.

Add a sprite

To make things a little more interesting, let's add a simple text Sprite to our game. We're using a text sprite so we don't have to worry about loading images.

Modify the playGame function as shown below:

/**
 * The main game loop.
 */
function playGame(gameArea) {
  const GAME_DIMENSIONS = gameArea.designDims;
  const mySprite = hcjeLib.sprites.createTextSprite(gameArea, "HELLO *WORLD*",
    { markdown: true,
      dimensions: {width: 64, height: 64}
    });
  mySprite.position = {x: GAME_DIMENSIONS.width / 2, y: GAME_DIMENSIONS.height / 2, angle: Math.PI};
}

This code creates a simple text sprite and then positions it near the middle of the game area and rotated by 180°(π radians). It's not actually centred as the position property is the sprite's top-left corner and not its centre.

Add a sprite from a texture

This is where things start to get a bit more interesting. First let's modify the loadAssets function to load a sprite sheet. In this example, we assume you have a folder named assets/textures and this contains the image sprite-sheet.png and associated data file sprite-sheet.json. In this guide the image contains three frames as shown below:

player_eating0.png player_eating1.png player_eating2.png

These represent a sprite with a basename of player.png, a state of eating, and three numbered frames: 0, 1 and 2.

Note

You can find sample files for this guide in the HCJE submodule in the folder resources_for_submodule_users\assets\textures. You can copy these into your source/assets/textures folder. Refer to the hcje/sprites module for details on how to create your own sprite sheets.

function loadAssets() {
  const assets = {};
  return hcjeLib.sprites.loadSpriteSheet(
    "assets/textures/sprite-sheet.json",
    "assets/textures/sprite-sheet.png", 
    new hcjeLib.domTools.TimeLimitedBusyIndicator()
  )
    .then((texture) => {
      assets.textureManager.spriteFactory = new hcjeLib.sprites.DomImageSpriteFactory(gameArea);
      assets.textureManager = textureManager;
      return assets;
    });
}

The loadSpriteSheet method creates a TextureManager instance which is added to the assets object once it has been loaded. The spriteFactory property of the TextureManager is also set to a DOMImageSpriteFactory. The TextureManager will use this factory to create sprites from the images contained in the texture.

Note

Information about the loadSpriteSheet method can be found in the hcje/sprites module.

Tip

You can use any naming convention you want for the images in the sprite sheet, but if you follow the default convention you will not need to create your own frameNameGenerator function.

Now the texture is loaded, let's replace our text sprite with an image loaded from the texture. To do this we need to modify the playGame function as follows:

  • Remove the call to the hcjeLib.sprites.createTextSprite as we no longer want the text sprite.
  • Create a sprite using the texture's createSprite method.
function playGame(gameArea, assets) {
  const GAME_DIMENSIONS = gameArea.designDims;
  const mySprite = assets.textureManager.createSprite("player.png", [
    {name:"eating", interval:100, cycleType: hcjeLib.sprites.CycleType.OSCILLATE}
  ]);
   mySprite.position = {x: GAME_DIMENSIONS.width / 2, y: GAME_DIMENSIONS.height / 2, angle: Math.PI};
}

You should finish up with a sprite towards the middle of the screen, but it won't be animated yet. To animate the sprite, we need to add an Animator to the game and update it. Add the following lines to the bottom of your playGame function.

const animator = new hcjeLib.sprites.Animator();
animator.addTarget(mySprite);
animator.active = true;

These lines simply create an Animator and then add the sprite to the list of targets that need to be regularly updated and finally turns the animator on.

If you run the code, the sprite should now be animated.

Clone this wiki locally