Sliding along "ice" in godot2d

Godot 4.3

Hey there, this is my first time posting in the forums so please forgive me if there’s any structural errors in how I’ve presented my question or if there’s mistakes in my grammar or terminology, and please let me know if there is. I’m fairly new to game programming, having made a couple of very simple games in unity and I’m brand new to godot.

Basically I’m creating a top down 2d game, where the player slides along some ice. The game uses grid based movement. At the moment I have constructed a small arena where there are 2 areas of land or “snow” on which the player can move around freely, 1 tile at a time and collides with any walls or obstacles.

What I’m struggling with is having the player slide along the ice. For that I need some conditions:

  1. The player travels continuously in the direction that they have entered the ice from until they either hit an wall/obstacle.
  2. Movement inputs are disabled while the player is sliding.
  3. Movement inputs are enabled if the player has stopped or is now off the ice.

I’m using custom data in the tile map named on_ice, which I’ve painted onto the ice tiles. This is called in a script that I’ve attached to my “world” and the player script calls it from there. So I have gone as far as the player being able to understand that it is on an ice tile. I’ve been trying different things for about 3 days, but I’m at a loss.

Here is my player script as it stands at the moment(I’ve deleted anything from the slide() function that hasn’t helped):

extends CharacterBody2D


#variables
@onready var ray = $RayCast2D
@onready var collider = $CollisionShape2D

const tile_size = 32
var moving = false
var sliding = false
var speed = 0.1
var input_dir
var speed_modifier := 1.0

#movement
func _physics_process(delta: float) -> void:
	
	var on_ice = false
	on_ice = World.get_custom_data_at(position, "is_ice")
	
	if on_ice == true:
		slide()
		
	if on_ice == false: # snow movement
		input_dir = Vector2.ZERO
		if Input.is_action_pressed("ui_down"):
			input_dir = Vector2(0,1)
			move()
		elif Input.is_action_pressed("ui_up"):
			input_dir = Vector2(0,-1)
			move()
		elif Input.is_action_pressed("ui_right"):
			input_dir = Vector2(1,0)
			move()
		elif Input.is_action_pressed("ui_left"):
			input_dir = Vector2(-1,0)
			move()
			
	move_and_slide()

func move():
	
	speed_modifier = World.get_custom_data_at(position, "speed_modifier")
	var move_speed = speed*speed_modifier
	
	var angle_dir = input_dir.angle() #raycast direction
	ray.rotation = angle_dir + PI/2
	ray.force_raycast_update()
	
	if !ray.is_colliding():
		if input_dir:
			if moving == false:
				moving = true
				var tween = create_tween()
				tween.tween_property(self, "position", position + input_dir*tile_size, move_speed)
				tween.tween_callback(move_false)

func slide():
	sliding = true
		

func move_false():
	moving = false

I finally solved it, I just made a while loop with the move function inside it, then changed the conditions to be able to use inputs as either not being on ice or being on ice and not moving.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.