ArkaLouReeD - Le légendaire casse briques

Bonsoir,

Merci JoyeuxNoël ! En effet il me faut revoir la partie "rebond raquette", sur une autre version j'y suis mieux arrivé...
Pour ce qui est de la vitesse et de l'angle de départ, dans cette version de test elle est aléatoire

 A = Int(Rnd * 71) + 10 ' un angle au choix entre 10° et 80° compris par pas de 1°
 V = (Int(Rnd * 5) + 1) * 5 ' vitesse entre 5 et 25 pixels sur le vecteur angulaire

Mais sinon dans la version finale l'angle sera de 30° avec une vitesse 5 !

J'ai remarqué également des "arrêts" sur le déplacement, je pensais que c'était du à ma machine qui date de 2013... Il faut peut-être que je sois moins gourmand en ressource et n'afficher que 20 images secondes... Pourtant pour ce qui est des calculs, je mets les données en mémoire afin de faire les tests en mémoire vive pour accélérer le processus, va falloir que je simplifie encore tout ceci peut-être... Surtout avec l'affichage des gifs animés !

Bon au niveau du code il y a de la "factorisation" à faire !

Mais comme vous dites cela reste acceptable pour le moment, et je n'ai pas trouver sur Excel un équivalent... Mais mes recherches n'ont pas étaient poussées !

@ bientôt

LouReeD

Bonsoir,

Configuration 7 : Pas d'impact au point 1 et 3 et un impact au point 2 :

l'impact de la balle dans la configuration 7 dépend de l'angle de sa trajectoire :

Si l'angle est inférieur à 45° alors il faudra calculer le Ca (déplacement en vertical) puis ensuite en déterminer le Co afin de remettre la balle sur sa trajectoire. Il y aura donc impact en Y donc on aura Dy = -Dy. Si l'inverse est fait alors la balle peut se retrouver "vraiment" loin de l'impact :

arkanoid explications20

Si l'angle est supérieur à 45° alors il faudra calculer le Co en premier et déterminer le Ca correspondant afin de remettre la balle sur sa trajectoire. Il y aura donc impact en X donc on aura Dx = -Dx. Si l'inverse est fait, là encore, la balle peut se retrouver loin du point d'impact :

arkanoid explications19

Dans cette configuration on distingue un léger décalage entre la balle et la brique, mais celui-ci dans le mouvement du jeu ne sera pas perceptible, je pense.

Si l'angle est égal à 45° alors if faut comparer les distance "de pénétration" des composantes du point 2 :

Si P2x > P2y alors on cherchera le Ca, et on déterminera le Co correspondant, il y aura rebond en Y : Dy = -Dy.

Si P2x < P2y alors on cherchera le Co, et on déterminera le Ca correspondant, il y aura rebond en X : Dx = -Dx.

Si P2x = P2y alors on pourra soit commencer par le Ca ou le Co et déterminer "l'opposé" correspondant afin de remettre la balle sur sa trajectoire. Dans ce cas la balle ne sera pas forcément en contact avec la brique. On pourrait alors utiliser ce que j'ai fait dans le fichier fourni plus haut, c'est à dire mettre la balle en contact avec la brique quelque soit sa trajectoire. On utilisera le SIN(45°) dans les calcul afin de positionner la balle au contact de l'angle de la brique. On aura alors Dx = - Dx et Dy = -Dy.

Configuration 8 et 9 : Impact au point 1 et 3 et un impact ou pas au point 2 :

Il me reste cette étude à faire, mais à première vu il faudra là aussi faire une comparaison de "pénétration" des points 1 et 3 tout en se basant sur l'angle de la trajectoire. En effet avec une trajectoire plutôt verticale (<45°) la balle aura un impact sur le coté haut en premier que le coté droit, et inversement avec un angle >45°. Dans cette configuration le seul moment où la balle va toucher les deux briques en même temps c'est quand elle aura une trajectoire de 45°. Ce dernier cas est donc facile à gérer, il suffira de placer la balle de façon à ce que sa partie haute soit au niveau bas de la brique du point 1 et sa partie droite devra être à gauche de la brique du point 3.

Je vous rassure, une fois toutes ces études faites sur les points d'impact de la balles sur les briques et la réaction de cette dernière qui en découle, le reste devrait être plus simple... Mis à part les déplacements des monstres....

@ bientôt

LouReeD

Bonsoir,

je n'ai pas encore fait les dessins de la configuration 8 et 9...

Par contre ci dessous une partie du code de gestion du déplacement des balles :

