Ir para o conteúdo
ReadySpawn

Como fazer um jogo de terror estilo PSX no Godot 4

Por Imersa Studios · Atualizado em

Renderize o jogo em baixa resolução (320x240) com filtro nearest, faça o snap dos vértices num shader spatial, coloque neblina densa e deixe a luz do jogador pequena. Depois adicione uma ameaça que caça o jogador com um NavigationAgent3D. Esse é um loop completo de terror PSX no Godot 4.

1. Renderize na resolução do PS1

Em Project Settings, defina Display > Window > Size > Viewport Width e Height como 320 x 240 e mude Stretch > Mode para viewport. O Godot renderiza o jogo inteiro nesse tamanho e amplia, então cada pixel fica nítido e grosso.

Defina Rendering > Textures > Canvas Textures > Default Texture Filter como Nearest e, em cada material 3D, coloque Texture Filter como Nearest também. Use texturas pequenas: 64 ou 128 px bastam, e o nosso gerador de paleta PSX ajuda a limitar as cores. Para a versão do visual que vale para qualquer engine e para a parte de design, veja como fazer um jogo de terror PSX.

2. Tremor nos vértices com um shader spatial

O PS1 não tinha precisão de subpixel, então os vértices pulavam entre posições da tela. Faça o snap da posição em clip space no vertex() para ter o mesmo tremor:

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. Neblina e uma lanterna que acaba

Adicione um WorldEnvironment, ligue a Fog e escolha uma neblina escura e levemente colorida. A neblina esconde o fim dos corredores e mantém baixa a contagem de triângulos, o mesmo motivo de os jogos de PS1 a usarem.

Faça da lanterna um SpotLight3D filho da câmera. Gaste a bateria a cada frame e faça a luz piscar quando estiver fraca:

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. Uma ameaça que caça você

Faça o bake de uma NavigationRegion3D no nível, dê ao monstro um NavigationAgent3D e mova-o em direção ao jogador enquanto ele consegue ver ou ouvir:

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()

Adicione esconderijos, uma rota de patrulha e um estado de busca quando ele perde o jogador, e a perseguição começa a parecer justa. O nosso guia de jump scares fala do ritmo.

5. Pule a parte trabalhosa

O Horror Essentials já traz tudo isso funcionando no Godot 4 e no Unity 6: a edição grátis tem movimento, portas e chaves, lanterna com baterias, notas e o filtro PSX; a edição Complete adiciona duas IAs perseguidoras, esconderijos e um sistema de história sem código. Monte o nível com as edições grátis dos nossos kits PSX.

Perguntas frequentes

Quem escreveu

Imersa Studios cria os sistemas Unity, packs low poly e guias vendidos no itch.io. O código e as técnicas daqui vêm de lançar esses produtos. Saiba mais sobre o estúdio.