• 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!

Object changes into bigger sprite> gets stuck in wall.

P

Power_Michael

Guest
Hey everyone, I have this simple game where a block changes sprite over time (an alarm) and it turns into a bigger sprite, then over time this sprite changes to a bigger one. I knew this would pose a few problems that I could easily fix, one being that when the sprite changes to a bigger sprite, the object gets stuck in the ground....to fix that I changed the y-axis center of the bigger sprites to be lower so when they would not get stuck in the ground. Now...My new problem is:

When the object is still a little sprite and in a small compact area (a roof above or something)...and then it changes into a big sprite..it is stuck inside of the roof! Or...lets say as a little sprite, the object is as close as it can be to a wall....and then it grows....it ends up being wedged inside of the wall. I am stuck with this issue...I was wondering if anybody knew a way I could make it so if it is too close to a block or something...when the sprite changes it moves it away and then changes? I will post the code I have for making the sprite change over time below:

Create:
Code:
alarm[0] = room_speed * 10;

//I also have a drag and drop ALARM 0 that is set to "1000 steps).
(Nothing in step)


Alarm[0]:

Code:
if (sprite_index == spr_babyBox) {
   sprite_index = spr_smallBox;
   alarm[0] = room_speed * 10;
}
else if (sprite_index == spr_smallBox) {
   sprite_index = spr_mediumBox;
   alarm[0] = room_speed * 10;
}
else if (sprite_index == spr_mediumBox) {
   sprite_index = spr_largeBox;
   alarm[0] = room_speed * 10;
}

So again....What is happening here is over time...the objects sprite changes from little sprite to a bigger sprite...and it continues getting bigger. The problem is when it is too close to a wall and it gets bigger it gets stuck inside of the wall. If you guys know a way I can make it move away from the wall THEN grow...that would be great. If you guys want me to interpret something better or have any questions just let me know below.

Thank you!
-Michael
 
G

GewoonNiels

Guest
Well if your game only has blocks with vertical and horizontal sides ( no diagonal), you could try:
To set up a for loop which checks all the possible directions to move left, up, right and down.

When checking left for example, it would check whether the most upper pixel and the most lower pixel are available, at ... distance left from the object. If so: move there at ... speed, else: check other sides. If there still is no place available increase the distance you are checking from the instance and start from the beginning.

Hopefully it is understandable.
If it is not, tell me
 
W

Wild_West

Guest
Hey everyone, I have this simple game where a block changes sprite over time (an alarm) and it turns into a bigger sprite, then over time this sprite changes to a bigger one. I knew this would pose a few problems that I could easily fix, one being that when the sprite changes to a bigger sprite, the object gets stuck in the ground....to fix that I changed the y-axis center of the bigger sprites to be lower so when they would not get stuck in the ground. Now...My new problem is:

When the object is still a little sprite and in a small compact area (a roof above or something)...and then it changes into a big sprite..it is stuck inside of the roof! Or...lets say as a little sprite, the object is as close as it can be to a wall....and then it grows....it ends up being wedged inside of the wall. I am stuck with this issue...I was wondering if anybody knew a way I could make it so if it is too close to a block or something...when the sprite changes it moves it away and then changes? I will post the code I have for making the sprite change over time below:

Create:
Code:
alarm[0] = room_speed * 10;

//I also have a drag and drop ALARM 0 that is set to "1000 steps).
(Nothing in step)


Alarm[0]:

Code:
if (sprite_index == spr_babyBox) {
   sprite_index = spr_smallBox;
   alarm[0] = room_speed * 10;
}
else if (sprite_index == spr_smallBox) {
   sprite_index = spr_mediumBox;
   alarm[0] = room_speed * 10;
}
else if (sprite_index == spr_mediumBox) {
   sprite_index = spr_largeBox;
   alarm[0] = room_speed * 10;
}

So again....What is happening here is over time...the objects sprite changes from little sprite to a bigger sprite...and it continues getting bigger. The problem is when it is too close to a wall and it gets bigger it gets stuck inside of the wall. If you guys know a way I can make it move away from the wall THEN grow...that would be great. If you guys want me to interpret something better or have any questions just let me know below.

