1
Bon voilà, ça fait quelques temps que je bosse dessus et comme ça commence à prendre forme, j'ai décidé de faire un petit topic pour le présenter et pour me motiver à continuer de le développer smile

9maU

Donc pour l'instant ce qui est fait : le tilemapper/les déplacements gestion des évènements (tout ça grâce à l'excellent GBA Lib 2), une grande partie des menus (j'ai fait des routines pratiques), le format d'encodage des pokémons, des attaques, de leurs stats, des types etc... et le début des combats... Et tout ça dans 8951 octets (enfin les sprites, tiles, la carte et les quelques pokémons que j'ai déjà encodés en bouffent une grande partie).

Ah j'avais commencé un éditeur de carte vite fait en PureBasic, mais comparé à celui de juego il est vraiment naze, il faudra que je le mette à jour tongue

Il y a quelques trucs qui me dérange encore : l'écran titre, quelques sprites (ceux de la fille notamment) et l'agencement du menu où on s'occupe de l'organisation des pokémons (il est trop petit, il va falloir que je fasse un sous-menu pour afficher les autres données, notamment l'expérience). Quelques routines pourraient être optimisées aussi (celle du flip des sprites entre autre), donc si ça vous dit d'essayer j'ai tenté de rendre la source le plus clair possible (par contre les commentaires ne sont là que pour que je m'y retrouve) : elles sont toutes regroupées dans "routines.inc".

Donc là quand j'ai un peu de temps libre je bosse sur le moteur de combat (les attaques surtout, ensuite la capture de pokémons sauvages puis enfin les combats contre dresseurs). J'aimerai bien ajouter le link avec la lib Bell, ça devrait pas être trop compliqué même s'il faudra me rappeler de faire quelque chose comme :

#ifdef	TI83
#define	bcall_link(romcall)	call romcall \ di
#endif
#ifdef	TI83P
#define	bcall_link(romcall)	rst 28h \ .dw romcall \ di
#endif

À cause de ces histoires d'interruptions...

Enfin pour l'instant je vais essayer de faire tenir mes ajouts dans 2~3ko pour qu'il me reste au moins 10ko pour les cartes et données dresseurs/pokémons, mais je commence à douter de pouvoir tout caser :/

En plus de ça je vais sans doute séparer les données de sauvegarde dans un programme externe (pour pouvoir les transférer facilement).

Et il faut que je garde au maximum la compatibilité TI 83 donc je ne pense pas passer en APPS...

Peut être que faire des "chapitres" peut être la solution confus

Bref ça vous plait ?

Tiens d'ailleurs il faudra aussi définir une histoire, des lieux etc... parce que j'aimerai bien faire un jeu original plutôt qu'une adaptation des versions gb/gbc smile

Ah et j'y pense ce sera peut être ma première contribution en tant que membre de la tift (enfin tongue) ou ma première contribution tout court même cheeky

En espérant que je ne m'en lasse pas comme pas mal d'autres projets !

Téléchargement : http://www.mirari.fr/NtSl

Page google code : http://code.google.com/p/pokemon-monochrome/
2
C'est génial deeph, vraiment magnifique.

Tu as l'obligation de finir ce jeu !
3
Merci smile

Erf j'ai complétement oublié de poster le lien pour le télécharger : http://www.mirari.fr/NtSl cheeky

Ah et aussi, il y a des effets de fondu d'écran (avec le contraste) qu'on ne voit pas sur le screen mais qui rendent très bien oncalc !
4
Bravo ! C'est très beau et il semble que tu as déjà fait une grande partie du travail ! Je crois pas que tu pourras ajouter tous les pokémon (pas d'espace), au moins pas pour la version 83. Pour le menu, tu pourrais afficher une autre boîte de texte quand on laisse rester le curseur quelques instants sur un pokémon ou mettre tous les infos dans un menu de status comme l'on fait normalement dans les jeux de Pokémon.

Au fait, à quoi sert la routine "lcd_to_gbuf" ? Je ne comprends pas pourquoi tu veux sauver le LCD, il semble que c'est parce que tu afficher le texte directemment au LCD, mais pourquoi ? Et je crois que l'on peut écrire une routine "rectangle_filled" plus optimisée (mais je ne suis pas sûr qu'elle sera vraiment plus optimisée) plus adapté à ce que tu veux faire. Pour commencer, tu peux changer les paramètres un peu pour donner les coordonnées initiales x,y puis la largeur et hauteur en pixels (en lieu des coordonnées finales).
5
Oui j'ai déjà codé pas mal de choses, mais il manque encore une bonne partie du moteur de combat (même si ça n'est pas très compliqué à coder, surtout qu'il y aura certaines choses simplifiées par rapport à la version originale : je ne pense pas inclure les attaques inutiles qui font baisser la défense/l'attaque temporairement) smile

Sinon c'est sûr que je ne pourrai pas tous les inclure, mais je pense pouvoir en caser au moins 30~40 voire même un peu plus pour la version 83+.

Pour la routine "lcd_to_gbuf", ça fait parti des trucs dont je me suis servi au tout début, mais c'est vrai que maintenant je me demande s'il n'y a pas facilement moyen de s'en passer...

Et pour "rectangle_filled", c'est la plus courte des routines de ce type que j'ai trouvé... Mais par contre je préfère ses paramètres (coordonnées initiales et d'arrivées), je trouve ça plus pratique.

edit : enfaite le "lcd_to_gbuf" était là pour éviter de devoir faire un "call ionFastCopy" à chaque caractère inscrit dans le gbuf avec la routine d'écriture lettre par lettre (parce qu'il m'en faut une copie dans le gbuf, car j'affiche d'autres trucs en parallèle, comme des curseurs), mais finalement c'est tout aussi rapide et m'en passer m'a fait gagner 44 octets !
6
Par exemple, je viens d'écrire ce petit morceau de code (mais qui seulement fonctionne avec des coordonnées X qui sont des multiples de huit) :
;b = # columns
;c = # rows
;d = starting x
;e = starting y
rectangle_filled2:
	ld a,d		;a = starting x coord
	ld l,e		;ld hl,e
	ld h,0		; ..
	ld d,h		;set d = 0
	add hl,de	;starting y * 12
	add hl,de	;x3
	add hl,hl	;x6
	add hl,hl	;x12
	rra			;a = x coord / 8
	rra			;
	rra			;
	and %00011111	;starting x/8
	ld e,a		;
	add hl,de	;add x
	ld de,gbuf
	add hl,de	;offset in gbuf
	ld a,b			;b = no columns
	rra
	rra
	rra
	and %00011111	;no. columns / 8
	ld b,a
	ld a,12
	sub b
	ld e,a
	ld d,0
rectangle_loop_y:
	push bc
rectangle_loop_x:
		ld (hl),$FF
		inc hl
		djnz rectangle_loop_x
	pop bc			;restore c (# columns)
	add hl,de		;move down to next row
	dec c
	 jr nz,rectangle_loop_y
rectangle_end:
	ret
Demain je peut l'améliorer un peu. La routine que tu utilises c'est bon si tu vas utiliser les autres routines (getpixel, V_line, etc.) mais je crois que tu n'auras pas besoin de tout ça.
7
Enfaite je me sert de cette routine pour plusieurs choses : afficher les cadres des textes, effacer une partie des sprites des pokémons lors des combats pour pouvoir afficher leur état (s'ils sont empoisonnés/endormis/paralysés) et pour afficher la ligne des points de vie/de l'expérience (même si ça doit être faisable avec les romcalls). Mais dans tous les cas les coordonnées X sont rarement des multiples de 8 :/

Enfin c'est sympa, parce que plus ce sera optimisé et plus j'aurai de place pour les données !

Là j'ai commencé à coder l'utilisation d'attaques et j'arrive presque à 9ko... Il va falloir que j'optimise encore d'autres trucs !

D'ailleurs je ferai certainement des tests lorsque j'en serai à la création des maps pour savoir si ça vaut le coup de les encoder en RLE.
8
C'est super comme projet !
Peut être tu pourrais choper des bouts de code dans le sources de "The verdante forest", le jeu était en multi-chapitre et marchait très bien.
Enfin bon, cela dit, la carte de Pokémon est tellement grosse que je le verrais mieux en App.
J'ai l'impression qu'il y a eu des tas de projets pokémon et qu'aucun n'a été fini jusque là. Ce serait cool d'en avoir un vrai :-)
9
Déjà je vais séparer la sauvegarde du jeu en lui même, et après sûrement faire des chapitres pour la 83 (même si ça m'embête, dans tous les pokémons ont pouvait revenir sur ses pas pour tenter de tout capturer...), je ferais peut être une transition du style le joueur prend un bateau ou quelque chose du genre...

Pour la 83+ je pourrai effectivement faire une APP, mais d'une part j'en ai jamais fait et d'autre part ça va me demander de modifier énormément la source (je fait beaucoup de SMC et j'utilise pratiquement toutes les routines d'Ion).
Je te l'avais écrit la nuit dernière mais la connexion d'internet s'était rompu, donc une version qui fait exactement la même chose que ce que tu utilises maintenant :
;b = # columns
;c = # rows
;d = starting x
;e = starting y
rectangle_filled_xor:
	ld a,$AE			;xor (hl)
	jr rectangle_filled2
rectangle_filled_solid:
	ld a,$B6			;or (hl)
rectangle_filled2:
	push de
	push bc
		ld hl,or_xor
		ld (hl),a			;use smc for xor/solid fill
		ld a,d				;starting x
		and $7				;what bit do we start on?
		ex af,af'
			ld a,d			;starting x
			ld l,e			;ld hl,e
			ld h,0			; ..
			ld d,h			;set d = 0
			add hl,de		;starting y * 12
			add hl,de		;x3
			add hl,hl		;x6
			add hl,hl		;x12
			rra				;a = x coord / 8
			rra				;
			rra				;
			and %00011111	;starting x/8 (starting byte in gbuf)
			ld e,a			;
			add hl,de		;add x
			ld de,gbuf		;
			add hl,de		;hl = offset in gbuf
		ex af,af'
		or a				;clear carry and check if a = 0
		ld e,a
		ld a,%10000000
		 jr z,$+6
			rra
			dec e
			jr nz,$-2
rectangle_loop_y:
		push af				;the rotated bit (pixel) to draw (bit 0-7)
		push bc
		push hl
rectangle_loop_x:
			ld e,a
or_xor = $
			or (hl)			;smc will modify this to or/xor
			ld (hl),a
			ld a,e
			rrca
			 jr nc,$+3
				inc hl
			djnz rectangle_loop_x
		pop hl
		pop bc				;restore b (# columns)
		pop af
		ld de,12
		add hl,de			;move down to next row
		dec c
		 jr nz,rectangle_loop_y
rectangle_end:
	pop bc
	pop de
	ret
C'est pas trop optimisé (quand même plus rapide/petit que ta routine), mais l'idée est là. Pour l'utiliser, on peut faire :
start:
	ld de,$041B
	ld bc,$1103
	call draw_box2
	call ionFastCopy
	bcall _getkey
	ret

draw_box2:
	call rectangle_filled_solid
	inc d
	inc e
	dec b
	dec b
	dec c
	dec c
	call rectangle_filled_xor
	ret


EDIT : Et si tu veux utiliser du SMC dans un APP, tu peux charger ces routines dans RAM. Tu peux aussi rechercher les "metatiles" (c'est pareil à ce que l'on a fait pour la GBA, si tu veux afficher un sprite de 16x16 il faut 4 sprites de 8x8) pour gagner de l'espace. Je crois que la taille de la carte ne va pas être le problème, ça sera plutôt tous les datas/sprites des pokémon. Pour la 83+, je peux t'aider avec les APPs smile

EDIT 2 : Ah, et jettez un coup d'oeuil ici : http://www.omnimaga.org/index.php?topic=9844.0 wink
Merci pour la routine ! Mais est-ce qu'elle permet de démarrer à n'importe quelles coordonnées (même non alignées) ? Ça me fait penser, je suis sûr qu'elle pourra servir à pas mal de monde : http://www.omnimaga.org/index.php?topic=1598.msg256238#msg256238

Sinon je pensais en faire une facilement avec _darkline, mais le flag bufferOnly n'existe pas sur 83... Peut être qu'en utilisant simplement une bonne routine de ligne avec un djnz ferait l'affaire...

Pour les APPS, en pratique je ne vois pas trop comment charger les routines en RAM... ? Autant modifier la source pour travailler avec les saferam, non ?

Et pour ce qui est des metatiles, je n'ai pas trop compris l'intérêt (c'est simplement le fait de tous les regrouper en mémoire, non ? Parce que c'est déjà le cas pour les tiles mais pas pour les sprites, mais dans les deux cas je ne vais pas les modifier).

D'ailleurs je vais peut être pouvoir modifier la taille des sprites des pokémons (de 40*26 à 32*26), enfin si ça rentre.

Sinon pour Pokémon Topaze, effectivement ça m'a pas mal motivé à terminer le mien (et je me suis inspiré de quelques sprites/"mises en pages", j'espère que ça dérangera pas Hayleia), mais pour le reste c'est de l'Axe (et je n'y connais rien), donc je préfère coder le mien sans trop comparer les méthodes smile

Là j'en suis à calculer les dégâts, c'est pas trop difficile avec les OP, et la formule est détaillée ici : http://www.pokepedia.fr/index.php/Calcul_des_d%C3%A9g%C3%A2ts

Tiens d'ailleurs ça me fait penser, Zeph, un admin de yN a rajouté les brushes z80 et ARM à la balise [source] (c'est pas encore officiel donc je ferai une annonce plus tard). On peut s'en servir comme ça : [source=z80][/source] smile

edit :
PJsf

J'ai un début de code pour calculer les dommages (en plus de ça il faudra que j'ajoute une animation pour les dommages, ou peut être simplement faire clignoter les sprites) :
Routine de calcul des dommages
calculate_damages: ; output : a = int((((hl+1*0.4+2)*[attack_power])*(hl+(pokemon_att-pokemon_stats))/(de+(pokemon_def-pokemon_lvl))*50+2)*CE) push hl ld h,0 ld l,opponent_pokemon_stats_def-opponent_pokemon_stats add hl,de ld l,(hl) ; on a DEF ld h,0 bcall _setxxxxop2 ld a,50 bcall _setxxop1 bcall _fpmult bcall _op1toop4 ld a,2 bcall _setxxop1 ld a,5 bcall _setxxop2 bcall _fpdiv pop hl push hl inc hl ; son niveau ld l,(hl) ld h,0 bcall _setxxxxop2 bcall _fpmult ld a,2 bcall _setxxop2 bcall _fpadd pop hl ld d,0 ld e,pokemon_att-pokemon_stats add hl,de ld l,(hl) ; on a ATT ld h,0 bcall _setxxxxop2 bcall _fpmult ld a,(current_attack) call find_attack_a ld d,0 ld e,attack_power-attack_data add hl,de ld l,(hl) ld h,d bcall _setxxxxop2 bcall _fpmult bcall _op4toop2 bcall _fpdiv ld a,2 bcall _setxxop2 bcall _fpadd CE = $+1 ld a,0 bcall _setxxop2 bcall _fpmult bcall _int bcall _convop1 ; rajouter la marge d'erreur de 15% (0.85 à 1 fois le résultat) ret

Il me reste plus qu'a "boucler" les combats et je posterai le nouveau code smile

(par contre si le sabelette niveau 32 n'inflige que 29 points de vie en moins au pauvre chenipan niveau 2 c'est parce que je ne lui ai pas mis les bonnes stats d'attaque)

Ah et j'en suis à 9263 octets !
deeph (./11) :
Merci pour la routine ! Mais est-ce qu'elle permet de démarrer à n'importe quelles coordonnées (même non alignées) ?
Oui, mais pour le moment elle prend les coordonnées initiales puis la largeur/hauteur de la boîte, mais il serait facile de changer ça (bien qu'un peu plus grand) si tu préfères utiliser deux coordonnées wink
Ça me fait penser, je suis sûr qu'elle pourra servir à pas mal de monde : http://www.omnimaga.org/index.php?topic=1598.msg256238#msg256238
Je suis sûr qu'elle n'est pas trop optimisée, mais je peux le poster là tout de même au cas où quelqu'un pourra s'en servir. smile
Pour les APPS, en pratique je ne vois pas trop comment charger les routines en RAM... ? Autant modifier la source pour travailler avec les saferam, non ?
Oui, on les charge dans saferam, par exemple :#DEFINE SAFERAM_OFFSET ($-saferam_start)+saferamRoutines saferamRoutines = appBackUpScreen ;on garde quelques routines ici pour gagner de l'espace start: ;charger quelques routines dans saferam pour ouvrir de l'espace ld hl,saferam_start ld de,saferamRoutines ld bc,768 ldir call keyCheck ret saferam_start: ;Ces routines vont être copiées dans saferam pour libérer de l'espace keyCheck = SAFERAM_OFFSET ; Initialiser les valeurs a 0 xor a ld (playerMovement),a ;si on a poussé gauche/droite ;clear ld a,groupe2 ; groupe 2 (clear) out (1),a ; porte 1: clavier in a,(1) ; lire cp diClear jr nz,$+10 in a,(1) ; lire cp diClear jr z,$-4 ;il faut relâcher clear, sinon on va quitter tout le programme ! pop hl ret ; si on appuie sur clear, quitter le programme saferam_end: .echo "Mémoire dans saferam1: ", saferam_end - saferam_startJettes un coup d'oeuil au define.
Et pour ce qui est des metatiles, je n'ai pas trop compris l'intérêt (c'est simplement le fait de tous les regrouper en mémoire, non ? Parce que c'est déjà le cas pour les tiles mais pas pour les sprites, mais dans les deux cas je ne vais pas les modifier).
Les metatiles vont te sauver de l'espace. Par exemple :
120000
340000
555500
555500
deviendrait :
100
220

0 =
00
00

1 =
12
34

2 =
55
55

Il faudrait peut-être reorganisé un peu tes maps pour mieux convenir aux groupes de 2x2 (ou plus grand) tuiles, mais tu pourrais gagner pas mal d'espace.

Pour les dommages c'est bon mais ça avance un peu lentement, non ? Pour le moment une animation pour l'attaque n'est pas nécéssaire, mais faire clignoter quelques fois le pokémon attaqué ne se verait pas mal ! grin Et si tu peux, je crois qu'utiliser des sprites 32x26 serait une bonne idée. As tu déjà dessiné un map du monde ?

C'est impressionant ce que tu as fait !
Ok je vais utiliser ta routine, il faudra juste que j'adapte les registres paramètres smile

Mais si tu veux encore l'optimiser je suis tout à fait d'accord ! tongue

Par contre pourquoi copier en RAM les routines, si on se sert d'APPS c'est justement pour ne plus avoir à se prendre la tête à essayer de gagner beaucoup de mémoire ? Et il y a un truc qui m'inquiète, d'après http://wikiti.brandonw.net/index.php?title=Programming_APPS_vs._Ram_Programs : "Most static data passed to bcalls (strings for instance) has to be copied to RAM first " fou

Il va falloir que je copie en RAM énormément de données (les textes, valeurs pour les calculs etc...), non ?
chickendude (./12) :
Les metatiles vont te sauver de l'espace.

C'est une forme de compression alors (comme le RLE) ? Mais comment tu définis les valeurs ?
chickendude (./12) :
Pour les dommages c'est bon mais ça avance un peu lentement, non ? Pour le moment une animation pour l'attaque n'est pas nécéssaire, mais faire clignoter quelques fois le pokémon attaqué ne se verait pas mal ! grin

Oui il faut que j'accélère un peu ça, et je vais rajouter le clignotement des sprites des pokémons attaqués smile
chickendude (./12) :
As tu déjà dessiné un map du monde ?

Non car je n'ai aucune idée du scénario du jeu. Je pensais faire quelque chose d'original mais qui reste dans l'esprit de la série (la totalité des pokémons se passent dans des régions ayant des noms de lieux japonnais : http://fr.wikipedia.org/wiki/Lieux_de_Pok%C3%A9mon ). Autrement pour le starter je me demande s'il faut donner le choix entre 3 pokémons au joueur ou lui en imposer un qui le mettra en désavantage dans la première arène pour le forcer à en capturer avant et ainsi augmenter un peu la durée de jeu ?
chickendude (./12) :
C'est impressionant ce que tu as fait !

Merci ! smile

editefine bcall xxxx rst 28h \ .dw xxxx \ di #endif : avec spasm, c'est pas possible de faire ça :#ifdef TI83 #define bcall xxxx call xxxx \ di #endif #ifdef TI83P #d ?

Ça me sort "Unknown opcode 'xxxx'" que je le mette entre parenthèses ou pas... sad
Essaie : #ifdef TI83 #define bcall(xxxx) call xxxx #endif #ifdef TI83P #define bcall(xxxx) rst 28h \ .dw xxxx \ di #endif

Pour les BCALLs, oui c'est vrai parce que ton texte ne va pas être là au même endroit dans mémoire ($4000-$7FFF) quand le BCALL s'exécute (je crois les bcalls s'y exécute). Ce que l'on fait normalement c'est d'utiliser _PutC/_vPutMap pour faire un simple routine de texte (le charactère à afficher est passé à travers l'accumulateur). Un truc comme : vPuts: ld a,(hl) or a ret z bcall(_vPutMap) inc hl jr vPuts
Ça ne marche pas non plus... Peut être avec les macro ?
;and (hl) jr rectangle_filled2Sinon j'ai rajouté à ta routine :rectangle_filled_and: ld a,$a6
Parce que j'ai besoin de pouvoir effacer une partie de l'écran (avec un rectangle blanc), avant d'afficher l'état du pokémon, mais je ne sais pas pourquoi il y a quelques pixels qui disparaissent après... confusbattle_draw_player_pokemon_state: ; input : hl = player pokemon state ld a,(hl) or a ret z push af ld bc,$0c06 ld de,$1e2a call rectangle_filled_and ; jusque là tout va bien pop af call battle_draw_pokemon_state ld de,$2a1f ld (pencol),de bcall _vputs ; le texte s'affiche mais il y a quelques pixels qui disparaissent à côté du cadre (même si le texte n'y est pas) ret battle_draw_pokemon_state: ld hl,menu_pokemon_str_poison cp 2 jr z,battle_draw_player_pokemon_state_sleep cp 3 jr z,battle_draw_player_pokemon_state_para ret battle_draw_player_pokemon_state_sleep: ld hl,menu_pokemon_str_sleep ret battle_draw_player_pokemon_state_para: ld hl,menu_pokemon_str_para ret
J'ai entouré en rouge là où ça bug :

1U3q

Ça ne vient pas d'un autre bout de code parce qu'avec 'rectangle_filled_xor' ou 'rectangle_filled_solid' ça marche (mais ça me met un rectangle noir).

Mais au pire ça marche avec : call rectangle_filled_solid call rectangle_filled_xor
Pour effacer je crois qu'il faudrait changer "ld a,%1000000" à "ld a,0", si non tu ne vas pas changer rien. Les bits à 1 resteront à 1, et les bits à 0 resteront à 0 :P
Bon je vais continuer à faire appel deux fois à la routine (_solid et _xor) alors.
Pourquoi ne pas faire : ;b = # columns ;c = # rows ;d = starting x ;e = starting y rectangle_filled_white: call rectangle_filled_solid rectangle_filled_xor: ld a,$AE ;xor (hl) jr rectangle_filled2 rectangle_filled_solid: ld a,$B6 ;or (hl) rectangle_filled2: call rectangle_filled_xor?
Ah oui, je vais faire ça smile

x4bp


J'ai optimisé pas mal de choses (j'en suis à 9215 octets), et je pense que la diminution des points de vie restera à cette vitesse.

Maintenant je vais rajouter le clignotement des sprites, gérer les changements d'état (empoisonnement etc...), "boucler" les combats, gérer l'expérience, puis enfin je pourrai rajouter la capture de pokémons, le combat contre les dresseurs... Bref, y'a du boulot... sick
Cool, ça avance bien !
Avec l'aide de Xeda j'ai fait quelques optimisations à la routine de rectangles. D'abord, une version optimisée de l'originale : #ifdef TI83P GBUF_LSB = $40 GBUF_MSB = $93 #else GBUF_LSB = $29 GBUF_MSB = $8E #endif ;b = # columns ;c = # rows ;d = starting x ;e = starting y rectangle_filled_xor: ld a,$AE ;xor (hl) jr rectangle_filled2 rectangle_filled_solid: ld a,$B6 ;or (hl) rectangle_filled2: push de push bc ld (or_xor),a ;use smc for xor/solid fill ld a,d ;starting x and $7 ;what bit do we start on? ex af,af' ld a,d ;starting x ld l,e ;ld hl,e ld h,0 ; .. ld d,h ;set d = 0 add hl,de ;starting y * 12 add hl,de ;x3 add hl,hl ;x6 add hl,hl ;x12 rra ;a = x coord / 8 rra ; rra ; and %00011111 ;starting x/8 (starting byte in gbuf) add a,GBUF_LSB ld e,a ; ld d,GBUF_MSB ; add hl,de ;hl = offset in gbuf ex af,af' ;carry should be reset and z affected from and $7 ld e,a ld a,%10000000 jr z,$+6 rra dec e jr nz,$-2 ld d,a ;starting bit to draw rectangle_loop_y: push bc push hl rectangle_loop_x: ld e,a ;save a (overwritten with or (hl)) or_xor = $ or (hl) ;smc will modify this to or/xor ld (hl),a ld a,e ;recall a rrca ;rotate a to draw the next bit jr nc,$+3 inc hl djnz rectangle_loop_x pop hl ;hl = first column in gbuf row ld c,12 ;b = 0, bc = 12 add hl,bc ;move down to next row pop bc ;restore b (# columns) ld a,d ;restore a (starting bit to draw) dec c jr nz,rectangle_loop_y rectangle_end: pop bc pop de ret

Mais aujourd'hui j'ai écrit une version plus rapide (en général 5-15%, selon les dimensions du rectangle) et de la même taille (70 octets), mais peut-être un peu plus lente pour les lignes (des rectangles avec une hauteur de 1/2) : #ifdef TI83P GBUF_LSB = $40 GBUF_MSB = $93 #else GBUF_LSB = $29 GBUF_MSB = $8E #endif ;b = # rows ;c = # columns ;d = starting x ;e = starting y rectangle_filled_xor: ld a,$AE ;xor (hl) jr rectangle_filled2 rectangle_filled_solid: ld a,$B6 ;or (hl) rectangle_filled2: push de push bc ld (or_xor),a ;use smc for xor/solid fill ld a,d ;starting x and $7 ;what bit do we start on? ex af,af' ld a,d ;starting x ld l,e ;ld hl,e ld h,0 ; .. ld d,h ;set d = 0 add hl,de ;starting y * 12 add hl,de ;x3 add hl,hl ;x6 add hl,hl ;x12 rra ;a = x coord / 8 rra ; rra ; and %00011111 ;starting x/8 (starting byte in gbuf) add a,GBUF_LSB ld e,a ; ld d,GBUF_MSB ; add hl,de ;hl = offset in gbuf ex af,af' ;carry should be reset and z affected from and $7 ld d,a ld a,%10000000 jr z,$+6 rra dec d jr nz,$-2 ld e,12 rectangle_loop_x: push af push bc push hl ld c,a rectangle_loop_y: or_xor = $ or (hl) ;smc will modify this to or/xor ld (hl),a ld a,c add hl,de djnz rectangle_loop_y pop hl pop bc pop af rrca jr nc,$+3 inc hl dec c jr nz,rectangle_loop_x rectangle_end: pop bc pop de retMais attention qu'ici b = la hauteur et c = la largeur (le contraire de l'autre version).

EDIT : et je crois que c'est une bonne vitesse, c'est très beau !
Wow, merci beaucoup ! smile
Franchement c'est magnifique ! Bravo !
J'ai écrit une routine pour afficher un rectangle normal (pas "rempli"), mais elle est un peu plus grande (presque 30 octets). Je ne sais pas si ça t'interesse ?

Y a-t-il d'autre chose qu'on peut faire pour t'aider ? grin
Pour l'instant ta routine est parfaite ! Je n'utilise pas de rectangles vides pour le moment (les cadres des textes se superposent en général à d'autres choses : la carte, etc... sauf peut être dans le menu des pokémons, mais ça ne justifie pas d'utiliser une autre routine simplement pour ça) smile

Autrement il y a bien la routine de flip des sprites (j'utilise cette vieille routine) qui pourrait être optimisée, mais c'est comme tu veux (elle fonctionne parfaitement, c'est juste histoire de gagner quelques octets) smile

Hier j'ai écrit une routine pour mieux générer les pokémons sauvages (calculs des PV, stats d'attaques et de défense, attribution de attaques en fonction du niveau etc...), grâce à http://www.pokepedia.fr/index.php/Calcul_des_statistiques , même si je ne prend pas en compte les paramètres IV et EP (ça n'influe pas énormément sur les stats), mais je me demande s'il ne vaudrait mieux pas tout de même les rajouter... IV ne prendrait qu'un octet en plus par pokémon, mais par contre je n'ai pas trop pigé EP/EV.

Maintenant je pense commencer l'IA (très simple pour les pokémons sauvages : ils attaquent bêtement).
Voici ma tentative (38 octets) :; INPUT : ; ix:sprite; b:height; c:width/8 ; OUTPUT : ; ix=flipped sprite ; destroys a, de ; uses saferam3 flip_sprite: push bc push ix pop de ld hl,saferam3 flip_sprite_outer: ;de = original sprite ;hl = buffer push bc ;save b (sprite height) ld b,0 ;bc = width in bytes add hl,bc ;go to very right of first sprite and draw leftward push hl ld b,8 flip_sprite_loop: dec hl ;go left in buffer push bc ;c gets overwritten so we need to save it ld a,(de) ;first byte in a rrca ;rotate a to the right and rotate the carry left into c rl c djnz $-3 ld (hl),c ;save flipped byte inc de ;next byte of sprite pop bc ;c = counter (number of bytes to flip) dec c jr nz,flip_sprite_loop pop hl pop bc ;restore b (height) djnz flip_sprite_outer ld ix,saferam3 pop bc retElle est peut-être plus lente mais je crois que ce ne sera pas un problème smile
Wow, la mienne faisait 20 octets de plus, merci !

J'ai bientôt terminé l'IA des pokémons sauvages, une fois que c'est fait je posterai le nouveau code source smile

edit : par contre ta routine détruis aussi hl, mais c'est pas forcément un problème même si ionLargeSprite utilise l comme paramètre : il suffit de le spécifier après avoir fait appel à flip_sprite.
ip_sprite_outer pop ix pop bc pop hl ret
Alors celle-ci est 39 octets et conserve hl :; INPUT :
; ix:sprite; b:height; c:width/8
; OUTPUT :
; ix=flipped sprite
; destroys a, de
; uses saferam3
flip_sprite:
	push hl
	push bc
		push ix
		pop de
		ld hl,saferam3
		push hl
flip_sprite_outer:
;de = original sprite
;hl = buffer
		push bc				;save b (sprite height)
			ld b,0			;bc = width in bytes
			add hl,bc		;go to very right of first sprite and draw leftward
			push hl
				ld b,8
flip_sprite_loop:
				dec hl			;go left in buffer
				push bc			;c gets overwritten so we need to save it
					ld a,(de)	;first byte in a
					rrca		;rotate a to the right and rotate the carry left into c
					rl c
					djnz $-3
					ld (hl),c	;save flipped byte
					inc de		;next byte of sprite
				pop bc			;c = counter (number of bytes to flip)
				dec c
				jr nz,flip_sprite_loop
			pop hl
		pop bc			;restore b (height)
		djnz fl
smile
6n3N


Pokémon Monochrome - 04-02-13.zip

Les combats sont bouclés et les dommages sont bien calculés (il ne manque que le "coup critique") smile

Ensuite il faudra que je gère l'expérience/les évolutions, le changement de pokémon durant le combat etc... Ça avance, mais il en reste de choses à faire fou

J'ai optimisé pas mal de routines, mais il y a encore certains parties du code que je peux "fusionner" (ça concerne les routines qui s'occupe seulement du joueur et celles qui s'occupent seulement de l'adversaire).
Wow ! Peut-on perdre ? C'est-à-dire, qu'est-ce qui se passe si ton pokémon s'évanouit ?

Quand tu ajouteras l'expérience et les niveaux on aura un vrai jeu, même si l'on ne peut pas attraper d'autres pokémon, il serait comme un RPG traditionnel grin

A propos, dans les routines de rectangle, tu peux enlever le "or a" après le "ex af,af'" et sauver encore un octet.

Mais une chose : il faut un petit saut ou quelque chose quand on baisse de ces rebords, je ne savais pas ce qu'ils étaient au début.

Si tu as besoin de quelque chose ou veux de l'aide, n'hésite pas à nous en demander !