Console
Clique sur « Exécuter » pour lancer le programme.
Code CoddyRun
@ CONFIGURATION
ecran est une toile
dimension(ecran, 480, 520)
OX est un nombre
OX vaut 240
OY est un nombre
OY vaut 280
HAUT est un nombre
HAUT vaut 18
TAILLE_MAX est un nombre
TAILLE_MAX vaut 100
COURSE est un nombre
COURSE vaut 150
@ LA TOUR
// chaque etage : coin (x0, y0), largeur (sur x) et profondeur (sur y)
cX0, cY0, cW, cD est un tableau
@ LE BLOC QUI GLISSE
axe, posBloc, sens, vitesse est un nombre
@ LES MORCEAUX QUI TOMBENT
mX0, mY0, mW, mD, mZ, mVZ, mEtage est un tableau
@ ETAT DU JEU
// etat : 0 titre, 1 jeu, 2 perdu
etat est un nombre
etat vaut 0
appActif est un booléen
appActif vaut vrai
lacher est un booléen
lacher vaut faux
score, meilleur, combo, tic, camZ, ech, anneauT, texteT, finT est un nombre
texteEffet est un texte
action, ptX, ptY est un nombre
tic vaut 0
ech vaut 1.2
essayer
meilleur vaut parametre('empile', 'meilleur')
attraper
meilleur vaut 0
fin essayer
@ LES COULEURS : un arc-en-ciel qui tourne doucement, etage apres etage
fonction teinte(k, lum)
r est un nombre
r vaut 150 + 95 * sinus(radians(k * 8))
v est un nombre
v vaut 150 + 95 * sinus(radians(k * 8 + 120))
b est un nombre
b vaut 150 + 95 * sinus(radians(k * 8 + 240))
retourne rgb(arrondi(r * lum), arrondi(v * lum), arrondi(b * lum))
fin fonction
fonction teinteFond(k, clair)
r est un nombre
r vaut 150 + 95 * sinus(radians(k * 8 + 180))
v est un nombre
v vaut 150 + 95 * sinus(radians(k * 8 + 300))
b est un nombre
b vaut 150 + 95 * sinus(radians(k * 8 + 60))
retourne rgb(arrondi(r + (255 - r) * clair), arrondi(v + (255 - v) * clair), arrondi(b + (255 - b) * clair))
fin fonction
@ LA PROJECTION ISOMETRIQUE
fonction ecX(x, y)
retourne OX + (x - y) * 0.866 * ech
fin fonction
fonction ecY(x, y, z)
retourne OY + ((x + y) * 0.5 - (z - camZ)) * ech
fin fonction
// un pave : coin (x0, y0), tailleB (w, d), du niveau z0 au niveau z0 + h
procédure pave(x0, y0, w, d, z0, h, k)
z1 est un nombre
z1 vaut z0 + h
// face de droite (x = x0 + w)
polygone(ecran, [ecX(x0 + w, y0), ecY(x0 + w, y0, z1), ecX(x0 + w, y0 + d), ecY(x0 + w, y0 + d, z1), ecX(x0 + w, y0 + d), ecY(x0 + w, y0 + d, z0), ecX(x0 + w, y0), ecY(x0 + w, y0, z0)], teinte(k, 0.78))
// face de gauche (y = y0 + d)
polygone(ecran, [ecX(x0, y0 + d), ecY(x0, y0 + d, z1), ecX(x0 + w, y0 + d), ecY(x0 + w, y0 + d, z1), ecX(x0 + w, y0 + d), ecY(x0 + w, y0 + d, z0), ecX(x0, y0 + d), ecY(x0, y0 + d, z0)], teinte(k, 0.62))
// le dessus
polygone(ecran, [ecX(x0, y0), ecY(x0, y0, z1), ecX(x0 + w, y0), ecY(x0 + w, y0, z1), ecX(x0 + w, y0 + d), ecY(x0 + w, y0 + d, z1), ecX(x0, y0 + d), ecY(x0, y0 + d, z1)], teinte(k, 1))
fin procédure
@ UNE PARTIE
procédure nouvellePartie()
vide cX0
vide cY0
vide cW
vide cD
vide mX0
vide mY0
vide mW
vide mD
vide mZ
vide mVZ
vide mEtage
// le socle (etage 0)
cX0 ajoute -TAILLE_MAX / 2
cY0 ajoute -TAILLE_MAX / 2
cW ajoute TAILLE_MAX
cD ajoute TAILLE_MAX
score vaut 0
combo vaut 0
axe vaut 0
posBloc vaut -COURSE
sens vaut 1
vitesse vaut 4
camZ vaut 0
ech vaut 1.2
anneauT vaut 0
texteT vaut 0
finT vaut 0
lacher vaut faux
fin procédure
procédure ajouterMorceau(x0, y0, w, d, z, k)
mX0 ajoute x0
mY0 ajoute y0
mW ajoute w
mD ajoute d
mZ ajoute z
mVZ ajoute 0
mEtage ajoute k
fin procédure
// le joueur lache le bloc
procédure poser()
dern est un nombre
dern vaut longueur(cW) - 1
k est un nombre
k vaut dern + 1
zNiv est un nombre
zNiv vaut dern * HAUT
// le bloc en mouvement et l'etage du dessous, le long de l'axe
m0, t0, tailleB est un nombre
si axe = 0 alors
tailleB vaut cW[dern]
t0 vaut cX0[dern]
sinon
tailleB vaut cD[dern]
t0 vaut cY0[dern]
fin si
m0 vaut t0 + posBloc
o0 est un nombre
o0 vaut maximum(m0, t0)
o1 est un nombre
o1 vaut minimum(m0 + tailleB, t0 + tailleB)
recouvre est un nombre
recouvre vaut o1 - o0
si recouvre <= 0 alors
// rate ! le bloc entier tombe
si axe = 0 alors
appelle ajouterMorceau(m0, cY0[dern], tailleB, cD[dern], zNiv, k)
sinon
appelle ajouterMorceau(cX0[dern], m0, cW[dern], tailleB, zNiv, k)
fin si
etat vaut 2
finT vaut 0
si score > meilleur alors
meilleur vaut score
parametre('empile', 'meilleur', meilleur)
fin si
sinon
nouv0 est un nombre
nouvT est un nombre
si absolue(posBloc) <= 3 alors
// PARFAIT : le bloc se cale pile dessus
combo ajoute 1
nouv0 vaut t0
nouvT vaut tailleB
si combo >= 3 et tailleB < TAILLE_MAX alors
// il regrandit un peu
nouvT vaut minimum(TAILLE_MAX, tailleB + 6)
nouv0 vaut t0 - (nouvT - tailleB) / 2
fin si
anneauT vaut 14
texteT vaut 18
si combo >= 2 alors
texteEffet vaut "PARFAIT x" + convertir_texte(combo)
sinon
texteEffet vaut "PARFAIT !"
fin si
sinon
// on coupe ce qui depasse, et ca tombe
combo vaut 0
nouv0 vaut o0
nouvT vaut recouvre
bout0 est un nombre
boutT est un nombre
si m0 < t0 alors
bout0 vaut m0
boutT vaut t0 - m0
sinon
bout0 vaut t0 + tailleB
boutT vaut m0 - t0
fin si
si axe = 0 alors
appelle ajouterMorceau(bout0, cY0[dern], boutT, cD[dern], zNiv, k)
sinon
appelle ajouterMorceau(cX0[dern], bout0, cW[dern], boutT, zNiv, k)
fin si
fin si
// le nouvel etage
si axe = 0 alors
cX0 ajoute nouv0
cY0 ajoute cY0[dern]
cW ajoute nouvT
cD ajoute cD[dern]
sinon
cX0 ajoute cX0[dern]
cY0 ajoute nouv0
cW ajoute cW[dern]
cD ajoute nouvT
fin si
score ajoute 1
// le bloc suivant arrive de l'autre cote, un peu plus vite
axe vaut 1 - axe
posBloc vaut -COURSE
sens vaut 1
vitesse vaut minimum(4 + score * 0.12, 9)
fin si
fin procédure
@ ANIMATION
procédure animer()
// le bloc glisse et rebondit au bout de sa course
si etat = 1 alors
posBloc vaut posBloc + vitesse * sens
si posBloc > COURSE alors
posBloc vaut COURSE
sens vaut -1
sinon si posBloc < -COURSE alors
posBloc vaut -COURSE
sens vaut 1
fin si
fin si
// les morceaux tombent
nbM est un nombre
nbM vaut longueur(mZ)
si nbM > 0 alors
km est un nombre
pour km de nbM - 1 à 0 pas -1
mVZ[km] vaut mVZ[km] + 1.4
mZ[km] vaut mZ[km] - mVZ[km]
si mZ[km] < camZ - 700 alors
mX0 supprime km
mY0 supprime km
mW supprime km
mD supprime km
mZ supprime km
mVZ supprime km
mEtage supprime km
fin si
fin pour
fin si
// la camera suit le sommet... ou recule pour montrer toute la tour
hauteurTour est un nombre
hauteurTour vaut (longueur(cW) - 1) * HAUT
si etat = 2 alors
finT ajoute 1
si finT > 20 alors
cible est un nombre
cible vaut minimum(1.2, 300 / (hauteurTour + 240))
ech vaut ech + (cible - ech) * 0.08
camZ vaut camZ + (hauteurTour * 0.5 - 40 - camZ) * 0.08
fin si
sinon
camZ vaut camZ + (hauteurTour - camZ) * 0.15
fin si
si anneauT > 0 alors
anneauT soustrait 1
fin si
si texteT > 0 alors
texteT soustrait 1
fin si
fin procédure
@ DESSIN
procédure centrer(txt, cx, ty, coul, taillePolice)
label(ecran, cx - label_largeur(txt, taillePolice) / 2, ty, txt, coul, taillePolice)
fin procédure
procédure dessinerTout()
effacer(ecran)
contour(ecran, #0)
dégradé(ecran, [teinteFond(score, 0.55), teinteFond(score + 10, 0.2)])
// des petites particules qui flottent
kp est un nombre
pour kp de 0 à 11
px est un nombre
px vaut (kp * 97 + tic * (1 + kp mod 3)) mod 500 - 10
py est un nombre
py vaut 520 - ((kp * 151 + tic * 2) mod 580)
cercle(ecran, px, py, 2 + kp mod 3, rgba(255, 255, 255, 0.25))
fin pour
// le socle : un grand pilier qui descend hors de l'ecran
appelle pave(-TAILLE_MAX / 2, -TAILLE_MAX / 2, TAILLE_MAX, TAILLE_MAX, -400, 400, 0)
// les etages (on ne dessine que ceux qui sont visibles)
ke est un nombre
nb est un nombre
nb vaut longueur(cW)
dern est un nombre
dern vaut nb - 1
pour ke de 1 à nb - 1
yBas est un nombre
yBas vaut ecY(cX0[ke], cY0[ke], (ke - 1) * HAUT)
si yBas > -60 et yBas < 640 alors
appelle pave(cX0[ke], cY0[ke], cW[ke], cD[ke], (ke - 1) * HAUT, HAUT, ke)
fin si
fin pour
// l'onde du "parfait" autour du sommet
si anneauT > 0 alors
marge est un nombre
marge vaut (14 - anneauT) * 2.5
zA est un nombre
zA vaut dern * HAUT
x0 est un nombre
x0 vaut cX0[dern] - marge
y0 est un nombre
y0 vaut cY0[dern] - marge
x1 est un nombre
x1 vaut cX0[dern] + cW[dern] + marge
y1 est un nombre
y1 vaut cY0[dern] + cD[dern] + marge
contour(ecran, rgba(255, 255, 255, anneauT / 14), 3)
polygone(ecran, [ecX(x0, y0), ecY(x0, y0, zA), ecX(x1, y0), ecY(x1, y0, zA), ecX(x1, y1), ecY(x1, y1, zA), ecX(x0, y1), ecY(x0, y1, zA)], rgba(255, 255, 255, 0))
contour(ecran, #0)
fin si
// le bloc qui glisse
si etat = 1 alors
si axe = 0 alors
appelle pave(cX0[dern] + posBloc, cY0[dern], cW[dern], cD[dern], dern * HAUT, HAUT, nb)
sinon
appelle pave(cX0[dern], cY0[dern] + posBloc, cW[dern], cD[dern], dern * HAUT, HAUT, nb)
fin si
fin si
// les morceaux qui tombent
si longueur(mZ) > 0 alors
km est un nombre
pour km de 0 à longueur(mZ) - 1
appelle pave(mX0[km], mY0[km], mW[km], mD[km], mZ[km], HAUT, mEtage[km])
fin pour
fin si
// le score
si etat <> 0 alors
appelle centrer(convertir_texte(score), 242, 92, rgba(0, 0, 0, 0.15), 64)
appelle centrer(convertir_texte(score), 240, 90, #FFFFFF, 64)
fin si
si texteT > 0 et etat = 1 alors
appelle centrer(texteEffet, 240, 140 - (18 - texteT), rgba(255, 255, 255, texteT / 18), 22)
fin si
si etat = 0 alors
appelle centrer("EMPILE", 243, 123, rgba(0, 0, 0, 0.15), 64)
appelle centrer("EMPILE", 240, 120, #FFFFFF, 64)
appelle centrer("Pose les blocs le plus haut possible", 240, 152, rgba(255, 255, 255, 0.85), 15)
si tic mod 20 < 14 alors
appelle centrer("ESPACE ou clic pour jouer", 240, 455, #FFFFFF, 18)
fin si
si meilleur > 0 alors
appelle centrer("Meilleur : " + convertir_texte(meilleur), 240, 485, rgba(255, 255, 255, 0.8), 14)
fin si
sinon si etat = 2 et finT > 30 alors
rectangle_arrondi(ecran, 110, 392, 260, 112, 20, rgba(255, 255, 255, 0.2))
appelle centrer("Ta tour : " + convertir_texte(score) + " étages", 240, 424, #FFFFFF, 18)
si score >= meilleur et score > 0 alors
appelle centrer("NOUVEAU RECORD !", 240, 452, #FFF59D, 16)
sinon
appelle centrer("Meilleur : " + convertir_texte(meilleur), 240, 452, rgba(255, 255, 255, 0.85), 15)
fin si
si tic mod 20 < 14 alors
appelle centrer("ESPACE pour rejouer", 240, 486, #FFFFFF, 15)
fin si
fin si
fin procédure
@ LE PROCESSUS : il anime, il pose, il dessine
processus Moteur()
tant que appActif
tic ajoute 1
si lacher alors
lacher vaut faux
si etat = 1 alors
appelle poser()
fin si
fin si
si etat <> 3 alors
appelle animer()
appelle dessinerTout()
affiche ecran
fin si
pause 60
fin tant que
fin processus
@ DEMARRAGE
appelle nouvellePartie()
Moteur()
tant que appActif
interagir ecran, [" ", "x"] dans action, ptX, ptY
si action = 2 alors
appActif vaut faux
sinon si etat = 1 alors
// on demande au processus de poser le bloc
lacher vaut vrai
sinon si etat = 0 alors
etat vaut 1
sinon si etat = 2 et finT > 30 alors
etat vaut 3
appelle nouvellePartie()
etat vaut 1
fin si
fin tant que
effacer(ecran)
dégradé(ecran, [#B39DDB, #80DEEA])
label(ecran, 240 - label_largeur("À bientôt !", 34) / 2, 270, "À bientôt !", #FFFFFF, 34)
affiche ecran