Godot Version
4.3 stable
Question
i’m trying to make a super mario world overworld map for my game with up, down, right and left exit possibilities for the tiles it interacts with.
What keeps happening is i have the input of if pressed ‘Right’ to follow the set pathfollow2d but it only moves 4 pixels at a time not moving with delta. something is effecting this and I don;t know if once the player reaches the next tile will the new pathfollow2d be set?
here’s the code:
extends Node2D
class_name OverworldTile
signal send_level_name(level_name)
signal send_area_name(area_name)
signal send_level_path(level_scene_path)
@onready var overworld_player: OverworldPlayer = %OverworldPlayer
@export var move_speed := 4.0
@export var interation_enabled : bool = false
@export var level_scene_path : String
@export var level_name : String
@export var area_name : String
@export var revealed : bool = false
@export_group("ConnectedPaths")
@export var path_up : PathFollow2D
@export var path_down : PathFollow2D
@export var path_left : PathFollow2D
@export var path_right : PathFollow2D
@export_group("")
@export_group("Enabled Directions")
@export var can_move_up = false
@export var can_move_down = false
@export var can_move_left = false
@export var can_move_right = false
@export_group("")
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
pass
func _process(delta):
if Input.is_action_just_pressed("right") && can_move_right == true:
path_right_moving(delta)
func path_right_moving(delta):
move_speed = 4
path_right.progress += move_speed * delta
if path_right.progress_ratio == 1:
move_speed = 0
func _on_overworld_player_on_level():
send_level_name.emit(OverworldMan.level_name == level_name)
send_area_name.emit(OverworldMan.area_name == area_name)
send_level_path.emit(OverworldMan.level_scene_path == level_scene_path)
is_action_just_pressed only triggers for the first frame the input is pressed. Maybe you want is_action_pressed
same thing happens, I tried that, both pressed and just_pressed do the same thing, moves it 4 pixels then stops
is there any reason can_move_right
would be set to false? can you show more of your code, that just_pressed
condition is the only error I see.
this is all the code for this, the can_move_right is just to check on the tile that you can then it lets the player be able to use the input to move
If this is all the code then I promise you is_action_pressed
will work as long as can_move_right
is checked in the inspector. Even the progress_ratio == 1
check will likely fail, and the move_speed = 4
above it makes the check worthless as the movement has already been applied.
Are you reparenting somthing to another tile? This code doesn’t change the player either.
this code is for the level tiles, SMW blinking spaces, once the mario sprite is on it, it tells the overworld game manager what the level is and where that level scene is, if you can move to next level you can move mario using the remote transform node and it moves you to the next then reset so it can do it all again until a level scene is loaded.
If you have multiple of these tiles and no other scripts then they will all trigger the same movement at the same time, if each has a remote transform to the same one mario character, then the last in process order will be mario’s position, not any tile in specific.
is_action_pressed moves it smoothly but only if i hold it down, it like the delta input doesn’t even count, weird
delta
is only a floating point number, often 0.016
, this is the elapsed frame time, you can use delta to ensure time-based movement instead of frame-based movement; this time-based movement is more consistent on different hardware i.e. a player on a high framerate 144hz monitor takes the same amount of time to move as a standard 60hz player, if it was frame-based the 144hz player would move over twice as fast.
If you want the tiles to progress their entire path progress, you should use a tween instead, and only once, something like this
func _input(event: InputEvet) -> void:
if event.is_action_pressed("right") and can_move_right:
path_right_moving()
set_process_input(false) # disable further inputs
func path_right_moving():
var move_tween := path_right.create_tween()
const MOVE_TIME = 2.0 # seconds
move_tween.tween_property(path_right, "progress_ratio", 1.0, MOVE_TIME).from(0.0)
i forgot yes the overworld player has some script that deals with it, sorry i got mixed up. (i started the map screen about 2 weeks ago and only just got back to it so kinda trying to remember what i did.)
the tile is called TouchedTile in this
here’s the Overworld_player.gd:
extends CharacterBody2D
class_name OverworldPlayer
signal on_level()
signal off_level()
@onready var animated_sprite_2d: PlayerAnimatedMapSprite = $AnimatedSprite2D
@onready var interactive_level_tile: OverworldTile = $"../LevelHolder/InteractiveLevelTile"
@onready var interactive_level_tile_2: OverworldTile = $"../LevelHolder/InteractiveLevelTile2"
@onready var touched_tile = preload("res://Scripts/World_Scripts/interactive_overworld_tile.gd")
@onready var world_ui: WorldUI = $"../Camera2D/WorldUI"
@onready var level_start_text: Label = $"../Camera2D/LevelStart/LevelStartText"
@onready var level_start_black: ColorRect = $"../Camera2D/LevelStart/LevelStartBlack"
@onready var level_start: CanvasLayer = $"../Camera2D/LevelStart"
var input_free: bool
var levelname:String
var local_area: String
var level_path: String
@export var on_map_tile : bool = false
# Level Paths -------------------------------------------------------------------------------------
var path1_1_to_1_2 = false
var path1_2_to_1_1 = false
func _ready() -> void:
if OverworldMan.spawn_point != null && OverworldMan.spawn_point != Vector2.ZERO:
global_position = OverworldMan.spawn_point
input_free = true
level_start.visible = false
level_start_black.self_modulate.a = 0.0
level_start_text.self_modulate.a = 0.0
func _process(delta):
var path: Path2D = null
if Input.is_action_just_pressed("Up") and touched_tile.can_move_up:
animated_sprite_2d.play("Up")
touched_tile.path_movement_up
path = touched_tile.path_up
elif Input.is_action_just_pressed("down") and touched_tile.can_move_down:
animated_sprite_2d.play("Down")
touched_tile.path_movement_down
path = touched_tile.path_down
elif Input.is_action_just_pressed("left") and touched_tile.can_move_left:
animated_sprite_2d.play("Left")
touched_tile.path_movement_left
path = touched_tile.path_left
elif Input.is_action_just_pressed("right") and touched_tile.can_move_right:
animated_sprite_2d.play("Right")
touched_tile.path_movement_right
path = touched_tile.path_right
if not path:
return
#var movement: Vector2 = (position - prev_position)
#prev_position = position
#
#var moving_angle: float = movement.angle()
#if Util.between(moving_angle, -TAU / 8, TAU / 8):
#animated_sprite_2d.play("Left")
#elif Util.between(moving_angle, TAU, / 8, 3 * TAU / 8)
#animated_sprite_2d.play("Down")
#elif moving_angle >= 3 * TAU / 8 or moving_angle <= -3 * TAU / 8:
#animated_sprite_2d.play("Left")
#animated_sprite_2d.flip_h = true
#else:
#animated_sprite_2d.play("Up")
# Set pan speed
var PanSpeedKey = 8
# Called when the node enters the scene tree for the first time.
func _input(event):
if Input.is_action_just_pressed("jump") && on_level.connect(_on_interactive_level_tiel_area_entered) && input_free == true:
animated_sprite_2d.play("Enter")
input_free = false
level_start.visible = true
$"../Camera2D/Coin".play()
$"../WorldMapMusic".stop()
await get_tree().create_timer(0.8).timeout
level_start_black.self_modulate.a = 1.0
var tween = get_tree().create_tween()
tween.tween_property(level_start_black, "modulate:a", 0, 0)
tween.chain().tween_property(level_start_black, "modulate:a", 1, 0.2).finished
await get_tree().create_timer(0.5).timeout
level_start_text.self_modulate.a = 1.0
await get_tree().create_timer(1).timeout
SceneManager.change_scene(level_path, {"pattern": "squares", "speed": 6})
# Handles entering a level.
#func _handle_entering_level():
#
## if Mario isn't touching a level tile, do nothing
#if not touched_tile:
#return
#
## if Mario is still moving, do nothing.
#if moving:
#return
#
## if no butto to enter a level is pressed, do nothing.
#if not _enter_level_button_pressed():
#return
#
## if the level tile doesn't have a level scene set, return.
#if not touched_tile.level_scene_path:
#return
#
## emit the "entered level" signal
#entered_level.emit(touched_tile)
#func _on_interactive_overworld_tile_player_touched() -> void:
#
#func handle_level_tile_collision(collision: KinematicCollision2D):
#if collision.get_collider() is OverworldTile:
#if Input.is_action_just_pressed("jump"):
#handle_overworldtile_collision()
#
#func handle_overworldtile_collision():
#var overworld_tile = OverworldTile
#OverworldMan.level_name = levelname
func _on_interactive_level_tiel_area_entered(area: Area2D):
print("entered tile")
on_map_tile = true
levelname = interactive_level_tile.level_name
local_area = interactive_level_tile.area_name
level_path = interactive_level_tile.level_scene_path
OverworldMan.level_name = levelname
OverworldMan.area_name = local_area
OverworldMan.level_scene_path = level_path
on_level.emit("on_level")
func _on_interactive_level_tile_2_area_entered(area: Area2D):
print("entered tile")
on_map_tile = true
levelname = interactive_level_tile_2.level_name
local_area = interactive_level_tile_2.area_name
level_path = interactive_level_tile_2.level_scene_path
OverworldMan.level_name = levelname
OverworldMan.area_name = local_area
OverworldMan.level_scene_path = level_path
on_level.emit("on_level")
I am a newbie at this, this is my first fortay into programming and started in mid feb
Seems like you intend to call the path_movement_*
functions from here, but failed to add the parenthesis to actually call the function; you may be getting several script warnings along the lines of “this statement has no effect”
Try adding parenthesis, for example
elif Input.is_action_just_pressed("right") and touched_tile.can_move_right:
animated_sprite_2d.play("Right")
touched_tile.path_movement_right() # with parenthesis
path = touched_tile.path_right
I do that but it come back with an error:
cannot call non-static function “path_movement_right()” on this class “OverworldTile” directly. Make and instance instead
Ah, your touched_tile
is a preload to the script, not an actual tile. Not sure how you’d want to fix that, suppose it should be an @export var touched_tile: Node
, or deduced through some collision detection like _on_interactive_level_tiel_area_entered
seems to be handling.
so while player is colliding with the area2d of the level tile, it can change a var in player, say it’s called Tile_path_right and when the _on_interactive_level_tiel_area_entered is working it makes the Tile_path_right work with the touched_tile function “Path_movement_right()” ?
also when i put that into the _on_interactive_leve_tiel_area_entered, the path_movement_right()
wants delta in the parenthesis but it’s not in that part what could i put for it to ignore it since I know null will just kill it?
wish there was a tutorial for something even close to this on multiple pathfollow2d on a map but they’re isn’t