numcraft.py

Created by systeme-eratz

Created on June 15, 2024

10.6 KB


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

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.