MSX Village forum

La Place des Développeurs moteur de jeu en basic création, optimisation

igal Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++

Inscrit le : 29/07/2010 à 17h19

Messages: 5492

Le 27/12/2010 à 22h22

Reprise du message précédent

Bonsoir à tous.

Après une petite visite sur le Wiki du village, j'ai découvert la Fonction STRIG (0) qui répond à l'appuie de la barre d'espace très simplement.
Le But étant d'appliquer une animation spécifique (un coup d'épée) suggérant une attaque!

J'ai abordé la chose de la façon suivante.
1) La détection doit se faire à chaque Cycle.
2) Lorsque l'appui de la [Barre d'espace] est détecté, une autre séquence d'animation doit être affichée (Le coup d'épée).

Je vous expose directement les modifications, puis l'explication qui la soutient. (Des erreurs sont possibles, merci de votre indulgence :oups)
Pour des raisons d'accessibilité, les avancées sont faites sur le moteur WINNIE de MsxOsaure (en attendant une lisibilité plus accessible du moteur MARIO FAT de Stapha :top )

ORIGINAL:
310 D=D+26:IF D = 208 THEN D = 0
D est le bloc à afficher, ici il s'incrémente de 26 pixels (largeur du bloque) et se limite à 208 (dernier pixel de la dernier image [8] à afficher).

MODIFICATIONS:
310 D=D+26:IF D = 208 THEN D = 52
J'ai décidé de consacrer 2 images aux coups d'épées (26+26=52), et 6 images par déplacement (de 52 à 208) Nord, Sud, Est, Ouest et enfin Statique.
Bien entendu, la matrice est dessinée en tenant compte de ces changements.

Pour plus de clarté, voici la Matrice:


La partie en rouge est celle affichée par défaut selon les directions choisis. Haut, Bas, Gauche et droite ainsi que pour les diagonales grâce aux commandes de la ligne 310.
La partie en noir sera jouée en cas d'appuie sur la [Barre d'espace] grâce aux commandes ne ligne 410.

ORIGINAL:
410 S=STICK(0)

MODIFICATIONS:
410 S=STICK(0):IFSTRIG(0)THEN D = 0
IF STRIG (0) THEN D = 0 signifie qu'en cas d'appui sur la [Barre d'espace], D prendra la valeur 0 et ce sera donc la partie en noir qui sera lue (Coups d'épée).

Le résulta est le suivant:
DEPLACEMENT DE LINK
STATUT MOUVEMENT ACTION COMENTAIRES
STATIQUE MARTEAU IMMOBILE Je n'arrive pas à inverser l'action et le mouvement!
HAUT DEPLACEMENT COUPS D EPEE La Face est dirigée vers le haut. Parfait
HAUT/DROIT DEPLACEMENT COUPS D EPEE La face est dirigée vers la droite. Parfait
DROIT DEPLACEMENT COUPS D EPEE La face est dirigée vers la droite. Parfait
DROIT/BAS DEPLACEMENT K.O La face est dirigée vers la droite, mais pas d'action pq???
BAS DEPLACEMENT COUPS D EPEE La face est dirigée vers le bas. Parfait
BAS/GAUCHE DEPLACEMENT COUPS D EPEE La face est dirigée vers la gauche. Parfait
GAUCHE DEPLACEMENT COUPS D EPEE La face est dirigée vers la gauche.Parfait
GAUCHE/HAUT DEPLACEMENT K.O La face est dirigée vers la gauche, mais pas d'actions pq???

Nb: J'ai essayé de changer la position de la [Face] en modifiant l'ordre d'application du déplacement en diagonale.
Fait [face à droite] lors du déplacement diagonal DROITE/BAS en suivant cet ordre:
Code TEXT :
2748 ' SP gestion mouvement: DROITE/BAS
2749 '
2750 P=POINT(INT((X+8)/16),203+INT((Y-4)/16))
2751 Q=POINT(INT((X+20)/16),203+INT((Y-4)/16))
2752 Y=Y+4*(P>6)*(Q>6)
2753 P=POINT(INT((X+8)/16)+1,202+INT((Y+8)/16))
2754 X=X-4*(P>6):A=38:RETURN


Fait [face en Bas] lors du déplacement diagonal DROITE/BAS en suivant cet ordre
Code TEXT :
2748 ' SP gestion mouvement: DROITE/BAS
2749 '
2750 P=POINT(INT((X+8)/16)+1,202+INT((Y+8)/16))
2751 X=X-4*(P>6)
2752 P=POINT(INT((X+8)/16),203+INT((Y-4)/16))
2753 Q=POINT(INT((X+20)/16),203+INT((Y-4)/16))
2754 Y=Y+4*(P>6)*(Q>6):A=152:RETURN


