How do I paint a shape?
#1
I have the few lines of code below, which draw a shape on the screen.
How do I implement a "Paint" (or P in a draw-string) to paint the inside of the shape, say red (_RGB(255,0,0) ?
Code: (Select All)
Screen _NewImage(1200, 820, 32)
Dim colr As _Unsigned Long: colr = _RGB(255, 0, 0)
colr = _RGB(0, 255, 255)
PSet (500, 300): Draw "C" + Str$(colr) + "R100F100D100G100L100H100U100E100"
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, W.A.) Big Grin
Reply
#2
Unfortunately, painting is a headache in this programming language, and especially if you want to use 32-bit color. :/

First you have to make absolutely sure the shape is closed. If not the painting would take over the whole screen or, less often, other screen elements that could ruin your landscape or portrait.

It's better to forget about "P" command for DRAW for 32-bit color because it's confusing, "C" already requires specific LONG integer values and otherwise this programming system is very good yelling "Illegal function call" back at you if it doesn't like a value. You have the border color already in a variable called "colr". Assuming the color you want to paint with is called "paintcolr" then the code could be added like this:

Code: (Select All)
DIM paintcolr AS LONG
paintcolr = _RGB(255, 0, 0)
PAINT(501, 301), paintcolr, colr

The POINT TO SELECT TO PAINT is very important. I had to deduce it from your code which seems to draw an octagon and begins from the top-left corner. Figuring out the point inside the closed figure to paint is a science in itself in BASIC graphics programming.

I suppose you could use STR$() to force the _RGB() values that you want for "P" command for DRAW but using PAINT is more concise. Otherwise would have to use POINT(0) and POINT(1) to obtain the X,Y coordinates of the DRAW "pen" but it's not reliable. Irritatingly the Wiki page on POINT() says nothing about DRAW.



This is a quick silly program that I wrote demonstrating POINT(0) and POINT(1):

Code: (Select All)

SCREEN 12
LOCATE 1, 1
PRINT POINT(0), POINT(1)
DRAW "s16fbdbrdhdbehebddhfbdhrbebuh"
LOCATE 2, 1
PRINT POINT(0), POINT(1)
END

It is verified the first X,Y coordinates shown is the middle of the screen.
Reply
#3
Code: (Select All)
SCREEN _NEWIMAGE(1200, 820, 32)
DIM colr AS _UNSIGNED LONG: colr = _RGB(255, 0, 0)
colr = _RGB(0, 255, 255)
PSET (500, 300): DRAW "C" + STR$(colr) + "R100F100D100G100L100H100U100E100"
PAINT STEP(10, 10), colr
As it happens, a straight paint after stepping into the shape works in this case, but mnrvovrfc is correct in that it requires a "manifold" (aka water tight) shape, or paint will over write the entire screen. It can be a difficult standard to hit sometimes.

Also, knowing which way to step the graphics cursor into a shape (as I did above) for paint insertion can be tricky if there are rotations or movements going on in a program. Paint is slow to implement, so if you need speed, it's probably better to define a painted shape as a discrete image at program startup and then _putimage it as needed.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#4
You can do the painting right on the default screen or on a work screen.

Try not to think in terms of needing to paint the object. Many times I'll simply paint an entire work screen, draw my object, then paint OUTSIDE the object to get the effect I need. Code below shows a few examples:

Code: (Select All)
SCREEN _NEWIMAGE(1200, 820, 32)

' Do the painting on the default screen (_DEST 0)

CLS , _RGB32(255, 0, 0) '            paint the entire screen first
DIM colr AS _UNSIGNED LONG: colr = _RGB(255, 0, 0)
colr = _RGB(0, 255, 255)
PSET (500, 300): DRAW "C" + STR$(colr) + "R100F100D100G100L100H100U100E100"
PAINT (0, 0), _RGB32(0, 0, 0), colr ' paint the screen black until cyan is met

SLEEP

' Do the painting on a work screen that gets copied to the default screen.

CLS
PRINT
PRINT " This is the default screen _DEST 0"
PRINT " The work screen will not wipe this text out"
WorkScreen& = _NEWIMAGE(1200, 820, 32)
_DEST WorkScreen& '                  all graphics command sent to work screen
CLS , _RGB32(255, 0, 0) '            paint the entire work screen first
PSET (500, 300): DRAW "C" + STR$(colr) + "R100F100D100G100L100H100U100E100"
PAINT (0, 0), _RGB32(0, 0, 0), colr ' paint the work screen black until colr met
_CLEARCOLOR _RGB32(0, 0, 0) '        make black on the work screen transparent
_DEST 0 '                            go back to default screen
_PUTIMAGE , WorkScreen&, 0 '          copy the work screen to the default screen
Software and cathedrals are much the same — first we build them, then we pray.
QB64 Tutorial
Reply
#5
When object overlaps another you can paint to Border Color of object inside or out, as:
Code: (Select All)
Paint (x, y), color~&, toBorderColor~& 

as the toBorderColor option parameter has been fixed!, if I recall our updates to QB64 correctly.

As already mentioned, make sure the object is enclosed by border inside the screen, no gaps or holes.
b = b + ...
Reply
#6
If for drawing you need to coloring an object that does not have color borders in the same color, use my Paint2 here: https://staging.qb64phoenix.com/showthread.php?tid=1507


Reply
#7
@PhilofPerth

Do you need the exact same shape in red?

In this way you can save to memory more images - and then place it using _PutImage - it is fastest method.

Code: (Select All)

'how create more images from one in different colors

Dim Images(3) As Long

Screen _NewImage(1200, 820, 32)
Dim colr As _Unsigned Long: colr = _RGB(255, 0, 0)

For ImageCreate = 0 To 3
    Select Case ImageCreate
        Case 0: R = 0: G = 255: B = 255
        Case 1: R = 255: G = 255: B = 255
        Case 2: R = 255: G = 255: B = 0
        Case 3: R = 0: G = 0: B = 255
    End Select

    Images(ImageCreate) = _NewImage(1200, 820, 32)
    _Dest Images(ImageCreate)
    colr = _RGB(R, G, B)
    PSet (500, 300): Draw "C" + Str$(colr) + "R100F100D100G100L100H100U100E100"
Next
_Dest 0
For ImageView = 0 To 3
    Cls
    _PutImage , Images(ImageView), 0
    Print "Press any key for next image..."
    Sleep
Next


Reply
#8
And in this way you fill your images with color:

Code: (Select All)


Dim Images(3) As Long

Screen _NewImage(1200, 820, 32)
Dim colr As _Unsigned Long: colr = _RGB(255, 0, 0)

For ImageCreate = 0 To 3
    Select Case ImageCreate
        Case 0: R = 0: G = 255: B = 255
        Case 1: R = 255: G = 255: B = 255
        Case 2: R = 255: G = 255: B = 0
        Case 3: R = 0: G = 0: B = 255
    End Select
    C$ = Str$(_RGB(R, G, B))

    Images(ImageCreate) = _NewImage(1200, 820, 32)
    _Dest Images(ImageCreate)
    colr = _RGB(R, G, B)
    PSet (500, 300): Draw "C" + Str$(colr) + "R100 F100 D100 G100 L100 H100 U100 E100 BD50  P" + C$ + "," + C$
Next
_Dest 0
For ImageView = 0 To 3
    Cls
    _PutImage , Images(ImageView), 0
    Print "Press any key for next image..."
    Sleep
Next

You must not forget to move the graphic cursor back to the filled area (in this case I am moving 50 pixels down the BD50 part)

   


Reply
#9
Hi
all different and working ways
but P of draw is not so bad
Draw wiki page

and taking the example 4
Code: (Select All)
SCREEN 12
DO
  LOCATE 1, 1: INPUT "Enter a number 0 to 9: ", num
  CLS
  SELECT CASE num
    CASE 0, 2, 3, 5 TO 9: PSET (20, 20), 12
      DRAW "E2R30F2G2L30H2BR5P12,12" 'top horiz
  END SELECT

  SELECT CASE num
    CASE 0, 4 TO 6, 8, 9: PSET (20, 20), 12
      DRAW "F2D30G2H2U30E2BD5P12,12" 'left top vert
  END SELECT

  SELECT CASE num
    CASE 0, 2, 6, 8: PSET (20, 54), 12
      DRAW "F2D30G2H2U30E2BD5P12, 12" 'left bot vert
  END SELECT

  SELECT CASE num
    CASE 2 TO 6, 8, 9: PSET (20, 54), 12
      DRAW "E2R30F2G2L30H2BR5P12, 12" 'middle horiz
  END SELECT

  SELECT CASE num
    CASE 0 TO 4, 7 TO 9: PSET (54, 20), 12
      DRAW "F2D30G2H2U30E2BD5P12,12" 'top right vert
  END SELECT

  SELECT CASE num
    CASE 0, 1, 3 TO 9: PSET (54, 54), 12
      DRAW "F2D30G2H2U30E2BD5P12,12" 'bottom right vert
  END SELECT

  SELECT CASE num
    CASE 0, 2, 3, 5, 6, 8: PSET (20, 88), 12
      DRAW "E2R30F2G2L30H2BR5P12,12" 'bottom horiz
  END SELECT
LOOP UNTIL num > 9
it is  clear that all previous tips told in this thread have been used.

P of DRAW works fine also in 32 bit color

here the same example using a screen 32 and a col$ _RGBA32
Code: (Select All)
Screen _NewImage(1000, 800, 32)
Col$ = Str$(_RGBA32(222, 116, 44, 255))
paint$ = "P" + Col$ + "," + Col$
Do
    Locate 1, 1: Input "Enter a number 0 to 9: ", num
    Cls
    Select Case num
        Case 0, 2, 3, 5 To 9: PSet (20, 20), Val(Col$)
            Draw "E2R30F2G2L30H2BR5" + paint$ 'top horiz
    End Select

    Select Case num
        Case 0, 4 To 6, 8, 9: PSet (20, 20), Val(Col$)
            Draw "F2D30G2H2U30E2BD5" + paint$ 'left top vert
    End Select

    Select Case num
        Case 0, 2, 6, 8: PSet (20, 54), Val(Col$)
            Draw "F2D30G2H2U30E2BD5" + paint$ 'left bot vert
    End Select

    Select Case num
        Case 2 To 6, 8, 9: PSet (20, 54), Val(Col$)
            Draw "E2R30F2G2L30H2BR5" + paint$ 'middle horiz
    End Select

    Select Case num
        Case 0 To 4, 7 To 9: PSet (54, 20), Val(Col$)
            Draw "F2D30G2H2U30E2BD5" + paint$ 'top right vert
    End Select

    Select Case num
        Case 0, 1, 3 To 9: PSet (54, 54), Val(Col$)
            Draw "F2D30G2H2U30E2BD5" + paint$ 'bottom right vert
    End Select

    Select Case num
        Case 0, 2, 3, 5, 6, 8: PSet (20, 88), Val(Col$)
            Draw "E2R30F2G2L30H2BR5" + paint$ 'bottom horiz
    End Select
Loop Until num > 9
I remember an exercise of the Terry's tutorial to build a landscape with DRAW, another to create Basic shapes to use for landscape.
In this last case you will find very useful the function S (scale) of DRAW to get different size of the same shape.
Reply
#10
Code: (Select All)

Screen _NewImage(1200, 820, 32)
Dim colr As _Unsigned Long: colr = _RGB32(255, 0, 0)
colr = _RGB32(0, 255, 255)
PSet (500, 300): Draw "C" + Str$(colr) + "R100F100D100G100L100H100U100E100"
Paint (600, 410), &HFFFF0000, colr
b = b + ...
Reply




Users browsing this thread: 4 Guest(s)