• 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 Throw snowball at an angle.

neutro

Member
Hi guys,
So now I am trying to implement an angle on my spawned snowball. I want to apply gravity and also that the movement speed of the snowball decreases. Having a bit of a hard time figuring this out. Any suggestions? The snowball movement is straight forward with fixed speed.
Code:

GML:
// Spawn snowball, goes right
if (image_index > 5) && (image_index < 5.34) && (image_xscale == 1) {
    var inst = instance_create_layer(x, y-8, "Instances", oSnowball);
    with (inst)  {
        speed = snowball_speed;
        direction = id.image_angle;
     
    }
}

// Spawn snowball, goes left
else if (image_index > 5) && (image_index < 5.34) && (image_xscale == -1) {
    var inst = instance_create_layer(x, y-8, "Instances", oSnowball);
    with (inst)  {
        speed = -snowball_speed;
        direction = -id.image_angle;
    }
}
Snowboy and Frosties says hello :)

ForumJPG.jpg
 
Last edited:

Nidoking

Member
If you're using direction and speed, then you can also use gravity. Reducing speed is literally a matter of reducing speed.
 

neutro

Member
If you're using direction and speed, then you can also use gravity. Reducing speed is literally a matter of reducing speed.
I don't know how to make a mathematical formula to decrease the speed. Or apply gravity.
Maybe a for loop in some way?
 

chamaeleon

Member
I don't know how to make a mathematical formula to decrease the speed. Or apply gravity.
Maybe a for loop in some way?
When you use speed, direction, and gravity, GMS manages it for you. Just set gravity to an initial value, just like you set speed and direction. Tweak the value until it "looks good" for your game.
 

Nidoking

Member
I don't know how to make a mathematical formula to decrease the speed.
speed = (some number that's less than speed);

Typically, you'd multiply speed by some number slightly less than one. 0.9? 0.7? Depends on how much you want it to slow down.
 

chamaeleon

Member
Not sure if reducing speed relevant. For the purposes of a game it seems like one can ignore the friction air has on the speed of a snowball, only gravity giving it a parabolic trajectory should be required.
 

neutro

Member
Thanks guys! Works like a charm! :) Just gotta find the right tweaks for most enjoyable gameplay.
Now I am gonna work on destroying the snowball while hitting ground, or enemy.

GML:
// Spawn snowball, goes right
if (image_index > 5) && (image_index < 5.34) && (image_xscale == 1) {
    var inst = instance_create_layer(x, y-8, "Instances", oSnowball);
    with (inst)  {
        speed = snowball_speed * 0.6;
        gravity = 0.01;
        direction = id.image_angle;
        
    }
}

// Spawn snowball, goes left
else if (image_index > 5) && (image_index < 5.34) && (image_xscale == -1) {
    var inst = instance_create_layer(x, y-8, "Instances", oSnowball);
    with (inst)  {
        speed = -snowball_speed * 0.6;
        gravity = 0.01;
        direction = -id.image_angle;
    }
}
 

neutro

Member
So what structure should I use for the snowball to be destroyed?
I got a sprite, sSnowballXplode.
Should I spawn an object, like if I create an object, oSnowballXplode, with the sSnowballXplode sprite, when my oSnowball hits the ground, or enemy?
Or maybe I should work out some states, in the oSnowball, and just switch between animations?
 

TheouAegis

Member
Um, a couple things no one even addressed about your code.


speed = -snowball_speed * 0.6;
speed is a scalar quantity typically, meaning it has no bearing on direction. GM treats negative speed, which itself is a misnomer, as moving in reverse. That's one of the reasons your code is seeming to work. Not saying you need to fix this line, just pointing out why it behaves as it does.


direction = -id.image_angle;
This is the crux of your code's flaw. There are actually three fatal flaws in this line (and two flaws in the similar version in the other conditional). And no, you cannot ignore any of these issues, as one illustrates you don't grasp trig/geometry, one shows you don't understand a fundamental of Game Maker, and the other illustrates you don't understand a fundamental of coding.

The first issue, the math one, is -direction. Your code seems to work because direction is 0, and -0 is still 0. If you move at speed 1 in direction 0, then setting speed to -1 still moves you in direction 0, albeit in reverse, hence it seems to work. Likewise, if direction happened to be 180 (which it obviously is not, more on that later), then -180 is still 180. However, -90 is 270 and -45 is 315. Again, your code would seem to work with negative soeed because negative speed essentially adds 180 to the direction. Thus, if direction is -20 with a negative speed, it is essentially 180-20, or 160.

Second, speed and direction are related, as illustrated above. Although changing one will not change the other, changing either will change the hspeed and vspeed variables. So typically you don't change both speed and direction. It's just coincidental that things seem to work out in your favor here.

The third issue is direction=id.direction means nothing, it is garbage code. It is the same as saying, "I am me." In a with() structure, you must use the keyword other to refer back to the instance running the code (or other.id, but GM makes that redundant here).
 

TheouAegis

Member
So what structure should I use for the snowball to be destroyed?
I got a sprite, sSnowballXplode.
Should I spawn an object, like if I create an object, oSnowballXplode, with the sSnowballXplode sprite, when my oSnowball hits the ground, or enemy?
Or maybe I should work out some states, in the oSnowball, and just switch between animations?
New object OR use states, it's inconsequential here as it would essentially just be a binary state machine anyway. Or just set speed to 0, change the sprite, set alarm 0,and in alarm 0's event, destroy the instance. But new object does take care of collision handling issues cleanly.
 
Last edited:

neutro

Member
Um, a couple things no one even addressed about your code.



speed is a scalar quantity typically, meaning it has no bearing on direction. GM treats negative speed, which itself is a misnomer, as moving in reverse. That's one of the reasons your code is seeming to work. Not saying you need to fix this line, just pointing out why it behaves as it does.



This is the crux of your code's flaw. There are actually three fatal flaws in this line (and two flaws in the similar version in the other conditional). And no, you cannot ignore any of these issues, as one illustrates you don't grasp trig/geometry, one shows you don't understand a fundamental of Game Maker, and the other illustrates you don't understand a fundamental of coding.

The first issue, the math one, is -direction. Your code seems to work because direction is 0, and -0 is still 0. If you move at speed 1 in direction 0, then setting speed to -1 still moves you in direction 0, albeit in reverse, hence it seems to work. Likewise, if direction happened to be 180 (which it obviously is not, more on that later), then -180 is still 180. However, -90 is 270 and -45 is 315. Again, your code would seem to work with negative soeed because negative speed essentially adds 180 to the direction. Thus, if direction is -20 with a negative speed, it is essentially 180-20, or 160.

Second, speed and direction are related, as illustrated above. Although changing one will not change the other, changing either will change the hspeed and vspeed variables. So typically you don't change both speed and direction. It's just coincidental that things seem to work out in your favor here.

The third issue is direction=id.direction means nothing, it is garbage code. It is the same as saying, "I am me." In a with() structure, you must use the keyword other to refer back to the instance running the code (or other.id, but GM makes that redundant here).
Hi Theougis,

Thanks for your input. I'm a happy beginner when it comes to both coding and game development. I got some basic math skills back from school and some very basic C# console programming in my backpack. I am probably more of a designer and pixel artist but am trying the best I can to learn more about this wonderful technology. I love playing good retro games, and those games are the inspiration for my own development. I will probably not go about to try to develop any AAA games, but you never know :)
As for the code and the flaws you adressed. I am on a noob-level, ESPECIALLY when it comes to GML and it's built in functions. I try to read and educate myself on a daily basis, when there is time for it(I'm also a family guy, dad, cat owner, gamer). I try to approach problems in different ways, mostly I try to understand and solve it by myself, sometimes tutorials, this forum, googling, and also trying solutions of code and thinking about what it does, and how, like reverse engineering. Small steps but still.
Maybe you can present me a better code solution and explain a bit more?
 

TheouAegis

Member
The only change you need to make is id.direction should be other.direction in this code. However, you are making a side-scroller, so direction is unnecessary. How are you even using "direction" in the player object (or whatever is throwing the snowball)? Is the player moving with just hspeed and you are using direction for the aiming only (which should be fine)?
 

Nidoking

Member
I believe direction is just initialized to 0 and he's depending on that, inadvertently. It would probably be better to hardcode the directions, since he's already splitting on which direction the player is facing.
 

neutro

Member
The only change you need to make is id.direction should be other.direction in this code. However, you are making a side-scroller, so direction is unnecessary. How are you even using "direction" in the player object (or whatever is throwing the snowball)? Is the player moving with just hspeed and you are using direction for the aiming only (which should be fine)?
Now:

GML:
// Spawn snowball, goes right
if (image_index > 5) && (image_index < 5.34) && (image_xscale == 1) {
    var inst = instance_create_layer(x, y-8, "Instances", oSnowball);
    with (inst)  {
        speed = snowball_speed * 0.6;
        gravity = 0.01;
        other.direction = image_angle;
        
        }
}

// Spawn snowball, goes left
else if (image_index > 5) && (image_index < 5.34) && (image_xscale == -1) {
    var inst = instance_create_layer(x, y-8, "Instances", oSnowball);
    with (inst)  {
        speed = -snowball_speed * 0.6;
        gravity = 0.01;
        other.direction = image_angle;
    }
}
End result in test is exactly the same.
 

chamaeleon

Member
Now:

GML:
// Spawn snowball, goes right
if (image_index > 5) && (image_index < 5.34) && (image_xscale == 1) {
    var inst = instance_create_layer(x, y-8, "Instances", oSnowball);
    with (inst)  {
        speed = snowball_speed * 0.6;
        gravity = 0.01;
        other.direction = image_angle;
       
        }
}

// Spawn snowball, goes left
else if (image_index > 5) && (image_index < 5.34) && (image_xscale == -1) {
    var inst = instance_create_layer(x, y-8, "Instances", oSnowball);
    with (inst)  {
        speed = -snowball_speed * 0.6;
        gravity = 0.01;
        other.direction = image_angle;
    }
}
End result in test is exactly the same.
Can you state what the problem is explicitly, or if there is a problem at all. Building on what @TheouAegis has been saying, not sure why you use negative speed. Set the speed to what you want speed to be in absolute terms, and use direction to indicate which direction it should go in. And speaking of direction, you are now changing the direction of the instance that is spawning snowballs, not the snowball itself, when you introduce the other.direction change.
 

Nidoking

Member
Well, now you're just setting the direction of the player instance to 0, and still leaving the snowball moving at direction 0 and speed +- snowball_speed * .6. It's still wrong, but it gives you the result you want. The question is whether you want to understand what you're doing, or whether you're happier having no clue as long as the snowball does what you want.
 

neutro

Member
Can you state what the problem is explicitly, or if there is a problem at all. Building on what @TheouAegis has been saying, not sure why you use negative speed. Set the speed to what you want speed to be in absolute terms, and use direction to indicate which direction it should go in. And speaking of direction, you are now changing the direction of the instance that is spawning snowballs, not the snowball itself, when you introduce the other.direction change.
Ok, I thought it was like this, when I got an snowball_speed, like 4, the snowball moves on the x-axis +4 pixels,
and if I want it to go the other direction, it is negative, hence the -snowball_speed.
 

Nidoking

Member
That's true IF direction is zero (i.e. directly right). Normally, you'd set direction to the direction you want the instance to move, and speed to the (positive) number of pixels per step.
 
Top