FrostyCat
Redemption Seeker
with Block Recipe Cards
GM Version: GMS 2.x, GMS 1.x, GM Legacy
Target Platform: All
Download: N/A
Links: N/A
Summary: A quick reference for a range of common use cases for the with block.
Summary
The with block is GML's most powerful means for manipulating instances, but mainstream GML education tends to omit all but its most trivial use cases. This guide aims to document a number of common and useful patterns as a reference.
Definitions:
A property is an expression from the perspective of a called instance. Examples:
A called instance is an instance being targeted by some iteration of a with block.
Looping Patterns
Looping patterns use with blocks to allow the calling instance to apply statements to one or more called instances. This is the form most commonly taught in other resources.
Run statements for all instances (Basic form)
For all other instances except self (Not-me loop)
For the first instance found that satisfies a condition
Note: If there are multiple instances satisfying the condition, which one would be selected is dependent on the program state and the runner's implementation. Avoid assuming any implicit ordering.
Alias an instance as other for a group of statements
Common functions to use as a source of instance IDs for this pattern include instance_place(), instance_position() and collision_*() functions.
For all instances that satisfy a condition (General form, with-if filter)
For all instances that satisfy any of the conditions (Set union / Whitelist)
Tip: Arrange the conditions in order of descending likeliness to be true for optimal performance.
For all instances that don't satisfy a condition (Set subtraction / Blacklist)
For all instances that satisfy all of the conditions (Set Intersection)
Tip: Arrange the conditions in order of descending likeliness to be false for optimal performance.
Polling Patterns
Polling patterns use with blocks to help the calling instance make a decision about a group of called instances, terminating as soon as there is enough information to produce an output. These may be combined with looping patterns.
If all instances satisfy a condition
If at least one instance satisfies a condition
Aggregating Patterns
Aggregating patterns use with blocks to produce an output that describes a group of called instances. These may be combined with looping patterns.
Count the number of instances satisfying a condition
Collect all instances that satisfy a condition
Collect all instances with property sorted in ascending order
Collect all instances with property sorted in descending order
Find the instance with lowest property value
Find the instance with highest property value
Last update (2018-02-13): Changed initial value of highest_val and lowest_val in the highest/lowest property value pattern to discourage a common misinterpretation.
GM Version: GMS 2.x, GMS 1.x, GM Legacy
Target Platform: All
Download: N/A
Links: N/A
Summary: A quick reference for a range of common use cases for the with block.
Summary
The with block is GML's most powerful means for manipulating instances, but mainstream GML education tends to omit all but its most trivial use cases. This guide aims to document a number of common and useful patterns as a reference.
Definitions:
A property is an expression from the perspective of a called instance. Examples:
- x
- sprite_width*sprite_height
- distance_to_object(other)
- visible
- id != other.id
- object_is_ancestor(object_index, other.object_index)
A called instance is an instance being targeted by some iteration of a with block.
Looping Patterns
Looping patterns use with blocks to allow the calling instance to apply statements to one or more called instances. This is the form most commonly taught in other resources.
Run statements for all instances (Basic form)
Code:
with (object_or_instance_or_all) {
/* statements */
}
For all other instances except self (Not-me loop)
Code:
with (object_or_all) {
if (id != other.id) {
/* statements */
}
}
For the first instance found that satisfies a condition
Code:
with (object_or_all) {
if (condition) {
/* statements */
break;
}
}
Alias an instance as other for a group of statements
Code:
with (instance_or_object) {
with (other) {
/* statements */
}
}
For all instances that satisfy a condition (General form, with-if filter)
Code:
with (object_or_all) {
if (condition) {
/* statements */
}
}
For all instances that satisfy any of the conditions (Set union / Whitelist)
Code:
with (object_or_all) {
if (condition1 || condition2 || /* ... || */ conditionn) {
/* statements */
}
}
For all instances that don't satisfy a condition (Set subtraction / Blacklist)
Code:
with (object_or_all) {
if (!condition) {
/* statements */
}
}
For all instances that satisfy all of the conditions (Set Intersection)
Code:
with (object_or_all) {
if (condition1 && condition2 && /* ... && */ conditionn) {
/* statements */
}
}
Polling Patterns
Polling patterns use with blocks to help the calling instance make a decision about a group of called instances, terminating as soon as there is enough information to produce an output. These may be combined with looping patterns.
If all instances satisfy a condition
Code:
var all_ok;
all_ok = true;
with (object_or_all) {
if (!condition) {
all_ok = false;
break;
}
}
if (all_ok) {
/* statements */
}
If at least one instance satisfies a condition
Code:
var some_ok;
some_ok = false;
with (object_or_all) {
if (condition) {
some_ok = true;
break;
}
}
if (some_ok) {
/* statements */
}
Aggregating Patterns
Aggregating patterns use with blocks to produce an output that describes a group of called instances. These may be combined with looping patterns.
Count the number of instances satisfying a condition
Code:
var n_ok;
n_ok = 0;
with (object_or_all) {
if (condition) {
n_ok += 1;
}
}
/* Use n_ok here */
Collect all instances that satisfy a condition
Code:
var i, insts_ok;
i = 0;
with (object_or_all) {
if (condition) {
insts_ok[i] = id;
i += 1;
}
}
/* Use insts_ok here */
Collect all instances with property sorted in ascending order
Code:
var i, lim, pq, insts_sorted;
pq = ds_priority_create();
with (object_or_all) {
ds_priority_add(pq, id, property);
}
lim = ds_priority_size(pq);
for (i = 0; i < lim; i += 1) {
insts_sorted[i] = ds_priority_delete_min(pq);
}
ds_priority_destroy(pq);
/* Use insts_sorted here */
Collect all instances with property sorted in descending order
Code:
var i, lim, pq, insts_sorted;
pq = ds_priority_create();
with (object_or_all) {
ds_priority_add(pq, id, property);
}
lim = ds_priority_size(pq);
for (i = 0; i < lim; i += 1) {
insts_sorted[i] = ds_priority_delete_max(pq);
}
ds_priority_destroy(pq);
/* Use insts_sorted here */
Find the instance with lowest property value
Code:
var val, lowest, lowest_val;
lowest = noone;
lowest_val = -1;
with (object_or_all) {
val = property;
if (lowest == noone || val < lowest_val) {
lowest = id;
lowest_val = val;
}
}
if (lowest != noone) {
/* Use lowest here */
}
Find the instance with highest property value
Code:
var val, highest, highest_val;
highest = noone;
highest_val = -1;
with (object_or_all) {
val = property;
if (highest == noone || val > highest_val) {
highest = id;
highest_val = val;
}
}
if (highest != noone) {
/* Use highest here */
}
Last update (2018-02-13): Changed initial value of highest_val and lowest_val in the highest/lowest property value pattern to discourage a common misinterpretation.
Last edited: