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

SOLVED Smear effect

I've come across this before and last time it had to do with instance_create. I can't remember exactly what. Does this look familiar to anyone?
 

kburkhart84

Firehammer Games
I don't know what you are looking for when you talk about a smear effect....if you can provide details or show me a picture or video I can probably help.
 

kburkhart84

Firehammer Games
Gotcha...so you are basically making a trail of the sprite following behind the object. Or is it supposed to be a full screen kind of thing.

For the first option, you could probably store a list of positions that the object has been at for the last some amount of steps, and then draw copies in order(has to be in order to get the effect you want). If you use instance_create() it makes a bunch of copies of the object, which probably isn't what you want unless the trail is kept short. I would also use a cheaper version of the object that doesn't do anything but draw itself for the trailed versions.

For the second method, it seems like you could just draw everything to a surface, and not clear it each frame, and everything you draw would just get on top of what is already drawn. This is similar to not clearing the video buffer in vanilla OpenGL and other engines if you have ever done lower level stuff with graphics.
 
Ok. I have 4 copies of this. They all work except the fourth one, this one that does the smearing. I tried swapping the sprite and s -well, words speak better than action. Just take a copy look its not a lot of code.

StartLogo2 Create Event
GML:
instance_create(700,500, Ring2Bat);

fade_duration =room_speed/2// = 1.5 seconds
alpha_step     = 0.1 / fade_duration // the amount by which to decrease the alpha per step
//alpha_step = 0.1;
movement_speed = 0.7 // the amount of pixels per step it floats
image_alpha = 1.0;
alpha = 0.85;
StartLogo2 Step Event
Code:
    alpha -= alpha_step // decrease alpha



    image_alpha = alpha;
y--;

if (alpha <= 0)
{
  instance_destroy()
}
Ring 2 Bat Create Event

Code:
fade_duration =room_speed// = 1.5 seconds
alpha_step     = 0.1 / fade_duration // the amount by which to decrease the alpha per step
//alpha_step = 0.1;
movement_speed = 0.7 // the amount of pixels per step it floats
image_alpha = 1.0;
alpha = 0.85;
Ring 2 Bat Step Event
Code:
    alpha -= alpha_step // decrease alpha



    image_alpha = alpha;
y--;

if (alpha <= 0)
{
  instance_destroy()
}
Ok that was one of the other ones, the ones that work. This doesn't work:
StartLogo4 Create Event
Code:
instance_create(700,500, Ring3Bat);

fade_duration =room_speed/2// = 1.5 seconds
alpha_step     = 0.1 / fade_duration // the amount by which to decrease the alpha per step
//alpha_step = 0.1;
movement_speed = 0.7 // the amount of pixels per step it floats
image_alpha = 1.0;
alpha = 0.85;
This is Start Logo 4 Step Event
Code:
alpha -= alpha_step // decrease alpha



    image_alpha = alpha;
//y--;

//if (alpha <= 0)
//{
 // instance_destroy()
