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.
100 rem Use built-in blob or load one 102 IF 0 THEN 104 rem You can find some blobs in the QOMBI dat directory 106 blb = LoadDat('win1_qmb_dat_s3_OF_blb'): ERT blb 108 ELSE 110 blb = Snow: rem Use built-in blob 112 END IF 114 : 116 ch = FOPEN('con') 118 sx% = PEEK_W(blb + 4): sy% = PEEK_W(blb + 6): rem Assumes origen = 0, 0 120 WINDOW#ch; sx% * 4.8, sy% * 2, 20, 20 122 BORDER#ch; 1, 2 124 PAPER#ch; 7: CLS#ch 126 : 128 gap% = 4.5 * sx% / 4 130 xp% = 10 132 yp% = (sy% * 2 - 3 * sy% / 2) 134 : 136 pat = MkPat64: rem Init 138 CHG_COL64 pat, 0: rem Set black 140 : 142 WBLOB#ch; xp%, yp%, blb, pat 144 xp% = xp% + gap% 146 : 148 CHG_COL64 pat, $FF0000: rem Red 150 WBLOB#ch; xp%, yp%, blb, pat 152 xp% = xp% + gap% 154 : 156 CHG_COL64 pat, $FF: rem Blue 158 WBLOB#ch; xp%, yp%, blb, pat 160 xp% = xp% + gap% 162 : 164 CHG_COL64 pat, $FF00: rem Green 166 WBLOB#ch; xp%, yp%, blb, pat 168 PAUSE#ch 170 QUIT 172 : 174 : 176 : 178 rem + ------------------------------------------------------------------------ + 180 rem |< MkPat64 >| 182 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 184 rem | Create RGB 16 X 1 colour pattern | 186 rem | | 188 rem | Creates the container for a RLE-compressed pattern. | 190 rem | Set or change the colour with CHG_COL64 | 192 rem + ------------------------------------------------------------------------ + 194 rem | V0.02, pjw, 2018 Dec 02 | 196 rem | V0.03, pjw, 2021 Nov 16, new name, streamlined code, no GLOBal variables | 198 rem + ------------------------------------------------------------------------ + 200 : 202 DEFine FuNction MkPat64 204 LOCal ad 206 ad = ALCHP(37): IF ad <= 0: RETurn -3: rem 24 + 8 + 5 208 : 210 rem Create sprite header 212 POKE ad, 2, 64, 0: rem GD2 mode 64 sprite.. 214 POKE ad + 3, %1000011: rem Pattern compressed, dont cache 216 POKE_W ad + 4, 16, 1, 0, 0: rem Size, origen 218 POKE_L ad + 12, 12, 0, 0: rem Offset to data 220 POKE$ ad + 24, 'RLE4': rem Compression header 222 POKE_L ad + 28, 64: rem Expanded data size 224 RETurn ad 226 END DEFine MkPat64 228 : 230 DEFine PROCedure CHG_COL64(adr, rgb) 232 POKE_L adr + 32, rgb 234 POKE adr + 32, CHR$(241): rem 257 - 16 236 END DEFine CHG_COL64 238 : 240 : 242 : 244 rem + ************************************************************************ + 246 rem *< Help routines and Data >* 248 rem + ************************************************************************ + 250 : 252 DEFine FuNction LoadDat(fnm$) 254 LOCal fl, ad 256 ad = FOP_IN(fnm$): IF ad < 0: RETurn ad 258 fl = FLEN(#ad): CLOSE#ad 260 ad = ALCHP(fl): IF ad <= 0: RETurn -3 262 LBYTES fnm$, ad 264 RETurn ad 266 END DEFine LoadDat 268 : 270 : 272 DEFine FuNction Snow 274 LOCal ad 276 rem 57 x 48, mode 4, blob 278 : 280 ad = ALCHP(792): IF ad <= 0: RETurn -3 282 : 284 POKE_W ad + 0, $100,$0: rem form, time/adaption 286 POKE_W ad + 4, $39,$30: rem x size, y size 288 POKE_W ad + 8, $0,$0: rem x origin, y origin 290 POKE_L ad + 12, 0: rem pointer to colour pattern 292 POKE_L ad + 16, 8: rem pointer to pattern mask 294 POKE_L ad + 20, 0: rem pointer to next definition 296 : 298 POKE_W ad + 24, $0,$0,$0,$808,$0,$0,$0,$0 300 POKE_W ad + 40, $0,$0,$0,$7F7F,$0,$0,$0,$0 302 POKE_W ad + 56, $0,$0,$202,$3E3E,$2020,$0,$0,$0 304 POKE_W ad + 72, $0,$0,$606,$7E7E,$6060,$0,$0,$0 306 POKE_W ad + 88, $0,$0,$1F1F,$FFFF,$FCFC,$0,$0,$0 308 POKE_W ad + 104, $0,$0,$F0F,$FFFF,$F8F8,$0,$0,$0 310 POKE_W ad + 120, $0,$0,$1F1F,$FFFF,$FCFC,$0,$0,$0 312 POKE_W ad + 136, $0,$0,$303,$FFFF,$F0F0,$0,$0,$0 314 POKE_W ad + 152, $0,$2020,$303,$FFFF,$E0E0,$101,$0,$0 316 POKE_W ad + 168, $303,$FCFC,$1F1F,$FFFF,$FCFC,$F0F,$E0E0,$0 318 POKE_W ad + 184, $1111,$F8F8,$8F8F,$FFFF,$F8F8,$4747,$C4C4,$0 320 POKE_W ad + 200, $3333,$F9F9,$9F9F,$FFFF,$F8F8,$CFCF,$CCCC,$0 322 POKE_W ad + 216, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 324 POKE_W ad + 232, $7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 326 POKE_W ad + 248, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 328 POKE_W ad + 264, $1F1F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FEFE,$0 330 POKE_W ad + 280, $1F1F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FCFC,$0 332 POKE_W ad + 296, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 334 POKE_W ad + 312, $7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 336 POKE_W ad + 328, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 338 POKE_W ad + 344, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 340 POKE_W ad + 360, $1111,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$C4C4,$0 342 POKE_W ad + 376, $303,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$E0E0,$0 344 POKE_W ad + 392, $0,$7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$8080,$0 346 POKE_W ad + 408, $0,$3F3F,$FFFF,$FFFF,$FFFF,$FFFF,$0,$0 348 POKE_W ad + 424, $303,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$E0E0,$0 350 POKE_W ad + 440, $1111,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$C4C4,$0 352 POKE_W ad + 456, $3333,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$CCCC,$0 354 POKE_W ad + 472, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 356 POKE_W ad + 488, $7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 358 POKE_W ad + 504, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 360 POKE_W ad + 520, $1F1F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FEFE,$0 362 POKE_W ad + 536, $1F1F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FCFC,$0 364 POKE_W ad + 552, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 366 POKE_W ad + 568, $7F7F,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 368 POKE_W ad + 584, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$0 370 POKE_W ad + 600, $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$8080 372 POKE_W ad + 616, $1111,$F8F8,$8F8F,$FFFF,$F8F8,$4747,$C4C4,$0 374 POKE_W ad + 632, $303,$FCFC,$1F1F,$FFFF,$FCFC,$F0F,$E0E0,$0 376 POKE_W ad + 648, $0,$6060,$303,$FFFF,$E0E0,$101,$0,$0 378 POKE_W ad + 664, $0,$0,$707,$FFFF,$E0E0,$0,$0,$0 380 POKE_W ad + 680, $0,$0,$1F1F,$FFFF,$FCFC,$0,$0,$0 382 POKE_W ad + 696, $0,$0,$F0F,$FFFF,$F8F8,$0,$0,$0 384 POKE_W ad + 712, $0,$0,$1F1F,$FFFF,$FCFC,$0,$0,$0 386 POKE_W ad + 728, $0,$0,$303,$3F3F,$3030,$0,$0,$0 388 POKE_W ad + 744, $0,$0,$202,$3E3E,$2020,$0,$0,$0 390 POKE_W ad + 760, $0,$0,$0,$7F7F,$0,$0,$0,$0 392 : 394 RETurn ad 396 END DEFine Snow 398 : 400 :