Kujira no Hara

Pour présenter ses jeux en cours de création, terminés ou abandonnés
Avatar du membre
Nemau
Administrateur du site
Messages : 837
Enregistré le : 28 avr. 2019, 14:40

Re: Kujira no Hara

Message par Nemau » 09 févr. 2023, 15:31

Ça le fait.

Avatar du membre
Roi of the Suisse
Messages : 2107
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 13 févr. 2023, 13:34

WIP de script qui affiche des conneries en 3D

Code : Tout sélectionner

class Tetra_Sprite < Sprite
  
  
  def initialize(viewport = nil)
    super
    self.bitmap = Bitmap.new(640, 480)
    self.x, self.y, self.z = 0, 0, 4
    refresh
  end
  
  
  def dispose
    self.bitmap.dispose
    super
  end
  
  
  def update
    refresh 
  end
  
  
  def refresh
    self.bitmap.clear
    
    require "matrix"
    
    # sommets
    s1 = Vector[-1,  1,  1].normalize
    s2 = Vector[ 1, -1,  1].normalize
    s3 = Vector[-1, -1, -1].normalize
    s4 = Vector[ 1,  1, -1].normalize
    
    # centres de faces
    c1 = (s2+s3+s4).normalize
    c2 = (s3+s4+s1).normalize
    c3 = (s4+s1+s2).normalize
    c4 = (s1+s2+s3).normalize
    
    # troncature sur l'arête entre sommet et centre de face
    l = 0.366
    s1c2 = (s1*l+c2*(1-l)).normalize
    s1c3 = (s1*l+c3*(1-l)).normalize
    s1c4 = (s1*l+c4*(1-l)).normalize
    s2c3 = (s2*l+c3*(1-l)).normalize
    s2c4 = (s2*l+c4*(1-l)).normalize
    s2c1 = (s2*l+c1*(1-l)).normalize
    s3c4 = (s3*l+c4*(1-l)).normalize
    s3c1 = (s3*l+c1*(1-l)).normalize
    s3c2 = (s3*l+c2*(1-l)).normalize
    s4c1 = (s4*l+c1*(1-l)).normalize
    s4c2 = (s4*l+c2*(1-l)).normalize
    s4c3 = (s4*l+c3*(1-l)).normalize
    
    # troncature sur l'arête entre deux sommets
    k = 0.611
    s1s2 = (s1*k+s2*(1-k)).normalize
    s2s1 = (s2*k+s1*(1-k)).normalize
    s2s3 = (s2*k+s3*(1-k)).normalize
    s3s2 = (s3*k+s2*(1-k)).normalize
    s4s3 = (s4*k+s3*(1-k)).normalize
    s3s4 = (s3*k+s4*(1-k)).normalize
    s4s1 = (s4*k+s1*(1-k)).normalize
    s1s4 = (s1*k+s4*(1-k)).normalize
    s4s2 = (s4*k+s2*(1-k)).normalize
    s2s4 = (s2*k+s4*(1-k)).normalize
    s1s3 = (s1*k+s3*(1-k)).normalize
    s3s1 = (s3*k+s1*(1-k)).normalize
    
    # faces hexagonales
    h1 = [s1s4, s1c2, s1s3, s1c4, s1s2, s1c3]
    h2 = [s2s1, s2c3, s2s4, s2c1, s2s3, s2c4]
    h3 = [s3s1, s3c4, s3s2, s3c1, s3s4, s3c2]
    h4 = [s4s1, s4c3, s4s2, s4c1, s4s3, s4c2]
    
    # faces pentagonales
    p14 = [s2c1, c1, s3c1, s3s2, s2s3]
    p12 = [s3c1, c1, s4c1, s4s3, s3s4]
    p13 = [s4c1, c1, s2c1, s2s4, s4s2]
    
    p24 = [s1c2, c2, s3c2, s3s1, s1s3]
    p21 = [s3c2, c2, s4c2, s4s3, s3s4]
    p23 = [s4c2, c2, s1c2, s1s4, s4s1]
    
    p34 = [s2c3, c3, s1c3, s1s2, s2s1]
    p32 = [s1c3, c3, s4c3, s4s1, s1s4]
    p31 = [s4c3, c3, s2c3, s2s4, s4s2]
    
    p43 = [s2c4, c4, s1c4, s1s2, s2s1]
    p42 = [s1c4, c4, s3c4, s3s1, s1s3]
    p41 = [s3c4, c4, s2c4, s2s3, s3s2]
    
    
    # filtrer les faces avec un dot product négatif 
    touteslesfaces = [h1,h2,h3,h4, p14,p12,p13, p21,p23,p24, p31,p32,p34, p41,p42,p43]    
	rotation = Time.now.to_f * 1000.0 % (2*Math.PI)
	for face in touteslesfaces
	  directionface = directionface(face)
	  dotprod = dotproduct(directionface, rotation)
	  if dotprod < 0
	    touteslesfaces.delete(face)
	  end
	end
	
	
    # classer les faces de la plus derrière à la plus devant
	touteslesfaces.sort! { |f1, f2|  dotproduct(f1, rotation) <=> dotproduct(f2, rotation) }
    
	
    # dessiner les faces
    for face in touteslesfaces
      # couleur en fonction de l'orientation de la face
	  dot = dotproduct(directionface(face), rotation)
	  if dot < 0 
	    dot = 0
	  end
	  facecolor = Color.new(dot, dot, dot, 255) # gris
      
      # on decompose la face en triangles
      sommet1 = face[0]
      for i in 1..face.size-1
        sommet2 = face[i]
        sommet3 = face[i+1]
		
        triangles = Array.new
        t = Triangle.new(
          # Projection de x et y de chaque sommet selon l'angle de rotation
          x1: dotproduct(sommet1, rotation), 
          y1: sommet1[2],
          
          x2: dotproduct(sommet2, rotation), 
          y2: sommet2[2],
          
          x3: dotproduct(sommet3, rotation), 
          y3: sommet3[2],
          
          color: 'red',
          z: 100
        )
        triangles.push(t)
      end
      
      for t in triangles
		draw_triangle(t)
      end

    end
  end
  
  
  # normale d'une face (vecteur)
  def directionface(face)
    directionface = Vector[0,  0,  0]
    for sommet in face
      directionface += sommet
    end
    return directionface
  end
  
  
  # produit scalaire entre un vecteur et un angle
  def dotproduct(vecteur, angle)
    return vecteur[0] * Math.cos(rotation) + vecteur[1] * Math.sin(rotation)
  end
  
  
  def draw_triangle(t, color)
    # at first sort the three vertices by y-coordinate ascending so v1 is the topmost vertice
	vertices = [[t.x1, t.y1], [t.x2, t.y2], [t.x3, t.y3]]
	vertices.sort! { |vertex1, vertex2|  vertex1[1] <=> vertex2[1] }
	v1 = vertices[0]
	v2 = vertices[1]
	v3 = vertices[2]

    # here we know that v1.y <= v2.y <= v3.y
    # check for trivial case of bottom-flat triangle
    if v2[1] == v3[1]
      fillBottomFlatTriangle(v1, v2, v3, color)
    # check for trivial case of top-flat triangle
    elsif v1[1] == v2[1]
      fillTopFlatTriangle(v1, v2, v3, color)
    else
      # general case: split the triangle in a topflat and bottom-flat one 
      v4 = [(v1[0] + ((v2[1] - v1[1]).to_f / (v3[1] - v1[1]).to_f) * (v3[0] - v1[0])).to_i,           v2[1]]
      fillBottomFlatTriangle(v1, v2, v4, color)
      fillTopFlatTriangle(v2, v4, v3, color)
    end
  end
  
  
  # remplir le demi-triangle dont le bas est plat
  def fillBottomFlatTriangle(v1, v2,  v3, color)
	invslope1 = (v2[0] - v1[0]).to_f / (v2[1] - v1[1]).to_f
	invslope2 = (v3[0] - v1[0]).to_f / (v3[1] - v1[1]).to_f

	curx1 = v1[0]
	curx2 = v1[0]

	for scanlineY in v1[1]..v2[1]
      # drawLine(curx1, scanlineY, curx2, scanlineY)
	  width = curx2 - curx1
	  height = 1
	  # fill_rect(x, y, width, height, color)
	  self.bitmap.fill_rect(curx1, scanlineY, width, height, color)
	  
      curx1 += invslope1
      curx2 += invslope2
    end
  end
  
  
  # remplir le demi-triangle dont le haut est plat
  def fillTopFlatTriangle(v1, v2, v3, color)
    invslope1 = (v3[0] - v1[0]).to_f / (v3[1] - v1[1]).to_f
    invslope2 = (v3[0] - v2[0]).to_f / (v3[1] - v2[1]).to_f

    curx1 = v3[0]
    curx2 = v3[0]

	# il y aura pê un problème ici, car la ligne est pê à l'envers
    for scanlineY in v1[1]..v3[1]
      # drawLine(curx1, scanlineY, curx2, scanlineY)
      width = curx2 - curx1
      height = 1
      # fill_rect(x, y, width, height, color)
      self.bitmap.fill_rect(curx1, scanlineY, width, height, color)
      curx1 -= invslope1;
      curx2 -= invslope2;
    end 
  end
  
  
