# How to fade image_alpha as you walk further from object

#### Pkirkby

##### Member
Hi everyone, as you can see from my image I have a simple light source. It's effective in drawing my shadow based on the placement of the light object. However, given my code I can't figure out how to properly fade the image_alpha out as I walk further from the light source. Here's the code I use:

var sx = oLighting.x - x;
var sy = oLighting.y - y;
//var light_xy = sx + sy;

gpu_set_fog(true,c_black,0,1);
draw_sprite_pos(sprite_index,image_index,
x-(sprite_width/2)-sx,
y-sy,
x+(sprite_width/2)-sx,
y-sy,
x+(sprite_width/2),
y,
x-(sprite_width/2),
y,
image_alpha);

I've come close with some equations that update the alpha based on the x/y coordinates of the light source, but I'm too noobish in GML to figure this one out. Also, I've looked into the "clamp" function, this was on YoYo's website:

image_alpha = clamp(image_alpha - 0.01, 0, 1);

The above code will slowly reduce the image_alpha until it reaches 0.

Surely there must be a way to do this with clamp?

EDIT: Now I've got it working, HOWEVER I'm trying to make it so everywhere I place this "oLighting" object, I'd like it to cast a separate "shadow" and I can't seem to accomplish this.

#### Attachments

• 68.4 KB Views: 11
Last edited:

#### obscene

##### Member
Use point_distance() to find the distance between two points
Set the variable max_distance to distance at which alpha should be 0.

image_alpha=1-(actual_distance/max_distance);

• Nocturne and Bentley

#### Pkirkby

##### Member
Ok, so let's say my light source is called (oLight) How would I go about implementing that into my current code? Thanks for a fast response!

#### MikeeyBikeey

##### Member
I got this to work in Gamemaker Studio 1.4.9999:
Code:
``````// if `distance` is below `min_distance` then the instance is fully visible
var min_distance = 32;
var max_distance = 256;
var distance = point_distance(oLighting.x, oLighting.y, x, y);
image_alpha = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);

var sx = oLighting.x - x;
var sy = oLighting.y - y;

// gpu_set_fog(true,c_black,0,1);
draw_sprite_pos(
sprite_index,
image_index,
x - sprite_width / 2 - sx,
y-sy,
x + sprite_width / 2 - sx,
y-sy,
x + sprite_width / 2,
y,
x - sprite_width / 2,
y,
image_alpha);``````

#### Pkirkby

##### Member
You're the best, I'm gonna try that tonight and see if I can make it work, thanks a lot!

#### Pkirkby

##### Member
I got this to work in Gamemaker Studio 1.4.9999:
Code:
``````// if `distance` is below `min_distance` then the instance is fully visible
var min_distance = 32;
var max_distance = 256;
var distance = point_distance(oLighting.x, oLighting.y, x, y);
image_alpha = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);

var sx = oLighting.x - x;
var sy = oLighting.y - y;

// gpu_set_fog(true,c_black,0,1);
draw_sprite_pos(
sprite_index,
image_index,
x - sprite_width / 2 - sx,
y-sy,
x + sprite_width / 2 - sx,
y-sy,
x + sprite_width / 2,
y,
x - sprite_width / 2,
y,
image_alpha);``````
Damn, I'm not sure what I'm doing wrong, is that exactly as you did it to get it work?

#### Pkirkby

##### Member
Nev
Damn, I'm not sure what I'm doing wrong, is that exactly as you did it to get it work?
Nevermind, I got it!!! Dude, you've solved an issue I've been struggling with for weeks lol. Thanks again!

#### Pkirkby

##### Member
Nev

Nevermind, I got it!!! Dude, you've solved an issue I've been struggling with for weeks lol. Thanks again!
Here's another question for you, when I make this an object, it only affects things in one instance, if I put multiple of these objects, they dont make individual shadows on the objects. Would you know a way around that?

#### obscene

##### Member
Sounds like you have one object to run the effect, right?

Best way to run code for multiple instances is something like this...

with (obj_name) { do stuff }

This will cause every obj_name to run the following code all at once.

So with multiple lights and multiple shadowcasters you might end up with something like this...

Code:
``````with (obj_light)
{
// save the lights position to temporary variables
var xx=x;
var yy=y;

{
// get distance from x,y to xx,yy and draw the shadows at x,y
}
}``````

• Yal

#### Pkirkby

##### Member
Sounds like you have one object to run the effect, right?

Best way to run code for multiple instances is something like this...

with (obj_name) { do stuff }

This will cause every obj_name to run the following code all at once.

So with multiple lights and multiple shadowcasters you might end up with something like this...

Code:
``````with (obj_light)
{
// save the lights position to temporary variables
var xx=x;
var yy=y;

{
// get distance from x,y to xx,yy and draw the shadows at x,y
}
}``````
Actually I already have it affecting any objects in my associated with my oParent, my problem is that I want this code to affect all "lamps" for example. So I want to place a bunch of "lamps" and have a shadow draw for each lamp's light source. But as of right now, it only seems to draw one. Thanks again for your reply.

#### obscene

##### Member
That's where "with" comes in. If you write with(obj_lamp) every lamp runs the code. Not sure if your code is in your shadowcaster objects or in a controller object, but in either case that's the way to approach it.

var sx = oLighting.x - x;
var sy = oLighting.y - y;

But that will only get one light.

This will get them all...

Code:
``````with (oLighting)
{
var sx=x; // this code is running from the perspective of each light instance, so simply get x and y.
var sy=y;
with (oParent)
{
// draw your shadow here for each object as you did before.
}
}``````

#### Pkirkby

##### Member
Yeah, I didn't post my with statement, it currently has a "with (oParent)" to affect all objects controlled by my parent object. But Im going to try that tonight, it's kind of what I was thinking but it's nice to see it from someone more experienced. Thanks a lot for your help!

#### Pkirkby

##### Member
That's where "with" comes in. If you write with(obj_lamp) every lamp runs the code. Not sure if your code is in your shadowcaster objects or in a controller object, but in either case that's the way to approach it.

var sx = oLighting.x - x;
var sy = oLighting.y - y;

But that will only get one light.

This will get them all...

Code:
``````with (oLighting)
{
var sx=x; // this code is running from the perspective of each light instance, so simply get x and y.
var sy=y;
with (oParent)
{
// draw your shadow here for each object as you did before.
}
}``````
So I tried that, but it seems that if I remove the "sx = oLighting.x - x;" it won't update the shadow based on the position of the object, it just fixes it. I can't seem to have each light source affect each object.

While we're here, I'm trying to apply an if statement of similar effect, where as my zsp (my jumping height) increases, the shadow size decreases. I should be able to use a similar statement, but how would you go about it?

bump.

#### Pkirkby

##### Member
You'll need to post your entire code. As it stands, sx = oLighting.x - x; shouldn't be a part of your code anywhere.

Also, is this top-down or sidescroller?
This is a Top-down style game, as of right now I have "oLighting" working and affecting all objects, I just cant place more than one "oLighting" and have multiple shadows cast from each source. Here's my current code:

with(oParent)
{
var min_distance = 2;
var max_distance = 150;
var distance = point_distance(oLamp.x, oLamp.y+z, x, y+z);
var shadow_alpha = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);
var shadow_distance = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);

var sx = oLamp.x - x;
var sy = oLamp.y - y;

gpu_set_fog(true,c_black,0,1);
draw_sprite_pos(
sprite_index,
image_index,
x - sprite_width / 2 - sx,
y-sy,
x + sprite_width / 2 - sx,
y-sy,
x + sprite_width / 2,
y,
x - sprite_width / 2,
y,

//draw_sprite_ext(sprite_index,image_index,x-5,y-5,image_xscale,image_yscale,0,c_black,0.5);

//This sets fog to disable,white is default.
gpu_set_fog(false,c_white,0,0);

}

#### MikeeyBikeey

##### Member
I got this to work:
Code:
``````// gpu_set_fog(true,c_black,0,1);

with(oLighting) // assuming all `oLighting` instances cast light
{
// jumping (z)
var cast_dir = point_direction(x, y, other.x, other.y);
var xcast = lengthdir_x(other.z, cast_dir) + other.x;
var ycast = lengthdir_y(other.z, cast_dir) + other.y;

var min_distance = 2;
var max_distance = 150;
var distance = point_distance(x, y, xcast, ycast);
var shadow_alpha = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);
var shadow_distance = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);