' on boucle sur le nombre de balle en jeu
For I = 1 To NbBalleMax

    ' si la balle est en jeu
    If Balle(I).Visible = True Then

        ' reprise de ses positions dans des variables temporaire afin de tester les différentes positions virtuelles jusqu'à la position finale.
        BLeftO = Balle(I).Left
        BTopO = Balle(I).Top

        ' boucle des itérations
        For J = 1 To 10

            ' calcul de la première position fictive
            BLeft = BLeftO + Dx * ((Tx / 10) * J)
            BTop = BTopO + Dy * ((Ty / 10) * J)

            ' avec cette position on calcul les composantes des coordonnées des points remarquables P1, P2, P3 et P4 où
            ' Db = diamètre de la balle, comme cela on peut aussi jouer sur son diamètre avec une capsule supplémentaire...
            ' Ox et Oy correspondent au décalage en X et Y du coin supérieur gauche de la zone de jeu
            ' Marge = la zone de jeu sans brique sur le haut du tableau
            ' LBrik = largeur des briques
            ' HBrik = hauteur des briques

            P1x = BLeft
            P1y = BTop
            P2x = BLeft + Db
            P2y = BTop
            P3x = BLeft + Db
            P3y = BTop + Db
            P4x = BLeft
            P4y = BTop + Db

            ' on initialise les variables Impact à faux
            Impact1 = False
            Impact2 = False
            Impact3 = False
            Impact4 = False

            ' détermination des imapacts pour ces quatre points
            Cb1 = Int(((P1x - Ox) / LBrik)) + 1
            Lb1 = Int(((P1y - Oy - Marge) / HBrik)) + 1
            Cb2 = Int(((P2x - Ox) / LBrik)) + 1
            Lb2 = Int(((P2y - Oy - Marge) / HBrik)) + 1
            Cb3 = Int(((P3x - Ox) / LBrik)) + 1
            Lb3 = Int(((P3y - Oy - Marge) / HBrik)) + 1
            Cb4 = Int(((P4x - Ox) / LBrik)) + 1
            Lb4 = Int(((P4y - Oy - Marge) / HBrik)) + 1

            ' si le point repère 1 de la balle arrive bien en zone de brique et qu'il y a une brique alors il y a impact
            If Lb1 >= 1 And Lb1 <= 16 And Cb1 >= 1 And Cb1 <= 13 And TabBrik(Lb1, Cb1) <> "" Then Impact1 = True

            ' si le point repère 2 de la balle arrive bien en zone de brique et qu'il y a une brique alors il y a impact
            If Lb2 >= 1 And Lb2 <= 16 And Cb2 >= 1 And Cb2 <= 13 And TabBrik(Lb2, Cb2) <> "" Then Impact2 = True

            ' si le point repère 3 de la balle arrive bien en zone de brique et qu'il y a une brique alors il y a impact
            If Lb3 >= 1 And Lb3 <= 16 And Cb3 >= 1 And Cb3 <= 13 And TabBrik(Lb3, Cb3) <> "" Then Impact3 = True

            ' si le point repère 4 de la balle arrive bien en zone de brique et qu'il y a une brique alors il y a impact
            If Lb4 >= 1 And Lb4 <= 16 And Cb4 >= 1 And Cb4 <= 13 And TabBrik(Lb4, Cb4) <> "" Then Impact4 = True

            ' détermination des tests à faire en fonction de la direction de la balle

            '********************************************************************************
            ' reste cette partie qui correspond aux différentes configurations vues plus haut
            '********************************************************************************

            ' au "retour" de ces test la variable Rebond sera soit à True soit à False en fonction qu'il y a eu un impact ou pas
            ' si rebond on sort de la boucle des itérations de position
            If rebond = True Then
                ' on affiche la balle à la position du rebond
                Balle(I).Left = Nx
                Balle(I).Top = Ny
                ' on sort de la boucle
                Exit For
            End If

        Next J

    End If

    ' s'il n'y a pas eu de rebond on affiche la balle à la position calculée prévue par le déplacement
    If Not rebond Then
        Balle(I).Left = Balle(I).Left + Dx * Tx
        Balle(I).Top = Balle(I).Top + Dy * Ty
    End If

Next I

Entre les "*" la grosse partie du code de test. Je suis en train d'essayer de "mutualiser" les codes de test du fichier fourni plus haut afin de simplifier tout cela.
En effet, en y regardant de plus près il y a beaucoup de chose en commun dans les différents module de test, Par exemple le premier test :

                If Impact1 And Not Impact2 And Not Impact3 Then
                    Dy = -Dy
                    Rebond = True
                    Ca = Abs((RY + 40 + Lb1 * 10) - P1y)
                    Co = Abs((Ca / Tx) * Ty)
                    Ny = Int(P1y + Ca)
                    Nx = Int(P1x - Co)
                    Balle.Left = Nx
                    Balle.Top = Ny
                    TableauBriques(Lb1, Cb1) = ""
                    ActiveSheet.Shapes(Lb1 & "-" & Cb1).Delete ' ok

est très proche du premier test pour une direction de balle différente :

                If Not Impact1 And Impact2 And Not Impact4 Then
                    Dy = -Dy
                    Rebond = True
                    Ca = Abs((RY + 40 + Lb2 * 10) - P2y)
                    Co = Abs((Ca / Tx) * Ty)
                    Ny = Int(P2y + Ca)
                    Nx = Int(P1x + Co)
                    Balle.Left = Nx
                    Balle.Top = Ny
                    TableauBriques(Lb2, Cb2) = ""
                    ActiveSheet.Shapes(Lb2 & "-" & Cb2).Delete ' ok

Et ce 4 fois... Alors que j'ai "réussie" à les simplifier de cette manière :

' Calcul de Ca en fonction de Dx
If Dx < 0 Then Ca = Abs((RY + 40 + Lb1 * 10) - P1y) Else Ca = Abs(P3y - (RY + 40 + (Lb3 - 1) * 10))

' dans tous les cas calcul de Co
Co = Abs((Ca / Tx) * Ty)

