MSX Village forum

La Place des Développeurs Assembleur MSX pour les noobs cours en ligne

aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2698

Le 21/12/2020 à 17h23

Reprise du message précédent

C'est vrai qu'on est plus totalement noob... on a p'être atteint le grade de mi-noobs :D


On est toujours ignorant avant de savoir.
Github    
MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 775

Le 26/12/2020 à 17h21
le noob ici c'est moi :D

J'ai une question d'ailleurs pour les experts. ça se passe comment l'interaction sprites/décors en screnn2 par exemple.
Je sais comment faire en basic, mais existe-t-il des routines ou méthodes en ASM pour ça?


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

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2698

Le 26/12/2020 à 19h20
Qu'entends-tu par « interaction sprites/décors » ?
A ma connaissance, les sprites sont toujours dessinés au dessus du décors et ne peuvent pas "interagir" avec lui.


On est toujours ignorant avant de savoir.
Github    
MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 775

Le 26/12/2020 à 21h43
aïe, je m'exprime mal.

Dans un jeu tu peux avoir besoin de gérer les tiles suivant la position de ton personnage. Par exemple: tu rencontre un mur tu es bloqué, tu passe sur une clé tu le ramasses, tu rencontre une porte tu l'ouvres si tu as la clé, etc.


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

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2698

Le 27/12/2020 à 01h26
Tu as plusieurs méthodes, mais qui ne ne sont pas spécifiques à l'assembleur :
- Les collisions entre sprites (entre le héros et la clef par ex.). En assembleur, on pourrait se brancher dans le Hook d'interruption et checker le registre de status S#0 du VDP pour voir si deux sprites se sont superposés. Sur MSX1, je ne sais pas comment on peut savoir lesquels des sprites ont collisionnés mais sur MSX2, tu peux facilement récupérer leurs numéros dans les registres du VDP et interagir en conséquence.
- Les collisions entre sprites (le héros par ex.) et des tiles du décors (une clef par ex.). Une solution simple c'est juste de "projeter" la position du sprite dans l'espace des tiles. Par ex., si tes tiles font 8x8 pixels, tu récupère la position du centre de ton sprite et tu la divise par 8 (3 shift à droite en asm). Ainsi, tu te retrouves avec la colonne et la ligne de ton sprite dans ton tableau de tiles et tu peux regarder si le contenu de cette case est un élément interactif et déclencher une réaction.

Je sais pas si ça réponds à ta question. :)


On est toujours ignorant avant de savoir.
Github    
Sector28 Membre non connecté

Villageois

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 12/05/2018 à 23h00

Messages: 553

Le 27/12/2020 à 06h44
Lecture de la tuile sous le pixel (x,y):
ld d,$18
ld a,(x)
and $f8
rrca
rrca
rrca
ld e,a
ld h,0
ld a,(y)
and $f8
ld l,a
add hl,hl
add hl,hl
add hl,de
jp $4a


Toute matrice carrée sur un corps K, dont le polynôme caractéristique est scindé, est semblable à une matrice de Jordan. Cette réduction est unique à l'ordre des blocs près. De plus, toute matrice carrée nilpotente sur un corps K est semblable à une matrice de Jordan dont chaque bloc est associé à la valeur 0. Évidement, cette réduction est encore unique à l'ordre des blocs près...
:)
   
MSXosaure Membre non connecté

Maire-adjoint

Rang

Avatar

Association

Inscrit le : 03/10/2009 à 00h09

Messages: 775

Le 30/12/2020 à 19h44
bien, merci

Maintenant que j'ai récupéré la donnée, le mieux est de tester les bit pour savoir quel type de tile j'ai?


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

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2698

Le 31/12/2020 à 09h21
Yep.
Tu as plusieurs solution pour faire ça efficacement.

Soit utiliser des flags pour identifier des comportements particuliers à traiter.
Par ex. :
- Tous tes objets collectables peuvent avoir un numéro de pattern avec le bit#7 à 1
- Les objets qui demande une interaction du joueur (un click de bouton par ex.), avoir le bit#6 à 1
- etc.

L'autre méthode, que je préfère, c'est d'avoir tous tes tiles interactifs en début de ta table de pattern (appelons N le nombre de pattern interactive dont tu as besoin pour ton jeu ; 8, 16, 32, ...).
- Quand tu récupères le pattern où se trouve le joueur, tu tests si sont numéro est inférieur à N (si c'est pas le cas, c'est qu'il est pas interactif et tu t'arrêtes là)
- Préalablement, tu as préparé un tableau de taille N avec les adresses des différentes fonctions qui vont traiter les interactions avec les tiles
- Du coup, tu as juste besoin de faire un truc du genre :
Code ASM :
LD HL, _monTableau
LD BC, _monTile
ADD HL, BC
CALL (HL)

- Ce qui est cool avec ce système, c'est que ton tableau peux être modifié d'un niveau à l'autre en fonction des besoins (s'il est en RAM évidement) et que plusieurs cases du tableau peuvent pointer vers la même fonction.

Si ça vous voulez, je peux détailler un peu plus l'une et/ou l'autre de ces techniques.


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5484

Le 31/12/2020 à 10h46
Citation :
Si ça vous voulez, je peux détailler un peu plus l'une et/ou l'autre de ces techniques.

oui oui vas y... ;)


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2698

Le 01/01/2021 à 22h38
ericb59 :
oui oui vas y... ;)


Bon, je vais vous faire ça en pseudo-code assembleur (ça sera plus compact et bcp plus facile pour moi à écrire).
Prenons un exemple concret (fictif) d’un jeu avec des tuiles représentants :
- les fond de décors (aucune interaction)
- les murs/sol (qui bloquent le joueur)
- de potions de vie/mana (qui remonte les HP/MP quand on passe dessus)
- des portes (qui s’ouvrent quand on passe dessus)
- des portes verrouillées (qui ne s’ouvrent que si on a une clef à utiliser)
- des clefs (qu’on peut accumuler)

Les murs/sols ne sont pas vraiment des objets interactifs donc je vais pas rentrer dans le détail. Il faut juste tester les coins du sprite du personnage avec ces tiles et ajuster sa position en fonction des collisions.

Méthode 1


Pour méthode 1 de gestion des interactions, on pourrait par ex. coder les numéros de pattern avec les règles suivantes :



En résumé :
- Les objets de fond du décor ont une valeur binaire de la forme [0XXX XXXX] (ou X peut prendre n’importe quelle valeur).
- Les murs/sols (blocker) ont une valeur de la forme [10XX XXXX].
- Les objets ramassables : [110X XXX]
-- Les clefs :[1100 0XXX]
-- Les potions de vie : [1101 0XXX]
-- Les potions de mana : [1101 1XXX]
- Les portes : [111X XXXX]
-- Les portes normales : [1110 0XXX]
-- Les portes verrouillés : [1110 1XXX]

L’avantage, c’est qu’on peut faire des traitements à différents niveaux de spécialisation de l’objet interactif. Par ex., une clef et une potion de vie étant tous les deux des « objets ramassables », on peut les faire disparaître quand le joueur passe dessus. Voici un pseudo code de traitement de ces objets :

Code TEXT :
DEBUT:
    si bit#7 de Pattern égal 0 goto FIN ; le décor, rien à faire
    si bit#6 de Pattern égal 0 goto CHECK_COL ; pas détaillé ici
    si bit#5 de Pattern égal 0 goto COLLECT ; objet ramassable
    ; sinon c’est une porte
PORTE:
    si bit#3&4 de Pattern égal 00 goto OUVRIR_PORTE ; porte normale
    si bit#3&4 de Pattern égal 01 goto CHECK_CLEF ; porte verrouillée
    goto FIN
CHECK_CLEF:
    si NombreDeClef égal 0 goto FIN ; pas de clef, la porte ne s’ouvre pas
    reduire NombreDeClef de 1 ; on consomme une clef
OUVRIR_PORTE:
    ouvrir la porte
    goto FIN
COLLECT:
    effacer le pattern à l’écran ; traitement commun à tous les objets ramassable
    si bit#3&4 de Pattern égal 00 goto CLEF
    si bit#3&4 de Pattern égal 10 goto POTION_VIE
    si bit#3&4 de Pattern égal 11 goto POTION_MANA
    goto FIN
CLEF:
    augmenter NombreDeClef de 1
    goto FIN
POTION_VIE:
    augmenter PointDeVie de 1
    goto FIN
POTION_MANA:
    augmenter PointDeMagie de 1
    goto FIN
FIN:
    retour


Voilà.
Cette technique a ses avantages et ses inconvénients.
Elle peut être utile quand vous avez beaucoup d’objets différents mais qui partagent une grosse partie de leur traitement.
Si vous avez peu d’objet, la méthode 2 (ou un mix) est sûrement plus intéressant.
Mais ça, c’est une autre histoire… :)


On est toujours ignorant avant de savoir.
Github    
ericb59 Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : compte ++ Groupe : Shoutbox

Inscrit le : 17/04/2012 à 10h25

Messages: 5484

Le 02/01/2021 à 15h28
Ha oui... ok... J'ai utilisé cette technique pour la suite de Treasure of Babylon (un jeu non fini, non sorti :siffle )
Bon, c'était moins fin, mais équivalent.


banniere-ericb59e
Site web    
aoineko Membre non connecté

Conseiller Municipal

Rang

Avatar

Groupe : Shoutbox

Inscrit le : 02/01/2011 à 21h17

Messages: 2698

Le 02/01/2021 à 18h28

Méthode 2



La methode 2 est encore plus simple.
Il suffit de réserver un nombre de tuile pour celles qui sont interactives.
Dans l’exemple précédent, réservons 8 tuiles et affectons les index suivants :
- 0 : Une clef
- 2 : Une potion de vie
- 3 : Une potion de mana
- 4 : Une porte normale
- 5 : Une porte verrouillée

Le pseudo code de traitement serait alors :

Code TEXT :
DONNEE:
    dw CLEF ; 0
    dw RIEN_FAIRE ; 1
    dw POTION_VIE ; 2
    dw POTION_MANA ; 3
    dw CHECK_CLEF ; 4
    dw OUVRIR_PORTE; 5
    dw RIEN_FAIRE ; 6
    dw RIEN_FAIRE ; 7
DEBUT:
    si Pattern supérieur à 7 goto FIN ; tuile non interactive
    goto DONNEE + Pattern ; aucun test à faire
FIN:
    retour
CLEF:
    effacer le pattern à l’écran
    augmenter NombreDeClef de 1
    retour
POTION_VIE:
    effacer le pattern à l’écran
    augmenter PointDeVie de 1
    retour
POTION_MANA:
    effacer le pattern à l’écran
    augmenter PointDeMagie de 1
    retour
CHECK_CLEF:
    si NombreDeClef égal 0 goto FIN ; pas de clef, la porte ne s’ouvre pas
    reduire NombreDeClef de 1 ; on consomme une clef
OUVRIR_PORTE:
    ouvrir la porte
    retour
RIEN_FAIRE:
    retour


Le code est beaucoup plus performant que dans la méthode 1 (très peu de test pour accéder au code spécifique à chaque interaction).
Le seul défaut c’est la nécessité d’allouer un peu d’espace à la table de saut (celle qui relie un numéro de pattern avec une routine dans le programme) et les risques de redondance.

J’ai présenté ces deux techniques de façon séparée par souci didactique, mais en vrai, si j’étais confronté à cette situation, je ferais sûrement un mix des 2 techniques.
Par exemple, pour check si une tuile est un bloqueur (mur/sol), j’utiliserais plutôt le check de bit, alors que pour le reste, j’utiliserai plutôt une table de saut.
Pour les objets dont le traitement est très proche – comme la potion de vie et de mana – je garderais des bits pour les différencier et j’utiliserai un code générique. Par ex., on pourrait avoir un tableau avec la vie comme entrée d’index 0 et la mana comme entrée 1 ; on pourrait alors avoir un code commun qui incrémente la valeur dans le tableau en fonction du bit#0 du Pattern, sans tester s’il s’agit d’une potion de vie et ou de mana.

Voilà, j’espère que ça vous est utile. :)


On est toujours ignorant avant de savoir.
Github    
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie