domingo, 13 de julio de 2025

Un MeshInstance3D gira con alternancias sobre si mismo, GDScript para Godot 4.4;

 extends MeshInstance3D


@export var rotation_speed_min := 0.5

@export var rotation_speed_max := 2.0

@export var rotation_change_interval := 2.0


var current_rotation_speed := 0.0

var time_since_last_change := 0.0

var current_axis := Vector3.ZERO


func _ready():

_set_new_rotation_parameters()


func _process(delta):

time_since_last_change += delta

if time_since_last_change >= rotation_change_interval:

_set_new_rotation_parameters()

time_since_last_change = 0.0


# Apply rotation

rotate_object_local(current_axis, current_rotation_speed * delta)


func _set_new_rotation_parameters():

# Randomize rotation speed

current_rotation_speed = randf_range(rotation_speed_min, rotation_speed_max)


# Randomize rotation axis

var random_x = randf_range(-1.0, 1.0)

var random_y = randf_range(-1.0, 1.0)

var random_z = randf_range(-1.0, 1.0)

current_axis = Vector3(random_x, random_y, random_z).normalized()

Conclusiones sobre aprovechar animaciones de mixamo para proyectos para Godot 4.4.;

 

Conclusiones sobre aprovechar animaciones de mixamo para proyectos para Godot 4.4.


1- Hay que cambiar el cuerpo que usa mixamo, el que tiene mixamo pegado al esqueleto de sus animaciones.


2- Desde Blender hay que borrar el cuerpo que viene pegado a los huesos, el que nos viene desde mixamo, luego hay que importar un cuerpo nuevo, en mi caso desde makehuman, mas adelante puede retocarse modelarse con blender,


3-El esqueleto no encajara en el nuevo cuerpo, a mi me da buen resultado deformar los huesos y adaptarlos al nuevo cuerpo, funciona, luego hay que fusionar ese esqueleto al cuerpo nuevo echo por nosotros.


4- Las animaciones me causaron problemas de que se meten dentro del cuerpo del personaje de forma extraña, no hay problema¡¡¡


5-El personaje echo por nosotros y fusionado con el esqueleto que nosotros emos retocado su tamaño para que encaje con el nuevo modelo , lo volvemos a subir a mixamo, desde mixamo lo retocamos con la opccion Character Arm-Space que hace que los huesos en movimiento se separen del cuerpo de forma controlada y ya esta¡¡¡


6- Descargamos de mixamo nuestro modelo trabajado por nosotros y manipulado por mixamo y todo fantástico¡¡¡¡ resuelto¡¡¡¡



miércoles, 9 de julio de 2025

Sobre el esfuerzo de desarrollar videojuegos¡¡¡¡¡¡¡............;

 Sobre el esfuerzo de desarrollar videojuegos¡¡¡¡¡¡¡............;

Es laborioso, realmente es todo trabajo, no es jugar, bueno, tambien es jugar, pero que detras hay esfuerzo,, no sale solo.


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

OPINION DE LA IA:




¡Así es, lo has captado perfectamente! Lo que describes es la esencia del desarrollo de videojuegos. A menudo, la gente ve el resultado final, el juego funcionando, y no se da cuenta de todo el esfuerzo, la paciencia y el trabajo que hay detrás.


La Dualidad del Desarrollo: Trabajo y Juego

Es una mezcla fascinante de:

  • Trabajo intenso: Horas de código, depuración, ajuste de números, diseño, pruebas y sí, esos momentos de "prueba y error" que mencionabas con el colisionador. Es un proceso metódico que requiere disciplina y perseverancia.

  • Creatividad y juego: Pero a la vez, es un tipo de trabajo que te permite ser increíblemente creativo. Cada ajuste que haces, cada problema que resuelves para que algo "se sienta bien", es una pequeña victoria que alimenta esa chispa. Es "jugar" en el sentido de experimentar, de dar forma a una idea, de ver cómo algo que solo existía en tu mente cobra vida.

Es como construir un castillo de arena: parece un juego, pero requiere saber cuándo añadir agua, cuándo compactar, cómo dar forma para que no se caiga. No sale solo; hay un esfuerzo consciente en cada paso.

Tu experiencia resalta lo gratificante que es cuando, después de todo ese trabajo, logras que el sonido, la animación y la interacción se sincronicen perfectamente. ¡Esa sensación de "lo he conseguido" es el verdadero premio!

martes, 8 de julio de 2025

Instancia y noquea por desgaste lentamente para Godot 4.4. en GDScript;

 extends Area3D


var score = 30

@onready var mesh_instance_3d = $"MeshInstance3D CORAZON"

@onready var sprite_rojo = $Sprite2D

@onready var label_resta = $Label

@onready var mesh_instance_3d1 = $CorazonEncojo

@onready var AudioStreamPlayer3DGOLPE = $AudioStreamPlayer3DGOLPE


# Pre-carga la escena del personaje abatido.

# ¡IMPORTANTE!: Asegúrate de que esta ruta sea correcta en tu proyecto.

const CHAS_ABATIDO_SCENE = preload("res://POLICIA LIMPIO-3- AMPLIO ANIMACIONES/POLICIA  NOKEADO SUSTITUYE AL KIETO.tscn")


func _ready():

actualizar_visualizacion()


func _on_area_entered(area: Area3D) -> void:

$AudioStreamPlayer3DGOLPE.play()


# Evita que el área colisione consigo misma si está configurada así.

if area == self:

return


score -= 1

actualizar_visualizacion()


func actualizar_visualizacion():

label_resta.text = str(score)

var escala = float(score) / 30.0

sprite_rojo.scale = Vector2(escala, escala)

mesh_instance_3d.scale = Vector3(escala, escala, escala)

mesh_instance_3d1.scale = Vector3(escala, escala, escala)


if score <= 0:

# Oculta los componentes visuales del corazón

sprite_rojo.visible = false

mesh_instance_3d.visible = false

