Alright, here we go. You only need one object and one room, though the room should be at least be 800 x 800. This is a *lot* more basic than the 64D example but you can apply the same techniques to get a suitable solution.

__Create event__

globalvar deltatime; //Deltatime functionality is game-wide, might as well be a globalvar
deltatime = 1;
x = room_width/2;
y = room_height/3; //Centre point of the planet "model"
res = 2; //Angular resolution of the longitude (x) coordinates, in degrees. This should probably be a number that divides 180 into a whole number
radius = 250; //Radius of the planet model
disk_size = 20; //Circle size used during generation
rotation_speed = 2; //Degrees per turn to spin
var rad_res = degtorad( res ); //Multiplier that turns tile index into radians, makes things a bit quicker
long_res = ceil( 360 / res ); //Number of tiles around the waist of the planet, all the way round
lat_res = ceil( 180 / res ); //Number of tiles from top to bottom, only halfway round though (planet model is basically a squeezed cyclinder)
scale = radius * sin( rad_res ) / 2; //Drawing scale of the tiles on the planet
rotation = 0; //Rotation of the planet model, in degrees
auto_rotate = true; //Automatically spin the planet at the start of the game
for( var deg = 0; deg < long_res + 1; deg++ ) {
var real_deg = deg * rad_res;
sin_of_deg[ deg ] = sin( real_deg ); //Generate two trig look up tables
cos_of_deg[ deg ] = cos( real_deg );
}
height_grid = ds_grid_create( long_res, lat_res ); //Our height map
colour_grid = ds_grid_create( long_res, lat_res ); //Our colour map for different "terrain" types
var wrap_grid = ds_grid_create( long_res + disk_size * 2, lat_res ); //Our height map with extra allowance for overspill from the circle-based generator
ds_grid_clear( height_grid, 0 ); //Make sure it's a clean slate
ds_grid_clear( wrap_grid, 0 );
for( var long = 0; long < long_res; long++ ) { //Actual generation. Super simple
for( var lat = 0; lat < lat_res; lat++ ) {
ds_grid_add_disk( wrap_grid, long + disk_size, lat, disk_size, 1 - random( 2 ) ); //Note "+ disk_size" horizontal offset
}
}
for( var long = 0; long < disk_size; long++ ) {
for( var lat = 0; lat < lat_res; lat++ ) {
var val = ds_grid_get( wrap_grid, long, lat );
ds_grid_add( wrap_grid, long_res + long, lat, val ); //Wrap left-most overflow onto the right hand side
var val = ds_grid_get( wrap_grid, long_res + disk_size + long, lat );
ds_grid_add( wrap_grid, disk_size + long, lat, val ); //Wrap right-most overflow onto the left hand side
}
}
for( var long = 0; long < long_res; long++ ) {
for( var lat = 0; lat < lat_res; lat++ ) {
var val = ds_grid_get( wrap_grid, long + disk_size, lat );
ds_grid_set( height_grid, long, lat, val ); //Copy across from one grid to another (yes, I know there's an in-built function to do it)
}
}
var mini = ds_grid_get_min( height_grid, 0, 0, long_res - 1, lat_res - 1 );
ds_grid_add_region( height_grid, 0, 0, long_res - 1, lat_res - 1, -mini );
var maxi = ds_grid_get_max( height_grid, 0, 0, long_res - 1, lat_res - 1 );
ds_grid_multiply_region( height_grid, 0, 0, long_res - 1, lat_res - 1, 1/maxi ); //Normalise the height map
for( var long = 0; long < long_res; long++ ) {
for( var lat = 0; lat < lat_res; lat++ ) {
var val = ds_grid_get( height_grid, long, lat );
val = colour_continuum( val ); //Turn the height value into a colour
ds_grid_set( colour_grid, long, lat, val ); //Generate colour map
}
}
surface_sur = surface_create( long_res, lat_res ); //Create the 2D map
surface_set_target( surface_sur );
draw_clear( c_fuchsia ); //Silly colour to help detect bugs
for( var long = 0; long < long_res; long++ ) {
for( var lat = 0; lat < lat_res; lat++ ) {
draw_set_color( ds_grid_get( colour_grid, long, lat ) );
draw_point( long, lat ); //Draw the colour map with 1x1 pixel resolution to save memory - we'll be scaling this up later
}
}
surface_reset_target();
ds_grid_destroy( height_grid );
ds_grid_destroy( wrap_grid ); //Free up some memory

