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

item pickup bug that I can't solve

I developed a little item pickup dialogue system. When the player interacts with the item, dialogue displays saying what the item is and then asks if you want to pick it up. If yes, then it says "you picked up the item" and then disappears, destroying the item object. If no, then it closes out of the item. Returning to the item resets the text.

All the text is typed out typewriter style except for the second line, which is drawn all at once (intentional).

This system is working perfectly for the most part but I've noticed a bug.

If I have two or more items in a room and the item I interact with is lower on my asset list than the first, it bugs out. If the item is higher on the asset list than the others, there's no issue.

What happens:
-If I select yes, then the highest item in the asset list is destroyed rather than the one I'm actually interacting with.
-If I select yes, the first line choice[0] never goes away and is permanently stuck on the screen.
-If I select no, the first line choice[0] never goes away and is permanently stuck on the screen, but I'm now able to walk around the room.
-----------
I'm noticing if I pick up the highest item first, the second highest item then becomes the highest item. So if I go to pick the third highest, it deletes the second highest and so on and so forth.
-----------
Each item has the exact same code (no parent, as it confused me too much).
Bear with me...

Create Event of obj_item:
Code:
image_index = 0;
image_speed = 0;
count = 0; //keep track of choice display
typewriter_out = ""; //string to write
text_to_write = ""; //placeholder for choice arrays
i = 1; //start position
stop_text = false;
soundfile = snd_readables;
Step Event of obj_item:
Code:
if keyboard_check_pressed(ord("Z")) && count  == 1{
        stop_text = true;
        instance_create_depth(camera_get_view_x(view_camera[0])+160,camera_get_view_y(view_camera[0])+100,-100,obj_itembox);
}
if count == 1{
    text_to_write = choice[0];
}

if count == 2{
if obj_itemmaster.i8 == ""{
text_to_write = choice[1];
if alarm[1] == -1{
alarm[1]=room_speed*1;
}
}

else{
text_to_write = choice[1];
if alarm[2] == -1{
alarm[2]=room_speed*1;
}
}
}

if obj_itemmaster.i8 == ""{
choice[0]="It's a library book.\nTake it?";
choice[1]="You took the book.";
}
else{
choice[0]="It's a library book.\nTake it?";
choice[1]="Your inventory is full.";
}

if count == 3 && alarm[3]==-1{
    alarm[3]=room_speed*.025;
}

if instance_exists(obj_itembox){
switch(obj_itembox.image_index){
    case 0:
        if keyboard_check_pressed(vk_space){
            stop_text = false;
            count = 2;
            i = 1;
            typewriter_out = "";
            instance_destroy(obj_itembox);
        }
        break;
    case 1:
        if keyboard_check_pressed(vk_space){
            count = 3;
            stop_text = false;
            i = 1;
            typewriter_out = "";
            global.freeze = false;
            global.itemgrab = false;
            instance_destroy(obj_itembox);
        }
        break;
}
}
Alarm 0 of obj_item:
Code:
if stop_text == false{
if !audio_is_playing(snd_readables2){
audio_play_sound(snd_readables2,5,false);
}
typewriter_out += string_char_at(text_to_write,i);//add new character to string
i += 1;
if i - 1 != string_length(text_to_write){//text has not finished displaying
    alarm[0]=room_speed/(room_speed-5); //restart alarm
}
else{
    audio_stop_sound(snd_readables2);
    if !instance_exists(obj_itembox){
    instance_create_depth(camera_get_view_x(view_camera[0])+160,camera_get_view_y(view_camera[0])+100,-1000000,obj_itembox);
}
}
}
Alarm 1 of obj_item:
Code:
count = 3;
global.tempItem = "Library Book";
global.additem = true;
global.bookcount += 1;
Alarm 2 of obj_item:
Code:
global.freeze = false;
count = 0;
global.itemgrab = false;
Alarm 3 of obj_item:
Code:
if distance_to_object(obj_player_parent) == 0{


if global.itemgrab{

count = 0;
global.itemgrab = false;
global.freeze = false;
instance_destroy(self);
}

if !global.itemgrab{

count = 0;
global.itemgrab = false;
global.freeze = false;
}
}
Draw Event of obj_item:
Code:
draw_self();

