GMS 2 [Solved] Bug: an object suddenly disappears and others draw themselves every frame

jiangca

Member
Hi, I'm new to gamemaker and have been using drag and drop to create a math shooting game. (I have also converted some drop and drop code to gml). The player is shown the solution and five different math equations, one of which equals the solution. They must shoot a bullet at the object that holds the equation to answer the question.

Behavior is normal until the player answers 11 questions correctly (score increase to 110 points). Then the player object disappears (player is normally pictured right under the solution text). However, the object of the player still exists because you can still move left to right and shoot bullets. Getting one more question right causes the fish in the background and any additional bullets to draw every frame as they move. The drawn score also stops updating even though the variable that contains the score still functions normally.
Screen Shot 2020-11-19 at 4.50.24 PM.png
This bug only occurs the first time the game is run from gamemaker. Going back to the main menu within the game and playing again after witnessing the bug does not cause this error to occur. However, if the player returns to the main menu and plays again after getting 4 questions correct, this bug appears after the player gets 7 questions right (effectively adding back up to 11 correct questions). Additionally, only correct answers affect this bug. Answering 11 questions incorrectly, or even 20 incorrect and 11 correct, does not cause this to happen.

Any insight into what is causing this error would be greatly appreciated.
Thanks!
 

flyinian

Member
If you post your code that may be in question we may be able to help more.

The code from the player object and code from any other objects that is having issues.
 

Nidoking

Member
What other things happen when the player answers questions correctly? Is something other than the score accumulating? I notice that you have a "Level" and "Target" listed. I don't think you're going to get much help without providing more detailed information.
 

jiangca

Member
@flyinian
The player object is called Obj_Sally
Code:
//create event for Obj_Sally

// Cooldown for bullet
Cooldown = 0;
Code:
//step event for Obj_Sally
direction = point_direction(x, y, x + 0, y + 0);

image_angle = 0;

// Shoot bullet with cooldown
var l3166FABF_0;
l3166FABF_0 = keyboard_check(vk_space);
if (l3166FABF_0)
{
    if(Cooldown <= 0)
    {
        instance_create_layer(Obj_Sally.x, Obj_Sally.y, "Instances", obj_bullet);
  
        audio_play_sound(snd_bullet, 0, 0);
  
        Cooldown = 50;
    }
}

Cooldown += -1;
Code:
//Obj_Sally key down left event
// Use left arrow to move if in room boundry.
if(x>0)
{
    x += -5;
    y += 0;
}

//Obj_Sally key down right event
// Use right arrow to move if in room boundry.
if(x<room_width)
{
    x += 5;
    y += 0;
}
The fish are part of objects named obj_randomfish_right and obj_randomfish_left (only difference is the direction they travel). Each different type of fish has the same code but a different sprite.
Code:
//obj_randomfish create event
cooldown = 0; //set cooldown for random generation time period

random_fish = irandom_range(0,3); //select one of the 4 types of fish to generate
Code:
//obj_randomfish step event
if(random_fish == 0)
{
    if(cooldown == 0)
    {
        instance_create_layer(x + 0, y + 0, "Background_instances", obj_schoolfish_left);
  
        cooldown = irandom_range(200,500);
  
        random_fish = irandom_range(0,3);
    }

    cooldown += -1;
}

else
{
    if(random_fish == 1)
    {
        if(cooldown <= 0)
        {
            instance_create_layer(x + 0, y + 0, "Background_instances", obj_greenfish_left);
      
            cooldown = irandom_range(200,500);
      
            random_fish = irandom_range(0,3);
        }
  
        cooldown += -1;
    }

    else
    {
        if(random_fish == 2)
        {
            if(cooldown <= 0)
            {
                instance_create_layer(x + 0, y + 0, "Background_instances", obj_shark_left);
          
                cooldown = irandom_range(200,500);
          
                random_fish = irandom_range(0,3);
            }
      
            cooldown += -1;
        }
  
        else
        {
            if(random_fish == 3)
            {
                if(cooldown <= 0)
                {
                    instance_create_layer(x + 0, y + 0, "Background_instances", obj_bluefish_left);
              
                    cooldown = irandom_range(200,500);
              
                    random_fish = irandom_range(0,3);
                }
          
                cooldown += -1;
            }
        }
    }
}
Code:
//obj_bluefish, obj_greenfish, obj_schoolfish, obj_shark step event

hspeed = 2;

x += 0;
y += 0;

direction = choose(180);
The bubbles with equations are obj_random.
Code:
//obj_random create event
randomize();

with(other) {
temp = global.range; //global.range is either 10, 20, 30 depending on easy/medium/hard difficulty selected

}

list_operations = ds_list_create();