Thank you!
-Michael
You could add a condition for if the block is close to a wall when the alarm goes off, like
if( place_meeting( x+ some high number, y,, wall) )
{
//move away from wall by affecting x position in the opposite direction
}

and then repeat for the left side.
I mean I'm far from an expert, I need at least 20 different trial and errors before I get my enemies working perfect but that's the first thing I'd TRY to do what your saying :p
 

Phil Strahl

Member
Hi Michael!

Personally I would put the alarm code into the step event, simply because that way you know when it happens and can move the sprite away from anything it might get stuck in before continuing. e.g.:

Step event
Code:
if (alarm[0] <= 0)
{
   // your alarm code as switch statement
   switch (sprite_index)
   {
      case spr_babyBox:
      {
      sprite_index = spr_smallBox;
      } break;
      case spr_smallBox:
      {
      sprite_index = spr_mediumBox
      } break;
      case spr_mediumBox
      {
      sprite_index = spr_largeBox;
      } break;
   }
   
   // reset alarm
   alarm[0] = room_speed * 10;   

  // collision check code (see below)
  
}
I don't know what objects your character collides with, so I just use obj_wall here. Basically, it's checking for a collision on either side of the bounding box and moves the instance away from it until there is no collision anymore.

insert this code in the step event code from above, where i put "collision check code" :

Code:
// do this for all collisions we detect:
do
{
  // checks for a collision of the instances bounding box with a wall object instance
  var check = collision_rectangle(bbox_left, bbox_top, bbox_right, bbox_bottom, obj_wall, false, true);

  // houson, we have a collision. let's get the boundin box of the colliding object
  var coll_left  = other.bbox_left;
  var coll_top  = other.bbox_top;
  var coll_right  = other.bbox_right;
  var coll_bottom = other.bbox_bottom;
   
  // new we compare the start of the two bounding boxes.

  // collision happens to the RIGHT of the player:   
  if (bbox_right > coll_left)
  {   
  // find out, how far it's overlapping
  var overlap = coll_left - bbox_right;
   
  // push back player instance that amount + 2 px for good measure
  x = x - overlap - 2;
  }
   
  // now we do the same for the other kinds of collisions:
   
  // collision happens to the LEFT of the player:
  if (bbox_left <= coll_right)
  {
  var overlap = bbox_left - coll_right;
  x = x + overlap + 2;
  }
   
  // collision happens UNDER the player:
  if (bbox_bottom > coll_top)
  {
  var overlap = bbox_bottom - coll_top;
  y = y - overlap - 2;
  }
   
  // collision happens ABOVE the player:
  if (bbox_top <= coll_bottom)
  {
  var overlap = coll_bottom - bbox_top;
  y = y + overlap + 2;
  }
} until (check == noone); // repeat this process until there are no more collisions
Disclaimer: I didn't test this code but from my comments I hope it's clear what it should be doing. Hope this helps!
 
G

gamible

Guest
This is a very ugly solution and definitely not the best, but you could make the players mask be spr_babyBox instead.

Put this in the player's create event.
Code:
mask_index = spr_babymask;
 
P

Power_Michael

Guest
You could add a condition for if the block is close to a wall when the alarm goes off, like
if( place_meeting( x+ some high number, y,, wall) )
{
//move away from wall by affecting x position in the opposite direction
}

and then repeat for the left side.
I mean I'm far from an expert, I need at least 20 different trial and errors before I get my enemies working perfect but that's the first thing I'd TRY to do what your saying :p
Yeah I get what you are saying, thanks for the answer!
 
P

Power_Michael

Guest
Hi Michael!

Personally I would put the alarm code into the step event, simply because that way you know when it happens and can move the sprite away from anything it might get stuck in before continuing. e.g.:

Step event
Code:
if (alarm[0] <= 0)
{
   // your alarm code as switch statement
   switch (sprite_index)
   {
      case spr_babyBox:
      {
      sprite_index = spr_smallBox;
      } break;
      case spr_smallBox:
      {
      sprite_index = spr_mediumBox
      } break;
      case spr_mediumBox
      {
      sprite_index = spr_largeBox;
      } break;
   }
 
   // reset alarm
   alarm[0] = room_speed * 10; 

  // collision check code (see below)

}
I don't know what objects your character collides with, so I just use obj_wall here. Basically, it's checking for a collision on either side of the bounding box and moves the instance away from it until there is no collision anymore.

insert this code in the step event code from above, where i put "collision check code" :

Code:
// do this for all collisions we detect:
do
{
  // checks for a collision of the instances bounding box with a wall object instance
  var check = collision_rectangle(bbox_left, bbox_top, bbox_right, bbox_bottom, obj_wall, false, true);

  // houson, we have a collision. let's get the boundin box of the colliding object
  var coll_left  = other.bbox_left;
  var coll_top  = other.bbox_top;
  var coll_right  = other.bbox_right;
  var coll_bottom = other.bbox_bottom;
 
  // new we compare the start of the two bounding boxes.

  // collision happens to the RIGHT of the player: 
  if (bbox_right > coll_left)
  { 
  // find out, how far it's overlapping
  var overlap = coll_left - bbox_right;
 
  // push back player instance that amount + 2 px for good measure
  x = x - overlap - 2;
  }
 
  // now we do the same for the other kinds of collisions:
 
  // collision happens to the LEFT of the player:
  if (bbox_left <= coll_right)
  {
  var overlap = bbox_left - coll_right;
  x = x + overlap + 2;
  }
 
  // collision happens UNDER the player:
  if (bbox_bottom > coll_top)
  {
  var overlap = bbox_bottom - coll_top;
  y = y - overlap - 2;
  }
 
  // collision happens ABOVE the player:
  if (bbox_top <= coll_bottom)
  {
  var overlap = coll_bottom - bbox_top;
  y = y + overlap + 2;
  }
} until (check == noone); // repeat this process until there are no more collisions
Disclaimer: I didn't test this code but from my comments I hope it's clear what it should be doing. Hope this helps!
Hey, first I wanted to thank you so much for the reply....and then I wanted to let you know that I tested the code....and it ALMOST worked...I have never worked with bounding boxes nor ever heard of them. If you could help me further that would be amazing...so I put the code in how you listed...and what happens is interesting. To test it....I moved the small block up against the wall so if it were to change it would either move away...or get stuck. It changed and it moved BELOW the ground and far to the right which evidently ended up wedged inside of another wall...then I sat there thinking IT MOVED....but not the right way LOL. Then I let it change again and it moved out of the wall and into the open where it fell out of view. So I am completely lost in the code you sent me....I am grateful that you sent it and it almost works....but I have no idea how to work with it so if you could help me that would be awesome...I will include more of my step event below if that helps and let me know if you need more info on my part. Here is some more of my code if it helps:

Step (collison code)

Code:
// Horizontal Collisions

if place_meeting(x+hspd, y, obj_ground1)
{
    while (!place_meeting(x+sign(hspd), y, obj_ground1))
    {
        x += sign(hspd);
    }
    hspd = 0;
}


//Move Horizontally

x += hspd;




// Vertical Collisions

if place_meeting(x, y+vspd, obj_ground1)
{
    while (!place_meeting(x, y+sign(vspd), obj_ground1))
    {
        y += sign(vspd)
    }
    vspd = 0;
}


//Move Vertically
y += vspd;

EDIT: So I tinkered around with the code some more....and I took away the top and bottom boxes...so I wouldn't fly up or down....then I changed the # of pixels I move in either direction (left or right)...From 2 I changed it to 100.....and it works great now...almost. I realized that because the alarm repeats itself...every 10 seconds...if I am close to a wall it will CORRECT my position which is not what i want....So I am on to something here...thank you again for your HALP.
 
Last edited by a moderator:

TheouAegis

Member
Code:
//Create Event...
    shift = 0;

//When you change your sprites....
sprite_index = whatever;
var col = instance_place(x,y,obj_ground1);
if col 
{
    if abs(col.bbox_left - bbox_right) < abs(col.bbox_right - bbox_left)
        shift = -1;
    else
        shift = 1;
}

