Réalité virtuelle

PhysiCore se joue en VR (OpenXR : Meta Quest en Link / Air Link / Virtual Desktop, SteamVR). Le joueur VR a un corps entier : son playermodel suit son casque et ses manettes (tête, torse, bras, doigts), et tous les autres joueurs le voient bouger ainsi. Joueurs VR et joueurs sur écran jouent ensemble.

Lancer en VR

Ajoute l'option de lancement --vr (Steam : Propriétés → Options de lancement, ou après -- en ligne de commande). Le jeu active les shaders VR dans user://rendering.cfg et se relance tout seul avec OpenXR (en Vulkan). Le casque doit être prêt avant : Meta Quest Link / Air Link ou SteamVR lancé. Sans casque détecté, la partie continue sur l'écran. Un lancement normal n'active jamais la VR.

Pour les développeurs : --vr-sim simule un casque sans en avoir (pavé numérique : 4 / 6 / 8 / 2 tourner la tête, flèches : avancer, 0 : gâchette droite, 5 / 7 : grips droit / gauche). Les scènes tools/_vr_sim_test.tscn et tools/_vr_net_test.tscn testent le corps, les mains et le réseau.

Commandes

ManetteAction
Joystick gaucheSe déplacer (vers où regarde la tête) ; poussé à fond : courir
Clic joystick gaucheAnnuler (undo)
Joystick droit gauche / droiteTourner par crans de 30° (réglable, ou rotation fluide)
Joystick droit haut / basArme suivante / précédente (dans un menu : faire défiler)
Clic joystick droitChat vocal (maintenir)
Gâchette droiteTirer, physgun, toolgun (dans un menu : cliquer)
Gâchette gaucheTir secondaire (clic droit)
A / BSauter / recharger
X / YUtiliser (E) / menu de spawn (reste ouvert, Y le referme)
Menu (manette gauche)Pause
Grips (gâchettes latérales)Attraper avec la main
Les deux joysticks cliquésCalibrer sa taille (se tenir droit)

S'accroupir dans la vraie vie accroupit le personnage, se déplacer dans la pièce le déplace (un mur l'arrête). Les menus (pause, spawn, fenêtres Lua) s'affichent sur un panneau devant le joueur, visé avec le laser de la main droite ; le HUD (vie, munitions) apparaît au dos du poignet gauche quand on le regarde. La taille du joueur est mesurée au début de la première partie : son personnage a ensuite la même hauteur d'yeux.

Le corps et les mains

Lua

FonctionOùRenvoie
ply:IsVR()partoutLe joueur joue en VR
ply:GetVRHeadPos(), ply:GetVRHeadAngles()partoutPosition et angles du casque (monde), nil hors VR
ply:GetVRHandPos(main), ply:GetVRHandAngles(main)partoutMain "left" ou "right" (monde)
ply:GetVRAimPos(), ply:GetVRAimVector()partoutRayon de visée de la main droite
ply:GetVRHandGrab(main)serveurLe prop tenu dans cette main, ou nil
vr.IsActive()clientCet ordinateur joue en VR

Hooks serveur : PlayerVRGrab(ply, ent, main) (renvoyer false empêche d'attraper) et PlayerVRDrop(ply, ent, main). ply:GetEyeTrace() et ply:GetAimVector() d'un joueur VR suivent sa main droite.

-- Serveur : on ne soulève pas les props des autres équipes à la main
hook.Add("PlayerVRGrab", "equipes", function(ply, ent, main)
	local proprio = ent:CPPIGetOwner()
	if IsValid(proprio) and proprio:Team() ~= ply:Team() then return false end
end)

-- Client : une sphère sur la main gauche des joueurs VR
hook.Add("PostDrawOpaqueRenderables", "mains_vr", function()
	for _, ply in ipairs(player.GetAll()) do
		if ply:IsVR() then
			render.DrawSphere(ply:GetVRHandPos("left"), 0.06, 8, 8, Color(0, 200, 255))
		end
	end
end)