Python Forum
[PyGame] Spawning platforms that don't touch
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Spawning platforms that don't touch
#10
Don't know any video tutorials. Just what I see people use.

I learn form this forum and docs. Using internet looking up specific question.
How I learn form this forum. Was answer questions but not post it. See what other people answer where.
  1. I learn to be explicit. I normally avoid abbreviation. Just make program harder to read.
  2. Pygame Rect are very powerful. They work great for placement and layouts.
  3. Pygame Vector2 will help reduce math and make it bit simpler once learn.
  4. Learn to pass images. This reference them.
  5. Learn to refactor code. Having one class handle multiply things. It just get messy.
  6. Learn to build a boiler plate. Just lets me code quickly.

My Boilerplate.
import pygame
import os

class Scene:
    # SceneManager Interface
    def __init__(self, manager):
        self.manager = manager

    def scene_draw(self, surface):
        self.on_draw(surface)

    def scene_drop(self):
        self.on_drop()

    def scene_event(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.on_quit()
            else:
                self.on_event(event)

    def scene_focus(self, *args, **kwargs):
        self.on_focus(*args, **kwargs)

    def scene_new(self,*args, **kwargs):
        self.on_new(*args, **kwargs)

    def scene_update(self, delta):
        self.on_update(delta)

    def flip(self, scene, *args, **kwargs):
        self.manager.flip(scene, *args, **kwargs)

    def flip_new(self, scene, *args, **kwargs):
        self.manager.flip_new(scene, *args, **kwargs)

    def on_quit(self):
        self.manager.quit()

    # Scene Interface
    def on_draw(self, surface): pass
    def on_drop(self): pass
    def on_event(self, event): pass
    def on_focus(self): pass
    def on_new(self): pass
    def on_update(self, delta): pass

class Manager:
    def __init__(self, title, width, height, center=True, flags=0):
        if center is True:
            os.environ['SDL_VIDEO_CENTERED'] = '1'
        elif center:
            os.environ['SDL_VIDEO_WINDOW_POS'] = '{0}, {1}'.format(*center)

        # Basic pygame setup
        pygame.display.set_caption(title)
        self.surface = pygame.display.set_mode((width, height), flags)
        self.rect = self.surface.get_rect()
        self.clock = pygame.time.Clock()
        self.running = False
        self.delta = 0
        self.fps = 60

        # Scene handling
        self._scene = Scene(self)
        self.scenes = {}

        self.extension = []

    def add_scene(self, scene, name=None):
        if name is None:
            name = scene.__class__.__name__

        self.scenes[name] = scene

    def _flip(self, scene):
        self._scene.scene_drop()
        if isinstance(scene, Scene):
            self._scene = scene
        else:
            # String: Load live scene
            self._scene = self.scenes[scene]

    def flip(self, scene, *args, **kwargs):
        self._flip(scene)
        self._scene.scene_focus(*args, **kwargs)

    def flip_new(self, scene, *args, **kwargs):
        self._flip(scene)
        self._scene.scene_new(*args, **kwargs)

    def mainloop(self):
        self.running = True
        while self.running:
            self._scene.scene_event()
            self._scene.scene_update(self.delta)
            self._scene.scene_draw(self.surface)
            for extension in self.extension:
                extension(self)

            pygame.display.flip()
            self.delta = self.clock.tick(self.fps)

    def quit(self):
        self.running = False
Example. Didn't use one global variable.
import pygame
from scene import Scene, Manager
from pygame.sprite import Sprite, Group

class GameSprite(Sprite):
    def __init__(self, image, position, anchor="topleft"):
        Sprite.__init__(self)
        self.image = image
        self.rect = image.get_rect(**{anchor: position})
        self.updates = []

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def update(self, keys_pressed, delta):
        for update in self.updates:
            update(keys_pressed, delta)

class LifePool:
    def __init__(self, value):
        self.max_value = value
        self.value = value

    def __add__(self, value):
        self.value = min(self.value + value, self.max_value)

    def __sub__(self, value):
        self.value = max(self.value - value, 0)

    def get_percent(self):
        return self.value / self.max_value

class CharacterMovement:
    def __init__(self, sprite, speed):
        self.sprite = sprite
        self.speed = speed * 0.01
        self.center = pygame.Vector2(sprite.rect.center)

        self._vector = pygame.Vector2(0, 0)

    def move_up(self):
        self._vector.y -= 1

    def move_down(self):
        self._vector.y += 1

    def move_left(self):
        self._vector.x -= 1

    def move_right(self):
        self._vector.x += 1

    def update(self, delta):
        if self._vector != pygame.Vector2(0, 0):
            self._vector.normalize_ip()
            self.center += self._vector * self.speed * delta

            self.sprite.rect.center = self.center
            self._vector = pygame.Vector2(0, 0)

class CharacterMovementKeys:
    def __init__(self, movement, up=pygame.K_w, down=pygame.K_s, left=pygame.K_a, right=pygame.K_d):
        self.movement = movement
        self.up = self.list_form(up)
        self.down = self.list_form(down)
        self.left = self.list_form(left)
        self.right = self.list_form(right)

    def list_form(self, key):
        if isinstance(key, list):
            return key
        elif isinstance(key, tuple):
            return list(key)
        return [key]

    def move(self, key_pressed, delta):
        if any([key_pressed[key] for key in self.up]):
            self.movement.move_up()

        if any([key_pressed[key] for key in self.down]):
            self.movement.move_down()

        if any([key_pressed[key] for key in self.left]):
            self.movement.move_left()

        if any([key_pressed[key] for key in self.right]):
            self.movement.move_right()

        self.movement.update(delta)

class Character:
    def __init__(self, image, position, anchor="topleft"):
        self.sprite = GameSprite(image, position, anchor)
        self.life = LifePool(20)
        self.create_life_sprite()
        self.movement = CharacterMovement(self.sprite, 8)
        self.keys = CharacterMovementKeys(self.movement)
        self.sprite.updates.append(self.keys.move)
        self.sprite.updates.append(self.update_life_position)

    def create_hit_points_image(self):
        size = self.sprite.rect.width, 5
        surface = pygame.Surface(size)
        surface.fill(pygame.Color('firebrick'))
        percent = self.life.get_percent()
        width = int(size[0] * percent)
        rect = (0, 0, width, size[1])
        pygame.draw.rect(surface, pygame.Color('lawngreen'), rect)
        return surface

    def create_life_sprite(self):
        image = self.create_hit_points_image()
        position = self.sprite.rect.midtop
        position = position[0], position[1] - image.get_height() - 2
        self.life_sprite = GameSprite(image, position, "midtop")

    def update_life_position(self, keys_pressed, delta):
        position = self.sprite.rect.midtop
        position = position[0], position[1] - self.life_sprite.rect.height - 2
        self.life_sprite.rect.midtop = position

class MainScene(Scene):
    def __init__(self, manager):
        Scene.__init__(self, manager)
        image = self.create_character_image()
        self.character = Character(image, manager.rect.center, "center")

        self.sprites = Group(self.character.sprite)
        self.life_bar = Group(self.character.life_sprite)

        self.show_life_bar = True

    def create_character_image(self):
        surface = pygame.Surface((30, 30))
        surface.fill(pygame.Color("dodgerblue"))
        return surface

    def on_draw(self, surface):
        surface.fill(pygame.Color("black"))
        self.sprites.draw(surface)
        if self.show_life_bar:
            self.life_bar.draw(surface)

    def on_event(self, event):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                self.show_life_bar = not self.show_life_bar

    def on_update(self, delta):
        keys_pressed = pygame.key.get_pressed()
        self.sprites.update(keys_pressed, delta)

def main():
    pygame.init()
    manager = Manager("Example", 800, 600)
    manager.flip(MainScene(manager))
    manager.mainloop()

if __name__ == "__main__":
    main()
99 percent of computer problems exists between chair and keyboard.
Reply


Messages In This Thread
RE: Spawning platforms that don't touch - by Windspar - Jan-24-2020, 10:59 AM

Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyGame] Timing the spawning enemies MichaelEssey 2 4,744 Aug-22-2020, 05:51 AM
Last Post: SheeppOSU
  spawning enemies in pygame Elberg 2 5,708 Mar-05-2020, 09:45 AM
Last Post: Windspar

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020