//Elsewhere in the Step Event...
if shift !=0
{
    x += shift << 1;
    if !place_meeting(x,y,obj_ground1)
        shift = 0;
}
 

Phil Strahl

Member
EDIT: So I tinkered around with the code some more....and I took away the top and bottom boxes...so I wouldn't fly up or down....then I changed the # of pixels I move in either direction (left or right)...From 2 I changed it to 100.....and it works great now...almost. I realized that because the alarm repeats itself...every 10 seconds...if I am close to a wall it will CORRECT my position which is not what i want....So I am on to something here...thank you again for your HALP.
Glad it helped at least a bit and not made everything worse. ;) If you want to run the collision code not every time the alarm is set off, just move it out of the if (alarm[0] <= 0) condition and have a different condition-check. E.g. for it to happen automatically when the sprite_index changes, I'd add a simple last_sprite_index variable in your player's create event.
Code:
last_sprite_index = sprite_index;
At the very end of the step event (or in the post-step event), set
Code:
last_sprite_index = index_index;
Then, in the step event, you can use it to check for any changes. I'd put after tampering with the sprite_index.
Code:
if last_sprite_index != sprite_index
{
   do 
   {
      // your modified code placement code
   }
}
Hope it didn't make things worse ;)
 
T

Toxicosis

Guest
What a surprise, Michael. I had exactly the same problem. But because of reasons... I didn't look for help here. Should have, in hindsight...

The first thing I tried was using move_outside_solid. Avoid at all costs- it's extremely demanding on the computer, I had the fps dipping all the way to 8 (or 12, can't recall exactly), and I'm not exactly coding on a pedaling potato.

