Source: Scratch Wiki en français
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 jeuniveaux::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 actuelniveau / idx::ring variables
, une variable qui permettra d'ouvrir un niveauniveau / point::ring variables
, une variable qui permettra d'ouvrir un niveau
Joueur
joueur / x::ring variables
, une variable qui stockera la position x du joueurjoueur / y::ring variables
, une variable qui stockera la position y du joueurjoueur / vx::ring variables
, une variable qui stockera la vitesse x du joueurjoueur / vy::ring variables
, une variable qui stockera la vitesse y du joueurjoueur / frottement::ring variables
, une variable qui stockera la vitesse de décélération du joueurjoueur / position::ring variables
, une variable qui stockera l'élément équivalent à la position du joueur dans leniveau::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
- 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
É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 rafraichissement 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 rafraichissement 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 rafraichissement 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))
É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 rafraichissement d'écran :
définir Render Physique::custom
Initialiser les correcteurs
Toujours sans rafraichissement 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 rafraichissement 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 rafraichissement 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
Fond personnalisé
Un bloc personnalisé, sans rafraichissement 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
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 rafraichissement 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 rafraichissement 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 rafraichissement 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)
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
: 50param / 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)
param / distance de rendu max::variables ring
: 100param / début du brouillard::variables ring
: 75param / champ de vision::variables ring
: 90pré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