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

GML About showing a portion of an alpha=0 sprite

C

create_event@

Guest
Just a potential graphic component i'd like to add, if possible.
I've got an energy shield that defaults as 0 alpha. When hit by an attack, the whole sprite gains a small increase to it's alpha, which then fades at a slower rate. More hits makes it more and more visible, with a cap at .5 alpha. Is there a way to only increase the alpha only in, say a 10 pixel radius of the hit?
 

jo-thijs

Member
Just a potential graphic component i'd like to add, if possible.
I've got an energy shield that defaults as 0 alpha. When hit by an attack, the whole sprite gains a small increase to it's alpha, which then fades at a slower rate. More hits makes it more and more visible, with a cap at .5 alpha. Is there a way to only increase the alpha only in, say a 10 pixel radius of the hit?
How is this?
http://www.mediafire.com/file/2up01ypb2rr66kx/GMC_force_field_alpha_effect.gmz

The code is of poor quality (performance wise and modifiability wise), for which my apologies.

The idea is that you use a surface to keep track of all the alpha values on the energy shield.
You can use blend modes to perform arithmetic on the alpha values.

I also included a "hit_array" structure that allows some flexibility with fading in over time.

Let me know if this was helpful and if you have any questions about it.
 

PlayerOne

Member
I'm not sure about the radius. However you can use this code to add alpha to the shield and have it increase when hit but decrease when greater than 0.

create:
Code:
img_alpha=0
step:
Code:
if position_meeting(x,y,obj_missile) && img_alpha<0.5{img_alpha+=0.005}
if img_alpha>0{img-=0.001}
img_alpha is the variable for point of reference to increase or decrease upon being hit. This method is more caveman level but it depends on how you draw your shield or if it's a separate object/layer.
 
Last edited:
C

create_event@

Guest
How is this?
http://www.mediafire.com/file/2up01ypb2rr66kx/GMC_force_field_alpha_effect.gmz

The code is of poor quality (performance wise and modifiability wise), for which my apologies.

The idea is that you use a surface to keep track of all the alpha values on the energy shield.
You can use blend modes to perform arithmetic on the alpha values.

I also included a "hit_array" structure that allows some flexibility with fading in over time.

Let me know if this was helpful and if you have any questions about it.
I really super appericiate this, but I'm using GM8.1 at the moment, so it doesn't look like I can use this file. I probably should have mentioned this fact earlier, but i didn't think somebody would be kind enough to actually create an example for me.

Also your talk of surfaces, blend modes, and arrays frightens me. :) I'm trying to work out how I'll create the actual mechanics before doing anything fancy. I'm just working on the coding for damage/destruction right now. I've already made probably 90% of the sprites I need.
 
W

whale_cancer

Guest
Also your talk of surfaces, blend modes, and arrays frightens me. :) I'm trying to work out how I'll create the actual mechanics before doing anything fancy. I'm just working on the coding for damage/destruction right now. I've already made probably 90% of the sprites I need.
You might want to put this kind of graphical effect on the backburner for now then. I can't see a way you can do this without using a surface. Now, surfaces aren't that hard so you could instead do some surface tutorials and figure that out first. However, applying this kind of effect is than just the basic level of GM coding.

The basic logic behind using a surface to solve this problem is you draw your shield on the surface. You then draw your surface on your player as appropriate. When the shield is hit, you figure out the x, y coordinates relative to the surface. You then manipulate the surface to change the transparency (along the lines jo-thijs suggests).
 

jo-thijs

Member
I really super appericiate this, but I'm using GM8.1 at the moment, so it doesn't look like I can use this file. I probably should have mentioned this fact earlier, but i didn't think somebody would be kind enough to actually create an example for me.
Well, luckily I wrote the example so that it was almost immediately portable to GM8.1, so here you go:
http://www.mediafire.com/file/21yseodxo2z2dtx/GMC_force_field_alpha_effect.gm81

Also your talk of surfaces, blend modes, and arrays frightens me.
Oh, then you're definitely going to be afraid of the example I linked to ... sorry.

Arrays, surfaces and blend mode aren't that difficult of a concept though.

Arrays:
Suppose you have variables with the following names: myvar1, mayvar2, myvar3, ..., myvar100.
You can imagine maintaining so many individual variables is not handy at all.
Well, arrays combine multiple variables in 1 name.
The variables would become: myvar[0], myvar[1], myvar[2], ..., myvar[99].
You can now use these in just the same way you would use normal variables.
However, you can do even more!
Take a look at this example:
Code:
myvar[0] = 0;
myvar[1] = "hello!";
myvar[2] = 6;
k = 5;
show_message(myvar[k-4]);
Put this in a create event and run it, you'll see the message "Hello!" appear.
Do you understand why?

In GM8.1 there isn't really much more to arrays than just that.
There are a couple of awkward details, but those aren't important for now.

There are also 2D arrays.
What I described above are 1D arrays, you provide 1 index to the array.
In a 2D array, you provide 2 indices:
Code:
a[0,0] = 5;
a[0,1] = 6;
a[1,0] = 9;
a[1,1] = 0;
Surfaces:
You usually draw things to the screen.
Surfaces are invisible canvases where you can draw to instead.
You create a surface, which is a recangle (using surface_create).
You tell GameMaker you want to start drawing on it (using surface_set_target).
You perform some draw functions (they don't need to be in the draw event for suraces).
Everything you draw, gets drawn to the surface.
You then tell GameMaker you're currently done drawing to the surface (using surface_reset_target).
You can then draw the surface whenever you want to te screen (using functions such as draw_surface).
When you don't need the surface anymore, you can remove it and free its memory (using surface_free).

Blend modes:
They change how alpha values have an effect on colors.
They're a bit more of an advanced feature though.
Some cool effects you can achieve with blend modes is inverting the colos of an area on the screen.


Now, I suggest you'd first experiment a bit with how arrays work and can be used, as they are a really handy feature.
Also take a look at for-loops, they work very nicely together with arrays.
 
C

create_event@

Guest
:eek:
Well, luckily I wrote the example so that it was almost immediately portable to GM8.1, so here you go:
http://www.mediafire.com/file/21yseodxo2z2dtx/GMC_force_field_alpha_effect.gm81


Oh, then you're definitely going to be afraid of the example I linked to ... sorry.

Arrays, surfaces and blend mode aren't that difficult of a concept though.

Arrays:
Suppose you have variables with the following names: myvar1, mayvar2, myvar3, ..., myvar100.
You can imagine maintaining so many individual variables is not handy at all.
Well, arrays combine multiple variables in 1 name.
The variables would become: myvar[0], myvar[1], myvar[2], ..., myvar[99].
You can now use these in just the same way you would use normal variables.
However, you can do even more!
Take a look at this example:
Code:
myvar[0] = 0;
myvar[1] = "hello!";
myvar[2] = 6;
k = 5;
show_message(myvar[k-4]);
Put this in a create event and run it, you'll see the message "Hello!" appear.
Do you understand why?

In GM8.1 there isn't really much more to arrays than just that.
There are a couple of awkward details, but those aren't important for now.

There are also 2D arrays.
What I described above are 1D arrays, you provide 1 index to the array.
In a 2D array, you provide 2 indices:
Code:
a[0,0] = 5;
a[0,1] = 6;
a[1,0] = 9;
a[1,1] = 0;
Surfaces:
You usually draw things to the screen.
Surfaces are invisible canvases where you can draw to instead.
You create a surface, which is a recangle (using surface_create).
You tell GameMaker you want to start drawing on it (using surface_set_target).
You perform some draw functions (they don't need to be in the draw event for suraces).
Everything you draw, gets drawn to the surface.
You then tell GameMaker you're currently done drawing to the surface (using surface_reset_target).
You can then draw the surface whenever you want to te screen (using functions such as draw_surface).
When you don't need the surface anymore, you can remove it and free its memory (using surface_free).

Blend modes:
They change how alpha values have an effect on colors.
They're a bit more of an advanced feature though.
Some cool effects you can achieve with blend modes is inverting the colos of an area on the screen.


Now, I suggest you'd first experiment a bit with how arrays work and can be used, as they are a really handy feature.
Also take a look at for-loops, they work very nicely together with arrays.
...
:eek:
...
You are super helpful. It's too late right now for me to really look at this, but I'll give it a very careful look tomorrow after work, and see if I can make sense of it. I've tried arrays before (I forget what for, I just know I'll need the same coding, so I'll have to dig it up), but I've tried to stay away from them because I'm not entirely sure how to use them for what I want to do. I don't have the time I once did to give the manual a thorough reading.:(
 

Neptune

Member
I have a lazy way, you could make an opaque sprite that represents a small portion of your energy shield when its hit.
And with a little bit of trig, draw it at the appropriate position on your shield when it is hit.
 

jo-thijs

Member
I have a lazy way, you could make an opaque sprite that represents a small portion of your energy shield when its hit.
And with a little bit of trig, draw it at the appropriate position on your shield when it is hit.
Nice idea, but it won't keep the alpha value capped at 0.5.

When hit by an attack, the whole sprite gains a small increase to it's alpha
So I just reread your original post and saw you mentioned using a sprite.
So I made an updated version of the example that uses a sprite:
http://www.mediafire.com/file/kh5pd9pp9q8aftk/GMC_force_field_alpha_effect.gm81
 
C

create_event@

Guest
@jo-thijs What did I do that karma sent you my way. I'm going to go over the code for this very carefully. How much of a graphical drain is this? Would several dozen of this effect be bad? If so, would the size I mentioned (about 10 pixels) be less of a drain?


I've played around with it a bit, and now I've got questions.First, Does this only work as a circle?

Perhaps I could upload my own game file for you to peek at...Would that be okay?
It's just a sandbox for me to do damage / destruction testing.
 
Last edited by a moderator:

jo-thijs

Member
How much of a graphical drain is this? Would several dozen of this effect be bad?
I don't think so.

If so, would the size I mentioned (about 10 pixels) be less of a drain?
No, the effect of the hit radius on performance should be negligable.

I've played around with it a bit, and now I've got questions.First, Does this only work as a circle?
Currently, yes, although it is very easy to change.

Perhaps I could upload my own game file for you to peek at...Would that be okay?
It's just a sandbox for me to do damage / destruction testing.
If you're ok with it, then sure.
 

jo-thijs

Member
http://www.mediafire.com/file/65jxjtxma61c05t/ship_function_mechanics.gm81

Cool. The code shouldn't be hard to read, and there's not much atm.

Edit-Oops, wrong kind of file. Fixed. Although, it probably would have worked...
I couldn't get the GMRES file to work, but the GM81 file was fine.

So, I changed the system a bit so that the array management is turned into objects,
I fixed something that might have been concidered a visual glitch when multiple circles were overlapping (gowing in alpha too much there)
and I made the system work with any shape of sprites and with image_angle applied to them.

How do you like it?
http://www.mediafire.com/file/np18gtgy7rt2d1k/ship_function_mechanics.gm81
 
C

create_event@

Guest
I couldn't get the GMRES file to work, but the GM81 file was fine.

So, I changed the system a bit so that the array management is turned into objects,
I fixed something that might have been concidered a visual glitch when multiple circles were overlapping (gowing in alpha too much there)
and I made the system work with any shape of sprites and with image_angle applied to them.

How do you like it?
http://www.mediafire.com/file/np18gtgy7rt2d1k/ship_function_mechanics.gm81
I like very much. I'll have to change my coding for the hits to something a bit more clunky, but it'll work great. Here's a question though. If I have multiple instances of that shield going, but using a different sprite, protecting a different ship, will that mess anything up?

EDIT- A closer look says no, probably not.

And just curious, do you have any comments on the way I'm working things there? Don't know if you looked at my code. I'll probably change the status display to something more graphical, off to the side.

EDIT-Got the damage system running again. Even able to make use of your variables to do it!
One more edit-question before sleep takes me. Will this system work even with drastically different shield shapes?
 
Last edited by a moderator:

jo-thijs

Member
I like very much. I'll have to change my coding for the hits to something a bit more clunky, but it'll work great. Here's a question though. If I have multiple instances of that shield going, but using a different sprite, protecting a different ship, will that mess anything up?

EDIT- A closer look says no, probably not.
Multiple shield instances and shield objects are supported.
Although it is not as efficient as it could be, but it'll probably suffice.

And just curious, do you have any comments on the way I'm working things there? Don't know if you looked at my code. I'll probably change the status display to something more graphical, off to the side.
Looks pretty good actually.

There are some improvements I can suggest however.

In this piece of code:
Code:
if reactor < 100//if power is not full

reactor += .25;//charge the reactor

if reactor > 100//if power is over-full

reactor = 100;//set power to max
you should be using indentation to make clear where the bodies of the if-statements are.
Using curley bracket is also slightly adviced, it has saved some people from unexpected bugs in the past:
Code:
if reactor < 100 { //if power is not full
    reactor += .25; //charge the reactor
}
if reactor > 100 { //if power is over-full
    reactor = 100; //set power to max
}
However, you can also shorten this piece of code to a single line:
Code:
// Charge the reactor up untill the power is 100
reactor = min(reactor + 0.25, 100);
These pieces of code:
Code:
shielded=1;//does the ship have shields?
Code:
if shielded<1//if ship has depleted shields

sh_count-=1;//countdown to regenerate them
Code:
if sh_count=0//if countdown is reached

    {
   ...
    shielded+=1// +1 for each - resets shield as acive
   ...
    };
Code:
if shielded>0//if there's a shield

{

    ...
            shielded-=1//and mark ship as not shielded - for a ship with redundant shields,
                                        //it just reduces the total count
                                        ...
};
Code:
if shielded=0//if the shields are out - including the shot that beat them
treat shielded as though it is an integer, but you actually use it as a boolean value.
You can make this clearer in your code as follows:
Code:
shielded = true;//does the ship have shields?
Code:
if !shielded { //if ship has depleted shields
    sh_count -= 1; //countdown to regenerate them
}
Code:
if sh_count == 0//if countdown is reached

    {
   ...
    shielded = true; // +1 for each - resets shield as acive
   ...
    };
Code:
if shielded { //if there's a shield
    ...
            shielded = false; //and mark ship as not shielded - for a ship with redundant shields,
                                        //it just reduces the total count
                                        ...
}
Code:
if !shielded //if the shields are out - including the shot that beat them
Also, try to use semicolons at the end of every statement (assignment or function call)
and don't use = inside the condition of an if-statement, use == instead.
A = B means assign the value of B to A.
A == B means compare the values of A with B and return whether they are the same.
GameMaker knows however that when you use a single = inside the condition of an if-satement that you probably meant to use == instead and interpretes it as that.
Also, don't use semicolons ; after a curley bracket }.

Don't try to squash multiple statements on a single line, like in this piece of code:
Code:
//shield restoration
if shielded > 0

    if reactor > 5
    
        if sh_en < 100

    {sh_en += .5 reactor -= .5;}
Do this instead:
Code:
//shield restoration
if shielded && reactor > 5 && sh_en < 100 {
    sh_en += 0.5;
    reactor -= 0.5;
}
This line of code:
Code:
    with HP3 image_alpha=.4// set shield visual cue
can also be written as:
Code:
    HP3.image_alpha = 0.4; // set shield visual cue
I'm not sure if I completely understand the intention behind this part:
Code:
        des_chance = 400 * (hp/100) //calculate the destruction chance for this hit

            {//then check each hardpoint against the chance
    
            if instance_exists(HP1) && random(100) > des_chance {with HP1 instance_destroy();}
            else
            if instance_exists(HP2) && random(100) > des_chance {with HP2 instance_destroy();}
            else
            if instance_exists(HP3) && random(100) > des_chance {with HP3 instance_destroy();}
            else
            if instance_exists(HP4) && random(100) > des_chance {with HP4 instance_destroy();}
            else
            if instance_exists(HP5) && random(100) > des_chance {with HP5 instance_destroy();}
    
            };
Is it actually supposed to be this way such that the odds of destruction are higher as you have more HP objects?

The HP1, ..., HP5 vriables are examples of where arrays and for loops can be applied to shorten your code a tiny bit.
For example, the code above could become:
Code:
        des_chance = 400 * (hp/100) //calculate the destruction chance for this hit

        //then check each hardpoint against the chance
        var i;
        for(i = 0; i < 5; i += 1) {
            if instance_exists(HP[i]) && random(100) > des_chance {
                with HP[i] {
                    instance_destroy();
                }
                break;
            }
        }
You'll need to change the other occurences of HP to take HP being an array into account as well though.

Comparing if a boolean value is true is in my opinion a bit superfluous, so I'd change:
Code:
if show_stats=true // in this case, if the mouse is touching the ship
to:
Code:
if show_stats // in this case, if the mouse is touching the ship
You use the variable reactor_level_sprite to refer to an image, which is kind of confusing.
Name it reactor_level_image instead.

In the draw event, you're using a bunch of variables that you only use in the draw event and are recalculated from scratch every time.
You can turn these kind of variables into "local" or "temporary" variables, which are variables that are deleted once the code they are declared in ends.
You can use them by adding this line somewhere at the start of the code in the raw event:
Code:
var bar_left, sh_col, hp_col, reactor_level_image;
And finally, in the alarm event, you've got this:
Code:
if shot_calc != 14 shot_calc += .05;
but it might be a bit safer to use:
Code:
if shot_calc < 14 {
    shot_calc += 0.05;
}
It might prevent bugs due to rounding errors and bugs due to changing 0.05 to a number that is not an integer fraction of 1, like 0.9237.

EDIT-Got the damage system running again. Even able to make use of your variables to do it!
One more edit-question before sleep takes me. Will this system work even with drastically different shield shapes?
Yes, it works with any shape now.

I couldn't get the GMRES file to work, but the GM81 file was fine.

So, I changed the system a bit so that the array management is turned into objects,
I fixed something that might have been concidered a visual glitch when multiple circles were overlapping (gowing in alpha too much there)
and I made the system work with any shape of sprites and with image_angle applied to them.

How do you like it?
http://www.mediafire.com/file/np18gtgy7rt2d1k/ship_function_mechanics.gm81
I actually forgot to clean up some unused stuff.

spr_bullet and spr_force_field may be removed.

This piece of code may be removed:
Code:
hit_count = 0; // Amount of hits that are still fading in
hit_array[0,0] = 0; // Array containing info about hits fading in

hit_X = 0; // x coordinate of hit
hit_Y = 1; // y coordinate of hit
hit_RAD = 2; // radius of hit fade-in area
hit_RINC = 3; // increase in radius per step for hit fade-in area
hit_AINC = 4; // increase in alpha per step for hit fade-in area
hit_TIME = 5; // remaining amount of steps for hit to complete fading in
hit_COUNT = 6; // amount of elements in this enum
And this line may be removed:
Code:
var last, i, j;
 
C

create_event@

Guest
Wow. This is some really good advice, glad you took the time to look at it. That array for the HP objects would be much better for the later ships. As to the shielded variable, some ships will have multiple hardpoints that are used as shields, so the shields wouldn't be fully destroyed until each one is dead, so it has to be read as an integer, that way I can use a standard "decrease shield count when killed" code instead of checking for each individual point, and then killing the shields. This way, I can automate it. If you know of a better way to handle it, I'm all ears. PC speakers. Whatever.

As to the HP destruction code, naturally the more hardpoints there are, the better the chance of killing one. I may have to be careful later on as I add more hardpoints, and enemies that do more damage. I may find my system bugging, and have to fix it. But for now, I'm happy.

Thankyouthankyouthankyou for all the help/advice you're tossing my way.
 
Top