Log In
Online Members (0)
No members are currently online.
Current Interguild Time:
Mon Jul 6 2020 2:29 am
Member Chat Box  [click here to enlarge]
Recent Posts and Comments
« Blogs Index < Aeon Project
« Livio's Blog

Click here for part one.

Table of Contents
( 1 ) Triggers
    ( 1.A ) Events
( 2 ) Properties
    ( 2.A ) Hitbox
    ( 2.B ) Collisions
    ( 2.C ) States: Static and Nonstatic
    ( 2.D ) Animation
( 3 ) Precedence
( 4 ) Tips and Tricks


If you looked at the level code for the default level, you'll notice that the biggest chunk of it is the under the
tag. Each style definition contains a set of triggers and a set of properties:

Hopefully, it's self-explanatory that the properties are what determine the concrete settings for each style definition.

Each trigger is based on the ID of a specific object type that you defined under the tag. For example, if you wanted to change the size of all of the objects with the id of 'x', your style definition would look like this:
x { ... }
. If you wanted the same settings to apply to more than one object, you can stack triggers together like this:
x, y, z { ... }
. But note that the previous example has the same effect as the following:
x { ... }
y { ... }
z { ... }


Most of the time, you'll want to change a setting based on a certain event that has happened to that object. Here's a list of all of the events that you can respond to:
  • water
    - when the object is submerged in water
  • ladder
    - when the object is in collision with a ladder
  • crawling
    - this event is triggered by the Behavior system, which hasn't been implemented yet, aside from the player controls.
  • jump
    - this event is only active for the split second in which the player is jumping. Like crawling, it's only triggered by the Behavior system.
  • standing-on-down
    - when the object has collided with something solid on its bottom border.
  • standing-on-up
    - when the object has collided with something solid on its top border.
  • standing-on-right
    - when the object has collided with something solid on its right border.
  • standing-on-left
    - when the object has collided with something solid on its left border.
  • left
    - triggered by Behaviors, and it's supposed to represent leftward movement.
  • right
    - triggered by Behaviors, and it's supposed to represent rightward movement.
  • up
    - triggered by Behaviors, and it's supposed to represent upward movement.
  • down
    - triggered by Behaviors, and it's supposed to represent downward movement.
  • face-right
    - whenever
    was the most-recently active directional event. Objects face right by default.
  • face-left
    - whenever
    was the most-recently active directional event.
  • face-up
    - whenever
    was the most-recently active directional event.
  • face-down
    - whenever
    was the most-recently active directional event.
  • static
    - whenever the object is in static/sleep mode.
  • nonstatic
    - whenever the object is not in static/sleep mode.
  • destroyed
    - mainly used to set death animations.
  • door-open
    - A global event, triggered when the player has enough points to open the door.
  • loading
    - A global event, triggered when the level is loading (which might not be relevant anymore), or when buffering streaming sound/video.
  • preview
    - A global event, when the player is on the Jump-To-Start screen.
  • ending
    - A global event, when the player is on the win screen.
It's worth pointing out that "falling" is the default state of every object, which is why there was no trigger made for it. Although, I should probably consider making one anyway, even if it's just a fake trigger, for the sake of usability...

Using an event is similar to using pseudo-classes in CSS:
x:right { ... }
. And here's how you can create a trigger that relies on multiple events at once:
x:crawling:right:standing-on-down { ... }
. The order in which you specify events doesn't make any difference.


You specify properties using the following syntax:
property-name: property-value;
. The semicolon at the end of each property is important since it separates each property definition.

The following is a list of all of the properties that you can set in the current demo.

Hitbox Properties
  • hitbox-width: [Number];
  • hitbox-height: [Number];
  • hitbox-size: [Width] [Height];

  • hitbox-offset-x: [Number];
  • hitbox-offset-y: [Number];
  • hitbox-offset: [OffsetX] [OffsetY];

  • show-hitbox: [true/false];
  • hitbox-color: [hexColorValue];
The hitbox represents the part of your object that triggers collisions. By default, all tiles are placed on the top-left corner of their grid location. Hitbox-offset provides a way to provide a more fine-tuned location for your hitbox. For example, you might want to make a floor spike, and so you might set hitbox-offset-y to something like 20.

When you're fine-tuning the hitbox for an object, you can set show-hitbox to true in order to see what your hitbox looks like. By default, all hitboxes are black, but you can change the color using hitbox-color. Colors must be written in hexadecimal format. Unfortunately, hitboxes are drawn behind any frames that you might have added to the object, which kind of defeats the purpose of this feature. Another way to test a hitbox is to make the object solid (below) and watch how it collides with other solid objects.