' les nouvelles coordonnées
Ny = Int(P1y - (Dy * Ca))
Nx = Int(P1x - (Dx * Co))

' par ce calcul on détermine la direction de la balle
Vecteur = Dx + (2 * Dy)

' en fonction de la direction on supprime la bonne brique
Select Case Vecteur
    Case -3
        TabBrik(Lb1, Cb1) = ""
        ActiveSheet.Shapes(Lb1 & "-" & Cb1).Delete
    Case -1
        TabBrik(Lb2, Cb2) = ""
        ActiveSheet.Shapes(Lb2 & "-" & Cb2).Delete
    Case 1
        TabBrik(Lb3, Cb3) = ""
        ActiveSheet.Shapes(Lb3 & "-" & Cb3).Delete
    Case 3
        TabBrik(Lb4, Cb4) = ""
        ActiveSheet.Shapes(Lb4 & "-" & Cb4).Delete
End Select

' il y a eu rebond en vertical donc en Y
Dy = -Dy
Rebond = True

Reste plus qu'à mutualiser les 4 fois autre modules de test et comme cela le code sera diminuer par 4...

@ bientôt

LouReeD

Bonsoir,

Ci dessous la partie de code de gestion de déplacement de la raquette et la gestion des flammes, avec un module dans la boucle de jeu, et une partie dans le code de la feuille pour le contrôle ActiveX :

' partie dans le code de la feuille
Private Sub BG_RaqDir_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    PosRaq = X
End Sub

' partie de code dans la boucle de jeu
' on fixe la valeur de la position de la souris
PosXRaq = Int(PosRaq)

' on rectifie cette valeur pour rester dans le cadre du jeu
If PosXRaq <= 100 + Int(Raquette.Width / 2) Then
    PosXRaq = Ox
    DDep = 0
ElseIf PosXRaq >= 490 - Int(Raquette.Width / 2) Then
    PosXRaq = Ox + 390 - Int(Raquette.Width)
    DDep = 0
Else
    PosXRaq = Ox + PosXRaq - 100 - Int(Raquette.Width / 2)
    DDep = 0
End If

' calcul du delta vitesse de la raquette
NDEP = PosXRaq

' cette valeur donne une indication sur le déplacement de la raquette 0= arrêt, <0 déplacement vers la gauche, >0 déplacement vers la droite
' elle permet le "lift" de la balle en fonction du sens et de la vitesse
DDep = NDEP - ADEP

' on met en mémoire cette ancienne valeur
ADEP = PosXRaq

If Raquette.Left > PosXRaq Then
    Raquette.Left = PosXRaq
    Call Flamme(False, True)
ElseIf Raquette.Left < PosXRaq Then
    Raquette.Left = PosXRaq
    Call Flamme(True, False)
Else
    Raquette.Left = PosXRaq
    Call Flamme(False, False)
End If

Les variables DDep NDep et ADep sont utilisées pour connaître le delta de déplacement de la raquette pour les futurs effets de "lift" et de "coupé".

@ bientôt

LouReeD

Bonsoir,

Ce soir on rentre un peu plus dans le code ! Quelque part c'est plus simple il n'y a pas de schéma à faire !

Etude pour les capsules bonus

Lorsqu'une brique est détruite, on lance un tirage au sort afin de savoir si cette dernière produit une capsule bonus ou pas. Si elle n'en produit pas alors le code continue, si elle en produit une alors on lance la procédure de création de capsule. Cette procédure n'est lancé que s'il y a une seule balle en jeu, en effet lors du multi-balle il n'y a pas de bonus à tomber.

Pour créer une capsule il faut connaître :

  • son type, là encore c'est un tirage au sort entre les différentes possibilités
  • sa position : elle correspond à la position "centrée" de la brique détruite.

Pour cela on crée un Shape de type Picture afin d'y intégrer un gif animé représentant le type de capsule. A chaque tour de la boucle de jeu, on déplace ce shape de 20 px (quantité à vérifier lors des tests) vers le bas. Lorsqu'il arrive en bas on le supprime. Si lors de sa descente il croise la raquette du joueur alors il faudra gérer les éventuelles modification de raquette et réaction de cette dernière.

Le code de création d'une capsule :

Sub CréaCaps(Cb, Lb)
  ' où Cb et Lb correspondent à la colonne et la ligne de la brique détruite dans le tableau TabBrik
  ' tirage au sort du type de capsule, il ne peut pas y avoir une démultiplication s'il y a plus de une balle en jeu
  ' CréaCaps ne sera appelée qui si le flag Bonus est à True
  TypBon = Int(RND * 8)) + 1
  Set BonusPic = ActiveSheet. Pictures.Insert("Système\" & TypBon & ".gif")
  With BonusPic
    .Name = "Bonus" & TypBon
    .Left = Ox+ Cb*20 + 5
    .Top = Oy + Marge + Lb + 2
    .Placement = xlfreeflaoting
  End With
End Sub

Ce code est lancé ponctuellement. Dans la boucle de jeu il faut mettre en place la routine de gestion de ces bonus :

For Each Capsule in ActiveShapes
  With Capsule
    If Left(.Name, 5) ="Bonus" then
      ' s'il y a contact avec la raquette
      If .Left >= Raquette.Left And .Right+ 30 <= Raquette.Left + Raquette.Width And  .Top >= Raquette.Top -20 and . Top <= Raquette.Top + 20 Then
        ' code pour valider l'interception du bonus
        Call QuelBonus(Right(.name,1))
        ' on efface la capsule
        .Delete
      ElseIf .Top >= 400 Then ' valeur 400 à vérifier
        .Delete
      End If
    End If
  End With
Next Capsule

Reste plus qu'à coder la procédure QuelBonus qui reçois en paramètre la lettre correspondant au type de bonus intercepté. En fonction de ce paramètre les actions au niveau du jeu seront différentes :

Sub QuelBonus (TypBon as String)
  Dim Rtop, Rleft
  ' quelque soit le type de bonus on met la raquette à jour et on incrémente le compteur de point
  ' on efface la raquette actuelle en gardant en mémoire ses caractéristiques
  With Raquette
    Rtop = .Top
    Rleft = .Left
    .Delete
  End With
  Set Raquette = ActiveSheet.Pictures.Insert("Système\R" & TypBon & ".png")
  With Raquette
    .Top = Rtop
    .Left = Rleft
  End With
  ' on incrémente le compteur de point
  Points = Points + 100
  ' tous les bonus font perdre les flags en cours
  Laser = False
  Capture = False
  ' en fonction du type des actions supplémentaires et différentes sont à exécuter
  Select Case TypBon
    Case "L" ' type laser
      ' mise en marche du flag laser
      Laser = True
    Case "C" ' type capture
      ' mise en marche du flag capture
      Capture = True
    Case "G" ' type grande raquette
      ' rien ne change pour celle-ci
    Case "V" ' type Vie
      ' on incrémente le nombre de vie Spare si inférieur à 5
      If VieSpare <5 Then VieSpare = VieSpare +1
      ' on affiche cette nouvelle vie Spare
      VieSparePic(VieSpare).Visible
    Case "D" ' type démultiplication
      Bonus = False ' on passe le flag "Bonus" à faux afin d'empêcher l'apparition de capsules lors du multi balle
      For I=2 to 3
        With Balle(I)
          .Left = Balle(1).Left
          .Top = Balle(1).Top
          .A = Int(Rnd*89)+1
          .V = Int(Rnd*5)+1)*5
          .Tx = ABS(V * SIN(A * 4 * ATN(1)/180))
          .Ty = ABS(V * COS(A * 4 * ATN(1)/180))
          .Dx = Balle(1).Dx
          .Dy = Balle(1).Dy
        End With
      Next I
      Multi = 3
    Case "B" ' type Balle qui ralentie
      For I = 1 to Multi
        If Balle(I).V > 10 Then Balle(I).V = 10
      Next I
    Case "S" ' type accès niveau suivant
      ' on affiche la porte de téléportation
      TeleportPic.Visible = True
      Teleport = True
  End Select
End Sub

Etude de la gestion des différentes balles en jeu :

Lors du jeu en simple balle, la balle est Balle(1). Lors d'un multi balle les balles sont repérées de Balle(1) à Balle(3). En fonction des balles perdue, il se peut que la balle restante soit Balle(3). Hors c'est incompatible avec le fonctionnement du code. C'est pourquoi il y a une routine de réduction du tableau de ces balles afin d'avoir uniquement Balle(1) pour une balle, Balle(1) et Balle(2) pour un jeu à deux balles et Balle(1), Balle(2) et Balle(3) pour trois balles.
Le code de réduction est le suivant :

For I = 1 to Multi - 1
  If Balle(I).Visible = False Then
    With Balle(I)
      .Left = Balle(Multi).Left
      .Top = Balle(Multi).Top
      .A = Balle(Multi).A
      .V = Balle(Multi).V
      .Tx = Balle(Multi).Tx
      .Ty = Balle(Multi).Ty
      .Dx = Balle(Multi).Dx
      .Dy = Balle(Multi).Dy
    End With
    ' si la Balle(Multi) est transférée sur une autre alors on la rend "perdu" = invisible
    Balle(Multi).Visible = True
    Exit For
  End If
Nect I
Multi = Multi -1

Le principe : on boucle sur le nombre de balle - 1, si on en trouve une qui est perdue (Visible = False) alors on prend la balle du plus grand index qui vaut Multi et on transfère ses données. Si lors de la boucle on ne trouve pas de balle perdue alors c'est que la balle perdue a pour index Multi. Dans tous les cas une fois la boucle lancée, on passe multi à Multi - 1.
Cette procédure ne sera lancée que lors d'une perte de balle et que Multi > 1.

Etude pour les laser

Tout comme pour les Capsules, il nous faut créer une procédure de création de Laser. Ces laser sont tirés par deux et la cadence de tir est limitée, par contre il n'y a pas de limite d'utilisation, tant que la raquette laser est en jeu on peut tirer.
Lors de l'appuis de la touche de commande de feu, à condition d'être en mode laser et être dans une phase de cadence de tir, cette procédure est lancée :

Sub CréaFeu
  Dim LaserPic as Picture
  ' création du laser de gauche
  Set LaserPic = ActiveSheet.Pictures.Insert("Système\Laser.png")
  With LaserPic
    .Left = Raquette.Left + 17
    .Top = Raquette.Top - 15
    .Name ="Laser"
    .Placement = XlFreeFlaoting
  End With
  ' création du laser de droite
  Set LaserPic = ActiveSheet.Pictures.Insert("Système\Laser.png")
  With LaserPic
    .Left = Raquette.Left + Raquette.Width - 17
    .Top = Raquette.Top - 15
    .Name ="Laser"
    .Placement = XlFreeFlaoting
  End With
