Killed 3 days, can't find an issue 0.0 point

Godot Version

4.3

Question

Hello everyone.

I am new to the engine and programming. I am making a game that has a map of a real city and objects on it. At the moment there is a character and a car.

Both are not set at point 0.0.

The problem is that initially both the car and the character moved to point zero immediately after loading the map.

At the moment the character stands still, but as soon as you get into the car and get out - it also goes to point zero.
I don’t know where to look, I suspect that this is an error like an incorrect line or condition, but due to inexperience I can’t figure out where it is.

Car Script
extends CharacterBody2D

@onready var fuel_gauge: TextureRect = $FuelGaugeSystem/FuelGauge
@onready var fuel_needle: TextureRect = $FuelGaugeSystem/FuelNeedle
@onready var speed_gauge: TextureRect = $SpeedGaugeSystem/SpeedGauge
@onready var speed_needle: TextureRect = $SpeedGaugeSystem/SpeedNeedle
@onready var odometer_label: Label = $SpeedGaugeSystem/OdometerLabel

@onready var car_start_audio: AudioStreamPlayer = $Sounds/CarStartAudio
@onready var car_off_audio: AudioStreamPlayer = $Sounds/CarOffAudio
@onready var car_start_no_fuel_audio: AudioStreamPlayer = $Sounds/CarStartNoFuelAudio
@onready var car_idle_audio: AudioStreamPlayer = $Sounds/CarIdleAudio

@onready var enter_hint_label: Label = $EnterHintLabel
@onready var car_menu: Control = $EnterHintLabel/CarMenu
@onready var car_menu_button: Button = $SpeedGaugeSystem/SpeedGauge/CarMenuButton

@export var fuel_consumption = 0.0000067 # Fuel consumption per unit distance
@export var max_fuel: int = 450000 # Maximum fuel level
@export var current_fuel: int = max_fuel
@export var max_speed: float = 37.5
@export var gear = -1 # Current gear (-1 means neutral)
@export var max_gear = 6 # Maximum gear
@export var gear_speeds = [0.0, 5.56, 11.11, 16.67, 22.22, 27.78, 37.5] # Speeds for each gear
@export var acceleration: float = 1.0 # Car acceleration
@export var deceleration: float = 10.0 # Car deceleration
@export var acceleration_smoothness: float = 5.0 # Smoothness parameter for acceleration and deceleration

@export var driver_seat_position: Vector2
@export var passenger_seat_positions: Array = [“Passenger - Front Seat”, “Passenger - Back”] # Array for passenger positions

@export var idle_audio_min_volume: float = -7.0 # Minimum idle audio volume
@export var idle_audio_max_volume: float = 1.0 # Maximum idle audio volume
@export var idle_audio_min_pitch: float = 1.0 # Minimum idle audio pitch
@export var idle_audio_max_pitch: float = 1.3 # Maximum idle audio pitch

@export var map_scale: float = 0.0027 # Scale 1:34000 (1 game unit = 0.34 km)

var target_speed: float = 0.0 # Target speed
var current_speed: float = 0.0 # Current speed

var click_position = Vector2(-1, -1)
var target_position = Vector2(-1, -1)

var engine_running = false # Engine state
var ignition_on = false # Ignition state
var fuel_indicator_visible = false # Fuel indicator visibility
var speed_indicator_visible = false
var total_distance: float = 0.0 # Total distance traveled

var activePlayer = false # Active player
var player_in_car = false # Player in car
var player_exited = false

var ignition_audio_finished = false # Flag for ignition audio completion
var can_shift_gears: bool = true # Flag for gear shifting

func _ready() → void:
fuel_gauge.visible = false
fuel_needle.visible = false
enter_hint_label.visible = false
car_menu.visible = false
speed_gauge.visible = false
speed_needle.visible = false
odometer_label.text = str(total_distance * map_scale)

print("Click Position: ", click_position)
print("Target Position: ", target_position)

func _input(event):
# Handle input
if event.is_action_pressed(“interaction”) and enter_hint_label.visible:
_on_car_menu_button_pressed()

if player_in_car and ignition_audio_finished:
    if event.is_action_pressed("shift_gear_up") and gear < max_gear:
        gear += 1
        print("Gear Up: ", gear)
    
    if event.is_action_pressed("shift_gear_down") and gear > 0:
        gear -= 1
        print("Gear Down: ", gear)

if Input.is_action_just_pressed("quit"):
    get_tree().quit()

func _control_car():
# Enter the car
var player = get_tree().get_first_node_in_group(“player”)
if player:
activePlayer = true
player_in_car = true
player.visible = false
player.set_process(false)
player.set_physics_process(false)

fuel_indicator_visible = true
fuel_gauge.visible = true 
fuel_needle.visible = true 

speed_indicator_visible = true
speed_gauge.visible = true
speed_needle.visible = true

print("Click Position in _control_car: ", click_position)
print("Target Position in _control_car: ", target_position)

func _leave_car():
var player = get_tree().get_first_node_in_group(“player”)
if player:
activePlayer = false
player_in_car = false
player.visible = true
player.set_process(true)
player.set_physics_process(true)

    # Set player position
    player.global_position = global_position
    print("Player Position in _leave_car: ", player.global_position)

fuel_indicator_visible = false
fuel_gauge.visible = false
fuel_needle.visible = false

speed_indicator_visible = false
speed_gauge.visible = false
speed_needle.visible = false

func _on_car_start_audio_finished() → void:
ignition_audio_finished = true
can_shift_gears = true # Allow gear shifting after ignition audio finishes

func _physics_process(_delta: float) → void:
if not activePlayer: return

if Input.is_action_just_pressed("Action"):
    click_position = get_global_mouse_position()

if position.distance_to(click_position) > 3:
    target_position = (click_position - position).normalized()
else:
    target_position = Vector2()   

var gear_index = clamp(gear, 0, gear_speeds.size() - 1)

if engine_running and ignition_on:
    target_speed = gear_speeds[gear_index]
else:
    target_speed = 0.0   

if current_speed < target_speed:
    current_speed = min(current_speed + acceleration * _delta, target_speed)
else:
    current_speed = max(current_speed - deceleration * _delta, target_speed)

velocity = target_position * current_speed
move_and_slide()

if Input.is_action_just_pressed("ignition"):
    if current_fuel > 0:
        ignition_on = not ignition_on
        if ignition_on:
            engine_running = true
            car_start_audio.play()
            ignition_audio_finished = false
            can_shift_gears = false
        else:
            engine_running = false
            car_off_audio.play()
            if car_idle_audio.playing:
                car_idle_audio.stop()
                gear = -1
            elif car_start_audio.playing:
                car_start_audio.stop()
    else:
        car_start_no_fuel_audio.play()

if engine_running:
    current_fuel -= (fuel_consumption * current_speed * current_speed * _delta)
    total_distance += current_speed * _delta
    _update_odometer()
    
    if ignition_audio_finished:
        if not car_idle_audio.playing:
            car_idle_audio.play()

        var normalized_speed = float(current_speed) / max_speed
        car_idle_audio.volume_db = lerp(idle_audio_min_volume, idle_audio_max_volume, normalized_speed)
        car_idle_audio.pitch_scale = lerp(idle_audio_min_pitch, idle_audio_max_pitch, normalized_speed)
    else:
        if car_idle_audio.playing:
            car_idle_audio.stop()

if current_fuel <= 0:
    if engine_running:
        current_fuel = 0
        current_speed = 0
        engine_running = false
        ignition_on = false
        car_idle_audio.stop()
        car_off_audio.play()
    else:
        current_fuel = 0
    
current_fuel = clamp(current_fuel, 0, max_fuel)
_update_fuel_gauge()
_update_speedometer()

func _update_fuel_gauge() → void:
if fuel_needle:
var normalized_fuel = float(current_fuel) / max_fuel
var min_angle = deg_to_rad(-255)
var max_angle = deg_to_rad(-100)
var angle = lerp_angle(min_angle, max_angle, normalized_fuel)
fuel_needle.rotation = angle

func _update_speedometer() → void:
if speed_needle:
var normalized_speed = float(current_speed) / max_speed
var min_angle = deg_to_rad(-130)
var max_angle = deg_to_rad(69)
var angle = lerp(min_angle, max_angle, normalized_speed)
speed_needle.rotation = angle

func _update_odometer() → void:
var distance_in_km = total_distance * map_scale
odometer_label.text = str(round(distance_in_km))

func _on_area_2d_body_entered(body):
if body == get_tree().get_first_node_in_group(“player”):
enter_hint_label.show()

func _on_area_2d_body_exited(body):
if body == get_tree().get_first_node_in_group(“player”) and player_in_car:
enter_hint_label.show()
else:
enter_hint_label.hide()

func _on_driver_pressed() → void:
if player_in_car:
_leave_car()
else:
_control_car()

func _on_passenger_front_pressed() → void:
pass # Replace with function body.

func _on_passenger_back_r_pressed() → void:
pass # Replace with function body.

func _on_passenger_back_l_pressed() → void:
pass # Replace with function body.

func _on_passenger_back_c_pressed() → void:
pass # Replace with function body.

func _on_car_menu_button_pressed() → void:
car_menu.visible = not car_menu.visible


Player Script
extends CharacterBody2D

The Player class handles player control

class_name Player

UI elements

@onready var stamina_bar: ProgressBar = $StatusPanel/StatusLayer/Panel/Stamina/StaminaBar
@onready var thirst_bar: ProgressBar = $StatusPanel/StatusLayer/Panel/Thirst/ThirstBar
@onready var hunger_bar: ProgressBar = $StatusPanel/StatusLayer/Panel/Hunger/HungerBar

Audio elements

@onready var walk_sound: AudioStreamPlayer2D = $Sounds/WalkSound

State parameters

@export var max_thirst: float = 100
@export var max_hunger: float = 100
@export var thirst_increase_rate: float = 0.009
@export var hunger_increase_rate: float = 0.001

var stamina = 100.0
var current_thirst: float = 0
var current_hunger: float = 0
var click_position = Vector2(-1, -1) # Initialize to an invalid value
var target_position = Vector2(-1, -1) # Initialize to an invalid value
var walk_speed = 3.0
var run_speed = 6
var slow_speed = 1.2
var stamina_depletion_rate = 0.1
var run_step_interval = 0.3
var walk_step_interval = 0.5
var step_timer = 0.0
var is_running = false
var activePlayer = true

func _ready():
# Initialize player
add_to_group(“player”)
walk_sound.stream = preload(“res://Materials/Character/WalkSound.wav”)

func on_exit_pressed():
# Exit the game
get_tree().quit()

func _physics_process(delta):
# Handle physics
if not activePlayer: return

handle_input()
update_movement(delta)
update_state(delta)
play_step_sound(delta)

func handle_input():
# Handle input
if Input.is_action_just_pressed(“Action”):
var mouse_pos = get_global_mouse_position()
if mouse_pos != position:
click_position = mouse_pos

if Input.is_action_just_pressed("move_mode"):  
    is_running = !is_running

if click_position != Vector2(-1, -1) and position.distance_to(click_position) > 3:
    target_position = (click_position - position).normalized()
else:
    target_position = Vector2.ZERO

func update_movement(delta):
# Update movement
var current_speed = walk_speed
var local_thirst_increase_rate = thirst_increase_rate
var local_hunger_increase_rate = hunger_increase_rate

if stamina <= 100.0:
    run_speed = 5.5
    local_thirst_increase_rate = 0.020
    local_hunger_increase_rate = 0.013
if stamina <= 70.0:
    run_speed = 5
    stamina_depletion_rate = 0.4
if stamina <= 60.0:
    run_speed = 4.3
    local_thirst_increase_rate = 0.029
    local_hunger_increase_rate = 0.018
if stamina <= 55.0:
    run_speed = 3.8
    local_thirst_increase_rate = 0.037
    local_hunger_increase_rate = 0.023
if stamina <= 40.0:
    run_speed = 3.3
    local_thirst_increase_rate = 0.055
    local_hunger_increase_rate = 0.032

if is_running and stamina > 0:
    current_speed = run_speed
    if target_position.length() > 0:
        stamina -= stamina_depletion_rate * delta * run_speed
    step_timer -= delta
else:
    current_speed = slow_speed
    step_timer -= delta

if target_position.length() > 0:
    current_thirst += local_thirst_increase_rate * delta * current_speed
    current_hunger += local_hunger_increase_rate * delta * current_speed
else:
    current_thirst += local_thirst_increase_rate * delta
    current_hunger += local_hunger_increase_rate * delta

current_thirst = clamp(current_thirst, 0, max_thirst)
current_hunger = clamp(current_hunger, 0, max_hunger)
stamina_bar.value = stamina
thirst_bar.value = current_thirst
hunger_bar.value = current_hunger

velocity = target_position * current_speed
move_and_slide()

if stamina < 100.0:
    if target_position.length() == 0:
        stamina += 0.5 * delta
    else:
        stamina += 0.2 * delta
    stamina = min(stamina, 100.0)

func update_state(delta):
# Update state
_update_thirst_bar()
_update_hunger_bar()

func play_step_sound(delta):
# Play step sound
var step_interval = run_step_interval if is_running else walk_step_interval
if target_position.length() > 0 and step_timer <= 0.0:
walk_sound.play()
step_timer = step_interval
else:
step_timer = max(step_timer, 0)

func _update_thirst_bar() → void:
# Update thirst indicator
if $StatusPanel:
thirst_bar.value = (current_thirst / max_thirst) * 100.0

func _update_hunger_bar() → void:
# Update hunger indicator
if $StatusPanel:
hunger_bar.value = (current_hunger / max_hunger) * 100.0

func _drink(amount: float) → void:
# Decrease thirst
current_thirst -= amount
current_thirst = clamp(current_thirst, 0, max_thirst)

func _eat(amount: float) → void:
# Decrease hunger
current_hunger -= amount
current_hunger = clamp(current_hunger, 0, max_hunger)

  1. Format your code, hard to read

Ex.
Car.gd :

extends CharacterBody2D

@onready var fuel_gauge: TextureRect = $FuelGaugeSystem/FuelGauge
@onready var fuel_needle: TextureRect = $FuelGaugeSystem/FuelNeedle
...

Thats how it look in editor
image

  1. Show scene tree with car and player nodes at your game level

I can guess, this code executed when player leaves car

player.global_position = global_position

In reality it mean

player.global_position = self.global_position

and it seems like Car script, so self is Car and if Car in postion 0.0 player also become in position 0.0


Initially they placed where you place them in editor, if you not create them with code in level script, but keep in mind global_position is position relative to all parant nodes,
For example you must have something like

World(Node2D, position 0;0)
  Level(Node2D, position 0;0)
  Car(CharacterBody2D, position 100;100)
  Player(CharacterBody2D, position 150;100)
2 Likes

Hello, bro

The thing is, I took the map, and it’s huge. And the characters will be saved where possible, and not start over from the initial point every time.

And yes, the hierarchy looks exactly as you said. GameScene - City - Car - Character
The problem is with exiting back from the car. The player is unpaused and becomes available again. But, apparently, the problem is in the character itself. In the car, I fixed the same situation in which it was driving in 0.0 - with one line in the ready. It doesn’t work with the player. Something conflicts

I’m already starting to think that maybe it’s worth getting around this somehow with the help of saves. But I’m not sure that in the future this conflict won’t become bigger

Or maybe there’s something in the inspector somewhere that affects it?

Now it goes not to the 00 point, but to the right.
Here is the log

Click Position: (-156, 341)
Target Position: (-156, 341)
Click Position in _control_car: (-155, 331)
Target Position in _control_car: (-1, -1)
Player Position in _leave_car: (-155, 331)
Click Position: (-114.5, 292)
Target Position: (0.72032, -0.693642)
Click Position in _control_car: (-114.5, 292)
Target Position in _control_car: (0.72032, -0.693642)
Player Position in _leave_car: (-155, 331)
Click Position: (-111.5, 291)
Target Position: (0.7361, -0.676873)

I do not understand,
may be problem here:

target_position = (click_position - position).normalized()

you take direction as global position - local position

1 Like

I don’t know how, but everything resolved itself. I don’t understand why this happened, but the player no longer goes to the 0 point
But, there is another problem - the mouse clicks through the inventory window