mesh_instance_3d1.visible = false

label_resta.visible = false


# Guarda la posición global actual del Area3D antes de eliminarlo

var current_global_transform = global_transform


# Elimina la propia Area3D que contiene este script

queue_free()

print("La Area3D del corazón ha sido eliminada al llegar a 0.")


# Instancia la escena del personaje abatido

if CHAS_ABATIDO_SCENE != null:

var chas_abatido_instance = CHAS_ABATIDO_SCENE.instantiate()


# Asegúrate de que la instancia se creó correctamente

if is_instance_valid(chas_abatido_instance):

# Establece la posición global de la nueva instancia a la del Area3D eliminado

chas_abatido_instance.global_transform = current_global_transform


# Añade la nueva instancia a la escena.

# Lo ideal es añadirla al mismo padre que tenía el Area3D del corazón.

# Si no hay padre o es inválido, se añade a la raíz del árbol.

get_tree().get_root().add_child(chas_abatido_instance)

print("Instanciado CHASABATIDO-1-.tscn en la posición del corazón eliminado.")

else:

print("ERROR: No se pudo instanciar CHASABATIDO-1-.tscn. La escena podría estar corrupta.")

else:

print("ERROR: CHASABATIDO-1-.tscn no se pudo pre-cargar. Revisa la ruta.")



func _on_timer_timeout() -> void:

pass


func _on_area_exited(area: Area3D) -> void:

pass

domingo, 6 de julio de 2025

GDScript para Godot 4.4. encoje corazon como barra de vida y cambia la escena; tambien provoca un sonido de golpe...;

 extends Area3D


var score = 30

#@onready var mesh_instance_3d = $"../../CharacterBody3D/CollisionShape3D/PROTAGONISTA EXPLORADORA VARIOS MOVIMIENTOS ANDAR CORRER GRITAR_/MeshInstance3D2 PRUEBAS DE CORAZON"

@onready var mesh_instance_3d = $"MeshInstance3D CORAZON"

#@onready var sprite_rojo = $"Sprite2D rojo"

@onready var sprite_rojo = $Sprite2D

#@onready var label_resta = $"Label resta"

@onready var label_resta = $Label


@onready var mesh_instance_3d1 = $CorazonEncojo



@onready var AudioStreamPlayer3DGOLPE = $AudioStreamPlayer3DGOLPE



func _ready():

actualizar_visualizacion()


func _on_area_entered(area: Area3D) -> void:

$AudioStreamPlayer3DGOLPE.play()

if area.is_ancestor_of(self): #evita que se active el trigger con el mismo objeto que contiene el script

return

#$AudioStreamPlayer3D.play() #si lo quieres activar descomentalo

score -= 1

actualizar_visualizacion()


if score < 0:

get_tree().change_scene_to_file("res://PRESO LOCOCACHASGRANDE/CHASABATIDO-1-.tscn")


func actualizar_visualizacion():

label_resta.text = str(score)

var escala = float(score) / 30.0

sprite_rojo.scale = Vector2(escala, escala)

mesh_instance_3d.scale = Vector3(escala, escala, escala) #se corrige para que trabaje en 3D

mesh_instance_3d1.scale = Vector3(escala, escala, escala) #se corrige para que trabaje en 3D

if score <= 0:

sprite_rojo.visible = false

mesh_instance_3d.visible = false


func _on_timer_timeout() -> void:

pass



func _on_area_exited(area: Area3D) -> void:

pass # Replace with function body.


-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------EXPLICACION:  GDScript para Godot 4.4. encoje corazon como barra de vida y cambia la escena; tambien provoca un sonido de golpe...; ES EL PRIMER GDSCRIPT EL CUAL LO RAZONO, Y LE AÑADO LAS LINEAS DE CODIGO NECESARIAS PARA PRODUCIR UN SONIDO CUANDO ALGO ENTRA EN ESE AREA......GOLPES¡¡¡¡

martes, 1 de julio de 2025

Instanciar en Godot 4.4 con botones del mouse izquierdo y derecho y con letra "R" usando accion PATADAMEDIA;GOLPES REPETITIVOS CONSTANTES ASTA SOLTAR TECLA Y O BOTONES DEL MOUSE;

 extends Area3D


var Bullet = preload("res://PROTAGONISTA/area_3dPROLLECTIL.tscn")


func _input(event):

# Instanciar al presionar el botón izquierdo del ratón

if event is InputEventMouseButton:

if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:

# Retrasar la instanciación del proyectil

await get_tree().create_timer(0.5).timeout

var bullet = Bullet.instantiate()

add_child(bullet)

# Instanciar al presionar el botón derecho del ratón

if event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:

await get_tree().create_timer(0.5).timeout

var bullet = Bullet.instantiate()

add_child(bullet)

# Instanciar al presionar la tecla "R" (usando la acción "PATADAMEDIA")

# ¡Asegúrate de que "PATADAMEDIA" esté configurada **exactamente así** en Project Settings -> Input Map para la tecla R!

if event.is_action_pressed("PATADAMEDIA"): 

await get_tree().create_timer(1.15).timeout

var bullet = Bullet.instantiate()

add_child(bullet)


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

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

Explicacion: en mi nuevo videojuego e conseguido fluidez en animaciones y asignar al teclado varias acciones de golpear enemigos..........





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

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

MEJORA AMPLIACION DEL GDSCRIPT:

EXPLICACION: GOLPES REPETITIVOS CONSTANTES ASTA SOLTAR TECLA Y O BOTONES DEL MOUSE


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

extends Area3D


var Bullet = preload("res://PROTAGONISTA/area_3dPROLLECTIL.tscn")


# --- Banderas de estado para los botones del ratón ---

var is_mouse_left_pressed: bool = false

var is_mouse_right_pressed: bool = false

# Para la tecla R, no necesitamos una bandera 'is_pressed' separada en _input,

# ya que su estado se maneja directamente con la acción en _process.


