dino.py

Created by azerlap652

Created on December 31, 2024

8.4 KB

Un remake de Chrome Dino sur Numworks !


from math import *
from random import *
from kandinsky import *
from ion import *
from time import sleep, monotonic

# Window
W,H = 320,222
SIZE, WIN = (W,H), (0,0,W,H)
FONTW, FONTH = 10,18

# Utils
def clamp(m,x,M): return max(m,min(x,M))
def proba(n): return randint(1,n)==1
def ints(list): return tuple(int(x) for x in list)
def center_pos(rect): return rect[0]+rect[2]//2, rect[1]+rect[3]//2

def collide_x(r1,r2): return r1[0] < r2[0]+r2[2] and r2[0] < r1[0]+r1[2]
def collide_y(r1,r2): return r1[1] < r2[1]+r2[3] and r2[1] < r1[1]+r1[3]
def collide  (r1,r2): return collide_x(r1,r2) and collide_y(r1,r2)


# - colors
BLACK = (0, 0, 0)
DARK_GRAY = (95, 87, 79)
LIGHT_GRAY = (194, 195, 199)
WHITE = (255, 241, 232)
# 4-7
DARK_BLUE = (29, 43, 83)
BLUE = (41, 173, 255)
DARK_GREEN = (0, 135, 81)
GREEN = (0, 228, 54)
# 8-B
YELLOW = (255, 236, 39)
ORANGE = (255, 163, 0)
RED = (255, 0, 77)
BROWN = (171, 82, 54)
# C-F
PEACH = (255, 204, 170)
PINK = (255, 119, 168)
PURPLE = (126, 37, 83)
LAVENDER = (131, 118, 156)

COLORS = [BLACK, DARK_GRAY, LIGHT_GRAY, WHITE, DARK_BLUE, BLUE, DARK_GREEN, GREEN, YELLOW, ORANGE, RED, BROWN, PEACH, PINK, PURPLE, LAVENDER]

# Image module
def draw_rect(rect, color):
    fill_rect(int(rect[0]),int(rect[1]),int(rect[2]),int(rect[3]),color)

def fill(color=WHITE):
    draw_rect(WIN, color)

def draw_image(img,color=BLACK, X=0,Y=0):
    "( (x,y,w,h[,color]), ... )"
    for r in img:
        draw_rect((X+r[0],Y+r[1], r[2], r[3]), (r[4] if len(r) > 4 else color))

def draw_text(text, x, y, side="topleft", color=BLACK, background=WHITE):
    if "right" in side: x -= len(text)*FONTW
    elif not "left" in side: x -= len(text)*FONTW/2
    if "bottom" in side: y -= FONTH
    elif not "top" in side: y -= FONTH/2
    draw_string(text, int(round(x)),int(round(y)), color, background)


# Time (time: temps de la FRAME ! ne pas utiliser en dehors d'engine)
time,timers = 0,{}
def every(dt):
    if dt not in timers: timers[dt] = time
    return (time - timers[dt]) >= dt
    
def timer(t, dura):
    return (monotonic() - t) >= dura

# update
pressed = {}
just_pressed = {}

def update(keys=[KEY_OK]):
    """ keys: touches inscrites dans just_pressed. BIG ATTENTION: ne JAMAIS utiliser just_pressed dans un "every" """
    global time
    for dt in timers:
        if time-timers[dt] >= dt:
            timers[dt] = time
    time = monotonic()

    for key in keys:
        kd = keydown(key)
        just_pressed[key] = kd and not pressed.get(key)
        pressed[key] = kd

    return True

## DINO
low_detail = False
started = jumped = False

scale = 4
def add(r1,r2):
    res = []
    for i in range(max(len(r1),len(r2))):
        x = r1[i] if i < len(r1) else 0
        y = r2[i] if i < len(r2) else 0
        res.append(x+y)
    return res
def scaled(*list): return [x*scale for x in list]
def bottom(rect): return rect[1]+rect[3]
def right(rect): return rect[0]+rect[2]

# Game
def game():
    global low_detail, started, jumped
    floor = (0, 136, W, H-136)

    crouch = False
    vy = 0
    JUMP_HEIGHT = 14
    
    left_foot, right_foot = scaled(1,8,2,1), scaled(4,8,2,1)
    head = (scaled(5,0,4,4), scaled(6,2,4,4))
    dino = [head[crouch],scaled(0,3,7,4),scaled(1,7,2,1),scaled(4,7,2,1)]
   
    dino_rects = [[100, floor[1]-15*scale, w*scale, 9*scale] for w in (9,10)]
    dino_rect = dino_hitbox = dino_rects[crouch]

    cactus = []
    next = 1
    speed = 35

    score = 0
    time = monotonic()

    bg, fg = LIGHT_GRAY, DARK_GRAY
    text_colors = BLACK, WHITE
    cactus_colors = DARK_GREEN, GREEN
    dino_colors = DARK_GRAY, LIGHT_GRAY

    def draw_dino(started):
        dino[0] = head[crouch]
        if low_detail:
            draw_rect(dino_hitbox, dino_colors[0])
        else:
            # corps du dino (tete, corps, jambe)
            draw_image(dino, dino_colors[0], *dino_rect[:2])
            # pieds du dino
            if bottom(dino_rect) == floor[1] and started:
                foot = int(monotonic() // .2 +1) %2
                draw_rect(add(left_foot, dino_rect[:2]), (bg,dino_colors[0])[foot])
                draw_rect(add(right_foot,dino_rect[:2]), (dino_colors[0],bg)[foot])
            # jeu a pas commencé ...
            elif bottom(dino_rect) == floor[1] and not started:
                draw_rect(add(left_foot, dino_rect[:2]), dino_colors[0])
                draw_rect(add(right_foot,dino_rect[:2]), dino_colors[0])

    def draw_low_detail_text(jumped):
        textcol, bgcol = ((BLACK,bg),(text_colors[1],fg))[jumped]
        draw_text(("  shift | low detail  ","[ shift | low detail ]")[low_detail], W/2,H*.92,"center",textcol, bgcol)

    fill(bg)
    if not started:
        draw_rect((dino_rect[0]-20, floor[1], dino_rect[2]+40, 40),fg)
    else:
        draw_rect(floor,fg)
    draw_low_detail_text(jumped)
    draw_text("0000", W-20,20,"topright",text_colors[0],bg)
    draw_dino(started)
    while update(keys=(KEY_OK,KEY_DOWN,KEY_SHIFT)):
        if just_pressed[KEY_DOWN]:vy = JUMP_HEIGHT
        if just_pressed[KEY_SHIFT]:
            low_detail = not low_detail
            draw_low_detail_text(jumped)
            
        # Dino
        if every(.02):
            # Input
            old_hitbox = dino_hitbox[:]
            crouch = keydown(KEY_DOWN)
            r = dino_rects[crouch]
            r[1] = bottom(dino_rect) - r[3]
            dino_rect = r
            if crouch:
                dino_hitbox = add(dino_rect, scaled(0,2,0,-2))
            else:
                dino_hitbox = dino_rect
            if keydown(KEY_UP) and bottom(dino_rect) == floor[1]:
                vy = -JUMP_HEIGHT
                # (début)
                jumped = True
                if not started:
                    fill_rect(0, 20, int(W*.7), 20, bg)
                    draw_rect(floor,fg)
                    draw_low_detail_text(jumped)

            # Y movement
            if vy < 0 or bottom(dino_rect) < floor[1]:
                vy += 1
                dino_rect[1] += vy
                dino_rect[1] = min(dino_rect[1], floor[1]-dino_rect[3])
            else:
                vy = 0
                dino_rect[1] = floor[1] - dino_rect[3]
                # (début)
                if jumped:
                    started = True
                elif not started:
                    draw_text("jump to start", W/2, 20, "midtop", background=bg)
            
            # Draw
            if vy or started:
                draw_rect(old_hitbox, bg)
                draw_dino(started)
        
        # Cactus
        if started and every(.15):
            bin = []
            
            # update all
            for type, r in cactus:
                # predraw
                draw_rect(r, bg)
                # move
                r[0] -= speed
                # delete
                if right(r) < 0: bin.append((type,r)); continue
            for c in bin: cactus.remove(c)

            # gameover
            gameover, cactus_dx = False, 0
            for type, r in cactus:
                if collide(r, dino_hitbox):
                    cactus_dx = right(dino_rect) - r[0]
                    gameover = True
                    break
            if gameover: break
            # draw all
            for type, r in cactus:
                draw_rect(r, cactus_colors[type])

            # new
            if timer(time, next):
                time = monotonic()
                next = .5 + random()*1.5
                air = proba(3)
                size = [randint(6,10)*scale]*2 if not air else [6*scale,4*scale]
                cactus.append((air, [W, floor[1]-size[1] - 28*air*randint(1,2), size[0], size[1]]))

        # Score
        if started and every(.2):
            score += 1
            if score%100 == 0:
                bg, fg = fg, bg
                speed = min(70, speed+score%100 * 10)
                cactus_colors = (cactus_colors[1],cactus_colors[0])
                text_colors = (text_colors[1],text_colors[0])
                dino_colors = (dino_colors[1],dino_colors[0])
                fill(bg)
                draw_rect(floor,fg)
                draw_text("0000", W-20,20,"topright",text_colors[0],bg)
                draw_low_detail_text(jumped)
            draw_text(str(score), W-20,20,"topright",text_colors[0],bg)

    for type, r in cactus:
        r[0] += cactus_dx
        draw_rect(r, cactus_colors[type])

    draw_text("ok to retry", W/2,H*.7,"center",text_colors[1],fg)
    draw_text("esc to quit", W/2,H*.8,"center",text_colors[1],fg)
    while not (update() and just_pressed.get(KEY_OK)): pass
    game()


# Start
game()

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.