• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM [solved]Helpf for simplify code for angling rocks

G

Go-a-og

Guest
I've got a simple code block for a rock object that changes its shape and angle depending on its nearest neighbor, is there a better way to do this without this horrific looking code? Like so.
Screenshot (2).png
Code:
//four sides
image_speed = 0
if !place_meeting(x-32,y,obj_rock)
 &&!place_meeting(x,y-32,obj_rock)
 &&!place_meeting(x,y+32,obj_rock)
 &&!place_meeting(x+32,y,obj_rock)
{
    image_index = 0
    image_angle =0
}else
//three sides
if !place_meeting(x-32,y,obj_rock)
 &&!place_meeting(x,y-32,obj_rock)
 &&!place_meeting(x,y+32,obj_rock)
{
    image_index = 1
    image_angle = 0
}else
if !place_meeting(x+32,y,obj_rock)
 &&!place_meeting(x,y-32,obj_rock)
 &&!place_meeting(x,y+32,obj_rock)
{
    image_index = 1
    image_angle = 180
}else
if !place_meeting(x-32,y,obj_rock)
 &&!place_meeting(x,y-32,obj_rock)
 &&!place_meeting(x+32,y,obj_rock)
{
    image_index = 1
    image_angle = 270
}else
if !place_meeting(x-32,y,obj_rock)
 &&!place_meeting(x,y+32,obj_rock)
 &&!place_meeting(x+32,y,obj_rock)
{
    image_index = 1
    image_angle = 90
}else
//two sides
if !place_meeting(x-32,y,obj_rock)
 &&!place_meeting(x,y-32,obj_rock)
{
    image_index = 3
    image_angle = 270
}else
if !place_meeting(x+32,y,obj_rock)
 &&!place_meeting(x,y-32,obj_rock)
{
    image_index = 3
    image_angle = 180
}else
if !place_meeting(x-32,y,obj_rock
 )&&!place_meeting(x,y+32,obj_rock)
{
    image_index = 3
 
}else
if !place_meeting(x+32,y,obj_rock)
 &&!place_meeting(x,y+32,obj_rock)
{
    image_index = 3
    image_angle = 90
}else
//one side
if !place_meeting(x+32,y,obj_rock) {image_index = 2 image_angle = 90}else
if !place_meeting(x-32,y,obj_rock) {image_index = 2 image_angle = 270}else
if !place_meeting(x,y-32,obj_rock) {image_index = 2 image_angle = 180}else
if !place_meeting(x,y+32,obj_rock) {image_index = 2 image_angle = 0}else
{image_index = 4}
 
Last edited by a moderator:

Cpaz

Member
Well, first thing I would say is stub out a lot of those constants.
IE: let 32 be tileSize or something like that. And InSolid be obj_rock.

You could also try using a loop each of the different positions kinda like:
Code:
// Probably doesn't work, just as an example
for(var i = 0; i < 3; i++) {
  if (!place_meeting(x + lengthdir_x(tileSize, i*90), y + lengthdir_y(tileSize, i*90), instSolid)) {
    Image_index = 2;
    Image_angle = i*90;
 }
}
 
G

Go-a-og

Guest
Well, first thing I would say is stub out a lot of those constants.
IE: let 32 be tileSize or something like that. And InSolid be obj_rock.

You could also try using a loop each of the different positions kinda like:
Code:
// Probably doesn't work, just as an example
for(var i = 0; i < 3; i++) {
  if (!place_meeting(x + lengthdir_x(tileSize, i*90), y + lengthdir_y(tileSize, i*90), instSolid)) {
    Image_index = 2;
    Image_angle = i*90;
 }
}
Thank you! It's not quite what I'm looking for but its definitely in the right direction, I'll continue to mess around and see what I come up with. (also, I had a little problem with the image index, cause you capitalized the first letter lol)
 

TailBit

Member
Do each check only once:
Code:
var e = !place_meeting(x-32,y,obj_rock);
var n = !place_meeting(x,y-32,obj_rock);
var s = !place_meeting(x,y+32,obj_rock);
var w = !place_meeting(x+32,y,obj_rock);

