sprites

new topic     » topic index » view thread      » older message » newer message

Hi everybody,

Initially, when I was asked to explain what was going on under the bonnet of my
aliens!, I thought it was quite obvious. Then I thought a bit more about it
and prepared these notes. Line numbers, where given, refer to the attached
 little
demo. It is actually a sanitized copy of my first attempt, with a few comments
thrown in for a good measure.

All the usual disclaimers and customary lies apply here too: this is my first
venture into the sprite territory, and there is always a better/faster way of
doing anything, etc...

I shall concentrate on the mode 19, because it has such an easy, linear
arrangement of the video memory: a block of 64,000 bytes, one for every pixel on
the screen. It starts at #A0000 location, which corresponds to the top left hand
corner of your screen, and continues in left-to-right, line-by-line manner to
the bottom of your screen. I shall also assume, for simplicity, that in this
case the *whole* screen is our playfield.


The method consists of six basic steps:

   Step 1: Reserve two blocks of memory for your virtual screens, one as a
      working area, and the other as a permanent storage of the screen
      background. Lines 74 & 75.

   Step 2: Draw the background directly on the screen in any way you fancy.

   Step 3: Store the background in one of the virtual screens.
      Normally, it would be something like: mem_copy(s1,A,N)
      I short-circuited the step 2 and 3 in the demo, drawing the
      background directly into the storage memory: Lines 78 to 82.


The next three steps will be repeated over and over again in the main action
loop (lines 114 to 118), which usually contains some other things like timing,
checking of input, etc. Here they are gathered in the frame() routine, lines 23
to 54.

   Step 4: Prepare your working virtual screen first by copying the background
      into it, line 26: mem_copy(s2,s1,N)

   Step 5: The tricky bit: update your sprites and draw them into the virtual
      working screen, lines 28 to 52.

   Step 6: Display the updated working screen by copying it to the video memory,
      line 53: mem_copy(A,s2,N)


In real life, of course, you will need more than two virtual screens to store
temporary backgrounds for your Intro, Game Over screens,etc.

The step 5, especially its second part, drawing of sprites, is most critical in
terms of speed. Hollow and/or complicated sprites lead to short, broken poke
sequences and are expensive. A bit of care and effort with things like sprite
pre-processing, or taking advantage of symmetries (as in the following demo),
can make a huge difference!

That's it!  Jiri

-- snip ------------------------------------------------------------------------

-- sprite.ex : sprite experiments
-- jiri babor
-- j.babor at gns.cri.nz
-- version 1.00   97-03-29

include graphics.e
include machine.e
include get.e

constant
   A=#A0000,      -- start of video memory
   N=64000,       -- screen size
   ns=20,         -- number of sprites
   x=1,  y=2,     -- sprite labels
   xv=3, yv=4,    -- sprite labels
   h=5,           -- sprite half height
   w=15           -- sprite width

atom dt,s1,s2,t
integer count,junk
sequence c,sdata,pal,s,S,ss

procedure frame()
   sequence s
   integer m,n
   mem_copy(s2,s1,N)    -- fresh copy of background into working screen
   -- update sprites
   for i=1 to ns do
      if sdata[i][x]+sdata[i][xv]<1 or sdata[i][x]+sdata[i][xv]+w>320 then
         sdata[i][xv]=-sdata[i][xv]
      end if
      if sdata[i][y]+sdata[i][yv]<1 or sdata[i][y]+sdata[i][yv]+h+h>200 then
         sdata[i][yv]=-sdata[i][yv]
      end if
      sdata[i][x]=sdata[i][x]+sdata[i][xv]
      sdata[i][y]=sdata[i][y]+sdata[i][yv]
      -- write sprites to virtual screen
      for r=1 to h do
         m=1   n=1
         while m<w do
            if ss[i][r][m]  then exit
            else m=m+1 end if
         end while
         n=m
         while n<w do
            if ss[i][r][n+1]  then n=n+1
            else exit end if
         end while
         poke(s2+(sdata[i][y]+r-1)*320+sdata[i][x]+m-1, ss[i][r][m..n])
         poke(s2+(sdata[i][y]+10-r)*320+sdata[i][x]+m-1, ss[i][r][m..n])
      end for
   end for
   mem_copy(A,s2,N)     -- display: copy virtual screen s2 into video memory
end procedure


-- main ------------------------------------------------------------------------

junk = graphics_mode(19)

-- set palette
pal=repeat({0,0,0},256)
for i=0 to 16 do
   pal[i+1]=palette(i,{0,0,0})
end for
for i=0 to 63 do
   pal[i+65]={32+floor(i/2),i,i}
   pal[i+129]={i,32+floor(i/2),i}
   pal[i+193]={i,i,32+floor(i/2)}
end for
all_palette(pal)

-- allocate memory for virtual screens
s1=allocate(N)
s2=allocate(N)

-- set background
for i=0 to 199 do
   for j=0 to 319 do
      poke(s1+i*320+j,255-floor(i*0.25))
   end for
end for

-- set sprite data
sdata=repeat(repeat(0,4),ns)
for i=1 to ns do
   sdata[i][x]=rand(319-w)
   sdata[i][y]=rand(199-h-h)
   sdata[i][xv]=6-rand(11)
   sdata[i][yv]=5-rand(9)
end for

-- generate sprite images
S={{0,0,0,0,1,1,1,1,1,1,1,0,0,0,0},
   {0,0,1,1,1,1,1,1,1,1,1,1,1,0,0},
   {0,1,1,1,2,2,2,2,2,2,2,1,1,1,0},
   {1,1,1,2,2,2,2,2,2,2,2,2,1,1,1},
   {1,1,1,2,2,2,2,2,2,2,2,2,1,1,1}}

ss={}
for i=1 to ns do
   s=S
   c={64*rand(3)+rand(40),64*rand(3)+rand(40)}   -- random color
   for j=1 to h do
      for k=1 to w do
         if s[j][k] then s[j][k]=c[s[j][k]]+k end if
      end for
   end for
   ss=append(ss,s)
end for

count=0
t=time()
while 1 do
   frame()
   if get_key()!=-1 then exit end if
   count=count+1
end while
dt=time()-t

junk = graphics_mode(-1)
printf(1,"%5.2f f.p.s.\n",count/dt)

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu