Move sprite to X,Y (as LINE) in assembly

Página 3/4
1 | 2 | | 4

Por DanySoft

Champion (452)

Imagen del DanySoft

15-09-2013, 19:17

Okay, but create a file in ASM, we use ASMSX?
He COS, SIN, ATN ASMSX in the program, but I SJSASM
or WBASS2, how do I build a COS, SIN in ASM?

Even if I use ASMSX, but I can not abandon my data created with SJASM.
By chance, someone has already created a source for M-TANK?
Can I have a copy of the COS, SIN, and the example of the game and its tank missiles.

I have two functions ready:

        LD    E,249  ; 249 / 49 = 5 CORRETT!
        LD    C,49
        CALL  DIVIDE
        RET
DIVIDE:
; E / B = A
        XOR   A
        LD    B,8
LOOP:
        RL    E
        RLA
        SUB   C
        JR    NC,NOADD
        ADD   A,C
NOADD:
        DJNZ  LOOP
        LD    B,A
        LD    A,E
        RLA
        CPL
        RET

and the multiplier:

;
;Multiply 8-bit values
;In:  Multiply H with E
;Out: HL = result
;
Mult8:
	ld d,0
	ld l,d
	ld b,8
Mult8_Loop:
	add hl,hl
	jr nc,Mult8_NoAdd
	add hl,de
Mult8_NoAdd:
	djnz Mult8_Loop
	ret


;
;Multiply 8-bit value with a 16-bit value
;In: Multiply A with DE
;Out: HL = result
;
Mult12:	ld l,0
	ld b,8
Mult12_Loop:
	add hl,hl
	add a,a
	jr nc,Mult12_NoAdd
	add hl,de
Mult12_NoAdd:
	djnz Mult12_Loop
	ret

Now we need the function COS, SIN and ATN but I do not think that will also serve the ABS (more or less useful).
Thank you.

DanySoft

Por flyguille

Prophet (3028)

Imagen del flyguille

17-09-2013, 00:35

flyguille wrote:

For like a missile guided trayectory you use the same linear model, but improved

Why to go to the BASICS in calculation? Because it is faster, ofcourse is nice the have object and in memory to handle angles, but that sucks in speed and more for a 3.57mhz computer.

So you do the basic in math, is SUM, take aways, divisions and multiplications, nothing more than that. And when less divisions & multiplications, better.

So as if you do it in BASIC or in ASM, to SAVE any value as result of a formula that can be reuse, is better.

Let's see the missile guided approach

On the shot do:

Xdistance = ShoterX - TargetX
Ydistance = ShoterY - TargetY
if abs(xdistance) < abs(ydistance) then yStep = 1*sgn(ydistance):XStep = xdistance / abs(ydistance) else xStep = 1*sgn(xdistance):yStep = ydistance / abs(xdistance)

THIS CALCULATION es ONLY ONE TIME.

then in each frame you do for the movement. SpeedFactor can be something like = 1 (pixel by pixel movement), or bigger if the draw of the sprite is 4x4 by example you can set a Speed of = 4.

BulletSpriteX = BulletSpriteX - xStep * SpeedFactor
BulletSpriteY = BulletSpriteY - yStep * SpeedFactor

Then in every frame you needs to test if the bullet reached the borders of the screen gameplay.

if BulletSpriteX < -3 or BulletSpriteY < -3 or BulletSpriteX > 255 or BulletSpriteY > 211 then ' Its out, remove the bullet.

And test with ON SPRITE GOSUB for the colission with the target.

NOW the added

On each few frames (a planned LAG like emulating a real guided missile) you recalculate the xStep & yStep as the following way.

Xdistance = ShoterX - TargetX
Ydistance = ShoterY - TargetY
if abs(xdistance) < abs(ydistance) then yStep2 = 1*sgn(ydistance):XStep2 = xdistance / abs(ydistance) else xStep2 = 1*sgn(xdistance):yStep2 = ydistance / abs(xdistance)

' At this point xstep, ystep, xstep2, ystep2 are in the same range from -1 to 1 indication the direction.

InertialForceFactor = 2
Xstep = xstep + (xstep2-xstep) / InertialForceFactor
ystep = ystep + (ystep2-ystep) / InertialForceFactor

The inertialforcefactor depends on each how many few frame you do the recalcutation of the direction, if you recalculate like each 4 frames, the inertial factor can be 2 , but if you recalculate faster like each 2 frames, the inertial factor needs to be higher like 4, so it is a matter of LAG in recalculating new direction vs the percentage applied of that new recalculation on the current direction.

EASY!, In assembler you shifts the calculations by an factor of 256 or 512, allowing to use plain integers instead of floats. Then when adding to the sprite current position you shifts back by 256 or 512 the value .

Oh, if the game is a "side view", & you want more realistic physics, you needs to emulae the gravity factor.

Letme include it (I do anyway if you are not listening my fast solutions).

Let's see the missile guided approach Plus gravity (for sideview games).

On the shot do:

Xdistance = ShoterX - TargetX
Ydistance = ShoterY - TargetY
if abs(xdistance) < abs(ydistance) then yStep = 1*sgn(ydistance):XStep = xdistance / abs(ydistance) else xStep = 1*sgn(xdistance):yStep = ydistance / abs(xdistance)

THIS CALCULATION es ONLY ONE TIME.

then in each frame you do for the movement. SpeedFactor can be something like = 1 (pixel by pixel movement), or bigger if the draw of the sprite is 4x4 by example you can set a Speed of = 4.

GravityConstantFactor must be in the range from 0.1 to 0.3, and depends in the SpeedFactor.

BulletSpriteX = BulletSpriteX - xStep * SpeedFactor
BulletSpriteY = BulletSpriteY - yStep * SpeedFactor + GravityConstantFactor

Then in every frame you needs to test if the bullet reached the borders of the screen gameplay.

if BulletSpriteX < -3 or BulletSpriteY < -3 or BulletSpriteX > 255 or BulletSpriteY > 211 then ' Its out, remove the bullet.

And test with ON SPRITE GOSUB for the colission with the target.

NOW the added

On each few frames (a planned LAG like emulating a real guided missile) you recalculate the xStep & yStep as the following way.

Xdistance = ShoterX - TargetX 
Ydistance = ShoterY - TargetY 
if abs(xdistance) < abs(ydistance) then yStep2 = 1*sgn(ydistance):XStep2 = xdistance / abs(ydistance) else xStep2 = 1*sgn(xdistance):yStep2 = ydistance / abs(xdistance)

' At this point xstep, ystep, xstep2, ystep2 are in the same range from -1 to 1 indication the direction.

InertialForceFactor = 2
Xstep = xstep + (xstep2-xstep) / InertialForceFactor
ystep = ystep + (ystep2-ystep) / InertialForceFactor

The inertialforcefactor depends on each how many few frame you do the recalcutation of the direction, if you recalculate like each 4 frames, the inertial factor can be 2 , but if you recalculate faster like each 2 frames, the inertial factor needs to be higher like 4, so it is a matter of LAG in recalculating new direction vs the percentage applied of that new recalculation on the current direction.

Something important that I didn't mentioned before, BulletSpriteX & BulletSpriteY sprite position muy be variables Single precision (aka float), or in ASSEMBLER shifted by a 128 or 256 factor. Because they needs be capable of store littles movements less than 1 pixel.

You can use a 16bit integer in assembler, and let says, the 8 less significant bits are the fraction, and 8 more significant bits are the actual pixel position in the screen (for screen 256px width), now, for 512px width you needs to tale 9 bits, just SHIFTs them one position to load the pixel position.

Por DanySoft

Champion (452)

Imagen del DanySoft

18-09-2013, 20:15

Yes, your source of page : Unexpected behaviour of little basic listing or wrong OpenMSX emulation or just I am too oxidated
have worked properly to BASIC on different movements.

But !!
I have done in assembly by Wbass2, see this:

 ORG   $4000

BEGIN:
        CALL  INIT
        CALL  GAME
        JP    EXIT

GAME:
        LD    A,0
        CALL  $D5
        CP    1
        RET   Z
        CP    3
        JP    Z,DES
        CP    7
        JP    Z,SIN
;
GAME2:
        CALL  FIRE
        CALL  POS
        LD    A,(DIR)
        ADD   48
        LD    HL,6144
        CALL  $4D
        HALT
        JP    GAME
;
DES:
        CALL  WAIT
        LD    A,(DIR)
        INC   A
        CP    6
        JP    Z,DES00
        LD    (DIR),A
DES00:
        JP    GAME2
SIN:
        CALL  WAIT
        LD    A,(DIR)
        DEC   A
        CP    0
        JP    Z,SIN00
        LD    (DIR),A
SIN00:
        JP    GAME2

WAIT:
        HALT
        HALT
        HALT
        HALT
        RET
FIRE:
        LD    A,(DIR)
        DEC   A
        ADD   A,A
        LD    C,A
        LD    B,0
        LD    HL,NEXT
        ADD   HL,BC
        LD    (ADR),HL
;
        LD    IY,(ADR)
        LD    IX,XY
;
        LD    B,(IY+0)
;
        LD    A,(IX+0)
        ADD   A,B
        LD    (IX+0),A
;
        LD    B,(IY+1)
;
        LD    A,(IX+1)
        ADD   A,B
        LD    (IX+1),A
        RET

ADR:    DW    0               ;indirizzo wait*DIR
DIR:    DB    0
XY:     DB    100,100,0,10
NEXT:   DB    0,2             ;dir 1
        DB    -1,2            ;dir 2
        DB    -2,1            ;dir 3
        DB    -3,1            ;dir 4
        DB    -2,0            ;dir 5

INIT:
        LD    A,1
        CALL  $5F
        LD    A,$18
        LD    HL,$3800
        LD    BC,2
        CALL  $56
        LD    H,100
        LD    L,100
        LD    (XY),HL
        LD    A,1
        LD    (DIR),A
        RET

POS:
        LD    HL,XY
        LD    DE,$1B00
        LD    BC,4
        CALL  $5C
        RET
EXIT:
        CALL  $9F
        LD    A,0
        JP    $5F
TEXT:
        DB    "0"

This dot allows movement with 5-way with the LEFT or RIGHT button.
UP to exit and return to Wbass2. (debug)
DanySoft

Por flyguille

Prophet (3028)

Imagen del flyguille

19-09-2013, 01:54

you are using tniASM? it is the best.

I am redoing the example in asm, since the speed of the basic interpreter is a shame for handling lots of objects.

I will do the physics control part, so you can start from that module (reading the tniasm manual againt ATM).

It is a bit of a problem, I must thinks about signed variables fMult16: don't take in account signs, that can be quite a problem for indicating upleft directions, or the sprite hidding partialy in the left/up border.

I have so far this

FNAME "bs.bin"

; STRUCTURES DECLARATIONS.

ORG $0
Bullet:
	.Type:	RB	1 ; (0 = disabled, 1 = bullet, 2 = missile.)
	.X:	RW	1 ; X position, scale 1pixel = 128.
	.Y:	RW	1 ; Y position """"".
	.StepX:	Rw	1 ; X Speed """"".
	.StepY:	RW	1 ; Y Speed """"".
	.RLag:	RB	1 ; Reaction Lag range in FRAMES.
	.SFactor: RW	1 ; SpeedFactor fixed point highbyte = integer.
	.Inertial: RB	1 ; Inertial, range 0 to 255 for (0% up to 100%), it is the % on how a given reaction affects the current trayectory. 
        .BPattern: RB	1 ; Base pattern to use.
	.PType:	RB	1 ; Some indication if it will be single pattern or directional pattern for graphics purpose.
	.SizeOf:

ORG $0



ORG $D000
TotalBullets:	EQU 31
GravityConst:	EQU $0010 ; = 1/16 pixel per frame.

BA:	RB	(Bullet.SizeOF * TotalBullets) ; It reserves space for all bullets instances.


; BSAVE header.

	DB $FE
	DW $9000
	DW ORG_END - 1
	DW $9000

ORG $9000

	ld b, TotalBullets
	ld ix, BA
ObjectBucleStart:
	push bc
	push ix			; Object Bucle **** FOR B=TotalBullets TO 0 step -1.


	ld a,(ix + Bullet.Type)
	and a
	jp z, ObjectBucle	; .Type = 0 = unused. 
	
	ld e,(ix + Bullet.StepX)
	ld d,(ix + (Bullet.StepX+1))
	ld l,(ix + Bullet.SFactor)
	ld h,(ix + (Bullet.SFactor+1))
	Call fMult16
	jp c, DeleteObject
	ex de,hl
	ld l,(ix + Bullet.X)
	ld h,(ix + (Bullet.X+1))
	sbc hl,de
	jp c, DeleteObject
	ld (ix + Bullet.X),l
	ld (ix + (Bullet.X+1)),h	; **** X(B)=X(B)-SX(B)* S!(B).

	ld e,(ix + Bullet.StepY)
	ld d,(ix + (Bullet.StepY+1))
	ld l,(ix + Bullet.SFactor)
	ld h,(ix + (Bullet.SFactor+1))
	Call fMult16
	jp c, DeleteObject
	ex de,hl
	ld l,(ix + Bullet.Y)
	ld h,(ix + (Bullet.Y+1))
	sbc hl,de
	jp c, DeleteObject
	
	ld de, GravityConst
	add hl,de
	jp c, DeleteObject

	ld (ix + Bullet.Y),l
	ld (ix + (Bullet.Y+1)),h	; **** Y(B)=Y(B)-SY(B)* S!(B) + GC.
	
	ld a, 0   ; **** IF X(B)<-384 OR Y(B)<-384 OR X(B)>30000 OR Y(B)> 27136 THEN










	
ObjectBucle:
	pop ix
	pop bc
	ld de, Bullet.SizeOf
	add ix, de
	dec b
	jp nz, ObjectBucleStart

	ret

DeleteObject:
	ld (ix + Bullet.Type),0
	; ****** Here the equivalent of PUT SPRITE B,(0,218) for erasing the sprite ******.
	jr ObjectBucle
	



; DE * A = HL + cf = 1 if overflow.

Mult12:	ld l,0
	ld b,8
Mult12_Loop:
	add hl,hl
	add a,a
	jr nc,Mult12_NoAdd
	add hl,de
	ret c
Mult12_NoAdd:
	djnz Mult12_Loop
	and a
	ret


; DE * HL (H-L as integer + fraction) = HL + cf = 1 if overflow.
fMult16:
	push de
	push hl
	ld a, h
	Call Mult12
	pop bc
	pop de
	ret c
	push hl
	ld e,d
	ld d,0
	ld a,c
	call mult12
	pop de
	ret c
	add hl, de
	ret




ORG_END:

If you catchs how is the programming.

Por DanySoft

Champion (452)

Imagen del DanySoft

19-09-2013, 15:23

Okay, but could not use a complete example?
the syntax is:
two missiles is reaching toward the object.
Add the sprite!

Almost forgot:
TNIASM << == do not want to know: in the free version, however,
has removed the macro's, so I do not care.

I am referring to SJASM, have the macro, so I can add more macro commands.

Meanwhile immediately examine your source, to see the results.

Thank you.

Por flyguille

Prophet (3028)

Imagen del flyguille

19-09-2013, 19:24

why do you needs MACROS? I didn't need it and you can anything.

Por DanySoft

Champion (452)

Imagen del DanySoft

19-09-2013, 22:28

Yes, there I need to have more MACRO's:
GEN80, M80/L80 already have the macro.

I have already created many sources with MACRO with SJASM, the best program compiler!

You do not need any macro in your source, waiting for your answer to my question below:

Quote:

Okay, but could not use a complete example?
the syntax is:
two missiles is reaching toward the object.
Add the sprite!

greetings
DanySoft

Por DanySoft

Champion (452)

Imagen del DanySoft

24-09-2013, 23:00

Done,
I just did a BASIC program:
I was able to use the four missiles with a simple function:
accelerates the speed with TURBO!

10 REM save "a.bas
20 KEY OFF:COLOR 15,1,1:SCREEN 1:WIDTH32
30 SPRITE$(0)=CHR$(&H18)+CHR$(&H18)
40 PRINT "Preparazione in corso...";
50 REM goto 90
60 CALL TURBO ON
70 DIM A(359),B(359),I(5),J(5)
80 FOR L=1 TO 359
90 A(L)=COS(L/180*3.14)
100 B(L)=SIN(L/180*3.14)
110 NEXT L
120 REM
130 PRINT " OK!!":D=40
140 REM
150 REM
160 LOCATE 5,5:PRINT"Direzione:";D:F=0:N=0:FOR L=D TO D+4
170 I(N)=L*7:J(N)=L*7:N=N+1
180 NEXT L
190 I$=INKEY$
200 IF I$=CHR$(27)  THEN GOTO 320
201 IF I$=CHR$(28) THEN F=1:D=D+1:IF D=>359 THEN D=0
202 IF I$=CHR$(29) THEN F=1:D=D-1:IF D=<1 THEN D=359
203 IF F=1 THEN GOTO 160
210 IF I$= " " THEN GOTO 240
220 GOTO 190
230 REM
240 N=0
250 FOR L=0 TO 3:
260 X=A(I(L))*N
270 Y=B(J(L))*N
280 PUT SPRITEL,(100+X,100+Y),15-L,0
290 NEXT L
300 N=N+4: IF N=>150 THEN N=0:GOTO 190
310 GOTO 250
320 REM
330 CALL TURBO OFF
340 END

Now I know how to program the missiles that soon will mount on assembleer.
Thank you for everything!
DanySoft Big smile

Por flyguille

Prophet (3028)

Imagen del flyguille

25-09-2013, 14:39

DanySoft wrote:

Done,
I just did a BASIC program:
I was able to use the four missiles with a simple function:
accelerates the speed with TURBO!

10 REM save "a.bas
20 KEY OFF:COLOR 15,1,1:SCREEN 1:WIDTH32
30 SPRITE$(0)=CHR$(&H18)+CHR$(&H18)
40 PRINT "Preparazione in corso...";
50 REM goto 90
60 CALL TURBO ON
70 DIM A(359),B(359),I(5),J(5)
80 FOR L=1 TO 359
90 A(L)=COS(L/180*3.14)
100 B(L)=SIN(L/180*3.14)
110 NEXT L
120 REM
130 PRINT " OK!!":D=40
140 REM
150 REM
160 LOCATE 5,5:PRINT"Direzione:";D:F=0:N=0:FOR L=D TO D+4
170 I(N)=L*7:J(N)=L*7:N=N+1
180 NEXT L
190 I$=INKEY$
200 IF I$=CHR$(27)  THEN GOTO 320
201 IF I$=CHR$(28) THEN F=1:D=D+1:IF D=>359 THEN D=0
202 IF I$=CHR$(29) THEN F=1:D=D-1:IF D=<1 THEN D=359
203 IF F=1 THEN GOTO 160
210 IF I$= " " THEN GOTO 240
220 GOTO 190
230 REM
240 N=0
250 FOR L=0 TO 3:
260 X=A(I(L))*N
270 Y=B(J(L))*N
280 PUT SPRITEL,(100+X,100+Y),15-L,0
290 NEXT L
300 N=N+4: IF N=>150 THEN N=0:GOTO 190
310 GOTO 250
320 REM
330 CALL TURBO OFF
340 END

Now I know how to program the missiles that soon will mount on assembleer.
Thank you for everything!
DanySoft Big smile

turbo basic is not standard, it works on a few given models of MSX. That is the reason why there is no plenty of BASIC GAMES made in turbo basic.

Por DanySoft

Champion (452)

Imagen del DanySoft

26-09-2013, 21:57

Ok
I will use ASMSX to compile the binary for all compatible models without the TURBO ON/OFF!

We hope to use the ASMSX to prepare a new project on the use of COS / SIN.

For the moment there is no news. Wait very soon!
Hello
DanySoft

Página 3/4
1 | 2 | | 4