perspective.py

Created by fixem

Created on May 31, 2025

2.99 KB

Simulation d’un environnement en fausse 3D (perspective cavalière) je vous conseille de le lancer soit sur le simulateur, soit sur N0120 pour un meilleur rafraichissement près des modèles. render -> plus la valeur est haute, moins il y aura de pixels pour dessiner les arrêtes SPEED -> définit la vitesse de déplacement.


from kandinsky import set_pixel, draw_string, fill_rect
from ion import keydown
from math import sin,cos,radians
WIDTH=320
HEIGHT=240
CENTER_X=WIDTH//2
CENTER_Y=HEIGHT//2
FOCAL_LENGTH=100
camera_x=0.0
camera_y=0.0
camera_z=-200.0
camera_angle=0.0
ROT_SPEED=5.0
last_x=camera_x
last_y=camera_y
last_z=camera_z
last_angle=camera_angle
def safe_set_pixel(x,y,color):
  if 0<=x<WIDTH and 0<=y<HEIGHT:
    set_pixel(x,y,color)

def draw_line(x0,y0,x1,y1,color):
  dr=0
  dx=abs(x1-x0)
  dy=-abs(y1-y0)
  sx=1 if x0<x1 else -1
  sy=1 if y0<y1 else -1
  err=dx+dy
  while True:
    if dr==render:
      safe_set_pixel(x0, y0, color)
      dr=0
    else:dr+=1
    if x0==x1 and y0==y1:
      break
    e2=2*err
    if e2>=dy:
      err+=dy
      x0+=sx
    if e2<=dx:
      err+=dx
      y0+=sy

def gcv(cx,cy,cz,sizex,sizey,sizez):
  sx=sizex/2
  sy=sizey/2
  sz=sizez/2
  return [
    (cx-sx,cy-sy,cz-sz),
    (cx+sx,cy-sy,cz-sz),
    (cx+sx,cy+sy,cz-sz),
    (cx-sx,cy+sy,cz-sz),
    (cx-sx,cy-sy,cz+sz),
    (cx+sx,cy-sy,cz+sz),
    (cx+sx,cy+sy,cz+sz),
    (cx-sx,cy+sy,cz+sz),
  ]
def project_point(x,y,z,camera):
  cam_x,cam_y,cam_z,cam_angle=camera
  dx=x-cam_x
  dz=z-cam_z
  if dz>400 or dz<0:
    return None
  angle_rad=radians(-cam_angle)
  rotated_x=cos(angle_rad)*dx-sin(angle_rad)*dz
  rotated_z=sin(angle_rad)*dx+cos(angle_rad)*dz
  if rotated_z<=0:
    return None
  sx=CENTER_X+int(rotated_x*FOCAL_LENGTH/rotated_z)
  sy=CENTER_Y-int((y-cam_y)*FOCAL_LENGTH/rotated_z)
  return (sx,sy)
def draw_cube(vertices,camera):
  edges=[
    (0,1),(1,2),(2,3),(3,0),
    (4,5),(5,6),(6,7),(7,4),
    (0,4),(1,5),(2,6),(3,7)
  ]
  projected=[]
  for i in range(8):
    p=project_point(vertices[i][0],vertices[i][1],vertices[i][2],camera)
    projected.append(p)
  for edge in edges:
    a,b=edge
    if projected[a] is not None and projected[b] is not None:
      draw_line(projected[a][0],projected[a][1],projected[b][0],projected[b][1],(0,0,255))
def handle_input():
  global camera_x,camera_y,camera_z,camera_angle
  changed=False
  angle_rad=radians(camera_angle)
  if keydown(1):
    camera_x+=sin(angle_rad)*SPEED
    camera_z+=cos(angle_rad)*SPEED
    changed=True
  if keydown(2):
    camera_x-=sin(angle_rad)*SPEED
    camera_z-=cos(angle_rad)*SPEED
    changed=True
  if keydown(0):
    camera_x-=cos(angle_rad)*SPEED
    camera_z+=sin(angle_rad)*SPEED
    changed=True
  if keydown(3):
    camera_x+=cos(angle_rad)*SPEED
    camera_z-=sin(angle_rad)*SPEED
    changed=True
  return changed
def main():
  global last_x,last_y,last_z,last_angle
  while True:
    changed=handle_input()
    if (camera_x!=last_x or camera_y!=last_y or camera_z!=last_z or camera_angle!=last_angle or changed):
      fill_rect(0,0,WIDTH,HEIGHT,(255,)*3)
      camera=(camera_x,camera_y,camera_z,camera_angle)
      for e in elements:
        draw_cube(e,camera)
      last_x=camera_x
      last_y=camera_y
      last_z=camera_z
      last_angle=camera_angle
elements=[]
for i in range(10):
  elements.append(gcv(0,5,100*i,50,50,10))
render=0
SPEED=10
main()

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.