Source: Scratch Wiki en français


Projets Étape par Étape : Raycaster


Un raycaster est un projet permettant de réaliser de la « fausse » 3D.
Ce tutoriel étape par étape vous propose de construire un jeu de labyrinthe en fausse 3D.

Étape 1 : Créer les bases

Sprite à créer

Pour commencer, créez un sprite tout simple (ici, render), et depuis ses options, cachez-le. Vous pouvez aussi créer un costume vide.

Listes et variables à créer

Listes (pour ce sprite (render) uniquement)

  • niveau::ring list, une liste qui stockera tous les niveaux de votre jeu
  • niveaux::ring list, une liste qui stockera tous les niveaux de votre jeu

Variables (pour ce sprite (render) uniquement)

Niveau
  • niveau actuel::ring variables, une variable qui stockera le niveau actuel
  • niveau / idx::ring variables, une variable qui permettra d'ouvrir un niveau
  • niveau / point::ring variables, une variable qui permettra d'ouvrir un niveau
Joueur
  • joueur / x::ring variables, une variable qui stockera la position x du joueur
  • joueur / y::ring variables, une variable qui stockera la position y du joueur
  • joueur / vx::ring variables, une variable qui stockera la vitesse x du joueur
  • joueur / vy::ring variables, une variable qui stockera la vitesse y du joueur
  • joueur / frottement::ring variables, une variable qui stockera la vitesse de décélération du joueur
  • joueur / position::ring variables, une variable qui stockera l'élément équivalent à la position du joueur dans le niveau::list ring
Paramètres
  • param / champ de vision::ring variables
  • param / distance de rendu max::ring variables
  • param / début du brouillard::ring variables
Raycaster
  • raycaster / x::ring variables
  • raycaster / bloqueur::ring variables
  • raycaster / étapes::ring variables
Correcteurs
  • track / FPS::ring variables
  • track / Δt::ring variables
  • track / dernier 1/30::ring variables

Créer un niveau


Info
 Info :
Créez votre niveau en suivante ce guide :
  • Cliquez sur un point pour changer sa valeur (mur (bleu par défaut), passage (blanc), début (rouge), fin (vert))
  • Utilisez le bouton Check pour vérifier que le niveau est jouable (un chemin bleu s'affiche)
  • Utilisez le bouton Export, puis, dans la liste, récoltez le code Level for French Wiki Raycaster Tuto
  • Ajoutez ce code dans la liste niveaux::list ring
Idée
 Idée :
Vous pouvez mettre le projet en français dans l'onglet Settings.
Idée
 Idée :
Si vous ne voulez pas créer de niveau, vous pouvez utiliser le bouton Examples.
Idée
 Idée :
Utilisez TurboWarp pour utiliser de manière fluide le projet.

Étape 2 : Premiers scripts (sans affichage)

Ouvrir un niveau avec un code du projet donné

Importez l'extension stylo, puis créez un bloc personnalisé sans rafraîchissement d'écran comme celui qui suit :

définir Ouvrir le niveau (niveau)
mettre [niveau / idx v] à (1)
supprimer tous les éléments de la liste [niveau v]
répéter (longueur de (élément (niveau::custom) de [niveaux v])) {
mettre [niveau / point v] à ()
répéter jusqu'à <(lettre (niveau / idx) de (élément (niveau::custom) de [niveaux v])) = [,]> {
mettre [niveau / point v] à (regrouper (niveau / point) et (lettre (niveau / idx) de (élément (niveau::custom) de [niveaux v])))
ajouter (1) à [niveau / idx v]::variables
}@loopArrow::control
ajouter (niveau / point) à [niveau v]::list
ajouter (1) à [niveau / idx v]::variables
}@loopArrow::control

Détecter la position du joueur dans un niveau

Créez le bloc suivant, sans rafraîchissement d'écran :

définir Détecter position joueur (x) (y)
mettre [joueur / position v] à (((30) * ([plancher v] de (([abs v] de ((y) - (180))) / (16)))) + ([plafond v] de (((x) + (240)) / (16))))

Le bloc retourne l'élément du niveau correspondant à x, y.

Faire bouger le joueur & Bloquer ses déplacement en fonction du niveau

Créez les blocs suivants, sans rafraîchissement d'écran :

Bloquer et réagir

définir Réagir à élément (index) (valeur changée)
si <(élément (index) de [niveau v]) = [wall]> alors
si <(valeur changée) = [changé : x]> alors
ajouter ((-1) * (joueur / xv)) à [joueur / x v]
fin
si <(valeur changée) = [changé : y]> alors
ajouter ((-1) * (joueur / yv)) à [joueur / y v]
fin
sinon
si <(élément (index) de [niveau v]) = [exit]> alors
mettre [joueur / position v] à [terminé]
fin
fin

Déplacer et réagir

définir Bouger de (pas) pas, direction (dir)
ajouter (((pas) * (track / Δt)) * ([sin v] de (dir))) à [joueur / xv v]
ajouter (((pas) * (track / Δt)) * ([cos v] de (dir))) à [joueur / yv v]


définir Physique
mettre [joueur / frottement v] à (0.92) // valeur strictement supérieure à 0 et strictement inférieure à 1
si <touche (flèche haut v) pressée ?> alors
Bouger de (2) pas, direction ((direction) + (0))::custom
fin
si <touche (flèche bas v) pressée ?> alors
Bouger de (2) pas, direction ((direction) + (180))::custom
fin
si <touche (flèche droite v) pressée ?> alors
Bouger de (2) pas, direction ((direction) + (90))::custom
fin
si <touche (flèche gauche v) pressée ?> alors
Bouger de (2) pas, direction ((direction) + (270))::custom
fin
ajouter (joueur / xv) à [joueur / x v]
Détecter position joueur (joueur / x) (joueur / y)::custom
Réagir à élément (joueur / position) [changé : x]::custom
ajouter (joueur / yv) à [joueur / y v]
Détecter position joueur (joueur / x) (joueur / y)::custom
Réagir à élément (joueur / position) [changé : y]::custom
mettre [joueur / xv v] à ((joueur / xv) * (frottement))
mettre [joueur / yv v] à ((joueur / yv) * (frottement))
Idée
 Idée :
Vous pouvez inverser les commandes en ajoutant 180 dans chaque bloc ((direction) + [x]).

Étape 3 : Raycaster

Les curieux se sont sans doute demandés pourquoi dans le bloc définir Détecter position joueur (x) (y), nous avons utilisés des entrées personnalisées et non directement les variables contenant la position du joueur. Nous allons nous servir du même bloc pour les rays (rayons) du raycaster, afin de détecter un mur.

Commencer un niveau

Créons le bloc principal de notre script, sans rafraîchissement d'écran :

définir Render
Physique::custom

Initialiser les correcteurs

Toujours sans rafraîchissement d'écran :

définir Setup
réinitialiser le chronomètre
mettre [track / Δt v] à (1)
mettre [track / dernier 1/30 v] à (0)
mettre [track / FPS v] à (30)

Trouver le début d'un niveau

Toujours sans rafraîchissement d'écran :

définir Aller au début du niveau actuel
si <<[niveau v] contient [start] ?> et <[niveau v] contient [exit] ?>> alors
mettre [joueur / y v] à ([176] - (([plancher v] de (((position de [start] dans [niveau v]) - (1)) / (30))) * [16]))
mettre [joueur / x v] à ([-232] + ((((position de [start] dans [niveau v]) - (1)) modulo (30)) * (16)))
sinon
mettre [joueur / position v] à [terminé] // Si ce bloc est exécuté, cela signifie que votre niveau ne contient pas de fin et/ou de début
fin

Jouer un niveau

Ensuite, avec rafraîchissement d'écran :

définir Jouer le niveau (idx)
Ouvrir le niveau (idx)::custom
Setup::custom
mettre [niveau actuel] à (idx)
mettre [joueur / position v] à [commencé] // pour éviter que le niveau terminé précédent reste et que le nouveau soit considéré comme terminé
répéter (1) fois
Aller au début du niveau actuel::custom
mettre [joueur / xv v] à (0)
mettre [joueur / yv v] à (0)
fin
répéter jusqu'à ce que <(joueur / position) = [terminé]> 
Render::custom
fin
Attention
 Attention :
Mettez bien ce bloc avec rafraîchissement d'écran, sinon vous risquez d'avoir de bonnes surprises…

Fond personnalisé

Un bloc personnalisé, sans rafraîchissement d'écran, pour définir une couleur de fond d'écran par défaut :