Collision Properties
  • allow-collisions: [true/false];

  • coll-edge-top-solidity: [edgeType];
  • coll-edge-bottom-solidity: [edgeType];
  • coll-edge-right-solidity: [edgeType];
  • coll-edge-left-solidity: [edgeType];
  • coll-edge-solidity: [edgeType];
  • coll-edge-solidity: [edgeType-top] [edgeType-right] [edgeType-bottom] [edgeType-left];
  • coll-edge-solidity: [edgeType-top-down] [edgeType-right-left];

  • Valid edgeTypes:
    • no-wall
      - Allows all tiles to pass through the object's borders.
    • solid-wall
      - Blocks all solid objects from passing through the object's borders.
    • pseudo-wall
      - Just like solid-wall, but it doesn't interrupt arrows or dynamite.
    • solid-ladder
      - Just like solid-wall, but it lets ladder-users through (See
      , below).
    • pseudo-ladder
      - Just like solid-ladder, but it doesn't interrupt arrows or dynamite.
Allow-collisions determines whether or not the game should go through the trouble of testing that tile for collisions. The coll-edge properties refer to "collision edge", which is kind of like a "collision border" around a tile. the coll-edge properties allow you set individual settings to each of these walls.
  • coll-edge-top-buffer: [Number];
  • coll-edge-bottom-buffer: [Number];
  • coll-edge-right-buffer: [Number];
  • coll-edge-left-buffer: [Number];
  • coll-edge-buffer: [Number];
  • coll-edge-buffer: [Number-top] [Number-right] [Number-bottom] [Number-left];
  • coll-edge-buffer: [Number-top-bottom] [Number-right-left];
Buffers essentially make special holes in solid collision edges, and their purpose is make the collision system a little less strict by not counting close-calls as actual collisions. For instance, if you set the left and right buffers of a tile to 5, then all vertical collisions where there is only an intersection width of 5 pixels or less is not considered a vertical collision. The tile is then nudged a little bit to the left or right as it passes the tile. Because of the way buffers work, setting extreme values can lead to many glitches.
  • coll-edge-top-recoil: [Number];
  • coll-edge-bottom-recoil: [Number];
  • coll-edge-right-recoil: [Number];
  • coll-edge-left-recoil: [Number];
  • coll-edge-recoil: [Number];
  • coll-edge-recoil: [Number-top] [Number-right] [Number-bottom] [Number-left];
  • coll-edge-recoil: [Number-top-bottom] [Number-right-left];
Recoils are a legacy feature, brought in from the past demos because they might lead to interesting tricks and glitches. Like buffers, recoils only apply to solid collisions. When two solid tiles collide, they are set to have a distance of zero from each other. Recoil changes that distance to something else, essentially creating a teleportation effect that is just filled with glitches, but that's what makes it fun.
  • coll-edge-top-bounce: [Number];
  • coll-edge-bottom-bounce: [Number];
  • coll-edge-right-bounce: [Number];
  • coll-edge-left-bounce: [Number];
  • coll-edge-bounce: [Number];
  • coll-edge-bounce: [Number-top] [Number-right] [Number-bottom] [Number-left];
  • coll-edge-bounce: [Number-top-bottom] [Number-right-left];
Bounce does what recoil failed to do, which is to provide a slight bounce effect when two tiles collide. Bounce alters the horizontal or vertical speed (depending on which side was hit) of the other object to the specified value.
  • coll-effect-ladder: [true/false];
  • coll-effect-water: [true/false];
  • can-use-ladder: [true/false];
When you collide with an object that has coll-effect-water set to true, your
event is triggered. It works the same for ladder, regardless of whether or not you have can-use-ladder set to true. The can-use-ladder property is used only as a way to grant yourself permission to pass through

State Properties: Static and Nonstatic

When an object is in static state, the game will not go out of its way to update its position, even if it is set to be affected by gravity. Not only does this make the game more efficient, but it's also how steel crates start a level by floating until something knocks them down. There are a couple of settings that give you more control of which state an object is in:
  • init-state: [static/nonstatic];
  • set-state: [static/nonstatic];
  • allow-state-change: [true/false];
The init-state property only applies during initialization.

When a solid, nonstatic object collides with a solid static object, the nonstatic one also becomes static. You can turn this off by setting allow-state-change to false. The set-state property allows you to change the state of an object in response to an event. For example, you could make it so that when the door is opened, a bunch of objects start to fall down. Or perhaps they fall when someone stands on them (standing-on-up).

Unfortunately, the game doesn't do a very good job of supporting nonstatic objects yet. I don't think it even tries to resolve solid collisions between two nonstatic objects. Also, I have a lot of optimization work to do because the game starts to slow down significantly whenever there are more than a few nonstatic objects in the level.

Movement Properties
  • accelerate-x: [Number];
  • accelerate-y: [Number];
  • accelerate: [NumberX] [NumberY];

  • friction-up: [Number];
  • friction-down: [Number];
  • friction-left: [Number];
  • friction-right: [Number];
  • friction-y: [Number-up] [Number-down];
  • friction-x: [Number-left] [Number-right];
  • friction: [Number];
  • friction: [Number-up] [Number-right] [Number-down] [Number-left];
  • friction: [Number-up-down] [Number-left-right];
Friction is applied whenever the object is not accelerating along the relevant axis, and different degrees of friction can be applied depending on direction of travel. The last option for setting friction can be particularly confusing, because one might expect the first number to represent the X axis while the second represent the Y, but it's actually the reverse. This is mainly an issue of whether or not I should stick to CSS conventions when defining these kinds of shorthands. But I guess if you don't like them, you're always free to use the individual settings for friction-x and friction-y.
  • max-speed-up: [Number];
  • max-speed-down: [Number];
  • max-speed-left: [Number];
  • max-speed-right: [Number];
  • max-speed-y: [Number-up] [Number-down];
  • max-speed-x: [Number-left] [Number-right];
  • max-speed: [Number];
  • max-speed: [Number-up] [Number-right] [Number-down] [Number-left];
  • max-speed: [Number-up-down] [Number-left-right];

  • set-speed-x: [Number];
  • set-speed-y: [Number];
  • set-speed: [NumberX] [NumberY];
The set-speed properties allow you to change the speed of an object in response to an event, such as jumping.

Player-Specific Properties
  • init-as-player: [true/false];
  • allow-enter-crawl: [true/false];
  • allow-be-in-crawl: [true/false];

  • allow-jump: [true/false];
  • mid-air-jump-limit: [Number];
The init-as-player thing is just a crude option to get the camera to focus on the player. It's a placeholder feature until I find a more elegant way to do it, which will probably involve the behavior system. The fact that this property starts with "init-" implies that it's a property that is only applied during initialization.

Allow-enter-crawl strictly determines whether or not the player is allowed to start crawling, while allow-be-in-crawl determines whether or not to cancel crawling states brought in from different scenarios. For example, you could turn off crawl-jumping entirely by setting both of these to true.

Mid-air-jump-limit allows you to set a maximum number of mid-air jumps. For example, set it to 1 and you allow the player to double jump. Set it to 3 and you give them 3 extra jumps. Set it to -1 (the default value) for infinite jumps.

Animation Properties
  • animate: [frameID];
  • z-index: [front/back];
This is fairly self-explanatory. The frameID refers to the frames defined under the tag, as discussed in Part 1.

The z-index refers to the stacking order of the entire object compared to all of the other objects. This is a work-in-progress feature, which will eventually offer a more sophisticated means of organizing the stacking order.


When you start messing with the styles system, you'll eventually run into problems of precedence, where you want one style definition to override the effects of another. The system has a very simple approach to determining precedence:
  1. Highest precedence is given to style definitions that use more of the following events:
    , and all of the global events, including
    , and
  2. The next highest precedence is given to the style definition that uses more events in general.
  3. A style definition does not get more precedence based on the number of extra triggers that you attach to it. For example
    x, y, z { ... }
    carries no extra precedence over
    x { ... }
If you plan to use the inheritance features, you must also understand the order of precedence within the different scopes of inheritance:
  1. Styles set by classes override everything.
  2. Below that are the styles set on the original object type itself.
  3. Lowest precedence is given to all ancestors of the object. The higher up you go in the inheritance chain, the less precedence you have.

Tips and Tricks

The styles system really requires a new way of thinking in order to find out all of the things you can do with it. What I find most crazy about this is that every single option can be set to change on an event, or combination of events. For instance, the reason I included those weird, morphing steel crates on the top of the default level was because it shows how even something as important as the hitbox of an object can be customized to change on a simple event. By mixing and matching all of these features, you can create some really interesting mechanics, especially once the other features are added.

One thing that you have to understand about how styles are applied is that if you have an event that alters a certain value, that value does not revert back to its original form when the event expires. For instance, if you never set the hitbox-size for an object (leaving it at its default 32x32) but you change the size based on an event, when the event turns off, the hitbox will not revert back to 32x32. Explicitly stating the hitbox-size for the default style definition (default, meaning it has no events) will resolve this issue.
[?] Karma: 0
User Comments

There are no comments yet, so feel free to be the first to comment.

« Forum Index < The Aeon Development Board

In order to post in the forums, you must be logged into your account.
Click here to login.

© 2020 The Interguild | About & Links | Contact: [email protected]
All games copyrighted to their respective owners.