image_speed = 0;
switch(e+w+n+s){
    case 4:
        image_index = 0; image_angle = 0;
    break;
    case 3:
        image_index = 1;
        image_angle = !e*180 + !s*270 + !n*90;
    break;
    case 2:
        image_index = 3;
        image_angle = n*180 + ((n&w)|(s&e))*90; // I thiiink this should be right
    break;
    case 1:
        image_index = 2;
        image_angle = w*90 + e*270 + s*180;
    break;
    case 0:
        image_index = 4;
    break;
}
EDIT: Oh, if you switch image_index 2 and 3 in the sprite (and also the number of their cases), then you can leave image_index outside the switch like so:
Code:
image_index=!e+!w+!n+!s;
and completely remove case 0, like so:
Code:
var e = !place_meeting(x-32,y,obj_rock);
var n = !place_meeting(x,y-32,obj_rock);
var s = !place_meeting(x,y+32,obj_rock);
var w = !place_meeting(x+32,y,obj_rock);

image_speed = 0;
image_index = !e+!n+!s+!w;

switch(e+w+n+s){
    case 4: image_angle = 0; break; // could even remove this line
    case 3: image_angle = n*180 + ((n&w)|(s&e))*90; break;
    case 2: image_angle = !e*180 + !s*270 + !n*90; break;
    case 1: image_angle = w*90 + e*270 + s*180; break;
}

....

One popular method for doing this automatically with a tileset that include the rotations is to check the 4 for true false on collision and then turn it into a 4 bit number:
Code:
image_index  = (place_meeting(x-32,y,obj_rock)<<3)
             + (place_meeting(x,y-32,obj_rock)<<2)
             + (place_meeting(x,y+32,obj_rock)<<1)
            +  place_meeting(x+32,y,obj_rock);
then you just need to put the correct sprite at the correct position in the tileset .. for example if there was a connection north and east .. and you combined the binary like so:
Code:
image_index = n*8 + s*4 + e*2 + w; // this is what the code above does
then north + east would be (8+2) .. image_index = 10
 
Last edited:

Cpaz

Member
Do each check only once:
Code:
var e = !place_meeting(x-32,y,obj_rock);
var n = !place_meeting(x,y-32,obj_rock);
var s = !place_meeting(x,y+32,obj_rock);
var w = !place_meeting(x+32,y,obj_rock);

image_speed = 0;
switch(e+w+n+s){
    case 4:
        image_index = 0; image_angle = 0;
    break;
    case 3:
        image_index = 1;
        image_angle = !e*180 + !s*270 + !n*90;
    break;
    case 2:
        image_index = 3;
        image_angle = n*180 + ((n&w)|(s&e))*90; // I thiiink this should be right
    break;
    case 1:
        image_index = 2;
        image_angle = w*90 + e*270 + s*180;
    break;
    case 0:
        image_index = 4;
    break;
}
One popular method for doing this automatically with a tileset that include the rotations is to check the 4 for true false on collision and then turn it into a 4 bit number:
Code:
image_index  = (place_meeting(x-32,y,obj_rock)<<3)
             + (place_meeting(x,y-32,obj_rock)<<2)
             + (place_meeting(x,y+32,obj_rock)<<1)
            +  place_meeting(x+32,y,obj_rock);
then you just need to put the correct sprite at the correct position in the tileset .. for example if there was a connection north and east .. and you combined the binary like so:
Code:
image_index = n*8 + s*4 + e*2 + w; // this is what the code above does
then north + east would be (8+2) .. image_index = 10
Yeah no- go with this, this is much cleaner, holy crap.
 
G

Go-a-og

Guest
Do each check only once:
Code:
var e = !place_meeting(x-32,y,obj_rock);
var n = !place_meeting(x,y-32,obj_rock);
var s = !place_meeting(x,y+32,obj_rock);
var w = !place_meeting(x+32,y,obj_rock);

image_speed = 0;
switch(e+w+n+s){
    case 4:
        image_index = 0; image_angle = 0;
    break;
    case 3:
        image_index = 1;
        image_angle = !e*180 + !s*270 + !n*90;
    break;
    case 2:
        image_index = 3;
        image_angle = n*180 + ((n&w)|(s&e))*90; // I thiiink this should be right
    break;
    case 1:
        image_index = 2;
        image_angle = w*90 + e*270 + s*180;
    break;
    case 0:
        image_index = 4;
    break;
}
EDIT: Oh, if you switch image_index 2 and 3 in the sprite (and also the number of their cases), then you can leave image_index outside the switch like so:
Code:
image_index=!e+!w+!n+!s;
and completely remove case 0, like so:
Code:
var e = !place_meeting(x-32,y,obj_rock);
var n = !place_meeting(x,y-32,obj_rock);
var s = !place_meeting(x,y+32,obj_rock);
var w = !place_meeting(x+32,y,obj_rock);

