PythonArellanoPyGameSeries

From Wiki

Jump to: navigation, search

delererlipas This is the support page for Chuck Arellano's Writing Arinoid using pyGame series.

Contents

Making a Barebones pyGame Program

#
# scriptedfun.com
#
# Screencast #1
# Barebones Pygame Application
#

import pygame
from pygame.locals import *

SCREENRECT = Rect(0, 0, 640, 480)

def main():
    pygame.init()

    screen = pygame.display.set_mode(SCREENRECT.size)

    # make background
    background = pygame.Surface(SCREENRECT.size).convert()
    background.fill((0, 0, 255))
    screen.blit(background, (0, 0))
    pygame.display.update()

    # keep track of sprites
    all = pygame.sprite.RenderUpdates()

    # keep track of time
    clock = pygame.time.Clock()

    # game loop
    while 1:

        # get input
        for event in pygame.event.get():
            if event.type == QUIT   \
               or (event.type == KEYDOWN and    \
                   event.key == K_ESCAPE):
                return

        # clear sprites
        all.clear(screen, background)

        # update sprites
        all.update()

        # redraw sprites
        dirty = all.draw(screen)
        pygame.display.update(dirty)

        # maintain frame rate
        clock.tick(30)

if __name__ == '__main__': main()

Using Sprite Sheets and Drawing the Background

#
# scriptedfun.com
#
# Screencast #2
# Arinoid - Using Sprite Sheets and Drawing the Background
#

import os, pygame
from pygame.locals import *

SCREENRECT = Rect(0, 0, 640, 480)

class Spritesheet:
    def __init__(self, filename):
        self.sheet = pygame.image.load(os.path.join('data', filename)).convert()
    def imgat(self, rect, colorkey = None):
        rect = Rect(rect)
        image = pygame.Surface(rect.size).convert()
        image.blit(self.sheet, (0, 0), rect)
        if colorkey is not None:
            if colorkey is -1:
                colorkey = image.get_at((0, 0))
            image.set_colorkey(colorkey, RLEACCEL)
        return image
    def imgsat(self, rects, colorkey = None):
        imgs = []
        for rect in rects:
            imgs.append(self.imgat(rect, colorkey))
        return imgs

class Arena:
    tileside = 31
    numxtiles = 12
    numytiles = 14
    topx = (SCREENRECT.width - SCREENRECT.width/tileside*tileside)/2
    topy = (SCREENRECT.height - SCREENRECT.height/tileside*tileside)/2
    rect = Rect(topx + tileside, topy + tileside, tileside*numxtiles, tileside*numytiles)
    def __init__(self):
        self.background = pygame.Surface(SCREENRECT.size).convert()
    def drawtile(self, tile, x, y):
        self.background.blit(tile, (self.topx + self.tileside*x,    \
                                    self.topy + self.tileside*y))
    def makebg(self, tilenum):
        for x in range(self.numxtiles):
            for y in range(self.numytiles):
                self.drawtile(self.tiles[tilenum], x + 1, y + 1)

def main():
    pygame.init()

    screen = pygame.display.set_mode(SCREENRECT.size)

    spritesheet = Spritesheet('arinoid_master.bmp')

    Arena.tiles = spritesheet.imgsat([(129, 321, 31, 31),   # purple - 0
                                      (161, 321, 31, 31),   # dark blue - 1
                                      (129, 353, 31, 31),   # red - 2
                                      (161, 353, 31, 31),   # green - 3
                                      (129, 385, 31, 31)])  # blue - 4

    # make background
    arena = Arena()
    arena.makebg(0) # you may change the background color here
    screen.blit(arena.background, (0, 0))
    pygame.display.update()

    # keep track of sprites
    all = pygame.sprite.RenderUpdates()

    # keep track of time
    clock = pygame.time.Clock()

    # game loop
    while 1:

        # get input
        for event in pygame.event.get():
            if event.type == QUIT   \
               or (event.type == KEYDOWN and    \
                   event.key == K_ESCAPE):
                return

        # clear sprites
        all.clear(screen, arena.background)

        # update sprites
        all.update()

        # redraw sprites
        dirty = all.draw(screen)
        pygame.display.update(dirty)

        # maintain frame rate
        clock.tick(30)

if __name__ == '__main__': main()


Arinoid - The Paddle

#
# scriptedfun.com
#
# Screencast #3
# Arinoid - The Paddle
#

import os, pygame
from pygame.locals import *

SCREENRECT = Rect(0, 0, 640, 480)

def paddleimage(spritesheet):
    paddle = pygame.Surface((55, 11)).convert()
    # left half
    paddle.blit(spritesheet.imgat((261, 143, 27, 11)), (0, 0))
    # right half
    paddle.blit(spritesheet.imgat((289, 143, 28, 11)), (27, 0))
    paddle.set_colorkey(paddle.get_at((0, 0)), RLEACCEL)
    return paddle

