GameMaker Struggling with game behavior inconsistencies between objects that share the same code.

P

parthhay

Guest
I'm using Game Maker Studio 2 v2.2.1.287.

I've included a short video link at the bottom that showcases my problem.

I've begun prototyping an "Inventory Simulator" game where the basic concept is you're supposed to pick items up of various shapes and sizes, and fit them into your limited inventory space in a certain amount of time leaving as few items behind as possible.

The first thing I did was create a couple items, and make it so if I clicked on them, they would follow my mouse, until I clicked again which would place them down while snapping to a grid. This works fine.

The problem I'm running into is the behavior of if there is an item beneath the item you're trying to place, I want it to essentially "switch" the items out. Put the one on the mouse down, and pick the one underneath up.

I created a parent object for the items since I was going to have upwards of a dozen items all of which should have nearly identical code.

In the Create Event of the parent object I declare 1 variable.

Code:
on_mouse = false;
In the Step Event I control the movement and depth of the items.

Code:
    if on_mouse == true {
        x = mouse_x;
        y = mouse_y;
        move_snap(16, 16);
        depth = -1;
    } else {
        depth = 1;
    }
Finally in a Left Pressed Event, I have the logic for what happens when you try to pick up, and place down items. Outside of this item parent object I have a controller object that simply creates the global variable holding and sets it to false.

Code:
    if global.holding == true {
        var under = instance_place(x, y, o_item_parent)
        if under != noone {
            on_mouse = false;
        
            under.on_mouse = true;
        
            global.holding = true;
        } else {
            on_mouse = false;
        
            global.holding = false;
        }
    } else {
        on_mouse = true;
    
        global.holding = true;
    }
My thought process here is as follows. First I check if global.holding is true, if not then I "pick up" the item by changing its variable "on_mouse" to true which enables the movement code in the step event. I also change the global.holding to true.

Second if global.holding is in fact true, then I create a local variable called under which checks whether or not there is an instance of the item parent at the current coordinates.

If "under" does return an ID, aka there is an instance underneath the mouse, then I turn the current held items variable "on_mouse" to false, which prevents it from moving. Then access the returned instance ID's "on_mouse" variable and change it to true which allows it to follow the mouse. Subsequently I change global.holding equal to true.

If "under" does not return an ID, aka there is no instance underneath the mouse, then I turn the current held items variable "on_mouse" to false, and global.holding to false.

Right now I have two items made, a "2x2" item, and a "1x1" item. One of each in the room. Both of them are Children of the o_item_parent object which runs the code above. If I run the game and click on either item to pick it up, and put it down in an empty area it works perfectly fine. However if I try and place an item on top of the other to "switch" them out something weird happens. Placing the "2x2" object on the "1x1" and clicking works fine, it swaps them out like I think it should. But when I try to do the opposite, by trying to place the "1x1" object on top of the "2x2" object to swap them out it simply doesn't work.

It doesn't "deactivate" the "1x1" so it recognizes that there is an item beneath and won't place itself down, but for whatever reason it won't swap out like the above scenario does.

Am I missing something in my code logic? Is there something I need to add in the items code on top of the code they are inheriting?

Here's a short video of me demonstrating the problem to help give a better idea of what I mean.

https://streamable.com/d01a0

Thank you in advance for your consideration, and time! Also, I am sorry for this wall of text. I just wanted to be thorough in my explanation.
 

Relic

Member
The issue is because one objects code always runs before the other and both objects will have their left pressed event triggered.

Let’s say you are holding the small block and the big blocks event runs first:

Big block event causes on-mouse and holding to become false for big block.

Then small block event runs and since holding is false, will “pickup” the small block, even though it already is picked up.
 
P

parthhay

Guest
Clear the mouse in that code so the 2x2 object isn't reading the mouse the same time the 1x1 got dropped.
I looked up mouse_clear() but I don't understand how to implement it to solve my problem.

The issue is because one objects code always runs before the other and both objects will have their left pressed event triggered.

Let’s say you are holding the small block and the big blocks event runs first:

Big block event causes on-mouse and holding to become false for big block.

Then small block event runs and since holding is false, will “pickup” the small block, even though it already is picked up.
I think I understand the problem, but I'm at a loss of how to solve it. How can I make it so only one item acts on mouse click?
 

TheouAegis

Member
In your code there, when you tell the currently selected object to replace the one underneath it, put mouse_clear() in there.
 
P

parthhay

Guest
In your code there, when you tell the currently selected object to replace the one underneath it, put mouse_clear() in there.
See I thought that might have been what you meant earlier and I tried that.

I tried placing mouse_clear(mb_left); before every single line of code and it doesn't seem to change anything. I'm not sure if I'm not understanding how this function works or if it simply won't solve my issue.

This is what you mean, no?

Code:
if global.holding == true {
    under = instance_place(x, y, o_item_parent)
    if under != noone {
        on_mouse = false;
        mouse_clear(mb_left);
        under.on_mouse = true;
      
        global.holding = true;
    } else {
        on_mouse = false;
      
        global.holding = false;
    }
} else {
    on_mouse = true;
  
    global.holding = true;
}
I appreciate you help. I'm just not getting this.
 
P

parthhay

Guest
That code is in the Left Pressed event in the item parent object.
 

TheouAegis

Member
Hmm...

This shouldn't matter, but try this: In the Step Event, put the line

if mouse_check_button_pressed(mb_left) { }

then copy your code in the last press event and paste it between those brackets. Then delete your left breast event so it doesn't conflict. test if clearing the mouse is working now that the code is all in the step event.

If that still doesn't work, try replacing the mouse_clear() with io_clear(). the latter is supposed to only be for the keyboard, but maybe they messed up.
 

hughrock18

Member
Im not exactly an expert programmer but why not simply have the "held" item run a quick collision check (with xy snapped to the grid) for the parent?

Basically, when you "drop" the item in the pressed event, before it actually drops (in the code) have a collision check for the parent. Simply snap the "held" item to the grid and use the snapped coor for the collision check. If the collision check returns true, you can simply swap out variables for which item is "held", but it sounds like there might a "holding issue" if you have more than 1 1x1 item under the 2x2 item you're trying to place. Perhaps you set the replaced item(s) back to there original state before being "picked up". Otherwise if the collision returns false, you simply set the xy coor back to the mouse's coor.

Disclaimer: again, im no expert. Ive just been coding for about 4 years now.

Hope that helps at all.
 
Top