ruin_lite.py

Created by fime

Created on May 02, 2022

8.62 KB

Lite version for Epsilon users.

Controls : - arrows : move and directing the bullets - ok : jump (hold to jump higher) - toolbox : shot bullets - backspace : pause


from math import *
from kandinsky import fill_rect as drawRect,draw_string as drawTxt,get_pixel as getPxl
from ion import keydown as key
from time import monotonic as cTime,sleep
from random import randint as rInt,seed as rSeed
TARG_SPF=0.02 #50fps
BG_COL,PL_COL,PTF_COL,NMY_COL,NMY_COL2,BLACK=(75,40,40),(240,10,10),(200,100,100),(0,150,255),(0,50,200),(0,0,0)
NAME,AUTH,START_MSG,EDITOR_URL=" R U | N "," by F | M E ","Press [OK] to start","/python/fime/ruin_lvl_maker"
class Entity():
  def __init__(it,x,y,w,h,drawFonc):
    it.x,it.y,it.w,it.h=x,y,w,h
    it.draw=lambda:drawFonc(it)
  def hitBox(it,it2):
    if it.x<it2.x+it2.w and it2.x<it.x+it.w and it.y<it2.y+it2.h and it2.y<it.y+it.h:return 1
    return 0
class Platform(Entity):
  def __init__(it,x,y,w,h):super().__init__(x,y,w,h,drawPlatform)
  def hitBox(it,it2):
    if super().hitBox(it2) and it2.y+it2.h<it.y+it.h:return 1
    return 0

class Movable(Entity):
  def __init__(it,*arg):
    super().__init__(*arg)
    it.vx,it.vy,it.grounded=0,0,0
  def setVel(it,vx,vy):it.vx,it.vy=vx,vy
  def addVel(it,vx,vy):
    it.vx+=vx
    it.vy+=vy
  def applyPhysics(it):
    if it.grounded:
      it2=it.grounded
      it.vy=0
      if it.x>it2.x+it2.w or it2.x>it.x+it.w:
        it.grounded=0
    else :
      it.addVel(0,0.2)
      it.y+=min(it.vy,4)
    it.vx/=1.3
    it.x+=it.vx
    it.x=max(min(it.x,320-it.w),0)
  def onPlatform(it,plat):
    if plat.hitBox(it) and not it.grounded and it.vy>0:
      it.grounded=plat
      it.vy,it.y=0,plat.y-it.h
  def jump(it):it.vy,it.grounded=-4.3,0

class Enemy(Movable):
  def __init__(it,*arg):
    super().__init__(*list(arg)+[drawEnemy])
  def applyPhysics(it):
    if it.grounded:
      it2=it.grounded
      if it2.w>20:
        if it.x<it2.x+it.w:
          it.vx+=0.05
        elif it.x>it2.x+it2.w-it.w*2:
          it.vx-=0.05
        elif it.vx==0:
          it.vx=1
    super().applyPhysics()
    it.vx*=1.3
class Bullet(Movable):
  def __init__(it,it2,input_vy):
    super().__init__(it2.x+it2.w/2,it2.y+it2.h/2,3,3,drawBullet)
    it.setVel(copysign(3,it2.vx)+it2.vx,it2.vy+input_vy*2-1)
  def applyPhysics(it):
    it.addVel(0,0.2)
    it.x+=it.vx
    it.y+=it.vy

def fade(col1,col2,n):return tuple([i1*(1-n)+i2*n for i1,i2 in zip(col1,col2)])
def shadow(it):
  for i in range(1,6):
    drawRect(int(it.x-i*2),int(it.y+i*it.h),it.w-i,it.h,fade(BLACK,BG_COL,i/6))
def drawBaseEntity(it,col):
  drawRect(int(it.x+2),int(it.y),it.w-2,it.h,col)
  drawRect(int(it.x),int(it.y),2,it.h,BLACK)