if(global.divide_clicked == 1) //checks if player wants to play with division
{
    value_1 = irandom(global.range);

    value_2 = irandom(global.range);

    while(true) //make sure division can be done without remainder
    {
        if((value_2 ==0) || (value_1 % value_2 !=0))
        {
            value_2 = irandom_range(1, value_1);
        }
  
        else
        {
            divide = value_1/value_2;
      
            dividea[0] = value_1;
            dividea[1] = value_2;
            dividea[2] = divide;
            dividea[3] = 0;   //used to know that / will be drawn on screen
      
            ds_list_add(list_operations, dividea);
      
            break;
        }
    }
}

if(global.add_clicked == 1) //checks if player wants to play with divide
{
    value_1 = irandom(global.range);

    value_2 = irandom(global.range);

    add = value_1+value_2;

    adda[0] = value_1;
    adda[1] = value_2;
    adda[2] = add;
    adda[3] = 1; //used to know that + will be drawn on screen

    ds_list_add(list_operations, adda);
}

if(global.subtract_clicked == 1) //checks if player wants to play with subtraction
{
    value_1 = irandom(global.range);

    value_2 = irandom(global.range);

    if(value_1 < value_2) //make sure there won't be negative answer values
    {
        value_temp = value_1;
  
        value_1 = value_2;
  
        value_2 = value_temp;
    }

    subtract = value_1-value_2;

    subtracta[0] = value_1;
    subtracta[1] = value_2;
    subtracta[2] = subtract;
    subtracta[3] = 2; //used to know that - will be drawn on screen

    ds_list_add(list_operations, subtracta);
}

if(global.multiply_clicked == 1) //check if player wants to play with multiplication
{
    value_1 = irandom(global.range);

    value_2 = irandom(global.range);

    multiply = value_1*value_2;

    multiplya[0] = value_1;
    multiplya[1] = value_2;
    multiplya[2] = multiply;
    multiplya[3] = 3; //used to know that x will be drawn on screen

    ds_list_add(list_operations, multiplya);
}

this_answer = ds_list_find_value(list_operations, irandom(ds_list_size(list_operations)-1)); //an array containing one of the bubble's equation

answer = this_answer[2];

layer_sequence_destroy(list_operations);
Code:
//obj_random draw event
//looks messy but its just drawing the first value, drawing the second value, drawing operation
//there are many if statements because I was trying to center the equation in the bubble

draw_self();

draw_set_colour($FF000000 & $ffffff);
var l405F50FD_0=($FF000000 >> 24);
draw_set_alpha(l405F50FD_0 / $ff);

draw_set_font(fnt_score);

if(global.add_clicked == 1)
{
    if(answer == add)
    {
        if(this_answer[3] == 1)
        {
            draw_text(id.x, id.y, string("+") + "");
        }
  
        if(this_answer[0] <= 9)
        {
            draw_text(-35+id.x, id.y,  + string(this_answer[0]));
        }
  
        else
        {
            if(this_answer[0] == 11)
            {
                draw_text(-40+id.x, id.y,  + string(this_answer[0]));
            }
      
            else
            {
                if(this_answer[0] == 21)
                {
                    draw_text(-50+id.x, id.y,  + string(this_answer[0]));
                }
          
                else
                {
                    if(this_answer[0] > 19)
                    {
                        draw_text(-65+id.x, id.y,  + string(this_answer[0]));
                    }
              
                    else
                    {
                        draw_text(-50+id.x, id.y,  + string(this_answer[0]));
                    }
                }
            }
        }
  
        if(this_answer[1] <= 9)
        {
            draw_text(40+id.x, id.y,  + string(this_answer[1]));
        }
  
        else
        {
            draw_text(35 + id.x, id.y,  + string(this_answer[1]));
        }
    }
}

if(global.subtract_clicked == 1)
{
    if(answer == subtract)
    {
        if(this_answer[3] == 2)
        {
            draw_text(5+id.x, id.y, string("-") + "");
        }
  
        if(this_answer[0] <= 9)
        {
            draw_text(-35+id.x, id.y,  + string(this_answer[0]));
        }
  
        else
        {
            if(this_answer[0] == 11)
            {
                draw_text(-40+id.x, id.y,  + string(this_answer[0]));
            }
      
            else
            {
                if(this_answer[0] == 21)
                {
                    draw_text(-50+id.x, id.y,  + string(this_answer[0]));
                }
          
                else
                {
                    if(this_answer[0] > 19)
                    {
                        draw_text(-65+id.x, id.y,  + string(this_answer[0]));
                    }
              
                    else
                    {
                        draw_text(-50+id.x, id.y,  + string(this_answer[0]));
                    }
                }
            }
        }
  
        if(this_answer[1] <= 9)
        {
            draw_text(40+id.x, id.y,  + string(this_answer[1]));
        }
  
        else
        {
            draw_text(35 + id.x, id.y,  + string(this_answer[1]));
        }
    }
}

