Console
Clique sur « Exécuter » pour lancer le programme.
Code CoddyRun
@ CONFIGURATION
ecran est une toile
dimension(ecran, 480, 520)
CX est un nombre
CX vaut 240
CY est un nombre
CY vaut 190
RAYON est un nombre
RAYON vaut 78
LONG_FL est un nombre
LONG_FL vaut 56
DEPART_Y est un nombre
DEPART_Y vaut 470
ECART_MIN est un nombre
ECART_MIN vaut 10
@ LA CIBLE
// angles (en degres, relatifs a la cible) des flechettes plantees et des pommes
plantees est un tableau
pommes est un tableau
rotation, vitesseRot, tempsCible est un nombre
@ LA FLECHETTE EN VOL, ET CELLE QUI REBONDIT
enVol est un booléen
volY est un nombre
rebX, rebY, rebVX, rebVY, rebAng est un nombre
@ EFFETS
eclX, eclY, eclVX, eclVY, eclT, eclC est un tableau
@ ETAT DU JEU
// etat : 0 titre, 1 jeu, 2 perdu, 3 cible brisee, 9 preparation
etat est un nombre
etat vaut 0
appActif est un booléen
appActif vaut vrai
lancer est un booléen
lancer vaut faux
niveau, restantes, score, meilleur, tic, secousse, flashT, finT, tranchees est un nombre
action, ptX, ptY est un nombre
messageNiv est un texte
messageT est un nombre
tic vaut 0
essayer
meilleur vaut parametre('flechettes', 'meilleur')
attraper
meilleur vaut 0
fin essayer
@ OUTILS
// distance entre deux angles (0 a 180)
fonction ecartAngle(a1, a2)
d est un nombre
d vaut absolue(a1 - a2) mod 360
si d > 180 alors
d vaut 360 - d
fin si
retourne d
fin fonction
fonction estBoss()
retourne niveau mod 5 = 0
fin fonction
procédure eclats(x, y, coul, nb)
ke est un nombre
pour ke de 1 à nb
si longueur(eclT) < 120 alors
eclX ajoute x
eclY ajoute y
eclVX ajoute hasard(-8, 8)
eclVY ajoute hasard(-10, 2)
eclT ajoute hasard(12, 26)
eclC ajoute coul
fin si
fin pour
fin procédure
procédure centrer(txt, xMil, ty, coul, taillePolice)
label(ecran, xMil - label_largeur(txt, taillePolice) / 2, ty, txt, coul, taillePolice)
fin procédure
@ LES NIVEAUX
procédure preparerNiveau()
vide plantees
vide pommes
rotation vaut 0
tempsCible vaut 0
enVol vaut faux
restantes vaut 5 + minimum(niveau, 6)
si estBoss() alors
restantes vaut 9
fin si
// des flechettes deja plantees (des obstacles), bien espacees
nbObs est un nombre
nbObs vaut minimum(niveau - 1, 4)
essais est un nombre
essais vaut 0
angA est un nombre
ok est un booléen
ko est un nombre
tant que longueur(plantees) < nbObs et essais < 100
essais ajoute 1
angA vaut hasard(0, 359)
ok vaut vrai
si longueur(plantees) > 0 alors
pour ko de 0 à longueur(plantees) - 1
si ecartAngle(angA, plantees[ko]) < 35 alors
ok vaut faux
fin si
fin pour
fin si
si ok alors
plantees ajoute angA
fin si
fin tant que
// une ou deux pommes, loin des flechettes
nbPommes est un nombre
nbPommes vaut hasard(1, 2)
essais vaut 0
tant que longueur(pommes) < nbPommes et essais < 100
essais ajoute 1
angA vaut hasard(0, 359)
ok vaut vrai
si longueur(plantees) > 0 alors
pour ko de 0 à longueur(plantees) - 1
si ecartAngle(angA, plantees[ko]) < 25 alors
ok vaut faux
fin si
fin pour
fin si
si longueur(pommes) > 0 alors
pour ko de 0 à longueur(pommes) - 1
si ecartAngle(angA, pommes[ko]) < 40 alors
ok vaut faux
fin si
fin pour
fin si
si ok alors
pommes ajoute angA
fin si
fin tant que
si estBoss() alors
messageNiv vaut "BOSS !"
sinon
messageNiv vaut "NIVEAU " + convertir_texte(niveau)
fin si
messageT vaut 30
fin procédure
procédure nouvellePartie()
niveau vaut 1
score vaut 0
tranchees vaut 0
secousse vaut 0
flashT vaut 0
finT vaut 0
vide eclX
vide eclY
vide eclVX
vide eclVY
vide eclT
vide eclC
appelle preparerNiveau()
fin procédure
// la facon de tourner change selon le niveau
fonction vitesseCible()
base est un nombre
base vaut 2.2 + minimum(niveau, 20) * 0.12
t est un nombre
t vaut tempsCible
si estBoss() alors
retourne base * 1.5 * sinus(radians(t * 2.2)) + base * 0.5
fin si
sorte est un nombre
sorte vaut niveau mod 4
si sorte = 1 alors
retourne base
sinon si sorte = 2 alors
// ralentit, accelere, repart dans l'autre sens
retourne base * 1.4 * sinus(radians(t * 1.5))
sinon si sorte = 3 alors
// change brusquement de sens
si arrondi_inferieur(t / 70) mod 2 = 0 alors
retourne base * 1.2
fin si
retourne -base * 1.2
fin si
// a-coups
retourne base * (1 + 0.8 * sinus(radians(t * 3)))
fin fonction
@ L'IMPACT
procédure impact()
// l'endroit touche : le bas de la cible (90 degres a l'ecran)
angleImpact est un nombre
angleImpact vaut ((90 - rotation) mod 360 + 360) mod 360
touche est un booléen
touche vaut faux
ko est un nombre
si longueur(plantees) > 0 alors
pour ko de 0 à longueur(plantees) - 1
si ecartAngle(angleImpact, plantees[ko]) < ECART_MIN alors
touche vaut vrai
fin si
fin pour
fin si
enVol vaut faux
si touche alors
// CLING ! la flechette rebondit : c'est perdu
rebX vaut CX
rebY vaut CY + RAYON
rebVX vaut sialors(hasard(0, 1) = 0, -5, 5)
rebVY vaut 3
rebAng vaut -90
secousse vaut 8
flashT vaut 5
appelle eclats(CX, CY + RAYON, #ECEFF1, 10)
si score > meilleur alors
meilleur vaut score
parametre('flechettes', 'meilleur', meilleur)
fin si
etat vaut 2
finT vaut 0
sinon
plantees ajoute angleImpact
restantes soustrait 1
score ajoute 1
secousse vaut 3
appelle eclats(CX, CY + RAYON, #A1887F, 5)
// une pomme tranchee ?
nbP est un nombre
nbP vaut longueur(pommes)
si nbP > 0 alors
pour ko de nbP - 1 à 0 pas -1
si ecartAngle(angleImpact, pommes[ko]) < 13 alors
xp est un nombre
xp vaut CX + cosinus(radians(pommes[ko] + rotation)) * (RAYON + 10)
yp est un nombre
yp vaut CY + sinus(radians(pommes[ko] + rotation)) * (RAYON + 10)
appelle eclats(xp, yp, #E53935, 10)
appelle eclats(xp, yp, #FFF59D, 6)
pommes supprime ko
score ajoute 5
tranchees ajoute 1
fin si
fin pour
fin si
si restantes = 0 alors
// la cible eclate !
score ajoute 3
si estBoss() alors
score ajoute 10
fin si
flashT vaut 6
appelle eclats(CX, CY, #8D6E63, 30)
appelle eclats(CX, CY, #D7CCC8, 20)
etat vaut 3
finT vaut 0
fin si
fin si
fin procédure
@ ANIMATION
procédure animer()
si etat = 1 ou etat = 0 alors
tempsCible ajoute 1
rotation vaut rotation + vitesseCible()
fin si
// la flechette lancee monte vers la cible
si enVol alors
volY vaut volY - 30
si volY - LONG_FL <= CY + RAYON alors
appelle impact()
fin si
fin si
// la flechette qui rebondit tombe en tournoyant
si etat = 2 alors
rebX vaut rebX + rebVX
rebY vaut rebY + rebVY
rebVY vaut rebVY + 1.2
rebAng vaut rebAng + rebVX * 4
finT ajoute 1
fin si
si etat = 3 alors
finT ajoute 1
si finT > 28 alors
niveau ajoute 1
appelle preparerNiveau()
etat vaut 1
fin si
fin si
// les eclats
nbE est un nombre
nbE vaut longueur(eclT)
si nbE > 0 alors
ke est un nombre
pour ke de nbE - 1 à 0 pas -1
eclX[ke] vaut eclX[ke] + eclVX[ke]
eclY[ke] vaut eclY[ke] + eclVY[ke]
eclVY[ke] vaut eclVY[ke] + 0.7
eclT[ke] vaut eclT[ke] - 1
si eclT[ke] <= 0 alors
eclX supprime ke
eclY supprime ke
eclVX supprime ke
eclVY supprime ke
eclT supprime ke
eclC supprime ke
fin si
fin pour
fin si
si secousse > 0 alors
secousse soustrait 1
fin si
si flashT > 0 alors
flashT soustrait 1
fin si
si messageT > 0 alors
messageT soustrait 1
fin si
fin procédure
@ DESSIN
// une flechette : pointe en (x, y), dirigee selon l'angle "ang" (degres)
procédure flechette(x, y, ang, coul)
dx est un nombre
dx vaut cosinus(radians(ang))
dy est un nombre
dy vaut sinus(radians(ang))
// le corps part de la pointe vers l'arriere
bx est un nombre
bx vaut x - dx * LONG_FL
by est un nombre
by vaut y - dy * LONG_FL
ligne(ecran, x, y, x - dx * 12, y - dy * 12, #CFD8DC, 3)
ligne(ecran, x - dx * 12, y - dy * 12, bx, by, coul, 5)
// les ailettes
polygone(ecran, [bx + dx * 14, by + dy * 14, bx - dy * 9, by + dx * 9, bx, by], #FAFAFA)
polygone(ecran, [bx + dx * 14, by + dy * 14, bx + dy * 9, by - dx * 9, bx, by], #FAFAFA)
fin procédure
procédure dessinerCible(sx, sy)
ccx est un nombre
ccx vaut CX + sx
ccy est un nombre
ccy vaut CY + sy
// les flechettes plantees (derriere la cible : la pointe est dans le bois)
ko est un nombre
si longueur(plantees) > 0 alors
pour ko de 0 à longueur(plantees) - 1
ang est un nombre
ang vaut plantees[ko] + rotation
// pointe un peu enfoncee dans la cible, corps vers l'exterieur
px est un nombre
px vaut ccx + cosinus(radians(ang)) * (RAYON - 10)
py est un nombre
py vaut ccy + sinus(radians(ang)) * (RAYON - 10)
appelle flechette(px, py, ang + 180, sialors(ko mod 2 = 0, #FF7043, #29B6F6))
fin pour
fin si
// la cible
cercle(ecran, ccx, ccy + 6, RAYON + 4, rgba(0, 0, 0, 0.3))
si estBoss() alors
cercle(ecran, ccx, ccy, RAYON + 4, #37474F)
cercle(ecran, ccx, ccy, RAYON, #78909C)
cercle(ecran, ccx, ccy, RAYON * 0.7, #546E7A)
cercle(ecran, ccx, ccy, RAYON * 0.35, #E53935)
// des rivets qui tournent
kr est un nombre
pour kr de 0 à 7
cercle(ecran, ccx + cosinus(radians(rotation + kr * 45)) * (RAYON - 10), ccy + sinus(radians(rotation + kr * 45)) * (RAYON - 10), 4, #CFD8DC)
fin pour
sinon
cercle(ecran, ccx, ccy, RAYON + 4, #5D4037)
cercle(ecran, ccx, ccy, RAYON, #A1887F)
cercle(ecran, ccx, ccy, RAYON * 0.75, #8D6E63)
cercle(ecran, ccx, ccy, RAYON * 0.5, #A1887F)
cercle(ecran, ccx, ccy, RAYON * 0.25, #D84315)
// les veines du bois tournent avec la cible
kv est un nombre
pour kv de 0 à 5
av est un nombre
av vaut radians(rotation + kv * 60)
ligne(ecran, ccx + cosinus(av) * RAYON * 0.3, ccy + sinus(av) * RAYON * 0.3, ccx + cosinus(av) * RAYON * 0.95, ccy + sinus(av) * RAYON * 0.95, rgba(93, 64, 55, 0.35), 2)
fin pour
fin si
// les pommes posees sur le bord
si longueur(pommes) > 0 alors
pour ko de 0 à longueur(pommes) - 1
ap est un nombre
ap vaut radians(pommes[ko] + rotation)
xp est un nombre
xp vaut ccx + cosinus(ap) * (RAYON + 10)
yp est un nombre
yp vaut ccy + sinus(ap) * (RAYON + 10)
cercle(ecran, xp, yp, 10, #E53935)
cercle(ecran, xp - 3, yp - 3, 3, rgba(255, 255, 255, 0.5))
ligne(ecran, xp, yp - 9, xp + 2, yp - 14, #5D4037, 2)
ellipse(ecran, xp + 6, yp - 13, 4, 2, #43A047)
fin pour
fin si
fin procédure
procédure dessinerTout()
effacer(ecran)
contour(ecran, #0)
si estBoss() et etat >= 1 alors
dégradé(ecran, [#311B92, #1A0E3D])
sinon
dégradé(ecran, [#1E2A44, #0E1424])
fin si
// un halo derriere la cible
cercle(ecran, CX, CY, RAYON + 60, rgba(255, 255, 255, 0.04))
cercle(ecran, CX, CY, RAYON + 30, rgba(255, 255, 255, 0.05))
sx est un nombre
sx vaut 0
sy est un nombre
sy vaut 0
si secousse > 0 alors
sx vaut hasard(-secousse, secousse)
sy vaut hasard(-secousse, secousse)
fin si
si etat <> 3 ou finT < 2 alors
appelle dessinerCible(sx, sy)
fin si
// la flechette prete, ou en vol
si etat = 1 alors
si enVol alors
appelle flechette(CX, volY - LONG_FL, -90, #FFCA28)
sinon
appelle flechette(CX, DEPART_Y - LONG_FL, -90, #FFCA28)
fin si
sinon si etat = 2 alors
appelle flechette(rebX, rebY, rebAng, #FFCA28)
fin si
// les eclats
si longueur(eclT) > 0 alors
ke est un nombre
pour ke de 0 à longueur(eclT) - 1
cercle(ecran, eclX[ke], eclY[ke], 3 + eclT[ke] / 8, eclC[ke])
fin pour
fin si
// les flechettes qui restent, en bas a gauche
si etat >= 1 alors
kr est un nombre
pour kr de 0 à restantes - 1
si kr < 12 alors
rectangle(ecran, 22, 488 - kr * 16, 22, 4, #FFCA28)
triangle(ecran, 44, 486 - kr * 16, 44, 494 - kr * 16, 50, 490 - kr * 16, #CFD8DC)
fin si
fin pour
appelle centrer(convertir_texte(score), 240, 46, #FFFFFF, 34)
label(ecran, 380, 30, "Niveau " + convertir_texte(niveau), rgba(255, 255, 255, 0.7), 13)
label(ecran, 380, 48, "🍎 " + convertir_texte(tranchees), rgba(255, 255, 255, 0.7), 13)
// les 5 etapes jusqu'au boss
kd est un nombre
pour kd de 1 à 5
etape est un nombre
etape vaut (niveau - 1) mod 5 + 1
si kd = 5 alors
cercle(ecran, 20 + kd * 16, 32, 6, sialors(kd <= etape, #E53935, rgba(255, 255, 255, 0.2)))
sinon
cercle(ecran, 20 + kd * 16, 32, 5, sialors(kd <= etape, #FFCA28, rgba(255, 255, 255, 0.2)))
fin si
fin pour
fin si
si messageT > 0 et etat = 1 alors
appelle centrer(messageNiv, 240, 340, rgba(255, 255, 255, messageT / 30), 30)
fin si
si flashT > 0 alors
rectangle(ecran, 0, 0, 480, 520, rgba(255, 255, 255, flashT * 0.05))
fin si
si etat = 0 alors
appelle centrer("FLÉCHETTES", 240, 350, #FFCA28, 40)
appelle centrer("FOLLES", 240, 390, #FFFFFF, 34)
appelle centrer("Ne touche jamais une fléchette déjà plantée !", 240, 420, rgba(255, 255, 255, 0.7), 13)
si tic mod 20 < 14 alors
appelle centrer("ESPACE ou clic pour jouer", 240, 462, #FFFFFF, 17)
fin si
si meilleur > 0 alors
appelle centrer("Meilleur : " + convertir_texte(meilleur), 240, 492, rgba(255, 255, 255, 0.6), 13)
fin si
sinon si etat = 2 et finT > 25 alors
rectangle_arrondi(ecran, 100, 320, 280, 140, 18, rgba(0, 0, 0, 0.5))
appelle centrer("CLING !", 240, 360, #FF7043, 30)
appelle centrer("Score : " + convertir_texte(score) + " (niveau " + convertir_texte(niveau) + ")", 240, 392, #FFFFFF, 15)
si score >= meilleur et score > 0 alors
appelle centrer("NOUVEAU RECORD !", 240, 418, #FFF59D, 15)
sinon
appelle centrer("Meilleur : " + convertir_texte(meilleur), 240, 418, rgba(255, 255, 255, 0.7), 14)
fin si
si tic mod 20 < 14 alors
appelle centrer("ESPACE pour rejouer", 240, 446, #FFFFFF, 14)
fin si
fin si
fin procédure
@ LE PROCESSUS
processus Moteur()
tant que appActif
tic ajoute 1
si lancer alors
lancer vaut faux
si etat = 1 et non enVol alors
enVol vaut vrai
volY vaut DEPART_Y
fin si
fin si
si etat <> 9 alors
appelle animer()
appelle dessinerTout()
affiche ecran
fin si
pause 60
fin tant que
fin processus
@ DEMARRAGE
niveau vaut 1
appelle preparerNiveau()
Moteur()
tant que appActif
interagir ecran, [" ", "x"] dans action, ptX, ptY
si action = 2 alors
appActif vaut faux
sinon si etat = 1 alors
lancer vaut vrai
sinon si etat = 0 ou (etat = 2 et finT > 25) alors
etat vaut 9
appelle nouvellePartie()
etat vaut 1
fin si
fin tant que
effacer(ecran)
dégradé(ecran, [#1E2A44, #0E1424])
label(ecran, 240 - label_largeur("À bientôt !", 34) / 2, 270, "À bientôt !", #FFFFFF, 34)
affiche ecran