doodle_man.py

Created by cent20

Created on April 23, 2021

8.73 KB


"""
Doodle Man !
A doodle jump clone (eco +).
Written by Fime
08/01/2021 - V1.0
https://workshop.numworks.com/python/fime/doodle_man
"""
from random import randint
from ion import keydown as kDwn
from time import monotonic as mntnc,sleep
from kandinsky import fill_rect as rect, draw_string as text

SCREEN_W=320
SCREEN_H=222

GAME_W=200
SCORE_W=100
GAME_H=200

OFFSET_X=(SCREEN_W-SCORE_W-GAME_W)//2
OFFSET_Y=(SCREEN_H-GAME_H)//2

MID_SCREEN=OFFSET_Y+10

KEYS={"L":0,"R":3,"bk":17}

TYPES=["simple","fake","moving","trampo","fantom"]

COLOR={"ddl":(255,50,50),
"eyes":(255,255,255),
"bg":(50,50,50),
"bg2":(70,70,70),
"font1":(200,200,200),
"font2":(255,255,255),
"simple":(255,200,0),
"fake":(70,70,100),
"moving":(50,200,0),
"trampo":(0,150,0),
"fantom":(50,50,255)}

TARG_FPS=30
TARG_FD=1/TARG_FPS#targetted frame during

def s(x):
  """return 's' since 'x'"""
  return mntnc()-x

def drawPauseText():
  txt="GAME PAUSED"
  x=GAME_W//2-len(txt)*5+OFFSET_X
  y=GAME_H//2-10+OFFSET_Y
  text(txt,x,y,COLOR["font2"],COLOR["bg2"])


