# GMLscripts.com

Discuss and collaborate on GML scripts

You are not logged in.

## #1 Re: GML Creations » CHALLENGE: Conway's Game of Life » 2011-05-03 05:09:12

Today I received my c++ assignment for this semester, would you believe it's "Conway's Game of Life"? lol

## #2 Re: GML Creations » CHALLENGE: Conway's Game of Life » 2011-04-29 05:12:54

Wow! I think I would have got somewhere near there eventually but it's a lot more work than I expected (and I quickly gave up because I'm lazy ). I would have done a few parts differently.

1) Creating the neighbour surface: you're current solution uses 1 clear and 8 draws, my proposed solution uses 2 clears and 6 draws (which is faster in my mind...). It works by summing the surfaces horizontally first than summing the result vertically. Note that the sum will now contain the centre cell also, but that's not an issue if you account for it when picking your upper and lower bounds for living cells.

Expand// xot's code
surface_set_target(sum);
draw_clear_alpha(c_black,1);
draw_set_blend_mode_ext(bm_one,bm_one);
draw_surface_ext(surf,-1,-1, 1,1,0,$010101,1); draw_surface_ext(surf, 0,-1, 1,1,0,$010101,1);
draw_surface_ext(surf, 1,-1, 1,1,0,$010101,1); draw_surface_ext(surf,-1, 0, 1,1,0,$010101,1);
draw_surface_ext(surf, 1, 0, 1,1,0,$010101,1); draw_surface_ext(surf,-1, 1, 1,1,0,$010101,1);
draw_surface_ext(surf, 0, 1, 1,1,0,$010101,1); draw_surface_ext(surf, 1, 1, 1,1,0,$010101,1);

// Suggested optimisation, maybe...
surface_set_target(sum_horizontal);
draw_clear_alpha(c_black,1);
draw_set_blend_mode_ext(bm_one,bm_one);
draw_surface_ext(surf,-1,0,1,1,0,$010101,1); draw_surface_ext(surf, 0,0,1,1,0,$010101,1);
draw_surface_ext(surf, 1,0,1,1,0,\$010101,1);
surface_set_target(sum);
draw_clear_alpha(c_black,1);
draw_surface(sum_horizontal,0,-1);
draw_surface(sum_horizontal,0, 0);
draw_surface(sum_horizontal,0, 1);

2) Filtering: Using the "removeback" feature of "background_create_from_surface" may be faster than your feedback method, I'm unsure whether the resource allocation will cost more or less than the drawing saved. I'm thinking something like:

• use background_create_from_surface making all white into transparent

• draw the background to a white surface with draw_background_ext(back, 0, 0, 1, 1, 0, c_black, 1)

• now everything which wasn't white is black. I think (?)

3) I'm a little confused, dare I ask...

Expand// Why this...
draw_primitive_begin(pr_trianglefan);
draw_vertex_color(0,0,lo,0);
draw_vertex_color(w,0,lo,0);
draw_vertex_color(w,h,lo,0);
draw_vertex_color(0,h,lo,0);
draw_primitive_end();

draw_set_color(lo);
draw_set_alpha(0);
draw_rectangle(0, 0, w, h, false);

Seems like 3 extra function calls to me, and surely it's not faster (?), or more obvious as to what it's doing (?), or does something different (?).

## #3 Re: GML Creations » CHALLENGE: Conway's Game of Life » 2011-04-28 19:09:17

I had a feeling that was going to happen! Great work guys! At least I think I provided a good baseline so you can compare how much faster it is to a well optimised loop based approach. Maybe I'll try my hand at making a surface/blend one before I go looking through your code and spoil it, I think I have a rough idea of how to approach it... Maybe...

## #4 Re: GML Creations » CHALLENGE: Conway's Game of Life » 2011-04-26 07:07:45

haha danny, your engine is just like mine, but hell'o faster! the difference is minimal

Funny isn't it! Focusing on reducing the amount of work needed to be done in the parts of code that are run the most can make a huge difference!