__Step event__

deltatime = min( 4, room_speed / ( 1000000 / delta_time ) ); //delta_time is measured in microseconds. I'm not sure GM is actually accurate down this far but whatever
if ( auto_rotate ) rotation += rotation_speed * deltatime; //This stuff is all kinda obvious
if ( keyboard_check( vk_left ) ) {
auto_rotate = false;
rotation -= rotation_speed * deltatime;
}
if ( keyboard_check( vk_right ) ) {
auto_rotate = false;
rotation += rotation_speed * deltatime;
}
rotation = ( rotation + 360 ) mod 360; //Make sure we don't get a negative rotation - causes bugs otherwise

__Draw event__

texture_set_interpolation( false );
draw_surface_ext( surface_sur, x - long_res, ( room_height - (y+radius) ) / 2 + (y+radius) - lat_res, 2, 2, 0, c_white, 1); //Draw the 2D map
texture_set_interpolation( true );
d3d_transform_set_identity();
d3d_transform_add_translation( x, y, 0 ); //Neat little hack to offset further draw calls
for( var long = 0; long < long_res; long++ ) {
var real_long = ( long * res + rotation ) mod 360; //Spins the planet round, making sure we're offseting tiles appropriately
if ( real_long > 180 ) { //...though obviously everything behind the planet we want to skip drawing (fancier people would call this "backface culling")
ipart = floor( real_long / res ); //Turn the rotation angle back into a tile coordinate as a estimate for the trig look up table
fpart = frac( real_long / res );
var sin_of_real_long = lerp( sin_of_deg[ ipart ], sin_of_deg[ ipart+1 ], fpart ); //Do an estimate on a trig value by interpolating between two known values
var cos_of_real_long = lerp( cos_of_deg[ ipart ], cos_of_deg[ ipart+1 ], fpart );
var real_x_scale = scale * sin_of_real_long; //This shrinks the x-axis scale to give the illusion of perspective. It's crude
for( var lat = 0; lat < lat_res; lat++ ) {
var colour = ds_grid_get( colour_grid, long, lat ); //Get the colour of the tile
draw_set_color( colour ); //...and set it
var sin_of_real_lat = sin_of_deg[ lat ]; //Look up trig values for this latitude
var cos_of_real_lat = cos_of_deg[ lat ];
var xx = cos_of_real_long * sin_of_real_lat; //Turn the spherical coordinates into (unit length) cartesian coordinates
var yy = -cos_of_real_lat;
var real_y_scale = scale * sin_of_real_lat; //This time, shrink the y-axis scale to give the illusion of perspective
var xxx = xx * radius; //Turn the unit coordinates (radius of length 1) into actual coordinates for display
var yyy = yy * radius;
draw_rectangle( xxx - real_x_scale, yyy - real_y_scale, xxx + real_x_scale, yyy + real_y_scale, false ); //Actually draw the damn tile
}
}
}
d3d_transform_set_identity();
draw_set_color( c_white );
draw_text( 10, 10, string( fps ) );
draw_text( 10, 30, string( long_res ) + " x " + string( lat_res ) );

Script, named colour_continuum

var val = argument0;
var colour = c_fuchsia;
var div_a = 0.5; //start of plains
var div_b = 0.7; //start of forest
var div_c = 0.8; //start of mountains
if ( val < div_a ) {
colour = merge_color( c_blue, c_aqua, val / div_a );
} else if ( val < div_b ) {
colour = merge_color( c_lime, c_green, ( val - div_a ) / ( div_b - div_a ) );
} else if ( val < div_c ) {
colour = merge_color( c_green, c_maroon, ( val - div_b ) / ( div_c - div_b ) );
} else {
colour = merge_color( c_maroon, c_white, ( val - div_c ) / ( 1 - div_c ) );
}
return colour;

Regarding objects versus sprites, be very careful about creating too many objects in your game. I can't remember what size map that program produces but even at 50x50 you're creating 2'500 objects.

**Edited by Juju, 05 June 2015 - 07:40 AM.**