définir Fond d'écran
aller à x:(0) y:(0)
mettre la taille du stylo à (800)
mettre la couleur du stylo à [#171350] // Un exemple (#171350), le choix est à vous
stylo en position d'écriture
relever le stylo

Correcteurs

Info
 Info :
Les correcteurs permettent d'améliorer l'expérience de jeu lorsque ce dernier subit une chute de FPS.
Si vous avez suivi le tuto en ajoutant la variable (track / Δt) dans le bloc Bouger de () pas, direction ()::custom, le jeu ne fonctionnera pas sans.

Toujours sans rafraîchissement d'écran :

définir FPS (dernier 1/30)
mettre [track / dernier 1/30 v] à ((chronomètre) * (30))
mettre [track / Δt v] à ((track / dernier 1/30) - (dernier 1/30))
mettre [track / FPS v] à ((arrondi de (((30) / (track / Δt)) * (1000))) / (1000))

Déplacement axe par axe

Ce bloc personnalisé, sans rafraîchissement d'écran, servira à afficher des couleurs différentes en fonction de l'orientation du mur. Il ne faut cependant pas le bloquer si jamais on veut adoucir les murs.

définir Avancer de (a idx) étapes
mettre [raycaster / bloqueur v] à [libre]
ajouter ((a idx) * ([sin v] de (direction))) à x
Détecter position joueur (abscisse x) (ordonnée y)::custom
si <<(joueur / position) = [exit]> et <(raycaster / bloqueur) = [libre]>> alors
mettre la couleur du stylo à [#e6d300] // #e6d300
mettre [raycaster / bloqueur v] à [bloqué]
fin
si <<(joueur / position) = [wall]> et <(raycaster / bloqueur) = [libre]>> alors
mettre la couleur du stylo à [#0099e6] // #0099e6
mettre [raycaster / bloqueur v] à [bloqué]
fin
ajouter ((a idx) * ([cos v] de (direction))) à y
Détecter position joueur (abscisse x) (ordonnée y)::custom
si <<(joueur / position) = [exit]> et <(raycaster / bloqueur) = [libre]>> alors
mettre la couleur du stylo à [#ffea00] // #ffea00
mettre [raycaster / bloqueur v] à [bloqué]
fin
si <<(joueur / position) = [wall]> et <(raycaster / bloqueur) = [libre]>> alors
mettre la couleur du stylo à [#00aaff] // #00aaff
mettre [raycaster / bloqueur v] à [bloqué]
fin
-

Raycaster

Encore un bloc personnalisé, sans rafraîchissement d'écran :

définir Raycast (précision) // Propagation par rayon (0 > précision ≥ 1)
Fond d'écran::custom
mettre [raycaster / direction v] à ((-90) + ((360) * (((sourix x::sensing) + (240)) / (480))))  // permet de s'orienter en fonction de la position x de la souris
s'orienter à ( (raycaster / direction) - ((param / champ de vision) / (2)))
mettre [raycaster / x v] à (0)
répéter ((param / champ de vision) * (précision)) fois
aller à x:(joueur / x) y:(joueur / y)
mettre [raycaster / étapes v] à (0)
Détecter position joueur (abscisse x) (ordonnée y)::custom
si < <(élément (joueur / position) de [niveau v]) = [wall]> ou < (élément (joueur / position) de [niveau v]) = [exit] > > alors
Aller au début du niveau actuel::custom
stop [ce script v]
fin

répéter jusqu'à ce que < <(raycaster / étapes) > (param / distance de rendu max)> ou < <(élément (joueur / position) de [niveau v]) = [wall]> ou < (élément (joueur / position) de [niveau v]) = [exit] > > >

Avancer de (1) étapes::custom
ajouter (1) à [raycaster / étapes v]
fin

tourner @turnRight de (180) degrés

si < <(élément (joueur / position) de [niveau v]) = [wall]> ou < (élément (joueur / position) de [niveau v]) = [exit] > > alors

répéter jusqu'à ce que < <(raycaster / étapes) < (1)> ou < < non <(élément (joueur / position) de [niveau v]) = [wall]> > et < non < (élément (joueur / position) de [niveau v]) = [exit] > > > >

avancer de (0.1) pas
ajouter (-0.1) à [raycaster / étapes v] // négatif car retourné, lisse les murs
fin

tourner @turnRight de (180) degrés

mettre [raycaster / étapes v] à ((raycaster / étapes) * ([cos v] de ((direction) - (raycaster / direction)))) // permet de tracer des murs droits
mettre la taille du stylo à ([plafond v] de (((480) / (param / champ de vision)) / (précision))) // évite d'avoir des murs hachés
mettre la (transparence v) du stylo à ( ( (100) / ( (param / distance de rendu max) - (param / début du brouillard) ) ) * ( (raycaster / étapes) - (param / début du brouillard) ) )
fin
répéter (1) fois
mettre x à ((-240) + (((480) / (param / champ de vision)) * (raycaster / x)))
mettre y à ((((raycaster / étapes) / (param / distance de rendu max)) * (160)) - (160))
stylo en position d'écriture
mettre y à ((ordonnée y) * (-1))
relever le stylo
fin
ajouter ((1) / (précision)) à [raycaster / x v]
tourner @turnRight de ((1) / (précision)) degrés
fin
s'orienter à (raycaster / direction)
Info
 Info :
La variable param / début du brouillard::variables ring doit être ≥ 0 et ≤ param / distance de rendu max::variables ring. Nous recommandons de définir ces valeurs pour les variables suivantes :
  • param / distance de rendu max::variables ring : 50
  • param / début du brouillard::variables ring : 25, dans l'idéal, ((param / distance de rendu max) - (25))
  • param / champ de vision::variables ring : 90 (1 ≤ x ≤360)
  • précision::custom ring : 0.5

Étape 4 : Fin de projet

Ajoutez le bloc Raycaster et FPS dans Render :

définir Render
FPS (track / dernier 1/30)::custom
Physique::custom
Raycaster (0.5)::custom

Créez plusieurs nouveaux niveaux pour votre projet et ajoutez-les dans la liste niveaux::list ring. Ensuite, ajoutez ce script dans votre sprite :

quand @greenFlag est cliqué
cacher
basculer sur le costume (vide v)
mettre [niveau actuel v] à (1)
répéter (longueur de [niveaux v]) fois
Jouer le niveau (niveau actuel)::custom
ajouter (1) à [niveau actuel v]
fin
aller à x:(0) y:(0)
basculer sur le costume (fin v)
montrer

Libre à vous de créer le costume montré quand le joueur a fini tous les niveaux.
Vous pouvez lui donner son temps avec le chronomètre.
N'oubliez pas de donner les instructions du projet et les crédits (les crédits au wiki francophone sont toujours la bienvenue).
Vous pouvez aussi créditer le projet original (par exemple en le remixant), mais c'est facultatif.

Bonus

Ce qui suit est complétement facultatif.

Définir des paramètres (bonus)

Info
 Info :
Avec TurboWarp, vous pouvez augmenter la précision du rendu. Nous recommandons de définir ces valeurs pour les variables suivantes :
  • param / distance de rendu max::variables ring : 100
  • param / début du brouillard::variables ring : 75
  • param / champ de vision::variables ring : 90
  • précision::custom ring : 0.2

Afficher selon des textures au .imw (bonus) en fonction du niveau

Ajouter des IAs (bonus)

Vous pouvez proposer à votre joueur d'affronter une IA en essayant d'être plus rapide qu'elle.


Ajouter une carte du niveau

Vous pouvez dans un coin du niveau afficher une minimap du niveau avec le stylo et un bloc personnalisé sans rafraîchissement d'écran à ajouter dans Render.

définir Render
FPS (track / dernier 1/30)::custom
Physique::custom
Raycaster (0.5)::custom
Minmap::custom // ajoutez le bloc ici
définir Minmap
détecter position joueur (joueur / x) (joueur / Y)::custom
mettre [minmap / idx v] à (1)
mettre la taille du stylo à ((4) / (3))
aller à x:(195) y:(175)
répéter (23) fois
répéter (30) fois
si <(minmap / idx) = (joueur / position)> alors
mettre la couleur du stylo à [#ff2222] // #ff2222
sinon
si <(élément (minmap / idx) de [niveau v]) = [wall]> alors
mettre la couleur du stylo à [#00aaff] // #00aaff
sinon
mettre la couleur du stylo à [#eeeeee] // #eeeee
fin
fin
stylo en position d'écriture
relever le stylo
ajouter ((4) / (3)) à x
ajouter (1) à [minmap / idx v]
fin
aller à x:(195) y:((ordonnée y) - ((4) / (3)))
fin

Voir aussi

Cet article fait partie de la catégorie des tutos
Tous les articles de cette catégorie :