Saltar al contenido
ReadySpawn

Cómo hacer un juego de terror estilo PSX en Godot 4

Por Imersa Studios · Actualizado el

Renderiza el juego a baja resolución (320x240) con filtro nearest, ajusta los vértices en un shader spatial, pon niebla densa y deja pequeña la luz del jugador. Luego añade una amenaza que persiga al jugador con un NavigationAgent3D. Ese es un bucle completo de terror PSX en Godot 4.

1. Renderiza a la resolución de PS1

En Project Settings, pon Display > Window > Size > Viewport Width y Height en 320 x 240 y cambia Stretch > Mode a viewport. Godot renderiza todo el juego a ese tamaño y lo amplía, así que cada píxel queda nítido y grueso.

Pon Rendering > Textures > Canvas Textures > Default Texture Filter en Nearest y, en cada material 3D, Texture Filter en Nearest también. Usa texturas pequeñas: 64 o 128 px bastan, y nuestro generador de paleta PSX ayuda a limitar los colores. Para la versión de la estética que sirve en cualquier motor y la parte de diseño, mira cómo hacer un juego de terror PSX.

2. Temblor en los vértices con un shader spatial

La PS1 no tenía precisión de subpíxel, así que los vértices saltaban entre posiciones de la pantalla. Ajusta la posición en clip space dentro de vertex() para conseguir el mismo temblor:

shader_type spatial;
render_mode diffuse_lambert, specular_disabled;

uniform sampler2D albedo_tex : source_color, filter_nearest;
uniform float snap = 120.0; // lower = more wobble

void vertex() {
    vec4 clip = PROJECTION_MATRIX * MODELVIEW_MATRIX * vec4(VERTEX, 1.0);
    clip.xy = round(clip.xy / clip.w * snap) / snap * clip.w;
    POSITION = clip;
}

void fragment() {
    ALBEDO = texture(albedo_tex, UV).rgb;
}

3. Niebla y una linterna que se agota

Añade un WorldEnvironment, activa Fog y elige una niebla oscura y algo coloreada. La niebla oculta el final de los pasillos y mantiene bajo el número de triángulos, la misma razón por la que la usaban los juegos de PS1.

Haz que la linterna sea un SpotLight3D hijo de la cámara. Gasta la batería cada frame y haz que parpadee cuando esté baja:

extends SpotLight3D

@export var drain_per_second := 1.5
var battery := 100.0

func _process(delta: float) -> void:
    if not visible:
        return
    battery = max(battery - drain_per_second * delta, 0.0)
    light_energy = 0.0 if battery == 0.0 else (randf_range(0.2, 1.0) if battery < 15.0 else 1.0)

func recharge(amount: float) -> void:
    battery = min(battery + amount, 100.0)

4. Una amenaza que te caza

Haz el bake de una NavigationRegion3D en el nivel, dale al monstruo un NavigationAgent3D y muévelo hacia el jugador mientras pueda verlo u oírlo:

extends CharacterBody3D

@export var speed := 2.5
@export var player: Node3D
@onready var agent: NavigationAgent3D = $NavigationAgent3D

func _physics_process(_delta: float) -> void:
    agent.target_position = player.global_position
    var next := agent.get_next_path_position()
    velocity = (next - global_position).normalized() * speed
    move_and_slide()

Añade escondites, una ruta de patrulla y un estado de búsqueda cuando pierde al jugador, y la persecución empieza a sentirse justa. Nuestra guía de jump scares habla del ritmo.

5. Sáltate la parte pesada

Horror Essentials ya trae todo esto funcionando en Godot 4 y Unity 6: la edición gratis tiene movimiento, puertas y llaves, linterna con baterías, notas y el filtro PSX; la edición Complete añade dos IA perseguidoras, escondites y un sistema de historia sin código. Arma el nivel con las ediciones gratis de nuestros kits PSX.

Preguntas frecuentes

Quién lo escribió

Imersa Studios crea los sistemas Unity, los packs low poly y las guías que se venden en itch.io. El código y las técnicas de aquí salen de publicar esos productos. Más sobre el estudio.