Creating an Enemy with Adobe Animate

Note

This document is a work in progress which will take time to complete.

If you intend to make an enemy for Helixftr Deluxe, please let me know! It will be a lot easier to work on this knowing that someone is actually using it.

— LongLevy (Bluesky/Patreon) | last edited March 1, 2026

The following files are provided as tools and learning aids.

File Description
Enemy Template These files can be used to create a new enemy without starting from scratch.
Example Enemy This is a working example enemy that can be used to learn from. The file includes the working FLA file and also can be loaded directly into the game.

Table of Contents

  1. Introduction
  2. File Structure
  3. Document Setup
  4. Animation Structure
  5. Global Variables
  6. Common Use Examples

Introduction

[[ref:AdobeEnemy]] is the JavaScript class which handles Helixftr Deluxe enemies made in Adobe Animate. Adobe Animate 2024 or later is required to export assets into HTML5 format for use with JavaScript.

In February 2026, Adobe announced plans to shut down Animate. Though they quickly backed down from this decision, other methods to create enemies are being researched to avoid reliance on this program.

File Structure

All the files for a character must be contained in a single ZIP file. An example of the expected structure of the ZIP file is below. Items with asterisks are required.

It is important to select the files inside the working folder to create the ZIP file. Do not create the ZIP file by selecting the working folder itself. Remember: don't include the working FLA file, as this is unneeded and will make your file very large.

portrait.png

The portrait file is a close-up image of the character's head with a transparent background. This does not have to be not have to be an image of the character's model exactly as they appear in the game, but could instead be artwork of the character.

This image should be square, but otherwise has no size requirements. It would be best to be at least 200 pixels, and all "official" Helixftr Deluxe character portraits are 256 pixels.

fullbody.png

The fullbody file is an image of the entire body of the character with a transparent background, as they appear in the game. It has no size requirements, and its scale and position on the character selection screen are determined by fields in meta.json.

manifest.json

The manifest file contains information about the character in JSON format that is extracted from the ZIP file without downloading the entire file. Below is an example manifest file with all possible fields.

{
  "author": "LongLevy",
  "author_link": "https://www.hungrycritters.net/",
  "background": {
    "image_smoothing": true,
    "path": "images/TestBackground.png",
    "scale": 0.8,
    "y": -500
  },
  "custom_fields": [
    ["Description", "A simple copy of the real Gandr, this version shares some of his abilities but none of his personality."]
  ],
  "enemy_class": "AdobeEnemy",
  "preview": {
    "helix_scale": 3.35,
    "path": "fullbody.png",
    "scale": 0.727,
    "x": 719,
    "y": 93
  },
  "game_version": 1,
  "init_file": "init.js",
  "main_file": "main.js",
  "manifest_version": 1,
  "name": "Polygandr",
  "portrait": "portrait.png",
  "title": "Simulacrum Kobold"
}

Fields

Field Description
author* The name of the author (your online handle).
author_link The URL of a webpage where people can see more of the author's work. This is currently unused, but will be added in the future.
background Fields for customizing the display of the character's background in the character select screen.
  • image_smoothing: whether to scale the background image smoothly. Setting false will make the background pixelated.
  • path**: the location of the background file inside the ZIP file
  • scale: the scale of the background image from its original size
  • y: The Y coordinate offset from the top of the screen. Smaller values move the background upward.
custom_fields An array of custom fields that will be displayed in the character's profile in order. Each entry is an array with two items: [0] field title, [1] field value. Assign an empty string to the field title to omit the title.
enemy_class The JavaScript class to be used for this enemy. If you are following along with this document, it should be "AdobeEnemy".
preview Fields for customizing the display of the character in the character select screen.
  • helix_scale: the scale of the Helix size-comparison silhouette. If omitted, the helix size reference will not be displayed. This may be desired for enemy encounters that don't feature Helix.
  • path: the path inside the ZIP file structure of the background image. If omitted, the default background will be used on the character select screen.
  • x*: X coordinate of the fullbody image from the top left corner of the screen
  • y*: Y coordinate of the fullbody image from the top left corner of the screen
  • scale: the scale of the fullbody image from its original size. If omitted, the image will be displayed at 100% size.
init_file* The path of the init file inside the ZIP file structure.
main_file* The path of the main file exported from Adobe Animate inside the ZIP file structure.
game_version* The version of the game this character was made for. Currently unused, as there is only one version.
manifest_version* The version of the meta file. Currently unused, as there is only one version.
name* The name of the enemy.
portrait* The path of the portrait image file inside the ZIP file structure.
title* The title of this enemy, usually the status property set inside the enemy file.

*Required field.
**Required field only if its parent field exists.

init.js

The init file contains some instructions for building the enemy in the game. The game looks for the following exported properties:

animations Property

The animations property is a required array of strings that lists all the character animations that will be used in your enemy. This animations are Animate library items with their linkage property set. Each string is an item's linkage name.

// A list of character animation MovieClips. They must have their linkage name set in the Animate library.
export const animations = [
  "Idle",
  "Move"
];

properties Property

