Console
Clique sur « Exécuter » pour lancer le programme.
Aucune exécutionCtrl+Entrée : exécuter · Échap : arrêter
Code CoddyRun
@ L'HELICO DES CAVERNES
// Pilote un helicoptere dans une grotte sans fin qui se resserre peu a peu !
// Z (ou un clic) : donner un coup de rotor pour monter. P : pause.
// Ramasse les pieces, les diamants et les bidons d'essence,
// et evite les parois et les rochers pointus.
@ Initialisation des variables
toileJeu est une toile
dimension(toileJeu, 800, 400)
heliX est un nombre
heliY est un nombre
vitesseY est un nombre
vitesseX est un nombre
gravite est un nombre
cameraX est un nombre
carburant est un nombre
pieces est un nombre
record est un nombre
imageNum est un nombre
explosionT est un nombre
poussee est un nombre
enCours est un booléen
enPause est un booléen
finProcessus est un booléen
causeFin est un texte
// Dictionnaire pour memoriser les objets ramasses (comme dans le jeu de voiture)
objetsRamasses est un dictionnaire
objetsRamasses vaut [:]
// Fumee du rotor (positions dans le monde)
fumX est un tableau
fumY est un tableau
fumT est un tableau
// Ramassages recents (textes qui s'envolent)
gainX est un tableau
gainY est un tableau
gainTxt est un tableau
gainT est un tableau
gravite vaut 0.9
@ Record
essayer
record vaut paramètre('helico_cavernes', 'record')
attraper
record vaut 0
fin essayer
@ La grotte : tout est calcule avec des sinus
// centre de la grotte a la position x
fonction centreGrotte(x)
retourne 200 + sinus(x / 260) * 55 + sinus(x / 97) * 22
fin fonction
// hauteur de la grotte : elle se resserre avec la distance
fonction ecartGrotte(x)
retourne maximum(150, 280 - x / 90)
fin fonction
fonction hautGrotte(x)
retourne centreGrotte(x) - ecartGrotte(x) / 2
fin fonction
fonction basGrotte(x)
retourne centreGrotte(x) + ecartGrotte(x) / 2
fin fonction
@ Les objets : un emplacement tous les 150 pixels
// 0 rien, 1 rocher pointu, 2 bidon d'essence, 3 diamant, 4 piece
fonction typeEmplacement(s)
res est un nombre
res vaut 0
si s >= 4 alors
si s mod 6 = 3 alors
res vaut 1
sinon si s mod 20 = 10 alors
res vaut 2
sinon si s mod 30 = 25 alors
res vaut 3
sinon si s mod 6 = 1 ou s mod 6 = 5 alors
res vaut 4
fin si
fin si
retourne res
fin fonction
fonction xEmplacement(s)
retourne s * 150 + 75
fin fonction
// hauteur d'un objet a ramasser : il ondule dans la grotte
fonction yObjet(s)
ox est un nombre
ox vaut xEmplacement(s)
retourne centreGrotte(ox) + sinus(ox / 70) * ecartGrotte(ox) * 0.22
fin fonction
// les rochers pendent du plafond ou sortent du sol, un groupe sur deux
fonction rocherEnHaut(s)
retourne arrondi_inferieur(s / 6) mod 2 = 0
fin fonction
fonction longueurRocher(s)
ox est un nombre
ox vaut xEmplacement(s)
retourne ecartGrotte(ox) * (0.42 + minimum(0.14, ox / 40000))
fin fonction
@ Nouvelle partie
procédure nouvellePartie()
heliX vaut 150
heliY vaut 200
vitesseY vaut 0
vitesseX vaut 6
cameraX vaut heliX - 200
carburant vaut 100
pieces vaut 0
imageNum vaut 0
explosionT vaut 0
poussee vaut 0
enCours vaut vrai
enPause vaut faux
finProcessus vaut faux
causeFin vaut ""
objetsRamasses vaut [:]
vide fumX
vide fumY
vide fumT
vide gainX
vide gainY
vide gainTxt
vide gainT
fin procédure
procédure ajouterGain(gx, gy, txt)
gainX ajoute gx
gainY ajoute gy
gainTxt ajoute txt
gainT ajoute 14
fin procédure
@ Dessin de l'helicoptere
procédure dessinerHelico(hx, hy)
// faisceau du phare dans le noir
polygone(toileJeu, [hx + 22, hy + 2, hx + 190, hy - 45, hx + 190, hy + 55], rgba(255, 244, 180, 0.10))
// queue et rotor arriere
rectangle(toileJeu, hx - 46, hy - 5, 28, 6, #f59f00)
si imageNum mod 2 = 0 alors
cercle(toileJeu, hx - 46, hy - 3, 7, rgba(220, 220, 220, 0.5))
sinon
cercle(toileJeu, hx - 46, hy - 3, 3, #dee2e6)
fin si
// corps et cockpit
ellipse(toileJeu, hx, hy, 24, 13, #f59f00)
ellipse(toileJeu, hx + 9, hy - 3, 11, 8, #a5d8ff)
ellipse(toileJeu, hx + 6, hy - 6, 4, 2, rgba(255, 255, 255, 0.7))
rectangle(toileJeu, hx - 20, hy + 2, 36, 3, #e8590c)
// patins
ligne(toileJeu, hx - 10, hy + 11, hx - 12, hy + 17, #495057, 2)
ligne(toileJeu, hx + 10, hy + 11, hx + 12, hy + 17, #495057, 2)
ligne(toileJeu, hx - 20, hy + 17, hx + 20, hy + 17, #495057, 3)
// rotor principal qui tourne
ligne(toileJeu, hx, hy - 13, hx, hy - 19, #495057, 3)
si imageNum mod 2 = 0 alors
ligne(toileJeu, hx - 32, hy - 20, hx + 32, hy - 20, #dee2e6, 3)
sinon
ligne(toileJeu, hx - 12, hy - 20, hx + 12, hy - 20, #dee2e6, 3)
fin si
fin procédure
@ Dessin de toute la scene
procédure dessinerScene()
effacer(toileJeu)
contour(toileJeu, #0)
// fond de la grotte
dégradé(toileJeu, [#141430, #22183d, #141430])
// parois lointaines (elles defilent plus lentement : effet de profondeur)
pointsFondH est un tableau
pointsFondH ajoute -10
pointsFondH ajoute -10
pointsFondB est un tableau
pointsFondB ajoute -10
pointsFondB ajoute 410
i est un nombre
pour i de 0 à 82
txF est un nombre
txF vaut (cameraX * 0.4) + (i * 10)
pointsFondH ajoute i * 10
pointsFondH ajoute 70 + sinus(txF / 110) * 30
pointsFondB ajoute i * 10
pointsFondB ajoute 330 + sinus(txF / 130) * 30
fin pour
pointsFondH ajoute 830
pointsFondH ajoute -10
pointsFondB ajoute 830
pointsFondB ajoute 410
polygone(toileJeu, pointsFondH, #2a2250)
polygone(toileJeu, pointsFondB, #2a2250)
// parois de la grotte (plafond et sol)
pointsHaut est un tableau
pointsHaut ajoute -10
pointsHaut ajoute -10
pointsBas est un tableau
pointsBas ajoute -10
pointsBas ajoute 410
pour i de 0 à 82
tx est un nombre
tx vaut cameraX + (i * 10)
pointsHaut ajoute i * 10
pointsHaut ajoute hautGrotte(tx)
pointsBas ajoute i * 10
pointsBas ajoute basGrotte(tx)
fin pour
pointsHaut ajoute 830
pointsHaut ajoute -10
pointsBas ajoute 830
pointsBas ajoute 410
contour(toileJeu, #9775fa, 3)
polygone(toileJeu, pointsHaut, #3b2f63)
polygone(toileJeu, pointsBas, #3b2f63)
contour(toileJeu, #0)
// cristaux lumineux incrustes dans les parois (decor)
baseC est un nombre
baseC vaut arrondi_inferieur(cameraX / 240) * 240
kc est un nombre
pour kc de 0 à 4
crX est un nombre
crX vaut baseC + kc * 240 + 120
crE est un nombre
crE vaut crX - cameraX
crH est un nombre
crH vaut hautGrotte(crX)
crB est un nombre
crB vaut basGrotte(crX)
si arrondi_inferieur(crX / 240) mod 3 = 0 alors
polygone(toileJeu, [crE - 6, crH - 2, crE + 6, crH - 2, crE, crH + 16], #63e6be)
polygone(toileJeu, [crE - 5, crB + 2, crE + 5, crB + 2, crE + 1, crB - 14], #f783ac)
sinon
polygone(toileJeu, [crE - 5, crH - 2, crE + 5, crH - 2, crE - 1, crH + 12], #74c0fc)
polygone(toileJeu, [crE - 6, crB + 2, crE + 6, crB + 2, crE, crB - 16], #ffd43b)
fin si
fin pour
// les objets visibles a l'ecran
sDebut est un nombre
sDebut vaut arrondi_inferieur(cameraX / 150) - 1
ks est un nombre
pour ks de sDebut à sDebut + 7
sorte est un nombre
sorte vaut typeEmplacement(ks)
oxW est un nombre
oxW vaut xEmplacement(ks)
oxE est un nombre
oxE vaut oxW - cameraX
cle est un texte
cle vaut "S_" + convertir_texte(ks)
si sorte = 1 alors
// rocher pointu
lgR est un nombre
lgR vaut longueurRocher(ks)
si rocherEnHaut(ks) alors
baseR est un nombre
baseR vaut hautGrotte(oxW) - 6
polygone(toileJeu, [oxE - 22, baseR, oxE + 22, baseR, oxE + 15, baseR + lgR * 0.7, oxE, baseR + lgR + 6, oxE - 15, baseR + lgR * 0.7], #5f4b8b)
ligne(toileJeu, oxE - 6, baseR + 10, oxE - 2, baseR + lgR * 0.6, #7950f2, 2)
sinon
baseR vaut basGrotte(oxW) + 6
polygone(toileJeu, [oxE - 22, baseR, oxE + 22, baseR, oxE + 15, baseR - lgR * 0.7, oxE, baseR - lgR - 6, oxE - 15, baseR - lgR * 0.7], #5f4b8b)
ligne(toileJeu, oxE - 6, baseR - 10, oxE - 2, baseR - lgR * 0.6, #7950f2, 2)
fin si
sinon si sorte >= 2 et contient(objetsRamasses, cle) = faux alors
oyE est un nombre
oyE vaut yObjet(ks)
si sorte = 2 alors
// bidon d'essence
rectangle_arrondi(toileJeu, oxE - 12, oyE - 16, 24, 32, 4, #e03131)
rectangle(toileJeu, oxE - 4, oyE - 22, 8, 7, #adb5bd)
label(toileJeu, oxE - 5, oyE + 6, "E", #ffffff, 14)
sinon si sorte = 3 alors
// diamant qui scintille
si imageNum mod 6 < 3 alors
cercle(toileJeu, oxE, oyE, 20, rgba(99, 230, 190, 0.25))
fin si
polygone(toileJeu, [oxE, oyE - 14, oxE + 12, oyE - 3, oxE, oyE + 14, oxE - 12, oyE - 3], #63e6be)
polygone(toileJeu, [oxE, oyE - 14, oxE + 5, oyE - 3, oxE, oyE + 4, oxE - 5, oyE - 3], #c3fae8)
sinon
// piece d'or
cercle(toileJeu, oxE, oyE, 11, #ffd43b)
cercle(toileJeu, oxE, oyE, 7, #f59f00)
label(toileJeu, oxE - 3, oyE + 4, "$", #ffffff, 10)
fin si
fin si
fin pour
// fumee
si longueur(fumT) > 0 alors
kf est un nombre
pour kf de 0 à longueur(fumT) - 1
cercle(toileJeu, fumX[kf] - cameraX, fumY[kf], 3 + (10 - fumT[kf]), rgba(200, 200, 220, 0.04 * fumT[kf]))
fin pour
fin si
// helicoptere (ou explosion)
hxE est un nombre
hxE vaut heliX - cameraX
si explosionT = 0 alors
appelle dessinerHelico(hxE, heliY)
sinon
cercle(toileJeu, hxE, heliY, explosionT * 6, rgba(255, 146, 43, 0.5))
cercle(toileJeu, hxE, heliY, explosionT * 4, rgba(255, 212, 59, 0.7))
cercle(toileJeu, hxE, heliY, explosionT * 2, #ffffff)
ligne(toileJeu, hxE, heliY, hxE - explosionT * 7, heliY - explosionT * 4, #f59f00, 3)
ligne(toileJeu, hxE, heliY, hxE + explosionT * 8, heliY - explosionT * 2, #adb5bd, 3)
ligne(toileJeu, hxE, heliY, hxE + explosionT * 3, heliY + explosionT * 6, #f59f00, 3)
fin si
// gains qui s'envolent
si longueur(gainT) > 0 alors
kg est un nombre
pour kg de 0 à longueur(gainT) - 1
label(toileJeu, gainX[kg] - cameraX, gainY[kg], gainTxt[kg], #ffffff, 16)
fin pour
fin si
// interface
distance est un nombre
distance vaut arrondi(heliX / 10)
rectangle_arrondi(toileJeu, 10, 10, 260, 92, 10, rgba(0, 0, 0, 0.55))
label(toileJeu, 22, 34, "Distance : " + convertir_texte(distance) + " m", #ffffff, 17)
label(toileJeu, 22, 60, "Pieces : " + convertir_texte(pieces), #ffd43b, 16)
label(toileJeu, 22, 88, "Essence", #cbd5e1, 13)
contour(toileJeu, #ffffff, 1)
rectangle(toileJeu, 86, 76, 150, 14, rgba(255, 255, 255, 0.15))
contour(toileJeu, #0)
si carburant > 0 alors
si carburant < 25 alors
si imageNum mod 6 < 3 alors
rectangle(toileJeu, 86, 76, carburant * 1.5, 14, #ff6b6b)
fin si
sinon
rectangle(toileJeu, 86, 76, carburant * 1.5, 14, #51cf66)
fin si
fin si
rectangle_arrondi(toileJeu, 600, 10, 190, 34, 10, rgba(0, 0, 0, 0.55))
label(toileJeu, 614, 32, "Record : " + convertir_texte(record) + " m", #a5b4fc, 14)
fin procédure
@ Processus principal : la physique et l'affichage
processus BoucleJeu()
tant que enCours = vrai
imageNum ajoute 1
// 1. Consommation d'essence
carburant soustrait 0.08
si carburant <= 0 alors
carburant vaut 0
fin si
// 2. Physique : la vitesse augmente doucement avec la distance
vitesseX vaut minimum(12, 6 + heliX / 2500)
vitesseY ajoute gravite
si poussee > 0 alors
vitesseY vaut -7.5
poussee soustrait 1
fin si
vitesseY vaut limiter(vitesseY, -8, 10)
heliX ajoute vitesseX
heliY ajoute vitesseY
cameraX vaut heliX - 200
// 3. Fumee derriere l'helico
si imageNum mod 2 = 0 alors
fumX ajoute heliX - 46
fumY ajoute heliY - 3
fumT ajoute 10
fin si
nbF est un nombre
nbF vaut longueur(fumT)
si nbF > 0 alors
kf est un nombre
pour kf de nbF - 1 à 0 pas -1
fumT[kf] vaut fumT[kf] - 1
fumY[kf] vaut fumY[kf] - 1
si fumT[kf] <= 0 alors
fumX supprime kf
fumY supprime kf
fumT supprime kf
fin si
fin pour
fin si
nbG est un nombre
nbG vaut longueur(gainT)
si nbG > 0 alors
kg est un nombre
pour kg de nbG - 1 à 0 pas -1
gainT[kg] vaut gainT[kg] - 1
gainY[kg] vaut gainY[kg] - 2
si gainT[kg] <= 0 alors
gainX supprime kg
gainY supprime kg
gainTxt supprime kg
gainT supprime kg
fin si
fin pour
fin si
// 4. Collisions avec les parois (on teste l'avant, le milieu et l'arriere)
kp est un nombre
pour kp de -1 à 1
pxT est un nombre
pxT vaut heliX + kp * 20
si heliY - 14 < hautGrotte(pxT) alors
enCours vaut faux
causeFin vaut "Aie ! Tu as touche le plafond."
fin si
si heliY + 16 > basGrotte(pxT) alors
enCours vaut faux
causeFin vaut "Aie ! Tu as touche le sol."
fin si
fin pour
// 5. Les objets proches : rochers, essence, diamants, pieces
sProche est un nombre
sProche vaut arrondi_inferieur((heliX - 75) / 150)
ko est un nombre
pour ko de sProche à sProche + 1
sorte est un nombre
sorte vaut typeEmplacement(ko)
oxW est un nombre
oxW vaut xEmplacement(ko)
cle est un texte
cle vaut "S_" + convertir_texte(ko)
si sorte = 1 alors
si absolue(heliX - oxW) < 38 alors
lgR est un nombre
lgR vaut longueurRocher(ko)
si rocherEnHaut(ko) alors
si heliY - 12 < hautGrotte(oxW) + lgR alors
enCours vaut faux
causeFin vaut "Crac ! Un rocher pointu..."
fin si
sinon
si heliY + 14 > basGrotte(oxW) - lgR alors
enCours vaut faux
causeFin vaut "Crac ! Un rocher pointu..."
fin si
fin si
fin si
sinon si sorte >= 2 et contient(objetsRamasses, cle) = faux alors
oyW est un nombre
oyW vaut yObjet(ko)
si absolue(heliX - oxW) < 32 et absolue(heliY - oyW) < 30 alors
objetsRamasses[cle] vaut vrai
si sorte = 2 alors
carburant vaut minimum(100, carburant + 35)
appelle ajouterGain(oxW - 30, oyW, "+ ESSENCE")
sinon si sorte = 3 alors
pieces ajoute 5
appelle ajouterGain(oxW - 12, oyW, "+5")
sinon
pieces ajoute 1
appelle ajouterGain(oxW - 8, oyW, "+1")
fin si
fin si
fin si
fin pour
appelle dessinerScene()
si carburant <= 0 et enCours alors
label(toileJeu, 290, 200, "PLUS D'ESSENCE : le rotor ralentit !", #ff6b6b, 16)
fin si
affiche toileJeu
pause 60
fin tant que
// Explosion
explosionT vaut 1
tant que explosionT <= 12
imageNum ajoute 1
appelle dessinerScene()
affiche toileJeu
pause 60
explosionT ajoute 1
fin tant que
// Ecran de fin
appelle dessinerScene()
rectangle_arrondi(toileJeu, 200, 90, 400, 220, 16, rgba(0, 0, 0, 0.8))
label(toileJeu, 250, 140, "CRASH !", #ff6b6b, 34)
label(toileJeu, 250, 172, causeFin, #ffffff, 14)
label(toileJeu, 250, 214, "Distance : " + convertir_texte(arrondi(heliX / 10)) + " m", #ffffff, 18)
label(toileJeu, 250, 244, "Pieces : " + convertir_texte(pieces), #ffd43b, 18)
si arrondi(heliX / 10) > record alors
label(toileJeu, 430, 214, "NOUVEAU RECORD !", #63e6be, 14)
fin si
label(toileJeu, 250, 288, "Clique pour continuer", #a5b4fc, 14)
affiche toileJeu
finProcessus vaut vrai
fin processus
@ Ecran titre
procédure dessinerTitre()
appelle nouvellePartie()
appelle dessinerScene()
rectangle_arrondi(toileJeu, 170, 70, 460, 260, 18, rgba(0, 0, 0, 0.75))
label(toileJeu, 215, 125, "L'HELICO DES CAVERNES", #ffd43b, 28)
label(toileJeu, 215, 160, "Vole le plus loin possible dans la grotte !", #d0bfff, 14)
label(toileJeu, 215, 196, "Z ou clic : coup de rotor pour monter", #ffffff, 14)
label(toileJeu, 215, 218, "P : pause", #ffffff, 14)
label(toileJeu, 215, 246, "Pieces +1 Diamants +5 Bidons : essence", #cbd5e1, 13)
label(toileJeu, 215, 268, "Attention aux parois et aux rochers pointus !", #ff8787, 13)
rectangle_arrondi(toileJeu, 300, 282, 200, 36, 18, #2b8a3e)
label(toileJeu, 342, 306, "Clique pour decoller", #ffffff, 14)
fin procédure
@ Entrees utilisateur
action est un nombre
clicX est un nombre
clicY est un nombre
tant que vrai
// titre
appelle dessinerTitre()
affiche toileJeu
cliquer toileJeu dans clicX, clicY
// une partie
appelle nouvellePartie()
BoucleJeu()
tant que enCours = vrai
interagir toileJeu, ['z', 'p'] dans action, clicX, clicY
si action = 2 alors
si enPause alors
enPause vaut faux
reprendre BoucleJeu()
sinon
enPause vaut vrai
suspendre BoucleJeu()
rectangle_arrondi(toileJeu, 300, 160, 200, 70, 14, rgba(0, 0, 0, 0.8))
label(toileJeu, 350, 196, "PAUSE", #ffffff, 26)
label(toileJeu, 322, 218, "P pour reprendre", #a5b4fc, 12)
affiche toileJeu
fin si
sinon si non enPause alors
// Z ou clic : un coup de rotor (s'il reste de l'essence)
si carburant > 0 alors
poussee vaut 2
carburant soustrait 0.2
fin si
fin si
fin tant que
// si le joueur a clique sur l'ecran de fin, c'est son clic "continuer"
dejaVu est un booléen
dejaVu vaut finProcessus
// sinon, on attend la fin de l'explosion puis un clic
tant que finProcessus = faux
pause 100
fin tant que
// record
si arrondi(heliX / 10) > record alors
record vaut arrondi(heliX / 10)
paramètre('helico_cavernes', 'record', record)
fin si
si dejaVu = faux alors
cliquer toileJeu dans clicX, clicY
fin si
fin tant que