How would I go about making a propulsion system within my game?

52 views Asked by At

I'm currently making a 2D platformer game within Gamemaker 2 and I'm using GML as the language.

I've had the idea of making a mechanic in my game where the player is able to aim a gun around themselves in a 360 degree radius. I want it to be so that I can click to shoot the gun and I'm propelled in the opposite direction in which I shot towards. I'm not sure how to actually go about this as I've done quite a bit of research and am unable to come up with a solution within my code.

First I found a formula to be able to calculate the opposite direction in which I was first aiming in so that I would be able to figure out what direction I need to propel the player when shooting but now I'm having trouble with moving the player in said direction. I've tried:

{ y += (sign(vSpd)*-100); } 

just to test it out to see if it works which it does but I'm not sure what direction to go to get the player to move smoothly instead of teleporting/Jumping to the point calculated. Please help any info or help is greatly appreciated!!!

Note my objects are oPlayer and oBlock and my Sprites are sPlayer, sBlock, and sAimHelp Here is my code that I am using currently:

Functions Script:

function draw_aim_help()
{
    //Drawing Sprite
        //Spacing of the sprite
            var _XOffset = lengthdir_x( weaponOffsetDist, aimDir );
            var _YOffset = lengthdir_y( weaponOffsetDist, aimDir );
    
        //Flipping the sprite
            var _weaponYscl = 1; // direction of sprite < or >
                // edit out if needed
            /*if aimDir > 90 and aimDir < 270
                {
                    _weaponYscl = -1;
                }
            */
        draw_sprite_ext( sAimHelp, 0, x + _XOffset, centerY + _YOffset, 1, _weaponYscl, aimDir, c_white, 1)
        depth = -bbox_bottom;
    
};

function get_aim_direction()
{
    if aimDir >= 90 and aimDir < 270
        {
            dirCheck = -1;
        }  
    else dirCheck = 1;
        
}

Create Event:

hSpd = 0;
vSpd = 0;
pGrv = 0.3;
plrSpd = 4;
grounded = 0;
vSpd_max = 15;
jump = -10;
jumpMod = 1.5;
//variables for aim
#region
    weaponOffsetDist = 128;
    centerYOffset = 0;
    centerY = y + centerYOffset;
    aimDir = 0;
    dirCheck = 0;
#endregion

Step Event:

//Movement Inputs
#region
leftKey = keyboard_check( ord("A")); 
rightKey = keyboard_check( ord("D"));
jumpKey = keyboard_check_pressed(vk_space);
jumpKeyHeld = keyboard_check(vk_space);

//Weapon Inputs
swapKeyPos = keyboard_check_pressed( ord("W")); 
swapKeyNeg = keyboard_check_pressed( ord("S"));
shootKey = mouse_check_button_pressed( mb_left );

//get aiming direction
get_aim_direction()
#endregion


    
    //propulsion mechanic
    if shootKey
        {
            weapon_propulsion();
        };
//Movement
#region
    //Player Movement
        var _horizKey = rightKey - leftKey;
        hSpd = _horizKey * plrSpd;
        vSpd = vSpd + pGrv;
    //jumping
        if jumpKey = 1 and grounded = true
            {
                vSpd += jump;
            }
            
        if vSpd < 0 and (!jumpKeyHeld)
            {
                vSpd = max(vSpd, jump / jumpMod)
            }
            
        //Gravity
            vSpd += pGrv;
            
        //Max speeds
            vSpd = clamp(vSpd, -vSpd_max, vSpd_max);
            
        
    //Horizontal movement
        if (place_meeting( x+hSpd, y, oBlock ))
        {
            while (!place_meeting( x+sign( hSpd ), y, oBlock ))
                {
                    x = x + sign( hSpd );
                }
                hSpd = 0;
        }
        
    //Vertical Movement
        if (place_meeting( x, y+vSpd, oBlock))
        {
            while (!place_meeting( x, y+sign(vSpd), oBlock))
            {
                y = y + sign(vSpd);
            }
            vSpd = 0;
            grounded = true;
        }
        else { grounded = false; };
        x += hSpd;
        y += vSpd;
#endregion

//Aiming
    centerY = y + centerYOffset;
    aimDir = round(point_direction( x, centerY, mouse_x, mouse_y));
    aimDirInv = ( aimDir + 180 ) mod 360;
    pushVar = degtorad(aimDirInv);

Draw Event: // Just for debugging process

draw_self();
draw_aim_help();
draw_text( x, y, string(aimDir));
draw_text( x, y+20, string(aimDirInv));
draw_text( x, y+40, string(pushVar));
draw_text( x, y+60, string(dirCheck));
1

There are 1 answers

0
Treasure Dev On

To get your propulsion movement smoother you'll first want to define a few more values in your create event:

recoilMax = 8; // Initial speed when shooting
recoilDeceleration = 0.8; // How quickly recoil decreases.
curRecoil = 0; // Tracks current recoil speed
recoilDir = 0; // Direction of recoil

Then in your step event you'll update your propulsion:

//propulsion mechanic
if shootKey {
    weapon_propulsion(); // it may make more sense to apply recoil in here but I do not know what the contents of this function are. 

    // Apply Recoil
    recoilDir = aimDir + 180; // Opposed direction of current aim direction
    curRecoil = recoilMax; // Set recoil spd to initial value
};

Lastly you'll apply this by your movement section, also in the step event:

//Player Movement
var _horizKey = rightKey - leftKey;
hSpd = _horizKey * plrSpd;
vSpd = vSpd + pGrv;

// Apply recoil
hSpd += lengthdir_x(curRecoil, recoilDir);
vSpd += lengthdir_y(curRecoil, recoilDir);
curRecoil *= recoilDeceleration;

Effectively, you want to apply the maximum initial force to your character then have it decelerate over time. We accomplish this by moving only a limited amount of pixels every single frame then decreasing that amount the longer the 'recoil' goes on to simulate that air resistance. Of course the specific values of how fast you start moving and how much you slow down by over time will change as the numbers provided above are just filler/an example.

Aside from this a recommendation i have would be to consider implementing a finite state machine. It takes a bit of setup and getting used to but it will save you a LOT of headaches in the long run. There was a good article on the gamemaker website that covered the basics for that if you're interested. Hope this helps: https://gamemaker.io/en/tutorials/coffee-break-tutorials-finite-state-machines-gml