ThePythonGameBook

learn Python. Create Games

User Tools

Site Tools


en:pygame:step005

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
en:pygame:step005 [2020/05/03 21:35]
Horst JENS ↷ Links adapted because of a move operation
en:pygame:step005 [2020/05/15 22:39] (current)
Horst JENS
Line 108: Line 108:
 with the "​%%//​%%"​ operator to truncate the quotients and return integers, rather than floating point numbers. And remember that print is now a function. with the "​%%//​%%"​ operator to truncate the quotients and return integers, rather than floating point numbers. And remember that print is now a function.
  
-//click reload in your browser if you see no code here:// +<code python>​ 
-<​html>​ +#!/usr/bin/env python 
- <​script src="​http://​gist-it.appspot.com/github/​horstjens/​ThePythonGameBook/​blob/​master/​pygame/​005_frame_based_movement.py">​ +"""​ 
- </script><​/html>+005_bouncing_ball_frame_based.py 
 +bouncing ball and pulsating circle 
 +url: http://thepythongamebook.com/en:part2:pygame:step005 
 +author: horst.jens@spielend-programmieren.at 
 +licence: gpl, see http://www.gnu.org/​licenses/​gpl.html
  
 +works with python3.4 and python2.7
 +
 +bouncing ball. each frame the complete screen is filled with the background,
 +making this example simple to code but possible slow on larger resolutions.
 +Each frame, a random-coloured circle is drawn with randomized radius directly on the screen.
 +Try to manipulate the display.set_mode values to change the resolution."""​
 +#the next line is only needed for python2.x and not necessary for python3.x
 +from __future__ import print_function,​ division
 +import pygame
 +import random
 +pygame.init()
 +screen=pygame.display.set_mode((640,​480),​) # try out larger values and see what happens !
 +screenrect = screen.get_rect()
 +# ------ constants ------------
 +clock = pygame.time.Clock()
 +mainloop = True
 +FPS = 30 # desired framerate in frames per second. ​
 +playtime = 0
 +radius = 50 # for pulsating circle
 +dr = 1  # change of radius in pixel per frame
 +# ------- background ---------
 +background = pygame.Surface(screen.get_size())
 +background.fill((255,​155,​155)) ​    #fill the background white (red,​green,​blue)
 +background = background.convert()
 +screen.blit(background,​ (0,​0)) ​    #draw background on screen (overwriting all)
 +# -------- bouncing ball surface ---------
 +ballsurface = pygame.Surface((50,​50)) ​    #​create a new surface (black by default)
 +ballsurface.set_colorkey((0,​0,​0)) ​        #make black the transparent color (red,​green,​blue)
 +#​pygame.draw.circle(Surface,​ color, pos, radius, width=0)
 +pygame.draw.circle(ballsurface,​ (100,​175,​81),​ (25,25),25) # paint blue circle
 +ballsurface = ballsurface.convert_alpha() ​      # if you use tranparent colors you need convert_alpha()
 +ballrect = ballsurface.get_rect() # the rectangle of the ball surface, for collision detection
 +ballx, bally = 550, 240           # start position of the ball (x,y)
 +dx = 10                 # x speed vector of the ball in pixel per frame            ​
 +dy = 0                 # y speed vector of the ball in pixel per frame
 +# ----------- bouncing ball (drawing) ------
 +x1 = 50
 +y1 = 200
 +dx1 = 7
 +dy1 = 0
 +radius1 = 40
 +# --------- static big blue ball -----------
 +pygame.draw.circle(background,​ (0,0,200), (screenrect.width//​2,​ screenrect.height//​2),​ screenrect.width//​3)
 +# --------- mainloop ----------
 +while mainloop:
 +    # do all this each frame
 +    milliseconds = clock.tick(FPS) # do not go faster than this framerate
 +    playtime += milliseconds / 1000.0
 +    for event in pygame.event.get():​
 +        if event.type == pygame.QUIT:​
 +            mainloop = False # pygame window closed by user
 +        elif event.type == pygame.KEYDOWN:​
 +            if event.key == pygame.K_ESCAPE:​
 +                mainloop = False # user pressed ESC
 +    pygame.display.set_caption("​FPS:​ %.2f X: %.2f Y: %.2f dx: %.2f dy:"
 +                               "​ %.2f" % (clock.get_fps(),​ ballx, bally, dx, dy))
 +    # ----- clean screen ----------
 +    screen.blit(background,​ (0,​0)) ​    #draw background on screen (overwriting all)
 +    # ------- bouncing ball (drawing) ---------
 +    x1 += dx1
 +    if x1 + radius1 >= screenrect.width:​
 +        x1 = screenrect.width - radius1
 +        dx1 *= -1
 +    elif x1 - radius1 <= 0:
 +        x1 =  radius1
 +        dx1 *= -1
 +    pygame.draw.circle(screen,​ (255,​255,​0),​ (x1,y1), radius1)
 +    # -------- bouncing ball surface ----------
 +    ballx += dx
 +    bally += dy 
 +    if ballx < 0: # bounce ball if out of screen
 +        ballx = 0
 +        dx *= -1 
 +    elif ballx + ballrect.width > screenrect.width:​
 +        ballx = screenrect.width - ballrect.width
 +        dx *= -1
 +    screen.blit(ballsurface,​ (round(ballx,​0),​ round(bally,​0))) ​   ​
 +    # ----- pulsating circle -----------
 +    colour = (random.randint(0,​255),​random.randint(0,​255),​random.randint(0,​255))
 +    if radius >100 or radius < 5:
 +        dr *= -1
 +    radius += dr
 +    pygame.draw.circle(screen,​ colour , (100,100), radius, 2) # draw pulsating circle
 +    # --------- flip screen ------------------
 +    pygame.display.flip() ​         # flip the screen FPS times a second
 +print("​This '​game'​ was played for {:.2f} seconds."​.format(playtime))
 +
 +</​code>​
  
 ==== Pretty Version ==== ==== Pretty Version ====
Line 122: Line 214:
   * https://​github.com/​horstjens/​ThePythonGameBook/​blob/​master/​pygame/​005_frame_based_movement_pretty.py   * https://​github.com/​horstjens/​ThePythonGameBook/​blob/​master/​pygame/​005_frame_based_movement_pretty.py
  
-//click reload in your browser if you see no code here:// + 
-<​html>​ +<code python>​ 
- <script src="​http://​gist-it.appspot.com/github/horstjens/ThePythonGameBook/blob/master/pygame/​005_frame_based_movement_pretty.py">​ +#!/usr/bin/env python 
- </script></html>+ 
 +"""​ 
 +Name   : blit_pulse2.py 
 +URL    : http://thepythongamebook.com/en:​part2:​pygame:​step003 
 +Author : yipyip 
 +Licence: gpl, see http://www.gnu.org/licenses/gpl.html 
 + 
 +works with pyhton3.4 and python2.7 
 +"""​ 
 + 
 +#### 
 + 
 +import ​pygame ​as pyg 
 +import random as rand 
 + 
 +#### 
 + 
 +def random_rgb():​ 
 +     
 +   ​return rand.randint(0, 255), rand.randint(0,​255),​ rand.randint(0,​ 255) 
 + 
 +#### 
 + 
 +class PygView(object):​ 
 + 
 +   
 +    def __init__(self,​ width=800, height=600, fps=50): 
 +        ​"""​Initializing background surface for static drawing 
 +           and screen surface for dynamic drawing  
 +        """​ 
 +        pyg.init() 
 +        pyg.display.set_caption("​Press ESC to quit"​) 
 +         
 +        self.width = width 
 +        self.height = height 
 +         
 +        self.screen = pyg.display.set_mode((self.width,​ self.height),​ pyg.DOUBLEBUF) 
 +        self.background = pyg.Surface(self.screen.get_size()).convert() ​  
 +        # white blackground 
 +        self.background.fill((255,​ 255, 255)) 
 + 
 +        self.act_surface = self.screen 
 +        self.act_rgb = 255, 0, 0 
 + 
 +         
 +    def draw_static(self):​ 
 + 
 +        self.act_surface = self.background 
 + 
 + 
 +    def draw_dynamic(self):​ 
 + 
 +        self.act_surface = self.screen 
 + 
 + 
 +    def set_color(self,​ rgb): 
 + 
 +        self.act_rgb = rgb 
 + 
 +         
 +    def circle(self,​ x, y, radius, width): 
 +        """​Allocate surface for blitting and draw circle 
 +        """​ 
 +        rad2 = 2 * radius 
 +        surface = pyg.Surface((rad2,​ rad2)) 
 +        pyg.draw.circle(surface,​ self.act_rgb,​ (radius, radius), radius, width) 
 +        surface.set_colorkey((0,​ 0, 0)) 
 +        self.act_surface.blit(surface.convert_alpha(),​ (x, y)) 
 + 
 + 
 +    def run(self, draw_dynamic):​ 
 +        """​The mainloop 
 +        """​ 
 +        running = True 
 +        while running: 
 +            for event in pyg.event.get():​ 
 +                if event.type == pyg.QUIT: 
 +                    running = False  
 +                elif event.type == pyg.KEYDOWN:​ 
 +                    if event.key == pyg.K_ESCAPE:​ 
 +                        running = False 
 + 
 +            draw_dynamic() 
 +            pyg.display.flip() 
 +            self.screen.blit(self.background,​ (0, 0)) 
 +             
 +        pyg.quit() 
 + 
 +#### 
 + 
 +class Ball(object):​ 
 +    """​A circle object with no hardcoded dependency on pygame 
 +       (and other libs too, obviously...) 
 +    """​ 
 +    def __init__(self,​ x, y, radius, speed_x=1, speed_pulse=0,​ color=(0,​0,​255),​ width=0): 
 + 
 +        self.x = x 
 +        self.y = y 
 +        self.radius = radius 
 +        self.act_radius = radius 
 +        self.speed_x = speed_x 
 +        self.speed_pulse = speed_pulse 
 +        self.color = color 
 +        self.width = width 
 +        self.shrinking = True 
 + 
 + 
 +    @property 
 +    def max_x(self):​ 
 + 
 +        return self.x + self.radius * 2 
 +     
 +         
 +    def rel_move(self,​ dx, dy): 
 + 
 +        self.x += dx 
 +        self.y += dy 
 + 
 + 
 +    def pulse(self):​ 
 +        """​Shrink or expand ball 
 +        """​ 
 +        if not self.speed_pulse:​ 
 +            return 
 + 
 +        # balls are shrinking first  
 +        if self.shrinking:​ 
 +            if self.act_radius ​self.width: 
 +                ​self.act_radius -= self.speed_pulse 
 +                self.act_radius = max(self.act_radius,​ self.width) 
 +            else: 
 +                self.shrinking = False 
 +        else: 
 +            if self.act_radius ​self.radius:​ 
 +                self.act_radius += self.speed_pulse 
 +            else: 
 +                self.shrinking = True 
 +         
 +         
 +    def draw(self, view): 
 +        """​ Draw on a device with an appropriate interface 
 +        """​ 
 +        if self.speed_pulse:​ 
 +            color = random_rgb() 
 +        else: 
 +            color = self.color  
 +        view.set_color(color) 
 +        view.circle(self.x,​ self.y, self.act_radius,​ self.width) 
 +      
 +#### 
 + 
 +def action(balls,​ width, view): 
 +    """​ Return a function for the pygame mainloop 
 +    """​ 
 +    # balls move to the right first  
 +    right_moving = [True] * len(balls) 
 + 
 +    def animate_balls():​ 
 +        """​ Draw moving balls 
 +        """​ 
 +        for i, ball in enumerate(balls):​ 
 +            if right_moving[i]:​ 
 +                if ball.max_x < width: 
 +                    ball.rel_move(ball.speed_x,​ 0) 
 +                else: 
 +                    right_moving[i] = False 
 +            else: 
 +                if ball.x ​0: 
 +                    ball.rel_move(-ball.speed_x,​ 0) 
 +                else: 
 +                    right_moving[i] = True 
 +             
 +            ball.pulse()  
 +            ball.draw(view) 
 + 
 +    return animate_balls ​    
 +         
 +#### 
 + 
 +def main(width):​ 
 +    """​Simple example with stationary and moving balls 
 +    """ ​   
 +    view = PygView(width) 
 +     
 +    view.draw_static() 
 +    # args:  x, y, radius, speed_x, speed_pulse,​ color, border_width 
 +    # border_width <= radius ! 
 +    ball01 = Ball(50, 60, 50, 0, 0, (255, 255, 0)) 
 +    ball01.draw(view) 
 +    ball02 = Ball(250, 150, 190, 0, 0, (66, 1, 166)) 
 +    ball02.draw(view) 
 + 
 +    view.draw_dynamic() 
 +    ball1 = Ball(15, 130, 100, 1, 0, (255, 0, 0)) 
 +    ball2 = Ball(25, 200, 80, 2, 0, (0, 255, 155)) 
 +    ball3 = Ball(20, 220, 110, 1, 1, (100, 55, 155)) 
 +    ball4 = Ball(20, 400, 70, 3, 0, (250, 100, 255)) 
 +    ball5 = Ball(90, 390, 70, 0, 1, (250, 100, 255), 1) 
 + 
 +    loopfunc = action((ball1,​ ball2, ball4, ball5), width, view) 
 +    view.run(loopfunc) 
 + 
 +#### 
 +     
 +if __name__ == '​__main__':​ 
 + 
 +    main(900) 
 +     
 + 
 +</code> 
  
 ^ [[:​en:​pygame:​step004| ← previous]] ^ [[en:​pygame:​start| ↑ Overview]] ^ [[:​en:​pygame:​step006| → next ]] ^ ^ [[:​en:​pygame:​step004| ← previous]] ^ [[en:​pygame:​start| ↑ Overview]] ^ [[:​en:​pygame:​step006| → next ]] ^
  
 ====== Comment this Ptage ====== ====== Comment this Ptage ======
-~~DISQUS~~+
  
/var/www/horst/thepythongamebook.com/data/pages/en/pygame/step005.txt · Last modified: 2020/05/15 22:39 by Horst JENS