Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

I did something stupid and it'll take forever to change so...

Status
Not open for further replies.

qbasicking

Programmer
Aug 19, 2001
628
US
I was putting some graphics onto the background of my GUI, but now I want to animate it. Its a dog, I want it to tilt its head and wag its tail. Heres the problem: I know how to tilt an object I made in DRAW but I made this thing using LINE and PSET statements, does anybody know I way that I can take a irregular shaped image (its head) and tilt it?
 
With no knowledge of the methods you are using (I guess it really doesn't matter), I can only suggest the "easy" way to display animations. Use the model adopted by every animated media since the first Steamboat Willie cartoon: break the animation into a series of "still" images and show them in sequence. The name of the man who discovered this effect is lost in history but the effect is pervasive... when the eye is presented with a series of images in sequence, the mind interprets the series of "still" images as motion.

Determine the length of the animation and divide this by the number of frames required to show the animation in its entirety. This will give you the length of the delay between animation frames.

In short... you need to create one or more routines that will run at specific intervals. Let's say you want to show a dog tilting its head and wagging its tail.... Determine the starting positions of the head and the tail and draw them (are you using DRAW, LINE, PSET... are you showing a GIF or BMP using a library function?). Determine the next position (or frame), and the next, and etc. until the animation is complete.

Timing is important. System speeds vary. You need to find a common ground in order to display your animation the same way from system to system. A FOR/NEXT or DO/LOOP won't work very well. Borrowing from my experience in sensory psychology, the term "critical flicker fusion" comes to mind. This is the timing threshold where two different images appear to be the same image (not a problem on faster systems LOL).

P.S. Post some code.

VCA.gif
 
the code for the dog is complicated, it acts like the Word 2000 office assistant, and the drawing process is too long to post, so here is a code that represents the dog with blocks and circles.

LINE (400,300)-(435,345),14,B 'lets say this is its head
LINE (440,345)-(500,400),14
LINE (500,400)-(415,400),14
LINE (415,400)-(415,300),14
LINE (500,400)-(515,400),14 'these next two will be its tail
LINE (515,400)-(485,390),14

There is no way to tilt its head without using the "Steamboat Willie" idea while preserving the background?

if I end up animating it this way how should I make the pause between frames? I was thinking of using SLEEP or Pn, would this work? I need the time between frames to be similar for different systems (I use both a 486 and a Pentium 4)
 
Here's a QB tutorial I came across about a year or two ago. It's in reference to masking sprites. With a little ingenuity you can most likely adapt it to your situation.


'---Starts here:
'
' "Masking" sprites
'
' Sprites In QBasic, and how to mask them.
'
' By: TF Software
'
' Email: tf_software@geocities.com
'
' Web site:
' http: //members.aol.com/TFSoft/
'
' Sprites are graphical images. Masking is a technique that will
' preserve the background when you place a sprite on the screen.
'
' To start out let me say that a sprite is an array. You DIM the array
' just like you would any other array. Finding the neccessary size of the
' array is the tricky part. The size of a graphics array is NOT the same
' in any screen mode. Also a sprite you GET in one screen mode may not be
' compatible with another screen mode.
'
' A sprite is rectangle in shape. To create a sprite you can draw an
' image on the screen and extract it using GET. What GET does is copies
' a rectangle section of the screen into an array. It is then saved into
' that array and can be placed back on the screen as many times as you want.
' It is kind of like copying and pasting. For example: In MS Paint you can
' use the copy tool to copy a rectangle section of the screen and then paste
' it back on the screen a number of times.
'
' Before you GET an array from off the screen you must frist set its
' dimensions using the DIM statement. A sprites size is NOT just the amount
' of pixels in the array. There is a formula used to find the exact size of
' an array. Things are explained in more detail in the program below:
'
'
RANDOMIZE TIMER 'Sets random seed.
SCREEN 7, 0, 1, 0: CLS 'To learn about screen pages and PCOPY see
'my page flipping program which is available
'at my web site.

'-----Make Background-----
BgC% = 1 'This creates the background.
FOR BgX% = 0 TO 319 STEP 80 'It is on screen page 1.
BgC% = BgC% + 1
LINE (BgX%, 0)-(BgX% + 79, 199), BgC%, BF
NEXT
'-----End Make Background-----

SCREEN 7, 0, 2, 0: CLS

'-----Make Sprite-----
FOR RP% = 1 TO 80 'This makes 80 random pixels which we will
Rx% = INT(RND * 20) 'use as our sprite.
Ry% = INT(RND * 20)
PSET (Rx%, Ry%), 1
NEXT
'-----End Make Sprite-----
'-----Make Mask-----
FOR Sx% = 0 TO 19 ' What this does is creates a mask for our
FOR Sy% = 0 TO 19 'sprite. What it does is scans the area where
Sc% = POINT(Sx%, Sy%) 'we put our pixels. When it scans it, if
IF Sc% = 0 THEN 'there is no pixel it will draw a pixel where
PSET (Sx%, Sy% + 100), 15 'our mask will be. If there is a pixel it wont
END IF 'draw a pixel where our mask will be.
NEXT ' Basicly it just draws a pixel in every
NEXT 'spot we want the background to show through.
'-----End Make Mask-----

'-----Display some info-----
LOCATE 1, 6
PRINT &quot;<- Here is our sprite.&quot;
LOCATE 2, 8
PRINT &quot;The background will show through&quot;
LOCATE 3, 8
PRINT &quot;the black area.&quot;

LOCATE 14, 6
PRINT &quot;<- Here is our mask.&quot;
LOCATE 15, 8
PRINT &quot;We must make this to have the&quot;
LOCATE 16, 8
PRINT &quot;background show through. Every&quot;
LOCATE 17, 8
PRINT &quot;white pixel is where it shows&quot;
LOCATE 18, 8
PRINT &quot;through.&quot;
PCOPY 2, 0
DO: LOOP UNTIL INKEY$ <> &quot;&quot;
'-----End Display some info-----

' Now lets get to the part of creating the array for the sprite. There is
' a formula to find the size of the array. Here it is:

'4 + INT(((x2 - x1 + 1) * (bits-per-pixel-per-plane) + 7)/8)* planes * ((y2 - y1) + 1)

' To find the Bits-Per-Pixel and the number of Planes, please look in
' your QBasic section. I have QBasic 4.5 and it is in the details of
' the GET (Graphics) part.
'
'
' Our sprite is from (0, 0)-(19, 19). Here is how we would find its size:

SpriteSize% = 4 + INT(((19 - 0 + 1) * (1) + 7) / 8) * 4 * ((19 - 0) + 1)

' Since our sprite is LONG we then divide the Size by 4. If it was integer
' we would divide it by 2. This information is also in the help section.

SpriteSize% = SpriteSize% / 4

' We are going to hold the sprite and its mask in one array so we need
' to multiply the size by 2. Also we are going to have the array start
' at element 0 of the array instead of 1. Therefore we must subtract the
' the size by 1.

TotalSize% = (SpriteSize% * 2) - 1

' Now we have the size so lets DIM it:

DIM Sprite(TotalSize%) AS LONG

' Now that our sprite is DIMmed lets GET it.

'Our sprite is from (0, 0)-(19, 19)
'Incase you don't know that is: (X1, Y1)-(X2, Y2)
GET (0, 0)-(19, 19), Sprite(0) 'As I said before this sprite starts at
'element 0 of the array.
'The size of the sprite takes up (SpriteSize - 1). This means we
'can still fit the mask in the array. So it will start at SpriteSize
'in the array.

'Our mask is from (0, 100)-(19, 119)
GET (0, 100)-(19, 119), Sprite(SpriteSize%) 'The mask will start at
'the SpriteSize in the array.

CONST SpritePict% = 0 'The location of the sprite in the array.
CONST SpriteMask% = 61 'The location of the mask in the array.
CONST SpriteWidth% = 20 'Width
CONST SpriteHeight% = 20 'Height


SpriteX% = 160 'Sets the X location
SpriteY% = 100 'Sets the Y location
SpriteAddX% = 1 'Amount added to X each frame.
SpriteAddY% = 1 'Amount added to Y each frame.

DO
PCOPY 1, 2

'-----Move Sprite-----
SpriteX% = SpriteX% + SpriteAddX%
SpriteY% = SpriteY% + SpriteAddY%
'-----End Move Sprite-----

'-----Make sprite bounce off wall-----
IF SpriteX% < 0 THEN SpriteX% = 0: SpriteAddX% = -SpriteAddX%
IF SpriteY% < 0 THEN SpriteY% = 0: SpriteAddY% = -SpriteAddY%
IF SpriteX% > 319 - SpriteWidth THEN SpriteX% = 319 - SpriteWidth: SpriteAddX% = -SpriteAddX%
IF SpriteY% > 199 - SpriteHeight THEN SpriteY% = 199 - SpriteHeight: SpriteAddY% = -SpriteAddY%
'-----End Make sprite bounce off wall-----

'Now then, to actually mask the image we must do two PUTs.
'We must first PUT the mask using the AND actionverb.
'Then we will PUT the sprite over the mask using the XOR action verb.

PUT (SpriteX%, SpriteY%), Sprite(SpriteMask), AND
PUT (SpriteX%, SpriteY%), Sprite(SpritePict), XOR

PCOPY 2, 0
LOOP UNTIL INKEY$ <> &quot;&quot;
END

'---Ends here.

Hopefully this helps some.
--MiggyD It's better to have two heads to solve a problem from different angles than to have tunnel vision to a dead end.
 
Using sprites might be a good option. Another way would be to GET and PUT larger areas of the screen.

Let's start with the dog's tail (the head will be a bit more complex).
[tt]
SCREEN 12
'
[/tt]Set up an area of the screen to save[tt]
Tailx1 = 485
Tailx2 = 515
Taily1 = 350
Taily2 = 420
EndTail = 400
'
[/tt]Get the size of an array big enough to hold the tail
' For screen 12....[tt]
BitsPerPixelPerPlane = 1
Planes = 4
Bytes = 4 + INT(((Tailx2 - Tailx1 + 1) * (BitsPerPixelPerPlane) + 7) / 8) * Planes * ((Taily2 - Taily1) + 1)
REDIM TailArray&(Bytes)
LINE (400, 300)-(435, 345), 14, B'
[/tt]lets say this is its head[tt]
LINE (440, 345)-(500, 400), 14
LINE (500, 400)-(415, 400), 14
LINE (415, 400)-(415, 300), 14
LINE (500, 400)-(515, 400), 14 '
[/tt]these next two will be its tail[tt]
LINE (515, 400)-(485, 390), 14
'
[/tt]Get the portion of the screen holding the tail[tt]
GET (Tailx1, Taily1)-(Tailx2, Taily2), TailArray&
TailInc = -2
DO
'
[/tt]Restore the tail, erasing the changes[tt]
PUT (Tailx1, Taily1), TailArray&, XOR
LINE (485, 390)-(515, EndTail), 14
LINE (485, 400)-(515, EndTail), 14
' [tt]Get the tail again[/tt]
GET (Tailx1, Taily1)-(Tailx2, Taily2), TailArray&
EndTail = EndTail + TailInc
IF EndTail < 350 THEN
EndTail = 350
TailInc = 2
END IF
IF EndTail > 420 THEN
EndTail = 420
TailInc = -2
END IF
LOOP
[/tt]

Just an idea.... You might combine this with MiggyD's sprite approach.

Again, you will have to address the problem of moving the tail at specific intervals. The results of doing this in a DO/LOOP will be inconsistent from system to system.

Hope this gives to some more ideas....
VCA.gif
 
Heres the answer to all ur problems. The idea is simple. U want to make an animated dog. The dog occupies a rectangle on the screen. Considering it is an assistant. Lets say it is not bigger than 150 in width 250 in height. As suggested by the above replies put the animated dog in a sequence of frames. Draw all the movements of ur assistant in some software and save it as a .gif file. Then load it using some utility in qb( u get many on the internet ) and BSAVE the file as a .BSV. After this u can BLOAD the files in a sequence and show them on the screen. What is crucial here that u must take care that when the mouse enters the area occupied by the dog u must hide the mouse pointer also if i am correct then when u use BLOAD then the image will create BLACK corners that is the image will destroy the background of the screen completely so u have to take care that u dont keep the back ground of the dog something having patterns or just put a box around the dog as if the dog is enclosed in that box. Also no window can extend on to the dog!

If u want the smooth movements of the dog then u must compromise the background. if u want the background of the dog then u must compromise the movements. You cant have everything! (unless u have Video Pages which is possible in Screen 7 but then again u will have to compromise on the resolution and u have only 16 colors.)
 
Just so that you know, you are not limited to mode 7. I've used mode 12 in some experiments to further my understanding of the above and the above code works fine.

Like I said, with some refinements, you can make it work for your situation.

Good luck,
--MiggyD It's better to have two heads to solve a problem from different angles than to have tunnel vision to a dead end.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top