The properties property is an optional object with properties that you want to set on the enemy at creation. If a property is an object and the enemy already has an object assigned to that property, the properties of the new object will be assigned to the original object.

// A list of character animation MovieClips. They must have their linkage name set in the Animate library.
// These properties are copied to the character after it is created.
export const properties = {
  name: "Polygandr",
  status: "Kobold Simulacrum",
  credit: "LongLevy"
};

init Property

The init property is an optional function that runs after the properties are set, in case conditionals are needed. The this variable inside the function is assigned to the enemy object, but the global E can also be used to access the same object.

// This function is called with the character clip as "this" after the properties are set, in case further instructions are needed.
export const init = function() {
  const date = new Date();
  
  // Check if today is Halloween (getMonth() starts at zero).
  if(date.getMonth() == 9 && date.getDate() == 31) {
    this.setValue("halloween", true);
  }
};

main.js

The main file is the JavaScript file exported from Adobe Animate by selecting File > Publish in the menu. Care has been taken to allow use of this file without any further modification after exporting.

Document Setup

It is recommended to use the provided template file at the top of this page when starting a new enemy. This file contains some helper objects to aid in development, including parts for Helix animations. Otherwise, follow the following instructions.

In the New Document dialog window, the Platform Type field should be set to "HTML5 Canvas" and the FPS field to "30". The size of the canvas does not matter at all, as it is not used.

Access Publish Settings through the menu by selecting File > Publish Settings... In the HTML/JS tab, uncheck "Overwrite HTML file on publish". In the Image Settings tab, set the Export As field to "Image Assets". Click the "OK" button to save these settings. In the future, selecting File > Publish in the menu will publish your project with these settings.

Animation Structure

Unlike the original Helixftr, which used one long animation timeline to hold all animations, AdobeEnemy holds each animation in its own [[cjs:MovieClip]]. This prevents clutter of the timeline with parts that show only for specific animations, or when the character model changes significantly. It also sidesteps a problem Animate's exporter causes by chaining too many method calls together in extremely long [[tjs:Tween]]s, throwing recursion errors.

These [[cjs:MovieClip]]s are created directly from the library and do not need to be placed on the stage. However, in order for Animate to include them in the export, their linkage names must be set. This can be done by double clicking in the Linkage column in the library panel in an item's row. The linkage name can—and usually should—be the same as its name to prevent confusion.

Global Variables

The following global variables are defined in the game environment:

These variables are available in all code, notably the frame code of any nested [[cjs:MovieClip]]s, to avoid having to traverse the display structure with this.parent.parent chains.

Example

// Check if a collision shape in the enemy collides with one in the player.
if(E.getRect("attackBox").intersects(P.getRect("rollbox"))) {
  G.shake(1);
  E.playAnim("AttackSuccess");
}

G Global Object

The G global object contains the following properties:

chance(percent:Number = 0.5):Boolean

A holdover from the original game, this returns true or false with the given probability from 0 to 1. Call this with no parameters for a 50% chance.

dialog(text:String):undefined

Displays the given text as a subtitle at the bottom of the screen for three seconds.

level:Level

A reference to the current [[Level]] object.

paused:Boolean

Whether the game is currently paused.

shake(amp = 1, freq = 1, decay = 0.01):undefined

Shakes the screen. Frequency and decay are currently unused, but are planned to be added in the future.

showResetAlert(text:String, color:String):undefined

Displays an alert in the bottom right corner of the screen with options to reset the encounter or continue. Call with no parameters to display the default "You are stuck. Reset?" message.

Common Use Examples

// Check if Helix is colliding with a collision shape on every frame.
E.drawStartFunc = function() {
     if(E.hitPlayer("attackBox")) {
          E.playAnim("AttackSuccess");
     }
};

// Remove drawStartFunc on the frame after the collision shape is removed from the stage.
E.drawStartFunc = null;

// Scale a MovieClip to show the amount of progress.
// Custom variable "progress" is expected to be a number from 0 to 100.
E.currentAnim.getChildByName("progressBar").scaleX = E.getValue("progress") / 100;

// Animation progress determined by a custom variable.
E.drawStartFunc = function() {
     const belly = E.currentAnim.getChildByName("belly");
     const finalFrame = belly.totalFrames - 1;
     
     // Custom variable "bellyProgress" is expected to be a number from 0 to 100.
     belly.gotoAndStop(Math.min(E.getValue("bellyProgress") / 100 * finalFrame, finalFrame));
};

// Make eye MovieClip stop on a frame determined by the custom variable "emotion".
// emotion is expected to be either an integer frame number or a frame label string.
E.currentAnim.getChildByName("head").getChildByName("eye").gotoAndStop(E.getValue("emotion"));

// Example for easy definition of a drawStartFunc that is reused in many animations.
// init.js:
export const properties = {
     vars: {
          updateProgress: function() {
               // Custom variable "progress" is expected to be a number from 0 to 100.
               E.currentAnim.getChildByName("progressBar").scaleX = E.getValue("progress") / 100;
          }
     }
};

// Frame code on the first frame of several animations containing a progress bar:
E.drawStartFunc = E.getValue("updateProgress");