mais aucun changement dans les [Actions] diagonales Bas/Droite. (Pas de coups d'épée)

Voici la disquette qui vous donnera une idée plus précise!
Il faut exécuter ZELDAVE.BAS
ZELDA.zip


Si vous avez une idée, merci de votre aide :top Edité par igal Le 27/12/2010 à 22h36


Tiens... voila du boudin, voila du boudin, voila du boudin... :siffle
MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 781

Le 27/12/2010 à 23h12
Juste une petite question: pourquoi un déplacement en diagonale pour un jeu à la Zelda, ça reste rare, non?


Le MSXien le plus à l'ouest :fou ... ou presque :D
osaurer
   
Fabf Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++

Inscrit le : 24/08/2010 à 20h55

Messages: 4833

Le 27/12/2010 à 23h24
Il est vraiment magnifique ce Zelda :top
Je verrai bien tous les tableaux stockés sous forme d'images SC5 sur un cd
Ca allégerait le programme et le rendrait plus fluide
Ce serait (à ma connaissance) le premier jeu MSX sur CD :|
igal Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++

Inscrit le : 29/07/2010 à 17h19

Messages: 5492

Le 27/12/2010 à 23h33
Salut Msxosaure :)

Ben en fait, que ce soit Mario, Zelda ou autre, j'essais juste de progresser ;) Donc j'essais d'incrémenter un maximum de choses :top

Toi qui est le Papounet de ce code, t'as une idée concernant la diagonale Droit/Bas et Gauche/Haut qui n'affichent pas les coups d'épée?

Je me permet la même question concernant la Position [Statique] pour laquelle, je dois inverser [Action] et [Mouvement]
Lorsque j'interviens sur la ligne de temporisation pour la position [Statique], pour inverser les valeurs de D tel que:
L'action => D doit aller de 52 à 208 => If D = 208 then D = 52
Le mouvement [Statique]=> D doit aller de 0 à 51 (26+26) => If D = 52 then D = 0
Nb: Si tu as une solution m'imposant d'inverser l'ordre des dessins sur la matrice, je suis preneur aussi :D

J'avais bien trouvé la disposition qui semble être parfaitement logique, mais j'ai eu pour résulta un mouvement Haut+Coup d'épée.
J'ai bien pris la peine de Valoriser A = 0, mais il semble que le tout est purement et simplement remplacé par l'identique vers le HAUT!
Comme si on glisse d'un GOSUB à l'autre !!!???
Nb: Le Pb se pose pour les diagonales Bas/Droite et Haut/Gauche!

Merci. Edité par igal Le 27/12/2010 à 23h34


Tiens... voila du boudin, voila du boudin, voila du boudin... :siffle
MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 781

Le 27/12/2010 à 23h52
Je ne suis pas sur mon ordi, je n'ai pas explorer ton code, mais vérfie si tes gosub vont bien sur la bonne ligne suivant la direction.

Pour ce genre d'exercice il est préférable de créer une position statique pour chaque orientation du personnage (pas de mouvement) et de prendre en compte cette orientation pour le choix de l'animation "coup d'épée".


Le MSXien le plus à l'ouest :fou ... ou presque :D
osaurer
   
igal Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++

Inscrit le : 29/07/2010 à 17h19

Messages: 5492

Le 28/12/2010 à 00h49
Une brève vidéo du link => http://www.youtube.com/watch?v=1rBRlex3jWA

J'ai pris soin de conserver tes No de Lignes ainsi que la structure que tu as mis en place.
Un petit rappel du Code, avec les différents greffons.

