Inventory System Duplicating Sprites

C

Cheinberger

Guest
Hello all!

I watched Beyond Us Games' tutorial on an inventory system (
) and tried to implement GUI to it, so that it follows the camera and player. For the most part, it works; however, when I press "I" to open the inventory, it creates the object, but duplicates the sprite, to where when I move around the room, one oInventory follows me like I want, but a duplicate sprite is left behind and staying still in the position it was created. The same problem happens with the oButton I created, but instead of the object following the camera, only the sprite follows the camera, while the pressable button with coding is left behind at the position it was created. I have a lot of code here, so please bear with me.

--------------oInventory
///Create Event
globalvar playerInventory, playerInventoryWidth;
playerInventoryWidth = 5;
playerInventory = ds_grid_create(playerInventoryWidth, 1);

///Draw GUI
if keyboard_check_pressed(ord("I"))
{
if(!instance_exists(oInventoryGUI)) {
inventoryDisplay = instance_create_depth(GetViewX(), GetViewY(), depth - 1, oInventoryGUI);
with(inventoryDisplay) {
x = GetViewX();
y = GetViewY();
}
}
else {
instance_destroy(oInventoryGUI);
repeat(2)
instance_destroy(oButton);
}
}

---------------oInventoryGUI
///Create Event
textBorder = 15;
myItems = playerInventory;
myColor = c_black;
isEmpty = false;
emptyMessage = "Empty";

globalvar itemSelected, scrolledAmount, inventoryEndAt;
itemSelected = 0;
scrolledAmount = 0;
inventoryEndAt = min(ds_grid_height(myItems), floor((sprite_height - (textBorder * 3)) / 32));
inventoryOnScreen = 0;
if(ds_grid_get(myItems, 0, 0) == 0) {
inventoryEndAt = 0;
isEmpty = true;
}

alarm[0] = 1;

///Draw GUI
draw_self();
draw_set_colour(myColor);
draw_set_font(fontInventory);


draw_text(bbox_left + textBorder, bbox_top + textBorder, "Image");
draw_text(bbox_left + 82, bbox_top + textBorder, "Name");
draw_text(bbox_left + 204, bbox_top + textBorder, "Amount");


itemLeftStart = bbox_left + 84;
itemTopStart = bbox_top + 48;

for(i = 0; i < inventoryEndAt; ++i) {
for(j = 0; j < playerInventoryWidth; ++j) {
inventoryOnScreen = i;
if(j == 0)
draw_text(itemLeftStart, itemTopStart + (i * 18), ds_grid_get(myItems, 0, i + scrolledAmount));
if(j == 1)
draw_text(itemLeftStart + 140, itemTopStart + (i * 18), ds_grid_get(myItems, 1, i + scrolledAmount))
if(j == 3)
draw_sprite(ds_grid_get(myItems, j, i + scrolledAmount), 0, bbox_left + 25, itemTopStart + (i * 18) + 6);
}
}

if(!isEmpty)
draw_rectangle(bbox_left + textBorder, itemTopStart + ((itemSelected - scrolledAmount) * 18) - 4, bbox_right - textBorder, itemTopStart + ((itemSelected - scrolledAmount) * 18) + 14, true);

draw_sprite(sItemBox, 0, GetViewX(), GetViewY());

if(isEmpty)
draw_text_ext(GetViewX() + 80, GetViewY() + 160, emptyMessage, 32, sprite_get_width(sItemBox) - textBorder);
else
draw_text_ext(GetViewX() + 80, GetViewY() + 160, ds_grid_get(myItems, 2, itemSelected), 20, sprite_get_width(sItemBox) - textBorder);


if(ds_grid_height(myItems) > floor((sprite_height - (textBorder * 3)) / 32)) {
draw_sprite(sScrollBar, 0, bbox_right - 10, bbox_top + 50 + itemSelected * (sprite_height - 89) / ds_grid_height(myItems));
}

///Alarm 0
useButton = instance_create_depth(GetViewX(), GetViewY(), depth - 1, oButton);
useButton.myText = "Use";

trashButton = instance_create_depth(GetViewX() + 45, GetViewY(), depth - 1, oButton);
trashButton.myText = "Destroy"

///Step Event
if(ds_grid_get(myItems, 0, 0) != 0) {
isEmpty = false;
inventoryEndAt = ds_grid_height(myItems);
if(ds_grid_height(myItems) >= floor((sprite_height - (textBorder * 3)) / 32))
inventoryEndAt = floor((sprite_height - (textBorder * 3)) / 32);
}

if(ds_grid_get(myItems, 0, 0) == 0) {
isEmpty = true;
inventoryEndAt = 0;
}

-----------------oButton
///Create Event
image_speed = 0;
myText = undefined;

///Draw GUI
draw_self();
draw_text(x + 213, y + 227, myText);

----------Scripts for GUI following player
///GetViewX
return camera_get_view_x(camera_get_active());

///GetViewY
return camera_get_view_y(camera_get_active());

 
Add an empty Draw Event to your inventory objects to prevent them from automatically drawing themselves to the application surface.

Edit: Also you if you are using Draw GUI even, you want to create your buttons relative to the top right top-left corner being 0,0, they don't need to be positioned relative to the view unless you were using the standard Draw Event.

Of course if you use Draw GUI you will need an alternative method to detect mouse clicks, such as point_in_rectangle() and device_mouse_x_to_gui () etc...
 
Last edited:
C

Cheinberger

Guest
Add an empty Draw Event to your inventory objects to prevent them from automatically drawing themselves to the application surface.

Edit: Also you if you are using Draw GUI even, you want to create your buttons relative to the top right corner being 0,0, they don't need to be positioned relative to the view unless you were using the standard Draw Event.

Of course if you use Draw GUI you will need an alternative method to detect mouse clicks, such as point_in_rectangle() and device_mouse_x_to_gui () etc...
Thank you! It worked for the duplicate sprites; however, its still creating the button object in the same position without following the player, just without the button sprite. Sorry, I'm just a little new to all this
 
Oops by the way when I said top right, I meant top left.

The way I do it is use the point_in_rectangle () function, and for the parameters I use the bbox_left, bbox_right etc...for the position of the button and device_mouse_x_to_gui() and device_mouse_y_to_gui() as the x and y coordinates to check when the user clicks the mouse.

This is assuming you have positioned the buttons relative to the screen using 0,0 as top left corner and they are not being repositioned.

Edit: I would double check the tutorial if I were you. I can't watch the video from where I am, but the code they are using probably means you should just be using the standard Draw event, not Draw Gui. If you just change that, and keep your original code it might work.
 
C

Cheinberger

Guest
Thanks so much for your patience! He did use standard draw events in his tutorial, but when I put my code in a standard draw event, the inventory wouldn't follow the screen or player, (he didn't want it to do that) which led me to some research, which led me to the draw GUI event. Forgive me, but I'm not understanding how to get the button object to follow the player. I tried to use the point_in_rectangle() function with bbox inside the Button Object, but it basically did the same thing that it was doing.

I can point my mouse in the button object at first, and it changes the sprite like I want it to, but if I move my player to a different position, and open the inventory, the buttons appear to be in the correct position (at least the sprites), but I have to hover my mouse over the original position the button was created in order to change the sprite. That's telling me that the button sprite is following the player like I want it to, but the button object itself is not. Its like when the button object is being created, it is being created to a specific point in the room, whether I'm near it or not, and not being created wherever my player and inventory are.

I'm such a rookie at this whole coding thing, and its really fun to learn about, but a big downfall of mine is that its hard to understand exactly what people mean when they try to help me :/ lol maybe I just need a little more hand holding for this one. With my code specifically, which object would I type the code to create the button with the 0,0 coordinates, which object would I type point_in_rectangle(), and device_mouse_x_to_gui()? Or could it be a different issue?
 
Hmm...In order to get this working with the minimum of changes required, you could try sticking with the tutorials setup, don't use the Draw GUI Event, just the Draw Event. Then all you need to do is in all your inventory objects/buttons that are displayed on screen, in the End Step Event, make sure you re-position their x and y coordinates using the functions you already have, GetViewX() and GetViewY().

Code:
x = GetViewX() + x_offset;
y = GetViewY() + y_offset;
Where x_offset and y_offset (call them whatever you want) are the positions on screen you want the buttons to appear.

So for example, setting x_offset and y_offset to 10,10, would have the button appear in the top left corner offset by 10 pixels, and it would follow the view wherever the player moved.

Let me know if you get stuck or need more details.
 
C

Cheinberger

Guest
Hmm...In order to get this working with the minimum of changes required, you could try sticking with the tutorials setup, don't use the Draw GUI Event, just the Draw Event. Then all you need to do is in all your inventory objects/buttons that are displayed on screen, in the End Step Event, make sure you re-position their x and y coordinates using the functions you already have, GetViewX() and GetViewY().

Code:
x = GetViewX() + x_offset;
y = GetViewY() + y_offset;
Where x_offset and y_offset (call them whatever you want) are the positions on screen you want the buttons to appear.

So for example, setting x_offset and y_offset to 10,10, would have the button appear in the top left corner offset by 10 pixels, and it would follow the view wherever the player moved.

Let me know if you get stuck or need more details.
Thanks so much for your help. I ended up getting frustrated enough to change the button system in my inventory entirely. I'm just using a shift+Click to destroy the item that is highlighted now. I really appreciate your patience!
 
Ha ha cool, happy to hear you found a way :) and you're welcome.

Just to answer the question from before the code would look something like this:

Step Event for oButton
Code:
if ( mouse_check_button_pressed(mb_left) )
{
    if point_in_rectangle(device_mouse_to_gui_x(), device_mouse_to_gui_y(), bbox_left, bbox_top, bbox_right, bbox_bottom)
    {
        // clicked = true
        // Do Stuff
    }
}
 
Top