End Sub

Dans la boucle de jeu il faut mettre une gestion de ces laser :

For Each Laser in ActiveShapes
  With Laser
    If Left(.Name, 5) ="Laser" Then
      ' on fait monter le laser de 30 pixels valeur à vérifier
      .Top =.Top -30
      If .Top <= 20 Then ' s'il arrive en haut du tableau de jeu, on l'efface
        .Delete
      Else
        ' on cherche s'il y a collision avec une brique, on transforme ses coordonnées en colonne/ligne pour comparer avec le tableau TabBrik
        Cl = Int(((.Top - Ox) / LBrik)) + 1
        Ll = Int(((.Left - Oy - Marge) / HBrik)) + 1
        If TabBrik(Ll,Cl) <> 9 Then
          TabBrick(LL,Cl) = ""
          ActiveSheet.Shapes(Ll & " -" & Cl).Delete
          Points = Points +2
        End If
      End If
    End If
  End With
Next Laser

Pour ce qui est de la cadence de tir pour les rafales, un petit compteur est mis en place, il s'incrémente de 1 à chaque tour de la boucle principale. Cette dernière est cadencée à 25 images secondes, donc si nous voulons accorder une cadence de 5 tir par seconde, il faut que le tir soit accordé toutes les 5 images, le compteur ira donc de 1 à 5. Ce compteur aura pour nom CptTir et le flag autorisation de tir TirLaser, la boucle ressemblera à ceci :

CptTir = CptTir +1
If CptTir > 4 Then
  CptTir = 0
  TirLaser = True
End If

L'appel du tir se fera par surveillance d'action sur une touche du clavier et sera codé comme ceci :

Si appuis sur la touche Tir ET que Mode Laser = true et TirLaser = True then Call CreaFeu : TirLaser = False

On voit ici le passage du flag TirLaser à Faux afin de ralentir la cadence de tir.

Fusion des boucles de tests sur les Shapes

Nous voyons ici qu'il y a deux boucles de test sur des Shapes Pictures, dont certaines se nomme "Bonus" et d'autre "Laser". Pour simplifier le code et augmenter les performances, nous pouvons fusionner ces deux boucles afin de ne tester qu'une fois l'ensemble des Shapes :

For Each Sh in ActiveShapes
  With Sh
    ' test si c'est un Laser
    If Left(.Name, 5) ="Laser" Then
      ' on fait monter le laser de 30 pixels
      .Top =.Top -30
      If .Top <= 20 Then ' s'il arrive en haut du tableau de jeu, on l'efface
        .Delete
      Else
        ' on cherche s'il y a collision avec une brique, on transforme ses coordonnées en colonne/ligne pour comparer avec le tableau TabBrik
        Cl = Int(((.Top - Ox) / LBrik)) + 1
        Ll = Int(((.Left - Oy - Marge) / HBrik)) + 1
        If TabBrik(Ll,Cl) <> 9 Then
          TabBrick(Ll,Cl) = ""
          ActiveSheet.Shapes(Ll & " -" & Cl).Delete
          Points = Points +2
          .Delete
        End If
      End If
    ' test si c'est un capsule
    ElseIf Left(.Name, 5) ="Bonus" Then
      ' s'il y a contact avec la raquette
      If .Left >= Raquette.Left And .Right+ 30 <= Raquette.Left + Raquette.Width And  .Top >= Raquette.Top -20 and . Top <= Raquette.Top + 20 Then
        ' code pour valider l'interception du bonus
        Call QuelBonus(Right(.Name,1))
        ' on efface la capsule
        .Delete
      ElseIf .Top >= 400 Then
        .Delete
      End If
    End If
  End With
Next Sh

On peut imaginer y intégrer le test de collision des monstres avec une des balles en jeu et la raquette en ajoutant un :

ElseIF Left(.Name, 5) = "Monst" Then

Comme vous pouvez le voir, les différents module du code se mettent "gentiment" en place. Par la même occasion il apparaît certaine variable. mais ce n'est pas grave, tout ceci devrait rentrer dans l'ordre au fur et à mesure de l'écriture... Enfin je l'espère !

@ bientôt

LouReeD

Bonsoir,

ce soir une chose très simple et que j'aurais du donner en premier, c'est le descriptif des actions à mener dans la boucle principale du jeu !

En avant dernière la voici !

'*************************************************
'* Structure type de la boucle principale de jeu *
'*************************************************

' on ne sait pas combien de fois la boucle va
' tournée lors d'une partie, on utilisera donc une
' boucle indéfinie Do Loop.
' il faudra juste gérer la sortie, par exemple,
' avec une variable Perdu booleen :
' Si Perdu = True on sort de la boucle
' Le principe d'une telle boucle est commun à tous
' les jeux : le programme gère à chaque "Tempo" tous
' les éléments les un après les autres
' c'est la rapidité de calcul qui fait que chaque
' élément à l'air d'être géré individuellement...