I haven't used GM for quite a while, but I just remembered another quirk to abuse. The repeat loop is noticeably faster than a for loop when the length of the loop is known at the start (as the condition is checked in compiled code). +9%fps get!

EDIT: Terribly sorry about the spam with all my different versions, but I'm excited!

I noticed that as I was caching the number of living neighbours a cell had, I no longer needed two copies of the state of the grid, therefore I no longer needed to clone the grid, therefore I could use an array instead of a grid and therefore I gained another 20%fps boost!

## #5 Re: GML Creations » CHALLENGE: Conway's Game of Life » 2011-04-26 04:24:38

I was disappointed that I gained only a tiny 1% increase by reusing my temporary grid rather than creating and destroying each frame. On the other hand I was thrilled that keeping a cache of the number of alive neighbours each cell has gave me a whopping 20% boost!

~260fps on my machine.

I think that's about as good as I can get by looping though every cell. I guess the next thing to try is to keep a set of cells which need to checked and only looping through those... I'd be surprised if I get that working any better, but I've been surprised before!

EDIT: Just for the fun of it, I made my engine run the 400x400 example. Not surprisingly it ran at around 2-3fps (1/100th the speed of the 40x40 example). Here it is, please excuse the half a minute of blank window as it reads in the image pixel by pixel

## #6 Re: GML Creations » CHALLENGE: Conway's Game of Life » 2011-04-25 02:23:30

Naive solutions for a 40x40 grid run around 1 FPS on my machine.

Just so I have a rough idea of where I'm at, how fast does this simple solution run on your machine?
https://docs.google.com/leaf?id=0Byhdbm … y=CNrEwNsE (EDIT: Look down.)
For anyone interested this is the algorithm, it seems to be the most obvious way to do it. I have a few ideas but I'm unsure as to how much they will improve it, I'll get back to you when (if) I've tried them.

Expand/// Apply Rules of Life
{
var next, sum, i, j;
next = ds_grid_create(40, 40);
ds_grid_copy(next, grid);

surface_set_target(surface);
draw_primitive_begin(pr_pointlist);

for (j = 0; j < 40; j +=1) {
for (i = 0; i < 40; i += 1) {
sum = ds_grid_get_sum(grid, i - 1, j - 1, i + 1, j + 1);
if (ds_grid_get(grid, i, j)) {
// Currently alive
if (sum < 3 or sum > 4) {
ds_grid_set(next, i, j, 0);
draw_vertex_color(i, j, 0, 1);
}
} else {
if (sum == 3) {
ds_grid_set(next, i, j, 1);
draw_vertex_color(i, j, 16777215, 1);
}
}
}
}

draw_primitive_end();
surface_reset_target();

ds_grid_destroy(grid);
grid = next;
}

EDIT: Don't look if you don't want to know xot's method.

Spoiler

Oh oh oh, I could blend in an answer.... But I wont. I just think an answer is surfacing in my head.

lol, very subtle. I did consider that approach but I'm rather terrible with blend modes. It does make sense to move the work to the GPU though as it's a very parallel algorithm.

EDIT2: I noticed that I had forgotten to make i and j script local variables, fixing this gives a 4% fps boost on my machine... Why can't that be the default!

## #7 Re: GML Creations » CHALLENGE: Lossless Data Compression / Decompression » 2010-10-19 07:13:07

Oops! Sorry! I caught the Minecraft bug... So addicting, so much time wasted, so many diamonds to be found!

## #8 Re: GML Creations » CHALLENGE: Lossless Data Compression / Decompression » 2010-09-23 20:17:01

I've got an extremely fast and effective solution (very comparable to ZIP *big hint!*), but decoding 64KB of data is currently taking too long for my tastes (about 11 seconds). It also won't work in GM7 (*bigger hint!*), so this may have to be an exhibition-only entry. It also has some semi-unavoidable overhead making it unsuited for files smaller than a hundred bytes (*biggest hint!*), although that can be worked around at the expense of speed.

That sounds an awful lot like my first (somewhat cheesy) idea... does you're solution use surface_save by any chance?

Because I thought that would be too easy, I think I'm going to have a shot at implementing Huffman coding in GML. I doubt my implementation will come close to the efficiency of DEFLATE (the compression used in PNG and gzip).

## #9 Re: GML Creations » CHALLENGE: Lossless Data Compression / Decompression » 2010-09-21 21:56:46

I'll give it a shot!

## #10 Re: GML Creations » CHALLENGE: Avoidance AI » 2010-09-18 07:48:56

Wow, that's really awesome jalb! Go jumpy blue ball!

EDIT: In the latest version it seems that the results are backward for places 2-5. In the final round it was yellow (jalb) vs blue (Dannyboy) but the results came out as:

Results wrote:

Dannyboy is the winner!
2: icuurd12b42
3: OpticalLiam
4: xot
5: jalb

## #11 Re: GML Creations » CHALLENGE: Avoidance AI » 2010-09-15 19:44:58

That's a really creative solution xot! Showing the surface really helps to visualise what's going on. One thing I did notice which I thought was a little odd was that it seems that you're treating the area behind the enemies as dangerous as the area in front, wouldn't it be better to have a less symmetrical mask for the enemies?

## #12 Re: GML Creations » CHALLENGE: Avoidance AI » 2010-09-15 02:59:54

Here's mine. It's GM8, should run on lite no problems.

And here's a version of it with some tacked on overlay stuff I used for debugging, just in case you're interested.

The grid method makes hills in a grid... or waves. the ai just flows down the hill

That's sounds really close to one of my ideas... I just couldn't be bothered trying to make it work, I'm glad someone did!

Don't miss out on the deadline xot!

## #13 Re: GML Creations » CHALLENGE: Avoidance AI » 2010-09-11 05:52:01

After fixing a stupid mistake with the evasion code, the direction was wrong, I don't know how it was working... And a bit more tweaking I've managed to get it down to about 0.4-0.8 collisions per minute, averaged over a full hour, I ramped the room speed up a little . I think that's about as good as I'm going to get from this method. I'm going to have to think up a new method to get any better.

Some things I've noticed so far:
1) Your method is much smoother than mine. Yours manages to move towards the quiet spots somehow. Mine is much more jerky, jumping out of the way at the last moment. I'm curious as to how you managed it.
2) Tweaking is annoying difficult. The values I get could be different by double or half when tested over times as long as 10 minutes. I wonder if there's a better, more stable, method to assess the performance than just collisions / time.

## #14 Re: GML Creations » CHALLENGE: Avoidance AI » 2010-09-10 21:06:00

Alright, I've now made a more accurate threat-o-meter to detect which enemy is the greatest threat, also I've made the evasive action to move away from the point of closest approach rather directly away from the enemy. With these improvements I ran the test for 3 minutes, 6 collisions for the first minute, 3 for the second and 4 for the third... I've got a long way to go yet!

Now that I have a decent method of detecting and avoiding threats I think I might try a weighted average rather than just focusing on a single threat, I'll let you know how it goes.

EDIT: Weighted average results so far: 7 collisions in 5 minutes. I'm catching up!

## #15 Re: GML Creations » CHALLENGE: Avoidance AI » 2010-09-10 08:51:09

Ooh, I think I'll give this a shot. I whipped up something really quick but I'll improve it before I post. The basic idea of my strategy is to:

Spoiler

Identify the most immediate threat (currently using instance nearest) and avoid it (currently using motion_add in the opposite direction). Also it tries to go towards the centre whenever it can. Simple.

It's better than sitting still but definitely needs improving before it could compete with yours!

EDIT: What sort of useless spoiler tag is that???

## #16 Re: Off Topic » Video Game Related Media » 2010-06-11 05:05:53

I saw this today and thought some of you might also find it interesting: http://chrishecker.com/Please_Finish_Your_Game

## #17 Re: GML Creations » UV Hijinks - Smoke and Mirrors » 2009-11-07 00:38:22

Wow! Some truly marvellous effects! There's much to be learnt from this, I'll study it some more after exams Thanks for sharing

## #18 Re: GML Reference » for statement - compound expressions » 2009-10-04 06:43:00

Hmm, that script looks somehow familiar

