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)