image_speed = 0;
image_index = !e+!n+!s+!w;

switch(e+w+n+s){
    case 4: image_angle = 0; break; // could even remove this line
    case 3: image_angle = n*180 + ((n&w)|(s&e))*90; break;
    case 2: image_angle = !e*180 + !s*270 + !n*90; break;
    case 1: image_angle = w*90 + e*270 + s*180; break;
}

....

One popular method for doing this automatically with a tileset that include the rotations is to check the 4 for true false on collision and then turn it into a 4 bit number:
Code:
image_index  = (place_meeting(x-32,y,obj_rock)<<3)
             + (place_meeting(x,y-32,obj_rock)<<2)
             + (place_meeting(x,y+32,obj_rock)<<1)
            +  place_meeting(x+32,y,obj_rock);
then you just need to put the correct sprite at the correct position in the tileset .. for example if there was a connection north and east .. and you combined the binary like so:
Code:
image_index = n*8 + s*4 + e*2 + w; // this is what the code above does
then north + east would be (8+2) .. image_index = 10
Thanks man! You are an angel stallion! This works awesomely! Other than a special case where both north and south, and west and east needed to be checked, this worked almost perfectly.(albeit with a few minor tweaks)
 

TheouAegis

Member
Do each check only once:
Code:
var e = !place_meeting(x-32,y,obj_rock);
var n = !place_meeting(x,y-32,obj_rock);
var s = !place_meeting(x,y+32,obj_rock);
var w = !place_meeting(x+32,y,obj_rock);

image_speed = 0;
switch(e+w+n+s){
    case 4:
        image_index = 0; image_angle = 0;
    break;
    case 3:
        image_index = 1;
        image_angle = !e*180 + !s*270 + !n*90;
    break;
    case 2:
        image_index = 3;
        image_angle = n*180 + ((n&w)|(s&e))*90; // I thiiink this should be right
    break;
    case 1:
        image_index = 2;
        image_angle = w*90 + e*270 + s*180;
    break;
    case 0:
        image_index = 4;
    break;
}
EDIT: Oh, if you switch image_index 2 and 3 in the sprite (and also the number of their cases), then you can leave image_index outside the switch like so:
Code:
image_index=!e+!w+!n+!s;
and completely remove case 0, like so:
Code:
var e = !place_meeting(x-32,y,obj_rock);
var n = !place_meeting(x,y-32,obj_rock);
var s = !place_meeting(x,y+32,obj_rock);
var w = !place_meeting(x+32,y,obj_rock);

image_speed = 0;
image_index = !e+!n+!s+!w;

switch(e+w+n+s){
    case 4: image_angle = 0; break; // could even remove this line
    case 3: image_angle = n*180 + ((n&w)|(s&e))*90; break;
    case 2: image_angle = !e*180 + !s*270 + !n*90; break;
    case 1: image_angle = w*90 + e*270 + s*180; break;
}

....

One popular method for doing this automatically with a tileset that include the rotations is to check the 4 for true false on collision and then turn it into a 4 bit number:
Code:
image_index  = (place_meeting(x-32,y,obj_rock)<<3)
             + (place_meeting(x,y-32,obj_rock)<<2)
             + (place_meeting(x,y+32,obj_rock)<<1)
            +  place_meeting(x+32,y,obj_rock);
then you just need to put the correct sprite at the correct position in the tileset .. for example if there was a connection north and east .. and you combined the binary like so:
Code:
image_index = n*8 + s*4 + e*2 + w; // this is what the code above does
then north + east would be (8+2) .. image_index = 10
Faster shifting:
image_index = ((n*2+s)*2+e)*2+w;
That's 3 fewer shifts.
 

TheouAegis

Member
Well, at least with Studio they're the same speed because <<1 and <<3 are apparently both O(1). But if you were to code for an older architecture, it'd be a bit faster. lol
 
Top