nuum2d.py

Created by andreanx

Created on February 22, 2021

6.05 KB

Version 2D du jeu spécial Halloween 2020 par NumWorks ! Oseras-tu explorer les 4 labyrinthes pour trouver les 4 clés et fuir cette sinistre crypte ? Déplace toi à l’aide des flèches directionnelles. Pour commencer, entre main().


from ion import *
from kandinsky import *
from math import *
from random import randint
from time import monotonic

### PROGRAM CONSTANTS
# Display
SCREEN_WIDTH = 320
SCREEN_HEIGHT = 222

# Movement
RUNNING_SPEED = 1

# Surfaces IDs
CEILING = 0
FLOOR = 1
WALL_EMPTY = 2
WALL_STANDARD = 3
WALL_FANCY = 4
WALL_SPECIAL_A = 5
WALL_SPECIAL_B = 6
WALL_SPECIAL_C = 7

MAZE_SIZE = 17
MAZES = [
    994639892451692017993627844655427188346119489096700102527510313302320457573868616417279,
    994639136329297165277925056994599494901591635504316814914476715640179960969549973159935,
    994638899191857351225063837897269868434453723710226411561032419934171038551468501237759,
    994638903127657620198142832056217335350998827328484167051085993695318850524015157706751,
        ]
HIGHLIGHTS = [WALL_FANCY, WALL_SPECIAL_A, WALL_SPECIAL_B, WALL_SPECIAL_C]

T_SIZE = SCREEN_HEIGHT//MAZE_SIZE

### IMAGES DEFINITION

def sprite_key(x, depth):
    rects = [
            (2,0,1,9,(255,181,49)),
            (0,9,1,3,(255,181,49)),
            (4,9,1,3,(255,181,49)),
            (1,9,3,1,(255,181,49)),
            (1,11,3,1,(255,181,49)),
            (2,1,3,3,(255,181,49)),
            ]
    draw_sprite(rects, x, depth, 2.5, 6, 5, 0)
KEY = (sprite_key, 13)

def sprite_pumpkin(x, depth):
    rects = [
            (2,0,6,1,(204,102,51)),
            (2,7,6,1,(204,102,51)),
            (0,1,10,6,(204,102,51)),
            (8,3,1,1,(51,51,51)),
            (3,3,1,1,(51,51,51)),
            (4,1,1,2,(51,51,51)),
            (4,5,1,1,(51,51,51)),
            (5,6,1,1,(51,51,51)),
            (3,6,1,1,(51,51,51)),
            (2,5,1,1,(51,51,51)),
            (6,5,1,1,(51,51,51)),
            (7,6,1,1,(51,51,51)),
            (8,5,1,1,(51,51,51)),
            (7,2,1,2,(51,51,51)),
            ]
    draw_sprite(rects, x, depth, 5, 4, 5, 50)
PUMPKIN = (sprite_pumpkin, 25)

SPRITES = [((MAZE_SIZE - 0.5, MAZE_SIZE - 1.5), KEY)]
### HELPERS

def nThBit(x, n):
    return (x >> n) & 1

def numberOfSprites(): return len(SPRITES)
def spritePosition(index): return SPRITES[index][0]
def spriteImage(index): return SPRITES[index][1][0]
def spriteHalfWidth(index): return SPRITES[index][1][1]

def startingPosition(): return (0.5, 1.5), (1, 0)

def wall(mapId, x, y):
    if nThBit(MAZES[mapId], x + MAZE_SIZE * y) == 0: return WALL_EMPTY
    if x % 3 == 0 and y % 3 == 0: return HIGHLIGHTS[mapId]
    return WALL_STANDARD

def prompt(mapId, x, y):
    if (floor(x), floor(y)) == (MAZE_SIZE - 1, MAZE_SIZE - 2): return "Grab Key"
    return str(mapId) + "/4"

def interact(x, y):
    if (floor(x), floor(y)) == (MAZE_SIZE - 1, MAZE_SIZE - 2): return True
    return False

def randomSprites(mapId, n = 5):
    res = []
    for i in range(n):
        x, y = 0, 0
        while nThBit(MAZES[mapId], x + MAZE_SIZE * y) == 1:
            x, y = randint(0, MAZE_SIZE - 1), randint(0, MAZE_SIZE - 1)
        res.append(((x + 0.5, y + 0.5), PUMPKIN))
    return res

