Chapitre 13, un début de Mazin GameC'est partie, nous allons entrer dans le dur ! la création d'un début de mazin game avant toute chose nous allons créer un cahier des charges pour ce début !
-Il faut un niveau qui représente la zone de jeu
Mémoriser le niveau en Rom
Mettre en mémoire les cases qui bloquent ou pas en Ram.
-Ce niveau sera composé de plusieurs élément graphique.
Des <<sols>> qui sont praticable.
Des <<murs>> qui bloque le passage.
-Il nous faut le personnage qui sera présenté par un sprite.
Ce personnage peut bouger dans les 4 directions
Il ne peut pas faire de mouvement sur une case qui comporte un mur.
Donc il faut gérer cette colision
-Il nous faut donc gérer les commandes du jeu.
Haut,Bas,Droite,Gauche
Voici donc un début de moteur sur mégadrive à réaliser... Avant de regarder la suite, je vous conseille de tester par vous même à réaliser ce petit moteur...
La Boucle du jeu !Nous n'avons pas le choix, il faut faire la boucle du jeu ! Pour cela une simple boucle While infini est suffisante !
Le code : While 1... Wend fait l'affaire.
Nous allons aussi mettre en place une commande d'attente avant de reboucler.
voici le morceau de code de départ !
Rem **************
Rem * MazinDrive *
Rem **************
' -----------------
' - Boucle du jeu -
' -----------------
While 1
Sleep 1,TvBlank
Wend
Nous allons débuter avec la gestion du pad et écrire une procédure pour la gestion des directions.
Nous allons enregistrer dans une variable unique, (G_Direction) une valeur.
4 si la touche gauche est utilisée, 6 pour la touche droite, 8 pour la touche haut,2 pour la touche bas 0 pour aucune touche.
J'utilise souvent 8/6/2/4 ! Pour me r'appeller la valeur, regardez un peu votre pavé numérique de votre pc !
C'est fréquemment ma méthode. Je n'aime pas directement faire si la touche gauche est utilisé alors déplace toi par la gauche. Il y a plusieurs avantage à faire ça. C'est du basic, le code est donc portable plus ou moins facilement sur d'autre support.
La pour modifier les commandes, j'ai juste à modifier la procedure dédié au commande que dans tous le programme ou je dois tester les commandes du pad....
Peut importe le langage utilisé voir même le logiciel. (Fusion, Construct...) si votre programme utilise le clavier et manette, ça évite à chaque fois les conditions du type si le joueur est au clavier ou à la manette dans tous le programme ! Juste faire ça à un petit endroit et c'est bouénos. ET si plus tard une manette x ou y n'est pas géré de la même manière, la modification de ce bout de programme est facile. Repasser sur tout le programme pour adapter la nouvelle manette ... Et puis savoir que la direction = 4 est plus parlant que de savoir si la direction = machin chose . 2 ou autre.
La commande pour tester une touche du pad c'est joypad(x).y comme nous l'avons vu dans un autre chapitre.
X est le numéro du pad. 0 ou 1.
et y le "bit" à tester pour savoir qu'elle touche du pad est utilisé.
Voici donc la procedure P_Commande que j'ai écrit pour l'exemple :
' -----------------------
' - Gestion du joypad 0 -
' -----------------------
Declare Sub P_Commande()
' // Direction Haut //
If JoyPad(0).0=1 Then
G_Direction=8
' // Direction Bas //
ElseIf JoyPad(0).1=1 Then
G_Direction=2
' // Direction Gauche //
ElseIf JoyPad(0).2=1 Then
G_Direction=4
' // Direction Droite //
ElseIf JoyPad(0).3=1 Then
G_Direction=6
' // Aucune Direction //
Else
G_Direction=0
G_Direction_Down=0
EndIf
End Sub
J'ai dans le "sinon/else) passé une autre variable à 0. Nous verrons plus tard pourquoi.
Au début du programme, il faut initier les deux variables global.
' -----------------------------
' - Déclaration des variables -
' -----------------------------
Global G_Direction As Integer,G_Direction_Down As Integer
Et enfin dans la boucle, on appelle au début la procedure P_Commande et on test le pad pour voir si tous fonctionne. voici de nouveau le morceau de code au complet.
Rem **************
Rem * MazinDrive *
Rem **************
' -----------------------------
' - Déclaration des variables -
' -----------------------------
Global G_Direction As Integer,G_Direction_Down As Integer
' -----------------
' - Boucle du jeu -
' -----------------
While 1
P_Commande
Print G_Direction
Sleep 1,TvBlank
Wend
' -----------------------
' - Gestion du joypad 0 -
' -----------------------
Declare Sub P_Commande()
' // Direction Haut //
If JoyPad(0).0=1 Then
G_Direction=8
' // Direction Bas //
ElseIf JoyPad(0).1=1 Then
G_Direction=2
' // Direction Gauche //
ElseIf JoyPad(0).2=1 Then
G_Direction=4
' // Direction Droite //
ElseIf JoyPad(0).3=1 Then
G_Direction=6
' // Aucune Direction //
Else
G_Direction=0
G_Direction_Down=0
EndIf
End Sub
Voila une bonne chose de réalisé. La prochaine étape c'est la création et l'affichage de notre joueur sur l'écran. Nous allons pour ce tuto, nous inspirer de ses graphismes.
Elles appartiennent à surt sous divers licences.
LienOn va commencer à encoder le personnage pour que cela soit un sprite ! Mais avant il va falloir créer notre palette de couleur. Nous allons décrypter ce perso !
Il possède 4 couleurs.
Le noir pour le fond #000000
Une couleur pour la peau #C8913e
Une couleur pour les bottes #5828b8
Une couleur pour le vêtement #699efc
Les couleurs que je présente, se sont des couleurs 24 bits (PC)
Il faut maintenant trouver plus ou moins sont équivalant sur mégadrive.
Pour cela on va garder la premier valeur de chaque teint.
Exemple sur la peau. La peau c'est #C8913E soit Rouge = C8 Vert=91 et Bleu= 3E
Je r'appelle que ce sont des valeurs Hexadécimal. Ce fait donc #C93
Maintenant sur mégadrive, il faut inverser le Rouge et le Bleu et ajouter un 0 au début !
Ce qui fait donc : #039C
Maintenant au niveau code couleur, il faut que chaque teinte soit une valeur paire. Donc le Bleu à 3 ça ne marche pas.
soit c'est 2 ou soit c'est 4. Le 9 ça marche pas. Soit c'est 9 ou soit c'est A(10). Mais C ça fonctionne (12). Nous avons donc plusieurs possibilités pour nous approché de notre teinte de base.
#028C
#02AC
#048C
#04AC
J'ai recomposé les 4 couleurs avec le logiciel palette contenu dans second basic.
Les couleurs sont dans l'ordre.
Vous avez plus cas comparer ce qui semble le plus proche et qui vous convient.
#02AC sembe pas trop mal. Nous allons faire pareil avec les autres couleurs.
Les bottes #5828b8 => #52B =>#0A24
Le Vêtement #699efc=>#69F=>#0EA6
Cela semble pas trop mal nous allons donc mettre le début de cette palette en rom.
E_Palette_A:
DATAINT $0000,$0000,$02AC,$0A24,$0EA6,$0000,$0000,$0000
DATAINT $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Alors concrètement avec cette palette :
0 = La couleur transparente.
1 = La couleur noir.
2= La peau
3= Les bottes
4= Les vêtement.
C'est bien beau d'avoir placé les couleurs en rom, il faut maintenant mettre ça en mémoire vidéo.
Juste avant notre boucle principale du jeu, on va faire un :
Palettes E_Palette_A,0,0,16
Notre palette est en mémoire. Passons maintenant au codage de notre petit personnage...
Notre perso fait 16px sur 16px. Un Tiles fait 8px sur 8px. Il est donc composé de 4 Tiles. Nous allons donc encoder ça en conséquence avec les numéros de couleur. :D
Je vais juste inscrite les suites de valeur hexadécimale pour représenter notre warrior !
Le PJ agrandie avec une grille, chaque carré est donc représenté par une valeur entre 0 et F ce qui recompose notre graphismes.Chaque valeur c'est tout simplement le numéros de couleur de notre palette !
1111111111111111
1111111221111111
1111111221111111
1111111221111111
1111244114421111
1111244114421111
1112224444222111
1112112222112111
1122114444112211
1122144444412211
1111122112211111
1111221111221111
1111331111331111
1111311111131111
1113311111133111
1111111111111111
Je ne dois pas être trop mal. Ceci dit attention, ce n'est pas du tout bon si on entre tout ça en rom ! Maintenant il va falloire organiser le code en sachant que pour un sprite de 16px sur 16px, le mégadrive pose en premier le premier tiles en haut à gauche, puis en bas à gauche, puis en en haut à droite puis en bas à droite... Il faut donc redécouper ça correctement dans les datas longs.
E_PJ:
Rem Pose Haut Gauche
Datalong $11111111
Datalong $11111112
Datalong $11111112
Datalong $11111112
Datalong $11112441
Datalong $11112441
Datalong $11122244
Datalong $11121122
Rem Pose Bas Gauche
Datalong $11221144
Datalong $11221444
Datalong $11111221
Datalong $11112211
Datalong $11113311
Datalong $11113111
Datalong $11133111
Datalong $11111111
Rem Pose Haut Droite
Datalong $11111111
Datalong $21111111
Datalong $21111111
Datalong $21111111
Datalong $14421111
Datalong $14421111
Datalong $44222111
Datalong $22112111
Rem Pose Bas Droite
Datalong $44112211
Datalong $44412211
Datalong $12211111
Datalong $11221111
Datalong $11331111
Datalong $11131111
Datalong $11133111
Datalong $11111111
Maintenant, nous n'avons plus cas mémoriser les données de la rom dans la mémoire vidéo. Juste après l'initation de la palette et avant le boucle de jeu. Nous allons mémoriser ça à la position 300. Cela devrais le faire.
LoadTiles E_PJ,4,300
Maintenant nous allons préparer le sprite. Au début du code on déclare notre variable du sprite avec un
Global sp1 As Integer.
Ensuite juste après le load tile on va faire ce morceau de code.
sp1=AddSprite(2,2)
PropSprite sp1,300,0
Et on va tester le sprite dans la boucle avec
MoveSprite sp1,128,128
Le code source jusque la !Rem **************
Rem * MazinDrive *
Rem **************
' -----------------------------
' - Déclaration des variables -
' -----------------------------
Global G_Direction As Integer,G_Direction_Down As Integer,sp1 As Integer
' --------------------------
' - Initation du programme -
' --------------------------
Palettes E_Palette_A,0,0,16
' * PJ *
LoadTiles E_PJ,4,300
sp1=AddSprite(2,2)
PropSprite sp1,300,0
' -----------------
' - Boucle du jeu -
' -----------------
While 1
P_Commande
Print G_Direction
MoveSprite sp1,128,128
Sleep 1,TvBlank
Wend
' -----------------------
' - Gestion du joypad 0 -
' -----------------------
Declare Sub P_Commande()
' // Direction Haut //
If JoyPad(0).0=1 Then
G_Direction=8
' // Direction Bas //
ElseIf JoyPad(0).1=1 Then
G_Direction=2
' // Direction Gauche //
ElseIf JoyPad(0).2=1 Then
G_Direction=4
' // Direction Droite //
ElseIf JoyPad(0).3=1 Then
G_Direction=6
' // Aucune Direction //
Else
G_Direction=0
G_Direction_Down=0
EndIf
End Sub
' ----------------
' - Donné en Rom -
' ----------------
' * Palette de couleur *
E_Palette_A:
DataInt $0000,$0000,$02AC,$0A24,$0EA6,$0000,$0000,$0000
DataInt $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
' * Sprite du joueur *
E_PJ:
Rem Pose Haut Gauche
DataLong $11111111
DataLong $11111112
DataLong $11111112
DataLong $11111112
DataLong $11112441
DataLong $11112441
DataLong $11122244
DataLong $11121122
Rem Pose Bas Gauche
DataLong $11221144
DataLong $11221444
DataLong $11111221
DataLong $11112211
DataLong $11113311
DataLong $11113111
DataLong $11133111
DataLong $11111111
Rem Pose Haut Droite
DataLong $11111111
DataLong $21111111
DataLong $21111111
DataLong $21111111
DataLong $14421111
DataLong $14421111
DataLong $44222111
DataLong $22112111
Rem Pose Bas Droite
DataLong $44112211
DataLong $44412211
DataLong $12211111
DataLong $11221111
DataLong $11331111
DataLong $11131111
DataLong $11133111
DataLong $11111111
Notre petit bout choux s'affiche bien. Sympathique non ?
La prochaine étape c'est de le faire bouger de case.
Déplacer le sprite !Nous allons déclarer en Global deux nouvelles variables pour mémoriser la case ou se trouve notre personnage. La case sera identifier par la valeur X et Y. Donc PJ_X et PJ_Y.
Maintenant dans la fonction MoveSprite nous allons ajouter un(PJ_X*16)+128 et un (PJ_Y*16)+128
N'oulibez pas que le Haut à Gauche à pour coordonné 128,128 pour les sprites machines.
maintenant le but du jeu c'est de modifier PJ_X et PJ_Y en fonction de la touche utilisé. Pour cela une nouvelle Procedure, des conditions, et des éditions, soustraction.
Global PJ_X As Integer, PJ_Y As Integer
La déclaration des variables adéquates.
' -------------------------
' - Déplacement du joueur -
' -------------------------
Declare Sub P_Deplacement()
If G_Direction = 6 Then
PJ_X=PJ_X+1
ElseIf G_Direction = 4 Then
PJ_X=PJ_X-1
ElseIf G_Direction = 8 Then
PJ_Y=PJ_Y-1
ElseIf G_Direction = 2 Then
PJ_Y=PJ_Y+1
End If
End Sub
La Procedure pour modifier la valeur PJ_X et PJ_Y.
Si G_Direction est égale à 6 donc si la touche Droite est utilisé. La valeur de la variable PJ_X est augmenté de 1.
oué X+1 = Gauche. Pour aller à droite c'est X-1. En principe tous le monde pige ça. C'est avec Haut et Bas qui peut poser des problèmes. Il faut retirer 1 à Y pour "monter" et l'inverse pour descendre.
Dans la boucle de jeu on appelle P_Deplacement après les commandes et avant d'afficher le sprite.
' -----------------
' - Boucle du jeu -
' -----------------
While 1
P_Commande
P_Deplacement
MoveSprite sp1,128+(PJ_X*16),128+(PJ_Y*16)
Sleep 1,TvBlank
Wend
Vous pouvez tester (N'oubliez pas donner le focus en cliquant dessus avec la sourie !) Ceci dit le perso se déplace trop rapidement ce n'est pas agréable pour ce type de jeu. C'est la que va intervenir la variable. G_Direction_Down
Nous allons placer une "double" condition. Le mouvement peut se faire à la condition que la variable G_Direction_Down soit égale à 0. Et quand un déplacement s’effectue, on place la valeur 1 dans cette variable. Mais elle revient à 0 quand il n'y a pas de touche de direction utilisé. (Déja programmé ça )
La nouvelle procedure.
' -------------------------
' - Déplacement du joueur -
' -------------------------
Declare Sub P_Deplacement()
If G_Direction_Down=0 Then
If G_Direction = 6 Then
PJ_X=PJ_X+1
G_Direction_Down=1
ElseIf G_Direction = 4 Then
PJ_X=PJ_X-1
G_Direction_Down=1
ElseIf G_Direction = 8 Then
PJ_Y=PJ_Y-1
G_Direction_Down=1
ElseIf G_Direction = 2 Then
PJ_Y=PJ_Y+1
G_Direction_Down=1
End If
End If
End Sub
Nous allons aussi initier au début PJ_X et PJ_Y pour le placer sur une autre case au début. Et voici donc le code complet à cette étape.
Rem **************
Rem * MazinDrive *
Rem **************
' -----------------------------
' - Déclaration des variables -
' -----------------------------
Global G_Direction As Integer,G_Direction_Down As Integer,sp1 As Integer
Global PJ_X As Integer, PJ_Y As Integer
' --------------------------
' - Initation du programme -
' --------------------------
Palettes E_Palette_A,0,0,16
' * PJ *
LoadTiles E_PJ,4,300
sp1=AddSprite(2,2)
PropSprite sp1,300,0
PJ_X=0
PJ_Y=0
' -----------------
' - Boucle du jeu -
' -----------------
While 1
P_Commande
P_Deplacement
MoveSprite sp1,128+(PJ_X*16),128+(PJ_Y*16)
Sleep 1,TvBlank
Wend
' -----------------------
' - Gestion du joypad 0 -
' -----------------------
Declare Sub P_Commande()
' // Direction Haut //
If JoyPad(0).0=1 Then
G_Direction=8
' // Direction Bas //
ElseIf JoyPad(0).1=1 Then
G_Direction=2
' // Direction Gauche //
ElseIf JoyPad(0).2=1 Then
G_Direction=4
' // Direction Droite //
ElseIf JoyPad(0).3=1 Then
G_Direction=6
' // Aucune Direction //
Else
G_Direction=0
G_Direction_Down=0
EndIf
End Sub
' -------------------------
' - Déplacement du joueur -
' -------------------------
Declare Sub P_Deplacement()
If G_Direction_Down=0 Then
If G_Direction = 6 Then
PJ_X=PJ_X+1
G_Direction_Down=1
ElseIf G_Direction = 4 Then
PJ_X=PJ_X-1
G_Direction_Down=1
ElseIf G_Direction = 8 Then
PJ_Y=PJ_Y-1
G_Direction_Down=1
ElseIf G_Direction = 2 Then
PJ_Y=PJ_Y+1
G_Direction_Down=1
End If
End If
End Sub
' ----------------
' - Donné en Rom -
' ----------------
' * Palette de couleur *
E_Palette_A:
DataInt $0000,$0000,$02AC,$0A24,$0EA6,$0000,$0000,$0000
DataInt $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
' * Sprite du joueur *
E_PJ:
Rem Pose Haut Gauche
DataLong $11111111
DataLong $11111112
DataLong $11111112
DataLong $11111112
DataLong $11112441
DataLong $11112441
DataLong $11122244
DataLong $11121122
Rem Pose Bas Gauche
DataLong $11221144
DataLong $11221444
DataLong $11111221
DataLong $11112211
DataLong $11113311
DataLong $11113111
DataLong $11133111
DataLong $11111111
Rem Pose Haut Droite
DataLong $11111111
DataLong $21111111
DataLong $21111111
DataLong $21111111
DataLong $14421111
DataLong $14421111
DataLong $44222111
DataLong $22112111
Rem Pose Bas Droite
DataLong $44112211
DataLong $44412211
DataLong $12211111
DataLong $11221111
DataLong $11331111
DataLong $11131111
DataLong $11133111
DataLong $11111111
La prochaine étape maintenant c'est de mémoriser une tuile qui représente le Sol, et une tuile qui représente un mur !
Une début de Tilset !Bon nous allons encoder un sol. Celui la.
Nous allons faire comme le sprite, rechercher une teinte pour l'ajouter à la palette de couleur, et coder l'image.
Au niveau des teintes nous avons le noir, et un gris. Le gris #525252 ce qui fait #555 donc soit #444 ou #666.
#666 semble le mieux s'adapter à ce que nous voulons. On le r'ajoute donc à notre palette. C'est la valeur 5.
E_Palette_A:
DataInt $0000,$0000,$02AC,$0A24,$0EA6,$0666,$0000,$0000
DataInt $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Les tiles ne sont pas entrelacer. Donc l'ordre est Haut Gauche, Haut Droite, Bas Gauche, Bas droite. Nous allons maintenant placer nos 1 pour le point noir et 5 pour le gris. Notons que pour l'exemple, je ne cherche pas à optimiser les datas. Le tile Sol c'est 4 fois le mêmes tiles.
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
Pour le mur en question, je vais modifié un peu les graphismes, et l'encoder.
Il possède deux couleurs.
Le rouge #822e24
et un jaune #c8913e
Voici donc une nouvelle modification de la palette. Je vais utiliser 22c pour le rouge (Index 6) et 2EC( index 7) pour le jaune. (J'adapte finalement)
Voici donc les datas pour les deux tiles.
E_Tiles:
Rem * Tiles du sol *
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
Rem * Tiles du sol *
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $77767776
DataLong $77767776
DataLong $66666666
DataLong $67776777
DataLong $67776777
DataLong $66666666
DataLong $77767776
DataLong $77767776
DataLong $77767776
DataLong $77767776
DataLong $66666666
DataLong $67776777
DataLong $67776777
DataLong $66666666
DataLong $77767776
DataLong $77767776
Maintenant nous allons les placer en mémoire. Comme d'habe juste avant le while :
Nous allons donc mettre en mémoire 8 tiles (2 gros tiles composé de 4 portions) a partir de 255.
Donc un beau
LoadTiles E_Tiles,8,255
Donc Le tile sur Sol se trouve à id 255
et le tile du mur à 259. (Et non 256 attention !!!)
Directement dans le While nous allons tester d'afficher les deux tiles en question avec
DrawTilesInc 255,4,4,2,2 (pour afficher le tile 255 à la position 4-4 de 2 tiles horizontale et 2 tiles verticale
et DrawTilesInc 259,4,2,2,2
Cela fonctionne vous pouvez même tester le déplacement du perso.
Voici le code complet jusque la.
Rem **************
Rem * MazinDrive *
Rem **************
' -----------------------------
' - Déclaration des variables -
' -----------------------------
Global G_Direction As Integer,G_Direction_Down As Integer,sp1 As Integer
Global PJ_X As Integer, PJ_Y As Integer
' --------------------------
' - Initation du programme -
' --------------------------
Palettes E_Palette_A,0,0,16
' * PJ *
LoadTiles E_PJ,4,300
sp1=AddSprite(2,2)
PropSprite sp1,300,0
PJ_X=0
PJ_Y=0
' *tile*
LoadTiles E_Tiles,8,255
' -----------------
' - Boucle du jeu -
' -----------------
While 1
P_Commande
P_Deplacement
DrawTilesInc 255,4,4,2,2
DrawTilesInc 259,4,2,2,2
MoveSprite sp1,128+(PJ_X*16),128+(PJ_Y*16)
Sleep 1,TvBlank
Wend
' -----------------------
' - Gestion du joypad 0 -
' -----------------------
Declare Sub P_Commande()
' // Direction Haut //
If JoyPad(0).0=1 Then
G_Direction=8
' // Direction Bas //
ElseIf JoyPad(0).1=1 Then
G_Direction=2
' // Direction Gauche //
ElseIf JoyPad(0).2=1 Then
G_Direction=4
' // Direction Droite //
ElseIf JoyPad(0).3=1 Then
G_Direction=6
' // Aucune Direction //
Else
G_Direction=0
G_Direction_Down=0
EndIf
End Sub
' -------------------------
' - Déplacement du joueur -
' -------------------------
Declare Sub P_Deplacement()
If G_Direction_Down=0 Then
If G_Direction = 6 Then
PJ_X=PJ_X+1
G_Direction_Down=1
ElseIf G_Direction = 4 Then
PJ_X=PJ_X-1
G_Direction_Down=1
ElseIf G_Direction = 8 Then
PJ_Y=PJ_Y-1
G_Direction_Down=1
ElseIf G_Direction = 2 Then
PJ_Y=PJ_Y+1
G_Direction_Down=1
End If
End If
End Sub
' ----------------
' - Donné en Rom -
' ----------------
' * Palette de couleur *
E_Palette_A:
DataInt $0000,$0000,$02AC,$0A24,$0EA6,$0666,$022c,$02EC
DataInt $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
' * Sprite du joueur *
E_PJ:
Rem Pose Haut Gauche
DataLong $11111111
DataLong $11111112
DataLong $11111112
DataLong $11111112
DataLong $11112441
DataLong $11112441
DataLong $11122244
DataLong $11121122
Rem Pose Bas Gauche
DataLong $11221144
DataLong $11221444
DataLong $11111221
DataLong $11112211
DataLong $11113311
DataLong $11113111
DataLong $11133111
DataLong $11111111
Rem Pose Haut Droite
DataLong $11111111
DataLong $21111111
DataLong $21111111
DataLong $21111111
DataLong $14421111
DataLong $14421111
DataLong $44222111
DataLong $22112111
Rem Pose Bas Droite
DataLong $44112211
DataLong $44412211
DataLong $12211111
DataLong $11221111
DataLong $11331111
DataLong $11131111
DataLong $11133111
DataLong $11111111
E_Tiles:
Rem * Tiles du sol *
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
Rem * Tiles du sol *
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $77767776
DataLong $77767776
DataLong $66666666
DataLong $67776777
DataLong $67776777
DataLong $66666666
DataLong $77767776
DataLong $77767776
DataLong $77767776
DataLong $77767776
DataLong $66666666
DataLong $67776777
DataLong $67776777
DataLong $66666666
DataLong $77767776
DataLong $77767776
Maintenant nous allons gérer une petite map !
La création de la mapNous allons simuler un niveau, une simple map. Comme les sprites et les tiles, il faut entrer ça dans la rom. Pour ça les Datas sont idéal. Nous allons utiliser de simple data.
Nous allons faire une map de 16 sur 12.
Nous allons décider que 0 c'est le vide, 1 c'est le sol et 2 et le mur.
Réalisons notre map en data et sans éditeur de map !
E_Map1:
Data 0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0
Data 0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0
Data 0,1,1,1,0,0,0,1,0,1,1,1,1,1,1,0
Data 0,1,1,1,2,0,0,0,0,1,1,1,1,0,0,0
Data 0,1,1,1,1,0,2,2,2,1,1,1,1,2,2,0
Data 0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0
Data 0,1,1,1,1,2,1,1,1,1,1,1,1,1,1,0
Data 0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0
Data 0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0
Data 0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0
Data 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Voici une map exemple. Maintenant nous allons poser les tiles avec une simple routine qui fait intervenir deux boucles For. L'une pour les lignes (Y) et l'autre pour (X)
Nous allons créer une nouvelle Procédure.
' *********************************
' * Routine pour afficher une map *
' *********************************
Declare Sub DrawMap()
Restore E_Map1
For Y=0 To 11
For X=0 To 15
Read ID
If id=1 Then
DrawTilesInc 255,x*2,y*2,2,2
ElseIf id=2 Then
DrawTilesInc 259,x*2,y*2,2,2
End If
Next
Next
End Sub
Alors, Restore permet de se brancher sur une étiquette pour la lecture des Datas qui est ici, E_Map1 (notre map test)
Les deux boucles For Y et X) permet donc d'afficher les lignes et les colonnes.
Dans chaque boucle on va chercher la nouvelle valeurs des datas avec Read id. (id est une variable)
Maintenant avec les conditions on affiche le tiles en question avec un *2 à X et Y car un tile c'est 2 tiles horizontale et verticale.
X*2 et Y*2 est calqué sur la boucle X et Y.
Enfin juste avant le while pour notre exemple, on va chercher cette procedure. ET on efface nos deux affichages de tiles test. Voici le code source actuel !
Rem **************
Rem * MazinDrive *
Rem **************
' -----------------------------
' - Déclaration des variables -
' -----------------------------
Global G_Direction As Integer,G_Direction_Down As Integer,sp1 As Integer
Global PJ_X As Integer, PJ_Y As Integer
' --------------------------
' - Initation du programme -
' --------------------------
Palettes E_Palette_A,0,0,16
' * PJ *
LoadTiles E_PJ,4,300
sp1=AddSprite(2,2)
PropSprite sp1,300,0
PJ_X=0
PJ_Y=0
' *tile*
LoadTiles E_Tiles,8,255
DrawMap
' -----------------
' - Boucle du jeu -
' -----------------
While 1
P_Commande
P_Deplacement
MoveSprite sp1,128+(PJ_X*16),128+(PJ_Y*16)
Sleep 1,TvBlank
Wend
' -----------------------
' - Gestion du joypad 0 -
' -----------------------
Declare Sub P_Commande()
' // Direction Haut //
If JoyPad(0).0=1 Then
G_Direction=8
' // Direction Bas //
ElseIf JoyPad(0).1=1 Then
G_Direction=2
' // Direction Gauche //
ElseIf JoyPad(0).2=1 Then
G_Direction=4
' // Direction Droite //
ElseIf JoyPad(0).3=1 Then
G_Direction=6
' // Aucune Direction //
Else
G_Direction=0
G_Direction_Down=0
EndIf
End Sub
' -------------------------
' - Déplacement du joueur -
' -------------------------
Declare Sub P_Deplacement()
If G_Direction_Down=0 Then
If G_Direction = 6 Then
PJ_X=PJ_X+1
G_Direction_Down=1
ElseIf G_Direction = 4 Then
PJ_X=PJ_X-1
G_Direction_Down=1
ElseIf G_Direction = 8 Then
PJ_Y=PJ_Y-1
G_Direction_Down=1
ElseIf G_Direction = 2 Then
PJ_Y=PJ_Y+1
G_Direction_Down=1
End If
End If
End Sub
' *********************************
' * Routine pour afficher une map *
' *********************************
Declare Sub DrawMap()
Restore E_Map1
For Y=0 To 11
For X=0 To 15
Read ID
If id=1 Then
DrawTilesInc 255,x*2,y*2,2,2
ElseIf id=2 Then
DrawTilesInc 259,x*2,y*2,2,2
End If
Next
Next
End Sub
' ----------------
' - Donné en Rom -
' ----------------
' * Palette de couleur *
E_Palette_A:
DataInt $0000,$0000,$02AC,$0A24,$0EA6,$0666,$022c,$02EC
DataInt $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
' * Sprite du joueur *
E_PJ:
Rem Pose Haut Gauche
DataLong $11111111
DataLong $11111112
DataLong $11111112
DataLong $11111112
DataLong $11112441
DataLong $11112441
DataLong $11122244
DataLong $11121122
Rem Pose Bas Gauche
DataLong $11221144
DataLong $11221444
DataLong $11111221
DataLong $11112211
DataLong $11113311
DataLong $11113111
DataLong $11133111
DataLong $11111111
Rem Pose Haut Droite
DataLong $11111111
DataLong $21111111
DataLong $21111111
DataLong $21111111
DataLong $14421111
DataLong $14421111
DataLong $44222111
DataLong $22112111
Rem Pose Bas Droite
DataLong $44112211
DataLong $44412211
DataLong $12211111
DataLong $11221111
DataLong $11331111
DataLong $11131111
DataLong $11133111
DataLong $11111111
E_Tiles:
Rem * Tiles du sol *
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
Rem * Tiles du sol *
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $77767776
DataLong $77767776
DataLong $66666666
DataLong $67776777
DataLong $67776777
DataLong $66666666
DataLong $77767776
DataLong $77767776
DataLong $77767776
DataLong $77767776
DataLong $66666666
DataLong $67776777
DataLong $67776777
DataLong $66666666
DataLong $77767776
DataLong $77767776
E_Map1:
Data 0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0
Data 0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0
Data 0,1,1,1,0,0,0,1,0,1,1,1,1,1,1,0
Data 0,1,1,1,2,0,0,0,0,1,1,1,1,0,0,0
Data 0,1,1,1,1,0,2,2,2,1,1,1,1,2,2,0
Data 0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0
Data 0,1,1,1,1,2,1,1,1,1,1,1,1,1,1,0
Data 0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0
Data 0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0
Data 0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0
Data 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Ce n'est pas une belle map mais osef
Nous pouvons nous amuser à nous déplacer sur la map mais pas de collision encore, c'est notre prochaine manipe !
La grille de colision en RamNous allons mettre en mémoire la grille de collision. Un tableau va nous servir à cela. Un tableau de la taille de notre map même.
Voyon voir la déclaration du tableau. Nous allons donc déclarer le tableau T_Map_Colision avec pour dimension (15,11) ce qui représente la taille de notre map. (16,12 n’oubliez pas qu'un tableau en basic débute par 0.) Nous allons faire un tableau global.
Donc :
Global T_Map_Collision(15,11) as integer
Maintenant un petit retour la ou on affiche la map ! Nous allons mémoriser la valeur 1 au mur et dans le vide. Nous allons modifier un petit perux le code.
' *********************************
' * Routine pour afficher une map *
' *********************************
Declare Sub DrawMap()
Restore E_Map1
For Y=0 To 11
For X=0 To 15
Read ID
If id=0 Then
T_Map_Collision(X,Y)=1
ElseIf id=1 Then
DrawTilesInc 255,x*2,y*2,2,2
T_Map_Collision(X,Y)=0
ElseIf id=2 Then
DrawTilesInc 259,x*2,y*2,2,2
T_Map_Collision(X,Y)=1
End If
Next
Next
End Sub
On ajoute la condition id=0
on ajoute le else avant le if de l'id 1
et on mémorise en fonction de ce que nous voulons une valeur dans le tableau en fonction de X et Y qui est aussi en fonction de la boucle.
T_Map_Colision(X,Y)=0
et haut dans le code, j'ai modifié le PJ_X et PJ_Y à 1 pour éviter que le pj débute dans une case bloquante.
PJ_X=1
PJ_Y=1
Bloquer le déplacement du joueurMaintenant à chaque fois que nous allons tester le déplacement du joueur, nous allons regarder dans qu'elle case qu'il doit se déplacer et voir si c'est une case "sol" donc 0 dans le tableau, ou une case mur/vide (donc 1).
C'est très simple, on test dans le tableau la prochaine case.
Exemple si le joueur doit se déplacer à droite : le tableau doit être à (PJ_X+1,PJ_Y)=0 si c'est 1 la condition sera fausse et le code du mouvement ne se fait pas.
' -------------------------
' - Déplacement du joueur -
' -------------------------
Declare Sub P_Deplacement()
If G_Direction_Down=0 Then
' * Déplacement Droite *
If T_Map_Collision(PJ_X+1,PJ_Y)=0 And G_Direction = 6 Then
PJ_X=PJ_X+1
G_Direction_Down=1
' * Déplacement Gauche *
ElseIf T_Map_Collision(PJ_X-1,PJ_Y)=0 And G_Direction = 4 Then
PJ_X=PJ_X-1
G_Direction_Down=1
' * Déplacement Haut *
ElseIf T_Map_Collision(PJ_X,PJ_Y-1)=0 And G_Direction = 8 Then
PJ_Y=PJ_Y-1
G_Direction_Down=1
' * Déplacement Bas *
ElseIf T_Map_Collision(PJ_X,PJ_Y+1)=0 And G_Direction = 2 Then
PJ_Y=PJ_Y+1
G_Direction_Down=1
End If
End If
End Sub
Et voila vous avez un moteur de déplacement case par case sur mégadrive avec gestion des collisions. (A la case bien sur)
La position en case du joueur, se ballade virtuellement donc dans le tableau et avec ça vous pouvez aussi récupérer des informations sur la case ou se trouve le PJ pour déclencher des événements...
De la finitionLe perso avec son fond noir c'est caca vous ne trouvez pas ? Remplacez les 1 du sprites du perso par des 0. Et nous avons le fond transparent.
E_PJ:
Rem Pose Haut Gauche
DataLong $00000000
DataLong $00000002
DataLong $00000002
DataLong $00000002
DataLong $00002440
DataLong $00002440
DataLong $00022244
DataLong $00020022
Rem Pose Bas Gauche
DataLong $00220044
DataLong $00220444
DataLong $00000220
DataLong $00002200
DataLong $00003300
DataLong $00003000
DataLong $00033000
DataLong $00000000
Rem Pose Haut Droite
DataLong $00000000
DataLong $20000000
DataLong $20000000
DataLong $20000000
DataLong $04420000
DataLong $04420000
DataLong $44222000
DataLong $22002000
Rem Pose Bas Droite
DataLong $44002200
DataLong $44402200
DataLong $02200000
DataLong $00220000
DataLong $00330000
DataLong $00030000
DataLong $00033000
DataLong $00000000
Pour pas perdre de temps, faite une selection des datas du sprites, menu Edit replace. Dans find faite 1 et replace with 0. Le tour est joué.
La couleur du perso ne se marie pas avec le sol (ou l'inverse) vous pouvez y remédier en la modifiant directement dans la palette par exemple remplacez le bleu claire par un vert, $0066 et les bottes par un rouge $020C?
Code Source 1.0' ****************************************
' * Nom ............ : megazin.sbs *
' * Role ........... : Exemple Megadrive *
' * Auteur ......... : Loïc Lété (Monos) *
' * Version ........ : V1 du 28/07/17 *
' * Licence ........ : CC-BY *
' * Compilateur .... : Second Basic *
' ****************************************
' = Crédit des graphismes :
' * Surt * sous licence :
' CC-By 3.0
' GPL 3.0
' GPL 2.0
' https://opengameart.org/content/loveable-rogue
' -----------------------------
' - Déclaration des variables -
' -----------------------------
Global G_Direction As Integer,G_Direction_Down As Integer,sp1 As Integer
Global PJ_X As Integer, PJ_Y As Integer
Global T_Map_Collision(15,11) As Integer
' --------------------------
' - Initation du programme -
' --------------------------
' * Mise en mémoire vidéo de la palette *
Palettes E_Palette_A,0,0,16
' * Mise en mémoire vidéo du sprite du joueur *
LoadTiles E_PJ,4,300
sp1=AddSprite(2,2)
PropSprite sp1,300,0
PJ_X=1
PJ_Y=1
' * Mise en mémoire vidéo des 2 tiles *
LoadTiles E_Tiles,8,255
' * Affichage de la map du jeu *
DrawMap
' -----------------
' - Boucle du jeu -
' -----------------
While 1
P_Commande
P_Deplacement
MoveSprite sp1,128+(PJ_X*16),128+(PJ_Y*16)
Sleep 1,TvBlank
Wend
' -----------------------
' - Gestion du joypad 0 -
' -----------------------
Declare Sub P_Commande()
' // Direction Haut //
If JoyPad(0).0=1 Then
G_Direction=8
' // Direction Bas //
ElseIf JoyPad(0).1=1 Then
G_Direction=2
' // Direction Gauche //
ElseIf JoyPad(0).2=1 Then
G_Direction=4
' // Direction Droite //
ElseIf JoyPad(0).3=1 Then
G_Direction=6
' // Aucune Direction //
Else
G_Direction=0
G_Direction_Down=0
EndIf
End Sub
' -------------------------
' - Déplacement du joueur -
' -------------------------
Declare Sub P_Deplacement()
If G_Direction_Down=0 Then
' // Déplacement Droite //
If T_Map_Collision(PJ_X+1,PJ_Y)=0 And G_Direction = 6 Then
PJ_X=PJ_X+1
G_Direction_Down=1
' // Déplacement Gauche //
ElseIf T_Map_Collision(PJ_X-1,PJ_Y)=0 And G_Direction = 4 Then
PJ_X=PJ_X-1
G_Direction_Down=1
' // Déplacement Haut //
ElseIf T_Map_Collision(PJ_X,PJ_Y-1)=0 And G_Direction = 8 Then
PJ_Y=PJ_Y-1
G_Direction_Down=1
' // Déplacement Bas //
ElseIf T_Map_Collision(PJ_X,PJ_Y+1)=0 And G_Direction = 2 Then
PJ_Y=PJ_Y+1
G_Direction_Down=1
End If
End If
End Sub
' *********************************
' * Routine pour afficher une map *
' *********************************
Declare Sub DrawMap()
Restore E_Map1
For Y=0 To 11
For X=0 To 15
Read ID
If id=0 Then
T_Map_Collision(X,Y)=1
ElseIf id=1 Then
DrawTilesInc 255,x*2,y*2,2,2
T_Map_Collision(X,Y)=0
ElseIf id=2 Then
DrawTilesInc 259,x*2,y*2,2,2
T_Map_Collision(X,Y)=1
End If
Next
Next
End Sub
' ----------------
' - Donné en Rom -
' ----------------
' * Palette de couleur *
E_Palette_A:
DataInt $0000,$0000,$02AC,$020C,$0066,$0666,$022c,$02EC
DataInt $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
' * Sprite du joueur *
E_PJ:
Rem Pose Haut Gauche
DataLong $00000000
DataLong $00000002
DataLong $00000002
DataLong $00000002
DataLong $00002440
DataLong $00002440
DataLong $00022244
DataLong $00020022
Rem Pose Bas Gauche
DataLong $00220044
DataLong $00220444
DataLong $00000220
DataLong $00002200
DataLong $00003300
DataLong $00003000
DataLong $00033000
DataLong $00000000
Rem Pose Haut Droite
DataLong $00000000
DataLong $20000000
DataLong $20000000
DataLong $20000000
DataLong $04420000
DataLong $04420000
DataLong $44222000
DataLong $22002000
Rem Pose Bas Droite
DataLong $44002200
DataLong $44402200
DataLong $02200000
DataLong $00220000
DataLong $00330000
DataLong $00030000
DataLong $00033000
DataLong $00000000
' * Tiles *
E_Tiles:
Rem * Tiles du sol *
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
DataLong $11111111
DataLong $15551555
DataLong $15551555
DataLong $15551555
DataLong $11111111
DataLong $55515551
DataLong $55515551
DataLong $55515551
Rem * Tiles du sol *
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $66666666
DataLong $77767776
DataLong $77767776
DataLong $66666666
DataLong $67776777
DataLong $67776777
DataLong $66666666
DataLong $77767776
DataLong $77767776
DataLong $77767776
DataLong $77767776
DataLong $66666666
DataLong $67776777
DataLong $67776777
DataLong $66666666
DataLong $77767776
DataLong $77767776
' * Map Exemple *
E_Map1:
Data 0,2,2,2,0,2,2,2,2,2,2,2,2,2,2,0
Data 0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0
Data 0,1,1,1,0,0,0,1,0,1,1,1,1,1,1,0
Data 0,1,1,1,2,0,0,0,0,1,1,1,1,0,0,0
Data 0,1,1,1,1,0,2,2,2,1,1,1,1,2,2,0
Data 0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0
Data 0,1,1,1,1,2,1,1,1,1,1,1,1,1,1,0
Data 0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0
Data 0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0
Data 0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0
Data 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Et voila, ce premier gros "tuto" dédié à la création d'un moteur touche à sa fin ! Maintenant c'est à vous de vous amuser avec.