My solution was... well, a bit more complicated. I generated an array to mark the positions available around the sprite. Then I had it check every (insert half of sprite's bounding box size) pixels around for a collision with an object whose mask was exactly the same size as the final sprite. That was the hardest part; in order to make sure the calculations were as few as possible, I took advantage of every cute trick I knew of.

Took me 3 scripts, over 250 lines of code, and some fiddling with surfaces (which helped me seeing what exactly was going on and just why it wasn't working) to make it work, though. Here's an abridged version that should just about do it for you.


First, create an object, box_target, make it invisible, nonsolid, nonphysics, and give it no actions. Just make sure it has the same bounding box as the target you were looking for. The easiest way to do this is to give it the same sprite. Then create the following script, scr_box_target.

For checking if there's enough room:
Code:
//This is scr_box_target.

var i, j, k, l, m, d; //This was the hard part. Basically, we're going to create an array to check where you got enough room.
m = 10; //The number of meshes we want to check in every direction.
d = 32; //The size of the mesh we want to check. I doubt you want to make a 640 px medium box, so, figure out what mesh size works for you.
k = 2*m; //The limit of the mesh in every direction. Don't check the whole level.
l = 2*m; //Same.

for (i=0; i!=k; i++)
   for (j=0; j!=l; j++)
      check[i,j]=0; //Initialize the array.

for (i=m-1; i!=m+2; i++)
   for (j=m-1; j!=m+2; j++)
      if place_meeting (x+d*(i-m),y+d*(j-m),obj_wall)
         check[i,j]=2; //First, check if there's any room at all. If the object has a wall closer than the mesh distance in any direction, don't bother with the rest of the collision checks in that direction. Those 9 checks can save you from doing 441 checks, so there you go.

for (i=m-1; i!=m+2; i++)
   for (j=m-1; j!=m+2; j++)
      if check[i,j]==2
      {
         for (k=0;k!=2m+1;k++)
            for (l=0;l!=2m+1;l++)
               {
               if (sign(k-m) == sign (i-m)) && (sigm (l-m) == sign (j-m)) check[k,l] = 1;
               //Cut off any positions that are in the same direction as the initial collisions.
               }
      }

//And here comes my favourite part. We draw a spiral, and start checking any position left against the bounding box of the larger sprite. I used a special object for that; maybe you can do the same?

var steps, head, counter;
counter = 1;
head = 1;
k=m;
l=m;
instance_create (0,0,box_target);
while (k!=-1 && k!=2m+1 && l!=-1 && l!=2m+1) //While we stay inside the same grid as before.
{
   for (steps = 0; steps != counter; steps++)
   {
      if check [k,l] == 0
      {
         with box_target
            if !place_meeting (other.x+(k-m)*d,other.y+(l-m)*d,obj_wall)
            {
            x=other.x+(k-m)*d
            y=other.y+(l-m)*d
            return true; //Do not start enlarging the box until it returns true.
            }
            else with other check[k,l] = 1;
      }
      switch (head mod 4):
      {
         case 0:
         k++;
         case 1:
         l++;
         case 2:
         k--;
         case 3:
         l--;
      }
   }
   head++;
   if (head mod 2 == 1) counter++;
}
with box_target instance_destroy(); //We're done with the box_target, so get rid of it before it screws something up.
return false; //If it doesn't find any room, leave the alarm ringing! As soon as this code returns true, it'll turn into a big box.
Place this in either the alarm or the step event.
Code:
if scr_box_target() //Call to the earlier code, and once it returns true, there you go.
{
x=box_target.x;
y=box_target.y;
with box_target instance_destroy();
spr_index=medium_box;
}
If you want this to work with all 4 changes, you'll need to make scr_box_target take an argument (probably the sprite_index you want), and pass it as the bounding box of the created instance of box_target. I've never done that before, though. I imagine you'd need to add something like

Code:
var proceed;
if sprite_index == 0
   proceed = scr_box_target(spr_smallbox);
if sprite_index == 1
   proceed = scr_box_target(spr_mediumbox);
if sprite_index == 2
   proceed = scr_box_target(spr_largebox);

if proceed
{all the stuff}

//That in the alarm.

with (box_target)   sprite_index = argument0;
//That in the room checking script.
immediately after the instance create, but I'm not sure.
 
Last edited by a moderator:
P

Power_Michael

Guest
What a surprise, Michael. I had exactly the same problem. But because of reasons... I didn't look for help here. Should have, in hindsight...

The first thing I tried was using move_outside_solid. Avoid at all costs- it's extremely demanding on the computer, I had the fps dipping all the way to 8 (or 12, can't recall exactly), and I'm not exactly coding on a pedaling potato.

My solution was... well, a bit more complicated. I generated an array to mark the positions available around the sprite. Then I had it check every (insert half of sprite's bounding box size) pixels around for a collision with an object whose mask was exactly the same size as the final sprite. That was the hardest part; in order to make sure the calculations were as few as possible, I took advantage of every cute trick I knew of.

Took me 3 scripts, over 250 lines of code, and some fiddling with surfaces (which helped me seeing what exactly was going on and just why it wasn't working) to make it work, though. Here's an abridged version that should just about do it for you.


First, create an object, box_target, make it invisible, nonsolid, nonphysics, and give it no actions. Just make sure it has the same bounding box as the target you were looking for. The easiest way to do this is to give it the same sprite. Then create the following script, scr_box_target.

For checking if there's enough room:
Code:
//This is scr_box_target.

var i, j, k, l, m, d; //This was the hard part. Basically, we're going to create an array to check where you got enough room.
m = 10; //The number of meshes we want to check in every direction.
d = 32; //The size of the mesh we want to check. I doubt you want to make a 640 px medium box, so, figure out what mesh size works for you.
k = 2*m; //The limit of the mesh in every direction. Don't check the whole level.
l = 2*m; //Same.

for (i=0; i!=k; i++)
   for (j=0; j!=l; j++)
      check[i,j]=0; //Initialize the array.

for (i=m-1; i!=m+2; i++)
   for (j=m-1; j!=m+2; j++)
      if place_meeting (x+d*(i-m),y+d*(j-m),obj_wall)
         check[i,j]=2; //First, check if there's any room at all. If the object has a wall closer than the mesh distance in any direction, don't bother with the rest of the collision checks in that direction. Those 9 checks can save you from doing 441 checks, so there you go.

for (i=m-1; i!=m+2; i++)
   for (j=m-1; j!=m+2; j++)
      if check[i,j]==2
      {
         for (k=0;k!=2m+1;k++)
            for (l=0;l!=2m+1;l++)
               {
               if (sign(k-m) == sign (i-m)) && (sigm (l-m) == sign (j-m)) check[k,l] = 1;
               //Cut off any positions that are in the same direction as the initial collisions.
               }
      }

//And here comes my favourite part. We draw a spiral, and start checking any position left against the bounding box of the larger sprite. I used a special object for that; maybe you can do the same?

var steps, head, counter;
counter = 1;
head = 1;
k=m;
l=m;
instance_create (0,0,box_target);
while (k!=-1 && k!=2m+1 && l!=-1 && l!=2m+1) //While we stay inside the same grid as before.
{
   for (steps = 0; steps != counter; steps++)
   {
      if check [k,l] == 0
      {
         with box_target
            if !place_meeting (other.x+(k-m)*d,other.y+(l-m)*d,obj_wall)
            {
            x=other.x+(k-m)*d
            y=other.y+(l-m)*d
            return true; //Do not start enlarging the box until it returns true.
            }
            else with other check[k,l] = 1;
      }
      switch (head mod 4):
      {
         case 0:
         k++;
         case 1:
         l++;
         case 2:
         k--;
         case 3:
         l--;
      }
   }
   head++;
   if (head mod 2 == 1) counter++;
}
with box_target instance_destroy(); //We're done with the box_target, so get rid of it before it screws something up.
return false; //If it doesn't find any room, leave the alarm ringing! As soon as this code returns true, it'll turn into a big box.
Place this in either the alarm or the step event.
Code:
if scr_box_target() //Call to the earlier code, and once it returns true, there you go.
{
x=box_target.x;
y=box_target.y;
with box_target instance_destroy();
spr_index=medium_box;
}
If you want this to work with all 4 changes, you'll need to make scr_box_target take an argument (probably the sprite_index you want), and pass it as the bounding box of the created instance of box_target. I've never done that before, though. I imagine you'd need to add something like

Code:
var proceed;
if sprite_index == 0
   proceed = scr_box_target(spr_smallbox);
if sprite_index == 1
   proceed = scr_box_target(spr_mediumbox);
if sprite_index == 2
   proceed = scr_box_target(spr_largebox);

if proceed
{all the stuff}

//That in the alarm.

with (box_target)   sprite_index = argument0;
//That in the room checking script.
immediately after the instance create, but I'm not sure.
Hey thank you for the solution, I gave it a try....with no success...it gave me a few errors such as with the "2m" variable being unrecognized so I changed it to "2*m" and it worked...same thing, different format. Then it said I needed a "{" right here:
Code:
      }
      switch (head mod 4):
      {
         case 0:
         k++;
         case 1:
         l++;
         case 2:
         k--;
         case 3:
         l--;
      }
   }
at line 50....which would be the start of this switch statement...
 
T

Toxicosis

Guest
Ah, oopsie.
Cases in a switch statement require {} brackets.

It'd go like
Code:
switch (head mod 4):
{
   case 0:
   {
   k++;
   }
//etc
}
That ought to work.

EDIT: Actually, my own code uses IFs, because I couldn't understand case and switch at the time, and there were so many brackets that I was losing patience. But switch should work for you.

IF works because these results are mutually exclusive. But I figure a switch statement might be slightly more efficient. I could be wrong, though.
 
Last edited by a moderator:
P

Power_Michael

Guest
Ah, oopsie.
Cases in a switch statement require {} brackets.

It'd go like
Code:
switch (head mod 4):
{
   case 0:
   {
   k++;
   }
//etc
}
That ought to work.

EDIT: Actually, my own code uses IFs, because I couldn't understand case and switch at the time, and there were so many brackets that I was losing patience. But switch should work for you.

IF works because these results are mutually exclusive. But I figure a switch statement might be slightly more efficient. I could be wrong, though.
This is strange, I feel as though it may be a glitch, but it is still giving the same error(s)....I will send a full copy of the code from MY END, if you can see anything let me know. Thank you so much for helping out!
Code:
//This is scr_box_target.

var i, j, k, l, m, d; //This was the hard part. Basically, we're going to create an array to check where you got enough room.
m = 10; //The number of meshes we want to check in every direction.
d = 32; //The size of the mesh we want to check. I doubt you want to make a 640 px medium box, so, figure out what mesh size works for you.
k = 2*m; //The limit of the mesh in every direction. Don't check the whole level.
l = 2*m; //Same.

for (i=0; i!=k; i++)
   for (j=0; j!=l; j++)
      check[i,j]=0; //Initialize the array.

for (i=m-1; i!=m+2; i++)
   for (j=m-1; j!=m+2; j++)
      if place_meeting (x+d*(i-m),y+d*(j-m),obj_wall)
         check[i,j]=2; //First, check if there's any room at all. If the object has a wall closer than the mesh distance in any direction, don't bother with the rest of the collision checks in that direction. Those 9 checks can save you from doing 441 checks, so there you go.

for (i=m-1; i!=m+2; i++)
   for (j=m-1; j!=m+2; j++)
      if check[i,j]==2
      {
         for (k=0;k!=2*m+1;k++)
            for (l=0;l!=2*m+1;l++)
               {
               if (sign(k-m) == sign (i-m)) && (sign (l-m) == sign (j-m)) check[k,l] = 1;
               //Cut off any positions that are in the same direction as the initial collisions.
               }
      }

//And here comes my favourite part. We draw a spiral, and start checking any position left against the bounding box of the larger sprite. I used a special object for that; maybe you can do the same?

var steps, head, counter;
counter = 1;
head = 1;
k=m;
l=m;
instance_create (0,0,box_target);
while (k!=-1 && k!=2*m+1 && l!=-1 && l!=2*m+1) //While we stay inside the same grid as before.
{
   for (steps = 0; steps != counter; steps++)
   {
      if check [k,l] == 0
      {
         with box_target
            if !place_meeting (other.x+(k-m)*d,other.y+(l-m)*d,obj_wall)
            {
            x=other.x+(k-m)*d
            y=other.y+(l-m)*d
            return true; //Do not start enlarging the box until it returns true.
            }else{ with other check[k,l] = 1;
            {
            {
   
      switch (head mod 4):
      {
         case 0:
         {
         k++;
         }
         case 1:
         {
         l++;
         }
         case 2:
         {
         k--;
         }
         case 3:
         {
         l--;
         }
         
      }
   }
   head++;
   if (head mod 2 == 1)
   {
   counter++;
   }
}
with box_target instance_destroy(); //We're done with the box_target, so get rid of it before it screws something up.
return false; //If it doesn't find any room, leave the alarm ringing! As soon as this code returns true, it'll turn into a big box.
It is still saying there is the error at the switch statement saying I need to put a "{". ;o
 
P

Power_Michael

Guest
Glad it helped at least a bit and not made everything worse. ;) If you want to run the collision code not every time the alarm is set off, just move it out of the if (alarm[0] <= 0) condition and have a different condition-check. E.g. for it to happen automatically when the sprite_index changes, I'd add a simple last_sprite_index variable in your player's create event.
Code:
last_sprite_index = sprite_index;
At the very end of the step event (or in the post-step event), set
Code:
last_sprite_index = index_index;
Then, in the step event, you can use it to check for any changes. I'd put after tampering with the sprite_index.
Code:
if last_sprite_index != sprite_index
{
   do
   {
      // your modified code placement code
   }
}
Hope it didn't make things worse ;)
Hey, so I have been trying multiple solutions including yours, but I am still stuck. I will be honest I didn't quite understand your last fix...I tried putting some of it in, but it just gave me an error at the end saying I needed to put the keyword "until" when there was already the keyword "until" and only one "do" statement. I think this also may be a glitch, but I don't know ;o. Thank you for helping out this far!

Edit: With what I have now, besides the fact that the collision fix repeats itself over and over...the re-positioning is kind of choppy...would you know a way that rather than just teleporting the block away from the wall, if it could slide away...a little more smooth.. :D
 

Phil Strahl

Member
Important: After each case in the switch, (or rather before each new case) you need to insert a break, otherwise the following cases get also executed (unless that's what you want)
 
T

Toxicosis

Guest
Yeah, Phil, you're right. I did it with a series of IF in my case.

Try this code, Michael.

Code:
//where it says
switch head mod 4
{}
Code:
 use instead
if head mod 4 == 0 k++;
if head mod 4 == 1 l++;
if head mod 4 == 2 k--;
if head mod 4 == 3 l--;
EDIT:

I checked your code. Apparently, I messed up the keys. Here's another version.

Code:
//This is scr_box_target.

var i, j, k, l, m, d; //This was the hard part. Basically, we're going to create an array to check where you got enough room.
m = 10; //The number of meshes we want to check in every direction.
d = 32; //The size of the mesh we want to check. I doubt you want to make a 640 px medium box, so, figure out what mesh size works for you.
k = 2*m; //The limit of the mesh in every direction. Don't check the whole level.
l = 2*m; //Same.

for (i=0; i!=k; i++)
  for (j=0; j!=l; j++)
  check[i,j]=0; //Initialize the array.

for (i=m-1; i!=m+2; i++)
  for (j=m-1; j!=m+2; j++)
  if place_meeting (x+d*(i-m),y+d*(j-m),obj_wall)
  check[i,j]=2; //First, check if there's any room at all. If the object has a wall closer than the mesh distance in any direction, don't bother with the rest of the collision checks in that direction. Those 9 checks can save you from doing 441 checks, so there you go.

for (i=m-1; i!=m+2; i++)
  for (j=m-1; j!=m+2; j++)
  if check[i,j]==2
  {
  for (k=0;k!=2*m+1;k++)
  for (l=0;l!=2*m+1;l++)
  {
  if (sign(k-m) == sign (i-m)) && (sign (l-m) == sign (j-m)) check[k,l] = 1;
  //Cut off any positions that are in the same direction as the initial collisions.
  }
  }

//And here comes my favourite part. We draw a spiral, and start checking any position left against the bounding box of the larger sprite. I used a special object for that; maybe you can do the same?

var steps, head, counter;
counter = 1;
head = 1;
k=m;
l=m;
instance_create (0,0,box_target);
while (k!=-1 && k!=2*m+1 && l!=-1 && l!=2*m+1) //While we stay inside the same grid as before.
{
  for (steps = 0; steps != counter; steps++)
  {
  if check [k,l] == 0
  {
  with box_target
  if !place_meeting (other.x+(k-m)*d,other.y+(l-m)*d,obj_wall)
  {
  x=other.x+(k-m)*d
  y=other.y+(l-m)*d
  return true; //Do not start enlarging the box until it returns true.
  }
  else
  {
  with other
  check[k,l] = 1;
  }
  }
  if head mod 4 == 0 k++;
  if head mod 4 == 1 l++;
  if head mod 4 == 2 k--;
  if head mod 4 == 3 l--;
  }
  head++;
  if (head mod 2 == 1)
  {
  counter++;
  }
}
with box_target instance_destroy(); //We're done with the box_target, so get rid of it before it screws something up.
return false; //If it doesn't find any room, leave the alarm ringing! As soon as this code returns true, it'll turn into a big box.
 
P

Power_Michael

Guest
I wanted to thank you all for your help, unfortunately, I have not successfully made any of this work....and it is more than likely my fault as I am still an amateur when it comes to programming. The game includes this feature where you grow...now I have decided that while growing over time (alarm) can create a ton of more problems, I have decided that instead I will make an object that you consume and it changes the sprite to the bigger sprite. Of course a good portion of this code will still be useful if the character is growing by a wall. Thank you all for your help...I am sorry I have not been able to successfully make any of this work, but thank you all for continuously helping out with this problem...if any of you happen to test a working solution....go ahead and put it in here if anyone else needs it....happy gamemaking everybody :D
 
Top