### DISPLAY MODULE
def transparent(wallId):
    return wallId == WALL_EMPTY

def color(wallId):
    if wallId == CEILING: return (33, 33, 33)
    elif wallId == FLOOR: return (48, 48, 48)
    elif wallId == WALL_STANDARD: return (62, 62, 62)
    elif wallId == WALL_FANCY: return (190, 110, 50)
    elif wallId == WALL_SPECIAL_A: return (50, 0, 80)
    elif wallId == WALL_SPECIAL_B: return (90, 255, 0)
    elif wallId == WALL_SPECIAL_C: return (255, 0, 0)
    return (247, 16, 247)

def draw_sprite(rects, x, y, xCenter, yCenter, scale, offset):
  for (px, py, dx, dy, color) in rects:
    fill_rect(x+px, y+py, dx, dy, color)

def drawSurfacesAndSprites(xp, yp, mapId):
  fill_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, color(CEILING))
  for y in range(MAZE_SIZE):
    for x in range(MAZE_SIZE):
      w = wall(mapId, x, y)
      if w != WALL_EMPTY:
        fill_rect(T_SIZE*x, T_SIZE*y, T_SIZE,T_SIZE,color(w))
  fill_rect(int(xp) * T_SIZE, int(yp) * T_SIZE, T_SIZE, T_SIZE, color(WALL_EMPTY))
  for sprite in SPRITES:
    sprite[1][0](int(sprite[0][0])*T_SIZE,int(sprite[0][1])*T_SIZE)

def drawPrompt(x, y, mapId):
  message = prompt(mapId, x, y)
  draw_string(message, SCREEN_WIDTH - (len(message) + 1) * 10, SCREEN_HEIGHT - 46, 'white', 'black')
    
def drawFrame(x, y, mapId):
  if mapId < len(MAZES):
    drawSurfacesAndSprites(x, y, mapId)
  drawPrompt(x, y, mapId)

### GAMEPLAY MODULE
def move(x, y, dx, dy, mapId):
  xNew, yNew = x + dx, y + dy
  if transparent(wall(mapId, floor(xNew), floor(yNew))):
    return xNew, yNew
  return x, y

def handleKeys(mapId, xOld, yOld):
  redraw, refresh = False, False
  x, y = xOld, yOld
  dx, dy = keydown(KEY_RIGHT) - keydown(KEY_LEFT), keydown(KEY_DOWN) - keydown(KEY_UP)
  if (dx, dy) != (0, 0):
    if interact(xOld, yOld):
      redraw, mapId, (x, y) = True, (mapId + 1), startingPosition()[0]
      del SPRITES[1:]
      if mapId < len(MAZES):
        SPRITES.extend(randomSprites(mapId))
      redraw = True
    else:
      x, y = move(xOld, yOld, dx, dy, mapId)
      refresh = (x, y) != (xOld, yOld)
  return (redraw, refresh, x, y, mapId)

### MAIN
def main():
  # Init
  game_map = 0
  (game_x, game_y) = startingPosition()[0]
  del SPRITES[1:]
  SPRITES.extend(randomSprites(game_map))

  redraw = True
  time, dt = monotonic(), 0

  # Run loop
  while game_map < len(MAZES) or redraw:
    if redraw:
      drawFrame(game_x, game_y, game_map)
      redraw = False
    elif refresh:
      fill_rect(int(game_old_x) * T_SIZE, int(game_old_y) * T_SIZE, T_SIZE, T_SIZE, color(CEILING))
      fill_rect(int(game_x) * T_SIZE, int(game_y) * T_SIZE, T_SIZE, T_SIZE, color(2))
      for sprite in SPRITES:
        (xSprite, ySprite) = sprite[0]
        if (int(xSprite), int(ySprite)) == (int(game_x), int(game_y)) or (int(xSprite), int(ySprite)) == (int(game_old_x), int(game_old_y)):
          sprite[1][0](int(sprite[0][0])*T_SIZE,int(sprite[0][1])*T_SIZE)
    if game_map < len(MAZES):
      dt = monotonic() - time
      
      if dt > .1:
        time += dt
        game_old_x, game_old_y = game_x, game_y
        redraw, refresh, game_x, game_y, game_map = handleKeys(game_map, game_x, game_y)

print("Launch with 'main()'.\nArrow keys to move.\nFind the four keys to escape.")