No primeiro artigo dessa série, tentamos fazer a Gemini programar o Pong na Godot. Ela conseguiu fazer a base, mas não conseguiu resolver um bug crucial para um bom funcionamento do jogo, então vamos dizer que ela falhou nessa tarefa de programar sozinha. Então dessa vez vamos tentar o amado ChatGPT na mesma tarefa.
Começando Simples
A regra desse desafio com o ChatGPT é o mesmo do Gemini: Só podemos usar códigos criados por eles, nada de outros códigos pegos na internet, mesmo que já estejam prontos.
O jogo de escolha vai continuar sendo PONG para termos um bom parâmetro de comparação. O único problema desse desafio (pelo menos pra mim) com o ChatGPT vai ser o limite diário de mensagens dele.
ChatGPT-5
Eu sempre fico embasbacado com a velocidade das mensagens dessa IA. Mesmo quando mandamos imagem ou vídeo para ela analisar, as mensagens sempre chegam muito rápido. Mas sem mais enrolação, já pedindo para ela criar o script do Paddle. Um fato interessante é que ela disse não saber se eu estava usando Godot 4 ou uma versão mais antiga, mas de qualquer jeito me deu a instrução de fazer um CharacterBody2D com o seguinte script:
extends CharacterBody2D
@export var speed: float = 400.0 # Velocidade de movimento do paddle
@export var is_player_one: bool = true # Define se este paddle é o da esquerda ou direita
func _physics_process(delta: float) -> void:
var input_dir := 0.0
# Controles diferentes para cada paddle
if is_player_one:
if Input.is_action_pressed("ui_up"):
input_dir = -1
elif Input.is_action_pressed("ui_down"):
input_dir = 1
else:
if Input.is_action_pressed("move_up_p2"):
input_dir = -1
elif Input.is_action_pressed("move_down_p2"):
input_dir = 1
velocity = Vector2(0, input_dir * speed)
move_and_slide()
# Limitar dentro da tela
var screen_size = get_viewport_rect().size
var paddle_height = $CollisionShape2D.shape.extents.y
position.y = clamp(position.y, paddle_height, screen_size.y - paddle_height)
Não sou um expert em códigos e imagino que quem possa dizer qual das IA fez o melhor código é quem manja de programação. De qualquer jeito quem tiver a curiosidade de ir comparando os códigos feito pelo ChatGPT e a Gemini, o artigo que fiz da Gemini está aqui.
Um fato que eu sempre notei no ChatGPT é que ele sempre pergunta no final da mensagem se o usuário quer que ele faça mais alguma coisa, até dá uma sugestão relacionado ao que ele acabou de fazer. E ah, sempre com os malditos emojis! 🤢

Para a Bola, ele escolheu fazer um CharacterBody2D e também fez o script que está abaixo.
extends CharacterBody2D
@export var speed: float = 300.0 # Velocidade base da bola
var direction: Vector2 = Vector2.ZERO
func _ready() -> void:
# Quando o jogo começa, lança a bola em direção aleatória
reset_ball()
func _physics_process(delta: float) -> void:
velocity = direction * speed
var collision = move_and_collide(velocity * delta)
if collision:
# Se colidir com algo, reflete a direção
direction = direction.bounce(collision.get_normal()).normalized()
func reset_ball() -> void:
position = get_viewport_rect().size / 2 # Volta pro centro da tela
# Direção inicial aleatória (esquerda/direita + leve variação vertical)
var x_dir = randf() > 0.5 ? 1 : -1
var y_dir = randf_range(-0.5, 0.5)
direction = Vector2(x_dir, y_dir).normalized()
De quebra também me instruiu a como fazer as “paredes” do topo e baixo do cenário.