class Spritesheet:
    def __init__(self, filename):
        self.sheet = pygame.image.load(os.path.join('data', filename)).convert()
    def imgat(self, rect, colorkey = None):
        rect = Rect(rect)
        image = pygame.Surface(rect.size).convert()
        image.blit(self.sheet, (0, 0), rect)
        if colorkey is not None:
            if colorkey is -1:
                colorkey = image.get_at((0, 0))
            image.set_colorkey(colorkey, RLEACCEL)
        return image
    def imgsat(self, rects, colorkey = None):
        imgs = []
        for rect in rects:
            imgs.append(self.imgat(rect, colorkey))
        return imgs

class Arena:
    tileside = 31
    numxtiles = 12
    numytiles = 14
    topx = (SCREENRECT.width - SCREENRECT.width/tileside*tileside)/2
    topy = (SCREENRECT.height - SCREENRECT.height/tileside*tileside)/2
    rect = Rect(topx + tileside, topy + tileside, tileside*numxtiles, tileside*numytiles)
    def __init__(self):
        self.background = pygame.Surface(SCREENRECT.size).convert()
    def drawtile(self, tile, x, y):
        self.background.blit(tile, (self.topx + self.tileside*x,    \
                                    self.topy + self.tileside*y))
    def makebg(self, tilenum):
        for x in range(self.numxtiles):
            for y in range(self.numytiles):
                self.drawtile(self.tiles[tilenum], x + 1, y + 1)