## #19 Script Submission » draw_polygon_inverted » 2009-10-04 02:59:22

~Dannyboy~
Replies: 3

Based on my recent topic at the GMC, I put together this script. As it is based on both "draw_rectangle_inverted" and "polygon_area" I borrowed the comments from them, I hope that's OK.

Expand/*
**  Usage:
**      draw_polygon_inverted(polygon)
**
**  Arguments:
**      polygon    ds_list containing XY coordinate pairs defining
**                 the shape of a polygon {x0,y0,x1,y1,...,xn,yn}
**
**  Returns:
**      nothing, inverts the given polygonal area of the screen
**
**  Notes:
**      Polygons are closed figures, the first point in the polygon
**      will also be considered the last point in the polygon.
**      Polygons must be simple, which means they can not have
**      edges that cross each other.
**
**      Resets blending mode to normal.
**
**  GMLscripts.com
*/
{
var polygon, i, j, x1, y1;
polygon = argument0;
j = ds_list_size(polygon);
draw_set_blend_mode_ext(bm_inv_dest_color, bm_inv_src_color);
draw_primitive_begin(pr_trianglefan);
for (i = 0; i < j; i += 2)
{
x1 = ds_list_find_value(polygon, i);
y1 = ds_list_find_value(polygon, i + 1)
draw_vertex_color(x1, y1, c_white, 1);
}
draw_primitive_end();
draw_set_blend_mode(bm_normal);
}

## #20 Script Alumni » polygon_area and polygon_centroid » 2009-10-04 02:29:33

~Dannyboy~
Replies: 1

I don't think you (xot) got enough sleep before writing these ones They (polygon_area and polygon_centroid) both suffer the same three issues.

Expand{
var a,i,j,x1,y1,x2,y2;
a = 0;
j = ds_list_size(polygon);
for (i=0; i<j div 2; i+=1) {
x1 = ds_list_find_value(polygon,(2*i)   mod j);
y1 = ds_list_find_value(polygon,(2*i+1) mod j);
x2 = ds_list_find_value(polygon,(2*i+2) mod j);
y2 = ds_list_find_value(polygon,(2*i+3) mod j);
a += x1*y2 - x2*y1;
}
return a / 2;
}

The first thing I'd like to point out is that "polygon" is never defined, thus the script will just throw an error. Secondly multiplying i by 2 four times (and dividing j once) every cycle just seems like a waste to me, you should really increase it by 2 instead. Finally "i" and "i + 1" should never be greater than j and therefore "modding" them is unnecessary (although nice for symmetry). I have not actually tested these scripts but assuming the originals worked (which assumes you had a local variable named polygon), these should work better

Expand// polygon_area
{
var polygon, a, i, j, x1, y1, x2, y2;
polygon = argument0;
a = 0;
j = ds_list_size(polygon);
for (i=0; i<j; i+=2) {
x1 = ds_list_find_value(polygon,i);
y1 = ds_list_find_value(polygon,i+1);
x2 = ds_list_find_value(polygon,(i+2) mod j);
y2 = ds_list_find_value(polygon,(i+3) mod j);
a += x1*y2 - x2*y1;
}
return a / 2;
}
Expand// polygon_centroid
{
var polygon,ai,atmp,xtmp,ytmp,i,j,x1,y1,x2,y2;
polygon = argument0;
atmp = 0;
xtmp = 0;
ytmp = 0;
global.xCentroid = 0;
global.yCentroid = 0;
j = ds_list_size(polygon);
for (i=0; i<j; i+=2) {
x1 = ds_list_find_value(polygon,i);
y1 = ds_list_find_value(polygon,i+1);
x2 = ds_list_find_value(polygon,(i+2) mod j);
y2 = ds_list_find_value(polygon,(i+3) mod j);
ai = x1*y2 - x2*y1;
atmp += ai;
xtmp += (x2 + x1) * ai;
ytmp += (y2 + y1) * ai;
}
if (atmp != 0) {
global.xCentroid = xtmp / (3 * atmp);
global.yCentroid = ytmp / (3 * atmp);
}
return atmp / 2;
}