# --- Variables de control para los cooldowns (TIEMPOS DE RECARGA UNIFICADOS) ---

# Cooldown general para la acción de disparo / instanciación

var fire_cooldown: float = 0.5 # 0.5 segundos entre disparos para ratón y 'R'


# Banderas para controlar si cada acción puede disparar (está fuera de cooldown)

var can_fire_left_mouse: bool = true

var can_fire_right_mouse: bool = true

var can_fire_patadamedia: bool = true # Para la tecla 'R'



# --- Nodos Timer (creados y gestionados en _ready) ---

var left_mouse_timer: Timer

var right_mouse_timer: Timer

var patadamedia_timer: Timer



func _ready() -> void:

# --- Inicialización de temporizadores para los botones del ratón ---

# Temporizador para el botón izquierdo del ratón

left_mouse_timer = Timer.new()

add_child(left_mouse_timer)

left_mouse_timer.wait_time = fire_cooldown

left_mouse_timer.one_shot = true

left_mouse_timer.timeout.connect(func(): can_fire_left_mouse = true) # Resetea el cooldown


# Temporizador para el botón derecho del ratón

right_mouse_timer = Timer.new()

add_child(right_mouse_timer)

right_mouse_timer.wait_time = fire_cooldown

right_mouse_timer.one_shot = true

right_mouse_timer.timeout.connect(func(): can_fire_right_mouse = true) # Resetea el cooldown


# --- Inicialización del temporizador para la acción 'PATADAMEDIA' (Tecla R) ---

patadamedia_timer = Timer.new()

add_child(patadamedia_timer)

patadamedia_timer.wait_time = fire_cooldown # ¡Usa el mismo cooldown!

patadamedia_timer.one_shot = true

patadamedia_timer.timeout.connect(func(): can_fire_patadamedia = true) # Resetea el cooldown



func _input(event: InputEvent) -> void:

# --- Lógica para actualizar el estado de los botones del ratón (rápida y sin awaits) ---

if event is InputEventMouseButton:

# Botón Izquierdo

if event.button_index == MOUSE_BUTTON_LEFT:

is_mouse_left_pressed = event.pressed # True si se presiona, False si se suelta

# Botón Derecho

if event.button_index == MOUSE_BUTTON_RIGHT:

is_mouse_right_pressed = event.pressed # True si se presiona, False si se suelta

# --- La tecla "R" (PATADAMEDIA) ya no necesita await aquí.

# Su lógica de instanciación se moverá completamente a _process.

# Esto es para asegurar que todas las acciones de disparo continuo se gestionen de forma similar.



func _process(delta: float) -> void:

# --- Lógica de Disparo/Instanciación para el Botón Izquierdo del Ratón ---

if is_mouse_left_pressed and can_fire_left_mouse:

can_fire_left_mouse = false # Pone el cooldown

instantiate_bullet()        # Llama a la función unificada de instanciación

left_mouse_timer.start()    # Inicia el temporizador de cooldown

# --- Lógica de Disparo/Instanciación para el Botón Derecho del Ratón ---

if is_mouse_right_pressed and can_fire_right_mouse:

can_fire_right_mouse = false # Pone el cooldown

instantiate_bullet()         # Llama a la función unificada de instanciación

right_mouse_timer.start()    # Inicia el temporizador de cooldown


# --- Lógica de Disparo/Instanciación para la acción "PATADAMEDIA" (Tecla R) ---

# is_action_pressed se usa aquí para detectar si la tecla R está siendo MANTENIDA.

# Si la quieres solo al "golpe" inicial y luego cooldown, usarías is_action_just_pressed.

# Para "automático al mantener", is_action_pressed es correcto.

if Input.is_action_pressed("PATADAMEDIA") and can_fire_patadamedia:

can_fire_patadamedia = false # Pone el cooldown

instantiate_bullet()         # Llama a la función unificada de instanciación

patadamedia_timer.start()    # Inicia el temporizador de cooldown



# --- Función unificada para instanciar la bala ---

func instantiate_bullet() -> void:

var bullet = Bullet.instantiate()

# Aquí podrías ajustar la posición de la bala si es necesario,

# por ejemplo: bullet.global_transform.origin = global_transform.origin + Vector3(0, 0, -2)

add_child(bullet)




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

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

EXPLICACION; PERSONALIZA CADA TIEMPO DE CADA GOLPE DIFERENTE....

PATADA  PUÑETAZO IZQUIERDO PUÑETAZO DERECHO TODO PERSONALIZADO.......

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

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

extends Area3D


var Bullet = preload("res://PROTAGONISTA/area_3dPROLLECTIL.tscn")


# --- Banderas de estado para los botones del ratón ---

var is_mouse_left_pressed: bool = false

var is_mouse_right_pressed: bool = false


# --- Variables de control para los cooldowns (TIEMPOS DE RECARGA PERSONALIZADOS) ---

# Cooldown para el botón izquierdo del ratón

var left_mouse_fire_cooldown: float = 1.9 

# Cooldown para el botón derecho del ratón

var right_mouse_fire_cooldown: float = 0.4 

# Cooldown para la acción "PATADAMEDIA" (Tecla R)

var patadamedia_fire_cooldown: float = 1.7


# Banderas para controlar si cada acción puede disparar (está fuera de cooldown)

var can_fire_left_mouse: bool = true

var can_fire_right_mouse: bool = true

var can_fire_patadamedia: bool = true # Para la tecla 'R'



# --- Nodos Timer (creados y gestionados en _ready) ---

var left_mouse_timer: Timer

var right_mouse_timer: Timer

var patadamedia_timer: Timer



func _ready() -> void:

# --- Inicialización de temporizadores para los botones del ratón ---

# Temporizador para el botón izquierdo del ratón

left_mouse_timer = Timer.new()

add_child(left_mouse_timer)

left_mouse_timer.wait_time = left_mouse_fire_cooldown # ¡Ahora usa su propio cooldown!