class Paddle(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.rect = self.image.get_rect()
        self.rect.bottom = self.arena.rect.bottom - self.arena.tileside
    def update(self):
        self.rect.centerx = pygame.mouse.get_pos()[0]
        self.rect.clamp_ip(self.arena.rect)

def main():
    pygame.init()

    screen = pygame.display.set_mode(SCREENRECT.size)

    spritesheet = Spritesheet('arinoid_master.bmp')

    Arena.tiles = spritesheet.imgsat([(129, 321, 31, 31),   # purple - 0
                                      (161, 321, 31, 31),   # dark blue - 1
                                      (129, 353, 31, 31),   # red - 2
                                      (161, 353, 31, 31),   # green - 3
                                      (129, 385, 31, 31)])  # blue - 4

    Paddle.image = paddleimage(spritesheet)

    # make background
    arena = Arena()
    arena.makebg(0) # you may change the background color here
    screen.blit(arena.background, (0, 0))
    pygame.display.update()

    Paddle.arena = arena

    # keep track of sprites
    all = pygame.sprite.RenderUpdates()

    Paddle.containers = all

    # keep track of time
    clock = pygame.time.Clock()

    paddle = Paddle()

    # game loop
    while 1:

        # get input
        for event in pygame.event.get():
            if event.type == QUIT   \
               or (event.type == KEYDOWN and    \
                   event.key == K_ESCAPE):
                return

        # clear sprites
        all.clear(screen, arena.background)

        # update sprites
        all.update()

        # redraw sprites
        dirty = all.draw(screen)
        pygame.display.update(dirty)

        # maintain frame rate
        clock.tick(30)

if __name__ == '__main__': main()

Arinoid - Ball Physics

#
# scriptedfun.com
#
# Screencast #4
# Arinoid - The Ball
#

import math, os, pygame
from pygame.locals import *

SCREENRECT = Rect(0, 0, 640, 480)

def paddleimage(spritesheet):
    paddle = pygame.Surface((55, 11)).convert()
    # left half
    paddle.blit(spritesheet.imgat((261, 143, 27, 11)), (0, 0))
    # right half
    paddle.blit(spritesheet.imgat((289, 143, 28, 11)), (27, 0))
    paddle.set_colorkey(paddle.get_at((0, 0)), RLEACCEL)
    return paddle

class Spritesheet:
    def __init__(self, filename):
        self.sheet = pygame.image.load(os.path.join('data', filename)).convert()
    def imgat(self, rect, colorkey = None):
        rect = Rect(rect)
        image = pygame.Surface(rect.size).convert()
        image.blit(self.sheet, (0, 0), rect)
        if colorkey is not None:
            if colorkey is -1:
                colorkey = image.get_at((0, 0))
            image.set_colorkey(colorkey, RLEACCEL)
        return image
    def imgsat(self, rects, colorkey = None):
        imgs = []
        for rect in rects:
            imgs.append(self.imgat(rect, colorkey))
        return imgs

class Arena:
    tileside = 31
    numxtiles = 12
    numytiles = 14
    topx = (SCREENRECT.width - SCREENRECT.width/tileside*tileside)/2
    topy = (SCREENRECT.height - SCREENRECT.height/tileside*tileside)/2
    rect = Rect(topx + tileside, topy + tileside, tileside*numxtiles, tileside*numytiles)
    def __init__(self):
        self.background = pygame.Surface(SCREENRECT.size).convert()
    def drawtile(self, tile, x, y):
        self.background.blit(tile, (self.topx + self.tileside*x,    \
                                    self.topy + self.tileside*y))
    def makebg(self, tilenum):
        for x in range(self.numxtiles):
            for y in range(self.numytiles):
                self.drawtile(self.tiles[tilenum], x + 1, y + 1)

class Paddle(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.rect = self.image.get_rect()
        self.rect.bottom = self.arena.rect.bottom - self.arena.tileside
    def update(self):
        self.rect.centerx = pygame.mouse.get_pos()[0]
        self.rect.clamp_ip(self.arena.rect)

class Ball(pygame.sprite.Sprite):
    speed = 5
    angleleft = 135
    angleright = 45
    def __init__(self):
        pygame.sprite.Sprite.__init__(self, self.containers)
        self.rect = self.image.get_rect()
        self.update = self.start
    def start(self):
        self.rect.centerx = self.paddle.rect.centerx
        self.rect.bottom = self.paddle.rect.top
        if pygame.mouse.get_pressed()[0] == 1:
            self.setfp()
            self.dx = 0
            self.dy = 1
            self.update = self.move
    def setfp(self):
        self.fpx = float(self.rect.centerx)
        self.fpy = float(self.rect.centery)
    def setint(self):
        self.rect.centerx = int(self.fpx)
        self.rect.centery = int(self.fpy)
    def move(self):
        #
        # Ball-Paddle Physics
        # - there are 2 extreme ball-paddle
        #   collision scenarios:
        #
        #
        # Scenario 1 - right edge
        #
        #            bbb
        #   pppppppppp
        #
        # - in this scenario, the left edge
        #   of the ball is at paddle.rect.right
        #
        #
        # Scenario 2 - left edge
        #
        # bbb
        #   pppppppppp
        #
        # - here, the left edge of the ball is
        #   (ball.rect.width - 1) units away from
        #   the paddle.rect.left, which means that
        #   the left edge of the ball is at
        #   (paddle.rect.left - (ball.rect.width - 1))
        #
        #
        # Hence, we want the linear function that
        # will determine the ball angle to contain
        # (paddle.rect.right, angler) and
        # (paddle.rect.left - (ball.rect.width - 1), anglel).
        #
        if self.rect.colliderect(self.paddle.rect) and self.dy > 0:
            x1 = self.paddle.rect.right
            y1 = self.angleright
            x2 = self.paddle.rect.left - (self.rect.width - 1)
            y2 = self.angleleft
            x = self.rect.left
            m = float(y2 - y1)/(x2 - x1)
            y = m*(x - x1) + y1
            angle = math.radians(y)
            self.dx = self.speed*math.cos(angle)
            self.dy = -self.speed*math.sin(angle)

        self.fpx = self.fpx + self.dx
        self.fpy = self.fpy + self.dy
        self.setint()

        if not self.arena.rect.contains(self.rect):
            if self.rect.bottom > self.arena.rect.bottom:
                self.kill()
            else:
                if self.rect.left < self.arena.rect.left or \
                   self.rect.right > self.arena.rect.right:
                    self.dx = -self.dx
                if self.rect.top < self.arena.rect.top:
                    self.dy = -self.dy
                self.rect.clamp_ip(self.arena.rect)
                self.setfp()

def main():
    pygame.init()

    screen = pygame.display.set_mode(SCREENRECT.size)

    spritesheet = Spritesheet('arinoid_master.bmp')

    Arena.tiles = spritesheet.imgsat([(129, 321, 31, 31),   # purple - 0
                                      (161, 321, 31, 31),   # dark blue - 1
                                      (129, 353, 31, 31),   # red - 2
                                      (161, 353, 31, 31),   # green - 3
                                      (129, 385, 31, 31)])  # blue - 4

    Paddle.image = paddleimage(spritesheet)
    Ball.image = spritesheet.imgat((428, 300, 11, 11), -1)

    # make background
    arena = Arena()
    arena.makebg(0) # you may change the background color here
    screen.blit(arena.background, (0, 0))
    pygame.display.update()

    Paddle.arena = arena
    Ball.arena = arena

    # keep track of sprites
    balls = pygame.sprite.Group()
    all = pygame.sprite.RenderUpdates()

    Paddle.containers = all
    Ball.containers = all, balls

    # keep track of time
    clock = pygame.time.Clock()

    paddle = Paddle()

    Ball.paddle = paddle

    # game loop
    while 1:

        # get input
        for event in pygame.event.get():
            if event.type == QUIT   \
               or (event.type == KEYDOWN and    \
                   event.key == K_ESCAPE):
                return

        # clear sprites
        all.clear(screen, arena.background)

        # update sprites
        all.update()
        if not balls:
            Ball()

        # redraw sprites
        dirty = all.draw(screen)
        pygame.display.update(dirty)

        # maintain frame rate
        clock.tick(60)

if __name__ == '__main__': main()
Personal tools