Hi,

I'm trying to create simple 2d platformer touch screen controls without ui buttons. Basically what I'm trying to archieve is: touch and hold on either side of player to make her move towards that x direction, and to touch or swipe above the player to make her jump or climb.

Note that I'm a complete beginner with code.

I think I need to write something like:

var player position
var touch position (hold)
if touch position x > player position x
move +x (=left)
if touch position x < player position x
move -x (=right)
if touch position y < player position y
jump (or climb if ladder etc.)

I have no idea of the feasibility of this. Atleast jumping/climbing would probably would need some margins between player position and the touch position x/y, so that you need to touch/swipe pretty directy above the character, and similarly touch+hold x direction far enough from the character.

I'm grateful for any feedback, ideas and especially examples with code of how to write this.

in Engine

+1 vote
``````func _input(event):
if event is InputEventMouseButton:
if event.pressed:
var local_event = make_input_local(event)

if local_event.position.x > 100:
print("move right")
elif local_event.position.x < -100:
print("move left")
elif local_event.position.y in range(-100, -50):
print("climb")
``````

This will print "move right" if you click a position at least 100 pixels to the right from the node the script is attached to, "move left" if you click a position at least 100 pixels to the left of it or "climb" if both of these conditions are false and you click in a region in the area between 50 and 100 pixels above the node. Adjust the values to your liking.

by (10,311 points)
selected by

Thank you. I managed to create a simple set distance movement to those directions with a click on either side. Next I need to figure out how to create continuous movement with a held touch.

``````enum STATES {
MoveRight,
MoveLeft,
Climb,
Idle
}

func _input(event):
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
if event.pressed:
var local_event = make_input_local(event)

if local_event.position.x > 100:
state = STATES.MoveRight
elif local_event.position.x < -100:
state = STATES.MoveLeft
elif round(local_event.position.y) in range(-100, -50):
state = STATES.Climb
else:
state = STATES.Idle

func _physics_process(delta):
match state:
STATES.MoveRight:
print("Move Right")
STATES.MoveLeft:
print("Move Left")
STATES.Climb:
print("Climb")
``````

Replace the print-statements with your movement-code and the player character will move as long as you hold down the mouse-button / finger.

Note that I fixed two smaller issues in my code along the way:

1. I now ensure that `event.button_index == BUTTON_LEFT`
2. I round the y-position to an integer in order for the clim-condition to work

Thank you so much. I tried to do something similar with var and constants, but I didn't think of to use match state as a link between the input event and movement.

Now the basic movement works, and I understand how to try and tweak it further.

:)

``````extends KinematicBody2D

const ACCELERATION = 20
const GRAVITY = 20

const MAX_SPEED = 200
const JUMP_HEIGHT = -500
const UP = Vector2(0,-1)

var motion = Vector2()

enum STATES {
MoveRight,
MoveLeft,
Jump
Idle
}

func _input(event):
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
if event.pressed:
var local_event = make_input_local(event)

if local_event.position.x > 20: #and local_event.position.y > -50:
state = STATES.MoveRight
elif local_event.position.x < -20: #and local_event.position.y > -50:
state = STATES.MoveLeft
elif round(local_event.position.y) in range(-400, -20):
state = STATES.Jump
else:
state = STATES.Idle

func _physics_process(delta):
motion.y += GRAVITY
var friction = false
match state:
STATES.MoveRight:
motion.x = min(motion.x+ACCELERATION, MAX_SPEED)
\$Sprite.flip_h = false
\$Sprite.play("Run")
STATES.MoveLeft:
motion.x = max(motion.x-ACCELERATION, -MAX_SPEED)
\$Sprite.flip_h = true
\$Sprite.play("Run")
STATES.Idle:
\$Sprite.play("Idle")
friction = true
STATES.Jump:
if is_on_floor():
motion.y = JUMP_HEIGHT
if friction == true:
motion.x = lerp(motion.x, 0, 0.2)
if motion.y < 0:
\$Sprite.play("Jump")
else:
\$Sprite.play("Fall")
if friction == true:
motion.x = lerp(motion.x, 0, 0.1)

motion = move_and_slide(motion, UP)
pass

(I don't know why it formats this so badly)
``````

In order for code to be formatted correctly here, it needs to be indented by at least one level. Just select all of your code in the editor and click the button with the curly brackets "{ }" and it will be formatted automagically for you. ;)

Magic, thanks!