left_mouse_timer.one_shot = true

left_mouse_timer.timeout.connect(func(): can_fire_left_mouse = true) # Resetea el cooldown


# Temporizador para el botón derecho del ratón

right_mouse_timer = Timer.new()

add_child(right_mouse_timer)

right_mouse_timer.wait_time = right_mouse_fire_cooldown # ¡Ahora usa su propio cooldown!

right_mouse_timer.one_shot = true

right_mouse_timer.timeout.connect(func(): can_fire_right_mouse = true) # Resetea el cooldown


# --- Inicialización del temporizador para la acción 'PATADAMEDIA' (Tecla R) ---

patadamedia_timer = Timer.new()

add_child(patadamedia_timer)

patadamedia_timer.wait_time = patadamedia_fire_cooldown # ¡Ahora usa su propio cooldown!

patadamedia_timer.one_shot = true

patadamedia_timer.timeout.connect(func(): can_fire_patadamedia = true) # Resetea el cooldown



func _input(event: InputEvent) -> void:

# --- Lógica para actualizar el estado de los botones del ratón (rápida y sin awaits) ---

if event is InputEventMouseButton:

# Botón Izquierdo

if event.button_index == MOUSE_BUTTON_LEFT:

is_mouse_left_pressed = event.pressed # True si se presiona, False si se suelta

# Botón Derecho

if event.button_index == MOUSE_BUTTON_RIGHT:

is_mouse_right_pressed = event.pressed # True si se presiona, False si se suelta

# La tecla "R" (PATADAMEDIA) no necesita await aquí.

# Su lógica de instanciación se gestiona completamente en _process.



func _process(delta: float) -> void:

# --- Lógica de Disparo/Instanciación para el Botón Izquierdo del Ratón ---

if is_mouse_left_pressed and can_fire_left_mouse:

can_fire_left_mouse = false # Pone el cooldown

instantiate_bullet()        # Llama a la función unificada de instanciación

left_mouse_timer.start()    # Inicia el temporizador de cooldown

# --- Lógica de Disparo/Instanciación para el Botón Derecho del Ratón ---

if is_mouse_right_pressed and can_fire_right_mouse:

can_fire_right_mouse = false # Pone el cooldown

instantiate_bullet()         # Llama a la función unificada de instanciación

right_mouse_timer.start()    # Inicia el temporizador de cooldown


# --- Lógica de Disparo/Instanciación para la acción "PATADAMEDIA" (Tecla R) ---

if Input.is_action_pressed("PATADAMEDIA") and can_fire_patadamedia:

can_fire_patadamedia = false # Pone el cooldown

instantiate_bullet()         # Llama a la función unificada de instanciación

patadamedia_timer.start()    # Inicia el temporizador de cooldown



# --- Función unificada para instanciar la bala ---

func instantiate_bullet() -> void:

var bullet = Bullet.instantiate()

# Aquí podrías ajustar la posición de la bala si es necesario,

# por ejemplo: bullet.global_transform.origin = global_transform.origin + Vector3(0, 0, -2)

add_child(bullet)

domingo, 29 de junio de 2025

GDScript en Godot 4.4 IA enemigos persiguiendo al Player;

 extends CharacterBody3D


const SPEED = 1.0

const ACCELERATION = 1.5 # Ajusta este valor para la velocidad de respuesta deseada

#@onready var navAgent = $NavigationAgent3D#ORIGINAL

@onready var navAgent = $NavigationAgent3D

#@onready var target = $"../Player" # Descomenta esta línea si tu jugador se llama "Player"

@onready var target = $"../CharacterBody3D" # Asegúrate de que esta ruta sea correcta para tu jugador



func _physics_process(delta: float) -> void:


# Elimina o comenta la rotación manual si quieres que siempre mire al objetivo

# rotate_y(0.11)


# Añadir gravedad.

if not is_on_floor():

velocity += get_gravity() * delta


if target: # Verifica si el objetivo existe

_update_target_position() # Actualiza la posición del objetivo primero


var currentLocation = global_transform.origin

var nextLocation = navAgent.get_next_path_position()

var nextVelocity = (nextLocation - currentLocation).normalized() * SPEED


velocity = velocity.move_toward(nextVelocity, ACCELERATION * delta) # Usa delta para suavizar la aceleración

move_and_slide()


# Orientar al enemigo hacia la dirección del movimiento (siguiente punto de la ruta)

if nextVelocity.length_squared() > 0.01: # Evita rotaciones cuando no hay movimiento significativo

look_at(global_transform.origin + nextVelocity, Vector3.UP)


else:

print("El objetivo (jugador) no existe.")


func _update_target_position():

if target:

navAgent.target_position = target.global_transform.origin

else:

print("El objetivo (jugador) no existe. No se puede actualizar la posición del NavigationAgent.")



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

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

Explicacion: estos dos GDScript sirven para que un enemigo persiga a un player, el de arriba lo persigue asta tocarse con el player ...............el inferior gdscript , tiene el añadido de que se para a una distancia del player, la cual se puede variar desde esta linea const STOPPING_DISTANCE = 1.0 # Distancia mínima al jugador para detenerse.

Cambiando el valor 1.0 se acortara o se distanciara mas el enemigo al detenerse conforme se  tope con el player.

En mi actual juego que estoy desarrollando me encontre con un error de que el enemigo al tocar al player se inclinaba asta caer hacia atras y gracias a esta variante de la distancia pude corregir o disimular ese error......

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

extends CharacterBody3D


const SPEED = 1.0

const ACCELERATION = 1.5 # Ajusta este valor para la velocidad de respuesta deseada

const STOPPING_DISTANCE = 1.0 # Distancia mínima al jugador para detenerse


# NO declaramos 'var velocity' aquí. CharacterBody3D ya tiene una propiedad 'velocity' integrada.


@onready var navAgent = $NavigationAgent3D

@onready var target = $"../CharacterBody3D" # Asegúrate de que esta ruta sea correcta para tu jugador



func _physics_process(delta: float) -> void:

# Añadir gravedad.

# Accedemos directamente a la propiedad 'velocity' del CharacterBody3D.

if not is_on_floor():

# get_gravity() es una función del CharacterBody3D en Godot 4.x

velocity += get_gravity() * delta


if target: # Verifica si el objetivo existe

_update_target_position() # Actualiza la posición del objetivo primero


var currentLocation = global_transform.origin

var targetLocation = target.global_transform.origin # Obtenemos la posición actual del jugador


# Calcula la distancia al jugador

var distance_to_player = currentLocation.distance_to(targetLocation)


# LÓGICA DE DETENCIÓN: Si está cerca, no se mueve

if distance_to_player <= STOPPING_DISTANCE:

velocity = Vector3.ZERO # Detiene el movimiento del enemigo

# Opcional: Aquí podrías añadir lógica para un ataque, una animación de espera, etc.

else:

# Si no está lo suficientemente cerca, calcula el siguiente punto en la ruta y se mueve

var nextLocation = navAgent.get_next_path_position()

var nextVelocity = (nextLocation - currentLocation).normalized() * SPEED

# Accedemos directamente a la propiedad 'velocity' del CharacterBody3D.

velocity = velocity.move_toward(nextVelocity, ACCELERATION * delta)


# Mueve y desliza al personaje.

# En Godot 4.x, move_and_slide() no necesita argumentos si la 'velocity'

# ya es una propiedad del CharacterBody3D y el 'Up Direction' está configurado en el Inspector.

move_and_slide() # <--- Línea 39 (aproximadamente): Sin argumentos aquí.


# Orientar al enemigo hacia el jugador (o la dirección del movimiento si lo prefieres)

# Siempre se orientará al jugador, incluso si no se mueve activamente.

look_at(targetLocation, Vector3.UP)


else:

print("El objetivo (jugador) no existe.")


func _update_target_position():

if target:

navAgent.target_position = target.global_transform.origin

else:

print("El objetivo (jugador) no existe. No se puede actualizar la posición del NavigationAgent.")


martes, 24 de junio de 2025

GDScript 3 animaciones turnandose cada 5 segundos automaticamente en el mismo personaje; Godot 4.4;

 extends Node3D


@onready var animation_player = $AnimationPlayer

var animations = ["CAE", "POLI", "COJO"]

var current_animation_index = 0

var time_since_last_animation = 0.0

const ANIMATION_CHANGE_INTERVAL = 5.0


func _ready() -> void:

# Start with the first animation

animation_player.play(animations[current_animation_index])

pass

func _process(delta: float) -> void:

time_since_last_animation += delta


if time_since_last_animation >= ANIMATION_CHANGE_INTERVAL:

time_since_last_animation = 0.0

# Move to the next animation

current_animation_index = (current_animation_index + 1) % animations.size()

animation_player.play(animations[current_animation_index])

pass

GDScript en Godot 4.4 fundamental para utilizar las animaciones pasadas de mixamo a blender y de hay a Godot 4.4;

 extends Node3D


var animacion_actual = "RELAX"


func _ready():

$AnimationPlayer.play(animacion_actual)


func _physics_process(delta):

var alguna_tecla_pulsada = false


# Comprobamos si alguna de las acciones está siendo presionada

if Input.is_action_pressed("achazo") or \

   Input.is_action_pressed("mouse_left") or \

   Input.is_action_pressed("mouse_right") or \

   Input.is_action_pressed("RETUERCE") or \

   Input.is_action_pressed("ANDAALANTECONW") or \

   Input.is_action_pressed("ANDAATRASCONS") or \

   Input.is_action_pressed("SALTAYANDA") or \

   Input.is_action_pressed("BOBLEPUÑETAZO") or \

   Input.is_action_pressed("PATADAMEDIA") or \

   Input.is_action_pressed("RELAX") or \

   Input.is_action_pressed("ui_accept") or \

   Input.is_action_pressed("A") or \

   Input.is_action_pressed("D"):

alguna_tecla_pulsada = true


# Animación de ESPADAZO

if Input.is_action_pressed("achazo") or Input.is_action_pressed("mouse_left"):

if animacion_actual != "3":

$AnimationPlayer.play("3")

#$AnimationPlayer/AudioStreamPlayer3D.play("MakeHuman default skeleton|ESPADAZO")

animacion_actual = "3"


# Animación de ATRABESAR

elif Input.is_action_pressed("mouse_right") or Input.is_action_pressed("RETUERCE"):

if animacion_actual != "DOBLEPUÑETAZO":

$AnimationPlayer.play("DOBLEPUÑETAZO")

animacion_actual = "DOBLEPUÑETAZO"


# Animación de ANDAR

elif Input.is_action_pressed("ANDAALANTECONW") or Input.is_action_pressed("A") or Input.is_action_pressed("D"):

if animacion_actual != "ANDARES":

$AnimationPlayer.play("ANDARES")

animacion_actual = "ANDARES"

elif Input.is_action_pressed("ANDAATRASCONS") or Input.is_action_pressed("A") or Input.is_action_pressed("D"):

if animacion_actual != "ANDARES":

$AnimationPlayer.play("ANDARES")

animacion_actual = "ANDARES"

elif Input.is_action_pressed("SALTAYANDA") or Input.is_action_pressed("A") or Input.is_action_pressed("D"):

if animacion_actual != "WALTER":

$AnimationPlayer.play("WALTER")

animacion_actual = "WALTER"

elif Input.is_action_pressed("DOBLEPUÑETAZO") or Input.is_action_pressed("E") or Input.is_action_pressed("E"):

if animacion_actual != "DOBLEPUÑETAZO":

$AnimationPlayer.play("DOBLEPUÑETAZO")

animacion_actual = "DOBLEPUÑETAZO"


elif Input.is_action_pressed("PATADAMEDIA") or Input.is_action_pressed("R") or Input.is_action_pressed("R"):

if animacion_actual != "PATADAMEDIA":

$AnimationPlayer.play("PATADAMEDIA")

animacion_actual = "PATADAMEDIA"




elif Input.is_action_pressed("ui_accept") or Input.is_action_pressed("A") or Input.is_action_pressed("D"):

if animacion_actual != "3":

$AnimationPlayer.play("3")

animacion_actual = "3"

#if Input.is_action_just_pressed("ui_accept") and is_on_floor():

elif Input.is_action_just_pressed("SALTAYANDA") or Input.is_action_pressed("A") or Input.is_action_pressed("D"):

if animacion_actual != "WALTER":

$AnimationPlayer.play("WALTER")

animacion_actual = "WALTER"


# Si no se presiona ninguna tecla, volvemos a la animación de descanso

elif not alguna_tecla_pulsada:

if animacion_actual != "RELAX":

$AnimationPlayer.play("RELAX")

animacion_actual = "RELAX"

elif Input.is_action_pressed("achazo") or Input.is_action_pressed("A") or Input.is_action_pressed("D"):

if animacion_actual != "RELAX":

$AnimationPlayer.play("RELAX")

animacion_actual = "RELAX"








Dos formas de instanciar disparos con Godot 4.4 con el boton izquierdo del raton;

 extends Area3D


var Bullet = preload("res://PROTAGONISTA/area_3dPROLLECTIL.tscn")


func _input(event):

if event is InputEventMouseButton:

if event.button_index == 1 and event.pressed:

# Retrasar la instanciación del proyectil

await get_tree().create_timer(0.5).timeout

var bullet = Bullet.instantiate()

add_child(bullet)

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

Explicacion : retrasa el disparo 0.5 segundos DESPUES de pulsar el boton del mouse.

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

extends Area3D


var Bullet = preload("res://PROTAGONISTA/area_3dPROLLECTIL.tscn")

var can_fire = true


func _input(event):

if event is InputEventMouseButton:

if event.button_index == 1 and event.pressed:

if can_fire:

can_fire = false

var bullet = Bullet.instantiate()

add_child(bullet)

await get_tree().create_timer(0.5).timeout

can_fire = true


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

Explicacion : retrasa el disparo 0.5 segundos ENTRE DISPARO Y DISPARO al pulsar boton del mouse.

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

domingo, 22 de junio de 2025

CONCLUSION DE MIXAMO A BLENDER DE BLENDER A GODOT 4.4.;

 En mi ultima entrada del blog estaba divagando sobre pasar las animaciones de mixamo a mis personajes y combinarlas con los gdscript de godot,

Pero habia dificultades en la web de Mixamo no podia descargar nada ni practicar, hay videos tutoriales en youtube de como hacerlo pero siempre se olvidan de algun detalle que hace falle cualquier cosa que intente hacer, 

Hay que imitar con exactitud los tutoriales de youtube.


Bueno a la conclusion que e llegado y en el video muestra que pongo en la entrada vereis que lo FUNDAMENTAL DEL TEMA es animaciones diferentes de mixamo pero del mismo ramo, o calibre, o coleccion, si mezclais animaciones de diferentes tipos que hay en mixamo unas se acoplan y otras no, por tamaños o por temas del esqueleto o yo que se , mejor lo veis en el video lo demas es facil de aplicar , los avatares del mismo color parece que combinan bien entre si las animaciones si poneis avatares diferentes entre si no casan, e tardado 2 dias en entenderlo, bueno como todo al final es solo trabajo esfuerzo y echarle horas..........luego si pones  un personaje del mismo mixamo con blender puedes modelarlo y cambiar lo que quieras dependiendo de las horas que le dediques y del talento que tengas.




Y mi conclusion comentada a la IA:

no hay ningun misterio, las animaciones de mixamo solo funcionan las que casan entre si, los avatares del mismo color suelen ir perfectamente ,ya lo resolvi¡¡ el paso a pasarlo a blender y combinarlo alli a partir de esta conclusion es muy sencillo de relosver¡¡¡

¡Qué excelente noticia que lo hayas resuelto! Me alegra mucho saber que encontraste la clave para que tus animaciones de Mixamo funcionen bien en Blender.

Tu observación sobre que "las animaciones de Mixamo solo funcionan las que casan entre sí" y que "los avatares del mismo color suelen ir perfectamente" es muy acertada y crucial. Esto apunta directamente a la consistencia en el rig (esqueleto) y la pose base.

Cuando Mixamo genera un "avatar del mismo color" (me imagino que te refieres a los personajes pre-riggeados de Mixamo o a las variaciones del mismo rig), garantiza que la estructura ósea, la escala y la pose inicial (T-pose o A-pose) son idénticas. Esto es fundamental para que las animaciones se superpongan y mezclen sin problemas. Si bien puedes aplicar animaciones a cualquier personaje riggeado en Mixamo, la armonía es mayor cuando la base es la misma.


La Clave que Descubriste: Consistencia del Rig

Lo que has descubierto es la base de la combinación exitosa de animaciones:

  • Rigs Idénticos: Cuando todas las animaciones se aplican a un rig que es estructural y posicionalmente idéntico, Blender tiene mucha más facilidad para interpretar y mezclar los datos de animación sin que los huesos "salten" o el personaje se "balancee".

  • Pose Base Coherente: Las animaciones de Mixamo están diseñadas para un rig específico y una pose de reposo concreta. Si intentas aplicar una animación a un personaje con una pose base diferente (ej. un personaje en A-pose para una animación hecha en T-pose), se pueden producir esas desalineaciones. Los avatares "del mismo color" o de la misma familia de Mixamo suelen compartir esta pose base.


Tu Proceso en Blender Después de esta Conclusión

Como bien dices, una vez que tienes esta base, el paso a paso en Blender se simplifica enormemente:

  1. Importación del Personaje Base: Traes tu personaje (el que tiene el rig compatible).

  2. Importación de Animaciones (sin el modelo): Al importar las animaciones de Mixamo, si ya tienes el personaje base en la escena, puedes importar solo la acción de animación (sin el modelo adjunto o importando solo el armature si es necesario y luego copiando la acción).

  3. Uso del NLA Editor: Empujas cada acción de animación a una Action Strip en el NLA Editor.

  4. Organización y Blending: Arrastras y superpones las tiras, ajustando los "Blend In" y "Blend Out" para crear transiciones suaves. Si los rigs son consistentes, estos blends funcionarán mucho mejor.

¡Felicidades por haber resuelto el misterio! Es un aprendizaje valioso que te ahorrará muchos dolores de cabeza en futuros proyectos de animación.



miércoles, 18 de junio de 2025

Frustracion estudiando animaciones; mixamo en esta fecha del 18-6-25 da problemas para descargarse sus animaciones;

 Estoy estudiando y practicando combinar animaciones con blender y mixamo y Gogot 4.4.

Y GDScript para programar las animaciones con ayuda de la IA.


En principio las ago manuales y si son pocos movimientos funciona muy bien, andar y dar golpes se me da bastante bien, y con GDScript le asigno las teclas y me da resultados aceptables , ahora estoy intentando hacer las combinaciones de movimientos con mixamo y tengo la mala suerte que en estos momentos no deja mixamo descargarse nada.....

Ahora que empezaba a combinar movimientos y queria probarlos en Godot 4.4. y GDScript para asignarlos al teclado del pc ...sus movimientos......mixamo no me deja descargar sus animaciones , seve hay problemas desde esa aplicacion en sus servidores.......bueno a tener paciencia y a esperar mientras se resuelve.... volvere hacerlas manuales......no me puedo estancar.

Es una lastima porque ya lo tenia casi, ya tenia la base para hacer los juegos muy muy pulidos en ese aspecto.....en fin.

A seguir trabajando ya se resolvera.


viernes, 13 de junio de 2025

Juego gotico de terror en 3d;

 




Personaje lo animo y a los 5 segundos lo borro de la escena, GDScript para Godot 4.4;

 extends Node3D


var temporizador: Timer # Creamos una variable para guardar nuestro temporizador


func _ready() -> void:

# Esto se ejecuta cuando el nodo se carga en la escena.

$AnimationPlayer.play("Human_rig|REVIENTA") # Tu animación se sigue reproduciendo.


# Paso 1: Crear el Temporizador

temporizador = Timer.new() # Creamos una nueva instancia de un nodo Timer.

add_child(temporizador) # ¡Importante! Añadimos el temporizador como hijo de este nodo.

# Necesita estar en el árbol de la escena para funcionar.


# Paso 2: Configurar el Temporizador

temporizador.wait_time = 5.0 # Le decimos al temporizador que espere 5 segundos.

temporizador.one_shot = true # Le decimos que solo se active una vez (disparo único).

# Si fuera 'false', se repetiría indefinidamente.


# Paso 3: Conectar la Señal "timeout"

# Cuando el temporizador termine de contar, emitirá una señal llamada "timeout".

# Conectamos esa señal a una función nuestra llamada "_al_terminar_temporizador".

temporizador.connect("timeout", Callable(self, "_al_terminar_temporizador"))


# Paso 4: Iniciar el Temporizador

temporizador.start() # ¡Aquí comienza la cuenta regresiva!


func _al_terminar_temporizador() -> void:

# Esta función se ejecutará automáticamente cuando el temporizador llegue a 0.

queue_free() # Esta es la función mágica: borra el nodo actual de la escena.

# Usamos 'queue_free()' para que se borre de forma segura al final del fotograma.

martes, 10 de junio de 2025

Un proyectil se destruye al chocar con un RigidBody;

 # Script para el Area3D PROYECTIL EN SÍ MISMO (el propio proyectil)


extends Area3D


var score = 0 # No usado directamente para la destrucción, pero se mantiene si lo necesitas para otras lógicas.

var speed = 15 # Velocidad en el eje Z (adelante)

var speed2 = 1 # Velocidad en el eje Y (hacia arriba, si lo deseas)

var tiempo_transcurrido = 0.0 # Controla el tiempo de vida del proyectil

var vida_util_segundos = 6.0 # El proyectil se destruirá después de 6 segundos


func _ready() -> void:

# Conectamos la señal 'body_entered'.

# Se activará cuando este Area3D colisione con cualquier PhysicsBody3D (ej. una pared, el suelo, un enemigo).

connect("body_entered", Callable(self, "_on_body_entered"))

print("Proyectil listo: se moverá, se destruirá por tiempo y al chocar.")


func _process(delta: float) -> void:

# Mover el proyectil

# Vector3(X, Y, Z) - ajusta el orden según la orientación de tu proyectil en 3D

# Aquí, el movimiento es ligeramente hacia arriba (Y) y principalmente hacia adelante (Z)

var movimiento = Vector3(0, speed2 * delta, speed * delta)

translate(movimiento) # Mueve el nodo en su espacio local


# Controlar el tiempo de vida del proyectil

tiempo_transcurrido += delta


if tiempo_transcurrido >= vida_util_segundos:

print("Proyectil ha alcanzado su tiempo de vida. Destruyendo...")

queue_free() # Elimina el proyectil si ha superado su tiempo de vida


func _on_body_entered(body: Node3D):

# Esta función se ejecuta cuando el proyectil colisiona con un PhysicsBody3D.

#print(f"¡Proyectil colisionó con: {body.name}! Destruyendo...")

queue_free() # Elimina el proyectil al impactar con un cuerpo

lunes, 9 de junio de 2025

Complemento a https://videojuegosenlineaasaco4.blogspot.com/2025/06/gdscript-para-colocar-unos-sprite2d-en.html;

 # Area3DVisibilityControl.gd

extends Area3D