def drawDll(x,y,s,c):
  rect(int(x),int(y),int(s),int(s),c)
  
  if c!=COLOR["bg"]:
    s_eye=s//4
    x_eye=int(x)+s//2+int(ddl["spd_x"]*ddl["size"]/ddl_init_size)
    c_eyes=COLOR["eyes"]
    
    rect(x_eye-s_eye-1,int(y)+s//2-s_eye//2,int(s_eye),int(s_eye),c_eyes)
    rect(x_eye+1,int(y)+s//2-s_eye//2,int(s_eye),int(s_eye),c_eyes)
  
  
def drawPlatform(x,y,hs,vs,c):
  
  if y>OFFSET_Y+GAME_H-vs:
    vs-=(y-(OFFSET_Y+GAME_H-vs))
  
  if y<=limits["y"][1]:
    rect(int(x),int(y),int(hs),int(vs),c)

def drawPlatforms(mode=None):
  
  x_ddl=ddl_prvs[0]
  y_ddl=ddl_prvs[1]
  s_ddl=ddl["size"]
  
  for p in platforms:
    x=p[0]
    y=p[1]
    hs=p[2]
    vs=p[3]
    t=p[4]
    c=p[5]
    lx=p[6]
    ly=p[7]
        
    if t=="moving":
      drawPlatform(lx,ly,hs,vs,COLOR["bg"])
      for p2 in platforms:
        if hitBox(p2,[lx,ly,hs,vs]) and not p==p2:
          drawPlatform(p2[0],p2[1],p2[2],p2[3],p2[5])
        
    if mode=="all" or t=="moving":
      drawPlatform(x,y,hs,vs,c)
      p[6]=x
      p[7]=y
        
    if hitBox(p,[x_ddl,y_ddl,s_ddl,s_ddl]):
      drawPlatform(x,y,hs,vs,c)
      p[6]=x
      p[7]=y      

def addPlatform(y):
 
  global cf
  
  try: cf==0
  except:cf=0#consecutive fake
  
  while True:
    
    np=createPlatform(y)
    if np!=None:
      if np[4]=="fake":
        if cf==1:
          np[4]="simple"
          np[5]=COLOR["simple"]
          cf=0
        else:cf+=1
      else:
        cf=0
      break
  platforms.append(np)
      
def createPlatform(y):
   
    hs=int(platform_hor_size)-score//2000 #horizontal size
    vs=hs//6 #vertical size
    
    limits_x=[OFFSET_X+5,GAME_W+OFFSET_X-hs-5]
    
    x=randint(limits_x[0],limits_x[1])
  
    t=TYPES[randint(0,len(TYPES)-1)]
    
    rand=randint(0,100)
    if rand<=percentages[t]:
      p=[x,y,hs,vs,t,COLOR[t],x,y,0.5]
      return p
      

def hitBox(p1,p2):
  x1=p1[0]
  y1=p1[1]
  hs1=p1[2]
  vs1=p1[3]
  
  x2=p2[0]
  y2=p2[1]
  hs2=p2[2]
  vs2=p2[3]
  
  if x1 <= x2+hs2 and x1+hs1 >= x2 and y1 <= y2+vs2 and y1+vs1 >= y2:
    return True
  else:
    return False

def game_engine():
  
  global ddl,ddl_prvs,ddl_init_size,limits,platforms,percentages,score,best_score,platform_hor_size,platform_vert_size
  
  ddl_init_size=20
  
  ddl={
  "x":OFFSET_X+GAME_W//2-ddl_init_size//2,
  "y":MID_SCREEN,
  "spd_x":0.0,
  "spd_y":0,
  "size":ddl_init_size,
  "color":COLOR["ddl"]}
  ddl_prvs=[0,0,0,0,(0,0,0)]
  
  print(">init game engine...")
  
  rect(0,0,SCREEN_W,SCREEN_H,COLOR["bg2"])
  
  speed=0.07
  jump_speed=2.4
  
  platform_hor_size=30
  
  score=0
  best_score=readBestScore()

  #init map
  drawScorePannel()
  rect(OFFSET_X,OFFSET_Y,GAME_W,GAME_H,COLOR["bg"])
  
  #limit : x[min][max], y[min][max]
  limits={
  "x":[OFFSET_X,OFFSET_X+GAME_W-ddl["size"]+1],
  "y":[OFFSET_Y,OFFSET_Y+GAME_H]}
    
  #init platforms
  percentages={"simple":50,"fake":40,"moving":40,"trampo":5,"fantom":5}
  
  platforms=[[OFFSET_X,
  limits["y"][1]-5,GAME_W,5,"simple",COLOR["simple"],OFFSET_X,limits["y"][1],0]]
  
  for y in range(OFFSET_Y+60,GAME_H+OFFSET_Y-5,60):
    addPlatform(y)
    
  drawPlatforms("all")
  draw_all=0
  
  draw_timer=mntnc()-TARG_FD
  fps=TARG_FPS
  lpf=1 #lapse_per_frame
  targ_tics=240
  targ_lpf=targ_tics/fps
  spd_corrector=1
  
  print(">launch the game...")
  
  while True:
    if s(draw_timer)>=TARG_FD:
      
      fps=int(1/s(draw_timer))
      targ_lpf=targ_tics//fps
      spd_corrector=lpf/targ_lpf
      lpf=0
      
      if draw_all:
        rect(OFFSET_X,OFFSET_Y,GAME_W,GAME_H,COLOR["bg"])
        drawPlatforms("all")
        draw_all=0
        
      else:
        drawDll(ddl_prvs[0],ddl_prvs[1],ddl_prvs[2],COLOR["bg"])
        drawPlatforms()
      
      if score>=best_score:
        best_score = score
      
      actualizeScore()
      
      drawDll(ddl["x"],ddl["y"],ddl["size"],COLOR["ddl"])
      ddl_prvs=[ddl["x"],ddl["y"],ddl["size"]]
      if kDwn(KEYS["bk"]):
        drawPauseText()
        while kDwn(KEYS["bk"]):
          pass
        while not kDwn(KEYS["bk"]):
          pass
        while kDwn(KEYS["bk"]):
          pass
        draw_all=1
      draw_timer=mntnc()
      
    lpf+=1
    ddl["x"]+=ddl["spd_x"]
    if ddl["y"]<=MID_SCREEN and ddl["spd_y"]<0:
      
      score-=int(ddl["spd_y"]*spd_corrector)//10
      
      for p in platforms:
        if p[1]<=limits["y"][1]-5:
          p[1]-=ddl["spd_y"]
          draw_all=1
        
        else:  
          platforms.remove(p)
          addPlatform(OFFSET_Y)

    else:
      ddl["y"]+=ddl["spd_y"]
    
    if ddl["x"]<limits["x"][0]:
      ddl["x"]=limits["x"][0]
      ddl["spd_x"]=0
    
    if ddl["x"]>limits["x"][1]:
      ddl["x"]=limits["x"][1]
      ddl["spd_x"]=0
    
    if ddl["y"]+ddl["size"]<=limits["y"][0]:
      ddl["y"]-=ddl["spd_y"]
      ddl["spd_y"]=0
    
    if ddl["y"]<=limits["y"][0]:
      ddl["y"]=limits["y"][0]
    
    
    if ddl["y"]+ddl["size"]>=limits["y"][1]:
      ddl["y"]=limits["y"][1]-ddl["size"]
      
      drawDll(ddl_prvs[0],ddl_prvs[1],ddl_prvs[2],COLOR["bg"])
      drawDll(ddl["x"],ddl["y"],ddl["size"],ddl["color"])
      
      print(">game end: dead...")
      print(">fps : {}".format(fps))
      print(">spd_corrector : {}, lpf : {}/{}".format(spd_corrector,lpf,targ_lpf))
      saveScore(best_score)
      deathAnimation()
      break
      
    if kDwn(KEYS["R"]):
      ddl["spd_x"]+=speed*spd_corrector
    
    if kDwn(KEYS["L"]):
      ddl["spd_x"]-=speed*spd_corrector
        
    for p in platforms:
      if hitBox(p,[ddl["x"],ddl["y"]+ddl["size"]-5,ddl["size"],5]) and ddl["spd_y"]>=0:
        
        if p[4]=="trampo":
          ddl["spd_y"]=-jump_speed*2*spd_corrector
        
        elif p[4]=="fantom":
          p[4]="fake"
          p[5]=COLOR["fake"]
          drawPlatform(p[0],p[1],p[2],p[3],p[5])
          ddl["spd_y"]=-jump_speed*spd_corrector
          
        elif p[4]=="fake":
          pass
        
        else:
          ddl["spd_y"]=-jump_speed*spd_corrector
          
        percentages[p[4]]*=0.01
        
      if p[4]=="moving":
          if p[0]<=OFFSET_X+1 or p[0]>=OFFSET_X+GAME_W-p[2]-1:
            p[8]=-p[8]
          p[0]+=p[8]*spd_corrector
          
    
    ddl["spd_x"]/= 1.02
    ddl["spd_y"]+=0.02 * spd_corrector
    
    ddl["size"]=ddl_init_size-score//2000

    limits={
    "x":[OFFSET_X,OFFSET_X+GAME_W-ddl["size"]],
    "y":[OFFSET_Y,OFFSET_Y+GAME_H]}
    
    
def transition():
  for c in [COLOR["font1"],COLOR["bg"]]:
    for y in range(OFFSET_Y,OFFSET_Y+GAME_H,10):
      sleep(0.016)
      rect(OFFSET_X,y,GAME_W,10,c)
  

def actualizeScore():
  
  x=OFFSET_X+GAME_W+SCORE_W//2
  y=OFFSET_Y+score_off
  
  text(str(score),x-len(str(score))*5,y+40,COLOR["font2"],COLOR["bg"])
  
  c=COLOR["simple"] if score==best_score else COLOR["font2"]
  text(str(best_score),x-len(str(best_score))*5,y+100,c,COLOR["bg"])
  
  
def drawScorePannel(): 
  global score_off
  
  x=OFFSET_X+GAME_W
  y=OFFSET_Y
  
  score_off=5
  
  rect(x+score_off,y,SCORE_W-2*score_off,GAME_H,COLOR["font1"])
  rect(x+2*score_off,y+score_off,SCORE_W-4*score_off,GAME_H-2*score_off,COLOR["bg"])
  
  x=OFFSET_X+GAME_W+SCORE_W//2
  y=OFFSET_Y+score_off
  
  text("SCORE",x-len("SCORE")*5,y+10,COLOR["font1"],COLOR["bg"])
  text("BEST",x-len("BEST")*5,y+70,COLOR["font1"],COLOR["bg"])
  
  s=ddl["size"]
  drawDll(x-s//2,y+140,s,COLOR["ddl"])


def deathAnimation():
  transition()
  game_engine()

def readBestScore():
  try:
    file=open("ddl_man.sav","r")
    best = file.readline()
    file.close()
    print(">score loaded !")
    return int(best)
  except:
    print(">failed to read the score...")
    return 0
  
def saveScore(score):
  try :
    file=open("ddl_man.sav","w")
    file.truncate(0)
    file.write(str(score))
    file.close()
    print(">score saved !")
  except:
    print(">failed to save the score...")
    
game_engine()

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.