Code TEXT :
1 'DEFUSR=&HD000:A=USR(0):FORP=0TO10:NEXT:POKE&HFD9F,201:SAVE"zelda.bas
10 VDP(10)=(0):WIDTH80:SCREEN5,2:COLOR 15,1,1:SETPAGE0,0:CLS:DEFINTA-Z
14 '
15 '            Chargement ecran des niveaux en page 3
16 '
20 SETPAGE0,3:BLOAD"fondw.sc5",S
24 '
25 '            Chargement ecran des "sprites" en page 2
26 '
30 SETPAGE0,1:BLOAD"winnie.sc5",S
40 COLOR=RESTORE
41 '
42 ' -----------INSERTION DES MUSIQUES ET SONS----------
43 GOTO 20000
44 'DEFUSR=&HD000:A=USR(0):'STOP LA MUSIQUE
45 DEFUSR=&HD000:A=USR(0):POKE&HCFFF,30:A=USR2(0):' MUSIQUE STAGE 6
54 '
55 '            Cr‚ation d'un sprite pour masque en page 0
56 '
60 SETPAGE0,0
70 FORI=&H7800TO&H781F:VPOKEI,255:NEXTI
80 PUTSPRITE0,(0,200),1,0
204 '
205 '            Initialisation des varibles et mise en place niveau 1
206 '
210 C=0:X=8:Y=132:D=52:A=0:N=0:M=0: ' D=52 Fait lire depuis le Pixel 52 de la matrice (animation)
240 GOSUB 10015
300 '
301 '            Boucle Principale:variable D pour animation du heros
302 '
310 D=D+26:IFD=208THEND=52: ' Lecture de la matrice jusqu au Pixel 208 et recommence au pixel 52 (animation)
400 '
401 '            BP:d‚placements heros: touche flech‚ + saut sous prog.
402 '
410 S=STICK(0):IFSTRIG(0)THEND=0: ' D=0 Fait lire depuis le Pixel 0 de la matrice (Actions coups d epee)
420 ONS+1GOSUB1500,2000,2030,2500,2750,3000,3250,3500,3750
500 GOSUB1000
600 '
601 '             BP:gestion rencontre avec un objet + saut SP
602 '
700 P=POINT(INT((X+15)/16),202+INT((Y+4)/16))
710 IFP<11THEN5000
800 IF X=224THENX=4:N=N+1:GOSUB10000
810 IF X=0THENX=220:N=N-1:GOSUB10000
894 '
895 '              BP:fin de la Boucle Principale
896 '
900 GOTO 310
1000 '
1001 '             SP affichage du personnage !
1002 '
1020 COPY(X,Y)-(X+34,Y+50),2TO(0,0),3
1030 COPY(D,A)-(D+25,A+37),1TO(4,4),3,TPSET
1040 COPY(0,0)-(34,50),3TO(X,Y),0
1050 RETURN
1100 '
1400 '
1401 '              SP gestion mouvement: statique!
1402 '
1500 A=0:FORI=0TO70:NEXTI:RETURN: ' Divers essais d inversion des Valeurs D pour inverser Action et Mouvement.
1900 '
1901 '              SP gestion mouvement: HAUT
1902 '
2000 P=POINT(INT((X+8)/16),202+INT(Y/16))
2010 Q=POINT(INT((X+20)/16),202+INT(Y/16))
2020 Y=Y+4*(P>6)*(Q>6)*(Y>0):A=76:RETURN
2027 '
2028 ' SP gestion mouvement: HAUT/DROITE
2029 '
2030 P=POINT(INT((X+8)/16),202+INT(Y/16))
2031 Q=POINT(INT((X+20)/16),202+INT(Y/16))
2032 Y=Y+4*(P>6)*(Q>6)*(Y>0)
2033 P=POINT(INT((X+8)/16)+1,202+INT((Y+8)/16))
2034 X=X-4*(P>6):A=38:RETURN
2400 '
2401 '              SP gestion mouvement: DROITE
2402 '
2500 P=POINT(INT((X+8)/16)+1,202+INT((Y+8)/16))
2520 X=X-4*(P>6):A=38:RETURN
2747 '
2748 ' SP gestion mouvement: DROITE/BAS
2749 '
2750 P=POINT(INT((X+8)/16),203+INT((Y-4)/16))
2751 Q=POINT(INT((X+20)/16),203+INT((Y-4)/16))
2752 Y=Y+4*(P>6)*(Q>6)
2753 P=POINT(INT((X+8)/16)+1,202+INT((Y+8)/16))
2754 X=X-4*(P>6):A=38:RETURN
2900 '
2901 '              SP gestion mouvement: BAS
2902 '
3000 P=POINT(INT((X+8)/16),203+INT((Y-4)/16))
3010 Q=POINT(INT((X+20)/16),203+INT((Y-4)/16))
3030 Y=Y+4*(P>6)*(Q>6):A=152:RETURN
3247 '
3248 ' SP gestion mouvement: BAS/GAUCHE
3249 '
3250 P=POINT(INT((X+8)/16),203+INT((Y-4)/16))
3251 Q=POINT(INT((X+20)/16),203+INT((Y-4)/16))
3252 Y=Y+4*(P>6)*(Q>6)
3253 P=POINT(INT((X+20)/16)-1,202+INT((Y+8)/16))
3254 X=X+4*(P>6):A=114:RETURN
3400 '
3401 '              SP gestion mouvement: GAUCHE
3402 '
3500 P=POINT(INT((X+20)/16)-1,202+INT((Y+8)/16))
3520 X=X+4*(P>6):A=114:RETURN
3747 '
3748 ' SP gestion mouvement: GAUCHE/HAUT
3749 '
3750 P=POINT(INT((X+8)/16),202+INT(Y/16))
3751 Q=POINT(INT((X+20)/16),202+INT(Y/16))
3752 Y=Y+4*(P>6)*(Q>6)*(Y>0)
3753 P=POINT(INT((X+20)/16)-1,202+INT((Y+8)/16))
3754 X=X+4*(P>6):A=114:RETURN
4900 '
4901 '              SP gestion rencontre avec objet
4902 '
5000 IF P=10THEN6000  ' si trou -> SP tombe
5002 POKE&HFD9F,201
5005 PSET(INT((X+15)/16),202+INT((Y+4)/16)),15:B=P*6:F=P*5
5010 COPY(240,191)-(255,206),1TO((INT((X+15)/16))*16,(INT((Y+36)/16))*16),2
5020 COPY(208,P*16-112)-(223,P*16-97),1TO(C*16+32,196),0
5030 POKE&HFD9F,201:POKE&HFDA0,&H6:POKE&HFDA1,&HD0:POKE&HFD9F,&HC3
5035 POKE&HCFFF,82:A=USR2(0)
5040 C=C+1
5100 GOTO 310
5900 '
5901 '              SP chute dans le trou
5902 '
6000 FORI=0TO36STEP2
6020 COPY(X,Y)-(X+34,Y+50),2TO(0,0),3
6030 COPY(D,A)-(D+25,A+37-I),1TO(4,4+I),3,TPSET
6040 COPY(0,0)-(34,50),3TO(X,Y),0
6050 A=A+38:IFA=190THENA=38
6060 B=I+40:POKE&HCFFF,70:A=USR2(0)
6065 IFPLAY(0)=-1THEN6065
6070 NEXT
6080 M=0:N=0
6090 LINE(32,196)-(255,212),1,BF
6100 GOTO 210
10000 '
10001 '              SP Mise en place du d‚cor
10002 '
10010 COPY(0,200)-(15,211),0TO(M*16,200),3
10015 COPY(N*16,200)-(15+N*16,211),3TO(0,200),0
10017 POKE&HCFFF,69:A=USR2(0)
10020 FORI=0TO15:FORJ=0TO11:P=POINT(I,J+200):COPY(P*16,191)-(15+P*16,206),1TO(I*16,J*16),0
10030 NEXTJ:NEXTI
10040 COPY(0,0)-(256,192),0TO(0,0),2
10050 M=N
10055 'BEEP
10060 RETURN
19990 GOTO 19990
20000 '---------DEBUT DE SALAMANDER DEMO MODIFIE----------------
20010 'POKE&HFBB1,1: 'EMPECHE CONTROL+STOP
20030 BLOAD"1.006":DEFUSR4=&HD600:' CHARGE LE PLAYER ?
20040 BLOAD"1.007":U=USR4(1):' CHARGE SONS ET MUSIQUES
20050 BLOAD"1.008":U=USR4(2):' CHARGE SONS ET MUSIQUES
20060 BLOAD"1.009":U=USR4(3):' CHARGE SONS ET MUSIQUES
20070 BLOAD"1.010":U=USR4(4):' CHARGE SONS ET MUSIQUES
20080 BLOAD"1.011":FORT=0TO2000:NEXT
20090 DEFUSR=&HD000:A=USR(0): 'PREREQUIS ARRET LA MUSIQUE
20100 DEFUSR2=&HD003:' PREREQUIS FONCTION INCONNUE
20101 POKE&HFD9F,201
20105 POKE&HFDA0,&H6:POKE&HFDA1,&HD0:POKE&HFD9F,&HC3
20115 ' LISTE COMPLETE DES MUSIQUES ET SONS DANS POKE SALAMANDER
20117 '
20120 DEFUSR=&HD000:A=USR(0):POKE&HCFFF,32:A=USR2(0):' MUSIQUE STAGE 6
20750 'POKE&HCFFF,67:A=USR2(0):' EXPLOSION D'ENNEMI MOYENNE
20755 '
20760 'DEFUSR=&HD000:A=USR(0):FORP=0TO10:NEXT:POKE&HFD9F,201:'PERMET ACCES DISK MAIS ARRETER MUSIQUE AVANT
20770 GOTO 44:' RETOUR A L ANIMATION
20800 '
20810 '---------FIN DE SALAMANDER DEMO MODIFIE-------------------
Edité par igal Le 28/12/2010 à 00h49