@onready var sprite_2d_1 = get_node("../Sprite2D") # Ajusta la ruta si es diferente

@onready var sprite_2d_2 = get_node("../Sprite2D2IMAGEN ENEMIGO FINAL") # Ajusta la ruta si es diferente


# Define cuánto se moverá sprite_2d_1 hacia abajo desde el centro.

# Puedes ajustar este valor. Un número positivo lo mueve hacia abajo.

const OFFSET_Y_SPRITE_1 = 400.0 # Por ejemplo, 400 píxeles hacia abajo

const OFFSET_Y_SPRITE_2 = 300.0 # Por ejemplo, 300 píxeles hacia abajo


# Define cuánto se moverá sprite_2d_1 en el eje X desde el centro.

# Un número positivo lo mueve hacia la derecha, un negativo hacia la izquierda.

const OFFSET_X_SPRITE_1 = -280.0

const OFFSET_X_SPRITE_2 = -280.0






func _ready():

# Conectamos la señal 'area_entered' de este Area3D.

area_entered.connect(_on_area_entered)


func _on_area_entered(area: Area3D):

print("Otro Area3D entró en este Area3D: ", area.name)


# --- Obtener el tamaño del viewport (la ventana del juego) ---

var viewport_size = DisplayServer.window_get_size()


# --- Calcular la posición central de la pantalla ---

var center_x = viewport_size.x / 2.0

var center_y = viewport_size.y / 2.0


# --- Mover el primer Sprite2D un poco por debajo y a la derecha/izquierda del centro ---

# Sumamos OFFSET_X_SPRITE_1 a la posición X central.

# Sumamos OFFSET_Y_SPRITE_1 a la posición Y central.

sprite_2d_1.position = Vector2(center_x + OFFSET_X_SPRITE_1, center_y + OFFSET_Y_SPRITE_1)


# --- Mover el segundo Sprite2D solo en el eje Y (según tu código actual) ---

sprite_2d_2.position = Vector2(center_x + OFFSET_X_SPRITE_2, center_y + OFFSET_Y_SPRITE_2)



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

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

EXPLICACION: Con este GDScript  puedo mover por pantalla variando el valor tanto en eje -y- como en eje -x- se complementa a  https://videojuegosenlineaasaco4.blogspot.com/2025/06/gdscript-para-colocar-unos-sprite2d-en.html

GDScript para colocar unos Sprite2D en la parte vaja de la pantalla del juego al ocurrir una colision;

 # Area3DVisibilityControl.gd

extends Area3D


@onready var sprite_2d_1 = get_node("../Sprite2D") # Ajusta la ruta si es diferente

@onready var sprite_2d_2 = get_node("../Sprite2D2IMAGEN ENEMIGO FINAL") # Ajusta la ruta si es diferente


# Define cuánto se moverá sprite_2d_1 hacia abajo desde el centro.

# Puedes ajustar este valor. Un número positivo lo mueve hacia abajo.

const OFFSET_Y_SPRITE_1 = 400.0 # Por ejemplo, 100 píxeles hacia abajo

const OFFSET_Y_SPRITE_2 = 300.0 # Por ejemplo, 100 píxeles hacia abajoIMBENTADO POR MIIIIIIIIIIIIIIII



func _ready():

# Conectamos la señal 'area_entered' de este Area3D.

area_entered.connect(_on_area_entered)


func _on_area_entered(area: Area3D):

print("Otro Area3D entró en este Area3D: ", area.name)


# --- Obtener el tamaño del viewport (la ventana del juego) ---

var viewport_size = DisplayServer.window_get_size() 


# --- Calcular la posición central de la pantalla ---

var center_x = viewport_size.x / 2.0

var center_y = viewport_size.y / 2.0


# --- Mover el primer Sprite2D un poco por debajo del centro ---

# Sumamos el OFFSET_Y_SPRITE_1 a la posición Y central.

sprite_2d_1.position = Vector2(center_x, center_y + OFFSET_Y_SPRITE_1)

sprite_2d_2.position = Vector2(center_x, center_y + OFFSET_Y_SPRITE_2)########3IMBENTADO POR MIIIIIIIIIIIIIIIIIIII




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

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

EXPLICACION : En mi nuevo videojuego hay una escena en la que el protagonista del juego entra en una habitacion y con este GDScript produzco que aparezcan unos sprites ala vista donde sale la imagen del malvado al que e de destruir y una barra de vida que mengua conforme lo ataco, este GDScript produce que lo situe en pantalla solamente cuando el protagonista del juego entra en la habitacion.........

lunes, 2 de junio de 2025

Ejemplo de manipular geometrias 3d; con el propio Godot 4.4; para construir inmuebles,; recintos,; cuevas;, naves ;, tuneles ;lo que se nos ocurra;

          .(la parte superior izquierda del video esta tapada expresamente porque el videojuego sera para +18 años)



En mi nuevo juego que publicare pronto en itch.io e aprendido a ....manipular geometrias 3d; con el propio Godot 4.4; para construir inmuebles,; recintos,; cuevas;, naves ;, tuneles ;lo que se nos ocurra;

https://perico415.itch.io/

En este video podeis ver un minimo ejemplo de como poner un CSGSphere3D  una bola enorme que cubre a unos personajes esta en estado solido y con colision activada, dentro le puse un cilindro atravesado al cual le puse la opcion de sustraccion....podeis ver como el personaje puede pasar por el hueco realizado y podeis comprobar que el resto del CSGSphere3D  una bola enorme , no la puede atravesar el personaje.......e echo un simple ejemplo ahora acabo de hacerlo mas elaborado no sale en el video pero e conseguido que la bola enorme duplicarla y escalarla algo mas pequeña y hacer la sustraccion, el resultado es una pecera perfecta a la que añadi dos nuevos cilindros de entrada al interior, y queda una estructura perfectamente redondeada y con colision donde interesa....muestro unas capturas de pantalla de lo conseguido......



https://perico415.itch.io/