Foi nesse script da bola que apareceu o primeiro erro e pela primeira vez eu vi o ChatGPT-5 demorar. Ele usou a opção de “Pensar” e ficou nessa por 2 minutos. Aparentemente foi alguma coisa relacionado a ela enviar novamente algo que só funciona em versões antigas da Godot. Com esse problema corrigido, vamos ao Paddle da CPU.
extends CharacterBody2D
@export var speed: float = 350.0 # Velocidade da CPU
@export var ball_path: NodePath # Caminho para a bola (arrastar no editor)
@export var reaction_delay: float = 0.05 # Atraso de reação para não ser perfeito demais
var ball: Node2D
var target_y: float
func _ready() -> void:
if ball_path != NodePath():
ball = get_node(ball_path)
func _process(delta: float) -> void:
if not ball:
return
# CPU "mira" a posição da bola no Y com leve atraso
target_y = lerp(target_y, ball.position.y, reaction_delay)
func _physics_process(delta: float) -> void:
if not ball:
return
var dir := 0.0
if position.y < target_y - 10:
dir = 1
elif position.y > target_y + 10:
dir = -1
velocity = Vector2(0, dir * speed)
move_and_slide()
# Limitar dentro da tela
var screen_size = get_viewport_rect().size
var paddle_height = $CollisionShape2D.shape.extents.y
position.y = clamp(position.y, paddle_height, screen_size.y - paddle_height)
Até aqui tudo bem. Agora o último elemento do core do jogo que faltava era o sistema de gols e pontos. Então ela mandou o script do goal.gd
extends Area2D
@export var side: String = "left" # "left" ou "right"
signal goal_scored(side: String)
func _ready() -> void:
connect("body_entered", Callable(self, "_on_body_entered"))
func _on_body_entered(body: Node) -> void:
if body.is_in_group("ball"): # garante que é a bola
emit_signal("goal_scored", side)
Ajuste no ball.gd
func _ready() -> void:
add_to_group("ball")
rng.randomize()
reset_ball()
Script de gerenciador de jogo (game.gd)
extends Node
var score_player: int = 0
var score_cpu: int = 0
@onready var ball = $Ball
@onready var goal_left = $Goal_Left
@onready var goal_right = $Goal_Right
func _ready() -> void:
goal_left.connect("goal_scored", Callable(self, "_on_goal_scored"))
goal_right.connect("goal_scored", Callable(self, "_on_goal_scored"))
func _on_goal_scored(side: String) -> void:
if side == "left":
score_cpu += 1
elif side == "right":
score_player += 1
print("Placar: Jogador %d x %d CPU" % [score_player, score_cpu])
ball.reset_ball()
Pronto, toda a nossa base do jogo Pong está pronta! Chegamos a uma conclusão: com as duas IA’s, conseguimos criar toda uma base do Pong sem problemas… mas aconteceu o mesmo bug de quando começou o inferno que a Gemini fez eu passar…
O problema das IAs: Resolução de problemas
Chegamos ao bug que também tinha acontecido com a Gemini programando: a bola arrastando o Paddle se o mesmo atingisse ela com uma das pontas. Mandei a mesma descrição do bug para o ChatGPT-5 e ele mandou a “solução”.
A desgraça da IA fez eu mudar todo o Nó dos Paddles para Area2D, mas depois que não deu certo, ela fez eu mudar pra StaticBody2D. Ou seja, ela se embananou igual a Gemini, dando soluções que realmente resolvem algo, mas acabam quebrando com toda lógica do jogo. A solução definitiva dela foi transformar os Paddles em StaticBody2D e modificar o script deles:
extends CharacterBody2D
@export var speed: float = 300.0
var direction: Vector2 = Vector2.ZERO
signal goal_scored(side: String)
func _ready() -> void:
reset_ball()
func _physics_process(delta: float) -> void:
velocity = direction * speed
velocity = move_and_slide()
# checa colisões do frame
for i in range(get_slide_collision_count()):
var collision = get_slide_collision(i)
var collider = collision.get_collider()
if collider and collider.is_in_group("paddle"):
direction.x = -direction.x
var paddle_y = collider.position.y
var hit_pos = position.y - paddle_y
var paddle_height = collider.get_node("CollisionShape2D").shape.extents.y
var normalized_hit = hit_pos / paddle_height
direction.y = normalized_hit
direction = direction.normalized()
# Reposiciona a bola fora do paddle
position += collision.get_normal() * 5
else:
direction = direction.bounce(collision.get_normal()).normalized()
func reset_ball() -> void:
position = get_viewport_rect().size / 2
direction = Vector2(randf_range(-1, 1), randf_range(-0.5, 0.5)).normalized()
Eu já estava descrente, sabendo que o ChatGPT-5 também tinha peidado na farofa… mas eu estava errado, ou quase errado. O bug da bola arrastar o Paddle que apareceu muito no artigo que fiz com a Gemini, estava corrigido. Mas tinha outro problema agora…
Acredito que em essência o bug continua parecido com o que aconteceu no nosso experimento com a Gemini: o problema é justamente quando a bola bate em uma das pontas do Paddle. Dessa vez, mesmo impedindo da bola levar junto pro limbo o Paddle, é o Paddle que está levando a bola pra cima ou baixo, caso o jogador fique pressionando o botão de movimento com a bola em cima/baixo do Paddle.
Fora mensagens e mais mensagens tentando resolver esse problema e nada. Fiquei pasmo na velocidade que o ChatGPT-5 analisa os vídeos que eu mando (mesmo sendo esses mais curtos como os anexados na postagem).
Conclusão
No fim ficou elas por elas: o Gemini empacou basicamente no mesmo lugar que o ChatGPT-5 empacou. A única vantagem de usar o Gemini é que ele basicamente dá tokens infinitos, então esse projetinho nele eu fiz em 1 tarde. Já o ChatGPT-5 ele dá um limite de uso diário no plano free para usar a versão mais parruda citada nessa postagem, então tive que dividir o desenvolvimento em 2 tardes.