How do i change direction with collisions? (Solved)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By KND2501

I want to change direction on the x axis wheneveris_on_wall.

I almost got it…

extends KinematicBody2D

const UP = Vector2(0, -1)
const GRAVITY = 20

var motion = Vector2()
var left = Vector2(-1, 0)
var right = Vector2(1, 0)

func _physics_process(delta):
motion.y += GRAVITY
motion = move_and_slide(motion, UP)
position += left

if is_on_wall():
	if left == left:
		left = right
	if right == right:
		right = left

Now whenever i hit a wall going left it will start moving right, but hitting a wall while moving right still makes it wants to keep moving right?!

KND2501 | 2018-03-09 23:25

UPDATED && OPTIMIZED

extends KinematicBody2D

const UP : = Vector2(0, -1)
const GRAVITY : = 20
const SPEED : = 300

var motion : = Vector2.ZERO
var direction : = 1.0

func _physics_process(delta: float) -> void:
     motion.y += GRAVITY
     motion.x = direction * SPEED
     motion = move_and_slide(motion, UP)

if is_on_wall():
	direction*=-1

To get autocompletion for this func _physics_process(delta: float) → void
go to editor settings >search for “add type hints” click “ON”

Adil | 2019-12-07 09:01

:bust_in_silhouette: Reply From: KoBeWi

In the code provided in your comment, you overwrite your directional vector. You should introduce another vector, which is either left or right depending on current movement.

var move = left

func _physics_process(delta):
    ...
    position += move

    if is_on_wall():
        if move == left:
            move = right
        elif move == right: #note the elif instead of if
            move = left

btw, why are you changing position directly? That’s what move_and_slide() is for. You should update your motion.x.

You should note i have no idea what i’m doing.

I’m changing position directly because its movement is not controlled by inputs, otherwise it just sits till.

So i am looking at your example, changed the var move to var direction . But it does exactly the same as what i had before.

extends KinematicBody2D

const UP = Vector2(0, -1)
const GRAVITY = 20

var motion = Vector2()
var left = Vector2(-1, 0)
var right = Vector2(1, 0)
var direction = left

func _physics_process(delta):
motion.y += GRAVITY
motion = move_and_slide(motion, UP)
position += direction

if is_on_wall():
	if direction == left:
		direction = right
		print("AAAA")
	elif direction == right:
		right = left
		print("BBBB")

KND2501 | 2018-03-10 00:17

You should note i have no idea what i’m doing.

Well, I’m not sure what you are trying to achieve too xd

What I mean by changing motion is something like this:

motion.y += GRAVITY
motion.x = direction.x

Then you should be able to move without changing position manually.
So, what exactly is the problem you have? I didn’t test the code, but seems like it should work with these changes. What is the output from print?

KoBeWi | 2018-03-10 00:41

Basically i am making a Goomba.

Kinematicbody2D just starts moving in a set direction (left), and whenever it hits a wall it changes direction until it hits another wall and changes direction again etc.

So far i got it to move and change direction from left to right upon collision with the wall.

The problem is having it change direction from right to left and i think it has got to do with the initial motion.

KND2501 | 2018-03-10 00:59

OMG. I just noticed you made a mistake in your code. You still have right = left after elif. It should be direction = left.

KoBeWi | 2018-03-10 01:18

Not a mistake, if i change it to =left it actually starts bouncing in the corner. If i change the other one to =right then its just stuck in the corner.

The direction variable doesn’t seem to work, i can achieve the same result i have now with less code. If i go back to this (i simplified it a bit) then i’m almost there:

position += left

if is_on_wall():
	if left:
		left = right
		print("AAAA")
	elif right:
		right = left
		print("BBBB")

But it won’t return my print("BBBB") because it’s always going position += left i think.

KND2501 | 2018-03-10 01:40

Ok, I made a test game specifically for this. Here’s the working code:

extends KinematicBody2D

const UP = Vector2(0, -1)
const GRAVITY = 20
const SPEED = 100

var motion = Vector2()
var left = Vector2(-1, 0)
var right = Vector2(1, 0)
var direction = left

func _physics_process(delta):
	motion.y += GRAVITY
	motion.x = direction.x * SPEED
	motion = move_and_slide(motion, UP)
	
	if is_on_wall():
		if direction == left:
			direction = right
		elif direction == right:
			direction = left

Now, what you do with left = right and right = left is totally wrong. Here’s what happens in your code:
-game starts, object moves left (-1, 0)
-object meets a wall, so the left is now right (1, 0)
-it meets another wall, and now, what it actually does is right = right.

That is because you modify your original vector. Remember that if you make a var in your object, modifying it will modify the original (if I’d want to explain it clearly). So doing left = right will permanently overwrite left, so it is now right. That’s why doing right = left then is basically making the variable assign itself.

Also, my code works, because you need to use move_and_slide() to determine whether something is on the wall. If you move only vertically, you are never on wall, so your is_on_wall() should always be false.
I don’t know how your original code worked (it didn’t for me), because when you hit the wall that way, you shouldn’t be able to bounce. The object just gets stuck (and is apparently pushed back by physics).

KoBeWi | 2018-03-10 02:03

Your code works! Yeah i saw a tutorial using a simular method to my right/left stuff, so i tried to adapt the code.

So yeah this is basically want i want, but i notice now it collides with the player as well, when before it would push me aside.

So before i used to move the “goomba” pixel by pixel, now i’m using physics right? What if i want to use pixel by pixel movement instead?

Thanx for thinking along btw.

KND2501 | 2018-03-10 02:19

Well, I never used pixel-by-pixel movement in Godot, so I don’t know how to handle collisions.

If you don’t want your Goomba to collide with player, modify their collisions layers. There’s a property in KinematicBody2D in inspector that let’s you change this. If they have collision layer 1 turned off, it means that nothing can collide with them, but they will still collide with environment if their collision masks are turned on.

KoBeWi | 2018-03-10 13:33

Actually i turned goomba in a bunny rabbit, just hopping around no collision.

What i meant was your method seems to interact with physics, while the other would override physics and just push through. That be nice for moving platforms.

Anyway thanx.

KND2501 | 2018-03-11 02:25

:bust_in_silhouette: Reply From: KND2501

Solution by KoBeWii

extends KinematicBody2D

const UP = Vector2(0, -1)
const GRAVITY = 20
const SPEED = 100

var motion = Vector2()
var left = Vector2(-1, 0)
var right = Vector2(1, 0)
var direction = left

func _physics_process(delta):
    motion.y += GRAVITY
    motion.x = direction.x * SPEED
    motion = move_and_slide(motion, UP)

if is_on_wall():
    if direction == left:
        direction = right
    elif direction == right:
        direction = left