Do

    '*******************************************************
    ' avant tous calculs on met en mémoire le temps horloge
    ' afin de gérer la jouabilité
    Tempo = Timer

    '*******************************************************
    ' ici le code de gestion de déplacement de la raquette
    ' en effet avant tout test sur les collision de la balle
    ' on donne la main au joueur pour placer sa raquette
    ' à ce moment la position de la raquette est considérée
    ' comme fixe mais un paramètre de "lift" indique sa
    ' direction et sa vitesse

    '*******************************************************
    ' ici on calcule les données nécessaire pour la recherche
    ' des éventuelles collision de la balle avec les briques
    ' par le système de déplacement par "itération"

    '*******************************************************
    ' ici on regarde les rebonds éventuels avec les limites
    ' de la zone de jeu s'il n'y a pas eu de rebond avec
    ' les briques

    '*******************************************************
    ' ici on regarde les éventuelles collision de la balle
    ' avec les monstres s'il n'y a pas eu de rebond avant

    '*******************************************************
    ' ici on regarde les rebonds éventuels avec la raquette
    ' s'il n'y a pas eu de rebond précédemment

    '*******************************************************
    ' gestion de déplacement des éventuelles capsules en jeu
    ' et gestion des réactions à déclencher.
    ' gestion des éventuels laser tirés et réaction en cas
    ' de touche avec une brique ou un monstre.
    ' gestion des éventuels monstres et de leur impact avec
    ' la balle ou la raquette du joueur.

    '*******************************************************
    ' mise à jour des différents éléments du jeu à l'écran
    ' Score etc...

    '*******************************************************
    ' temporisation pour la jouabilité :
    ' on fait de façon à ce que chaque boucle de jeu dure à
    ' minima 1/25 seconde, ce qui fait un affichage de
    ' 25 images par secondes
    ' l'avantage c'est que l'affichage ne dépend pas de la
    ' puissance de la machine : même si les calculs et mise
    ' à jour se font vite, la boucle prochaine ne sera
    ' lancée qu'une fois la tempo écoulée.
    ' si au contraire les calculs se font lentement alors le
    ' jeu sera ralenti mais au juste nécessaire

    Do
        ' boucle de jouabilité à 25 images par secondes
        ' tant que tempo + 0.04 seconde est supérieur à Timer
        ' alors on boucle sinon le jeu serait trop rapide
        DoEvents ' permet de "rendre la main" à l'application
                ' le jeu n'est pas figé
    Loop While Tempo + 0.04 > Timer

    ' test de fin de partie,
    ' si c'est le cas on sort de la boucle
    If Perdu Then Exit Do

Loop

@ bientôt

LouReeD

Bonsoir,

Ca y est ! J'ai fait le graphique pour la configuration 8 et 9 qui en fait n'en font qu'une car le fait qu'il y ait deux briques en diagonale, le fait qu'il y ait une brique ou pas au point 2 ne change rien car elle ne peut être atteinte par la balle.

Configuration 8 et 9 : Impact au point 1 et 3 et un impact ou pas au point 2 :

Comme annoncé plus haut, la réaction de la balle (ou plutôt du code) va dépendre de l'angle de la trajectoire et ceci toujours en fonction de l'angle de 45°.
Le seul moment où les points 1 et 3 entre en contactent avec leur briques respectives en même temps est lorsque la trajectoire à un angle de 45°.
A ce moment là il suffit de déplacer la balle au contact des deux briques et d'inverser les deux directions.

Pour les angles inférieurs et supérieurs à 45° en fait la balle touche une brique avant l'autre et il suffit alors de calculer le Ca pour trouver le Co et inversement.

arkanoid explications21

Sur l'image on voit bien que pour un angle de plus de 45° il faut commencer par décaler en Ca puis trouver le Co pour revenir sur la trajectoire, si l'inverse est fait une fois les deux calculs fait on se retrouve avec une balle à cheval sur la brique violette.
Du coup pour un angle inférieur à 45° c'est bien le Co que l'on calcul et le Ca que l'on détermine afin de revenir sur la trajectoire. Dans les deux cas il se peut que la balle ne soit pas en contact direct avec la brique mais on voit bien qu'il n'y a pas de touche simultanée, donc même si le jeu semble montrer le contraire en fait la balle va faire deux touches consécutives rapprochées et non pas une seule.

Donc maintenant avec toutes ces études, les différentes configurations de rebond on été travaillées ! il ne reste plus qu'à coder tout ceci et le multiplier par 4 vu qu'il y a 4 directions. Mais comme dit plus haut vu que les structures de raisonnement sont semblables il est peut-être possible de fusionner les groupes de calculs qui se ressembles.

Il reste donc à gérer les rebonds avec les bords du jeu : 4 cotés à gérer et éventuellement de doubles cotés pour les angles en haut à droite et à gauche.
Il reste à gérer le rebond sur la raquette qui a pour principe : un rebond sur la partie droite de la raquette alors que la balle va vers la gauche renvoie la balle vers la droite et inversement pour le coté gauche. Ceci si la raquette se déplace très peu.

Si la même touche est faite alors que la raquette se déplace vers la gauche avec une vitesse remarquable, alors le rebond n'est pas inversé, et l'angle est accentué, c'est l'effet lift, sa vitesse sera augmentée. L'inverse est vrai pour la partie gauche.

Si la même touche est faite alors que la raquette se déplace vers la droite avec une vitesse remarquable, alors le rebond sera inversé et l'angle sera diminué c'est l'effet coupé, sa vitesse sera diminuée également. L'inverse est vrai pour la partie gauche.

Si la balle va vers la gauche et qu'elle rebondi sur la partie gauche de la raquette alors elle rebondi avec un angle identique sans changer de direction horizontale si la raquette à une vitesse normale. Il en est de même pour l'inverse.

En cas de vitesse remarquable de la raquette l'effet lift et coupé seront appliqués

Il reste également la gestion de déplacements des monstres et leur collision avec les balles et la raquette... Il se peut que je fasse l'impasse sur ce domaine.

@ bientôt

LouReeD

Bonsoir,

je me suis mis en tête alors que le codage n'est pas fini de faire des effets de transition entre les différentes raquettes !

Voici les deux raquettes normales petite et grande :

rne ren

Pour voir et revoir l'effet il faut cliquer sur le lien du message afin de mettre à jour la page en étant sur le bon message...
En effet l'effet n'est pas répétitif ! Il ne marche qu'une fois dans le Gif animé !

@ bientôt

LouReeD

Bonjour,

nouvelle idée = nouveau problème !
Lors de la transformation de la raquette en petit ou en grand, le déplacement de cette dernière est autorisé mais les flammes ne la touche plus !
En effet la petite raquette comporte une zone invisible pour permettre l'agrandissement sans changement de hauteur !
donc aujourd'hui je change l'idée des Gif animés pour passer à des images Png.

L'idée est de changer l'image de la raquette tous les x tours de la boucle principale : cette dernière est cadencée à 25 images par secondes, la raquette se transforme en 8 images et cette transformation dure 1 seconde. Donc si on prend en repère 24 images secondes, il y a transformation de la raquette toutes le 3 images.

Comme pour la cadence de tir de laser, je vais mettre en place un compteur qui permettra toutes les trois images de modifier celle de la raquette pour aller vers l'agrandissement ou l'inverse. Les flammes seront donc toujours au bord des limites de l'image en cours, le joueur pourra toujours déplacer la raquette, tout sera "transparent" !

En écrivant ces lignes je me rend compte qu'il me manque des animations ! De la grande vers le laser ou la capture et inversement !

Faut que j'y aille !

@ bientôt

LouReeD

Bonjour,

après réflexion et début de dessin pour les transformations une idée de simplification m'est venue et je vais l'adopter :
Pour aller de la grande raquette vers le laser, elle passera par la petite raquette qui a son tour se transformera en laser. Et si l'inverse devait de produire alors le laser ira vers la petite raquette qui à son tour se transformera en grande raquette. Il va en être de même pour la raquette capture. Idem pour aller de la capture vers le laser et inversement. Bref vous l'avez compris, comme j'ai dessiné les transformation depuis et vers la raquette "normale" alors les transformations "transverses" passeront par la raquette normale ! C'est plus simple pour moi, reste plus qu'à le coder...

@ bientôt

LouReeD

Bonsoir,

j'ai commencé à travailler sur le déplacement des monstres. Pour commencer j'ai analysé des vidéos pour les comprendre. En fait c'est simple : sur la partie supérieur du tableau de jeu, les monstres n'ont qu'une idée en tête c'est d'aller vers le bas par le chemin "le plus court" sans se superposer aux briques. Donc ils se promènent de gauche à droite à la recherche d'une brèche en direction du bas, une fois trouvée ils la suivent même si elle mène nulle part.
Une fois plus de la moitié de l'écran de jeu parcouru, alors ils se mettent à "tournoyer" de façon aléatoire, et vont même jusqu'à "marcher" sur des briques existantes !

j'ai réussi à faire ces deux types de comportement : vers le bas puis tournoiement aléatoire, il me reste à programmer la non superposition avec les briques pour la première partie de leur déplacement.

@ bientôt

LouReeD

Voici le fichier avec les monstres en forme de cônes :

La descente, vu qu'il n'y a pas de briques et surtout qu'il n'y a pas la gestion d'évitement de ces dernières se résume à une diagonale vers le bas...
Mais l'idée est là.

Le code :

Type Monstre_Type
    Mo As Picture
    Dx As Integer ' direction en X du monstre : -1 vers le haut, 1 vers le bas
    Dy As Integer ' direction en Y du monstre : -1 vers la gauche, 1 vers la droite
    Tx As Integer ' translation en X
    Ty As Integer ' translation en Y
    Mi As Boolean ' à passer le milieu du tableau 
End Type

Public Monstre(1 To 3) As Monstre_Type

Sub test()

    ActiveSheet.Shapes("Fond").Width = 400
    ActiveSheet.Shapes("Fond").Height = 400

    Randomize

    For J = 1 To 3
        Set Monstre(J).Mo = ActiveSheet.Pictures("Monstre" & J)
        With Monstre(J)
            .Dx = -(Int(Rnd * 2) * 2) + 1
            .Dy = 1
            .Tx = 2
            .Ty = 2
            .Mo.Left = J * 100
            .Mo.Top = 5 * J
            .Mi = False
        End With
    Next J

    For i = 1 To 1000
        ' tempo de jouabilité
        tempo = Timer
        For J = 1 To 3
            If Monstre(J).Mo.Visible = True Then
                With Monstre(J)
                    If .Mi = False Then
                        If .Mo.Left + (.Dx * .Tx) >= 400 - .Mo.Width Or .Mo.Left + (.Dx * .Tx) <= 0 Then
                            .Dx = -.Dx
                            .Mo.Left = .Mo.Left + (.Dx * .Tx)
                        Else
                            .Mo.Left = .Mo.Left + (.Dx * .Tx)
                        End If
                        If .Mo.Top + (.Dy * .Ty) <= 0 Or .Mo.Top + (.Dy * .Ty) >= 400 - .Mo.Height Then
                            .Dy = -.Dy
                            .Mo.Top = .Mo.Top + (.Dy * .Ty)
                        Else
                            .Mo.Top = .Mo.Top + (.Dy * .Ty)
                        End If
                        If .Mo.Top > 200 And .Mi = False Then .Mi = True
                    Else
                        If .Mo.Left + (.Dx * .Tx) >= 400 - .Mo.Width Or .Mo.Left + (.Dx * .Tx) <= 0 Then
                            .Dx = -.Dx
                            .Mo.Left = .Mo.Left + (.Dx * .Tx)
                        Else
                            .Mo.Left = .Mo.Left + (.Dx * .Tx)
                        End If
                        If Int(Rnd * 5) > 3 Then .Tx = Int(Rnd * 10) + 1
                        If Int(Rnd * 100) < 10 And Cpt Mod 15 = 0 Then .Dx = -.Dx
                        If .Mo.Top + (.Dy * .Ty) <= 150 Or .Mo.Top + (.Dy * .Ty) >= 350 Then
                            .Dy = -.Dy
                            .Mo.Top = .Mo.Top + (.Dy * .Ty)
                        Else
                            .Mo.Top = .Mo.Top + (.Dy * .Ty)
                        End If
                        If Int(Rnd * 5) > 3 Then .Ty = Int(Rnd * 10) + 1
                        If Int(Rnd * 100) < 10 And Cpt Mod 15 = 0 Then .Dy = -.Dy: Cpt = 0
                        Cpt = Cpt + 1
                    End If
                End With
            End If
        Next J
        ' jouabilité
        Do
            DoEvents
        Loop While tempo + 0.043 > Timer
    Next i

End Sub

@ bientôt

LouReeD

Bonsoir,

sur le fichier ci : Supprimé par LouReeD

Les monstres se déplacent afin de trouver le passage vers le bas, une fois la zone de briques passée alors ils se "libèrent" et "volent" comme ils veulent !
Il se peut qu'il y ait des configurations où les monstres feront des aller retours "sans fin" entre différentes briques, mais comme en même temps le joueur va modifier la structure des briques ils finiront par trouver la sortie !

Alors ce n'est pas exactement comme "le vrai", mais cela s'y rapproche, non ?

@ bientôt

LouReeD

Bonsoir,

le précédent fichier de gestion des monstres ne me plaisait pas... Cela manquait de déplacement aléatoire avant d'arriver sur la zone de brique.
Le fichier ci :

corrige cela : les monstres se déplacent aléatoirement au dessus de la zone de brique, puis après "deux touches" au niveau des briques supérieures de la zone, ils se mettent "en rang" pour trouver un passage. Une fois la zone passée, alors ils se remettent à se déplacer aléatoirement.

Il me reste à gérer la collision entre eux et tout sera rentré dans l'ordre !

Bon je prend une nouvelle fois du retard sur mon projet, mais je vais essayer de ne pas faire comme avec HéroQuest ! Je vais m'y tenir et arriver au bout.
Comme dit plus haut j'ai déjà une version qui fonctionne, me reste plus qu'à l'améliorer, à mettre le "skin" en place et gérer les points et tout le reste.

@ bientôt

LouReeD

Bonsoir,

petites informations :
Il est bien évident qu'il n'y aura pas 6 monstres simultanément !
Vous pouvez modifier les briques présente sur le fichier en modifiant le tableau de la feuille 2.
Le code détermine "automatiquement" la zone libre de brique du haut de la zone où les monstres vont pouvoir se déplacer aléatoirement.
Il me reste donc à en faire de même pour la zone du dessous qui devrait être elle aussi égale à la dernière ligne libre de la zone de brique et le bas de l'écran...

@ bientôt

LouReeD

Bonsoir,

un grand merci à tous ceux qui cliquent pour donner des "petits 1" sur ce sujet, je viens juste de m'en rendre compte et ceci compte autant qu'un message !

@ bientôt

LouReeD

Bonsoir,

je crois que je vais essayer de tout reprendre... Le fichier fourni fonctionne bien mais je le trouve trop lourd au niveau du code...
Je me souhaite donc bonne chance sur cette nouvelle étape !

Bon le soucis c'est que le reste n'avance plus...

@ bientôt

LouReeD

Aller ! A 700 vues je m'y remet !

@ bientôt

LouReeD

Vache ! J'aurais du dire 800 ! Je n'ai pas le temps là maintenant ! C'est les congés de fin d'année !

@ bientôt

LouReeD

Bonsoir,

et bien plus d'un an après... je m'y remet ! Edit du 21/03/2023 : je crois que je m'y suis vraiment remis ! Voir dernier message de ce fil !

@ bientôt

LouReeD

Rechercher des sujets similaires à "arkaloureed legendaire casse briques"