The QBNews Page 16 Volume 2, Number 3 September 15, 1991 Manipulating Sprites in Screen 13 by Fred Sexton Jr. In January I bought my first real computer(386SX).I don't count the TI-99 that's still in the closet.After a month or so of GWBASIC I bought QuickBasic 4.5 .I was instantly hooked,and have spent alot of my spare time coding. I wanted to make a few animated educational games for my kids.I soon found that animation would require alot of "sprites".I needed an easy to use drawing program to create sprites in my favorite mode SCREEN 13 (320x200x256).So I set out to create one.I ended up with "THE SPRITE MASTER" (so named because I finally had mastered them). Along the way I learned alot about SCREEN 13.I decided to pass along some of it. NOTE:I always use DEFINT A-Z.So,all arrays discussed here are integer arrays. The easiest way to store an image is with Q.B.'s GET statement. To find the minimum size to dimension an array,I set up a loop getting a 10w X 10h image decreasing the number of elements each time until an error occurred.I don't care for the formula in the book.The result was that a 10w X 10h image required 52 elements or, DIM ary(51).The elements are numbered starting with zero by default. So,always remember to DIM an array with a value that is one less than you really want.Knowing that the colors are in the range of 0 - 255 we can determine that each pixel requires 8 bits (1byte) to store it's color value (255 = 11111111 B).So,in a 10w X 10h image there are 100 bytes or 50 words.We can conclude that GET needs the number of words in the image plus two additional words. Therefore : elements = ((width * height) + 1) \ 2 + 2 (the "+ 1" takes care of odd values) To find out what the two extra words are for,we'll GET a couple of different size images from a blank screen. Then we'll compare the values in the resulting arrays. With image1 = 10w X 10h and image2 = 20w X 5h: ary1(0) = 80 ary2(0) = 160 ary1(1) = 10 ary2(1) = 5 ary1(2-51) = 0 ary2(2-51) = 0 Now we know the first two elements are used by GET to store the image size information.The first element is the image width in bits. Remember we said 1 pixel = 8 bits.To find pixel width just divide by 8.The second element is the height. To determine the rest of the pattern let's set a few points and get the image. FOR t = 0 TO 3 PSET(t , 0), t + 1 PSET(t , 1), t + 5 NEXT GET (0 , 0) - (3 , 1), ary We already know what's in the first two elements so let's look at the rest. The QBNews Page 17 Volume 2, Number 3 September 15, 1991 ary(2) = 513 on the byte level low byte = 1 => value of the pixel (0,0) high byte = 2 => value of the pixel (1,0) ary(3) = 1027 on the byte level low byte = 3 => value of the pixel (2,0) high byte = 4 => value of the pixel (3,0) ary(4) = 1541 on the byte level low byte = 5 => value of the pixel (0,1) high byte = 6 => value of the pixel (1,1) ary(5) = 2055 on the byte level low byte = 7 => value of the pixel (2,1) high byte = 8 => value of the pixel (3,1) This was a 4w X 2h image.Starting at the low byte the third element,the next four bytes correspond to the first row of four pixels.The next four bytes correspond to the second row of four pixels.Analysis of other images will show the same pattern.Thus we can conclude for an image with a width of W : Starting with the low byte of the third element,the first W # of bytes will correspond to the pixels in the first row and the second W # of bytes will correspond to the pixels in the second row and so on for each row. Once the pattern is known manipulating the arrays can accomplish many things.Here are a few examples. Change a color: To change a color in an image array we would search the array at the byte level for the source color.When it is found we will replace it with the new color. In pseudo code: FOR t = 0 TO bytes - 1 (because we start with zero) IF PEEK (t + start offset) = oldcolor THEN POKE t + start offset, newcolor END IF NEXT Mirror an image: To create a mirror image we need to reverse the order of each row of pixels.We know the pixels are stored in groups corresponding to the width of the image.So,in a 10w X 10h image starting with the low byte The QBNews Page 18 Volume 2, Number 3 September 15, 1991 of the third element the first byte would be the first pixel in the first row and the tenth byte would be the last pixel in the first row.To make it easier let's dimension a second array the same size as the first.Then after making the size information the same we can just copy the bytes from one to the other in the proper order (first to tenth,second to ninth,etc.). In pseudo code: aofs=offset of first pixel in first row of source bofs=offset of last pixel in first row of target FOR first row TO last row FOR first pixel TO last pixel PEEK at aofs + increasing pixel number (0 to start) POKE to bofs decrease bofs to next lower pixel NEXT source pixel aofs=offset of first pixel in next row of source bofs=offset of last pixel in next row of target NEXT row Superimpose an image: To superimpose an image ie. put it front of or behind existing images without destroying them or messing the colors up.Again it is easiest to use a second array of the same size.First we get the area of the screen where we are planning to put the image.Then to put in front we take all non-zero (background) pixels from the first array and put them into the second array.To put behind we only poke pixels from the source array there are zeros in the second array. The result can be PUT with PSET and we won't end up with the blacked out area we normally have. In pseudo code: IN FRONT: GET target area into work array FOR first pixel in first row TO last pixel in last row PEEK at a source pixel IF pixel is not zero THEN POKE pixel into work array NEXT PUT work array PSET BEHIND: GET target area into work array FOR first pixel in first row TO last pixel in last row PEEK at a work pixel IF pixel is zero THEN PEEK at same pixel in source POKE pixel into work array END IF The QBNews Page 19 Volume 2, Number 3 September 15, 1991 NEXT PUT work array PSET These are just a few of many possibilities.(The superimpose routine could be easily modified to allow partial PUTS.) The documented source for each routine discussed is in G13UTIL.BAS . I recently started learning MASM and have converted these to faster versions.I plan to release a shareware library of fast routines for SCREEN 13,as well as a shareware version of "THE SPRITE MASTER". I plan to Upload them to COMPUSERVE and AMERICA ON LINE. Comments and/or suggestions would be appreciated. [EDITOR'S NOTE] All code for this article can be found in SPRITE.ZIP ********************************************************************* Fred Sexton Jr. is an electrician for Ford Motor Co. He works extensively with Allen Bradley Programmable controllers and Kuka robotics.He received electrical training in the NAVY as an electronics technician / reactor operator. He can be reached on Compuserve at 70253,163 and on A.O.L. at 7408. *********************************************************************