Re: Clipping & Scrolling

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

Andy wrote:
> 
> How do you do clipping and scrolling using the win32lib. By clipping, I mean
> so the sprite dosen't move off the screen and with scrolling to scroll it
> left,
> right up, or down. I am confused on how to do these. Any help is appericated.

The simple answer is that you set their X/Y position to where you want them to
be.

Have look at the demo program called "WordCatcher" for example code techniques.

But in more detail ...

Firstly, do all your drawing onto a Pixmap control. If you're smart, you only
have to redraw the section that has changed due to your animation rather than the
whole screen. Then whenever you get a Paint event, copy the portion of the PixMap
to the Window that needs updating.

Let's assume you have a timer event that is going to fire every 10th of a
second. In the routine that handles that event you would ...

 * redraw the region where the sprite currently is - but without the sprite.
 * calculate the new location of the sprite
 * draw the sprite in the new location.
(I'm assuming that the sprite is the topmost object for this exercise).

Ok, so let's assume the current location for the sprite is bounded by the box
[45,101 - 54,109], a 10x10 pixel sprite and that its the only one. We now redraw
the background in that region. If the background is a fixed one such as a bitmap
or solid color this is easy. From a bitmap you just BitBlt to copy the
corresponding square to the pixmap, from a solid color you just draw filled
rectangle there. If the back ground is more complex it can still be done of
course, but you need to do more work ... so it is always a good idea to have the
complete background rendered in a different pixmap offscreen so you can quickly
itBlt parts of it for the current scrren.

Calculate the new sprite location. This of course depends on how you have
defined the way the sprite can move. Let's assume that the current speed is 10
pixels/sec in the X direction and -15 pixels/sec in the Y direction. As our
routine fires off 10 times per second the calcs are ...

  atom OldX  -- stores fractional pixels
  atom OldY
  atom NewX
  atom NewY

  NewX = OldX + XSpeed/10    [45.0 + (10/10) = 46.0]
  NewY = OldY + YSpeed/10    [101.0 + (-15/10) = 99.5]

Check that the new 'box' is still in view and if not make adjustments as
required.

  if NewX < LeftHandEdge then
     NewX = LeftHandEdge
  elsif NewX+SpriteWidth > RightHandEdge
     NewX = RightHandEdge - SpriteWidth
  end if
  
  if NewY < TopEdge then
     NewY = TopEdge
  elsif NewY+SpriteHeight > BottomEdge
     NewY = BottomEdge - SpriteHeight
  end if

Depending on your game, you might need to do collision detection at this time
and adjust the coordinates appropriately.

Now draw the sprite (assuming there are some transparent bits) ...

  transBlt( myPixmap, floor(NewX), floor(NewY), MySprite )

  
Note, doing this will NOT cause the image on screen to change. This only changes
the mirror screen you are keeping in your pixmap. To force it to be made visible,
you need to tell Windows that the screen needs updating ...

The simplest way is to call ...
   repaintFG( mywindow ) 
but that cause the entire window to be refreshed. If you know exactly which
parts need to be updated you can target them specifically.

Assuming that our pixmap and window both have origins at [0,0] we could call
...

   repaintRect(myWindow, floor(min(OldX, NewX)),
                         floor(min(OldY, NewY)),
                         floor(max(OldX, NewX) + SpriteWidth),
                         floor(max(OldY, NewY) + SpriteHeight)
               )

Finally set things up for the next timer event.

   OldX = NewX
   OldY = NewY

Depending on your game, you might need to do adjustments to the sprite's speed
at this time.


Actually, still nothing will happen on your window yet. We need to do that in
the window's Paint handler.


In the Paint handler, you get passed the region on the window that needs
refreshing. All that is needed is to BitBlt the corresponding region in the
pixmap to the window.

  procedure Paint_VPWindow(integer self, integer event, sequence parms)
    bitBlt( self,     parms[1], parms[2], 
            myPixmap, parms[1], parms[2], 
            parms[3] - parms[1] + 1, 
            parms[4] - parms[2] + 1,  
            SRCCOPY )
  end procedure
  setHandler(myViewPortWindow, w32HPaint, routine_id("Paint_VPWindow"))


See, its simple :)

-- 
Derek Parnell
Melbourne, Australia
Skype name: derek.j.parnell

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

Search



Quick Links

User menu

Not signed in.

Misc Menu