cavetest.py

Created by andreanx

Created on October 06, 2020

7.21 KB


from math import pi, asin, sin, cos, sqrt

def fix_angle(a):
  return a * 2 * asin(1) / pi

def col3_2_rgb(c, bits, bgr):
  return c[2*bgr]//2**(8 - bits[0]) + c[1]//2**(8 - bits[1])*2**bits[0] + c[2*(not bgr)]//2**(8-bits[2])*2**(bits[0] + bits[1])
def kc16_draw_line(x1, y1, x2, y2, c):
  draw_line(int(x1), int(y1), int(x2), int(y2), col3_2_rgb(c, [5, 6, 5], 1))
def kc16_fill_rect(x, y, w, h, c):
  draw_rectangle(float(x), float(y), float(w), float(h), col3_2_rgb(c, [5, 6, 5], 1) + filled)
def kc16_fill_ellipse(x, y, rx, ry, c):
  draw_arc(float(x), float(y), float(rx), float(ry), 0, 2*pi, col3_2_rgb(c, [5, 6, 5], 1) + filled)

def get_infos():
  global kc16_draw_line, kc16_fill_rect, kc16_fill_ellipse
  fnop = lambda : None
  screen_w, screen_h, color_bits, poly_has_color, poly_set_pixel, poly_show, poly_draw_line, poly_fill_rect, poly_fill_ellipse, poly_clean_screen, poly_pause, need_clean, need_pause, need_line, need_rect, need_ellipse = 0, 0, [5, 6, 5], 1, fnop, fnop, fnop, fnop, fnop, fnop, fnop, 0, 0, 1, 1, 1
  try:
    if chr(256)==chr(0): # KhiCAS Python compat.
      need_line = 0
      need_clean = 1
      screen_w, screen_h = 320, 222
      def poly_set_pixel(x, y, c):
        set_pixel(x, y, col3_2_rgb(c, [5,6,5], 0))
      poly_draw_line, poly_fill_rect, poly_fill_ellipse = kc16_draw_line, kc16_fill_rect, kc16_fill_ellipse
  except:
    pass
  if not screen_w:
    kc16_draw_line, poly_fill_rect, poly_fill_ellipse = None, None, None
    try: # KhiCAS Micropython
      import graphic
      def poly_draw_line(x1, y1, x2, y2, c):
        graphic.draw_line(int(x1), int(y1), int(x2), int(y2), col3_2_rgb(c, color_bits, 1))
      def poly_fill_rect(x1, y1, x2, y2, c):
        graphic.draw_filled_rectangle(int(x1), int(y1), int(x2), int(y2), c)
      def poly_fill_ellipse(x, y, rx, ry, c):
        graphic.draw_filled_arc(int(x), int(y), int(rx), int(ry), 0, 360, c)
      screen_w, screen_h, poly_set_pixel, need_clean, need_line, need_rect, need_ellipse = 320, 222, graphic.set_pixel, 1, 0, 0, 0
    except:
      pass
  if not screen_w:
    try: # NumWorks
      import kandinsky
      screen_w, screen_h, poly_set_pixel, need_rect = 320, 222, kandinsky.set_pixel, 0
      def poly_fill_rect(x, y, w, h, c):
        kandinsky.fill_rect(int(x), int(y), int(w), int(h), c)
    except:
      pass
  if need_line:
    def poly_draw_line(x1, y1, x2, y2, c):
      m, a1, b1, a2, b2 = 0, int(x1), int(y1), int(x2), int(y2)
      if (x2 - x1) ** 2 < (y2 - y1) ** 2:
        m, a1, a2, b1, b2 = 1, b1, b2, a1, a2
      if min(a1, a2) != a1: a1, b1, a2, b2 = a2, b2, a1, b1
      for k in range(a2 - a1 + 1):
        a, b = a1 + k, int(b1 + (b2 - b1) * k / ((a2 - a1) or 1))
        poly_set_pixel((a, b)[m], (b, a)[m], c)

  if need_rect:
    def poly_fill_rect(x, y, w, h, c):
      for k in range(h):
        poly_draw_line(x, y + k, x + w - 1, y + k, c)

  if need_ellipse:
    from math import sqrt
    def poly_fill_ellipse(x, y, rx, ry, c):
      for h in range(-ry, ry+1):
        w = sqrt(max(0, rx*rx*(1-h*h/ry/ry)))
        x1, x2 = x - w, x + w
        yc = y + h
        poly_draw_line(x1, yc, x2, yc, c)

  if need_clean:
    def poly_clean_screen():
      poly_fill_rect(0, 0, screen_w, screen_h, [255, 255, 255])

  return screen_w, screen_h, poly_has_color, poly_set_pixel, poly_draw_line, poly_fill_rect, poly_fill_ellipse, poly_clean_screen, fnop

