1# -*- coding: utf-8 -*-
2#-----------------------------------------------------------------------------
3# Copyright (c) 2013-2019, PyInstaller Development Team.
4#
5# Distributed under the terms of the GNU General Public License with exception
6# for distributing bootloader.
7#
8# The full license is in the file COPYING.txt, distributed with this software.
9#-----------------------------------------------------------------------------
10
11
12# This is a copy of
13# http://jonasbsb.jo.funpic.de/hendrix/pygame-example.py
14
15
16try:
17    import sys
18    import random
19    import math
20    import os
21    import pygame
22    import time
23    from pygame.locals import *
24
25except ImportError as err:
26    raise SystemExit("Error, couldn't load module. %s" % err)
27
28if not pygame.mixer: print('Warning, sound disabled')
29
30NUM_SPRITES = 10
31
32### Klassendefinitionen
33
34class Screen:
35    def __init__(self, resolution=(640, 480), cmdline=""):
36        self.color = (0,0,0)
37        self.resolution = resolution
38        if "--fullscreen" in cmdline:
39            self.window = \
40                pygame.display.set_mode(self.resolution, pygame.FULLSCREEN)
41        else:
42            self.window = pygame.display.set_mode(self.resolution)
43        # pygame.display.set_mode() verändert die Größe des Fensters
44        # Über das zweite Argument, pygame.FULLSCREEN, kann das Fenster
45        # in den Vollbildmodus versetzt werden
46
47        pygame.display.set_caption('A Simple Yet Insightful Pygame Example')
48        # Verändert die Beschriftung des Fensters
49
50        pygame.mouse.set_visible(0)
51        # Verhindert, dass die Maus gezeigt wird
52
53        self.screen = pygame.display.get_surface()
54        # Generiert ein Surface des Fensters
55        # Siehe: Allgemeines über Surfaces
56
57        self.screen.fill(self.color)
58        # Füllt das Surface self.screen mit der übergebenen Farbe
59        # Siehe: Allgemeines über Farben
60
61        self.screen_rect = self.screen.get_rect()
62        # Rectangle des Fensters
63        # Siehe: Allgemeines über Rectangles
64
65    def size(self):
66        return self.screen_rect
67
68    def fill(self):
69        self.screen.fill(self.color)
70        # Füllt das Surface self.screen mit der übergebenen Farbe
71        # Siehe: Allgemeines über Farben
72
73
74class Sprite(pygame.sprite.Sprite):
75    def __init__(self, screen):
76        pygame.sprite.Sprite.__init__(self)
77        # Die Klasse Sprite wird von der pygame-Basisklasse
78        # pygame.sprite.Sprite abgeleitet
79
80        self.screen= screen
81
82        self.width = 10
83        self.height = 10
84        # Legt die Höhe und Breite der Objekte fest
85
86        self.x = random.randint(0, screen.resolution[0] + self.width)
87        self.y = random.randint(0, screen.resolution[1] + self.height)
88        # Generiert zufällig eine x- und eine y-Koordinate als Startpunkt
89
90        self.direction = random.choice((1,-1))
91        self.angle = random.choice((0.45, 2.69)) * self.direction
92        self.speed = random.randint(5,8)
93        # Wählt zufällig Werte für die Richtung und Geschwindigkeit aus
94
95        self.image = pygame.Surface([self.width, self.height])
96        # Generiert ein Surface des Objektes mit der definierten Größe
97        # Siehe: Allgemeines über Surfaces
98
99        self.rect = self.image.get_rect()
100        # Siehe: Allgemeines über Rectangles
101
102        self.rect = self.rect.move(self.x,self.y)
103        # self.rect.move(x-Wert, y-Wert) berechnet einen
104        # neuen Punkt und ordnet ihn dem Rectangle des
105        # Objektes zu
106        #
107        # Das Koordinatensystem beginnt am oberen, linken Rand
108        # des Bildschirms mit (0,0)
109
110        self.area = pygame.display.get_surface().get_rect()
111        # Rectangle des Fensters
112        # Siehe: Allgemeines über Rectangles
113
114    def position(self):
115        return self.rect
116
117    def changeColor(self):
118        newColor = []
119        for i in range(3):
120            newColor.append(random.randint(0,255))
121        self.color = newColor
122        # Generiert einen zufälligen Farbwert
123
124        self.image.fill(self.color)
125        # Füllt das Surface des Objektes
126        # Siehe: Allgemeines über Farben
127
128    def update(self):
129        dx = self.speed*math.cos(self.angle)
130        dy = self.speed*math.sin(self.angle)
131        # Mathematische Grundlage der Bewegung
132        # siehe: http://de.wikipedia.org/wiki/Sinus
133
134        newpos = self.rect.move(dx,dy)
135        # berechnet eine neue Position
136
137        if not self.area.contains(newpos):
138        # Kollisionsberechnung
139            tl = not self.area.collidepoint(newpos.topleft)
140            tr = not self.area.collidepoint(newpos.topright)
141            bl = not self.area.collidepoint(newpos.bottomleft)
142            br = not self.area.collidepoint(newpos.bottomright)
143            # Kollisionen mit den Eckpunkten des Fensters werden
144            # berechnet und als boolescher Wert gespeichert
145            # (0 keine Kollision, 1 Kollision)
146
147            if tr and tl or (br and bl):
148            # Falls das Objekt mit dem oberen oder unteren
149            # Bildschirmrand kollidiert,
150                self.angle = -self.angle
151                self.changeColor()
152                # wird der Winkel (und damit die Richtung) umgekehrt
153                # und die Farbe verändert
154
155            if tl and bl or (tr and br):
156            # Falls das Objekt mit dem linken oder rechten
157            # Bildschirmrand kollidiert,
158                self.angle = math.pi - self.angle
159                self.changeColor()
160                # Wird der Winkel (und damit die Richtung) umgekehrt
161                # und die Farbe verändert
162
163        self.rect = newpos
164        # Ordnet dem Rectangle des Objekts die neue Position zu
165        # Die Veränderung der Position wird erst hier gültig!
166
167
168### Funktionsdefinitionen
169
170def end():
171    sys.exit(0)
172
173def game(events, screen, sprites):
174    for event in events:
175    # Wertet die Event-Warteschleife aus
176        if event.type == QUIT:
177            # Beendet das Programm, wenn z.B. das Fenster geschlossen wurde
178            end()
179            return
180        elif event.type == KEYDOWN and event.key == K_ESCAPE:
181            # Beendet das Programm, wenn die Taste Escape gedrückt wurde
182            end()
183            return
184        elif event.type == KEYDOWN and event.key == K_f:
185            # Schaltet in den Vollbildmodus, wenn die Taste F gedrückt wurde
186            pygame.display.toggle_fullscreen()
187            return
188
189    screen.fill()
190    # Füllt den Bildschirm
191
192    sprites.update()
193    # Bewegung und Kollisionserkennung der Sprite-Gruppe
194    # Die update-Funktion der Instanzen wird automatisch
195    # für alle 123 Rechtecke aufgerufen
196
197    sprites.draw(screen.screen)
198    # Zeichnet die Sprite-Instanzen auf den Bildschirm
199
200    pygame.display.update()
201    # Aktualisiert den Bildschirm
202
203
204def main():
205    pygame.init()
206
207    pygame.key.set_repeat(1, 1)
208    # Legt fest, wie oft Tastendrücke automatisch wiederholt werden
209    # Das erste Argument gibt an ab wann, das zweite in welchen
210    # Intervallen der Tastendruck wiederholt wird
211
212    clock = pygame.time.Clock()
213    # Erstellt einen Zeitnehmer
214
215    screen = Screen(cmdline=sys.argv)
216    # Erstellt eine Instanz der Klasse Screen()
217
218    movingSprites = []
219    for i in range(NUM_SPRITES):
220        movingSprites.append(Sprite(screen))
221    # Die for-Schleife erstellt 123 Instanzen der Klasse Sprite
222    # und fügt sie der Liste movingSprites hinzu
223
224    sprites = pygame.sprite.RenderPlain((movingSprites))
225    # Fasst die erstellen Sprite-Instanzen zu einer Gruppe zusammen
226    # um das Zeichnen der Sprites zu erleichtern
227
228    while True:
229        clock.tick(30)
230        # Verhindert, dass das Spiel zu schnell läuft
231
232        game(pygame.event.get(), screen, sprites)
233        # Ruft die Funktion game auf und übergibt ihr
234        # die Event-Warteschleife, die Zeichenfläche und die Objekte
235    end()
236
237main()
238