Posté le 29/01/2013 à 22:27Edité par deeph le 05/02/2013 à 17:44 Membre depuis le 15/03/2005, 3470 messages
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/
Posté le 30/01/2013 à 08:37 Membre depuis le 02/02/2009, 672 messages
C'est génial deeph, vraiment magnifique.

Tu as l'obligation de finir ce jeu !
Posté le 30/01/2013 à 09:32 Membre depuis le 15/03/2005, 3470 messages
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 !
Posté le 30/01/2013 à 17:37 Membre depuis le 03/06/2011, 520 messages
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).
Posté le 30/01/2013 à 17:48 Membre depuis le 15/03/2005, 3470 messages
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 !
Posté le 30/01/2013 à 20:19 Membre depuis le 03/06/2011, 520 messages
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.
Posté le 30/01/2013 à 20:52 Membre depuis le 15/03/2005, 3470 messages
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.
Posté le 31/01/2013 à 08:15 Membre depuis le 11/04/2007, 1076 messages
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 :-)
Posté le 31/01/2013 à 10:44 Membre depuis le 15/03/2005, 3470 messages
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).
Posté le 31/01/2013 à 18:02 Membre depuis le 03/06/2011, 520 messages
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
Posté le 31/01/2013 à 19:23 Membre depuis le 15/03/2005, 3470 messages
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 !
Posté le 01/02/2013 à 10:49 Membre depuis le 03/06/2011, 520 messages
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_start
Jettes 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 !
Posté le 01/02/2013 à 11:29 Membre depuis le 15/03/2005, 3470 messages
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
Posté le 01/02/2013 à 11:58 Membre depuis le 03/06/2011, 520 messages
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
Posté le 01/02/2013 à 13:16 Membre depuis le 15/03/2005, 3470 messages
Ça ne marche pas non plus... Peut être avec les macro ?
;and (hl) jr rectangle_filled2
Sinon 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... confus
battle_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
Posté le 01/02/2013 à 14:10 Membre depuis le 03/06/2011, 520 messages
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
Posté le 01/02/2013 à 14:12 Membre depuis le 15/03/2005, 3470 messages
Bon je vais continuer à faire appel deux fois à la routine (_solid et _xor) alors.
Posté le 01/02/2013 à 16:04 Membre depuis le 03/06/2011, 520 messages
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
?
Posté le 03/02/2013 à 10:11 Membre depuis le 15/03/2005, 3470 messages
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
Posté le 03/02/2013 à 10:46 Membre depuis le 11/04/2007, 1076 messages
Cool, ça avance bien !
Posté le 03/02/2013 à 12:19Edité par chickendude le 04/02/2013 à 18:09 Membre depuis le 03/06/2011, 520 messages
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
	ret
Mais 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 !
Posté le 03/02/2013 à 12:33 Membre depuis le 15/03/2005, 3470 messages
Wow, merci beaucoup ! smile
Posté le 03/02/2013 à 21:34 Membre depuis le 02/02/2009, 672 messages
Franchement c'est magnifique ! Bravo !
Posté le 04/02/2013 à 08:35 Membre depuis le 03/06/2011, 520 messages
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
Posté le 04/02/2013 à 10:24 Membre depuis le 15/03/2005, 3470 messages
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).
Posté le 04/02/2013 à 12:57 Membre depuis le 03/06/2011, 520 messages
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
	ret
Elle est peut-être plus lente mais je crois que ce ne sera pas un problème smile
Posté le 04/02/2013 à 13:44 Membre depuis le 15/03/2005, 3470 messages
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.
Posté le 04/02/2013 à 15:57 Membre depuis le 03/06/2011, 520 messages
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
Posté le 04/02/2013 à 16:58 Membre depuis le 15/03/2005, 3470 messages
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).
Posté le 04/02/2013 à 18:22 Membre depuis le 03/06/2011, 520 messages
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 !