Adapter le "Télécran" pour en faire un jeu TRON
Quelles sont les différences entre un télécran et le jeu TRON dans la gestion du tracé? J'en vois deux : - Le point se déplace sans pouvoir s'arrêter. - Le jeu s'arrête quand le point recontre le bord de l'écran ou sa propre trace. Il y a d'autres subtilités dans le contrôle de la 'moto' comme la façon de changer de direction. Nous allons conserver notre curseur et les quatre directions dans un premier temps. Première modification, faire avancer le point en permanence Pour faire avancer le point en permanence, nous avons besoin de deux variables correspondant aux incréments à apporter à X et Y à chaque itération. Nous allons aussi initialiser le premiermouvement vers le haut, donc une décrémentation de Y. ld hl,0 : ld (increment_x),hl ; init! ld hl,-1 : ld (increment_y),hl ; initialiser le premier mouvement vers le haut!... increment_x defw 0 increment_y defw 0Notre routine de gestion des touches se simplifie, plus besoin d'utiliser XL car nous allons afficher le point à chaque fois, on supprimer des lignes pour arriver à ça. ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : call z,gererHaut ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : call z,gererBas ld a,(OCTET_CURSEUR_DROITE) : and BIT_CURSEUR_DROITE : call z,gererDroite ld a,(OCTET_CURSEUR_GAUCHE) : and BIT_CURSEUR_GAUCHE : call z,gererGaucheNos routines de gestion haut, bas, droite, gauche se simplifient, elles se contentent inconditionnellement de changer les valeurs des incréments. Chaque routine se charger d'effacer l'autre incrément pour éviter les diagonales dont nous ne voulons plus dans ce jeu! gererHaut ld hl,-1 : ld (increment_y),hl : ld hl,0 : ld (increment_x),hl : ret gererBas ld hl,1 : ld (increment_y),hl : ld hl,0 : ld (increment_x),hl : ret gererGauche ld hl,-1 : ld (increment_x),hl : ld hl,0 : ld (increment_y),hl : ret gererDroite ld hl,1 : ld (increment_x),hl : ld hl,0 : ld (increment_y),hl : retEffectuer le mouvement, contrôler la position avec les bords écranEnsuite, après la gestion des touches, il faut ajouter les incréments aux positions et aussi tester tous les cas de bord écran. Si on sort de la zone, on ira vers une routine de FinDuJeu. J'en profite pour introduire une comparaison 16 bits avec SBC HL,DE qui positionne le flag Z en cas de zéro. ld hl,(positionx) : ld de,(increment_x) : add hl,de : ld (positionx),hl ld a,h : cp #FF : jp z,FinDuJeu ; si HL est négatif, alors on quitte xor a : ld de,320 : sbc hl,de : jp z,FinDuJeu ; si HL vaut 320 alors on est sorti de l'écran ld hl,(positiony) : ld de,(increment_y) : add hl,de : ld (positiony),hl ld a,h : cp #FF : jp z,FinDuJeu ; si HL est négatif, alors on quitte ld a,l : cp 200 : jp z,FinDuJeu ; si HL vaut 200, on est sorti de l'écran et on quitte; après les contrôles, il faut aussi changer le saut, on ne revient plus on clavier! jp AfficherPoint ; revenir tout le temps à l'affichage!Gérer la collision avec sa propre trace Pour terminer, il manque un contrôle indispensable, à savoir vérifier que le point que nous allons écrire n'existe pas déjà à l'écran. On ajoute un test avant d'afficher le point. ld a,(hl) : and c ; on ne conserve que l'éventuel point qu'on veut mettre cp c : jp z,FinDuJeu ; si le point était déjà là (flag Z pour comparaison réussie), on quitte ld a,(hl) : or c : ld (hl),a ; fusionner le pixel à l'écranArf, il nous faut aussi une routine pour terminer le jeu! Dans un premier temps, je propose simplement d'attendre une seconde ou deux. FinDuJeu ld xl,100 ; 100 VBL = 2 secondes .attente call waitVBLstart : dec xl : jr nz,.attente jp EffaceEcran ; on recommence le jeu!Et voici le source complet du TRON BUILDSNA : BANKSET 0 ORG #100 : RUN #100;====================================== EffaceEcran ;====================================== ld hl,#C000 xor a ; A=0 .loop ld (hl),a ; écrire #00 à l'adresse pointée par HL inc l ; incrémenter seulement L positionne le flag Z une fois revenu à zéro jr nz,.loop ; on boucle donc tant que L est différent de zéro inc h ; même chose pour H, sauf que nous savons ici que L vaut zéro jr nz,.loop ; tant que H ne vaut pas zéro on reboucle ; ici nous avons HL=#0000 nous sommes revenus au début de la mémoire, l'écran est effacer, on s'arrête ; initialiser les coordonnées de notre point ld hl,160 : ld (positionx),hl ld hl,100 : ld (positiony),hl ; position de départ au centre de l'écran ld hl,0 : ld (increment_x),hl ; init! ld hl,-1 : ld (increment_y),hl ; initialiser le premier mouvement vers le haut! ;====================================== AfficherPoint ;====================================== ld bc,(positionx) ld hl,(positiony) call CalculeAdressePixel ld a,(hl) : and c ; on ne conserve que l'éventuel point qu'on veut mettre cp c : jp z,FinDuJeu ; si le point était déjà là, on quitte ld a,(hl) : or c : ld (hl),a ; fusionner le pixel à l'écran call waitVBLstart ; 50Hz call waitVBLstart ; 25Hz call waitVBLstart ; 17Hz allez on speed un peu à 17 images par seconde :) ;====================================== LireLeClavier ;====================================== call lectureMatriceClavier OCTET_CURSEUR_HAUT equ matriceClavier : BIT_CURSEUR_HAUT equ 1 OCTET_CURSEUR_DROITE equ matriceClavier : BIT_CURSEUR_DROITE equ 2 OCTET_CURSEUR_BAS equ matriceClavier : BIT_CURSEUR_BAS equ 4 OCTET_CURSEUR_GAUCHE equ matriceClavier+1 : BIT_CURSEUR_GAUCHE equ 1 OCTET_TOUCHE_ESPACE equ matriceClavier+5 : BIT_TOUCHE_ESPACE equ 128 ; si on appuie sur Espace, on revient à l'effacement de l'écran ld a,(OCTET_TOUCHE_ESPACE) : and BIT_TOUCHE_ESPACE : jp z,EffaceEcran ; ; ; touches du curseur ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : call z,gererHaut ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : call z,gererBas ld a,(OCTET_CURSEUR_DROITE) : and BIT_CURSEUR_DROITE : call z,gererDroite ld a,(OCTET_CURSEUR_GAUCHE) : and BIT_CURSEUR_GAUCHE : call z,gererGauche ; gérer le déplacement du point et le test des bords ld hl,(positionx) : ld de,(increment_x) : add hl,de : ld (positionx),hl ld a,h : cp #FF : jp z,FinDuJeu ; si HL est négatif, alors on quitte xor a : ld de,320 : sbc hl,de : jp z,FinDuJeu ; si HL vaut 320 alors on est sorti de l'écran ld hl,(positiony) : ld de,(increment_y) : add hl,de : ld (positiony),hl ld a,h : cp #FF : jp z,FinDuJeu ; si HL est négatif, alors on quitte ld a,l : cp 200 : jp z,FinDuJeu ; si HL vaut 200, on est sorti de l'écran et on quitte ; jp AfficherPoint ; revenir tout le temps à l'affichage! ;====================================== ; sous-routines de gestion des touches ;====================================== gererHaut ld hl,-1 : ld (increment_y),hl : ld hl,0 : ld (increment_x),hl : ret gererBas ld hl,1 : ld (increment_y),hl : ld hl,0 : ld (increment_x),hl : ret gererGauche ld hl,-1 : ld (increment_x),hl : ld hl,0 : ld (increment_y),hl : ret gererDroite ld hl,1 : ld (increment_x),hl : ld hl,0 : ld (increment_y),hl : ret ;====================================== CalculeAdressePixel ;====================================== ; BC=coordonnée X (0-319) ; HL=coordonnée Y (0-199) ld de,tableau add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2 add hl,de ld a,(hl) : inc hl ld h,(hl) : ld l,a ; HL=adresse de la ligne ld a,c ; on sauvegarde le X avant de diviser par 4 srl bc : srl bc ; diviser le X par 4 pour avoir l'octet en mode 1 add hl,bc ld c,%10000000 ; encre 1 pour le pixel mode 1 le plus à gauche dans l'octet and 3 ; avec le modulo 4 on va savoir quel est le pixel en partant de la gauche jr z,.noShift .Shift srl c dec a jr nz,.Shift .noShift ret ; HL=adresse écran aux coordonnées X/Y données et C est le pixel d'encre 1 ;------------------- adresse_ecran=#C000 largeur_ecran=80 tableau repeat 25 repeat 8 defw adresse_ecran adresse_ecran+=#800 rend adresse_ecran+=largeur_ecran adresse_ecran-=#4000 rend ;============== waitVBLstart ;============== ld b,#F5 .loop in a,(c) : rra : jr c,.loop ; attendre l'absence de VBL ;============== waitVBL ;============== ld b,#F5 .loop in a,(c) : rra : jr nc,.loop ; attendre la VBL ret ;====================================== FinDuJeu ;====================================== ld xl,100 ; 100 VBL = 2 secondes .attente call waitVBLstart : dec xl : jr nz,.attente jp EffaceEcran ; on recommence le jeu! ;====================================== lectureMatriceClavier ;====================================== ld hl,matriceClavier ld bc,#f782 out (c),c ld bc,#f40e ld e,b out (c),c ld bc,#f6c0 ld d,b out (c),c out (c),0 ld bc,#f792 out (c),c ld a,#40 ld c,d .loop ld b,d out (c),a ; sélectionner la ligne ld b,e ini ; lire et stocker dans notre tableau inc a inc c jr nz,.loop ret matriceClavier defs 10,#FF ;================================================= ; en fin du programme, nos coordonnées sur 16 bits ;================================================= positionx defw 0 positiony defw 0 increment_x defw 0 increment_y defw 0Et voilà notre point qui se déplace tout seul, les deux types de collisions sont gérées. Il serait bien de pouvoir voir les bords de l'écran mais vous savez déjà comment changer le border non? 
Roudoudou CPCrulez[Content Management System] v8.732-desktop Page créée en 026 millisecondes et consultée 26 foisL'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko. |
|