IndieBrosCEO / Tetrahedron

This is the Final Project for P5 AP Computer science Principles
0 stars 1 forks source link

platforming sample #4

Open Descrates opened 6 years ago

Descrates commented 6 years ago

import os import sys import random import pygame as pg

CAPTION = "Basic Platforming: Pixel Perfect Collision" SCREEN_SIZE = (700, 500) BACKGROUND_COLOR = (50, 50, 50)

class _Physics(object): """ A simplified physics class. Using a 'real' gravity function here, though it is questionable whether or not it is worth the effort. Compare to the effect of gravity in fall_rect and decide for yourself. """ def init(self): """You can experiment with different gravity here.""" self.x_vel = self.y_vel = self.y_vel_i = 0 self.grav = 20 self.fall = False self.time = None

def physics_update(self):
    """If the player is falling, calculate current y velocity."""
    if self.fall:
        time_now = pg.time.get_ticks()
        if not self.time:
            self.time = time_now
        self.y_vel = self.grav*((time_now-self.time)/1000.0)+self.y_vel_i
    else:
        self.time = None
        self.y_vel = self.y_vel_i = 0

class Player(_Physics, pg.sprite.Sprite): """Class representing our player.""" def init(self,location,speed): """ The location is an (x,y) coordinate pair, and speed is the player's speed in pixels per frame. Speed should be an integer. """ _Physics.init(self) pg.sprite.Sprite.init(self) self.image = PLAYER_IMAGE self.mask = pg.mask.from_surface(self.image) self.speed = speed self.jump_power = 10 self.rect = self.image.get_rect(topleft=location)

def get_position(self, obstacles):
    """Calculate the player's position this frame, including collisions."""
    if not self.fall:
        self.check_falling(obstacles)
    else:
        self.fall = self.check_collisions((0,self.y_vel), 1, obstacles)
    if self.x_vel:
        self.check_collisions((self.x_vel,0), 0, obstacles)

def check_falling(self, obstacles):
    """If player is not contacting the ground, enter fall state."""
    self.rect.move_ip((0,1))
    collisions = pg.sprite.spritecollide(self, obstacles, False)
    collidable = pg.sprite.collide_mask
    if not pg.sprite.spritecollideany(self, collisions, collidable):
        self.fall = True
    self.rect.move_ip((0,-1))

def check_collisions(self, offset, index, obstacles):
    """
    This function checks if a collision would occur after moving offset
    pixels.  If a collision is detected position is decremented by one
    pixel and retested. This continues until we find exactly how far we can
    safely move, or we decide we can't move.
    """
    unaltered = True
    self.rect.move_ip(offset)
    collisions = pg.sprite.spritecollide(self, obstacles, False)
    collidable = pg.sprite.collide_mask
    while pg.sprite.spritecollideany(self, collisions, collidable):
        self.rect[index] += (1 if offset[index]<0 else -1)
        unaltered = False
    return unaltered

def check_keys(self, keys):
    """Find the player's self.x_vel based on currently held keys."""
    self.x_vel = 0
    if keys[pg.K_LEFT] or keys[pg.K_a]:
        self.x_vel -= self.speed
    if keys[pg.K_RIGHT] or keys[pg.K_d]:
        self.x_vel += self.speed

def jump(self):
    """Called when the user presses the jump button."""
    if not self.fall:
        self.y_vel_i = -self.jump_power
        self.fall = True

def update(self, obstacles, keys):
    """Everything we need to stay updated."""
    self.check_keys(keys)
    self.get_position(obstacles)
    self.physics_update()

def draw(self,surface):
    """Blit the player to the target surface."""
    surface.blit(self.image, self.rect)

class Block(pg.sprite.Sprite): """A class representing solid obstacles.""" def init(self, location): """The location argument is an (x,y) coordinate pair.""" pg.sprite.Sprite.init(self) self.make_image() self.mask = pg.mask.from_surface(self.image) self.rect = pg.Rect(location, (50,50))

def make_image(self):
    """Something pretty to look at."""
    color = [random.randint(0,255) for _ in range(3)]
    self.image = pg.Surface((50,50)).convert_alpha()
    self.image.fill(color)
    self.image.blit(SHADE_IMG, (0,0))

class Control(object): """Class for managing event loop and game states.""" def init(self): """Nothing to see here folks. Move along.""" self.screen = pg.display.get_surface() self.clock = pg.time.Clock() self.fps = 60.0 self.keys = pg.key.get_pressed() self.done = False self.player = Player((50,-25), 4) self.obstacles = self.make_obstacles()

def make_obstacles(self):
    """Adds some arbitrarily placed obstacles to a sprite.Group."""
    obstacles = [Block((400,400)), Block((300,270)), Block((150,170))]
    obstacles += [Block((500+50*i,220)) for i in range(3)]
    for i in range(12):
        obstacles.append(Block((50+i*50,450)))
        obstacles.append(Block((100+i*50,0)))
        obstacles.append(Block((0,50*i)))
        obstacles.append(Block((650,50*i)))
    return pg.sprite.Group(obstacles)

def event_loop(self):
    """We can always quit, and the player can sometimes jump."""
    for event in pg.event.get():
        if event.type == pg.QUIT or self.keys[pg.K_ESCAPE]:
            self.done = True
        elif event.type == pg.KEYDOWN:
            if event.key == pg.K_SPACE:
                self.player.jump()

def update(self):
    """Update held keys and the player."""
    self.keys = pg.key.get_pressed()
    self.player.update(self.obstacles, self.keys)

def draw(self):
    """Draw all necessary objects to the display surface."""
    self.screen.fill(BACKGROUND_COLOR)
    self.obstacles.draw(self.screen)
    self.player.draw(self.screen)

def display_fps(self):
    """Show the programs FPS in the window handle."""
    caption = "{} - FPS: {:.2f}".format(CAPTION, self.clock.get_fps())
    pg.display.set_caption(caption)

def main_loop(self):
    """As simple as it gets."""
    while not self.done:
        self.event_loop()
        self.update()
        self.draw()
        pg.display.update()
        self.clock.tick(self.fps)
        self.display_fps()

if name == "main": os.environ['SDL_VIDEO_CENTERED'] = '1' pg.init() pg.display.set_caption(CAPTION) pg.display.set_mode(SCREEN_SIZE) PLAYER_IMAGE = pg.image.load("smallface.png").convert_alpha() SHADE_IMG = pg.image.load("shader.png").convert_alpha() run_it = Control() run_it.main_loop() pg.quit() sys.exit()