end

Avatar du membre
Roi of the Suisse
Messages : 2107
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 17 févr. 2023, 12:08

Voilà ce que ça donne :

Image

Avatar du membre
Roi of the Suisse
Messages : 2107
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 17 févr. 2023, 12:29

Image

Avatar du membre
trotter
Messages : 1688
Enregistré le : 09 juil. 2019, 19:38

Re: Kujira no Hara

Message par trotter » 17 févr. 2023, 22:29

Tonsillolithe ?

Avatar du membre
Roi of the Suisse
Messages : 2107
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 18 févr. 2023, 09:52

Berk nan.
C’est juste un triakitétraèdre tronqué parce que j’aime bien les triakitétraèdres tronqués.

Avatar du membre
Nemau
Administrateur du site
Messages : 837
Enregistré le : 28 avr. 2019, 14:40

Re: Kujira no Hara

Message par Nemau » 18 févr. 2023, 16:45

(un ballon de foot quoi :edente: )

Woh. T'as écrit le script toi-même ? Ça marche comment, le moteur colore des surfaces de l'écran en fonction de certains paramètres ?

Le saviez-tu ? La triforce dans l'intro de ALttP est en vraie 3D, de même pour les cristaux qui tournent quand on délivre les descendantes des sept sages.

Avatar du membre
Roi of the Suisse
Messages : 2107
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 19 févr. 2023, 19:43

Non un ballon de foot c’est un icosaèdre tronqué, pas un triakitétraèdre tronqué. Tu ne connais rien au foot ma parole !
:king:

Bah euh le script est simple : je note les coordonnées x y z de chaque sommet de l’objet, puis je découpe les faces en triangles, je projette les triangles sur l’écran avec un produit scalaire et voilà.
Pour la couleur de chaque face, c’est encore un produit scalaire, cette fois-ci entre la perpendiculaire de chaque face et le vecteur "lumière" (qui indique la direction de la lumière).
C’est rare qu’on utilise un produit scalaire ou un produit vectoriel dans la vie de tous les jours, mais là c’est le cas.

Oué bah pour Zelda je pense qu’ils ont exactement écrit le même script.

Avatar du membre
Roi of the Suisse
Messages : 2107
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 19 févr. 2023, 22:52

:fgr: Je peux aussi faire des objets simples :

Image

Erf il y a un petit bug sur une face qui s'affiche quand il ne faut pas et qui ne s'affiche pas quand il faudrait :pwned:

Avatar du membre
Roi of the Suisse
Messages : 2107
Enregistré le : 28 avr. 2019, 23:38
Contact :

Re: Kujira no Hara

Message par Roi of the Suisse » 20 févr. 2023, 13:01

Spoiler de la fin du jeu
Spoiler
Afficher
Image

Image

Répondre