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

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

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.

```        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
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:
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:
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

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.

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.

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.

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)
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
LD    C,A
LD    B,0
LD    HL,NEXT
;
LD    IX,XY
;
LD    B,(IY+0)
;
LD    A,(IX+0)
LD    (IX+0),A
;
LD    B,(IY+1)
;
LD    A,(IX+1)
LD    (IX+1),A
RET

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.
DanySoft

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.

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
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
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:
ret c
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
ret

ORG_END:

```

If you catchs how is the programming.

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

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.

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

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.

greetings
DanySoft

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 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 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.

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