1. Hey! Guest! The 32nd GMC Jam will take place between Feb 22nd, 12:00 UTC (Friday noon) and Feb 25th, 12:00 UTC (Monday noon). Why not join in! Click here to find out more!
    Dismiss Notice

GMS 2 Precise Enemy Knockback

Discussion in 'Programming' started by dsosa, Feb 12, 2019 at 6:36 PM.

  1. dsosa

    dsosa Member

    Joined:
    Tuesday
    Posts:
    2
    Hello! This is my first post on this forum. I haven't done any programming in a long time so I'm very rusty, not that I was a professional before or anything. My code is very messy and disorganized but the game operates pretty well so far. But I've just been having trouble trying to get any sort of knockback system working adequately. I want the enemy to be sent in a specfic direction with a specific amount of force when it collides with the hitbox object, but for now after so many attempts I don't even really know where to start. Help would be very much appreciated.
     
  2. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,046
    For wanting so many specific things that happen, you haven't specified what exactly you want to happen and what specifics you want specifically.
     
    Bayesian likes this.
  3. samspade

    samspade Member

    Joined:
    Feb 26, 2017
    Posts:
    1,496
    At a minimum you need to post your movement and collision code. Describing some general things about your game might be good as well (top down, side scroller, etc.) as well as describing how you're detecting collisions with this object and how you (ideally) want to determine the force and direction.
     
  4. dsosa

    dsosa Member

    Joined:
    Tuesday
    Posts:
    2
    Code:
    /// @description Control player character
    
    //Step Event
    
    var k_left  = keyboard_check(ord("A"));
    var k_leftr = keyboard_check_released(ord("A"));
    var k_right = keyboard_check(ord("D"));
    var k_rightr = keyboard_check_released(ord("D"));
    var k_jump  = keyboard_check_pressed(vk_space);
    var k_down = keyboard_check(ord("S"));
    var k_downp = keyboard_check_pressed(ord("S"));
    var k_downr = keyboard_check_released(ord("S"));
    var k_dash = keyboard_check_pressed(vk_shift);
    var k_punch = keyboard_check_pressed(ord("P"));
    var k_knee = keyboard_check_pressed(ord("O"));
    var k_kick = keyboard_check_pressed(ord("I"));
    
    var spd_wanted = 0; //The wanted horizontal speed for this step
    var haccl = 0 //Set horizontal acceleration
    
    if(k_left && crouchstate == 0 && attackstate == 0 && dashstate == 0 && !k_down)
    {
        image_xscale = 1;
        haccl -=0.25;
        spd_wanted -= 2;
        if (speed_x >= spd_wanted){
        haccl +=0.25;   
        }
        if (place_meeting(x,y+1,oWall) && !k_down){
        
        image_speed = abs(speed_x)*0.85;
        sprite_index = sJotaroWalk;   
        pstate = "walk";
        }
    }
    
    if(k_right && crouchstate == 0 && attackstate == 0 && dashstate == 0 && !k_down)
    {   
        image_xscale = -1;
        haccl +=0.25;
        spd_wanted += 2;
        if (speed_x <= spd_wanted){
        haccl -=0.25;   
        }
        if (place_meeting(x,y+1,oWall) && !k_down){
        image_speed = abs(speed_x)*0.85;
        sprite_index = sJotaroWalk;   
        pstate = "walk";
        }
    }
    
    if (k_downp && place_meeting(x,y+1,oWall) && dashstate = 0 && attackstate = 0){
    image_index = 0;
    
    }
    
    if (k_down && place_meeting(x,y+1,oWall) && dashstate = 0 && sprite_index != sJotaroCrouchBackhand && attackstate = 0){
    
    sprite_index = sJotaroCrouch
    image_speed = 0.9;
    crouchstate = 1;
    haccl = 0;
    spd_wanted = 0;
    pstate = "crouch";
    if (stam < maxstam){
    stam += 0.5   
    }
    
    }
    
    
    if (k_downr && crouchstate == 1 && dashstate == 0 && attackstate == 0){
    image_index = 0;
    sprite_index = sJotaroStandUp;   
    }
    
    
    if(k_dash && speed_x != 0 && dashstate == 0 && pstate != "dash" && attackstate = 0){
    dashstate = 1;
    image_index = 0;
    }
    if (dashstate == 1){
    pstate = "dash";
    stam -=2;
    if(place_meeting(x,y+1,oWall)){
    sprite_index = sJotaroDash;
    image_speed = 1.05;
    }
    if(!place_meeting(x,y+1,oWall)){
    sprite_index = sJotaroAirdash
    image_speed = 1.05;
    }
    if (image_xscale == -1){
    haccl = 0.8;
    }
    if (image_xscale == 1){
    haccl = -0.8;
    }
    }
    if (dashstate == 0){
    pstate = "idle";
    haccl = 0;
    
    }
    
    if (!k_right && !k_left && place_meeting(x,y+1,oWall) && !k_jump && dashstate = 0 && !k_down && sprite_index != sJotaroStandUp && sprite_index != sJotaroPunch && sprite_index != sJotaroKnee && sprite_index != sJotaroKick && sprite_index != sJotaroCrouchBackhand){
    image_speed = 1;
    sprite_index = sJotaroIdle;
    pstate = "idle";
    crouchstate = 0;
    attackstate = 0;
    }
    
    if (k_punch && dashstate == 0 && place_meeting(x,y+1,oWall) && attackstate == 0 && crouchstate == 0){
    attackstate = 1;
    image_index = 0;
    image_speed = 1.05;
    sprite_index = sJotaroPunch;
    instance_create_depth(x,y,0,oPunchHitbox);
    }
    if (k_knee && dashstate == 0 && place_meeting(x,y+1,oWall) && attackstate == 0){
    attackstate = 1;
    image_index = 0;
    image_speed = 1.05;
    sprite_index = sJotaroKnee;
    instance_create_depth(x,y,0,oKneeHitbox);
    }
    if (k_kick && dashstate == 0 && place_meeting(x,y+1,oWall) && attackstate == 0){
    attackstate = 1;
    image_index = 0;
    image_speed = 1.05;
    sprite_index = sJotaroKick;
    instance_create_depth(x,y,0,oKickHitbox);
    }
    if (k_punch && dashstate == 0 && place_meeting(x,y+1,oWall) && attackstate == 0 && crouchstate == 1){
    attackstate = 1;
    image_index = 0;
    image_speed = 1.05;
    sprite_index = sJotaroCrouchBackhand;
    instance_create_depth(x,y,0,oBackhandHitbox);
    }
    
    
    if (!place_meeting(x,y+1,oWall) && sprite_index != sJotaroJump && dashstate = 0){
    if (speed_y > 0){
    image_speed = 1.05;
    sprite_index = sJotaroFall;
    }
    if (speed_y <= 0){
    image_speed = 1.05;
    sprite_index = sJotaroAirborne;
    }
    crouchstate = 0;
    }
    
    speed_x += haccl; //Set the horizontal speed based on the wanted speed
    
    speed_y += grav; //Apply gravity
    
    if (dashstate = 0 && stam < maxstam){
    stam +=1;   
    }
    
    //Horizontal collision
    if(place_meeting(x + speed_x, y, oWall))
    {
        while(!place_meeting(x + sign(speed_x), y, oWall))
        {
        x+=sign(speed_x);
        }
        speed_x = 0;
    }
    x += speed_x;
    
    //Vertical collision
    if(place_meeting(x, y + speed_y, oWall))
    {
        while(!place_meeting(x, y + sign(speed_y), oWall))
        {
        y+=sign(speed_y);
        }
        speed_y = 0;
    }
    y += speed_y;
    
    /*var spd_wanted = 0; //The wanted horizontal speed for this step
    
    */
    speed_x += (spd_wanted - speed_x) * 0.15; //Smoothly accelerate / decelerate to the wanted speed
    
    var xsp = round(speed_x); //Turn the theoretical value into an integer for collision and movement
    
    //Horizontal collision
    if(place_meeting(x+xsp, y, oWall))
    {
        while(!place_meeting(x+sign(xsp), y, oWall))
        {
        x += sign(xsp);
        }
        xsp     = 0;
        speed_x = 0; 
    }
    x += xsp;
    
    speed_y += grav; //Apply gravity
    
    if(k_jump && place_meeting(x, y + 1, oWall))
    {
        if(dashstate = 0) {
        image_speed = 1.2/*speed_y*8*/;
        image_index = 0;
        sprite_index = sJotaroJump;
        }
        if (crouchstate = 1) {
        crouchstate = 0;
        speed_y = -8.5
        pstate = "jump";
        } else {
        speed_y = -7;
        pstate = "jump";   
      }
    }
    
    var ysp = round(speed_y); //Turn the theoretical value into an integer for collision and movement
    
    //Vertical collision
    if(place_meeting(x, y + ysp, oWall))
    {
        while(!place_meeting(x, y+sign(ysp), oWall))
        {
            y+=sign(ysp);
        }
        ysp     = 0
        speed_y = 0; 
    }
    y += ysp;
    
    Sorry about that, here's everything in my step event. I made another object that can be controlled with the arrow keys and that's what I'm trying to get to work with the hitboxes. I made sprites for the hitboxes that coincide with the animations, and I'm using those for the hitbox objects.

    For specifics, I wanted to try and make the punch hitbox send the object diagonally downward with strong force, and knee hitbox diagonally upward with lighter force, the kick hitbox forward with strong force, and the backhand hitbox diagonally upward (angled more upward than the knee) with strong force.
     
  5. samspade

    samspade Member

    Joined:
    Feb 26, 2017
    Posts:
    1,496
    Admittedly, I'm not sure why you have speed_x and speed_y and xsp and ysp. And why you change your x/y position twice based on both of those values. It seems like that would add a lot of unnecessary speed to the character. I would remove one of these.

    But otherwise, looking at this, it seems like you have a side scroller and that your movement is based on acceleration - or your new location equals your old location plus velocity, and your velocity equals your current velocity plus your current acceleration.

    In pseudo code:

    acceleration = 0;
    //do things to add to acceleration
    //probably add in friction
    velocity += acceleration;
    location += velocity; //after checking for collisions

    This type of system is pretty easy to add knockback, or really just any movement, too. You should be able to simply add it directly to velocity (which in your case is either speed_x/y or x/ysp or both, see first comment).

    So, here is an example script:

    Code:
    
    scr_add_movement_to_player(force, direction);
    /// @description Add movement to Player
    /// @param force
    /// @param direction
    
    //translate force and direction (which is a representation of a vector as angle and magnitude)
    //into an x and a y (which is a representation of the same vector using grid space)
    var x_force = lengthdir_x(argument0, argument1);
    var y_force = legntdhir_y(argument0, argument1);
    
    with (obj_player) {
        speed_x += x_force;
        speed_y += y_force;
    }
    
    
    Now you can call that script wherever you want to add force. Again, without fully understanding your system, no guarantees that this would work exactly but as long as you're not setting your velocity to zero each step this should work.

    Edit: if the vector stuff doesn't make sense, I would recommend watching this video:
     
  6. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,046
    Wait, you just want each of the four separate hitboxes to affect enemies differently, right? I mean, you already have distinct hitbox objects, so give each hitbox its own code. If it collides with an enemy, reduce the enemy's hp and if that kills the enemy, set the hsp and vsp of the enemy as is appropriate, and put the enemy in a "knockback" state so it doesn't run its normal code while flying through the air.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice