martes, 27 de octubre de 2026

Maravilloso GDScript para manejar una camara fija en Godot 4.7 ; en 3d;

 extends Camera3D


@export_group("Movimiento y Cámara")

@export var speed: float = 5.0

@export var mouse_sensitivity: float = 0.003


@export_group("Zoom / Enfoque (Rueda del Ratón)")

@export var zoom_speed: float = 3.0

@export var min_fov: float = 10.0   # Enfoque máximo (teleobjetivo)

@export var max_fov: float = 120.0   # Enfoque mínimo (gran angular)


@export_group("Límites de Desplazamiento (Metros)")

@export var limit_forward: float = 10.0    # Máximo W (Adelante)

@export var limit_backward: float = 5.0    # Máximo S (Atrás)

@export var limit_left: float = 8.0        # Máximo A (Izquierda)

@export var limit_right: float = 8.0       # Máximo D (Derecha)


var rotation_x: float = 0.0

var start_position: Vector3


func _ready() -> void:

Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

start_position = global_position


func _unhandled_input(event: InputEvent) -> void:

if event.is_action_pressed("ui_cancel") or (event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE):

get_tree().quit()


# Control de la vista con el movimiento del ratón

if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:

rotate_y(-event.relative.x * mouse_sensitivity)

rotation_x -= event.relative.y * mouse_sensitivity

rotation_x = clamp(rotation_x, deg_to_rad(-89.0), deg_to_rad(89.0))

rotation.x = rotation_x


# Control del zoom / enfoque con la rueda del ratón

if event is InputEventMouseButton and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:

if event.pressed:

if event.button_index == MOUSE_BUTTON_WHEEL_UP:

fov = clamp(fov - zoom_speed, min_fov, max_fov)

elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:

fov = clamp(fov + zoom_speed, min_fov, max_fov)


func _process(delta: float) -> void:

var input_dir := Vector3.ZERO


if Input.is_key_pressed(KEY_W):

input_dir.z -= 1  # W: Adelante

if Input.is_key_pressed(KEY_S):

input_dir.z += 1  # S: Atrás

if Input.is_key_pressed(KEY_A):

input_dir.x -= 1  # A: Izquierda

if Input.is_key_pressed(KEY_D):

input_dir.x += 1  # D: Derecha


if input_dir != Vector3.ZERO:

input_dir = input_dir.normalized()


# Movemos en el plano horizontal para no volar al mirar arriba/abajo

var forward := -global_transform.basis.z

forward.y = 0

forward = forward.normalized()


var right := global_transform.basis.x

right.y = 0

right = right.normalized()


# Calculamos el intento de movimiento

var movement := (right * input_dir.x + forward * -input_dir.z) * speed * delta

var target_position := global_position + movement


# Medimos la distancia acumulada desde el origen

var offset := target_position - start_position


# Aplicamos los 4 límites independientes (W, S, A, D)

offset.x = clamp(offset.x, -limit_left, limit_right)

offset.z = clamp(offset.z, -limit_forward, limit_backward)


# Asignamos la posición corregida manteniendo la altura fija (Y)

global_position = Vector3(start_position.x + offset.x, start_position.y, start_position.z + offset.z)



-------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------

Explicacion, caracteristicas: Enfoque  desde rueda del mouse, giros de 360 grador en eje -y- limitaciones de avance por escenario , con teclas -w-a-s-d-.....todo calibrado desde el inspector.




martes, 20 de octubre de 2026

GDScript para Godot 3d 4.7; abre una puerta y emite su sonido;

 extends Area3D


@export var velocidad: float = 2.0

@export var distancia_x: float = 22222.5


# Rutas exactas basadas en tu árbol de nodos

@onready var mesh_instance: MeshInstance3D = $CollisionShape3D/MeshInstance3D

@onready var audio_player: AudioStreamPlayer3D = $CollisionShape3D/MeshInstance3D/AudioStreamPlayer3D


var posicion_inicial_x: float = 0.0

var moviendo: bool = false


func _ready() -> void:

if mesh_instance:

posicion_inicial_x = mesh_instance.position.x

area_entered.connect(_on_area_entered)


func _process(delta: float) -> void:

if not mesh_instance:

return

var objetivo_x = posicion_inicial_x + distancia_x if moviendo else posicion_inicial_x

mesh_instance.position.x = move_toward(mesh_instance.position.x, objetivo_x, velocidad * delta)


func _on_area_entered(area: Area3D) -> void:

if not moviendo:

moviendo = true

# Reproducimos el sonido 3D de forma segura

if audio_player and audio_player.stream and not audio_player.playing:

audio_player.play()



domingo, 11 de octubre de 2026

Excelente GDScript para manejar personaje en Godot 4.7, calibacion de animaciones y sonidos desde inspector;

 extends Node3D


var anim_player: AnimationPlayer


# Nombres de las animaciones para tener el código limpio

const ANIM_RELAX: String = "MakeHuman default skeleton|RELAX"

const ANIM_ANDAR: String = "MakeHuman default skeleton|ANDAR"

const ANIM_ZARPAZO: String = "MakeHuman default skeleton|ZARPAZO"

const ANIM_MANOTAZO: String = "MakeHuman default skeleton|MANOTAZO"

const ANIM_FURIA: String = "MakeHuman default skeleton|FURIA"


# -------------------------------------------------------------

# AJUSTES CALIBRABLES DESDE EL INSPECTOR

# -------------------------------------------------------------

@export_group("Transición de Animaciones")

@export_range(0.0, 1.0, 0.05) var tiempo_transicion: float = 0.2 # Tiempo de suavizado entre animaciones


@export_group("Velocidad de Animaciones")

@export_range(0.1, 5.0, 0.05) var vel_relax: float = 1.0

@export_range(0.1, 5.0, 0.05) var vel_andar: float = 1.0

@export_range(0.1, 25.0, 0.05) var vel_zarpazo: float = 1.0

@export_range(0.1, 25.0, 0.05) var vel_manotazo: float = 1.0

@export_range(0.1, 5.0, 0.05) var vel_furia: float = 1.0


func _ready() -> void:

# Busca el AnimationPlayer dentro de este nodo y sus hijos

anim_player = buscar_animation_player_propio(self)

if anim_player:

print("¡AnimationPlayer propio del personaje encontrado con éxito!")

# Configura RELAX y ANDAR en Ping-Pong

asegurar_pingpong(ANIM_RELAX)

asegurar_pingpong(ANIM_ANDAR)

# Arranca en RELAX

reproducir(ANIM_RELAX)

else:

print("ERROR: No se encuentra ningún AnimationPlayer dentro de este personaje.")


func buscar_animation_player_propio(nodo: Node) -> AnimationPlayer:

if nodo is AnimationPlayer:

return nodo as AnimationPlayer

for hijo in nodo.get_children():

var resultado = buscar_animation_player_propio(hijo)

if resultado:

return resultado

return null


func _unhandled_input(event: InputEvent) -> void:

if not anim_player:

return


# -------------------------------------------------------------

# 1. CUANDO SE PRESIONA UNA TECLA O BOTÓN (ACCIONES)

# -------------------------------------------------------------

if event.is_pressed() and not event.is_echo():

# Clic Izquierdo -> ZARPAZO + Sonido del ratón

if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:

reproducir(ANIM_ZARPAZO)

if has_node("AudioStreamPlayer3D2") and not $AudioStreamPlayer3D2.playing:

$AudioStreamPlayer3D2.play()

return

# Clic Derecho -> MANOTAZO

if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT:

reproducir(ANIM_MANOTAZO)

return


# Teclado

if event is InputEventKey:

match event.keycode:

KEY_W:

reproducir(ANIM_ANDAR)

# Sonido al caminar con W (solo si no está sonando ya)

if has_node("AudioStreamPlayer3D2CAMINA2") and not $AudioStreamPlayer3D2CAMINA2.playing:

$AudioStreamPlayer3D2CAMINA2.play()

KEY_P:

reproducir(ANIM_ZARPAZO)

if has_node("AudioStreamPlayer3D") and not $AudioStreamPlayer3D2.playing:

$AudioStreamPlayer3D2.play()

KEY_I:

reproducir(ANIM_FURIA)

KEY_O:

reproducir(ANIM_RELAX)


# -------------------------------------------------------------

# 2. CUANDO SE SUELTA CUALQUIER TECLA O BOTÓN -> VOLVER A RELAX

# -------------------------------------------------------------

if not event.is_pressed():

# Si soltamos cualquier botón/tecla y no queda NINGUNA otra pulsada, pasa a RELAX

if not hay_entrada_activa():

reproducir(ANIM_RELAX)


# Comprueba si el usuario tiene mantenida alguna tecla o botón de acción

func hay_entrada_activa() -> bool:

return Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) \

or Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT) \

or Input.is_key_pressed(KEY_W) \

or Input.is_key_pressed(KEY_P) \

or Input.is_key_pressed(KEY_I) \

or Input.is_key_pressed(KEY_O)


# Activa el modo Loop lineal (bucle normal)

func asegurar_loop(nombre: String) -> void:

if anim_player.has_animation(nombre):

var anim = anim_player.get_animation(nombre)

anim.loop_mode = Animation.LOOP_LINEAR


# Activa el modo Ping-Pong (ida y vuelta continua)

func asegurar_pingpong(nombre: String) -> void:

if anim_player.has_animation(nombre):

var anim = anim_player.get_animation(nombre)

anim.loop_mode = Animation.LOOP_PINGPONG


# Devuelve la velocidad asignada a la animación indicada

func obtener_velocidad(nombre: String) -> float:

match nombre:

ANIM_RELAX: return vel_relax

ANIM_ANDAR: return vel_andar

ANIM_ZARPAZO: return vel_zarpazo

ANIM_MANOTAZO: return vel_manotazo

ANIM_FURIA: return vel_furia

_: return 1.0


func reproducir(nombre: String) -> void:

if anim_player.has_animation(nombre):

# Solo cambia si la animación solicitada no es la que ya está sonando

if anim_player.current_animation != nombre:

var vel: float = obtener_velocidad(nombre)

# Pasamos 'tiempo_transicion' como custom_blend (segundo parámetro)

anim_player.play(nombre, tiempo_transicion, vel)

print("Reproduciendo: ", nombre, " (Velocidad: ", vel, " | Transición: ", tiempo_transicion, "s)")

else:

print("La animación '", nombre, "' no existe en este AnimationPlayer.")


martes, 6 de octubre de 2026

GDScript para manejar personaje en Godot 4.7 3d; permite calibrar velocidad de cada animacion diferente desde inspector;

 extends Node3D


var anim_player: AnimationPlayer


# Nombres de las animaciones para tener el código limpio

const ANIM_RELAX: String = "MakeHuman default skeleton|RELAX"

const ANIM_ANDAR: String = "MakeHuman default skeleton|ANDAR"

const ANIM_ZARPAZO: String = "MakeHuman default skeleton|ZARPAZO"

const ANIM_MANOTAZO: String = "MakeHuman default skeleton|MANOTAZO"

const ANIM_FURIA: String = "MakeHuman default skeleton|FURIA"


# -------------------------------------------------------------

# VELOCIDADES CALIBRABLES DESDE EL INSPECTOR

# -------------------------------------------------------------

@export_group("Velocidad de Animaciones")

@export_range(0.1, 5.0, 0.05) var vel_relax: float = 1.0

@export_range(0.1, 5.0, 0.05) var vel_andar: float = 1.0

@export_range(0.1, 5.0, 0.05) var vel_zarpazo: float = 1.0

@export_range(0.1, 5.0, 0.05) var vel_manotazo: float = 1.0

@export_range(0.1, 5.0, 0.05) var vel_furia: float = 1.0


func _ready() -> void:

# Busca el AnimationPlayer dentro de este nodo y sus hijos

anim_player = buscar_animation_player_propio(self)

if anim_player:

print("¡AnimationPlayer propio del personaje encontrado con éxito!")

# Configura RELAX en bucle normal y ANDAR en Ping-Pong

asegurar_loop(ANIM_RELAX)

asegurar_pingpong(ANIM_ANDAR)

# Arranca en RELAX

reproducir(ANIM_RELAX)

else:

print("ERROR: No se encuentra ningún AnimationPlayer dentro de este personaje.")


func buscar_animation_player_propio(nodo: Node) -> AnimationPlayer:

if nodo is AnimationPlayer:

return nodo as AnimationPlayer

for hijo in nodo.get_children():

var resultado = buscar_animation_player_propio(hijo)

if resultado:

return resultado

return null


func _unhandled_input(event: InputEvent) -> void:

if not anim_player:

return


# -------------------------------------------------------------

# 1. CUANDO SE PRESIONA UNA TECLA O BOTÓN (ACCIONES)

# -------------------------------------------------------------

if event.is_pressed() and not event.is_echo():

# Clic Izquierdo -> ZARPAZO

if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:

reproducir(ANIM_ZARPAZO)

return

# Clic Derecho -> MANOTAZO

if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT:

reproducir(ANIM_MANOTAZO)

return


# Teclado

if event is InputEventKey:

match event.keycode:

KEY_W:

reproducir(ANIM_ANDAR)

KEY_P:

reproducir(ANIM_ZARPAZO)

KEY_I:

reproducir(ANIM_FURIA)

KEY_O:

reproducir(ANIM_RELAX)


# -------------------------------------------------------------

# 2. CUANDO SE SUELTA CUALQUIER TECLA O BOTÓN -> VOLVER A RELAX

# -------------------------------------------------------------

if not event.is_pressed():

# Si soltamos cualquier botón/tecla y no queda NINGUNA otra pulsada, pasa a RELAX

if not hay_entrada_activa():

reproducir(ANIM_RELAX)


# Comprueba si el usuario tiene mantenida alguna tecla o botón de acción

func hay_entrada_activa() -> bool:

return Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) \

or Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT) \

or Input.is_key_pressed(KEY_W) \

or Input.is_key_pressed(KEY_P) \

or Input.is_key_pressed(KEY_I) \

or Input.is_key_pressed(KEY_O)


# Activa el modo Loop lineal (bucle normal)

func asegurar_loop(nombre: String) -> void:

if anim_player.has_animation(nombre):

var anim = anim_player.get_animation(nombre)

anim.loop_mode = Animation.LOOP_LINEAR


# Activa el modo Ping-Pong (ida y vuelta continua)

func asegurar_pingpong(nombre: String) -> void:

if anim_player.has_animation(nombre):

var anim = anim_player.get_animation(nombre)

anim.loop_mode = Animation.LOOP_PINGPONG


# Devuelve la velocidad asignada a la animación indicada

func obtener_velocidad(nombre: String) -> float:

match nombre:

ANIM_RELAX: return vel_relax

ANIM_ANDAR: return vel_andar

ANIM_ZARPAZO: return vel_zarpazo

ANIM_MANOTAZO: return vel_manotazo

ANIM_FURIA: return vel_furia

_: return 1.0


func reproducir(nombre: String) -> void:

if anim_player.has_animation(nombre):

# Solo cambia si la animación solicitada no es la que ya está sonando

if anim_player.current_animation != nombre:

var vel: float = obtener_velocidad(nombre)

