rpg.py

Created by loic-azavant

Created on March 24, 2023

18.8 KB

fonctionne sur upsilon, un ptit rpg. Necessite les script dialog_box.py et ion_plus.py


from kandinsky import *
from ion import *
from random import *
from ion_plus import *
from time import *
from dialog_box import *

newDelay(0.1)

pixelSize = 3
tileSize = pixelSize*8
offset = (16,15)

def drwTile(nbr,x=0,y=0):
  for i in range(len(bin(nbr))-2):
    if nbr >> i & 1:
      fill_rect(x+(i%8)*pixelSize,y+(i//8)*pixelSize,pixelSize,pixelSize,(0,0,0))


class Terrain:
  def __init__(self):
    self.world = 1
    self.x = 1
    self.y = 2
    self.sizeX = 12
    self.sizeY = 8
    self.bigSizeX = 4
    self.bigSizeY = 4
    self.terrain = ((('0202W0202020/1/1920/1/1/2020)1/)()((020/)()()())/1/)()())202020()()(20202020(()(12021/1/()(201/1', '201/;<<<<<<<1/(**;<<<<<<()()-**-;<<<)()((*-**-*-0)()((((****20)(()((-()(0/)((()(()((/(20)()(((()','<<<<<<<<<<<=<<<9<<<<<<=*<<=**;<<=**6*;<<><<=**64*-*****-*643(****-**643)(((-(64643))(((((56464))',')646464646466464356435644643)(53)(56643)())()))553)(6464()64(())5643)646)))(643))535(64)564())64'),
                     ('2020()(1/202020/)()()1/1/1/())()((((020)((:::(((20/(((::::((1/))((7:::((20(()((797((1/((((*****(', '0(1/(((()(((/(()(88(((()()((88888()(((((88888)(2(()(77797(20**((*****(1/(****()*(()(()*(((((()((','(()((.5353())(()((.64().)(((().53)).020(((.64()620/))(.564(51/)((((.564(()(((()((520(((()(((((1/',')64)643))(53643)564)()).53)()56464).4)))645353).3()643)())(.64643)(64646564364)53564)53643)()646'),
                     ('20())((***((0/))((***(()/())(****()(.(()****())(.()(**(()());=((*(()())(;<<<><<<<<<<(;<<><<<<<<<', '((*(()(()((()(**(8888()((20*(8888((((1/(*7977(()((((*****)((()((((**)(()<<<=((((((((<<<<<<<<<<<<','(((()((()(20(()20(()()1/)(2020(((((2((1/120()((1)((((1/((()((()((((()(()**(*((((()((<<<<<<=()()(','2064643)(564120643()))5601/53()()(*5/()(())(**+-((()(()**++-)()()((**++,(()(((***++,()((()***++,'),
                     (');<<><<<<<<<);<<><<<<<<<).+++++++;<<.+++++++++++.+++++++++++.+++++++++++,,,,,,,,,+++,,,,,,,,,,,,', '<<<<<<<<<<<<<<<<9<<<<<<<<<=*****************************+++++++++++++++++++++++++,,,,,,,,,,,,,,,','<<<<<<=(()()<<<<<<<=)(((*****;<<<<><******;<<<><+++++*******++++++++++++,,,+++++++++,,,,,,,,,,,,',')((((((**++,();=((***++,<<<=(****++,<<=****++++,*****++++++,+++++++++,,,+++++++,,,,,,,,,,,,,,,,,')),
                    (('02020202020220/1/1/1/1201/()()()()1/0)())()()(20/()(((()(2020))()()(202020()(2020202020U20/1/1/1', 'TTTTTTTTTTTTT(((TT(((((TT(-(((TT(T((T(-(-((((TTTT(T((TTTTT(TT((TTT((((((TT((((((TTTTTTTTTTTTTTTT','TTTTTTTTTTTTTTT(((((((((((((TTTTTTTTTTTT((((T((TT((T(TTTTT(T(((T((((TT((T((TTTT((((TTTTTTTTUTTTT','TTTTTTTTTTTT((((((-((((TTTTTT(TTTT(TT(((T((((T(TT(-(TTTT(T(T((TTT((((T(TT(((((TT(((TTTTTTTTTTTTT'),
                     ('VVVBFFFFCVVVVVVHRRAAIVVVVVVHSSAAKFFCVVVHAAAA@AAIVVVHAA@NOAAIVVVHAAAQPAAIVVVHAAAAAAAIVVVDGGLUMGGE', 'BFFFFFFFFFFCHAAAAAAAAAAIHRRAAAAAAAAIHSSAAAAA@@AIHAAAAAA@NOAIHAAAAAAAQP@IHAAAAAAAA@AIDGGGGGLUMGGE','((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((','(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((('),
                     ('((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((', 'VVVVVVVVVVVVVVVVVVVVVVVVVBFFFFFFFFCVVHAAAA@NOAIVVHAAAAAQPAIVVHRAAAA@AAIVVHSAAAAAAAIVVDGGGGLUMGEV','((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((','(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((('),
                     ('<<<<<<<<<<<<=(((;=(((((;=(-(((;=(;((=(-(-((((;<<=(=((;<<<=(;=((;<=((((((<=(((((;<<<<<<<<<<<<<<<<', '<<<<<<<<<<<<<<=(((((((((((((;<<<<<<<<<<=((((;((;=((;(;<<<=(;(((=((((;=((=((;<<=((((;<<<<<<<U<<<<','<<<<<<<<<<<<((((((-((((;<<<<=(;<<=(;=(((=((((;(;=(-(<<<=(<(;((;<<((((=(;=(((((;=(((;<<<<<<<<<<<<','((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((')))
   
    self.colliderTile = ",-./0123456789:;<=?BCDEFGHIJKLMNOPQRSTUVW"
    self.tile = (0,289393798101340160,70368744439808,1156303053698117680,3589368839774666748,2031800169560882688,10582011061376019456,1087634837330782433,15330750740042101263,17296268948190398753,1226563808452037872,1804834316039274688,9476014093006549007,617258116189192963,13943436062555770096,18411165791475844095,16707129605460043263,18410291408486040063,16717262860148778495,17761497623194600062,17833273755174732671,9175103195607483263,9348771052416500157,9144420220433809980,10199492280597504,567348004134912,13360466067332596735,10778969444221763839,18375537474188962217,18428906282520385181,18384537042982797567,18374687575173448959,12243503676868110761,10778687952030898069,18420566527204950271,18394386523979055615,18410857112226734847,18374970149745542655,4765408903566130176,5784948781351452416,6824948943380560,7032553983346306,13367246385280024958,9115848052463207361,0,9312457211248541439,18446744073709551615,3910285604860217599)

    self.visibleEntities = []


  def drwMap(self):
    fill_rect(offset[0],offset[1],self.sizeX*tileSize,self.sizeY*tileSize,(255,)*3)
    for i in range(self.sizeX):
      for j in range(self.sizeY):
        drwTile(self.tile[ord(self.terrain[self.world][self.y][self.x][j*self.sizeX+i])-40],i*tileSize+offset[0],j*tileSize+offset[1])
    self.sortEntities()
  
  def sortEntities(self):
    self.visibleEntities.clear()
    for entity in entities:
      if entity.mapTile == (self.world,self.x,self.y):
        self.visibleEntities.append(entity)
    self.drwEntities()
  
  def drwEntities(self):
    for entity in self.visibleEntities:
      entity.drw()
  
  
overworld = Terrain()

collectables = []
specialCollectables = []

class Collectable:
  def __init__(self,sprite,text,special=False,**kwargs):
    if special:
      specialCollectables.append(self)
    else:
      collectables.append(self)
    self.sprite = sprite
    self.nbr = 0
    self.text = text
    self.discovered = False
  
  def drw(self,x,y):
    drwTile(self.sprite,x,y)

Collectable(433782063166437488,"Chicken leg")
Collectable(2030665482720643088,"Apple")
Collectable(4004205508976640,"Iron Ingot",True)
Collectable(2819261376544896,"Legendary Sword",True)
Collectable(7949736413750134,"Chestplate",True)
Collectable(2828073702547456,"Sword",True)

class Player:
  def __init__(self):
    self.x = 3
    self.y = 5
    self.sprite = 2647480505366099006
    self.sprite2 = 2647480504902233212
    self.orientation = 1
    self.orientationX = 0
  
  def drw(self):
    fill_rect(offset[0]+self.x*tileSize,offset[1]+self.y*tileSize,tileSize,tileSize,(255,)*3)
    if self.orientationX == 1:
      drwTile(self.sprite2,self.x*tileSize+offset[0],self.y*tileSize+offset[1])
    else:
      drwTile(self.sprite,self.x*tileSize+offset[0],self.y*tileSize+offset[1])

  def checkXMovement(self):
    moveH = keydowntimed(3)-keydowntimed(0)
    if moveH!=0:
      self.orientation = int(1.5*moveH+1.5)
      if 0>moveH+self.x or self.x+moveH>=overworld.sizeX:
        overworld.x += moveH
        overworld.drwMap()
        self.x = (overworld.sizeX-1)*(moveH==-1)
        self.orientationX = int(0.5*moveH+0.5)
        self.drw()
      elif not overworld.terrain[overworld.world][overworld.y][overworld.x][self.x+self.y*overworld.sizeX+moveH] in overworld.colliderTile:
        for entity in overworld.visibleEntities:
          if entity.coord == self.x+moveH+self.y*overworld.sizeX:
            fill_rect(self.x*tileSize+offset[0],self.y*tileSize+offset[1],tileSize,tileSize,(255,)*3)
            self.orientationX = int(0.5*moveH+0.5)
            self.drw()
            return
        fill_rect(self.x*tileSize+offset[0],self.y*tileSize+offset[1],tileSize,tileSize,(255,)*3)
        drwTile(overworld.tile[ord(overworld.terrain[overworld.world][overworld.y][overworld.x][self.y*overworld.sizeX+self.x])-40],self.x*tileSize+offset[0],self.y*tileSize+offset[1])
        self.x += moveH
        self.orientationX = int(0.5*moveH+0.5)
        self.drw()
      else:
        fill_rect(self.x*tileSize+offset[0],self.y*tileSize+offset[1],tileSize,tileSize,(255,)*3)
        self.orientationX = int(0.5*moveH+0.5)
        self.drw()

  def checkYMovement(self):
    moveV = keydowntimed(2)-keydowntimed(1)
    if moveV!=0:
      self.orientation = int(0.5*moveV+1.5)
      if 0>self.y+moveV or self.y+moveV>=overworld.sizeY:
        overworld.y += moveV
        overworld.drwMap()
        self.y = (overworld.sizeY-1)*(moveV==-1)
        self.drw()
      elif not overworld.terrain[overworld.world][overworld.y][overworld.x][self.x+(self.y+moveV)*overworld.sizeX] in overworld.colliderTile:
        for entity in overworld.visibleEntities:
          if entity.coord == self.x+(self.y+moveV)*overworld.sizeX:
            return
        fill_rect(self.x*tileSize+offset[0],self.y*tileSize+offset[1],tileSize,tileSize,(255,)*3)
        drwTile(overworld.tile[ord(overworld.terrain[overworld.world][overworld.y][overworld.x][self.y*overworld.sizeX+self.x])-40],self.x*tileSize+offset[0],self.y*tileSize+offset[1])
        self.y += moveV
        self.drw()

  def applyAction(self):
    if keyinput(4):
      if overworld.terrain[overworld.world][overworld.y][overworld.x][(self.y-1)*overworld.sizeX+self.x] == "9":
        overworld.world = 1
        door = overworld.terrain[overworld.world][overworld.y][overworld.x].index('U')
        self.x = door%overworld.sizeX
        self.y = (door//overworld.sizeX)-1
        overworld.drwMap()
        self.drw()
        return
      elif overworld.world==1 and overworld.terrain[overworld.world][overworld.y][overworld.x][(self.y+1)*overworld.sizeX+self.x] == "U":
        overworld.world = 0
        door = overworld.terrain[overworld.world][overworld.y][overworld.x].index("9")
        self.x = door%overworld.sizeX
        self.y = (door//overworld.sizeX)+1
        overworld.drwMap()
        self.drw()
        return
        
      for entity in overworld.visibleEntities:
        if entity.coord == self.x+1*(self.orientation==3)-1*(self.orientation==0)+(self.y+1*(self.orientation==2)-1*(self.orientation==1))*overworld.sizeX:
          entity.interact(self.y<4)
          return

      fill_rect(offset[0]+tileSize,offset[1]+tileSize,(overworld.sizeX-2)*tileSize,(overworld.sizeY-2)*tileSize,(0,)*3)
      fill_rect(offset[0]+tileSize+5,offset[1]+tileSize+5,(overworld.sizeX-2)*tileSize-10,(overworld.sizeY-2)*tileSize-10,(255,)*3)      
      y=0
      for i in range(len(collectables)):
        if not collectables[i].discovered:
          continue
        drwTile(collectables[i].sprite,offset[0]+tileSize+10,offset[1]+tileSize+10+y*30)
        draw_string("x"+str(collectables[i].nbr),offset[0]+tileSize+40,offset[1]+tileSize+10+y*30)
        y+=1
      y=0
      for i in range(len(specialCollectables)):
        if not specialCollectables[i].discovered:
          continue
        drwTile(specialCollectables[i].sprite,offset[0]+tileSize+90,offset[1]+tileSize+10+y*30)
        draw_string("x"+str(specialCollectables[i].nbr),offset[0]+tileSize+120,offset[1]+tileSize+10+y*30)
        y+=1
      while not keyinput(4):
        pass
      fill_rect(offset[0]+tileSize,offset[1]+tileSize,(overworld.sizeX-2)*tileSize,(overworld.sizeY-2)*tileSize,(255,)*3)
      for i in range(1,overworld.sizeX-1):
        for j in range(1,overworld.sizeY-1):
          drwTile(overworld.tile[ord(overworld.terrain[overworld.world][overworld.y][overworld.x][i+j*overworld.sizeX])-40],offset[0]+i*tileSize,offset[1]+j*tileSize)
      self.drw()
      overworld.drwEntities()

  def updt(self):
    self.checkXMovement()
    self.checkYMovement()
    self.applyAction()


entities = []
class Entity:
  def __init__(self,world,bigx,bigy,x,y):
    entities.append(self)
    self.mapTile = (world,bigx,bigy)
    self.coord = x+y*overworld.sizeX


class NPC(Entity):
  def __init__(self,sprite,world,bigx,bigy,x,y,**kwargs):
    super().__init__(world,bigx,bigy,x,y)
    self.sprite = sprite
    self.dialogs = (("",),("",))
    self.side = ((self.coord//overworld.sizeX)<5)
    self.hasTalk = False
    self.thereIsAQuest = False
    self.quest = lambda: 0
    self.questDone = False
    for key,value in kwargs.items():
      setattr(self,key,value)
  
  def drw(self):
    fill_rect(offset[0]+(self.coord%overworld.sizeX)*tileSize,offset[1]+(self.coord//overworld.sizeX)*tileSize,tileSize,tileSize,(255,)*3)
    drwTile(self.sprite,offset[0]+(self.coord%overworld.sizeX)*tileSize,offset[1]+(self.coord//overworld.sizeX)*tileSize)
  
  def interact(self,*arg,**kwargs):
    if self.thereIsAQuest:
      questDialogIndex = self.quest(self)
      dialog = self.dialogs[questDialogIndex]
    else:
      dialog = self.dialogs[0]
    dialogBox.init(self.side)
    for phrase in dialog:
      dialogBox.drw(phrase,self.side)
    dialogBox.hide(self.side)

def quest1(npc):
  if not npc.hasTalk:
    npc.hasTalk = True
    return 0
  if npc.questDone:
    return 1
  if collectables[0].nbr>=5:
    collectables[0].nbr-=5
    npc.questDone = True
    return 1
  return 0

NPC(2465226564412522012,1,1,1,3,2,thereIsAQuest=True,quest=quest1,dialogs=(("Hello","If you give me 5 Chicken legs, I will tell you a secret"),("Thank you, you want my secret now don't you","There are two caves on this island, one to the south and one to the north. Both are identical")))

def quest2(npc):
  if not npc.hasTalk:
    npc.hasTalk = True
    return 0
  if npc.questDone:
    return 2
  if specialCollectables[3].nbr>=1:
    specialCollectables[3].nbr-=1
    dialogBox.init(npc.side)
    for i in npc.dialogs[1]:
      dialogBox.drw(i,npc.side)
    dialogBox.hide(npc.side)
    npc.questDone = True
    fill_rect(offset[0]+(npc.coord%overworld.sizeX)*tileSize,offset[1]+(npc.coord//overworld.sizeX)*tileSize,tileSize,tileSize,(255,)*3)
    npc.mapTile = (1,1,2)
    npc.coord = 6+4*overworld.sizeX
    overworld.visibleEntities.remove(npc)
    return 3
  return 0

NPC(2611437328763469340,1,2,0,11,5,thereIsAQuest=True,quest=quest2,dialogs=(("I lost my sword in this cave, but without one, I cannot do anything","Please, help me"),("You are giving me a new sword ! THANK YOU ! Now I will be able to leave",),("Oh hello!","You are the one who helped me in the cave","If you find my old sword, you can keep it"),tuple()))

def quest3(npc):
  if not npc.hasTalk:
    npc.hasTalk = True
    return 0
  if npc.questDone:
    return 2
  if specialCollectables[0].nbr >= 1:
    specialCollectables[0].nbr -= 1
    specialCollectables[3].nbr += 1
    specialCollectables[3].discovered = True
    npc.questDone = True
    return 1
  return 0

NPC(3908805469474268190,1,0,1,6,3,thereIsAQuest=True,dialogs=(("Hello, I am a blacksmith","If you have 1 iron ingot, I can turn it into a sword"),("So you want a sword...","Give me this ingot","Now wait a second","And boom, here is your sword"),("I hope my sword is useful",)),quest=quest3)

def quest4(npc):
  if not npc.hasTalk:
    npc.hasTalk = True
    return 0
  if npc.questDone:
    return 2
  if specialCollectables[1].nbr == 1:
    fill_rect(offset[0]+(npc.coord%overworld.sizeX)*tileSize,offset[1]+(npc.coord//overworld.sizeX)*tileSize,tileSize,tileSize,(255,)*3)
    npc.coord += overworld.sizeX+1
    npc.drw()
    npc.questDone = True
    return 1
  return 0

NPC(2647279269050211384,0,0,0,4,2,thereIsAQuest=True,quest=quest4,dialogs=(("I'm sorry, only the legendary warrior will pass, a monster is here",),("I'm sorry, only the legenda... Wait... You have the legendary sword, this means you are the legendary warrior","You can go in this room, and defeat the monster, please, defeat the monster"),("You can go in this room, please, defeat the monster",)))

def quest5(npc):
  if specialCollectables[2].nbr==0:
    dialogBox.init(1)
    dialogBox.drw("HA HA",1)
    dialogBox.drw("You thought you could kill me!",1)
    dialogBox.drw("You are so naive! HA HA HA",1)
    dialogBox.hide(1)
    for i in range(10):
      fill_rect(0,0,320,222,(255,)*3)
      fill_rect(0,0,320,222,(0,)*3)
    draw_string("You Died",120,111,(255,)*3,(0,)*3)
    while not keyinput(4): pass
    player.x = 4
    player.y = 3
    overworld.world = 0
    overworld.drwMap()
    player.drw()
    return 0
  else:
    dialogBox.init(1)
    dialogBox.drw("AAAAAARGH",1)
    dialogBox.drw("HOW DID YOU KILL ME ?!",1)
    dialogBox.drw("I AM INVINCIBLE",1)
    dialogBox.drw("AAAAAARGH",1)
    fill_rect(0,0,320,222,(0,)*3)
    draw_string("You defeated the \nmonster\n\nYou went back home\n\nYou went to bed\n\nToday has been a good day\n\nThanks for playing",10,10,(255,)*3,(0,)*3)
    while 1: pass

NPC(12231140784100616220,1,0,0,5,3,thereIsAQuest=True,quest=quest5,dialogs=(("You might need something to protect you",),("AAARGH",)))

NPC(2611169719451679744,0,2,0,10,6,dialogs=(("Hey big bro!","This forest is so big!","Bye"),))

jarSprite = 9144420220433809980
class Jar(Entity):
  def __init__(self,world,bigx,bigy,x,y,**kwargs):
    super().__init__(world,bigx,bigy,x,y)
    self.item = lambda: collectables[randint(0,len(collectables)-1)]
    self.nbr = lambda: choice([1,1,1,1,1,2])
    self.respawn = True
    for key,value in kwargs.items():
      setattr(self,key,value)

  def drw(self):
    fill_rect(offset[0]+(self.coord%overworld.sizeX)*tileSize,offset[1]+(self.coord//overworld.sizeX)*tileSize,tileSize,tileSize,(255,)*3)
    drwTile(jarSprite,offset[0]+(self.coord%overworld.sizeX)*tileSize,offset[1]+(self.coord//overworld.sizeX)*tileSize)

  def interact(self,side):
    item=self.item()
    item.discovered = True
    nbr=self.nbr()
    dialogBox.init(side)
    dialogBox.drw("You broke the pot",side)
    phrase = "There was "+str(nbr)+" "+item.text+"s"*(nbr>1)+" in it"
    dialogBox.drw(phrase,side)
    dialogBox.hide(side)
    item.nbr += nbr
    fill_rect(offset[0]+(self.coord%overworld.sizeX)*tileSize,offset[1]+(self.coord//overworld.sizeX)*tileSize,tileSize,tileSize,(255,)*3)
    drwTile(overworld.tile[ord(overworld.terrain[overworld.world][overworld.y][overworld.x][self.coord])-40],offset[0]+(self.coord%overworld.sizeX)*tileSize,offset[1]+(self.coord//overworld.sizeX)*tileSize)
    overworld.visibleEntities.remove(self)
    if not self.respawn:
      entities.remove(self)


def hidefunc(side):
  for i in range(1,overworld.sizeX-1):
    for j in range(5*side,5*side+3):
      drwTile(overworld.tile[int(ord(overworld.terrain[overworld.world][overworld.y][overworld.x][j*overworld.sizeX+i])-40)],i*tileSize+offset[0],j*tileSize+offset[1])
  overworld.drwEntities()

dialogBox = DialogBox((40,15,240,72),(40,135,240,72),hidefunc=hidefunc)

Jar(1,0,1,4,4)
Jar(1,0,1,4,5)
Jar(1,0,1,4,6)
Jar(1,0,1,10,3)
Jar(1,0,1,10,4)

Jar(1,1,1,6,1)
Jar(1,1,1,7,1)
Jar(1,1,1,2,6)
Jar(1,1,1,3,6)

Jar(1,1,2,4,3)
Jar(1,1,2,9,5)
Jar(1,1,2,9,6)

Jar(1,1,3,1,4,item=lambda: specialCollectables[0],nbr=lambda: 1, respawn=False)
Jar(1,2,0,1,4,item=lambda: specialCollectables[1],nbr=lambda: 1, respawn=False)
Jar(0,3,1,1,4,item=lambda: specialCollectables[2],nbr=lambda: 1, respawn=False)

fill_rect(0,0,320,222,(0,)*3)

overworld.drwMap()
player = Player()
player.drw()
dialogBox.init(0)
dialogBox.drw("You wake up",0)
dialogBox.drw("You are feeling good",0)
dialogBox.drw("Today is going to be a good day",0)
dialogBox.hide(0)

def main():
  while 1:
    player.updt()

main()

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.