Moving sprites using keys

ページ 1/2
| 2

By DeadMan

Supporter (8)

DeadMan さんの画像

04-05-2023, 00:40

Hello,i'm using sjasm and following a tutorial,but i cant figure out how to move a sprite.Being a noob as i am it took me like an hour or two to show a sprite on screen,but now i dont know how to move it.
How can i move a sprite up/down,left/right using keys?
I'm displaying a character using two sprites,one for the outline color and the other one used to fill the color.
Im in screen mode 2 for msx1.

Thank you and i hope im not violating any rules. Tongue

ログイン/登録して投稿

By aoineko

Paragon (1132)

aoineko さんの画像

04-05-2023, 10:13

You first have to detect key press, then to move your sprite accordingly you have to change the X and Y value in the corresponding Sprite attribute table.
If you use sprite #0 and #1 for your character, you have to update both position.
Sprite attribute table is an area of the VRAM that store each sprite's attribute. Each sprite use 4 bytes for attribute. First Y position, then X one (then Pattern index and color).

By DeadMan

Supporter (8)

DeadMan さんの画像

04-05-2023, 13:23

Yes,i know the theory,but i cant get the sprites to move,how do i change the values of the sprite attribute table in an effective way?
Thank you

By thegeps

Paragon (1249)

thegeps さんの画像

04-05-2023, 13:32

Post here the code you are using to display the sprite, so we can suggest you how to modify it. Otherwise you'll be overwhelmed by a multitude of differents sources, and many of them you won't be able to understand yet.

Anyway, as starting point, check out the MSX bios routines. You will find write ro vram routines and joustick routines too (you can use GTSTCK to read cursor keys too)

By aoineko

Paragon (1132)

aoineko さんの画像

04-05-2023, 13:39

It's all about writing the right value at the write VRAM address.
If you want to put sprite N at position X,Y, you have to write Y at (SAT_Addr + 4 * N) and X at (SAT_Addr + 4 * N + 1).

So you need two things:
- Have a vpoke routine (you have one in BIOS)
- Know where SAT is located in VRAM (depend of your system but you can get the address from BIOS)

But if you are able to display a sprite on screen, I suppose you already have both.

By DeadMan

Supporter (8)

DeadMan さんの画像

04-05-2023, 15:44

Hi,thanks for the answers,this is my code,im sure its full of nonsense lol
The sprite and the tilemaps show no problem,but i cant figure out what im doing wrong to move the sprite with the o,p keys....

    output	"programa.rom"


CHGET equ     #009F
CHPUT equ     #00A2
POSIT equ     #00C6
INLIN equ     #00B1
GTTRIG equ    #00D8
GTSTCK equ    #00D5



RDVDP equ      #013E
WRTVDP equ     #0047
LDIRVM equ     #005C
LDIRMV equ     #0059
CHGMOD equ     #005F

RG0SAV equ     #F3DF
RG1SAV equ     #F3E0
RG2SAV equ     #F3E1
RG3SAV equ     #F3E2
RG4SAV equ     #F3E3
RG5SAV equ     #F3E4
RG6SAV equ     #F3E5
RG7SAV equ     #F3E6
STATFL equ     #F3E7
;NUMERO DE SPRITES
NMRSPRTS         equ   2
NMRATRBTS        equ   2


		
		org		#4000
			
		;Cabecera
		db "AB"
		word START
		word END
		word START	
	 
	 
START:      
	 di
	 call  inicia_video	
	 call  inicia_tiles_y_sprites 
	 call  volcar_sprite_VRAM
     ret
inicializar_sprite:
     ld ix, atributos_sprites ;	 
loop:
    
	halt
    call CHGET ;espera a que se pulse una tecla, cuando se pulsa la almacena en el registro a del z80
    cp 'p'
    jp z, mover_sprite_derecha
    cp 'o'
    jp z, mover_sprite_izquierda
    ;;;;;	
    jp loop    

mover_sprite_derecha:
     ld a,(ix+1)
     add 3
     ld (ix+1), a 
	 call loop
	 call volcar_sprite_VRAM
mover_sprite_izquierda:
     ld a,(ix+1)
     sub 3
     ld (ix+1), a 	 
	 call loop
	 call volcar_sprite_VRAM 
inicia_video:    
	  ;ponemos modo 2 de pantalla de la bios
    ld    a,2
    call  CHGMOD
    ;prueba cambio borde y fondo
	ld  a,(RG1SAV)
	or  00000010b
	and 11111110b	
	ld  b,a
	ld  c,1
	call WRTVDP	
    ret	
inicia_tiles_y_sprites:
    ;MAPAS TILES
	;cargamos patrones de tiles
    ld    hl,tiles_primer_tercio
    ld    de,#0000
    ld    bc,765*8
    call  LDIRVM	
	
	;cargamos los colores de los tilesets
	ld    hl,tiles_primer_tercio_color
	ld    de,#2000
	ld    bc,765*8
	call LDIRVM
	
	;cargamos los nombres de los patrones
	ld    hl,dibujo
	ld    de,#1800
	ld    bc,765
	call  LDIRVM
	ret
volcar_sprite_VRAM:	
  ;cargamos los sprites y atributos
    ;sprite
	ld    hl,sprites
	ld    de,#3800
	ld    bc,NMRSPRTS*32
	call  LDIRVM
    ;atributos
	ld hl,atributos_sprites
	ld de,#1b00	
	ld bc,NMRATRBTS*4
	call LDIRVM
	ret
 
	 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
;CONSTANTES 
tiles_primer_tercio:            incbin "tiles.bin.chr"
tiles_primer_tercio_color:      incbin "tiles.bin.clr"
dibujo:                         incbin "dibujo.bin"
sprites:
; SPRITE IDLE FILL
    .....
; SPRITE IDLE OUTLINE
     ....
;VARIABLES
atributos_sprites:	      
       db 104,105,0,14
	   db 104,105,4,1
END:

I removed the sprite data so the code is not so long but other than that,thats my full code.

By theNestruo

Champion (428)

theNestruo さんの画像

04-05-2023, 15:54

Not looked at it deeply (sorry), but I think the problem is here:

mover_sprite_derecha:
     ; ... 
	 call loop
	 call volcar_sprite_VRAM
mover_sprite_izquierda:
     ; ...
	 call loop
	 call volcar_sprite_VRAM 

It is more likely that you wanted to do:

mover_sprite_derecha:
     ; ...
	 call volcar_sprite_VRAM
	 jp loop
mover_sprite_izquierda:
     ; ...
	 call volcar_sprite_VRAM 
	 jp loop

Otherwise, you are going back to the loop before blitting to VRAM.

Edit:
Also: it seems that the ret at the end of START should not be here. It is preventing the flow to continue to inicializar_sprite and loop.
And, despite interruptions are more likely restored by the BIOS somewhere after you disabled them, I would put an ei just before inicializar_sprite to be extra sure.

By DeadMan

Supporter (8)

DeadMan さんの画像

04-05-2023, 16:04

Thanks theNestruo,i changed the code as you said,and still cant move the sprite,also,i noticed that if i check the sprite viewer in meisei emulator,i have 8 sprite attribute sets created,when i only have 2 in my code. oO

By cjs

Master (143)

cjs さんの画像

04-05-2023, 16:16

DeadMan wrote:
		org		#4000
			
		;Cabecera
		db "AB"
		word START
		word END
		word START	

START:      
	 ...

This is probably not related to your problem, but it looks to me as if you've set up the incorrectly. The db "AB" and first word START are correct, but after that you're setting up BASIC CALL to jump to just past the end of your code and a couple of other things related to BASIC. I think after the first word START you want a db 12 dup $00 (i.e., twelve $00 values) or equivalent to ensure that the rest of the header is $00 values before you start your code.

(What you've got there, if you replaced the initial db "AB" with db $FE would be the correct header for a file you BLOAD "...",R from BASIC.)

By DeadMan

Supporter (8)

DeadMan さんの画像

04-05-2023, 16:49

cjs wrote:

This is probably not related to your problem, but it looks to me as if you've set up the incorrectly. The db "AB" and first word START are correct, but after that you're setting up BASIC CALL to jump to just past the end of your code and a couple of other things related to BASIC. I think after the first word START you want a db 12 dup $00 (i.e., twelve $00 values) or equivalent to ensure that the rest of the header is $00 values before you start your code.

(What you've got there, if you replaced the initial db "AB" with db $FE would be the correct header for a file you BLOAD "...",R from BASIC.)

Does that work for a rom cartridge format?

By santiontanon

Paragon (1830)

santiontanon さんの画像

04-05-2023, 17:05

cjs is correct, the header is wrong for a .rom, the header should be:

;-----------------------------------------------
    db "AB"     ; ROM signature
    dw START
    db 0,0,0,0,0,0,0,0,0,0,0,0
;-----------------------------------------------

Also, as TheNestruo already said:
- the "ret" just before "inicializar_sprite:" should not be there, as that will try to "return", but to an uninitialized stack position, so, execution from that point will be random.
- Instead of that "ret", you need an "ei", otherwise, the "halt" right after might stop your program forever as interrupts might be disabled, depending on the BIOS.
- also, I am not sure if CHGET modifies the "ix" register or not, so, to be safe I would move that "ld ix, atributos_sprites" line to both "mover_sprite_derecha" and "mover_sprite_izquierda"
- and finally, if it still does not work, the easy way to figure it out is to run this through the openMSXDebugger and set some breakpoints. Do you know how to use it? It'll probably solve your problem in 5 minutes Smile

ページ 1/2
| 2