Tiens... voila du boudin, voila du boudin, voila du boudin... :siffle
Jipe Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 02/10/2009 à 19h41

Messages: 10731

Le 28/12/2010 à 11h19
pourquoi Link tape t'il du marteau quand il est a l'arrêt ?
une position sur place rendrait mieux
le MSX a 2 boutons de tir on peut sortir l'épée avec le 1er et taper du marteau avec le second
au clavier on peux tester une touche ( exemple a la konami M )


:noel
Site web    
igal Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++

Inscrit le : 29/07/2010 à 17h19

Messages: 5492

Le 28/12/2010 à 15h41
Salut Jipe.

Justement...
Le lecture normale est D = 52 + 26 et si D = 208 alors D = 52
Ce qui Affiche les blocs depuis le Pixel 52 jusqu'au pixel 208 (soit 6 X 26 Blocs) pour les animations des mouvements....
Jusque la pas de problèmes sauf que par manque de place sur la MATRICE, dans les même Longitudes ( 52 à 208) se trouve l'animation destiné à l'[action] au lieu du Mouvement [Statique].

Je dois donc trouver une solution pour Inverser [Rigoureusement] la Valeur de D lorsque la ligne [STATIQUE] doit être affichée.
Concrètement, je dois passer de:
D = 52 ( Premier pixel de tous les mouvements sauf pour STATIQUE )
210 C = 0 : X = 8 : Y = 132 : D = 52 : A = 0 : N = 0 : M = 02