//}
This is the fourth (one that doesn't work)
RingBat4 Create Event
Code:
    alpha -= alpha_step // decrease alpha



    image_alpha = alpha;
//y--;

//if (alpha <= 0)
//{
 // instance_destroy()
//}
This is the ring bat 4 step event

Code:
    alpha -= alpha_step // decrease alpha



    image_alpha = alpha;
y--;

//if (alpha <= 0)
//{
 // instance_destroy()
//}
And the RingBat 4 Draw
Code:
draw_self();

draw_set_font(CarnivalFont);

draw_text_transformed_color(x+270, y+440, "4", 5, 5, 0, c_black, c_black, c_black, c_black, alpha);
Thoughts?
 

kburkhart84

Firehammer Games
I see that the code in the last one has the instance_destroy() code commented out. It isn't commented out in the other ones.
Code:
//if (alpha <= 0)
//{
 // instance_destroy()
//}
That's what I see different. I'm betting that this is the issue.
 
NO deal. The code for the bat splash screen is almost identical. I copied most of the cost from bat3 to bat4 when it 4 started to malfunction It has to be something outside that is causing that I think,
 

kburkhart84

Firehammer Games
Bat Step 2
Code:
    alpha -= alpha_step // decrease alpha



    image_alpha = alpha;
y--;

if (alpha <= 0)
{
  instance_destroy()
}
Bat 4 step
Code:
    alpha -= alpha_step // decrease alpha



    image_alpha = alpha;
y--;

//if (alpha <= 0)
//{
 // instance_destroy()
//}
This is a straight copy from your post. Do you see how in the second one that the code that destroys them after alpha gets low is commented out? That's a difference, and very possibly what is causing the issue since that object is never getting destroyed going by the code.
 
Yeah I saw it and changed it. So its:

GML:
    alpha -= alpha_step // decrease alpha



    image_alpha = alpha;
y--;

if (alpha <= 0)
{
 instance_destroy()
}
:(
 

kburkhart84

Firehammer Games
So that didn't fix the problem then? I guess you would need to check all the stuff externally. It seems you are somehow creating a lot more instances than you wanted to. Have you checked the debugger to see if that is the case?
 

kburkhart84

Firehammer Games
I recommend it. The debugger is actually really nice despite the software not having features of other engines and languages. You can usually figure out issues using it. It lets you see variables on your instances, etc.. too.
 
@kburkhart84 I traced through the code and no luck. I did notice what thing though,. There are four ring bats, one for each stage, The weird thing is that the one ring bat shows up twice. But I can't see into the code so I can't see where the second 3rd bat is being creating, (edit) I can see in the code but that didn't help . This is so frustrating. The code for RingBat3 and RingBat4 is almost identical and I tried to swap them and they they did the same thing. The fourth always smears.
(edit)
Ok. There is one that isn't showing up in the code. I was right. The StartLogoLevel3. That controller calls the RingBat3. So it has to be instantiated but I search through the code and it doesn't find it
 
Last edited:

kburkhart84

Firehammer Games
You could add debug printing in the create event of that object. If they are all created at the same time it won't help but if they are somehow being created at separate times it may give you a clue.
 

kburkhart84

Firehammer Games
I'm referring to just printing to the debug console, no need to go to a file unless its just more convenient. In this case I don't think it would be necessary. You can use show_debug_message() to print your own stuff to the console. You can do strings, reals, or both(if you combine the numbers into a long string using the string() functions).
 
I think I know where the problem is, I just don't know why.

GML:
var target = noone;
global.game_map++;

switch(global.game_map)
{
    
    case 1: target = FirstLevel; break;
    case 2: target = FirstLevel1B; break;
    case 3: target = FirstLevel1C; break;
    case 4: target = FirstLevel1D; break;
    case 5: target = FirstLevelBOSS; break;
    case 6: target = VideoMap; break;     ///ForestMap
    case 7: target = SecondLevel; break;
    case 8: target = SecondLevelB; break;
    case 9: target = SecondLevelC; break;
    case 10: target = SecondLevelD; break;
    case 11: target = SecondLevelD; break;
    case 12: target = SecondLevelBOSS; break;
    case 13: target = VideoMap; break;    //SnowMap
    case 20: target = ThirdLevel; break;
    case 21: target = ThirdLevelB; break;
    case 22: target = ThirdLevelC; break;
    case 23: target = ThirdLevelD; break;
    case 24: target = ThirdLevelBOSS; break;
    case 25: target = VideoMap; break;   //LavaMap
    case 30: target = FourthLevel;break;
    case 31: target = FourthLevelB;break;
    case 32: target = FourthLevelC;break;
    case 33: target = FourthLevelD;break;
    case 34: target = FourthLevelBOSS;break;
    case 35: target = VideoMap; break;        //JungleMap
    case 40: target = FifthLevel; break;
    case 41: target = FIfthLevelB; break;
    case 42: target = FifthLevelC; break;
    case 43: target = FifthLevelD; break;
    case 44: target = FifthLevelBOSS; break;
    case 45: target = VideoMap; break;        //DesertMap
    case 50: target = SixthLevel; break;
    case 51: target = SixthLevelB; break;
    case 52: target = SixthLevelC; break;
    case 53: target = SixthLevelD; break;
    case 54: target = SixthLevelBOSS; break;
    case 55: target = VideoMap; break;  //LagoonMap
    case 60: target = SeventhLevel; break;
    case 61: target = SeventhLevelB; break;
    case 62: target = SeventhLevelC; break;
    case 63: target = SeventhLevelD; break;
    case 64: target = SeventhLevelBOSS; break;
    case 65: target = VideoMap; break;     //SwampMap
    case 70: target = EightLevel; break;
    case 71: target = EightLevelB; break;
    case 72: target = EightLevelC; break;
    case 73: target = EightLevel1D; break;
    case 74: target = EightLevel1BOSS; break;
    case 75: target = VideoMap;break;        //RuinsMap
    case 80: target = NinthLevel;break;
    case 81: target = NinthLevelB;break;
    case 82: target = NinthLevelC;break;
    case 83: target = NinthLevelD;break;
    case 84: target = VideoMap;break;    //StormMap
    case 90: target = TenthLevel; break;
    case 91: target = TenthLevelB;break;
    case 92: target = TenthLevelC;break;
    case 93: target = TenthLevelD;break;
    case 94: target = TenthLevelBOSS;break;
    case 95: target = VideoMap;break;    //SkyMap
    case 100: target = EleventhLevel;break;
    case 101: target = EleventhLevelB;break;
    case 102: target = EleventhLevelC;break;
    case 103: target = EleventhLevelD;break;
    case 104: target = EleventhLevelBOSS;break;
    case 105: target = VideoMap;break; //SciFiMap
    case 110: target = TwelfthLevel;break;
    case 111: target = TwelfthLevelB;break;
    case 112: target = TwelfthLevelC;break;
    case 113: target = TwelfthLevelD;break;
    case 114: target = TwelfthLevelBOSS;break;
}

room_goto(target);

//0 is the indicator , the map
//target is the map to go to
 

kburkhart84

Firehammer Games
The thing that looks like an error to me there is that your target won't work right since you are skipping numbers. You are doing a ++ on the target which only adds one, but in that array you skip number all over, going from 35 to 40 with nothing in between. I'm not saying this is causing the smear affect, and it doesn't seem to me like it would...but I though I'd mention that it doesn't look right.
 
So..something clobbered my fourth level. Fixed now, My room was was just a blank room. I'm not sure why that smear effect
was occur. Maybe because the fact that there was 3 stages, Oh well. THanks for you hep @kburkhart84
 
If your room doesn't have a background, it's equivalent to stopping the application surface from being cleared. Every frame, when the game draws something to the screen, that drawing remains in place going into future frames, meaning that if an object moves each frame of its movement remains drawn and thus there's a "smear effect" following any movement.
 
So which level is this in? One of the things you could try is checking if the room exists before the switch statement:
Code:
var target = noone;
global.game_map++;
if (room_exists(global.game_map)) {
   show_debug_message("Room exists");
}
else {
   show_debug_message("Room does not exist");
}
And see what message is sent when you get to the messed up part.

I assume that this code is running in a trigger that then uses target to go to the correct room? I'm curious as to how global.game_map is being used elsewhere? Is it literally just an index counter that goes up in that one line? Also, there's some inconsistencies in the values that target is set to in the switch statement, such as:
Code:
case 10: target = SecondLevelD; break;
case 11: target = SecondLevelD; break;
Are these intentional? There's other inconsistencies in there besides those ones.
 
Last edited:
Hi. I've got a smear problem again. I made sure the background exists. This is the transition map code:

GML:
target = noone;
global.game_map++;

switch(global.game_map)
{
   
    case 1: target = FirstLevel; break;
    case 2: target = FirstLevel1B; break;
    case 3: target = FirstLevel1C; break;
    case 4: target = FirstLevel1D; break;
    case 5: target = FirstLevelBOSS; break;
    case 6: target = VideoMap; break;     ///ForestMap
    case 7: target = SecondLevel; break;
    case 8: target = SecondLevelB; break;
    case 9: target = SecondLevelC; break;
    case 10: target = SecondLevelD; break;
    case 11: target = SecondLevelBOSS; break;
    case 12: target = VideoMap; break;
   
    case 20: target = ThirdLevel; break;
    case 21: target = ThirdLevelB; break;
    case 22: target = ThirdLevelC; break;
    case 23: target = ThirdLevelD; break;
    case 24: target = ThirdLevelBOSS; break;
    case 25: target = VideoMap; break;   //LavaMap
    case 30: target = FourthLevel;break;
    case 31: target = FourthLevelB;break;
    case 32: target = FourthLevelC;break;
    case 33: target = FourthLevelD;break;
    case 34: target = FourthLevelBOSS;break;
    case 35: target = VideoMap; break;        //JungleMap
    case 40: target = FifthLevel; break;
    case 41: target = FIfthLevelB; break;
    case 42: target = FifthLevelC; break;
    case 43: target = FifthLevelD; break;
    case 44: target = FifthLevelBOSS; break;
    case 45: target = VideoMap; break;        //DesertMap
    case 50: target = SixthLevel; break;
    case 51: target = SixthLevelB; break;
    case 52: target = SixthLevelC; break;
    case 53: target = SixthLevelD; break;
    case 54: target = SixthLevelBOSS; break;
    case 55: target = VideoMap; break;  //LagoonMap
    case 60: target = SeventhLevel; break;
    case 61: target = SeventhLevelB; break;
    case 62: target = SeventhLevelC; break;
    case 63: target = SeventhLevelD; break;
    case 64: target = SeventhLevelBOSS; break;
    case 65: target = VideoMap; break;     //SwampMap
    case 70: target = EightLevel; break;
    case 71: target = EightLevelB; break;
    case 72: target = EightLevelC; break;
    case 73: target = EightLevel1D; break;
    case 74: target = EightLevel1BOSS; break;
    case 75: target = VideoMap;break;        //RuinsMap
    case 80: target = NinthLevel;break;
    case 81: target = NinthLevelB;break;
    case 82: target = NinthLevelC;break;
    case 83: target = NinthLevelD;break;
    case 84: target = NinthLevelBOSS;break;
    case 85: target = VideoMap;break;    //StormMap
    case 90: target = TenthLevel; break;
    case 91: target = TenthLevelB;break;
    case 92: target = TenthLevelC;break;
    case 93: target = TenthLevelD;break;
    case 94: target = TenthLevelBOSS;break;
    case 95: target = VideoMap;break;    //SkyMap
    case 100: target = EleventhLevel;break;
    case 101: target = EleventhLevelB;break;
    case 102: target = EleventhLevelC;break;
    case 103: target = EleventhLevelD;break;
    case 104: target = EleventhLevelBOSS;break;
    case 105: target = VideoMap;break; //SciFiMap
    case 110: target = TwelfthLevel;break;
    case 111: target = TwelfthLevelB;break;
    case 112: target = TwelfthLevelC;break;
    case 113: target = TwelfthLevelD;break;
    case 114: target = TwelfthLevelBOSS;break;
}

room_goto(target);

//0 is the indicator , the map
//target is the map to go to
//we
And this is the smear:
Does anyone remember how we fixed this?
 

Attachments

Last edited:
Is the smear only with that ghost thing or for the entire room? I'm somewhat doubtful that the effect is caused by the code you posted in particular, does it only happen in a specific room? How are you setting up that room when you're entering it? Does your background have any transparency in it? Also is there any reason why you are skipping cases in that switch statement? Seems like that would be an easy way to have something weird happen to the target variable. Try chucking in:
Code:
default:
   show_debug_message("Target is not being assigned a value as global.game_map was not set to one of the cases in the switch");
break;
After your defined cases in the switch statement and see if that debug message gets triggered before any weirdness happens.
 
Is the smear only with that ghost thing or for the entire room? I'm somewhat doubtful that the effect is caused by the code you posted in particular, does it only happen in a specific room? How are you setting up that room when you're entering it? Does your background have any transparency in it? Also is there any reason why you are skipping cases in that switch statement? Seems like that would be an easy way to have something weird happen to the target variable. Try chucking in:
Code:
default:
   show_debug_message("Target is not being assigned a value as global.game_map was not set to one of the cases in the switch");
break;
After your defined cases in the switch statement and see if that debug message gets triggered before any weirdness happens.

The smear ghost is only on the ghost thing. When this happened before it was just one smear too. Its happneing one room as far I can tell. No transparency. The skipping thing is to make things more manageable. Every set of stages is a set of 10. It worked worked, not sure why it wouldn't now.

(Edit)

Checked it out in the debugger and it ooks like what we are thinking, it is creating ghosts over and over and over.

(Edit)

I think this is the culprit....somewhere in this code:

GML:
if (mouse_check_button_pressed(mb_right))
    {
        inst = instance_position(mouse_x, mouse_y, BrainParentObject)
        inst2 = instance_position(mouse_x,mouse_y, BOSSESParent)
        inst3 = instance_position(mouse_x, mouse_y, SpecialBrains)
        inst4 = instance_position(mouse_x, mouse_y, FranksParent)
        
        if (SpecialBrains != noone)
        {
            with (SpecialBrains)
            {
                if (hp <= 1000)
                {
                    hp_minus = irandom_range(200, 300)
                    hp -= hp_minus
                    floater = instance_create_depth(x+10, y-10, -1700, DamageIndicatorObject);
                    floater.text = string(hp_minus);
                    if (hp <= 0)
                    {               
                        instance_create_depth(x, y, -1100,DeadBrainObject);       
                        instance_create_depth(x-150, y-20, -1100, FadingGemObject);
                        audio_play_sound(DieingBrainSound, 20, false);       
                        instance_destroy()
                    }
                }
            }
            
                
                
        }
        
        
        if (inst != noone || inst2 != noone  || inst3 != noone || inst4 != noone)
        {
        
        /*
        for (i=0;i<30;i++)
        {
            show_debug_message("Getting ready to draw lightning")
            //draw_set_color(c_white)
            //draw_lightning_simple(x,y,mouse_x,mouse_y,32,60)//render lightning with a single line of code!
            draw_lightning_color(path[0], 20, 300, c_blue, c_orange, 1.0, path[1], p_metal, fx.particles, weighting);
        }*/
        
        global.tgt_x = mouse_x;
        global.tgt_y = mouse_y;
        
        
        for (i=0;i<room_speed/7;i++)
        {
            instance_create(global.tgt_x, global.tgt_y,o_lightning_hue)
        }
        
        
        }
}
/*
 

kburkhart84

Firehammer Games
I don't see any creation of any object called "ghost" anything in that code. I don't see any calls to other functions either except GM functions. I don't think that code is it. You can always search by text for the name of the ghost object to see exactly where all they are being created from and go from there.
 
I don't see any creation of any object called "ghost" anything in that code. I don't see any calls to other functions either except GM functions. I don't think that code is it. You can always search by text for the name of the ghost object to see exactly where all they are being created from and go from there.
There is no instance of ghost that I could find either. However if you look at the debugger there are dozens instances of that ghost instance making it evident that the problem to be whatever is causing the instantiate the ghost. Suggestions?

Run through of the debug:
 

Attachments

chamaeleon

Member
My guess is yet another mistaken name being used in in an instance create call with something that is not an object id, but has the same value as the asset index of FrankGhostObject, if FrankGhostObject is not explicitly created by some relevant line of code. At any statement in the create event for FrankGhostObject put a breakpoint, run the game in debug mode, and when the object is created look at the call stack to see exactly which line creates the instance. If that line does not use FrankGhostObject as the object to create, you will presumably be able to use your programming skills to both change it to the proper object and ensure that the line is executed exactly as many times as it is supposed to.
 
At the very bottom:
Code:
global.tgt_x = mouse_x;
        global.tgt_y = mouse_y;
        
        
        for (i=0;i<room_speed/7;i++)
        {
            instance_create(global.tgt_x, global.tgt_y,o_lightning_hue)
        }
        
        
        }
}
Also, I'm very inclined to agree with chamaeleon, their answer was my first thought as well. If you have no reference to creating FrankGhostObject anywhere in your code (which, might I say, is kind of confusing, why have an object that you are not using?) then you are likely using a variable to create an instance and that variable just happens to hold a value which is the same internal object number as FrankGhostObject, thus spawning an instance of that. I would do exactly what chamaeleon said if I were in your position.
 
Ok. I think you are talking about two diferent things, What I'm understanding is that i'm using
an instance_create_depth(0,0,-1100, FrankGhostObject) when FrankGhostObject is actually a sprite,
along those lines??
 

chamaeleon

Member
Ok. I think you are talking about two diferent things, What I'm understanding is that i'm using
an instance_create_depth(0,0,-1100, FrankGhostObject) when FrankGhostObject is actually a sprite,
along those lines??
We mean (assuming this line ends up creating an bunch of FrankGhostObject instances incorrectly).
GML:
instance_create_depth(0,0,-1100, AnythingThatIsNotAFrankGhostObjectButHasTheSameValueAsTheFrankGhostObjectAssetId);
By putting a breakpoint in the Create event in FrankGhostObject, run the program, and look at the function call stack in the debugger, you should see what line calls the instance create function, which will tell you A) what asset or variable is passed and you should then replace it with the proper parameter, and B) give you an indication when it happens (once every step without conditions to prevent it from happening more than one time, etc.)
 
Top