def rnd():
  global s
  rnd_max = 0x7fff
  s = (s * 214013 + 2531011) % 4294967296
  return ((s // (2*rnd_max + 1)) & rnd_max) / rnd_max

def hmap(t):
  frq, pha, hm, amp = [ 1, 3, 15, 21, 39, 51, 97, 145 ], [], [], []
  for i in range(8):
    amp.append((rnd() + 1) * (cave_h * 27) / 200 / 1.2**i)
  for k in frq:
    pha.append(pi * rnd())
  for x in range(cave_w):
    hm.append(int(sum([amp[i] * (1 + sin(fix_angle(frq[i]*x/cave_w + pha[i]))) / 2 for i in range(len(amp))])))
  return [ h - min(hm) + t for h in hm ]

cave_w, cave_h, s = 128, 64, 0xdeadbeef
fl, cv = hmap(2), hmap(8)

screen_w, screen_h, poly_has_color, poly_set_pixel, poly_draw_line, poly_fill_rect, poly_fill_ellipse, poly_clean_screen, poly_show_screen = get_infos()
zx, zy = (screen_w - 1) / (cave_w - 1), (screen_h - 1) / (cave_h - 1)
get_infos, poly_set_pixel, hmap, rnd = None, None, None, None

def interpol1(yi, yf, dx):
  return yi + dx*(yf - yi)

def interpol_list(lst, i):
  i0 = int(i)
  v = lst[i0]
  if i > i0 and i < len(lst) - 1:
    v = interpol1(v, lst[i0 + 1], i - i0)
  return v

def test_collision(x, y):
  f = cave_h - interpol_list(fl, x)
  return y >= f or y <= f-interpol_list(cv, x)

def test_collision_rect(x, y, dx, dy):
  x1, x2, y1, y2 = max(0, x - dx), min(cave_w - 1, x + dx), y - dy, y + dy
  return test_collision(x1, y1) + test_collision(x2, y1) + test_collision(x1, y2) + test_collision(x2, y2)

def test_balloon(x, y, rx, ry, d_vert):
  rmax, r2, k, collisions = [rx, ry][d_vert], [ry, rx][d_vert], -1, 0
  while k < rmax:
    k = min(k + 1, rmax)
    k2 = sqrt(max(0, r2*r2*(1 - k*k/rmax/rmax)))
    collisions += test_collision_rect(x, y, [k, k2][d_vert], [k2, k][d_vert])
  return collisions

def rxy(a):
  if a%2 == 1:
    rx, ry = 0, 1-2*(a%4 == 3)
  else:
    a = fix_angle(a * pi/2)
    rx, ry = abs(cos(a)), abs(sin(a))
  return 1 + abs(rx), 1 + abs(ry)

colors = ([0, 0, 0], [255, 255, 255], [0, 0, 255], [255, 0, 0], [159, 159, 159])

def modifier_vol(ay, da, dt):
  global state
  if ay or da:
    state[4] += 10
  x, y, a = state[0:3]
  while state[0] < cave_w - 1 and dt:
    state[0] += 1
    state[2] = max(0, min(1, a + da))
    state[3] -= ay
    state[1] = max(0, min(cave_h - 1, state[1] + state[3]))
    dt = max(0, dt - 1)  
    da, dapi, dx = abs(state[2] - a), abs(state[2] - .5), 1
    state[4] += 3*(da > 0)*(1 + da) + 2*(dapi > 0)*(1 + dapi)
    xc, yc, dx = x, y, 1
    rx, ry = rxy(state[2])
    if state[1] != y:
      dx = min(1 / abs(state[1] - y), 1)
    collisions = test_balloon(state[0], state[1], rx, ry, 0) + test_balloon(state[0], state[1], rx, ry, 1)
    if collisions:
      state[4] += 7 * (1 + collisions)
    while xc < state[0]:
      xc += dx/zx
      yc = interpol1(y, state[1], xc - x)
      rx, ry = rxy(interpol1(a, state[2], state[2] - a))
      poly_fill_ellipse(xc * zx, yc * zy, rx * zx, ry * zy, colors[2*poly_has_color + (collisions > 0)])
    x, y, a = state[0], state[1], state[2]

def voler_selon(f):
  global state, fl, cv
  state = [0, 12, .5, 0,0]
  poly_fill_rect(0, 0, screen_w, screen_h, colors[4])
  for x in range(cave_w):
    f1, dx = cave_h - fl[x], 0
    c1 = f1 - cv[x]
    while dx < zx:
      f2 = cave_h - interpol_list(fl, x + dx/zx)
      c2 = f2 - interpol_list(cv, x + dx/zx)
      poly_draw_line(x*zx + dx, c2 * zy, x*zx + dx, f2 * zy, colors[1])
      dx += 1
    if poly_has_color:
      poly_draw_line(x * zx, c1 * zy, (x + 1) * zx, c2 * zy, colors[0])
      poly_draw_line(x * zx, f1 * zy, (x + 1) * zx, f2 * zy, colors[0])
  f()
  if state[0] < cave_w - 1:
    modifier_vol(0, 0, cave_w - 1 - state[0])
  poly_show_screen()
  print('Consommation : ' + str(state[4]))
  print('Bravo, tu es passe-e.')
  print('Pour jouer et gagner,')
  print('envoie ton script a')
  print('info@tiplanet.org.')
  return state[4]

def plan():
  modifier_vol(-1, 0, 5)
  modifier_vol(1, 0, 8)
  modifier_vol(-0.89, 0.1, 6)
  modifier_vol(0, 0.1, 5)
  modifier_vol(1, 0.1, 8)

#voler_selon(plan)