import kandinsky as kd import random import time import ion class Input: presses={key: value for key,value in zip(("left","right","up","down","ok"), (ion.KEY_LEFT,ion.KEY_RIGHT,ion.KEY_UP,ion.KEY_DOWN,ion.KEY_OK))} def is_pressed(*args): for arg in args: if ion.keydown(Input.presses[arg]): return(True) return(False) class Grid: vlr=10 width=32 height=23 grids=dict() class Tile: colors={"air": ((135,205,250),None), "dirt": ((139,69,19),(35,140,35)), "fog": (42,)*3, "stone": ((130,)*3,None), "coal": ((130,)*3,(55,70,80)), "iron": ((130,)*3,(205,130,65)), "gold": ((130,)*3,(255,215,0)), "diamond": ((130,)*3,(0,190,255))} base_mineral_subrects=((5,2,2,2),(6,2,2,2),(7,2,2,2), (1,4,2,2),(2,4,2,2),(3,4,2,2), (7,6,2,2),(8,6,2,2),(9,6,2,2), (3,8,2,2),(4,8,2,2),(5,8,2,2)) subrects=None def __init__(self,index,x,y,breed,is_visible=False): self.index=index self.x=x self.y=y self.breed=breed self.is_visible=is_visible def display(self): if not self.is_visible: kd.fill_rect(self.x*Grid.vlr,self.y*Grid.vlr,Grid.vlr,Grid.vlr,Grid.Tile.colors["fog"]) return(None) kd.fill_rect(self.x*Grid.vlr,self.y*Grid.vlr,Grid.vlr,Grid.vlr,Grid.Tile.colors[self.breed][0]) if not Grid.Tile.colors[self.breed][1]: return(None) if self.breed=="dirt": if self.y-1>=0 and Grid.grids[self.index][self.y-1][self.x].breed!="air": return(None) for x,y,w,h in Grid.Tile.subrects[self.breed]: kd.fill_rect(self.x*Grid.vlr+x,self.y*Grid.vlr+y,w,h,Grid.Tile.colors[self.breed][1]) def init(index=0): #/10 Grid.Tile.subrects={"dirt": ((0,0,10,3),), "coal": Grid.Tile.base_mineral_subrects, "iron": Grid.Tile.base_mineral_subrects, "gold": Grid.Tile.base_mineral_subrects, "diamond": Grid.Tile.base_mineral_subrects} ground_level=9 Grid.grids[index]=[] for y in range(Grid.height): Grid.grids[index].append([]) for x in range(Grid.width): visibility=y<=ground_level breed=("air" if y<ground_level else "dirt") if y>ground_level+1 and not random.randrange(max(10+min(ground_level-y+1,0),1)): breed="stone" Grid.grids[index][-1].append(Grid.Tile(index,x,y,breed,visibility)) Grid.grids[index][-1][-1].display() for i in range(random.randrange(13)): Grid.spawn_mineral(index,"coal",ground_level) for i in range(random.randrange(8)): Grid.spawn_mineral(index,"iron",ground_level+3) for i in range(random.randrange(5)): Grid.spawn_mineral(index,"gold",ground_level+6) for i in range(random.randrange(2)): Grid.spawn_mineral(index,"diamond",ground_level+9) if index: return(None) Grid.grids[index][3][11].breed="dirt" Grid.grids[index][3][11].display() Grid.grids[index][6][13].breed="dirt" Grid.grids[index][6][13].display() def spawn_mineral(index,breed,ground_level): vects=[(1,0),(-1,0),(0,1),(0,-1)]*2 del vects[vects.index((0,-1))] vects.append((0,1)) size=random.randrange(1,8) position=[random.randrange(Grid.width),random.randrange(ground_level+1,Grid.height)] for i in range(size): vect=random.choice(vects) position[0]+=vect[0] position[1]+=vect[1] if not 0<=position[0]<Grid.width: continue if not ground_level<position[1]<Grid.height: continue Grid.grids[index][position[1]][position[0]].breed=breed Grid.grids[index][position[1]][position[0]].display() def display(index): for line in Grid.grids[index]: for tile in line: tile.display() class Player: gravity=1 base_jump_height=10 base_fog_radius=2 base_digging_delay=1/4 def init(base_color): Player.base_color=base_color def __init__(self,x,y,width,height,color,index=0): self.index=index self.x=x self.y=y self.width=width self.height=height self.color=color self.vel=[0,0] self.jump_height=Player.base_jump_height self.fog_radius=Player.base_fog_radius self.digging_delay=Player.base_digging_delay self.last_dug=float("-inf") self.ground=None self.ahead=[1,0] self.digging_phase=False self.previous_position=(x,y) def update(self,Grid,left,right,up,down): self.previous_position=(round(self.x-1),round(self.y-1)) if left: self.ahead=[-1,0] elif right: self.ahead=[1,0] elif down: self.ahead=[0,1] elif up: self.ahead=[0,-2] if self.ground and up: self.vel[1]-=self.jump_height self.vel[0]=(right-left)*5 self.vel[1]+=Player.gravity self.x+=self.vel[0] abort=False for x in range(self.x//Grid.vlr,(self.x+self.width)//Grid.vlr+1): if abort or not self.vel[0]: break for y in range(self.y//Grid.vlr,(self.y+self.height)//Grid.vlr+1): if not (0<=x<Grid.width and 0<=y<Grid.height): continue if Grid.grids[self.index][y][x].breed=="air": continue rect=(x*Grid.vlr,y*Grid.vlr) if rect[0]+Grid.vlr<self.x: continue if rect[0]>self.x+self.width: continue if rect[1]+Grid.vlr<self.y: continue if rect[1]>self.y+self.height: continue if self.vel[0]>0: self.x=rect[0]-self.width-1 else: self.x=rect[0]+Grid.vlr+1 abort=True break pass self.y+=self.vel[1] self.ground=None abort=False for x in range(self.x//Grid.vlr,(self.x+self.width)//Grid.vlr+1): if abort or not self.vel[1]: break for y in range(self.y//Grid.vlr,(self.y+self.height)//Grid.vlr+1): if not (0<=x<Grid.width and 0<=y<Grid.height): continue if Grid.grids[self.index][y][x].breed=="air": continue rect=(x*Grid.vlr,y*Grid.vlr) if rect[0]+Grid.vlr<self.x: continue if rect[0]>self.x+self.width: continue if rect[1]+Grid.vlr<self.y: continue if rect[1]>self.y+self.height: continue if self.vel[1]>0: self.ground=Grid.grids[self.index][y][x] self.y=rect[1]-self.height-1 self.vel[1]=0 else: self.y=rect[1]+Grid.vlr+1 self.vel[1]=0 abort=True break if self.y>=(length:=Grid.vlr*Grid.height-self.height): self.y=length-1 self.ground=True self.vel[1]=0 def dig(self,Grid,should_dig=True): if not should_dig or time.monotonic()-self.last_dug<self.digging_delay: return(None) position=[self.x//Grid.vlr,(self.y+self.height)//Grid.vlr] position[0]+=self.ahead[0] position[1]+=self.ahead[1] if not 0<=position[0]<Grid.width: return(None) if not 0<=position[1]<Grid.height: return(None) if self.ahead[0]: self.digging_phase=not(self.digging_phase) if self.digging_phase: position[1]-=1 Grid.grids[self.index][position[1]][position[0]].breed="air" Grid.grids[self.index][position[1]][position[0]].display() self.last_dug=time.monotonic() def update_fog(self,Grid): fog_radius=self.fog_radius**2 position_cache=(self.x//Grid.vlr,self.y//Grid.vlr) for y in range(-self.fog_radius,self.fog_radius+1): for x in range(-self.fog_radius,self.fog_radius+1): dx=position_cache[0]+x dy=position_cache[1]+y if not 0<=dx<Grid.width: continue if not 0<=dy<Grid.height: continue if Grid.grids[self.index][dy][dx].is_visible: continue if x**2+y**2<=fog_radius: Grid.grids[self.index][dy][dx].is_visible=True Grid.grids[self.index][dy][dx].display() def knock_knock(self,Grid): if self.x>Grid.vlr*Grid.width: self.x=round(self.width*0.5) self.vel[0]=0 self.index+=1 if self.index not in Grid.grids.keys(): Grid.init(self.index) else: Grid.display(self.index) return(None) if self.x+self.width<0: self.x=round(Grid.vlr*Grid.width-self.width*1.5) self.vel[0]=0 self.index-=1 if self.index not in Grid.grids.keys(): Grid.init(self.index) else: Grid.display(self.index) def display(self): ints=(round(self.x-1),round(self.y-1)) kd.fill_rect(self.previous_position[0],self.previous_position[1],self.width+2,self.height+2,Player.base_color) kd.fill_rect(ints[0],ints[1],self.width+2,self.height+2,self.color) def main(): player.update(Grid,Input.is_pressed("left"),Input.is_pressed("right"), Input.is_pressed("up"),Input.is_pressed("down")) player.update_fog(Grid) player.dig(Grid,should_dig=Input.is_pressed("ok")) player.knock_knock(Grid) player.display() Grid.init() Player.init(Grid.Tile.colors["air"][0]) player=Player(0,0,Grid.vlr*1-2,Grid.vlr*2-2,(0,0,255)) try: while True: frame_start=time.monotonic() main() #frames.append(1/(time.monotonic()-frame_start)) #del frames[0] #print(sum(frames)/len(frames)) while time.monotonic()-frame_start<1/30: pass except KeyboardInterrupt: pass