D = D + 26 : IF D = 208 THEN D = 52 ( Dernier et Premier pixel de tous les mouvements sauf pour STATIQUE )
310 D = D + 26 : IF D = 208 THEN D = 52

IF STRIG (0) THEN D = 0 (Si la barre d'espace est appuyée, le Premier pixel de toutes les actions sauf pour STATIQUE)
410 S = STICK (0) : IF STRIG (0) THEN D = 0
420 ONS+1GOSUB1500,2000,2030,2500,2750,3000,3250,3500,3750
500 GOSUB1000

Je dois obtenir ca:
IF STRIG (0) THEN D = 52 (Si la barre d'espace est appuyée, le Premier pixel de l'action STATIQUE de LINK )
410 S = STICK (0) : IF STRIG (0) THEN D = 0 AND GOSUB 1501

1401 ' SP gestion MOUVEMENTt: statique!
1402 '
1500 D = D + 26 : IF D + 52 THEN D = 0 : A = 0 : FOR I = 0 TO 70 : NEXT I : RETURN

1501 ' SP gestion COUPS DE MASSUE : statique!
1502 '
1503 D = D + 26 : IF D = 208 THEN D = 0 : A = 0 : FOR I = 0 TO 70 : NEXT I : RETURN

Il me semble avoir déjà essayé ça, mais le résulta a été de voir LINK se déplace et donne les coups d'épée vers le HAUT au lieu de STATIC.

Voilà. J'espère avoir été assez clair, des fois, j'ai du mal a me suivre :D


Tiens... voila du boudin, voila du boudin, voila du boudin... :siffle
Jipe Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 02/10/2009 à 19h41

Messages: 10731

Le 28/12/2010 à 15h58
il te reste plein de place en page 3 pour mettre des animes ou des petits montres ;)

regarde la vue de la page 3 en lançant link.bas dans cette version ou juste la ligne 60 a été changée link.zip

et puis moi j'aime bien cette version labyrinthe ou l'on découvre le jeu peu a peu :love


:noel
Site web    
igal Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++

Inscrit le : 29/07/2010 à 17h19

Messages: 5492

Le 04/01/2011 à 12h22
Jipe :
il te reste plein de place en page 3 pour mettre des animes ou des petits montres ;)



regarde la vue de la page 3 en lançant link.bas dans cette version ou juste la ligne 60 a été changée link.zip



et puis moi j'aime bien cette version labyrinthe ou l'on découvre le jeu peu a peu :love




Très intéressant de voir ce qui se passe en arrière plan. :top

J'ai modifié quelques formules de sortes à afficher la fenêtre de "travail" en page 0 (celle visible donc!)

J'en ai profité aussi pour améliorer les graphismes de Zelda.SC5 (deux blocs de 16X16 n'étaient pas enrichis de graphismes particuliers)

Les programmes sont en .ASC ils sont donc ouvrables avec le Bloc Note Windows.

Il y a quatre versions dans la disquette:



Mod pesanteur.

Mod Pesanteur fenêtré.

Mod aventure.

Mod aventure fenêtré.



J'ai limité le nombre de Vies à 3 en procédant:

Code TEXT :
 
209 V=3
 
6099 V=V-1:IFV=0THEN7000
6100 GOTO 210
7000 SCREEN0:PRINT"                GAME OVER
7001 GOTO7001 
 




Pour ce qui est de la pesanteur, j'ai revu mon approche en observant:

"Les conséquences visibles de la pesanteur, plutôt que la physique auquel elle doit répondre"

Le but étant de minimiser la boucle principale, cette solution est trop gourmande en ressources.



Principe de La Simulation par le Visuel:

Pour simuler une conséquence physique de la pesanteur, j'avais implanté l’équation [Direction Bas] dans la [Boucle Principale].

Il en résultait la nécessité d'augmenter les valeurs de déplacements Haut, Haut Droit et Haut Gauche pour contrecarrer cette force, sans quoi, Link ne pouvait pas décoller du sol :moue .

L'effet est très réussi, mais le moteur en est très ralenti.



Principe des Conséquences Visuelles:

Visuellement, une pesanteur à pour effet de faire [Chuter] dans lors d'un stationnement ou mouvement non opposé dans le vide.

[Statique] dans le Vide => Chute verticale.

[Droite] dans le vide => Chute et déplace vers la droite.

[Gauche ] dans le vide => Chute et déplace vers la gauche.

Il suffit donc d'appliquer cette logique pour obtenir un résulta visuel approprié sans charger la boucle principale.



Tout n'est pas parfait, mais je trouve le résulta plutôt encourageant!

Voici la disquette => ZELDAF.zip

Et voilà le résulta en image:





L'ancienne Boucle principale se présente comme suit:

Code TEXT :
 