if count != 0 && count != 3{
text_xOrigin = __view_get( e__VW.XView, 0 ) + 10;
text_yOrigin = __view_get( e__VW.YView, 0 ) + 6;

//Padding for inside dialogue box
var padding = 16;

//Max width & height
max_width = __view_get( e__VW.WView, 0 ) - (padding*2);
max_height = (__view_get( e__VW.HView, 0 )/4)-(.25*(__view_get( e__VW.HView, 0 )/4));

//draw dialogue boxes

var bw = 3; // Border width

// Draw dialogue box

margin_x = 15;
margin_y = 5;
text_margin_x = 10;
text_margin_y = 6.5;
text_height = 2.5;
draw_set_color(c_black);
draw_rectangle(__view_get( e__VW.XView, 0 ) +margin_x, __view_get( e__VW.YView, 0 )+7, __view_get( e__VW.XView, 0 ) + __view_get( e__VW.WView, 0 )-margin_x, __view_get( e__VW.YView, 0 ) + __view_get( e__VW.HView, 0 )-165,false);

// Rectangle Borders
var bw = 3; // Border width
draw_set_color(c_white);
draw_line_width(__view_get( e__VW.XView, 0 ) +margin_x, ((__view_get( e__VW.YView, 0 )+__view_get( e__VW.HView, 0 ))-max_height)-(padding*1.5) -margin_y - 160, __view_get( e__VW.XView, 0 )+margin_x, (__view_get( e__VW.YView, 0 )+__view_get( e__VW.HView, 0 )) - margin_y -160, bw);
draw_line_width(__view_get( e__VW.XView, 0 )-(bw/2)+margin_x, ((__view_get( e__VW.YView, 0 )+__view_get( e__VW.HView, 0 ))-max_height)-(padding*1.5)-margin_y -160, __view_get( e__VW.XView, 0 )+__view_get( e__VW.WView, 0 )-margin_x, ((__view_get( e__VW.YView, 0 )+__view_get( e__VW.HView, 0 ))-max_height)-(padding*1.5)-margin_y - 160, bw);
draw_line_width(__view_get( e__VW.XView, 0 )+__view_get( e__VW.WView, 0 )-bw/2 -margin_x, ((__view_get( e__VW.YView, 0 )+__view_get( e__VW.HView, 0 ))-max_height)-(padding*1.5) - margin_y -160, __view_get( e__VW.XView, 0 )+__view_get( e__VW.WView, 0 )-bw/2 -margin_x, (__view_get( e__VW.YView, 0 )+__view_get( e__VW.HView, 0 ))-margin_y -160, bw);
draw_line_width(__view_get( e__VW.XView, 0 ) +margin_x, (__view_get( e__VW.YView, 0 )+__view_get( e__VW.HView, 0 ))-bw/2 - margin_y - 160, __view_get( e__VW.XView, 0 )+__view_get( e__VW.WView, 0 )-margin_x, (__view_get( e__VW.YView, 0 )+__view_get( e__VW.HView, 0 ))-bw/2 - margin_y -160, bw);

// Draw Text On Screen
draw_set_color(c_white);
draw_set_font(fnt_readables);


switch (count){
  
    case 1:
    if stop_text == false{
    draw_text_ext(text_xOrigin + 16,text_yOrigin + 13,typewriter_out,16,max_width);
    }
    if stop_text == true{
        draw_text_ext(text_xOrigin + 16,text_yOrigin + 13,text_to_write,16,max_width);
    }
    break;
  
    case 2:
        if obj_itemmaster.i8 ==""{
        image_index = 1;
        draw_text_ext(text_xOrigin + 16,text_yOrigin + 13,choice[1],16,max_width);
        }
        else{
        draw_text_ext(text_xOrigin + 16,text_yOrigin + 13,choice[1],16,max_width);
        }
        break;
}
}
Collision event with obj_player:
Code:
if distance_to_object(obj_player_parent) == 0 && keyboard_check_pressed(vk_space)&& count == 0 && !global.paused && !global.tboxActive && !global.encounter_go && !global.inventory && !global.quests{
    global.freeze = true;
    global.itemgrab = true;
    count = 1;
    alarm[0]=room_speed/(room_speed-10);
}
Then I have the obj_itembox, which basically displays the yes no options.

Create Event of obj_itembox:
Code:
image_speed = 0;
image_index = 0; //yes by default
depth = -45000;
Step Event:
Code:
if keyboard_check_pressed(ord("D")){
    image_index = 1;
}
if keyboard_check_pressed(ord("A")){
    image_index = 0;
}
 

Rob

Member
This is a bad way to code an item system. Using globals that all your different item objects use is going to cause you plenty of issues now, and in the future.

Using objects like this (1 for each item) is also going to mess you up and there are much easier ways to do it.

The way that involves least learning that I can think of is as follows:

  • Have ONE item object
  • When you place/spawn then give them a reference number based on what item they are (so you know what you're picking up)
  • When you want to pick an item up (or interact with it in general) use some kind of function that will return that object's ID - like collision_point
  • If you want to know if a function returns an ID or not, just check the manual and it will tell you
  • When you've got the instance ID then you can just manipulate that particular instance's variables, no need for globals that will affect every other item
Code:
//EXAMPLE CODE

//step event of player

//We'll use the mouse to click on an item and get its ID

//Check to see if the LMB has been pressed
if (mouse_check_button_pressed(mb_left)){

   //if so, check to see if there are any instances of obj_item at the mouse cursor
   if (collision_point(mouse_x, mouse_y, obj_item, false, false)){

      item = collision_point(mouse_x, mouse_y, obj_item, false, false);
      item.grab = true;
      //Do whatever else needs to be done

   }

}

//The main limitation I can think of is if you have multiple items under the mouse cursor there's no way to get a specific one with this example code. There are ways to do it but it's hard to write code without knowing exactly how the game should work.
As to what happens afterwards, it depends on what your items do. I'd strongly recommend using an array to track your inventory (as well as setting up your item stats) and then getting those stats is a simple task because we've already given each item instance its own relevant item number.

0 could be an apple. 1 a sword etc etc.
 
Top