var sx = x - xcast;
var sy = y - ycast;

draw_sprite_pos(
other.sprite_index,
other.image_index,
xcast - other.sprite_width / 2 - sx,
ycast - sy,
xcast + other.sprite_width / 2 - sx,
ycast - sy,
xcast + other.sprite_width / 2,
ycast,
xcast - other.sprite_width / 2,
ycast,
}

// This sets fog to disable, white is default.
// gpu_set_fog(false,c_white,0,0);``````

#### Pkirkby

##### Member
I got this to work:
Code:
``````// gpu_set_fog(true,c_black,0,1);

with(oLighting) // assuming all `oLighting` instances cast light
{
// jumping (z)
var cast_dir = point_direction(x, y, other.x, other.y);
var xcast = lengthdir_x(other.z, cast_dir) + other.x;
var ycast = lengthdir_y(other.z, cast_dir) + other.y;

var min_distance = 2;
var max_distance = 150;
var distance = point_distance(x, y, xcast, ycast);
var shadow_alpha = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);
var shadow_distance = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);

var sx = x - xcast;
var sy = y - ycast;

draw_sprite_pos(
other.sprite_index,
other.image_index,
xcast - other.sprite_width / 2 - sx,
ycast - sy,
xcast + other.sprite_width / 2 - sx,
ycast - sy,
xcast + other.sprite_width / 2,
ycast,
xcast - other.sprite_width / 2,
ycast,
}

// This sets fog to disable, white is default.
// gpu_set_fog(false,c_white,0,0);``````
Awesome, I'm going to try tomorrow. Appreciate the response!

#### Pkirkby

##### Member
I got this to work:
Code:
``````// gpu_set_fog(true,c_black,0,1);

with(oLighting) // assuming all `oLighting` instances cast light
{
// jumping (z)
var cast_dir = point_direction(x, y, other.x, other.y);
var xcast = lengthdir_x(other.z, cast_dir) + other.x;
var ycast = lengthdir_y(other.z, cast_dir) + other.y;

var min_distance = 2;
var max_distance = 150;
var distance = point_distance(x, y, xcast, ycast);
var shadow_alpha = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);
var shadow_distance = 1 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 1);

var sx = x - xcast;
var sy = y - ycast;

draw_sprite_pos(
other.sprite_index,
other.image_index,
xcast - other.sprite_width / 2 - sx,
ycast - sy,
xcast + other.sprite_width / 2 - sx,
ycast - sy,
xcast + other.sprite_width / 2,
ycast,
xcast - other.sprite_width / 2,
ycast,
}

// This sets fog to disable, white is default.
// gpu_set_fog(false,c_white,0,0);``````
Ok, so I fooled around with it, I am trying to make sense of it. What's the "other" object and how is it controlled? Seems I get an issue with the "object.z" right off the bat.

#### Pkirkby

##### Member
Anyone have any more suggestions? I've read up on With but I still can't seem to have all objects "oLamp" draw shadow, only the most recent "oLamp" will affect other objects. I have my "oLighting" affecting my "oParent" which essentially affects everything that should cast a shadow, and I made oLamp the reference point in which the light is cast. As you can see from the screenshot, light is casting from the right lightsource but wont from the left. Here's my code, any help would be amazing, thanks!

with(oParent)
{
var min_distance = 2;
var max_distance = 150;
var distance = point_distance(oLamp.x, oLamp.y, x, y);
var shadow_alpha = 0.8 - clamp((distance - min_distance) / (max_distance - min_distance), 0, 0.8);

var sx = oLamp.x - x;
var sy = oLamp.y - y;

gpu_set_fog(true,c_black,0,1);
draw_sprite_pos(
sprite_index,
image_index,
x - sprite_width / 2 - sx,
y-sy,
x + sprite_width / 2 - sx,
y-sy,
x + sprite_width / 2,
y,
x - sprite_width / 2,
y,

//draw_sprite_ext(sprite_index,image_index,x-5,y-5,image_xscale,image_yscale,0,c_black,0.5);

//This sets fog to disable,white is default.
gpu_set_fog(false,c_white,0,0);

}

#### Attachments

• 53.5 KB Views: 2