-
Notifications
You must be signed in to change notification settings - Fork 75
/
drag_text.py
executable file
·144 lines (122 loc) · 4.3 KB
/
drag_text.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#! /usr/bin/env python
"""
A very simple example showing how to drag an item with the mouse.
Dragging in this example uses relative mouse movement.
-Written by Sean J. McKiernan 'Mekire'
"""
import os
import sys
import pygame as pg
CAPTION = "Drag the Red Square"
SCREEN_SIZE = (1000, 600)
class Character(object):
"""
A class to represent our lovable red sqaure.
"""
SIZE = (150, 150)
def __init__(self, pos):
"""
The argument pos corresponds to the center of our rectangle.
"""
self.rect = pg.Rect((0,0), Character.SIZE)
self.rect.center = pos
self.text, self.text_rect = self.setup_font()
self.click = False
def setup_font(self):
"""
If your text doesn't change it is best to render once, rather than
re-render every time you want the text. Rendering text every frame is
a common source of bottlenecks in beginner programs.
"""
font = pg.font.SysFont('timesnewroman', 30)
message = "I'm a red square"
label = font.render(message, True, pg.Color("white"))
label_rect = label.get_rect()
return label, label_rect
def check_click(self, pos):
"""
This function is called from the event loop to check if a click
overlaps with the player rect.
pygame.mouse.get_rel must be called on an initial hit so that
subsequent calls give the correct relative offset.
"""
if self.rect.collidepoint(pos):
self.click = True
pg.mouse.get_rel()
def update(self, screen_rect):
"""
If the square is currently clicked, update its position based on the
relative mouse movement. Clamp the rect to the screen.
"""
if self.click:
self.rect.move_ip(pg.mouse.get_rel())
self.rect.clamp_ip(screen_rect)
self.text_rect.center = (self.rect.centerx, self.rect.centery+90)
def draw(self, surface):
"""
Blit image and text to the target surface.
"""
surface.fill(pg.Color("red"), self.rect)
surface.blit(self.text, self.text_rect)
class App(object):
"""
A class to manage our event, game loop, and overall program flow.
"""
def __init__(self):
"""
Get a reference to the screen (created in main); define necessary
attributes; and create our player (draggable rect).
"""
self.screen = pg.display.get_surface()
self.screen_rect = self.screen.get_rect()
self.clock = pg.time.Clock()
self.fps = 60
self.done = False
self.keys = pg.key.get_pressed()
self.player = Character(self.screen_rect.center)
def event_loop(self):
"""
This is the event loop for the whole program.
Regardless of the complexity of a program, there should never be a need
to have more than one event loop.
"""
for event in pg.event.get():
if event.type == pg.QUIT or self.keys[pg.K_ESCAPE]:
self.done = True
elif event.type == pg.MOUSEBUTTONDOWN and event.button == 1:
self.player.check_click(event.pos)
elif event.type == pg.MOUSEBUTTONUP and event.button == 1:
self.player.click = False
elif event.type in (pg.KEYUP, pg.KEYDOWN):
self.keys = pg.key.get_pressed()
def render(self):
"""
All drawing should be found here.
This is the only place that pygame.display.update() should be found.
"""
self.screen.fill(pg.Color("black"))
self.player.draw(self.screen)
pg.display.update()
def main_loop(self):
"""
This is the game loop for the entire program.
Like the event_loop, there should not be more than one game_loop.
"""
while not self.done:
self.event_loop()
self.player.update(self.screen_rect)
self.render()
self.clock.tick(self.fps)
def main():
"""
Prepare our environment, create a display, and start the program.
"""
os.environ['SDL_VIDEO_CENTERED'] = '1'
pg.init()
pg.display.set_caption(CAPTION)
pg.display.set_mode(SCREEN_SIZE)
App().main_loop()
pg.quit()
sys.exit()
if __name__ == "__main__":
main()