def drawPlayer(it):
  drawBaseEntity(it,PL_COL)
  drawRect(int(it.x+it.w/2),int(it.y+7),2,3,BLACK)
  for i in (3,it.h-3):drawRect(int(it.x+i+it.vx/4),int(it.y+2),2,2,BLACK)
def drawEnemy(it):
  drawBaseEntity(it,NMY_COL)
  drawRect(int(it.x+2),int(it.y+it.h/2),it.w-2,it.h//2,NMY_COL2)
  for i in (3,it.h-3):drawRect(int(it.x+i),int(it.y+it.h/2-2),2,5,BLACK)
def hideEntity(it):
  drawRect(int(it.x),int(it.y),int(it.w),int(it.h),BG_COL)
def drawPlatform(it):
  drawBaseEntity(it,PTF_COL)
  shadow(it)
def drawDoor(it):
  drawRect(int(it.x),int(it.y),it.w,it.h,BLACK)
  for i in range(1,5):
    drawRect(int(it.x+1),int(it.y+it.h-i*2),int(it.w/2-i*2+3),1,fade(PTF_COL,BLACK,i/6))
def drawBullet(it):drawRect(int(it.x),int(it.y),it.w,it.h,PTF_COL)
def createDoor(l1):
  x,y,w,h=l1
  x,y,w,h=x+w//2-7.5,y-15,15,15
  return Entity(x,y,w,h,drawDoor)
def createPlayer(l1):
  x,y,w,h=l1
  y,w,h=y-10,10,10
  return Movable(x,y,w,h,drawPlayer)
def createEnemy(l1,id):
  x,y,w,h=l1
  x,y,w,h=x+10*id,y-10,10,10
  return Enemy(x,y,w,h)
def unpackPlatforms(n,type):
  string=levels(type)[n]
  Hex2Int=lambda n:int("0x"+n)
  level=[]
  for i in range(0,len(string),9):
    ptf_str=string[i:i+9]
    plat=[]
    for j in range(0,8,2):plat+=[Hex2Int(ptf_str[j:j+2])*5]
    plat.append(int(ptf_str[-1]))
    level.append(plat)
  return level
def loadLevel(lvl,type):
  file=unpackPlatforms(lvl,type)
  platforms,enemies=[],[]
  for i in file:
    platforms+=[Platform(*i[0:4])]
    if i[4]:
      enemies+=[createEnemy(i[0:4],j) for j in range(i[4])]
  player,door=createPlayer(file[0][0:4]),createDoor(file[-1][:4])
  return [player,platforms,enemies,door]
def shortTransition():
  for i in range(30):drawRect(0,0,320,222,fade(BG_COL,BLACK,sin(i/30)))
def releaseKey(x):
  while key(x):pass

class GameEngine():
  def __init__(it,lvl_type="original"):
    it.lvl,it.status,it.total_frame,it.lvl_type,it.lvl_nb=0,0,0,lvl_type,len(levels(lvl_type))
  def nextLevel(it):
    if it.status==2:
      game.playTransition(mode=1)
      it.lvl+=1
      game.playTransition()
    else:shortTransition()
  def displayEndMsg(it):
    t=game.total_frame*TARG_SPF
    msg=["You finished the ",
"{} original levels !".format(it.lvl_nb),
"","Virtual time: {} min {}s".format(t//60,round(t%60,2)),
"","Download the level maker at :",
"my.numworks.com",
EDITOR_URL]
    if it.lvl_type=="custom":msg=[msg[3]]
    for i,txt in enumerate(msg):
      drawTxt(txt,160-len(txt)*5,111-(len(msg)//2-i)*20,PTF_COL,BG_COL)
  def playTransition(it,h=222,mode=0):
    try:l=loadLevel(it.lvl,it.lvl_type)
    except:return
    entities,s_init,y=l[1]+[l[3]],20,int(h)
    if not mode:
      entities+=[l[0]]+l[2]
      for entity in entities:entity.y-=y
    del l
    while 1:
      if y<1:break
      if mode:s=(1-y/h)*s_init+5
      else:s=sqrt(y/h)*s_init
      y=round(y-s,1)
      sleep(TARG_SPF*2)
      drawRect(0,0,320,222,BG_COL)
      for entity in entities:
        entity.y+=s
        entity.draw()
  def playLevel(it):
    drawRect(0,0,320,222,BG_COL)
    player,platforms,enemies,door=loadLevel(it.lvl,it.lvl_type)
    frame_nb,shot_frame,bullets,it.status=0,0,[],0
    while it.status==0:
      t=cTime()
      frame_nb+=1
      player.addVel(key(3)-key(0),0.1*(1-key(4)))
      if (frame_nb+9)%10==0:door.draw()
      for b in bullets:
        hideEntity(b)
        b.applyPhysics()
        if b.y>222:bullets.remove(b)
        else:b.draw()
      for movable in enemies+[player]:
        hideEntity(movable)
        if movable!=player:
          if movable.hitBox(player):
            it.status=1
            break
          for b in bullets:
            if b.hitBox(movable):
              movable.addVel(b.vx/3,b.vy/3)
          if movable.y>222:
            enemies.remove(movable)
        movable.applyPhysics()
        for platform in platforms:
          movable.onPlatform(platform)
          if (frame_nb+9)%10==0 and movable==player:platform.draw()
        movable.draw()
      if frame_nb-shot_frame>10 and key(16):
        shot_frame=frame_nb
        bullets+=[Bullet(player,key(2)-key(1))]
      if player.grounded:
        if key(4):player.jump()
        if player.hitBox(door)==1:it.status=2
      if player.y>222:it.status=1
      while cTime()-t<TARG_SPF:pass
      if key(17):
        drawTxt(" P A U S E D ",95,101,BG_COL,PTF_COL)
        frame_nb+=10-frame_nb%10
        releaseKey(17)
        while not key(17):pass
        releaseKey(17)
        drawRect(95,101,130,20,BG_COL)
    it.total_frame+=frame_nb

def levels(lvl_type):
  if lvl_type!="custom":return ("011606010071632010391606010",
"011606010111606010231606010341606010",
"0216060101e1601010331606010",
"042306010161c060100e1410011290f06011350f06010",
"08280601026280a011342102010291b020100f1b0201003140a011190d0201026080a010",
"0624060101a28020102b220201031190a01118160a0110a0e020101b070201030070a010",
"0527060101927010102a27010103420060112819060110c19060110511010100b09010101a060a013330606010",
"0428060100c2001010041c010100c16010102f1e01010391801010301101010260b0601012070a010",
"0128060101526010103026010103921010102d1a010101a1501010230e01010310d0a010",
"052506010051e06011051606011050f06011050806011301806010",
"0628060101623060110c1e020101719020102b19020103b12020102b0c02010170c02010060906010",
"0228060101d28060103122060111d1d020100e1b020100515020100e0f02010240d06011320d06010",
"0105040100c05350100823010101a1f060111e1801010341206011280e06010280e06010",
"362706010292006011351a020102f1302010042006011041706011080f010100c0706010",
"032806010242806011342106011251906011081901010021201010090c01010150706011270706010",
"042806010192306011251e06010311a060112514060100316060110a0e01010140806010",
"3726060101f2601010042601010081e010101019010102519010102f1006011220b06010",
"1a28060102a2306010331b01010251701010141706011051201010100a010101c0606010",
"0327060100c20010101619010102119030112d1903011351306010260a060111a0a01010050a06010",
"0220060101d1b020113117020111c0f06010",
"2f28060101428040110422020100e1b04010271a04011321402010270e040110e0e04011040806010")
  else:return []#insert your lvl here

game=GameEngine(lvl_type="")#"custom" for custom lvl
game.playTransition()
while game.lvl<game.lvl_nb:
  game.playLevel()
  game.nextLevel()
game.displayEndMsg()

# Commands:
# arrows = move
# toolbox/paste = fire
# backspace/clear = pause

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 <a href="https://www.numworks.com/legal/cookies-policy/">cookies policy</a>.