The Python Game Book

code games. learn Python.

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 ↷ Links adapted because of a move operation
en:pygame:step005 [2020/05/15 22:39] (current)
horst
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~~+
  
en/pygame/step005.txt · Last modified: 2020/05/15 22:39 by horst