celeste2.py

Created by mathieu-croslacoste

Created on February 06, 2026

9.54 KB

Adaptation du script “celeste” par loic-azavant (https://my.numworks.com/python/loic-azavant/celeste) pour Epsilon (le firmware officiel par défaut)

Nécéssite “celeste_levels.py” (https://my.numworks.com/python/mathieu-croslacoste/celeste_levels) pour fonctionner.


from celeste_levels2 import*
class World:
 def __init__(it):it.chap=0;it.x=0;it.y=14;it.datX=0;it.datY=0;it.datH=13;it.datW=20;it.nbOnScreen=(20,13);it.cols=tileCol;it.scale=16;it.deadTiles=(20,21,22,23);it.collTiles=(2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);it.spawnTile=1;it.tramp=18;it.curLv=8;it.dat=();it.t=M()
 def drw(it):
  F(0,14,320,208,tileCol[0])
  for i in range(it.nbOnScreen[1]):
   for j in range(it.nbOnScreen[0]):drwTexture(ord(it.dat[it.curLv][0][(it.datY+i)*it.datW+j+it.datX])-95,it.x+j*it.scale,it.y+i*it.scale)
 def move(it,x,y):
  if 0>it.datX+x or it.datW-it.nbOnScreen[0]<it.datX+x:x=0
  if 0>it.datY+y or it.datH-it.nbOnScreen[1]<it.datY+y:y=0
  if x==0 and y==0:return
  for g in ghosts:F(g.x,g.y,g.sx,g.sy,tileCol[0]);g.x-=x*it.scale;g.y-=y*it.scale
  beforeScreen=[it.dat[it.curLv][0][(it.datY+i)*it.datW+it.datX:(it.datY+i)*it.datW+it.datX+it.nbOnScreen[0]]for i in range(it.nbOnScreen[1])];it.datX+=x;it.datY+=y;nowScreen=[it.dat[it.curLv][0][(it.datY+i)*it.datW+it.datX:(it.datY+i)*it.datW+it.datX+it.nbOnScreen[0]]for i in range(it.nbOnScreen[1])]
  for i in range(it.nbOnScreen[1]):
   for j in range(it.nbOnScreen[0]):
    if beforeScreen[i][j]!=nowScreen[i][j]:drwTexture(ord(nowScreen[i][j])-95,it.x+j*it.scale,it.y+i*it.scale)
  pl.y-=y*it.scale;pl.x-=x*it.scale
 def getMapTileAtPt(it,x,y):return(int((x+it.datX*it.scale-it.x)/it.scale),int((y+it.datY*it.scale-it.y)/it.scale))
 def getMapTilePos(it,x,y):return((x-it.datX)*it.scale+it.x,(y-it.datY)*it.scale+it.y)
 def getTile(it,x,y):
  if x<0 or x>=it.datW or y<0 or y>=it.datH:return 0
  return ord(it.dat[it.curLv][0][y*it.datW+x])-95
ghosts=[]
class Ghost:
 def __init__(it):ghosts.append(it);it.x=int(pl.x);it.y=int(pl.y);it.sx=pl.sx;it.sy=pl.sy;it.c=pl.oriCol;it.maxStep=50;it.step=0
 def drw(it):
  F(it.x,it.y,it.sx,it.sy,it.c)
  if it.step==it.maxStep:ghosts.remove(it);del it;return
  it.step+=1;it.c=((it.c[0]*(it.maxStep-it.step)+tileCol[0][0]*it.step)//it.maxStep,(it.c[1]*(it.maxStep-it.step)+tileCol[0][1]*it.step)//it.maxStep,(it.c[2]*(it.maxStep-it.step)+tileCol[0][2]*it.step)//it.maxStep)
class Player:
 def __init__(it):it.sx=8;it.sy=14;it.vx=0;it.vy=0;it.oriCol=(0,200,0);it.col=(0,200,0);it.nbDash=1;it.maxNbDash=1;it.dashing=0;it.dashT=0;it.maxDashT=16;it.dashSpd=4;it.diagDash=0;it.onGround=0;it.onRwall=0;it.onLwall=0;it.jumpTramp=0;it.climbing=0;it.climbT=0;it.maxClimbT=1000;it.climbSpd=.04;it.maxClimbSpd=.8;it.climbDelay=-1;it.tutoWalljump=0;it.lastLvJump=1;it.nbDeath=0;it.collPrec=1
 def init(it):
  if wrd.curLv==0:it.tutoClimb=0;it.tutoDash=0
  ghosts.clear();wrd.datH,wrd.datW=wrd.dat[wrd.curLv][1];a=wrd.dat[wrd.curLv][0].find("`");x2,y2=a%wrd.datW,a//wrd.datW;wrd.datX=max(0,min(wrd.datW-wrd.nbOnScreen[0],x2-wrd.nbOnScreen[0]//2));wrd.datY=max(0,min(wrd.datH-wrd.nbOnScreen[1],y2-wrd.nbOnScreen[1]//2));it.x,it.y=wrd.getMapTilePos(x2,y2);it.oldX,it.oldY=it.x,it.y;it.vx,it.vy=0,0;it.dashing=0;it.dashT=0;wrd.drw()
 def drw(it,x,y,c):F(int(x),int(y),it.sx,it.sy,c)
 def checkLvOne(it):
  if wrd.chap!=0:return
  if it.x+wrd.datX*wrd.scale<50 and wrd.curLv==0:
   it.climbing=0
   if 1-it.tutoClimb:D("Climb with [back]",75,20,"w",tileCol[0]);it.tutoClimb=1
   if 170>wrd.datX*wrd.scale+it.x>154:D(" "*17,75,20,tileCol[0],tileCol[0])
  if wrd.curLv==1:
   if 1-it.tutoWalljump:D("Walljump by pressing\n[OK] against a wall",3,17,"w",tileCol[0]);it.tutoWalljump=1
  if wrd.datX*wrd.scale+it.x<448 or wrd.curLv!=3:it.nbDash=0
  else:
   if 1-it.tutoDash:
    for i in range(10):it.oldX,it.oldY=it.x,it.y;wrd.move(1,0);it.drw(it.oldX,it.oldY,tileCol[0]);it.drw(it.x,it.y,"g");S(.05)
    for i in range(21):D("Dash with [backspace]"[i],70+i*10,20,"w",tileCol[0]);S(.08)
    while 1-K(17):0
    D(" "*21,70,20,tileCol[0],tileCol[0]);it.jumpTramp=0;it.dashing=1;dashed=1;it.vx=it.dashSpd;it.vy=-it.dashSpd;it.diagDash=1;it.tutoDash=1
   else:it.vx=.4
   if it.onGround:
    S(.5)
    for i in range(21):F(0,14+i*10,320,10,(100,0,75));S(.05)
    S(.2)
    for i in range(15):D("You can do this"[i],85+i*10,100,"w",(100,0,75));S(.15)
    S(1.5)
    for i in range(9):D("Good luck"[i],115+i*10,130,"w",(100,0,75));S(.1)
    S(1)
    for i in range(10):D("Press [OK]"[i],110+i*10,190,"w",(100,0,75));S(.1)
    while 1-K(4):0
    home()
 def Ground(it):
  btmL=wrd.getMapTileAtPt(it.x+it.collPrec,it.y+it.sy);btmLtile=wrd.getTile(*btmL);btmR=wrd.getMapTileAtPt(it.x+it.sx-it.collPrec,it.y+it.sy);btmRtile=wrd.getTile(*btmR)
  if btmLtile in wrd.collTiles or btmRtile in wrd.collTiles:
   if wrd.tramp in(btmLtile,btmRtile):it.vy=-1.7;it.jumpTramp=1
   else:it.vy=min(0,it.vy)
   it.y=wrd.getMapTilePos(*btmR)[1]-it.sy;return 1
  elif btmLtile in wrd.deadTiles or btmRtile in wrd.deadTiles:it.playDead()
  return 0
 def onCeil(it):
  topL=wrd.getMapTileAtPt(it.x+it.collPrec,it.y);topLtile=wrd.getTile(*topL);topR=wrd.getMapTileAtPt(it.x+it.sx-it.collPrec,it.y);topRtile=wrd.getTile(*topR)
  if topLtile in wrd.collTiles or topRtile in wrd.collTiles:it.vy=max(0,it.vy);it.y=wrd.getMapTilePos(*topL)[1]+wrd.scale;return 1
  elif topLtile in wrd.deadTiles or topRtile in wrd.deadTiles:it.playDead()
  return 0
 def onRWall(it):
  topR=wrd.getMapTileAtPt(it.x+it.sx,it.y+it.collPrec);topRtile=wrd.getTile(*topR);btmR=wrd.getMapTileAtPt(it.x+it.sx,it.y+it.sy-it.collPrec);btmRtile=wrd.getTile(*btmR)
  if topRtile in wrd.collTiles or btmRtile in wrd.collTiles:it.vx=min(0,it.vx);it.x=wrd.getMapTilePos(*topR)[0]-it.sx;return 1
  if topRtile in wrd.deadTiles or topRtile in wrd.deadTiles:it.playDead()
  return 0
 def onLWall(it):
  topL=wrd.getMapTileAtPt(it.x,it.y+it.collPrec);topLtile=wrd.getTile(*topL);btmL=wrd.getMapTileAtPt(it.x,it.y+it.sy-it.collPrec);btmLtile=wrd.getTile(*btmL)
  if topLtile in wrd.collTiles or btmLtile in wrd.collTiles:it.vx=max(0,it.vx);it.x=wrd.getMapTilePos(*topL)[0]+wrd.scale;return 1
  if topLtile in wrd.deadTiles or btmLtile in wrd.deadTiles:it.playDead()
  return 0
 def coll(it):it.onGround=it.Ground();it.onRwall=it.onRWall();it.onLwall=it.onLWall();it.onCeil()
 def playDead(it):it.init();it.nbDeath+=1
 def updt(it):
  grav=.02;it.oldX,it.oldY=it.x,it.y;arrL=K(0);arrR=K(3);arrU=K(1);arrD=K(2);okPress=K(4);backPress=K(5);delPress=K(17)
  if wrd.chap!=0 and wrd.curLv==len(wrd.dat)-1:
   if it.lastLvJump:S(.2);it.vy=-1.3;it.lastLvJump=0
   it.vx=.7;okPress=1
   if it.onGround:
    for i in range(10):D("You did it"[i],110+i*10,100,"w",tileCol[0]);S(.14)
    S(.5)
    for i in range(80):D("You did it",110,100-i,"w",tileCol[0]);S(.02)
    a="You died "+str(it.nbDeath)+" time"+"s"*(it.nbDeath>1)
    for i in range(len(a)):D(a[i],160-(len(a)*10)//2+i*10,100,"w",tileCol[0]);S(.05)
    S(.5)
    for i in range(50):D(a,160-(len(a)*10)//2,100-i,"w",tileCol[0]);S(.02)
    S(.3);t=M()-wrd.t;a="It took you "+str(int(t//60))+" min and "+str(round(t)%60)+" sec"
    for i in range(len(a)):D(a[i],160-(len(a)*10)//2+i*10,100,"w",tileCol[0]);S(.05)
    S(.3)
    for i in range(20):D(a,160-(len(a)*10)//2,100-i,"w",tileCol[0]);S(.02)
    S(.3)
    for i in range(8):D("Congrats"[i],120+i*10,110,"w",tileCol[0]);S(.05)
    S(.3)
    for i in range(10):D("Press [OK]"[i],110+i*10,140,"w",tileCol[0]);S(.02)
    while K(4)^1:0
    home()
  if 1-it.dashing:
   arrSum=arrR-arrL
   if arrSum:
    if it.onGround:it.vx+=.04*arrSum
    else:it.vx+=.015*arrSum
   else:
    if it.onGround:it.vx/=1.5
    else:it.vx/=1.1
   it.vx=max(-.8,min(0.8,it.vx))
   if okPress:
    if it.onGround:it.vy=-1.3
    elif it.onLwall or it.onRwall:it.vy=-.8;it.vx=.8*(it.onLwall-it.onRwall)
   elif it.vy<0 and 1-it.jumpTramp:it.vy=max(-.5,it.vy)
   if it.jumpTramp and it.vy>0:it.jumpTramp=0
   if 1-it.climbing:it.vy+=grav;it.vy=min(8,it.vy,.8+50*((1-it.onLwall and 1-it.onRwall)or it.climbT>it.maxClimbT))
   if backPress and it.onLwall+it.onRwall:
    if it.climbT<it.maxClimbT:
     if 1-it.climbing:it.vy=0
     it.climbing=1
   else:it.climbing=0
   it.checkLvOne()
   if it.climbing:
    arrVsum=arrD-arrU
    if arrVsum==0:it.vy/=2
    else:it.vy+=it.climbSpd*arrVsum;it.vy=max(-it.maxClimbSpd,min(it.maxClimbSpd,it.vy))
    it.climbT+=1+abs(arrVsum)*3
    if it.climbT>it.maxClimbT:
     it.climbing=0
     if it.climbDelay==-1:it.climbDelay=0
   dashed=0
   if keyinput(17,delPress)and it.nbDash>0:
    it.jumpTramp=0;it.nbDash-=1;it.dashing=1;dashed=1;it.vx=it.dashSpd*(arrSum+(not arrD+arrU+arrL+arrR));it.vy=it.dashSpd*(arrD-arrU)
    if it.vx!=0 and it.vy!=0:it.diagDash=1
   if it.onGround:
    if not dashed:it.nbDash=it.maxNbDash
    it.climbT=0;it.col=it.oriCol;it.climbDelay=-1
   if it.climbDelay%20==0:
    if it.climbDelay!=-1:it.climbSpd+=1
    if it.col==it.oriCol:it.col="r"
    else:it.col=it.oriCol
  else:
   it.dashT+=1+.5*it.diagDash
   if it.dashT%(4-it.diagDash)==0:Ghost()
   if it.dashT>it.maxDashT:it.dashing=0;it.diagDash=0;it.dashT=0
  it.y+=it.vy;it.x+=it.vx
  if(it.x<0 and wrd.dat[wrd.curLv][-1]==0)or(it.y<0 and wrd.dat[wrd.curLv][-1]==1)or(it.x>320 and wrd.dat[wrd.curLv][-1]==2)or(it.y>222 and wrd.dat[wrd.curLv][-1]==3):wrd.curLv+=1;it.init()
  elif it.y<0 or it.y>222 or it.x<0 or it.x>320:it.nbDeath+=1;it.init()
  it.coll();it.drw(it.oldX,it.oldY,tileCol[0]);willMove=[(it.x>270)-(it.x<40),(it.y>180)-(it.y<40)]
  if willMove!=[0,0]:wrd.move(*willMove)
  it.drw(it.x,it.y,it.col)
wrd=World();pl=Player()
def home():
 z=loadLv(4);F(0,0,320,222,tileCol[0]);drwLogo();s=("[0] Prologue","[1] Chapter 1 - A side","[2] Chapter 1 - B side","[3] Chapter 1 - C side","[4] Chapter 1 - Custom")
 for i in range(4+(z!=0)):D(s[i],20,115+20*i,"w",tileCol[0])
 while 1:
  for i in range(5):
   if K([48,42,43,44,36][i])and(i!=4 or z):wrd.chap=i;wrd.curLv=0;wrd.dat=loadLv(i);wrd.t=M();pl.nbDeath=0;pl.init();return
home()
while 1:
 F(0,0,320,14,(248,180,48));pl.updt()
 for i in ghosts:i.drw()

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.