310 D=D+26:IFD=208THEND=0
400 '
401 '            BP:d‚placements heros: touche flech‚ + saut sous prog.
402 '
410 S=STICK(0)
420 ONS+1GOSUB1500,2000,2500,2500,2500,3000,3500,3500,3500
500 GOSUB1000
600 '
601 '             BP:gestion rencontre avec un objet + saut SP
602 '
700 P=POINT(INT((X+15)/16),202+INT((Y+4)/16))
710 IFP<11THEN5000
800 IF X=224THENX=4:N=N+1:GOSUB10000
810 IF X=0THENX=220:N=N-1:GOSUB10000
894 '
895 '              BP:fin de la Boucle Principale
896 '
900 GOTO 310
1000 '
1001 '             SP affichage du personnage !
1002 '
1020 COPY(X,Y)-(X+34,Y+50),2TO(0,0),3
1030 COPY(D,A)-(D+25,A+37),1TO(4,4),3,TPSET
1040 COPY(0,0)-(34,50),3TO(X,Y),0
1050 RETURN
 


Une fois les REM soustraits on obtient ceci:

Code TEXT :
 
310 D=D+26:IFD=208THEND=0
410 S=STICK(0)
420 ONS+1GOSUB1500,2000,2500,2500,2500,3000,3500,3500,3500
500 GOSUB1000
700 P=POINT(INT((X+15)/16),202+INT((Y+4)/16))
710 IFP<11THEN5000
800 IF X=224THENX=4:N=N+1:GOSUB10000
810 IF X=0THENX=220:N=N-1:GOSUB10000
900 GOTO 310
1020 COPY(X,Y)-(X+34,Y+50),2TO(0,0),3
1030 COPY(D,A)-(D+25,A+37),1TO(4,4),3,TPSET
1040 COPY(0,0)-(34,50),3TO(X,Y),0
1050 RETURN
 


Après réflexion, j'en suis arrivé à implanté l'affichage du personnage (1020, 1030, 1040, 1050) à intérieur de la boucle principale, et contracté ce qui pouvait l'être. et obtenir ceci:

Code TEXT :
310 D=D+26:IFD=208THEND=52
410 S=STICK(0):ONS+1GOSUB1500,2000,2030,2500,2750,3000,3250,3500,3750:IFX=224THENX=4:N=N+1:GOSUB10000
500 COPY(X,Y)-(X+48,Y+48),2TO(0,0),3:COPY(D,A)-(D+25,A+37),1TO(4,4),3,TPSET:COPY(0,0)-(48,48),3TO(96,0),0:P=POINT(INT((X+15)/16),202+INT((Y+4)/16)):IFP<11THEN5000
810 IFX=0THENX=220:N=N-1:GOSUB10000
900 GOTO 310
Edité par igal Le 04/01/2011 à 14h04


Tiens... voila du boudin, voila du boudin, voila du boudin... :siffle
igal Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++

Inscrit le : 29/07/2010 à 17h19

Messages: 5492

Le 05/01/2011 à 11h48
La même approche avec 6 fenêtres de 48 X 48 Pixels toujours avec le moteur Winnie (Msxosaure) :oups
http://www.youtube.com/watch?v=fYtdf6Oh4D0

La même chose avec le Moteur Mario Fat (Révision Stapha) Une seule fenêtre de 100 X 100 :top
http://www.youtube.com/watch?v=xLbU0hhjFlo Edité par igal Le 05/01/2011 à 11h48


Tiens... voila du boudin, voila du boudin, voila du boudin... :siffle
MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 781

Le 07/01/2011 à 16h11
Joli travail igal ce qui prouve que tu maitrise bien la chose maintenant. :top

à toi aussi de faire évoluer le moteur d'origine. il devient facile de faire un jeu style: je ramasse un objet(clé) qui me permet de détruire un autre (porte) et jouer sur la stratégie pour avancer dans le jeu. Je ne me rappelle plus le nom du jeu paru sur un Disk Station qui utilisait ce mode (genre la baguette détruit le fantôme, etc...)

Avec quelques évolutions et une accélération X-basic tu peux faire ausssi un joli jeu en scrolling plus ou moins fluide ;)


Le MSXien le plus à l'ouest :fou ... ou presque :D
osaurer
   
Stapha Membre non connecté

Touriste

Rang

Avatar

Inscrit le : 22/11/2010 à 14h17

Messages: 35

Le 11/01/2011 à 12h40
Bonjour à tous,

Tout d'abord, je vous adresse à tous mes meilleurs voeux pour cette année 2011, en vous souhaitant bonheur, santé et réussite.

Maintenant que la saison des réveillons (et des rhumes et grippes...) est passée, je peux reprendre l'explication que j'ai promise à Igal.

Cela va prendre plusieurs post, puisque je vais optimiser encore le code.

Première étape : redéfinir les ecrans de sprites et de tiles.

Les sprites de Mario étaient positionnés tous les 26 pixels et toutes les 37 lignes.
J'ai redéfini la page pour les positionner tous les 32 pixels et toutes les 36 lignes. J'ai calé chaque sprite sur la ligne du haut (pour diminuer les effets de clipping, on verra ça plus tard)
J'ai inclus les définitions des tableaux juste au-dessus des tiles.

