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