anim_player.play(nombre, -1, vel)

print("Reproduciendo: ", nombre, " (Velocidad: ", vel, ")")

else:

print("La animación '", nombre, "' no existe en este AnimationPlayer.")


domingo, 4 de octubre de 2026

GDScript perfecto para animar personaje; para Godot 4.7 en 3d;

 extends Node3D


var anim_player: AnimationPlayer


# Nombres de las animaciones para tener el código limpio

const ANIM_RELAX: String = "MakeHuman default skeleton|RELAX"

const ANIM_ANDAR: String = "MakeHuman default skeleton|ANDAR"

const ANIM_ZARPAZO: String = "MakeHuman default skeleton|ZARPAZO"

const ANIM_MANOTAZO: String = "MakeHuman default skeleton|MANOTAZO"

const ANIM_FURIA: String = "MakeHuman default skeleton|FURIA"


func _ready() -> void:

# Busca el AnimationPlayer dentro de este nodo y sus hijos

anim_player = buscar_animation_player_propio(self)

if anim_player:

print("¡AnimationPlayer propio del personaje encontrado con éxito!")

# Configura RELAX y ANDAR para que se reproduzcan en bucle

asegurar_loop(ANIM_RELAX)

asegurar_loop(ANIM_ANDAR)

# Arranca en RELAX

reproducir(ANIM_RELAX)

else:

print("ERROR: No se encuentra ningún AnimationPlayer dentro de este personaje.")


func buscar_animation_player_propio(nodo: Node) -> AnimationPlayer:

if nodo is AnimationPlayer:

return nodo as AnimationPlayer

for hijo in nodo.get_children():

var resultado = buscar_animation_player_propio(hijo)

if resultado:

return resultado

return null


func _unhandled_input(event: InputEvent) -> void:

if not anim_player:

return


# -------------------------------------------------------------

# 1. CUANDO SE PRESIONA UNA TECLA O BOTÓN (ACCIONES)

# -------------------------------------------------------------

if event.is_pressed() and not event.is_echo():

# Clic Izquierdo -> ZARPAZO

if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:

reproducir(ANIM_ZARPAZO)

return

# Clic Derecho -> MANOTAZO

if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT:

reproducir(ANIM_MANOTAZO)

return


# Teclado

if event is InputEventKey:

match event.keycode:

KEY_W:

reproducir(ANIM_ANDAR)

KEY_P:

reproducir(ANIM_ZARPAZO)

KEY_I:

reproducir(ANIM_FURIA)

KEY_O:

reproducir(ANIM_RELAX)


# -------------------------------------------------------------

# 2. CUANDO SE SUELTA CUALQUIER TECLA O BOTÓN -> VOLVER A RELAX

# -------------------------------------------------------------

if not event.is_pressed():

# Si soltamos cualquier botón/tecla y no queda NINGUNA otra pulsada, pasa a RELAX

if not hay_entrada_activa():

reproducir(ANIM_RELAX)


# Comprueba si el usuario tiene mantenida alguna tecla o botón de acción

func hay_entrada_activa() -> bool:

return Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) \

or Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT) \

or Input.is_key_pressed(KEY_W) \

or Input.is_key_pressed(KEY_P) \

or Input.is_key_pressed(KEY_I) \

or Input.is_key_pressed(KEY_O)


# Activa el modo Loop en Godot para las animaciones continuas

func asegurar_loop(nombre: String) -> void:

if anim_player.has_animation(nombre):

var anim = anim_player.get_animation(nombre)

anim.loop_mode = Animation.LOOP_LINEAR


func reproducir(nombre: String) -> void:

if anim_player.has_animation(nombre):

# Solo cambia si la animación solicitada no es la que ya está sonando

if anim_player.current_animation != nombre:

anim_player.play(nombre)

print("Reproduciendo: ", nombre)

else:

print("La animación '", nombre, "' no existe en este AnimationPlayer.")