if(global.multiply_clicked == 1)
{
    if(answer == multiply)
    {
        if(this_answer[3] == 3)
        {
            draw_text(5+id.x, id.y, string("x") + "");
        }
  
        if(this_answer[0] <= 9)
        {
            draw_text(-35+id.x, id.y,  + string(this_answer[0]));
        }
  
        else
        {
            if(this_answer[0] == 11)
            {
                draw_text(-40+id.x, id.y,  + string(this_answer[0]));
            }
      
            else
            {
                if(this_answer[0] == 21)
                {
                    draw_text(-50+id.x, id.y,  + string(this_answer[0]));
                }
          
                else
                {
                    if(this_answer[0] > 19)
                    {
                        draw_text(-65+id.x, id.y,  + string(this_answer[0]));
                    }
              
                    else
                    {
                        draw_text(-50+id.x, id.y,  + string(this_answer[0]));
                    }
                }
            }
        }
  
        if(this_answer[1] <= 9)
        {
            draw_text(40+id.x, id.y,  + string(this_answer[1]));
        }
  
        else
        {
            draw_text(35 + id.x, id.y,  + string(this_answer[1]));
        }
    }
}

if(global.divide_clicked == 1)
{
    if(answer == divide)
    {
        if(this_answer[3] == 0)
        {
            draw_text(id.x, id.y, string("/") + "");
        }
  
        if(this_answer[0] <= 9)
        {
            draw_text(-35+id.x, id.y,  + string(this_answer[0]));
        }
  
        else
        {
            if(this_answer[0] == 11)
            {
                draw_text(-40+id.x, id.y,  + string(this_answer[0]));
            }
      
            else
            {
                if(this_answer[0] == 21)
                {
                    draw_text(-50+id.x, id.y,  + string(this_answer[0]));
                }
          
                else
                {
                    if(this_answer[0] > 19)
                    {
                        draw_text(-65+id.x, id.y,  + string(this_answer[0]));
                    }
              
                    else
                    {
                        draw_text(-50+id.x, id.y,  + string(this_answer[0]));
                    }
                }
            }
        }
  
        if(this_answer[1] <= 9)
        {
            draw_text(40+id.x, id.y,  + string(this_answer[1]));
        }
  
        else
        {
            draw_text(35 + id.x, id.y,  + string(this_answer[1]));
        }
    }
}
The purple colored bubble is obj_bullet

Code:
//obj_bullet's step event
vspeed = -5;

//obj_bullet's collision with obj_random event
temp = global.objective;

if(global.createscore == 1) //if in gameplay mode
{
    temp = global.points;

    temp = global.target;

    temp = global.target_counter;

    // Check if the bubble (instance of obj_random) obj_bullet collided
    // with does not contain the equation whose answer equals the displayed
    // target answer (global.objective)
    if(!(variable_instance_get(instance_place(id.x, id.y, obj_random), "answer") == global.objective))
    {
        if(global.points <= 0)
        {
            // don't add any points if the score is less than or
            // equal to 0 and the wrong bubble is shot
            global.points += 0;
        }
  
        else
        {
            // remove 10 points from global.points if the shot
            // bubble does not contain the target solution and the
            // score is greater than 0
            global.points += -10;
        }
  
        // Player loses life if wrong answer shot.
        global.playerlives += -1;
  
        // Destroy the bullet.
        with(obj_bullet) instance_destroy();
  
        // Turn the bubble into a grey bubble.
        with(other) instance_change(Obj_gbubble, true);
  
        audio_play_sound(snd_bubblepop, 0, 0);
  
        if(global.playerlives > 0)
        {
            // Wrong message pops up to give feedback.
            instance_create_layer(380, 415, "Instances", Obj_wrongmessage);
        }
  
        else
        {
            // If out of lives go back to main menu.
            room_goto(Title_screen);
        }
    }

    else
    {
        // If the bubble's equation equals global.objective, add 10 points to
        // global.points
        global.points += 10;
  
        // Destroys all the bubbles, bullet, and answer.
        with(obj_bullet) instance_destroy();
  
        with(obj_random) instance_destroy();
  
        with(obj_answer) instance_destroy();
  
        audio_play_sound(snd_bubblepop, 0, 0);
  
        if(global.playerlives > 0)
        {
            // Give correct message as feeback.
            instance_create_layer(380, 415, "Instances", obj_correctmessages);
        }
  
        if(global.points == global.target)
        {
            // Won the gamr.
            if(global.target == 750)
            {
                // Create endong room.
                room_goto(menu_room);
            }
      
            // After this add the dolphin sequence
            else
            {
                // Increase the target for the next level.
                global.target = global.target + (50*global.target_counter);
          
                global.target_counter = global.target_counter+1;
          
                // Increase the level
                global.level += 1;
          
                // Reset player lives to three.
                global.playerlives = 3;
            }
        }
  
  
  
  
  
        instance_create_layer(672, 128, "Instances", obj_random);
  
  
  
  
  
        // Generate new answer.
        instance_create_layer(x + 0, y + 0, "Instances", obj_answer);
  
        with(Obj_gbubble) instance_destroy();
    }
}

