Re: Clipping & Scrolling
- Posted by Derek Parnell <ddparnell at bigpond.com> May 06, 2007
- 641 views
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