Автор: Toni Baker
Год: 1984
Издатели: Your Spectrum
Языки:
Английский
Формат:
TAP лента
Требования:
ZX Spectrum 48K
Ссылки:
Страница на ZXArt
Страница на World Of Spectrum
Страница на Spectrum Computing
Скриншоты:
Год: 1984
Издатели: Your Spectrum
Языки:
Формат:
Требования:
Ссылки:
Скриншоты:
!0.......^.........^.........^..
!B
\H11\H07\H10\H00 S P R I T E
\H11\H07\H10\H00 D E S I G N E R
!2.......^.........^.........^.........^.........^.........^....
User-defined sprites on the Spectrum? It's not that difficult!
Get things moving on-screen with more machine code magic from
Toni Baker.
!1.......^.........^.........^.........^........
This month's block of crafty code makes weird
shapes fly around all over the screen. In fact,
you shouldn't find it too hard to add a few bits
and pieces to the idea yourself. It's all basic-
ally very simple. You design up to five
different sprites - of any figure, shape, design
and so on - which in this case are 16 pixels
wide by 16 pixels high; imagine four user-
defined graphics characters glued together in a
square and you have the idea. But - and this is
where the story really begins - there's more to
this program than meets the eye, for it incorp-
orates a rather mind-blowing idea ...
!0.......^.........^.........^..
!B
MOTION PICTURES
!1.......^.........^.........^.........^........
You see, once you've defined a sprite, you can
then specify its coordinates on the screen and
its velocity across the screen. In other words,
they move! Curiouser and curiouser. Once a
sprite is set in motion, you can continue exe-
cuting more Basic or machine code. The sprites
will keep moving on-screen, simultaneously with
any other program.
One line of Basic can set a sprite in motion.
The next Basic line will, of course, be executed
in sequence - but it'll be executed whilst the
sprite is moving. Thus, the setting in motion in
the first place is all you have to worry about.
How it all works is quite intricate, so I'll
explain in a moment or two; if you find the
blurb a bit too heavy going, try quaffing a
cuppa or two before attempting to follow it. In
the meantime, I'll tell you how to integrate my
machine code with your Basic.
!0.......^.........^.........^..
!B
DOWN TO DESIGN
!1.......^.........^.........^.........^........
The first statement of your Basic program must
be a "DIM s$(x,8)"; where x is the maximum
number of things you want flying around on-
screen at any one time. Then, you'll want to
include the statements "LET on=33013" and "LET
off=33020". From here on in it's up to you. The
statement "RANDOMIZE USR on" will bring the
moving sprite facility into action, whereas the
statement "RANDOMIZE USR off"will bring things
back to normal.
The sprites themselves are defined using the
ordinary user-defined graphics. You can have up
to five different designs on-screen at once,
which are:
!0.......^.........^.........^..
Sprite 1=UDGs A,B,C,D
Sprite 2=UDGs E,F,G,H
Sprite 3=UDGs I,J,K,L
Sprite 4=UDGs M,N,O,P
Sprite 5=UDGs Q,R,S,T
!1.......^.........^.........^.........^........
You can define them yourself in the usual ways.
The array, s$, is the one that contains all
the information, however, and each element must
be precisely defined. Now ... it's "pay atten-
tion" time. Take a look at the box giving the
explanation of the sprite parameters. (Note that
in the explanations given, I've used the letter
'N' to represent one of the strings in s$; the
number is completely arbitrary.)
The element s$(N,8) is actually very import-
ant. If it contains any character whose code is
less than or equal to 64 (decimal), then the
sprite is said to be inactive - that is, it'll
not appear on the screen. You can make as many
alterations as you like to the other elements of
s$. Once all the alterations have been made, you
can then alter s$(N,8) and the sprite will be
active and will start moving across the screen.
If such a moving sprite collides with anything
on-screen, or if it hits the edges of the
screen, then it'll instantly stop
!0.......^.........^.........^..
!B
--------------------------------
\H11\H07\H10\H00 THE SPRITE PARAMETERS
--------------------------------
STRING | EXPLANATION
ELEMENT |
--------------------------------
s$(N,1) |CHR$ (the sprite number
| - between one & five)
--------------------------------
s$(N,2) |This must always be
|initialised to CHR$(1)
--------------------------------
s$(N,3) |CHR$ (the number of
|frames between
|successive movements)
--------------------------------
s$(N,4) |CHR$ (the figure's Y
|coordinate)
--------------------------------
s$(N,5) |CHR$ (the figure's X
|coordinate)
--------------------------------
s$(N,6) |CHR$ (the figure's
|vertical displacement
|each time it moves)
--------------------------------
s$(N,7) |CHR$( the figure's
|horizontal displacement
|each time it moves)
--------------------------------
s$(N,8) |This must be set last
|of all, and must be any
|character whose code is
|greater than 64
--------------------------------
!2.......^.........^.........^.........^.........^.........^....
In the table above, it must be noted that 'N' is used to repre-
sent one of the strings in s$ - the number is arbitrary.
!1.......^.........^.........^.........^........
!B
moving and deactivate. Element s$(N,8) will
automatically reset to CHR$(0). You can test for
this occurrence in a Basic program.
!0.......^.........^.........^..
A TIMELY INTERRUPTION
!1.......^.........^.........^.........^........
OK, it's tea-break time! Arm yourself with a
cuppa and I'll explain how it all works.
The machine code is an interrupt routine. This
means that the program runs itself automatically
50 times a second. Each time it runs it checks
out the array s$ and shuffles sprites around the
screen accordingly. The basic instruction
"RANDOMIZE USR on" simply activates this
interrupt procedure, whereas "RANDOMIZE USR off"
deactivates it. Interrupt procedures are quite
clever; however, it's very easy to muck things
up and just a tiny little bug will spell total
disaster and blast the poor Speccy into
oblivion. This is true simple because the
program runs itself once for every new TV frame,
whether you want it to or not.
Take a peek at the basic program that's lying
around in this article. It manages to do in just
a few statements what would otherwise have been
quite a complicated program; it produces a
figure which bounces around the screen. The
first seven lines just initialise the array, s$,
and line 80 starts things moving. Line 90 is the
one to think about - it looks like an infinite
loop, but in fact it's not; it's just waiting
until the figure hits an edge. If you break out
of the program at any time you'll notice that
the figure will keep moving even while you type
a command, until it hits a wall (when it will
stop). At this point, you should type "RANDOMIZE
USR off" before you do anything else.
Well, that's it for this issue. I'm just going
off to stick my head in a bucket of inspiration
- hopefully in time for me to produce yet more
gems next month. See you then.
!2.......^.........^.........^.........^.........^.........^....
!B
--------------------------------.-------------------------------
10 DIM s$(1,8) Dimensions the array, s$
--------------------------------.-------------------------------
20 LET on=33013 Initialise the variables
30 LET off=33020
--------------------------------.-------------------------------
40 FOR j=1 TO 8 Read the data in line 160
50 READ a
60 LET s$(1,j)=CHR$ a
70 NEXT j
--------------------------------.-------------------------------
80 RANDOMIZE USR on Switches on the sprite facility
--------------------------------.-------------------------------
90 IF s$(1,8)="A" THEN GO TO Waits until a sprite hits the
90 edge of the screen
--------------------------------.-------------------------------
100 LET y=CODE s$(1,4) 'y' is the Y coordinate of the
sprite
--------------------------------.-------------------------------
110 LET x=CODE s$(1,5) 'x' is the X coordinate of the
sprite
--------------------------------.-------------------------------
120 IF y=0 OR y=22 THEN LET s$ Reverses the Y movement of
(1,6)=CHR$ (256-CODE s$(1,6)): B the sprite if necessary
EEP .03,24
--------------------------------.-------------------------------
130 IF x=0 OR x=30 THEN LET s$ Reverses the X movement of
(1,7)=CHR$ (256-CODE s$(1,7)): B the sprite if necessary
EEP .03,12
--------------------------------.-------------------------------
140 LET s$(1,8)="A" Reactivates the sprite
--------------------------------.-------------------------------
150 GO TO 90 A loop to send the action back
to line 90.
--------------------------------.-------------------------------
160 DATA 1,1,2,10,5,255,1,65 Contains the data for s$
--------------------------------.-------------------------------
The Basic program to get things moving on-screen - type it in
and see ...
!B
Machine code Assembler Comments
---------.---------.------------------.-------------------------
ORG 80F5
---------.---------.------------------.-------------------------
3E80 ON LD A,#80
ED47 LD I,A I:=80
ED5E IM 2 Activate interrupt routine
C9 RET
---------.---------.------------------.-------------------------
ED46 OFF IM 0 Deactivate routine
C9 RET
---------.---------.------------------.-------------------------
0181 IADDR DEFW 8101 Direct interrupt control
to address 8101
---------.---------.------------------.-------------------------
F5 SPRITES PUSH AF
C5 PUSH BC
D5 PUSH DE
E5 PUSH HL
DDE5 PUSH IX Stack all registers used
by the routine
DD2A4B5C LD IX,(VARS) Point IX to array s$
DD7E00 LD A,(IX+#00)
FED3 CP #D3
200F JR NZ,EXIT Jump if first variable is
not array s$
DD4604 LD B,(IX+#04) B:=1st dimension of array
(number of sprites)
---------.---------.------------------.-------------------------
C5 SP_LOOP PUSH BC Stack this number
010800 LD BC,#0008
DD09 ADD IX,BC Point IX to start of next
sprite(next array element)
CD7181 CALL NXT_SPRT Treat next sprite
C1 POP BC B:=remaining number of
sprites to treat
10F4 DJNZ SP_LOOP
---------.---------.------------------.-------------------------
DDE1 EXIT POP IX
E1 POP HL
D1 POP DE
C1 POP BC
F1 POP AF Restore all registers
FF RST #38 Carry out normal
interrupt procedures
C9 RET
---------.---------.------------------.-------------------------
CB0C LINE RRC H
CB0C RRC H
CB0C RRC H HL:=coded print position
011F00 LD BC,#001F
09 ADD HL,BC Move print position one
square down and one left
CB04 RLC H
CB04 RLC H
CB04 RLC H HL:=correct print position
C9 RET
---------.---------.------------------.-------------------------
CD4081 WIPE CALL H_WIPE Erase top half of sprite
CD2981 CALL LINE Point HL to bottom half of
sprite
---------.---------.------------------.-------------------------
CD4481 H_WIPE CALL Q_WIPE Erase one square of sprite
23 INC HL Point HL to remaining square
---------.---------.------------------.-------------------------
E5 Q_WIPE PUSH HL
0608 LD B,#08 B:=Number of rows per
square
---------.---------.------------------.-------------------------
3600 WP_LOOP LD (HL),#00 Erase next row
24 INC H Point HL to next row
10FB DJNZ WP_LOOP
E1 POP HL
C9 RET
---------.---------.------------------.-------------------------
AF TEST XOR A A:=00
CD5581 CALL H_TEST Test upper half of sprite
position
CD2981 CALL LINE Point HL to lower half
---------.---------.------------------.-------------------------
CD5981 H_TEST CALL Q_TEST Test one square of sprite
position
23 INC HL Point HL to remaining square
---------.---------.------------------.-------------------------
E5 Q_TEST PUSH HL
0608 LD B,#08
---------.---------.------------------.-------------------------
B6 TS_LOOP OR (HL) If any pixel is set then A
becomes non-zero
24 INC H HL points to next row
10FC DJNZ TS_LOOP
E1 POP HL
C9 RET
---------.---------.------------------.-------------------------
78 FIND_ADDR LD A,B This subroutine computes
E618 AND #18 in HL the print pos of the
F640 OR #40 square (on-screen) which
67 LD H,A has PRINT-AT coords given
78 LD A,B by registers B,C
0F RRCA
0F RRCA
0F RRCA
E6E0 AND #E0
B1 OR C
6F LD L,A
C9 RET
---------.---------.------------------.-------------------------
DD7E07 NXT_SPRT LD A,(IX+#07) A:=activation flag
FE40 CP #40
D8 RET C Return if sprite inactive
DD3501 DEC (IX+#01) Count frames between
movements
C0 RET NZ Return if the sprite does
not require moving
DD7E02 LD A,(IX+#02) A:=frame interval between
movements
DD7701 LD (IX+#01),A Re-initialise frame count
DD4603 LD B,(IX+#03) B:=y coordinate
DD4E04 LD C,(IX+#04) C:=x coordinate
CD6281 CALL FIND_ADDR HL:=print pos of sprite
CD3A81 CALL WIPE Erase sprite
DD7E03 LD A,(IX+#03) A:=y coordinate
DD8605 ADD A,(IX+#05) A:=intended y coordinate
FE17 CP #17
301F JR NC,NS_EXIT Jump if intended y coord
out of range
47 LD B,A B:=intended y coordinate
DD7E04 LD A,(IX+#04) A:=x coordinate
DD8606 ADD A,(IX+#06) A:=intended x coordinate
FE1F CP #1F
3014 JR NC,NS_EXIT Jump if intended x coord
out of range
4F LD C,A C:=intended x coordinate
---------.---------.------------------.-------------------------
C5 PUSH BC
CD6281 CALL FIND_ADDR HL:=intended print pos
CD4E81 CALL TEST Test for collision
C1 POP BC BC:=intended coordinates
A7 AND A
2008 JR NZ,NS_EXIT Jump if sprite has hit
something
DD7003 LD (IX+#03),B Store new y coordinate
DD7104 LD (IX+#04),C Store new x coordinate
180A JR NS_DRAW
---------.---------.------------------.-------------------------
DD360700 NS_EXIT LD (IX+#07),#00 Deactivate sprite
DD4603 LD B,(IX+#03) B:=old y coordinate
DD4E04 LD C,(IX+#04) C:=old x coordinate
---------.---------.------------------.-------------------------
DD6E00 NS_DRAW LD L,(IX+#00) L:=sprite type number
2D DEC L L now in range 0 to 4
2600 LD H,#00 HL now in range 0 to 4
29 ADD HL,HL
29 ADD HL,HL
29 ADD HL,HL
29 ADD HL,HL
29 ADD HL,HL Multiply by 32d
ED5B7B5C LD DE,(UDG) Point DE to graphic A
19 ADD HL,DE Point HL to required
sprite graphics
E5 PUSH HL
CD6281 CALL FIND_ADDR HL:=print pos of sprite
D1 POP DE DE:=address of pixel
information
---------.---------.------------------.-------------------------
CDDB81 DRAW CALL H_DRAW Draw upper half of sprite
CD2981 CALL LINE Point HL to lower half
---------.---------.------------------.-------------------------
CDDF81 H_DRAW CALL Q_DRAW Draw next square of sprite
23 INC HL Point HL to next square
---------.---------.------------------.-------------------------
E5 Q_DRAW PUSH HL
0608 LD B,#08
---------.---------.------------------.-------------------------
1A DR_LOOP LD A,(DE)
77 LD (HL),A Print next row
13 INC DE
24 INC H Point HL to next row
10FA DJNZ DR_LOOP
E1 POP HL
C9 RET
---------.---------.------------------.-------------------------
!1.......^.........^.........^.........^........
!B
--
from Your Spectrum #10 (Dec/Jan.1984/85)
--
!$
!B
\H11\H07\H10\H00 S P R I T E
\H11\H07\H10\H00 D E S I G N E R
!2.......^.........^.........^.........^.........^.........^....
User-defined sprites on the Spectrum? It's not that difficult!
Get things moving on-screen with more machine code magic from
Toni Baker.
!1.......^.........^.........^.........^........
This month's block of crafty code makes weird
shapes fly around all over the screen. In fact,
you shouldn't find it too hard to add a few bits
and pieces to the idea yourself. It's all basic-
ally very simple. You design up to five
different sprites - of any figure, shape, design
and so on - which in this case are 16 pixels
wide by 16 pixels high; imagine four user-
defined graphics characters glued together in a
square and you have the idea. But - and this is
where the story really begins - there's more to
this program than meets the eye, for it incorp-
orates a rather mind-blowing idea ...
!0.......^.........^.........^..
!B
MOTION PICTURES
!1.......^.........^.........^.........^........
You see, once you've defined a sprite, you can
then specify its coordinates on the screen and
its velocity across the screen. In other words,
they move! Curiouser and curiouser. Once a
sprite is set in motion, you can continue exe-
cuting more Basic or machine code. The sprites
will keep moving on-screen, simultaneously with
any other program.
One line of Basic can set a sprite in motion.
The next Basic line will, of course, be executed
in sequence - but it'll be executed whilst the
sprite is moving. Thus, the setting in motion in
the first place is all you have to worry about.
How it all works is quite intricate, so I'll
explain in a moment or two; if you find the
blurb a bit too heavy going, try quaffing a
cuppa or two before attempting to follow it. In
the meantime, I'll tell you how to integrate my
machine code with your Basic.
!0.......^.........^.........^..
!B
DOWN TO DESIGN
!1.......^.........^.........^.........^........
The first statement of your Basic program must
be a "DIM s$(x,8)"; where x is the maximum
number of things you want flying around on-
screen at any one time. Then, you'll want to
include the statements "LET on=33013" and "LET
off=33020". From here on in it's up to you. The
statement "RANDOMIZE USR on" will bring the
moving sprite facility into action, whereas the
statement "RANDOMIZE USR off"will bring things
back to normal.
The sprites themselves are defined using the
ordinary user-defined graphics. You can have up
to five different designs on-screen at once,
which are:
!0.......^.........^.........^..
Sprite 1=UDGs A,B,C,D
Sprite 2=UDGs E,F,G,H
Sprite 3=UDGs I,J,K,L
Sprite 4=UDGs M,N,O,P
Sprite 5=UDGs Q,R,S,T
!1.......^.........^.........^.........^........
You can define them yourself in the usual ways.
The array, s$, is the one that contains all
the information, however, and each element must
be precisely defined. Now ... it's "pay atten-
tion" time. Take a look at the box giving the
explanation of the sprite parameters. (Note that
in the explanations given, I've used the letter
'N' to represent one of the strings in s$; the
number is completely arbitrary.)
The element s$(N,8) is actually very import-
ant. If it contains any character whose code is
less than or equal to 64 (decimal), then the
sprite is said to be inactive - that is, it'll
not appear on the screen. You can make as many
alterations as you like to the other elements of
s$. Once all the alterations have been made, you
can then alter s$(N,8) and the sprite will be
active and will start moving across the screen.
If such a moving sprite collides with anything
on-screen, or if it hits the edges of the
screen, then it'll instantly stop
!0.......^.........^.........^..
!B
--------------------------------
\H11\H07\H10\H00 THE SPRITE PARAMETERS
--------------------------------
STRING | EXPLANATION
ELEMENT |
--------------------------------
s$(N,1) |CHR$ (the sprite number
| - between one & five)
--------------------------------
s$(N,2) |This must always be
|initialised to CHR$(1)
--------------------------------
s$(N,3) |CHR$ (the number of
|frames between
|successive movements)
--------------------------------
s$(N,4) |CHR$ (the figure's Y
|coordinate)
--------------------------------
s$(N,5) |CHR$ (the figure's X
|coordinate)
--------------------------------
s$(N,6) |CHR$ (the figure's
|vertical displacement
|each time it moves)
--------------------------------
s$(N,7) |CHR$( the figure's
|horizontal displacement
|each time it moves)
--------------------------------
s$(N,8) |This must be set last
|of all, and must be any
|character whose code is
|greater than 64
--------------------------------
!2.......^.........^.........^.........^.........^.........^....
In the table above, it must be noted that 'N' is used to repre-
sent one of the strings in s$ - the number is arbitrary.
!1.......^.........^.........^.........^........
!B
moving and deactivate. Element s$(N,8) will
automatically reset to CHR$(0). You can test for
this occurrence in a Basic program.
!0.......^.........^.........^..
A TIMELY INTERRUPTION
!1.......^.........^.........^.........^........
OK, it's tea-break time! Arm yourself with a
cuppa and I'll explain how it all works.
The machine code is an interrupt routine. This
means that the program runs itself automatically
50 times a second. Each time it runs it checks
out the array s$ and shuffles sprites around the
screen accordingly. The basic instruction
"RANDOMIZE USR on" simply activates this
interrupt procedure, whereas "RANDOMIZE USR off"
deactivates it. Interrupt procedures are quite
clever; however, it's very easy to muck things
up and just a tiny little bug will spell total
disaster and blast the poor Speccy into
oblivion. This is true simple because the
program runs itself once for every new TV frame,
whether you want it to or not.
Take a peek at the basic program that's lying
around in this article. It manages to do in just
a few statements what would otherwise have been
quite a complicated program; it produces a
figure which bounces around the screen. The
first seven lines just initialise the array, s$,
and line 80 starts things moving. Line 90 is the
one to think about - it looks like an infinite
loop, but in fact it's not; it's just waiting
until the figure hits an edge. If you break out
of the program at any time you'll notice that
the figure will keep moving even while you type
a command, until it hits a wall (when it will
stop). At this point, you should type "RANDOMIZE
USR off" before you do anything else.
Well, that's it for this issue. I'm just going
off to stick my head in a bucket of inspiration
- hopefully in time for me to produce yet more
gems next month. See you then.
!2.......^.........^.........^.........^.........^.........^....
!B
--------------------------------.-------------------------------
10 DIM s$(1,8) Dimensions the array, s$
--------------------------------.-------------------------------
20 LET on=33013 Initialise the variables
30 LET off=33020
--------------------------------.-------------------------------
40 FOR j=1 TO 8 Read the data in line 160
50 READ a
60 LET s$(1,j)=CHR$ a
70 NEXT j
--------------------------------.-------------------------------
80 RANDOMIZE USR on Switches on the sprite facility
--------------------------------.-------------------------------
90 IF s$(1,8)="A" THEN GO TO Waits until a sprite hits the
90 edge of the screen
--------------------------------.-------------------------------
100 LET y=CODE s$(1,4) 'y' is the Y coordinate of the
sprite
--------------------------------.-------------------------------
110 LET x=CODE s$(1,5) 'x' is the X coordinate of the
sprite
--------------------------------.-------------------------------
120 IF y=0 OR y=22 THEN LET s$ Reverses the Y movement of
(1,6)=CHR$ (256-CODE s$(1,6)): B the sprite if necessary
EEP .03,24
--------------------------------.-------------------------------
130 IF x=0 OR x=30 THEN LET s$ Reverses the X movement of
(1,7)=CHR$ (256-CODE s$(1,7)): B the sprite if necessary
EEP .03,12
--------------------------------.-------------------------------
140 LET s$(1,8)="A" Reactivates the sprite
--------------------------------.-------------------------------
150 GO TO 90 A loop to send the action back
to line 90.
--------------------------------.-------------------------------
160 DATA 1,1,2,10,5,255,1,65 Contains the data for s$
--------------------------------.-------------------------------
The Basic program to get things moving on-screen - type it in
and see ...
!B
Machine code Assembler Comments
---------.---------.------------------.-------------------------
ORG 80F5
---------.---------.------------------.-------------------------
3E80 ON LD A,#80
ED47 LD I,A I:=80
ED5E IM 2 Activate interrupt routine
C9 RET
---------.---------.------------------.-------------------------
ED46 OFF IM 0 Deactivate routine
C9 RET
---------.---------.------------------.-------------------------
0181 IADDR DEFW 8101 Direct interrupt control
to address 8101
---------.---------.------------------.-------------------------
F5 SPRITES PUSH AF
C5 PUSH BC
D5 PUSH DE
E5 PUSH HL
DDE5 PUSH IX Stack all registers used
by the routine
DD2A4B5C LD IX,(VARS) Point IX to array s$
DD7E00 LD A,(IX+#00)
FED3 CP #D3
200F JR NZ,EXIT Jump if first variable is
not array s$
DD4604 LD B,(IX+#04) B:=1st dimension of array
(number of sprites)
---------.---------.------------------.-------------------------
C5 SP_LOOP PUSH BC Stack this number
010800 LD BC,#0008
DD09 ADD IX,BC Point IX to start of next
sprite(next array element)
CD7181 CALL NXT_SPRT Treat next sprite
C1 POP BC B:=remaining number of
sprites to treat
10F4 DJNZ SP_LOOP
---------.---------.------------------.-------------------------
DDE1 EXIT POP IX
E1 POP HL
D1 POP DE
C1 POP BC
F1 POP AF Restore all registers
FF RST #38 Carry out normal
interrupt procedures
C9 RET
---------.---------.------------------.-------------------------
CB0C LINE RRC H
CB0C RRC H
CB0C RRC H HL:=coded print position
011F00 LD BC,#001F
09 ADD HL,BC Move print position one
square down and one left
CB04 RLC H
CB04 RLC H
CB04 RLC H HL:=correct print position
C9 RET
---------.---------.------------------.-------------------------
CD4081 WIPE CALL H_WIPE Erase top half of sprite
CD2981 CALL LINE Point HL to bottom half of
sprite
---------.---------.------------------.-------------------------
CD4481 H_WIPE CALL Q_WIPE Erase one square of sprite
23 INC HL Point HL to remaining square
---------.---------.------------------.-------------------------
E5 Q_WIPE PUSH HL
0608 LD B,#08 B:=Number of rows per
square
---------.---------.------------------.-------------------------
3600 WP_LOOP LD (HL),#00 Erase next row
24 INC H Point HL to next row
10FB DJNZ WP_LOOP
E1 POP HL
C9 RET
---------.---------.------------------.-------------------------
AF TEST XOR A A:=00
CD5581 CALL H_TEST Test upper half of sprite
position
CD2981 CALL LINE Point HL to lower half
---------.---------.------------------.-------------------------
CD5981 H_TEST CALL Q_TEST Test one square of sprite
position
23 INC HL Point HL to remaining square
---------.---------.------------------.-------------------------
E5 Q_TEST PUSH HL
0608 LD B,#08
---------.---------.------------------.-------------------------
B6 TS_LOOP OR (HL) If any pixel is set then A
becomes non-zero
24 INC H HL points to next row
10FC DJNZ TS_LOOP
E1 POP HL
C9 RET
---------.---------.------------------.-------------------------
78 FIND_ADDR LD A,B This subroutine computes
E618 AND #18 in HL the print pos of the
F640 OR #40 square (on-screen) which
67 LD H,A has PRINT-AT coords given
78 LD A,B by registers B,C
0F RRCA
0F RRCA
0F RRCA
E6E0 AND #E0
B1 OR C
6F LD L,A
C9 RET
---------.---------.------------------.-------------------------
DD7E07 NXT_SPRT LD A,(IX+#07) A:=activation flag
FE40 CP #40
D8 RET C Return if sprite inactive
DD3501 DEC (IX+#01) Count frames between
movements
C0 RET NZ Return if the sprite does
not require moving
DD7E02 LD A,(IX+#02) A:=frame interval between
movements
DD7701 LD (IX+#01),A Re-initialise frame count
DD4603 LD B,(IX+#03) B:=y coordinate
DD4E04 LD C,(IX+#04) C:=x coordinate
CD6281 CALL FIND_ADDR HL:=print pos of sprite
CD3A81 CALL WIPE Erase sprite
DD7E03 LD A,(IX+#03) A:=y coordinate
DD8605 ADD A,(IX+#05) A:=intended y coordinate
FE17 CP #17
301F JR NC,NS_EXIT Jump if intended y coord
out of range
47 LD B,A B:=intended y coordinate
DD7E04 LD A,(IX+#04) A:=x coordinate
DD8606 ADD A,(IX+#06) A:=intended x coordinate
FE1F CP #1F
3014 JR NC,NS_EXIT Jump if intended x coord
out of range
4F LD C,A C:=intended x coordinate
---------.---------.------------------.-------------------------
C5 PUSH BC
CD6281 CALL FIND_ADDR HL:=intended print pos
CD4E81 CALL TEST Test for collision
C1 POP BC BC:=intended coordinates
A7 AND A
2008 JR NZ,NS_EXIT Jump if sprite has hit
something
DD7003 LD (IX+#03),B Store new y coordinate
DD7104 LD (IX+#04),C Store new x coordinate
180A JR NS_DRAW
---------.---------.------------------.-------------------------
DD360700 NS_EXIT LD (IX+#07),#00 Deactivate sprite
DD4603 LD B,(IX+#03) B:=old y coordinate
DD4E04 LD C,(IX+#04) C:=old x coordinate
---------.---------.------------------.-------------------------
DD6E00 NS_DRAW LD L,(IX+#00) L:=sprite type number
2D DEC L L now in range 0 to 4
2600 LD H,#00 HL now in range 0 to 4
29 ADD HL,HL
29 ADD HL,HL
29 ADD HL,HL
29 ADD HL,HL
29 ADD HL,HL Multiply by 32d
ED5B7B5C LD DE,(UDG) Point DE to graphic A
19 ADD HL,DE Point HL to required
sprite graphics
E5 PUSH HL
CD6281 CALL FIND_ADDR HL:=print pos of sprite
D1 POP DE DE:=address of pixel
information
---------.---------.------------------.-------------------------
CDDB81 DRAW CALL H_DRAW Draw upper half of sprite
CD2981 CALL LINE Point HL to lower half
---------.---------.------------------.-------------------------
CDDF81 H_DRAW CALL Q_DRAW Draw next square of sprite
23 INC HL Point HL to next square
---------.---------.------------------.-------------------------
E5 Q_DRAW PUSH HL
0608 LD B,#08
---------.---------.------------------.-------------------------
1A DR_LOOP LD A,(DE)
77 LD (HL),A Print next row
13 INC DE
24 INC H Point HL to next row
10FA DJNZ DR_LOOP
E1 POP HL
C9 RET
---------.---------.------------------.-------------------------
!1.......^.........^.........^.........^........
!B
--
from Your Spectrum #10 (Dec/Jan.1984/85)
--
!$