else //if in freeplay mode
{
    // Check if the bubble (instance of obj_random) obj_bullet collided
    // with does not contain the equation whose answer equals the displayed
    // target answer (global.objective)
    if(!(variable_instance_get(instance_place(id.x, id.y, obj_random), "answer") == global.objective))
    {
        with(obj_bullet) instance_destroy();
  
        with(other) instance_change(Obj_gbubble, true);
  
        audio_play_sound(snd_bubblepop, 0, 0);
    }

    else
    {
        with(obj_bullet) instance_destroy();
  
        with(obj_random) instance_destroy();
  
        with(obj_answer) instance_destroy();
  
        audio_play_sound(snd_bubblepop, 0, 0);
  
        instance_create_layer(128, 320, "Instances", obj_random);
  
        instance_create_layer(384, 192, "Instances", obj_random);
  
        instance_create_layer(672, 128, "Instances", obj_random);
  
        instance_create_layer(960, 192, "Instances", obj_random);
  
        instance_create_layer(1216, 320, "Instances", obj_random);
  
        instance_create_layer(x + 0, y + 0, "Instances", obj_answer);
  
        with(Obj_gbubble) instance_destroy();
    }
}
"Solution: __" is controlled by obj_answer
Code:
//obj_answer create event
list = ds_list_create();

for(i = 0; i < instance_number(obj_random); i += 1) {
    ds_list_add(list, variable_instance_get(instance_find(obj_random, i), "answer"));
}

global.objective = ds_list_find_value(list, irandom(ds_list_size(list)-1));

layer_sequence_destroy(list);

//obj_answer draw event
draw_text(-90+ Obj_Sally.x, -180+ Obj_Sally.y, string("Solution: ") + string(global.objective));
"Score: __" controlled by obj_score
Code:
//obj_score create event
global.points = 0;

global.target = 50;

global.target_counter = 2;

global.level = 1;

//obj_score draw event
draw_set_font(fnt_score);

if(global.createscore == 1) //if in gameplay mode
{
    draw_text(1075, 96, string("Score: ") + string(global.points));

    draw_text(64, 96, string("Target: ") + string(global.target));

    draw_text(64, 32, string("Level: ") + string(global.level));
}
Three starfish normally pictured in the top right above the score (they have disappeared as well) are controlled by Obj_Lives
Code:
//Obj_Lives create event
// Player starts with three lives.
global.playerlives = 3;

//Obj_Lives draw event
var myfirst_0 = sprite_get_width(Spr_Lives);
var myfirst_1 = 0;
for(var myfirst_2 = global.playerlives; myfirst_2 > 0; --myfirst_2) {
    draw_sprite(Spr_Lives, 0, 1100 + myfirst_1, 60);
    myfirst_1 += myfirst_0;
}
 
Last edited:

jiangca

Member
What other things happen when the player answers questions correctly? Is something other than the score accumulating? I notice that you have a "Level" and "Target" listed. I don't think you're going to get much help without providing more detailed information.
When the player answers a question correctly the equation bubbles will regenerate to have new equations/a new solution, and a correct message ("Correct! Great job!") is displayed. The score increases 10 points each time the player is right.

Level tells the player what level out of 5 they are on. Target is the target score they are trying to reach to pass the level.
Level 1 --> Target 50
Level 2 --> Target 150
Level 3 --> Target 300
Level 4 --> Target 500
Level 5 --> Target 750
These two shouldn't be causing the issue because they were added after the bug was already occuring.
 

jiangca

Member
Why are you doing this? How have you correctly chosen the ds_list_create function to create lists, but you couldn't find the ds_list_destroy function to destroy them?
I'm not sure. I used the convert to gml function on dnd code. The dnd code box I used was the "Destroy Sequence" one
 

jiangca

Member
Why would you use that instead of the "Free Data Structure" action that's called out specifically on the Create List Manual page?
That's a mistake on my part. I was following the advice I saw in another forum question, and I didn't change it enough to fit my game. Changing it to Free Data Structure did fix the issue. Thanks for all the help!
 
Top