# Articles
This builds on the excellent guide by Mawral. (opens new window) Thank you Mawral ❤️
Sometimes you want an instance other than your character.
You grow a tree, have an owlfriend, drop bear traps, or throw a bouncy saw blade.
Sometimes you can handle articles as simple projectiles. Other times it's okay to make them part of your character, tracking their location in a variable and using a draw script.
If you have something with more complex behavior, it's probably easier to use an article.
Articles are mostly empty instances, that can be flexibly repurposed into almost anything. Modders have even made
ice-climbers style pseudo-characters with articles, though that's easier now with Player-Articles.
Being blank slates means that it can take a lot of code to define their behavior.
# Types of articles
There are five article objects:
obj_article1
obj_article2
obj_article3
obj_article_solid
obj_article_platform
obj_article1
through 3 are 'basic' articles with no special properties. You can do anything with these.
obj_article_solid
acts as a solid block (like Kragg's rock and pillar)obj_article_platform
acts as a platform (like Shovel Knight's mobile gear). Be aware that these two can have issues interacting with players when you set their hsp or vsp to decimal values.
# Creating an Instance of an Article
You create instances of articles with instance_create("obj_article1"), (opens new window) or whichever article type. Note that this is the only time when you need to put the article object name in quotes.
//attack_update.gml
if attack == AT_DSPECIAL {
if window == 2 && window_timer == 1 && hitpause == false { // 'hitpause == false' prevents it from running multiple times if frozen in hitpause
bomb = instance_create(x, y, "obj_article1") // Optionally save a reference to the instance in a variable.
}
}
# Scripting Articles
Each article type has its own scripts detailed here.
# Article Variables
Articles have the following built-in variables:
Usually constant:
player_id
- The character instance that owns the article.can_be_grounded
- Determines if the article follows platforms when free == false.false
by default.ignores_walls
- Determines if the article moves through solid objects rather than colliding.true
by default.hit_wall
- Is true if the article hit a wall due to its own movement.uses_shader
- Whether the player's shader recolors the article.
Changing:
hsp
- The horizontal speed of the article.vsp
- The vertical speed of the article.free
- Whether the article is in the air or not.spr_dir
- The direction the article is facing:1
is right,-1
is lefthitstop
- The frames remaining in hitpause. Hitpause automatically prevents movement.
# Referencing Articles
instance_create()
(opens new window) returns the id of the newly-created article, which
you can save in a variable to access later.
instance_exists(instance_id)
(opens new window)
returns true
if the instance exists. You can use this to check if your player article variable has an article assigned
to it or not.
// init.gml
my_player_article = noone;
// attack_update.gml
// if an article doesn't exist yet, let the player create an article with dspecial.
if !instance_exists(my_player_article) {
if attack == AT_DSPECIAL {
my_player_article = instance_create("obj_article1")
}
} else { // if an article exists, make the article move upwards with uspecial.
if attack == AT_USPECIAL {
my_player_article.vsp = -5
}
}
# Referencing all of a Character's Articles
Sometimes you may want to run code in every instance of an article created by a player, no matter how many they have. To
do this, you should use a with
statement, combined with a check for the article's player_id
.
Using the with
statement by itself will loop through ALL article instances, including articles that belong to other
players! Always match the article's player_id
variable with the player's id variable to make sure your character only
affects their own articles.
//attack_update.gml
//taunt to make all of the player's article1s move downwards.
if attack == AT_TAUNT {
with (obj_article1) {
if (player_id == other.id) { // If the article belongs to you
vsp = 5;
}
}
# Destroying Articles
# Safely
Destroying articles without organization can make lead to bugs and strange behaviors.
To make sure the article doesn't disappear in the middle of doing something, it's good to let the article handle its own destruction.
// article<name>_init.gml
lifetime = 0;
should_die = false
// article<name>_update.gml
lifetime++
if lifetime >= 200 {
should_die = true
}
// or any file you want to destroy the article from
my_article.should_die = true
// the bottom of article<name>_update.gml
if should_die {
instance_destroy() // Destroys the current instance.
exit // optional. Makes the script stop at this point. Useful if you can't put this at the very bottom.
}
When using an article that might have been destroyed,
use instance_exists(instance_id)
(opens new window)
to check.
# Manually
You can destroy articles directly using instance_destroy(article_id)
(opens new window)
or instance_destroy()
if you're in the article's perspective.
// update.gml
// destroy the referenced article when the player presses 'shield'.
if instance_exists(my_player_article) && shield_pressed {
instance_destroy(my_player_article)
}
You can also use the with
statement to destroy all articles at once.
Remember to match player ids so that you don't destroy other characters' articles.
// update.gml
// destroy all your article1s when the player presses 'shield'.
if shield_pressed {
with obj_article1 {
if player_id == other {
instance_destroy();
}
}
}
# Article Behavior
# Collisions
You must handle article collisions manually. This can be the most difficult part of setting up a working article. There are several different ways to handle article collisions, and so this guide will outline the most common options.
# place_meeting Collisions
Use the place_meeting() (opens new window) function. This is the simplest way to check for a collision in an article script. This function can cause a lot of slowdown if it's used too frequently.
Objects you may want to check for include:
pHurtBox
(hurtboxes) For when you need precise collision detection.oPlayer
(players) When you need to check for players' platforming boxes instead of their hurtbox, or when you don't need precise collisions detection. You should also check their 'clone' variable to see if they are a Forsburn clone or not.)pHitBox
(hitboxes)asset_get(par_block)
(walls and floors)asset_get(par_jumpthrough)
(platforms)
# Manual Collisions
Make a 'manual' collision detection by comparing x
, y
and char_height
values, or
using point_distance()
(opens new window)
. This method is fast, and recommended for making articles that act like 'fields', e.g. Wrastor's slipstream.
# Hitbox Collisions
Create a projectile with create_hitbox()
(opens new window), save the instance id, and move
the projectile's coordinates to overlap the article in article[name]_update.gml
.
This is the most complex method, but also the most accurate, and faster than place_meeting()
.
You should use this for articles that act when opponent's touch them, or may need to be 'parried' by
opponents.
If the projectile disappears, you can assume something happened that would destroy the article.
You can use your character's hit_player.gml
script to check when the article collides with a player's hurtbox.
Under Construction
Common article features (hopefully powered by the standard library)
Player articles
Code examples of each collision detection method