Draw Shapes With The Mouse In Pygame By albro

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@albro·
0.000 HBD
Draw Shapes With The Mouse In Pygame By albro
<center>![Draw Shapes With The Mouse In Pygame](https://files.peakd.com/file/peakd-hive/albro/23xyiBA8ae9ownhFC7rMkSyn6aCNXdVigT5jroMcTWtb7SFe9iWHyjA4MKHbefMymMfNz.png)</center>

<p>When we press the mouse buttons, events such as <code>MOUSEBUTTONDOWN</code> and <code>MOUSEBUTTONUP</code> are generated. First of all, let's detect these events in our game loop and print a message on the console if they exist!</p>
<pre>code>for event in pygame.event.get():
    if event.type == QUIT:
        running = False
    elif event.type == MOUSEBUTTONDOWN:
        print(event)
    elif event.type == MOUSEBUTTONUP:
        print(event)</code></pre>
<p>Now, if I left-click or right-click in the game window, the following events will be generated immediately and will be printed on the console.</p>
<pre><code><Event(1025-MouseButtonDown {'pos': (53, 53), 'button': 1, 'touch': False, 'window': None})>
<Event(1026-MouseButtonUp {'pos': (53, 53), 'button': 1, 'touch': False, 'window': None})>
<Event(1025-MouseButtonDown {'pos': (546, 249), 'button': 3, 'touch': False, 'window': None})>
<Event(1026-MouseButtonUp {'pos': (546, 249), 'button': 3, 'touch': False, 'window': None})></code></pre>
<p>Mouse movement in the game window causes the <code>MOUSEMOTION</code> event. So I can also add the following code to the program!</p>
<pre><code>elif event.type == MOUSEMOTION:
    print(event)</code></pre>
<h3>Draw a rectangle with mouse movement</h3>
<p>I want to use mouse events to draw the rectangle. At the beginning, let's have an understanding of the process. As I said before, we need a <code>display</code> object and a <code>color</code> to draw a rectangle. Then we must have the upper-left corner point of the rectangle and its width and height. So, when the mouse is pressed in a point, the coordinates of that point in the window can be considered as the starting point of the drawing. Mouse movement determines the size of the rectangle. As soon as the mouse is released at an endpoint, I can calculate the size and draw the rectangle. So I need all three events above. I need a <code>flag</code> with a default value of <code>False</code> to tell if I'm drawing or not. In addition, I need another variable called <code>size</code>.</p>
<p>Let's first define the following four variables.</p>
<pre><code>start = (0, 0)
size = (0, 0)
drawing = False</code></pre>
<p>When the mouse is pressed, we must put the current position in the <code>start</code> and <code>end</code> variables and change the value of the <code>drawing</code> to <code>True</code>. This means we are drawing!</p>
<pre><code>elif event.type == MOUSEBUTTONDOWN:
    start = end = event.pos
    size = (0, 0)
    drawing = True</code></pre>
<p>When the mouse button is released, I set the <code>end</code> value to the position of that point and return the <code>drawing</code> value to <code>False</code> to indicate that the drawing is finished.</p>
<pre><code>elif event.type == MOUSEBUTTONUP:
    if(event.pos[1]>start[1]):
        end = event.pos
    else:
        start = event.pos
    size = (end[0] - start[0], end[1] - start[1])
    drawing = False</code></pre>
<p>Finally, we need to check whether we are drawing or not when the mouse is moving. If the answer is yes, then let's use the current position as the <code>end</code> point:</p>
<pre><code>elif event.type == MOUSEMOTION and drawing:
    if(event.pos[1]>start[1]):
        end = event.pos
    else:
        start = event.pos
    size = (end[0] - start[0], end[1] - start[1])</code></pre>
<p>One thing that should be noted and can be seen in the code above is that to calculate the size of the rectangle, it is enough to subtract the width and height coordinates. So when I want to calculate the width of the rectangle, it is enough to subtract the X coordinate value of the starting pont from the X coordinate value of the current point. I will also get help from the Y coordinate for the height!</p>
<p>At the end of the work, I draw the rectangle.</p>
<pre><code>screen.fill(GRAY)
pygame.draw.rect(screen, RED, (start, size), 2)
pygame.display.update()</code></pre>
<p>In fact, after all the events are over, I tell Pygame to do the drawing now!</p>
<pre><code>import pygame,sys
from pygame.locals import *<br />
RED = (255, 0, 0)
GRAY = (127, 127, 127)<br />
pygame.init()
screen = pygame.display.set_mode((640, 400))
pygame.display.set_caption('Draw Shapes')<br />
start = (0, 0)
size = (0, 0)
drawing = False<br />
running = True
while running:<br />
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        elif event.type == MOUSEBUTTONDOWN:
            start = end = event.pos
            size = (0, 0)
            drawing = True
        elif event.type == MOUSEBUTTONUP:
            if(event.pos[1]>start[1]):
                end = event.pos
            else:
                start = event.pos
            size = (end[0] - start[0], end[1] - start[1])
            drawing = False
        elif event.type == MOUSEMOTION and drawing:
            if(event.pos[1]>start[1]):
                end = event.pos
            else:
                start = event.pos
            size = (end[0] - start[0], end[1] - start[1])<br />
    screen.fill(GRAY)
    pygame.draw.rect(screen, RED, (start, size), 2)
    pygame.display.update()<br />
pygame.quit()</code></pre>
<p>Now if I run the above code, pressing and releasing each of the mouse buttons will create something like the following:</p>

<center>![Draw a rectangle with mouse movement](https://files.peakd.com/file/peakd-hive/albro/23wqkWh6Xmbrh3g19s1ThzLkvzeCihsT62myTS8EfbKP2TtLM5w8rAdmMJib33jpUcuDa.png)</center>

<h3>Draw several rectangles with the mouse</h3>
<p>If I want to draw multiple rectangles, I need to have a list to hold the rectangles!</p>
<pre><code>rect_list = []</code></pre>
<p>Now, in the previous code, when the mouse button is released, I need to create a rectangle object and add it to the list:</p>
<pre><code>elif event.type == MOUSEBUTTONUP:
    if(event.pos[1]>start[1]):
        end = event.pos
    else:
        start = event.pos
    size = (end[0] - start[0], end[1] - start[1])
    rect = pygame.Rect(start, size)
    rect_list.append(rect)
    drawing = False</code></pre>
<p>Then after I've painted the background, I need to draw the objects using a loop and finally draw the current rectangle in blue!</p>
<pre><code>screen.fill(GRAY)
for rect in rect_list:
    pygame.draw.rect(screen, RED, rect, 3)
pygame.draw.rect(screen, BLUE, (start, size), 1)
pygame.display.update()</code></pre>
<p>So I have:</p>
<pre><code>import pygame,sys
from pygame.locals import *<br />
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GRAY = (127, 127, 127)<br />
pygame.init()
screen = pygame.display.set_mode((640, 400))
pygame.display.set_caption('Draw Shapes')<br >
start = (0, 0)
size = (0, 0)
drawing = False
rect_list = []<br />
running = True
while running:<br />
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        elif event.type == MOUSEBUTTONDOWN:
            start = end = event.pos
            size = (0, 0)
            drawing = True
        elif event.type == MOUSEBUTTONUP:
            if(event.pos[1]>start[1]):
                end = event.pos
            else:
                start = event.pos
            size = (end[0] - start[0], end[1] - start[1])
            rect = pygame.Rect(start, size)
            rect_list.append(rect)
            drawing = False
        elif event.type == MOUSEMOTION and drawing:
            if(event.pos[1]>start[1]):
                end = event.pos
            else:
                start = event.pos
            size = (end[0] - start[0], end[1] - start[1])<br />
    screen.fill(GRAY)
    for rect in rect_list:
        pygame.draw.rect(screen, RED, rect, 3)
    pygame.draw.rect(screen, BLUE, (start, size), 1)
    pygame.display.update()<br />
pygame.quit()</code></pre>

<center>![Draw several rectangles with the mouse](https://files.peakd.com/file/peakd-hive/albro/23x1B2ZGwENt8PY9VhdxvJXY2ctmJ9MybvMsKodMZSrU6EtKhaF2sjFyVKWznn7PU3UWT.png)</center>

<h3>Draw a polygon with the mouse</h3>
<p>To draw a polygon we need to add all the points to an array of points. First, we define an array called <code>points</code> and a <code>drawing</code> flag:</p>
<pre><code>drawing = False
points = []</code></pre>
<p>In the following code for handling the <code>MOUSEBUTTONDOWN</code> event, we add the current point to the array and set the <code>drawing</code> flag to <code>True</code>:</p>
<pre><code>elif event.type == MOUSEBUTTONDOWN:
    points. append(event.pos)
    drawing = True</code></pre>
<p>When the <code>MOUSEBUTTONUP</code> event occurs, we disable the <code>drawing</code> flag:</p>
<pre><code>elif event.type == MOUSEBUTTONUP:
    drawing = False</code></pre>
<p>If the flag is set, and the <code>MOUSEMOTION</code> event occurs, we move the last point from the polygon list:</p>
<pre><code>elif event.type == MOUSEMOTION and drawing:
    points[-1] = event.pos</code></pre>
<p>If there are more than 2 points in the points array, we draw a green border line for the polygon. A polygon is drawn inside this line. Calling the <code>pygame.draw</code> function returns a <code>Rect</code> or bounding rectangle for the polygon. This rectangle encloses the polygon. We display this rectangle in green.</p>
<pre><code>screen.fill(GRAY)
if len(points)>1:
    rect = pygame.draw.lines(screen, RED, True, points, 3)
    pygame.draw.rect(screen, GREEN, rect, 1)
pygame.display.update()</code></pre>
<p>Pressing the ESCAPE key removes the last dot in the array:</p>
<pre><code>elif event.type == KEYDOWN:
    if event.key == K_ESCAPE:
        if len(points) > 0:
            points.pop()</code></pre>
<p>So</p>
<pre><code>import pygame,sys
from pygame.locals import *<br />
RED = (255, 0, 0)
GREEN = (0, 255, 0)
GRAY = (150, 150, 150)<br />
pygame. init()
screen = pygame.display.set_mode((640, 240))<br />
drawing = False
points = []
running = True<br />
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False<br />
        elif event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                if len(points) > 0:
                    points.pop()<br />
        elif event.type == MOUSEBUTTONDOWN:
            points.append(event.pos)
            drawing = True<br />
        elif event.type == MOUSEBUTTONUP:
            drawing = False<br />
        elif event.type == MOUSEMOTION and drawing:
            points[-1] = event.pos<br />
    screen.fill(GRAY)
    if len(points)>1:
        rect = pygame.draw.lines(screen, RED, True, points, 3)
        pygame.draw.rect(screen, GREEN, rect, 1)
    pygame.display.update()<br />
pygame.quit()</code></pre>

<center>![Draw a polygon with the mouse](https://files.peakd.com/file/peakd-hive/albro/23wMeqFw7Arx5DwFog54csigM2VX7DQcqB5i7sn5ANocgHnRDSWmybTHckTDja77uTSjW.png)</center>
👍 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,