Avec tout ça, j'ai perdu les 3 motifs à utiliser quand Mario ramasse un objet.

Ce n'est pas grave car j'ai utilisé un autre système : charger en début le panneau des scores. Ce panneau contient les 3 dessins (et uniquement ça pour l'instant) à coté desquels des compteurs ont fait leur apparition.

J'ai ensuite changé l'ordre des tiles : les objets correspondent aux tiles 12 à 14 et le trou au tile 15 (plus pratique pour construire le tableau des actions car il y a action dès que le n° du tile > 11)

Voici ce que donne l'écran des sprites, tiles et tableaux :

Et voici ce que donne le jeu :


Pour rappel, voici la boucle principale :

Code :
310 D=D+32:IFD=256THEND=0 
320 S=STICK(0):NX=X+DX(S):NY=Y+DY(S):A=VA(S) 
330 IFCO((NX+24)/8,(NY+12)/8)THENX=NX:Y=NY 
340 COPY(X,Y)-(X+34,Y+45),2TO(0,0),3 
350 COPY(D,A)-(D+25,A+37),1TO(4,4),3,TPSET 
360 COPY(0,0)-(34,45),3TO(X,Y),0 
370 ONAC((X+14)/16,(Y+1)/16)GOTO310,510,610,710,710,710,810


La seule différence vient de la première ligne, dans laquelle l'incrément est passé de 26 à 32 et la valeur max de 208(26x8) à 256 (32x8).

Au prochain post, on commence l'optimisation par cette ligne justement (et on verra l'utilité de passer de 26 à 32)...
Site web    
Stapha Membre non connecté

Touriste

Rang

Avatar

Inscrit le : 22/11/2010 à 14h17

Messages: 35

Le 11/01/2011 à 12h46
Optimisation du moteur : Il suffit de demANDer...;)

Arretons nous sur la première instruction de la boucle principale

310 D=D+32:IFD=256THEND=0

Et étudions les valeurs que va prendre D

1: 32
2: 64
3: 96
4: 128
5: 160
6: 192
7: 224
8: 0

Jusque là, y a rien qui saute aux yeux. Mais si on affiche ces valeurs en binaire ?
ça donne :

1: 00000000 00100000
2: 00000000 01000000
3: 00000000 01100000
4: 00000000 10000000
5: 00000000 10100000
6: 00000000 11000000
7: 00000000 11100000
8: 00000000 00000000

Toujours rien ? ok : étudions ce qui se passerait à la 8eme itération s'il n'y avait pas le test "IFD=256THEND=0"

8: 00000001 00000000

Là on remarque 2 choses :
1) les 8 premiers bits ont la bonne valeur, c'est le 9eme qui pose problème.
2) ce bit (et tous les autres après lui) ne devrait jamais être à 1

Conclusion :

Si on efface systématiquement le 9eme bit à chaque fois qu'on ajoute 32, on aura les mêmes valeurs qu'avant d'avoir enlevé le test.

Question :

Comment effacer ce bit ?

Reponse :

On utilise l'opérateur AND. Rappellons que :

0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1

Ce qui revient à dire que X AND 0 efface le bit X et X AND 1 le préserve.

Or, ce qu'on veut faire c'est effacer le 9eme bit tout en préservant les 8 premiers.

Si on fait 00000001 00000000 AND 00000000 11111111, ça donne 00000000 00000000

Et si on fait, par exemple, 00000000 11100000 AND 00000000 11111111, ça donne 00000000 11100000

Il suffit donc d'ajouter 32 à D puis de faire un AND 00000000 11111111 à la valeur obtenue et le tour est joué.

00000000 11111111 ça donne 255 en décimal.

Notre ligne devient donc :

310 D=(D+32)AND255

Ce qui est plus rapide evidemment.

A bientot, pour de nouvelles optimisations...
Site web    
Stapha Membre non connecté

Touriste

Rang

Avatar

Inscrit le : 22/11/2010 à 14h17

Messages: 35

Le 11/01/2011 à 16h33
Explications et une très légère optimisation qui FONCTIONne... ;)

On passe à la ligne suivante :

320 S=STICK(0):NX=X+DX(S):NY=Y+DY(S):A=VA(S)

Cette ligne permet de calculer les coordonnées de Mario en fonction du mouvement de la manette.

Le fonctionnement est très simple : NX contiendra X, X+4 ou X-4 selon la valeur de STICK(0).
Si on étudie comment est initialisé le tableau DX, on se rend compte qu'il contient :
- 4 dans les éléments 2, 3 et 4. Ce qui correspond à la valeur que retournera STICK(0) quand la manette ira en haut et à droite

(2), a droite (3) ou en bas et à droite (4).
- -4 dans les éléments 6, 7 et 8. Ce qui correspond à la valeur que retournera STICK(0) quand la manette ira en bas et à gauche

(6), a gauche (7) ou en haut et à gauche (8).

X n'est pas modifié directement car pour l'instant on calcule les futurs coordonnées mais on ne sait pas encore si Mario pourra y aller. D'ou l'utilisation de la variable NX.

Le même principe est appliqué pour Y. Cette fois on utilise le tableau DY (initalisé avec -4 pour les 3 valeurs de stick(0) qui correspondent à un mouvement vers le haut et avec +4 pour les 3 qui correspondent à un mouvement vers le bas). La nouvelle valeur sera stockée dans NY.

Ce qui signifie qu'on peut autoriser ou non la gestion des diagonales simplement en modifiant la façon dont DX et DY sont initialisés. On peut même modifier ces valeurs en cours de jeu pour , par exemple, faire accélerer ou ralentir la vitesse de déplacement.

Et le même principe est utilisé avec A. Rappelons que A contient la ligne de sprite à utiliser. Chaque ligne correspond à un sens de mouvement (et D correspond à la colonne)

Normalement, il est plus rentable de stocker la valeur de STICK(0) dans la variable S car la lecture d'une variable est plus rapide que l'appel une fonction telle que STICK(0) et le gain devrait être supérieur à la perte engendrée par l'affectation...

Normalement ! Car en MSX basic ce n'est pas le cas !

J'ai fait des essais qui ont montré qu'il valait mieux appeler 3 fois STICK(0).

J'ai donc remplacé la ligne par

320 NX=X+DX(STICK(0)):NY=Y+DY(STICK(0)):A=VA(STICK(0))

C'est étrange mais ça va plus vite d'utiliser la fonction.

La prochaine fois nous verrons comment l'ordre d'execution d'une série d'instruction peut influer sur la vitesse...
Site web    
Stapha Membre non connecté

Touriste

Rang

Avatar

Inscrit le : 22/11/2010 à 14h17

Messages: 35

Le 11/01/2011 à 16h49
Encore une optimisation ? Ok, si c'est un ORDRE... ;)

Etudions les 3 lignes suivantes :

340 COPY(X,Y)-(X+34,Y+45),2TO(0,0),3
350 COPY(D,A)-(D+25,A+37),1TO(4,4),3,TPSET
360 COPY(0,0)-(34,45),3TO(X,Y),0

L'instruction COPY est utilisée 3 fois. Comment fonctionne-t-elle ? Et bien l'interpréteur basic calcule une série de valeurs à placer dans les registres du VDP et lance la copie. C'est le VDP et non le Z80 qui réalise cette copie. Et dès que c'est lancé, l'interpréteur passe à l'instruction suivante sans attendre que le VDP ait terminé (j'ai fait des tests de vitesse qui l'ont confirmé). C'est un très bon point pour le basic MSX !

Mais que ce passe-t-il si l'instruction suivante est un COPY (ou une autre instruction qui sera exécutée par le VDP, comme LINE ou PSET) ? N'y a-t-il pas risque de gener le VDP en accédant à ces registres alors qu'il est en train de travailler ? Ou est-ce que le traitement que le VDP était en train de faire est interrompu ?
Heureusement rien de tout ça. Et pour l'eviter c'est très simple : à chaque instruction qui fait appel au VDP, l'interpréteur attend que la commande en cours soit terminée (s'il y en a une) pour envoyer la suivante.

Donc, quand on enchaine 2 COPY, il y a des moments ou le Z80 ne fait rien du tout. Dommage de perdre du temps comme ça... Alors que c'est facilement évitable : il suffit de glisser des instructions entre les COPY ! Avec un COPY qui traiterait tout l'écran, on aurait le temps d'en faire plusieurs. Mais avec ces 3 COPY, une seule suffira.

J'ai donc réagencé la boucle principale ainsi :

Code :
310 NX=X+DX(STICK(0)):NY=Y+DY(STICK(0))
320 IFCO(NX/4+6,(NY+34)/16)THENX=NX:Y=NY
330 COPY(X,Y)-(X+34,Y+45),1TO(0,0),3:A=VA(STICK(0))
340 COPY(D,A)-(D+25,A+37),2TO(4,4),3,TPSET:D=(D+32)AND255
350 COPY(0,0)-(34,45),3TO(X,Y),0
360 ONAC((X+12)/16,Y/16+1)GOTO310,510,610,710,710,710,810


Cette fois la valeur de A est déterminé juste avant qu'on l'utilise et la valeur de D... juste après ! mais ce n'est pas grave : D est une variable qui boucle sur une série de valeur, donc ça ne change rien. A la limite c'est même plus cohérent : la première valeur de D qui sera utilisée est 0 alors qu'avant c'était 32. Mais visuellement ça ne change rien (si ça avait été le cas, il aurait suffit d'initialiser D à 32 en début de programme).

On a donc gagné du temps juste en changeant l'ordre des instructions....

Et après ? Peut-on encore optimiser ? Et bien oui, mais il va falloir changer le système d'affichage de Mario. C'est ce qu'on verra au prochain post...
Site web    
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie