How do I make my character jump when it hits an object?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By godotboy
:warning: Old Version Published before Godot 3 was released.

My character is kinematic body 2D and the object is area2D. My character has to accelerate up when it collides with the object. What’s a way to approach this? I’ve been stuck on this for hours and can’t find an answer.

If you have an acceleration variable, you can just give it a negative y value on collision.

How are you doing the movement? If you post your movement code, it might help to point you in the right direction.

kidscancode | 2017-09-23 01:31

Hi, thank you for responding. Acceleration variable has negative y value indeed. I tried using signal body.enter to resolve the issue, but it didn’t work. What do you see in my code that’s wrong?

extends KinematicBody2D

onready var ground_ray = get_node("ground_ray")
onready var bell = preload("res://bell.tscn")

const ACCEL = 1500
const MAX_SPEED = 500
const FRICTION = -500
const GRAVITY = 4000
const JUMP_SPEED = -1400
const MIN_JUMP = -500

var acc = Vector2()
var vel = Vector2()

func _ready():
	var b = bell.instance()
	b.connect("bell_out", self, "_on_bell_out")
	set_fixed_process(true)
	set_process_input(true)

func _input(event):
	if event.is_action_pressed("ui_up") and ground_ray.is_colliding(): 
		vel.y = JUMP_SPEED
		
func _on_bell_out():
	vel.y= JUMP_SPEED
	move(vel)

func _fixed_process(delta):
	acc.y = GRAVITY
	acc.x = Input.is_action_pressed("ui_right") - Input.is_action_pressed("ui_left")
	acc.x *= ACCEL
	if acc.x == 0:
		acc.x = vel.x * FRICTION * delta

	vel += acc * delta
	vel.x = clamp(vel.x, -MAX_SPEED, MAX_SPEED)

	var motion = move(vel * delta)
	if is_colliding():
		var n = get_collision_normal()
		motion = n.slide(motion)
		vel = n.slide(vel)
		move(motion)

godotboy | 2017-09-23 04:26

:bust_in_silhouette: Reply From: eons

If the second object is an area, it wont collide, it will overlap instead and only the area will detect that.

You have a couple of options:

-Make the area connect with it’s body_enter signal and tell the entering body (if is in the desired group/type) to do something.

-Another is to connect the body to all the areas that will affect it (depending of the game may be a good option, but is not common).

-Add an area to the body to detect other areas and connect to the parent body (may be a regular approach).

KinematicBody2D (main with script)
|-Shape
|-Area2D (connected to the parent on Area enter)
    |-Shape

Any area (in same mask/layer) will trigger, just filter by groups to get the proper reaction.

I tried the first option and it didn’t work at all even though it definitely should. Here’s the copy of my code for the player.

extends KinematicBody2D

onready var ground_ray = get_node("ground_ray")
onready var bell = preload("res://bell.tscn")
onready var collision = get_node("collision")

const ACCEL = 1500
const MAX_SPEED = 500
const FRICTION = -500
const GRAVITY = 4000
const JUMP_SPEED = -1400
const MIN_JUMP = -500

var acc = Vector2()
var vel = Vector2()

func _ready():
	set_fixed_process(true)
	set_process_input(true)
	var b = bell.instance()
	b.connect("bell_grabbed", self, "_on_bell_grabbed")

func _input(event):
	if event.is_action_pressed("ui_up") and ground_ray.is_colliding(): 
		vel.y = JUMP_SPEED

func _on_bell_grabbed():
	acc.y = JUMP_SPEED

func _fixed_process(delta):

	acc.y = GRAVITY
	acc.x = Input.is_action_pressed("ui_right") - Input.is_action_pressed("ui_left")
	acc.x *= ACCEL
	if acc.x == 0:
		acc.x = vel.x * FRICTION * delta

	vel += acc * delta
	vel.x = clamp(vel.x, -MAX_SPEED, MAX_SPEED)

	var motion = move(vel * delta)
	if is_colliding():
		var n = get_collision_normal()
		motion = n.slide(motion)
		vel = n.slide(vel)
		move(motion)

godotboy | 2017-09-23 15:42

Your bell is an area, if doing the 1st option it should have something like:

#after connecting itself
func _on_body_enter(body):
  #check if body is the player or in a group affected by bells
  body.got_bell(data_to_pass_to_the_body)

Then on the body that can “enter” the bell:

func got_bell(bell_data):
  do_something_with_bell_data()

Something to add, you are resetting acc.y on every fixed frame, any change you do to that value gets back to GRAVITY, maybe you may want to add a boost ratio instead, by default 1 and increased a bit by the bell grab.

acc.y = GRAVITY * boost

eons | 2017-09-23 21:51