Bouncy is a class which demonstrates Bouncing rectangle animation which
options like resolution, bouncy rectangle size, speed. Whenever it
collides with the borders or wall it plays a sound. The code doesn't
have any Magic Numbers, everything has been named pretty well so that it
is readable to most and many error handling cases has been handled
(These being the reason that the code is long else it can be reduced).
How to use ?
Just initialize the class with the parameters. if you don't give any params a default value is taken.
Parameters :-
1. resolution : Takes a tuple of values for Screen Size like (800, 600). Default Value : (640, 480)
2. rectobj_size : Takes a tuple of values for rectangle object size like (40, 30). Default Value : (50, 50)
3. speed : Animation Speed. Min value 1
Example :-
Bouncy( ( 600, 400 ), ( 40, 40 ), 5 ) or Bouncy( resolution = ( 600, 400 ), rectobj_size = ( 40, 40 ), speed = 5 )
Code:
How to use ?
Just initialize the class with the parameters. if you don't give any params a default value is taken.
Download the Sound from here : https://mega.co.nz/#!45VTzKxK!vsx-IBhnGNEGvoZMSYdCod_ORMjsfEQ4YxcE3DW8Z28
Parameters :-
1. resolution : Takes a tuple of values for Screen Size like (800, 600). Default Value : (640, 480)
2. rectobj_size : Takes a tuple of values for rectangle object size like (40, 30). Default Value : (50, 50)
3. speed : Animation Speed. Min value 1
Example :-
Bouncy( ( 600, 400 ), ( 40, 40 ), 5 ) or Bouncy( resolution = ( 600, 400 ), rectobj_size = ( 40, 40 ), speed = 5 )
Code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Copyright (C) 2014 Animesh Shaw. All rights reserved. | |
Redistribution and use in source and binary forms, with or without modification, are | |
permitted provided that the following conditions are met: | |
1. Redistributions of source code must retain the above copyright notice, this list of | |
conditions and the following disclaimer. | |
2. Redistributions in binary form must reproduce the above copyright notice, this list | |
of conditions and the following disclaimer in the documentation and/or other materials | |
provided with the distribution. | |
THIS SOFTWARE IS PROVIDED BY Animesh Shaw ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR | |
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
""" | |
import os | |
import sys | |
import pygame | |
from pygame.constants import NOFRAME, K_ESCAPE, KEYUP | |
from pygame.mixer import Sound | |
class Bouncy: | |
def __init__(self, resolution=(640, 480), rectobj_size=(50, 50), speed=5): | |
pygame.init() | |
# Center the SDL Window on the Display Screen | |
os.environ['SDL_VIDEO_CENTERED'] = '1' | |
self.screen_depth = 32 | |
self.rCBack = (27, 27, 27) | |
self.border = (227, 227, 227) | |
self.rCRed = (227, 27, 27) | |
""" | |
Check is resolution parameter is supplied, if yes then check if its valid or not. | |
If the values are acceptable then it is accepted else ValueError Exception is raised. | |
""" | |
if type(resolution) is tuple and resolution is not None: | |
self.width, self.height = resolution | |
else: | |
raise ValueError("Tuple of Screen size (width, height) expected but found" + type(resolution)) | |
# Set the Display Screen Mode | |
self.screen = pygame.display.set_mode(resolution, NOFRAME, self.screen_depth) | |
# Set the Padding for both sides for rectangular border | |
self.pad = 10 | |
# Sets the thickness of the border | |
self.border_thickness = 3 | |
# Set the Framerate | |
self.fps = 30 | |
self.timer = pygame.time.Clock() | |
# Set the dimensions for rectangular border size | |
self.rect_border_size = (self.pad, self.pad, self.width - 2 * self.pad, | |
self.height - 2 * self.pad) | |
""" | |
Rectangular Object coordinates which will bounce. | |
Check is rectobj_size parameter is supplied, if yes then check if its valid or not. | |
If the values are acceptable then it is accepted else ValueError Exception is raised. | |
""" | |
if type(rectobj_size) is tuple and rectobj_size is not None: | |
self.rectx, self.recty = self.pad + self.border_thickness, self.pad + self.border_thickness | |
self.rect_width, self.rect_height = rectobj_size | |
else: | |
raise ValueError("Tuple of RectObject size (width, height) expected but found" + type(rectobj_size)) | |
""" | |
Check if the speed supplied is valid or not. Minimum value is 1. if Conditions are | |
not met a ValueError Exception is raised. | |
""" | |
if type(speed) == int and speed is not None and speed > 1: | |
self.speed = speed | |
else: | |
raise ValueError("Speed must be int and greater than 0 but found " + type(speed)) | |
# Draw the rectangle which will bounce | |
pygame.draw.rect(self.screen, self.rCRed, (self.rectx, self.recty, self.rect_width, self.rect_height)) | |
# Initially fill the background and initialize other variables. | |
self.fill_background() | |
# Start the main game loop. | |
self.__game_loop() | |
def __game_loop(self): | |
# Create a sound object with a music file to play when the object hits | |
sound = Sound("resources/sounds/hitwall.wav") | |
speedx, speedy = self.speed, self.speed | |
# Inner Function to Play sound when object collides with wall | |
def play_sound(): | |
sound.play(1) | |
# Values from where the object will return after collision | |
bottom_collision_offset = self.rect_bounce_area.bottom - self.rect_height - self.border_thickness | |
right_collision_offset = self.rect_bounce_area.right - self.rect_width - self.border_thickness | |
# Main game loop | |
while True: | |
for event in pygame.event.get(): | |
if event.type == KEYUP and event.key == K_ESCAPE: | |
pygame.quit() | |
sys.exit() | |
self.fill_background() | |
pygame.draw.rect(self.screen, self.rCRed, (self.rectx, self.recty, self.rect_width, self.rect_height)) | |
self.rectx += speedx | |
self.recty += speedy | |
# Check for wall collision. | |
if self.recty > bottom_collision_offset or self.recty < (self.pad + self.border_thickness): | |
speedy *= -1 | |
play_sound() | |
if self.rectx > right_collision_offset or self.rectx < (self.pad + self.border_thickness): | |
speedx *= -1 | |
play_sound() | |
pygame.display.update() | |
self.timer.tick(self.fps) | |
# Fill the background wil color and the border | |
def fill_background(self): | |
self.screen.fill(self.rCBack) | |
self.rect_bounce_area = pygame.draw.rect(self.screen, self.border, | |
self.rect_border_size, self.border_thickness) | |
def main(): | |
Bouncy(resolution=(600, 400), rectobj_size=(40, 40), speed=2) | |
if __name__ == '__main__': | |
main() |