Patterns and Blobs are two basic Wman objects that havent had the attention they deserve. A pattern is a (repeating) pattern of colours, but has no limits and so no shape. A blob defines a shape, but has no colour or pattern. Combining a pattern with a blob produces a visible object, aka a Sprite. (However, nowadays we can also have solid sprites, ie sprites consisting only of a pattern and no blob (aka mask).)
Here are some "fun facts" about these objects that I have collected over the years. Some of these you can find spread around in the various literature, others you would normally just have to figure out yourself. So I decided to put some of the core facts down in one place:
There is more, much more. For the excuciating detail you need the Qptr manual (at time of writing V6.5). A good and compact summary of the latest GD2 sprite formats can be found in the display_txt text file that comes with the SMSQ/E sources, in the extras directory. While there are other useful sources of information, these are the ones I always return to for reference.
BTW: Convention (not a strong concept in the anarchic QL world) suggests that blobs get the file extension _blb , and patterns _pat
Now to the program below: It demonstrates the colouring of a blob using a simple, programmed pattern (lines 124 - 158). In this example the pattern is created as a mode 64 object, as RGB colour coding is simple to manage. If the colour required were to come off the screen, the Channel Definition Block, or the Wman palette, it is simpler to use a Native colour pattern of the current display mode.
Note: The program below requires EasyPtr's ptrmen_cde to display the blob, or exchange WBLOB to Qptr's LBLOB.
Either supply your own blob or sprite or use the in-built one. The harness is not very sophisticated, so there is no guarantee that just any sprite or blob will display properly or not crash the program! Notice that the supplied blob, Snow, is a QL mode 4 sprite!
Similar routines to the ones below do the magic in QOMBI, that allow the card symbols be of any colour you choose.
10 rem Use built-in blob or load one 11 IF 0 THEN 12 rem You can find some blobs in the QOMBI dat directory 13 blb = LoadDat('win1_qmb_dat_s3_OF_blb'): ERT blb 14 ELSE 15 blb = Snow: rem Use built-in blob 16 END IF 17 : 18 ch = FOPEN('con') 19 sx% = PEEK_W(blb + 4): sy% = PEEK_W(blb + 6): rem Assumes origen = 0, 0 20 WINDOW#ch; sx% * 4.8, sy% * 2, 20, 20 21 BORDER#ch; 1, 2 22 PAPER#ch; 7: CLS#ch 23 : 24 gap% = 4.5 * sx% / 4 25 xp% = 10 26 yp% = (sy% * 2 - 3 * sy% / 2) 27 : 28 pat = MkPat64: rem Init 29 CHG_COL64 pat, 0: rem Set black 30 : 31 WBLOB#ch; xp%, yp%, blb, pat 32 xp% = xp% + gap% 33 : 34 CHG_COL64 pat, $FF0000: rem Red 35 WBLOB#ch; xp%, yp%, blb, pat 36 xp% = xp% + gap% 37 : 38 CHG_COL64 pat, $FF: rem Blue 39 WBLOB#ch; xp%, yp%, blb, pat 40 xp% = xp% + gap% 41 : 42 CHG_COL64 pat, $FF00: rem Green 43 WBLOB#ch; xp%, yp%, blb, pat 44 PAUSE#ch 45 QUIT 46 : 47 : 48 : 100 rem + ------------------------------------------------------------------------ + 102 rem |< MkPat64 >| 104 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 106 rem | Create RGB 16 X 1 colour pattern | 108 rem | | 110 rem | Creates the container for a RLE-compressed pattern. | 112 rem | Set or change the colour with CHG_COL64 | 114 rem + ------------------------------------------------------------------------ + 116 rem | V0.02, pjw, 2018 Dec 02 | 118 rem | V0.03, pjw, 2021 Nov 16, new name, streamlined code, no GLOBal variables | 120 rem + ------------------------------------------------------------------------ + 122 : 124 DEFine FuNction MkPat64 126 LOCal ad 128 ad = ALCHP(37): rem 24 + 8 + 5 130 : 132 rem Create sprite header 134 POKE ad, 2, 64, 0: rem GD2 mode 64 sprite.. 136 POKE ad + 3, %1000011: rem Pattern compressed, dont cache 138 POKE_W ad + 4, 16, 1, 0, 0: rem Size, origen 140 POKE_L ad + 12, 12, 0, 0: rem Offset to data 142 POKE$ ad + 24, 'RLE4': rem Compression header 144 POKE_L ad + 28, 64: rem Expanded data size 146 RETurn ad 148 END DEFine MkPat64 150 : 152 DEFine PROCedure CHG_COL64(adr, rgb) 154 POKE_L adr + 32, rgb 156 POKE adr + 32, CHR$(241): rem 257 - 16 158 END DEFine CHG_COL64 160 : 162 : 164 : 166 rem + ************************************************************************ + 168 rem *< Help routines and Data >* 170 rem + ************************************************************************ + 172 : 174 DEFine FuNction LoadDat(fnm$) 176 LOCal fl, ad 178 ad = FOP_IN(fnm$): IF ad < 0: RETurn ad 180 fl = FLEN(#ad): CLOSE#ad 182 ad = ALCHP(fl) 184 LBYTES fnm$, ad 186 RETurn ad 188 END DEFine LoadDat 190 : 192 : 194 DEFine FuNction Snow 196 LOCal ad 198 rem 57 x 48, mode 4, blob 200 : 202 ad = ALCHP(792) 204 : 206 POKE_W ad + 0, $100,$0: rem form, time/adaption 208 POKE_W ad + 4, $39,$30: rem x size, y size 210 POKE_W ad + 8, $0,$0: rem x origin, y origin 212 POKE_L ad + 12, 0 : rem pointer to colour pattern 214 POKE_L ad + 16, 8 : rem pointer to pattern mask 216 POKE_L ad + 20, 0 : rem pointer to next definition 218 : 220 POKE_W ad + 24, $0,$0,$0,$808,$0,$0,$0,$0 222 POKE_W ad + 40, $0,$0,$0,$7F7F,$0,$0,$0,$0 224 POKE_W ad + 56, $0,$0,$202,$3E3E,$2020,$0,$0,$0 226 POKE_W ad + 72, $0,$0,$606,$7E7E,$6060,$0,$0,$0 228 POKE_W ad + 88, $0,$0,$1F1F,$FFFF,$FCFC,$0,$0,$0 230 POKE_W ad + 104, $0,$0,$F0F,$FFFF,$F8F8,$0,$0,$0 232 POKE_W ad + 120, $0,$0,$1F1F,$FFFF,$FCFC,$0,$0,$0 234 POKE_W ad + 136, $0,$0,$303,$FFFF,$F0F0,$0,$0,$0 236 POKE_W ad + 152, $0,$2020,$303,$FFFF,$E0E0,$101,$0,$0 238 POKE_W ad + 168, $303,$FCFC,$1F1F,$FFFF,$FCFC,$F0F,$E0E0,$0 240 POKE_W ad + 184, $1111,$F8F8,$8F8F,$FFFF,$F8F8,$4747,$C4C4,$0 242 POKE_W ad + 200, $3333,$F9F9,$9F9F,$FFFF,$F8F8,$CFCF,$CCCC,$0 244 POKE_W ad + 216, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 246 POKE_W ad + 232, $7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 248 POKE_W ad + 248, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 250 POKE_W ad + 264, $1F1F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FEFE,$0 252 POKE_W ad + 280, $1F1F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FCFC,$0 254 POKE_W ad + 296, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 256 POKE_W ad + 312, $7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 258 POKE_W ad + 328, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 260 POKE_W ad + 344, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 262 POKE_W ad + 360, $1111,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$C4C4,$0 264 POKE_W ad + 376, $303,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$E0E0,$0 266 POKE_W ad + 392, $0,$7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$8080,$0 268 POKE_W ad + 408, $0,$3F3F,$FFFF,$FFFF,$FFFF,$FFFF,$0,$0 270 POKE_W ad + 424, $303,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$E0E0,$0 272 POKE_W ad + 440, $1111,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$C4C4,$0 274 POKE_W ad + 456, $3333,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$CCCC,$0 276 POKE_W ad + 472, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 278 POKE_W ad + 488, $7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 280 POKE_W ad + 504, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 282 POKE_W ad + 520, $1F1F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FEFE,$0 284 POKE_W ad + 536, $1F1F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FCFC,$0 286 POKE_W ad + 552, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 288 POKE_W ad + 568, $7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 290 POKE_W ad + 584, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 292 POKE_W ad + 600, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 294 POKE_W ad + 616, $1111,$F8F8,$8F8F,$FFFF,$F8F8,$4747,$C4C4,$0 296 POKE_W ad + 632, $303,$FCFC,$1F1F,$FFFF,$FCFC,$F0F,$E0E0,$0 298 POKE_W ad + 648, $0,$6060,$303,$FFFF,$E0E0,$101,$0,$0 300 POKE_W ad + 664, $0,$0,$707,$FFFF,$E0E0,$0,$0,$0 302 POKE_W ad + 680, $0,$0,$1F1F,$FFFF,$FCFC,$0,$0,$0 304 POKE_W ad + 696, $0,$0,$F0F,$FFFF,$F8F8,$0,$0,$0 306 POKE_W ad + 712, $0,$0,$1F1F,$FFFF,$FCFC,$0,$0,$0 308 POKE_W ad + 728, $0,$0,$303,$3F3F,$3030,$0,$0,$0 310 POKE_W ad + 744, $0,$0,$202,$3E3E,$2020,$0,$0,$0 312 POKE_W ad + 760, $0,$0,$0,$7F7F,$0,$0,$0,$0 314 : 316 RETurn ad 318 END DEFine Snow 320 : 322 :