Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/data/GSOC examples/rotate polygon
blob: 01d2b9db29ddcf15971a9f8a9c2af0d952c336e6 (plain)
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# This code creates a polygon and then rotates it around one of its points.
# Two static polygons are here so you can experiment with them, but you'll
# have to uncomment them first.

# Practice: 
#   When you start this example, the two lines of text will be too close to each other.
#   How could that be fixed?
#
#   Also, the starting shape is kinda small. We can increase it with our Up arrow, 
#   but can you find what should be changed in this example so that that shape
#   starts larger by default?


import pippy, pygame, sys
from pygame.locals import *
from random import *
from math import cos, sin
from math import pi as Pi
import gtk

# always need to init first thing
pygame.init()

# XO screen is 1200x900
size = width, height = gtk.gdk.screen_width(), gtk.gdk.screen_height()

# create the window and keep track of the surface
# for drawing into
screen = pygame.display.set_mode(size)

# turn off the cursor
pygame.mouse.set_visible(False)

# This is used to define how our shapes (polygons) look like and behave.
# By default, a polygon will have three sides (a triangle), each 300 in length.
class Polygon(object):
    # If you don't specify the number of sides and length you with your 
    # polygon to have, it will take these values as default.
    def __init__(self, n = 3, length = 300):
        if n < 3:
            print "Number of points cannot be less than three"
            return 
        self.n_sides = n
        self.side_length = length
        self.points = []
        starting_point = (0, 0)
        self.points.append(starting_point)
        for i in range(n-1):
            point = self.points[i][0] + cos(2 * Pi * i/n) * length, \
                    self.points[i][1] - sin(2 * Pi * i/n) * length
            self.points.append(point)

    # This defines how our polygon will draw itself on a surface we give it.
    # The surface variable is called "screen" in this example.
    # Variable "start" defines the point from which we'll start drawing it, and
    # then later rotating it. By default, it's the middle of the screen.
    # 
    def draw(self, screen, start = (screen.get_width() / 2, \
                                    screen.get_height() / 2) ):
        real_coordinates = []
        for point in self.points:
            real_point = point[0] + start[0], point[1] + start[1]
            real_coordinates.append(real_point)
        # draw a line between each two neighbouring points
        for i in range(len(real_coordinates)-1):
            pygame.draw.line(screen, (0, 255, 0), real_coordinates[i], real_coordinates[i+1])
        # another line between the last point and the first one to close the polygon
        pygame.draw.line(screen, (0, 255, 0), real_coordinates[i+1], real_coordinates[0])

    # This rotates the polygon around its starting point.
    # It doesn't draw anything - it recalculates where all the other vertices
    # will be when the triangle is rotated.
    def rotate(self, angle):
        # delete everything but the starting point, since we need to
        # calculate all the other points again
        self.points = [(0,0)] 
        for i in range(self.n_sides-1):
            point = self.points[i][0] + cos(angle + 2 * Pi * i/self.n_sides) * self.side_length, \
                    self.points[i][1] - sin(angle + 2 * Pi * i/self.n_sides) * self.side_length
            self.points.append(point)

# OK, let's create out polygon!
# Set some values it will use.. (practice hint here!)
side_length = 50
number_of_sides = 5
rotation_angle = 0
speed_factor = 0

poly1 = Polygon(number_of_sides, side_length)

# Commented out is the code which creates two more polygons. You could
# uncomment it to try it out. Code:
# poly2 = Polygon(number_of_sides, side_length)
# triangle1 = Polygon(length = side_length)

# Background color will be black.
bgcolor = (0, 0, 0)

# for displaying the instructions and rotation speed
font_size = 36
font_colour = (0, 250, 0)
font = pygame.font.Font(None, font_size)

# Conversion from degrees to radians. For us, it represents the smallest amount
# of rotation possible. If you wish to understand it better, it has to do with
# math (trigonometry) so you can try finding some information about it.
degree = Pi / 180

# While L or R arrow is pressed and held, these variables will change so that 
# our program knows to keep increasing the speed of the rotation.
# Left arrow increases the rotation in the counter clockwise direction (+) and
# the right one clockwise (-).
less = False
more = False

# for controling the polygon size when U or D arrow is pressed
size_changed = False

while pippy.pygame.next_frame():
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        # right arrow makes it rotate clockwise
        elif event.type == KEYDOWN and event.key == K_RIGHT:
            less = True
        # left arrow makes it rotate counterclockwise
        elif event.type == KEYDOWN and event.key == K_LEFT:
            more = True
        # when a key is lifted, stop changing speed
        elif event.type == KEYUP and event.key == K_RIGHT:
            less = False
        elif event.type == KEYUP and event.key == K_LEFT:
            more = False

        # Changing the size of our polygon with up and down keys.
        # Practice: Unlike L and R keys, this does not keep changing size
        # while the keys are pressed. Could you make it so? Look to L and R 
        # examples to understand how it's done.
        elif event.type == KEYDOWN and event.key == K_UP:
            side_length += 5
            size_changed = True
        elif event.type == KEYDOWN and event.key == K_DOWN and side_length > 5:
            side_length -= 5
            size_changed = True
        elif event.type == KEYDOWN and event.key == K_q:
            sys.exit()    

    screen.fill(bgcolor)

    # display instructions, speed and size
    msg = "Use left and right arrows for controling speed.  Speed: " 
    msg = msg + str(speed_factor)
    msg2 = "Use up and down arrows for controling size. Size : " + str(side_length)
    text1 = font.render(msg , True, font_colour)
    text_box1 = text1.get_rect()
    text_box1.top = height / 20
    text2 = font.render(msg2 , True, font_colour)
    text_box2 = text2.get_rect()
    text_box2.top = height / 20 + 14

    # if the L or R arrow is pressed (and held), keep adjusting speed
    # You'll have to click it real fast if you with to change the speed by 
    # only one!
    if less == True:
        speed_factor = speed_factor - 1
    if more == True:
        speed_factor = speed_factor + 1

    # The new angle by which our polygone is turned is the previous angle + the
    # change in rotation due to speed_factor being changed by L or R keys.
    rotation_angle = rotation_angle + degree *  speed_factor

    # If the size was changed (with up and down keys), create a new polygon
    # with that size.
    if size_changed == True:
        poly1 = Polygon(number_of_sides, side_length)
        size_changed = False
    poly1.rotate(rotation_angle)
    poly1.draw(screen)

    # This should also be uncommented if you with to see some other polygons
    # we've prepared for you.
    # Practice: Uncomment the code and change some values. What happend?
    # Code to uncomment:
    # poly2.draw(screen)
    # triangle1.rotate(30 * Pi / 180)
    # triangle1.draw(screen, (800, 650))
    
    # draw the text
    screen.blit(text1, text_box1)
    screen.blit(text2, text_box2)

    # refresh the screen
    pygame.display.flip()