From: Neil Date: Tue, 6 Sep 2016 15:44:25 +0000 (+0200) Subject: Enter Boyd, from not exactly stage left. X-Git-Tag: tabakrolletjie-v1.0.0~236 X-Git-Url: https://git.ctpug.org.za/?a=commitdiff_plain;h=35aa986992aeeb0882174591d325e6259c372e32;p=tabakrolletjie.git Enter Boyd, from not exactly stage left. --- diff --git a/tabakrolletjie/constants.py b/tabakrolletjie/constants.py index 8e6bac7..5acf89a 100644 --- a/tabakrolletjie/constants.py +++ b/tabakrolletjie/constants.py @@ -15,3 +15,4 @@ FPS = 60 # Pymunk categories OBSTACLE_CATEGORY = 1 << 0 LIGHT_CATEGORY = 1 << 1 +MOULD_CATEGORY = 1 << 2 diff --git a/tabakrolletjie/enemies.py b/tabakrolletjie/enemies.py new file mode 100644 index 0000000..3f9210b --- /dev/null +++ b/tabakrolletjie/enemies.py @@ -0,0 +1,111 @@ +# Boyd, the friendly, misunderstood turnip loving, light hating space mould + +import pymunk +import pymunk.pygame_util +import pygame.draw +import pygame.surface +import pygame.display + +import pygame.locals as pgl + +from .constants import SCREEN_SIZE, MOULD_CATEGORY, OBSTACLE_CATEGORY + +MOULD_FILTER = LIGHT_FILTER = pymunk.ShapeFilter( + mask=MOULD_CATEGORY | OBSTACLE_CATEGORY, + categories=MOULD_CATEGORY) + + +class Mould(pymunk.Body): + """A segment of Boyd""" + + def __init__(self, gamestate, space, pos): + super(Mould, self).__init__(0, 0, pymunk.Body.STATIC) + self.position = pos + self._shape = pymunk.Circle(self, 16) + space.add(self, self._shape) + self._shape.filter = MOULD_FILTER + self._resistances = {} + self._age = 0 + self._img = None + + def get_image(self): + if not self._img: + img = pygame.surface.Surface((32, 32)) + img.convert_alpha(pygame.display.get_surface()) + img.fill((0, 0, 0, 0)) + pygame.draw.circle(img, (255, 255, 255, 255), (16, 16), 16) + self._img = img + return self._img + + def tick(self, gamestate, space, moulds): + """Grow and / or Die""" + self._age += 1 + + refresh = False + + if (self._age % 15) == 0 and len(moulds) < 1000: + # Spawn a new child, if we can + spawn = True + import random + choice = random.randint(0, 4) + if choice == 0: + pos = self.position + (0, 24) + elif choice == 1: + pos = self.position + (24, 0) + elif choice == 2: + pos = self.position + (-24, 0) + else: + pos = self.position + (0, -24) + # check for bounds + if pos[0] < 0 or pos[0] >= SCREEN_SIZE[0]: + spawn = False + if pos[1] < 0 or pos[1] >= SCREEN_SIZE[1]: + spawn = False + # Check for free space + # We allow some overlap, hence not checking full radius + query = space.point_query(pos, 8, MOULD_FILTER) + if query: + # for x in query: + # if not isinstance(x.shape.body, Mould): + # print x.shape, x.shape.body + spawn = False + if spawn: + child = Mould(gamestate, space, pos) + moulds.append(child) + refresh = True + + if self._age > 120: + # We die of old age + space.remove(self, self._shape) + moulds.remove(self) + refresh = True + return refresh + + def damage(self, light_color, intensity): + """Take damage for light, adjusted for resistances.""" + + +class Boyd(object): + + def __init__(self, gamestate, space): + seed = Mould(gamestate, space, (400, 400)) + self._moulds = [seed] + self._image = pygame.surface.Surface(SCREEN_SIZE) + self._image.convert_alpha(pygame.display.get_surface()) + self._image.fill((0, 0, 0, 0)) + + def tick(self, gamestate, space): + redraw = False + for mould in self._moulds[:]: + if mould.tick(gamestate, space, self._moulds): + redraw = True + if redraw: + self._image.fill((0, 0, 0, 0)) + for mould in self._moulds: + pos = pymunk.pygame_util.to_pygame(mould.position, self._image) + self._image.blit(mould.get_image(), pos, None, + pgl.BLEND_RGBA_ADD) + + def render(self, surface): + """Draw ourselves""" + surface.blit(self._image, (0, 0), None, pgl.BLEND_RGBA_ADD) diff --git a/tabakrolletjie/scenes/night.py b/tabakrolletjie/scenes/night.py index 16d8cf6..7f6b5bb 100644 --- a/tabakrolletjie/scenes/night.py +++ b/tabakrolletjie/scenes/night.py @@ -3,12 +3,16 @@ import pygame.locals as pgl import pymunk +import time from .base import BaseScene from ..lights import BaseLight from ..obstacles import BaseObstacle +from ..enemies import Boyd from ..events import SceneChangeEvent +from ..constants import DEBUG + class NightScene(BaseScene): def enter(self, gamestate): @@ -22,7 +26,10 @@ class NightScene(BaseScene): for light in self._lights: light.add(self._space) + self._mould = Boyd(gamestate, self._space) + def render(self, surface, gamestate): + start_time = time.time() surface.fill((0, 0, 155)) for light in self._lights: light.render_light(surface) @@ -30,9 +37,21 @@ class NightScene(BaseScene): obs.render(surface) for light in self._lights: light.render(surface) + self._mould.render(surface) + + end_time = time.time() + if DEBUG: + print "Night Render", end_time - start_time def event(self, ev, gamestate): if ev.type == pgl.KEYDOWN: if ev.key in (pgl.K_q, pgl.K_ESCAPE): from .menu import MenuScene SceneChangeEvent.post(scene=MenuScene()) + + def tick(self, gamestate): + start_time = time.time() + self._mould.tick(gamestate, self._space) + end_time = time.time() + if DEBUG: + print "Night Tick", end_time - start_time