class SceneGame(Scene): def __init__(self, window): super().__init__(window) self.game_objects = [] self.fx_bot_objects = [] self.fx_top_objects = [] self.batch = Batch() self.level_number = 0 self.level = Level1() self.bg_manager = CloudsBackground() self.overlay = Overlay(self) self.player = MisuPlayer(self) self.game_objects.append(self.player) def draw(self): super().draw() self.bg_manager.draw() self.batch.draw() def update(self, dt): super().update(dt) self.bg_manager.update(dt) for e in self.game_objects + self.fx_bot_objects + self.fx_top_objects: e.early_update(dt) e.update(dt) e.late_update(dt) for key in self.keys: self.player.input(key, self.keys[key]) def add_game_object(self, go): self.game_objects.append(go) go.sprite.batch = self.batch
def draw(self, current_view): batch_to_draw = Batch() for c in self.graphic_components: if c.current_view == current_view: options = c.get_draw_options() batch_to_draw.add(*options) batch_to_draw.draw()
class Overlay: def __init__(self, game): self.game = game self.batch = Batch() self.width, self.height, = self.game.window.width, self.game.window.height, self.centerX, self.centerY, = self.width // 2, self.height // 2 self.fpslist = [] self.debug = DebugLabelHandler(self) self.saving = SavingLabelHandler(self) self.reticle = ReticleHandler(self) self.compass = CompassHandler(self) self.inventory = InventoryHandler(self) self.health = HealthHandler(self) self.endscreen = EndScreenHandler(self) def draw(self): self.debug() self.saving() self.reticle() self.compass() self.inventory() self.health() self.endscreen() self.batch.draw() __call__ = draw
class Mesh(GameObject): def __init__(self, vertices=[], indices=[], normals=[], group=None, **args): self.vertices = [x for x in vertices] self.indices = [x for x in indices] self.normals = [x for x in normals] self.vertex_list = None self.batch = Batch() self.group = group super(Mesh, self).__init__(**args) self.update_mesh() def update_mesh(self): if self.vertex_list: self.vertex_list.delete() self.vertex_list = self.batch.add_indexed( len(self.vertices) // 3, GL_TRIANGLES, self.group, self.indices, ('v3f/static', self.vertices), ('n3f/static', self.normals)) def __del__(self): if self.vertex_list is not None: self.vertex_list.delete() def onDraw(self): super(Mesh, self).onDraw() self.batch.draw()
class Test(cocos.scene.Scene): def __init__(self): super(Test, self).__init__() self.layer = cocos.layer.Layer() self.add(self.layer) self.batch = Batch() sprite = cocos.sprite.Sprite('fondo.png') sprite.position = -400, 480 - sprite.height / 2 - 50 sprite.do(Repeat(MoveBy((20, 0), 1))) self.layer.add(sprite) sprite_2 = cocos.sprite.Sprite('fondo.png') sprite_2.position = 320, 100 self.layer.add(sprite_2) self.sprite_2 = sprite_2 self.x = -100.0 self.schedule_interval(self.update, 1/20.0) def update(self, dt): self.x += dt * 20 self.sprite_2.position = int(self.x), self.sprite_2.position[1] def draw(self): self.batch.draw()
class Model: def get_texture(self, file): texture = load_img(file).texture glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) return TextureGroup(texture) def __init__(self): self.batch = Batch() self.top = self.get_texture('./resources/grass_top.png') self.side = self.get_texture('./resources/grass_side.png') self.bottom = self.get_texture('./resources/dirt.png') x, y, z = 0, 0, -1 X, Y, Z = x + 1, y + 1, z + 1 texture_coords = ('t2f', (0, 0, 1, 0, 1, 1, 0, 1)) self.batch.add(4, GL_QUADS, self.side, ('v3f', (x, y, z, X, y, z, X, Y, z, x, Y, z)), texture_coords) def draw(self): self.batch.draw()
class Body(object): "A list of primitives. Creates a single batch to draw these primitives." def __init__(self, items=None): self.primitives = [] if items: self.add_items(items) self.batch = None def add_items(self, items): "'items' may contain primitives and/or bodys" for item in items: if isinstance(item, Body): for prim in item.primitives: self.primitives.append(prim) else: self.primitives.append(item) def batch_draw(self): if self.batch is None: self.batch = Batch() for primitive in self.primitives: batchVerts = \ [primitive.verts[0], primitive.verts[1]] + \ primitive.verts + \ [primitive.verts[-2], primitive.verts[-1]] numverts = len(batchVerts) / 2 self.batch.add( numverts, primitive.primtype, None, # draw order group to be implemented later ('v2f/static', batchVerts), ('c3B/static', primitive.color * numverts), ) self.batch.draw()
class ParticleEmitter: def __init__(self, lifetime: float): self.crt_time = 0 self.lifetime = lifetime self.particles = set() self.batch = Batch() def create_particle( self, x: float, y: float, scale: float, initial_texture: Texture, behaviors: T.List[ParticleBehavior], ): sprite = Sprite(initial_texture, x, y, batch=self.batch) sprite.scale = scale self.particles.add(Particle(sprite, behaviors)) def update(self, dt): self.crt_time += dt to_remove = set() for particle in self.particles: pop = particle.update(dt) if pop: to_remove.add(particle) [self.particles.remove(tr) for tr in to_remove] def draw(self): self.batch.draw()
class Renderer: instance: 'Renderer' = None def __init__(self): self.__class__.instance = self self._main_batch = Batch() self._main_group = OrderedGroup(0) self._ui_object_list = [] self._ui_that_use_scissor_list = [] # stores ui objects that use scissor buffer and must be updated in draw method def get_batch(self) -> Batch: return self._main_batch def get_main_group(self) -> OrderedGroup: return self._main_group def draw(self): self._main_batch.draw() [i.update_logic() for i in self._ui_that_use_scissor_list if i is not None] def add_ui_object(self, ui_object: Sprite): self._ui_object_list.append(ui_object) def remove_ui_object(self, ui_object: Sprite): self._ui_object_list.remove(ui_object) def add_ui_object_scissor(self, ui_object: Sprite): self._ui_that_use_scissor_list.append(ui_object) def remove_ui_object_scissor(self, ui_object: Sprite): self._ui_that_use_scissor_list.remove(ui_object) def update_logic(self): [i.update_logic() for i in self._ui_object_list if i is not None]
def render(self) -> None: """ Render the board onto the screen. """ # Clear the old board. self.clear() # Draw the board in a single batch. batch = Batch() obstacle_layer, connection_layer, boid_layer = (OrderedGroup(order) for order in range(3)) if self._show_lines: batch = self.draw_connections(batch, connection_layer, "neighbors", color=GREEN) batch = self.draw_connections(batch, connection_layer, "obstacles", color=RED) batch = self.draw_models(batch, boid_layer, self.system.population, color=WHITE) batch = self.draw_models(batch, obstacle_layer, self.system.obstacles, color=RED) batch.draw() # Send to screen. self.flip()
class SvgFiles(object): def __init__(self): datadir = join('solescion', 'geom', 'svgload', 'demodata') self.filenames = self.get_filenames(datadir) if len(self.filenames) == 0: raise Exception('no testdata svg files found') self.number = -1 self.current = None self.next() def get_filenames(self, path): return [ join(path, filename) for filename in listdir(path) if filename.endswith('.svg') ] def next(self): self.number = (self.number + 1) % len(self.filenames) filename = self.filenames[self.number] print filename self.current = SvgParser(filename) self.batch = Batch() self.current.add_to_batch(self.batch) glClearColor( uniform(0.0, 1.0), uniform(0.0, 1.0), uniform(0.0, 1.0), 1.0) def draw(self): self.batch.draw()
def draw_sprite_objs(self): sprite_batch = Batch() self.rendered_sprite = [] ship = self.model.player if ship.is_active: colour = self.player_glow_colour if self.model.player.is_blown: colour = [255, 0, 0] elif self.model.q_jam or self.model.e_jam: colour = [255, 0, 255] self.draw_illumination(self.to_screen_x(ship.x + ship.width // 2), self.to_screen_y(ship.y), 150 + self.player_glow_intensity, colour) player_batch = Batch() player_sprite = self.get_rendered_sprite(ship, player_batch) self.rendered_sprite.append(player_sprite) self.draw_flame(self.to_screen_x(ship.x), self.to_screen_y(ship.y), self.to_screen_x(ship.width)) player_batch.draw() objs = [] objs.extend(self.model.objects) if hasattr(self.model, 'boxes'): objs.extend(self.model.boxes) for obj in objs: if obj.is_active: sprite = self.get_rendered_sprite(obj, sprite_batch) self.rendered_sprite.append(sprite) sprite_batch.draw()
def draw_lasers(self): batch = Batch() inner_colors = (0, 200, 255, 0, 200, 255) radius = 3 * SpaceWindow.BULLET_RADIUS_PERCENT * self.width for bullet in self.model.bullets: # self.draw_illumination(self.to_screen_x(bullet[0]), self.to_screen_y(bullet[1]), radius, inner_colors[:3]) batch.add(2, GL_LINES, None, ('v2f', [self.to_screen_x(bullet[0]), self.to_screen_y(bullet[1]), self.to_screen_x(bullet[0]), self.to_screen_y(bullet[1] + int(self.BULLET_HEIGHT_PERCENT * self.main_height))]), ('c3B', inner_colors)) radius = SpaceWindow.BULLET_RADIUS_PERCENT * self.width purple = [255, 0, 255] for x, y in self.model.alien_bullets: self.draw_illumination(self.to_screen_x(x), self.to_screen_y(y), 6 * radius, purple) circ_pts = [self.to_screen_x(x), self.to_screen_y(y) + radius] for theta in np.linspace(0, 2 * math.pi, 8): error = random.randint(-1 * radius // 4, radius // 4) circ_pts.extend([circ_pts[0] + (radius + error) * math.sin(theta), circ_pts[1] + (radius + error) * math.cos(theta)]) num_of_vert = (len(circ_pts) // 2) colors = [255, 255, 255] colors.extend((num_of_vert - 1) * purple) graphics.draw(num_of_vert, GL_TRIANGLE_FAN, ('v2f', circ_pts), ('c3B', colors)) batch.draw()
class Render(object): groups = [ OrderedGroup(0), # sky OrderedGroup(1), # hills OrderedGroup(2), # birds & feathers OrderedGroup(3), # hud ] def __init__(self, game): self.game = game game.item_added += self.on_add_item game.item_removed += self.on_remove_item self.win = None self.clockDisplay = clock.ClockDisplay() self.batch = Batch() def assign_images_and_sizes(self, images): for klass in [Ground, Player, Enemy, Feather]: klass.images = images[klass.__name__] klass.width = klass.images[0].width klass.height = klass.images[0].height def init(self, win): self.win = win glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) graphics = Graphics() images = graphics.load() self.assign_images_and_sizes(images) win.on_draw = self.draw def draw(self): for item in self.game: if hasattr(item, 'animate'): item.animate() self.batch.draw() self.clockDisplay.draw() self.win.invalid = False def on_add_item(self, item): if hasattr(item, 'add_to_batch'): item.add_to_batch(self.batch, self.groups) def on_remove_item(self, item): if hasattr(item, 'remove_from_batch'): item.remove_from_batch(self.batch)
class Map(object): LAYERS = { 'soil': OrderedGroup(0), 'ground': OrderedGroup(1), 'bodies': OrderedGroup(2), 'trees': OrderedGroup(3), 'berries': OrderedGroup(4) } def __init__(self, width, height): self.width = width self.height = height self._map = Batch() self._create() self._add_hero() self._add_lost() def _create(self): for x in range(0, self.width, Soil.size()[0]): for y in range(0, self.height, Soil.size()[1]): soil = Soil(x, y) self.add(soil) try: soil.grow(self, x, y) except NotFertileError as e: logger.debug(str(e)) def add(self, thing): thing.vertex_list = self._map.add( len(thing.vertices) // 2, GL_QUADS, self.LAYERS[thing.LAYER], ('v2i/dynamic', thing.vertices), ('c4B/static', thing.colors) ) return thing.vertex_list def _add_body(self, body_name, kind): body = getattr(things, body_name)(*START_POS[kind]) setattr(self, kind, body) self.add(body) return body @info("Adding {}".format(BODY_HERO)) def _add_hero(self): self._add_body(BODY_HERO, 'hero') @info("Hiding {}".format(BODY_LOST)) def _add_lost(self): self._add_body(BODY_LOST, 'lost') # keep a list of every tree to hide him def draw(self): self._map.draw()
class DinamicObj(Importer): def __init__(self, *args, **kwargs): self.batch = Batch() super(DinamicObj, self).__init__(*args, **kwargs) def draw_faces(self): glPushMatrix() glTranslatef(self.x, self.y, self.z) glScalef(self.scale, self.height, self.thickness) self.batch.draw() glPopMatrix()
def render(self): """ Render the board onto the screen. """ # Clear the old board. self.clear() # Draw the board in a single batch. batch = Batch() batch = self.draw_board(batch) batch.draw() # Send to screen. self.flip()
class CloudsBackground: def __init__(self): self.batch = Batch() self.clouds = [ Sprite(IMAGES['backgrounds']['clouds'], x=0, y=0, batch=self.batch, group=G_BACKGROUND_2), Sprite(IMAGES['backgrounds']['clouds'], x=-1280, y=0, batch=self.batch, group=G_BACKGROUND_2), Sprite(IMAGES['backgrounds']['clouds'], x=0, y=720, batch=self.batch, group=G_BACKGROUND_2), Sprite(IMAGES['backgrounds']['clouds'], x=-1280, y=720, batch=self.batch, group=G_BACKGROUND_2) ] self.grass = [ Sprite(IMAGES['backgrounds']['grass'], x=0, y=0, batch=self.batch, group=G_BACKGROUND_1), Sprite(IMAGES['backgrounds']['grass'], x=0, y=720, batch=self.batch, group=G_BACKGROUND_1) ] def draw(self): self.batch.draw() def update(self, dt): for s in self.clouds: s.x += 0.1 s.y -= 5 if s.x > 1280: s.x -= 1280 * 2 if s.y < -720: s.y += 720 * 2 for s in self.grass: s.y -= 9 if s.y < -720: s.y += 720 * 2
def draw(self, group): batch = Batch() ss = [] for particle in group: s = Sprite(self.image, batch=batch) s.position = list(particle.position)[:2] s.color = [c * 255 for c in list(particle.color)[:3]] s.scale = particle.size[0] / 64.0 s.rotation = particle.age * 720 s.opacity = particle.color[3] * 255 ss.append(s) batch.draw()
class Body(object): "A list of shapes. Creates a single batch to draw these shapes." __metaclass__ = IterRegistry _registry = [] def __init__(self,items=None,anchor=[0,0],angle=0,drawable=True): self.shapes = [] self._registry.append(self) self.body=body self.anchor=anchor self.angle=angle self.drawable=drawable if items: self.add_items(items) self.batch = None def add_items(self, items): "'items' may contain shapes and/or bodies" for item in items: if isinstance(item, Body): for shp in item.shapes: self.shapes.append(shp) else: self.shapes.append(item) def batch_draw(self): if self.batch is None: self.batch = Batch() for shape in self.shapes: batchVerts = \ [shape.verts[0], shape.verts[1]] + \ shape.verts + \ [shape.verts[-2], shape.verts[-1]] numverts = len(batchVerts) / 2 self.batch.add( numverts, shape.primtype, None, # draw order group to be implemented later ('v2f/static', batchVerts), ('c3B/static', shape.color * numverts), ) self.batch.draw() def paint_all(): for z in Zulu: glPushMatrix() glTranslatef(z.anchor[0],z.anchor[1],0) # Move bac glRotatef(z.angle, 0, 0, 1) z.body.batch_draw() glPopMatrix()
class SceneBulletTest(Scene): def __init__(self, window): super().__init__(window) self.bullets = [LinearBullet(IMAGES['bullets']['round'])] self.batch = Batch() def update(self, dt): super().update(dt) for bullet in self.bullets: bullet.sprite.batch = self.batch bullet.update() bullet.update_sprite() def draw(self): super().update() self.batch.draw()
class Log(object): GROUPS = { 'text_bac' } def __init__(self, width, height, x, y, queue): self.width = width self.height = height self._log = Batch() self._create(x, y) self.queue = queue def _create(self, x, y): self._title = Label( "_______________ LOG _______________", x=x, y=y + self.height + 5, height=20, batch=self._log ) self._doc = decode_text("\n") self._doc.set_style(0, 0, dict(color=(255, 255, 255, 255))) self._box = ScrollableTextLayout( self._doc, self.width, self.height, multiline=True, batch=self._log ) self._box.x = x self._box.y = y def draw(self): self._log.draw() def insert(self, message): self._doc.insert_text(-1, message + "\n") self._box.view_y = -self._box.content_height def scroll(self, height): self._box.view_y += height def start(self): schedule_interval(self.update, 0.3) def update(self, dt): try: item = self.queue.popleft() self.insert(item['message']) except IndexError: pass
class Screen: """Abstract base class for other Screens.""" def __init__(self, game: "Pong") -> None: self.game = game self.batch = Batch() def on_draw(self) -> None: """Called every frame, so that the application can draw itself.""" self.game.window.clear() self.batch.draw() @abstractmethod def update(self, delta_time: float) -> None: """Called every frame, used to update all objects on the screen.
def draw_pixel_spills(self): pxl_batch = Batch() for px in self.pixel_spills: px.update(self.tick) self.pixel_spills[:] = [val for val in self.pixel_spills if not val.is_vanished] num_of = 0 px_vertices = [] colours = [] for px in self.pixel_spills: num_of += 4 px_vertices.extend((px.x, px.y, px.x, px.y + px.size, px.x + px.size, px.y + px.size, px.x + px.size, px.y)) colours.extend(px.colour) pxl_batch.add(num_of, GL_QUADS, None, ('v2f', px_vertices), ('c3B', colours)) pxl_batch.draw()
class HUD(object): SPRITES = { 'captain': 'captain.png', 'booty': 'booty.png', 'logo': 'logo.png' } def __init__(self, width, height): self.width = width self.height = height self.batch = Batch() self.load_sprites() self.booty_sprite = self.create_sprite('booty', self.width - 50, 15) self.booty = 0 self.booty_score = Label('0', font_name=FONT_NAME, font_size=28, color=(205, 175, 2, 0xff), x=self.width - 60, y=20, anchor_x='right', batch=self.batch) def add_booty(self, v): self.booty += v self.booty_score.text = str(self.booty) def load_sprites(self): load = pyglet.resource.image self.sprites = dict((k, load(v)) for k, v in self.SPRITES.items()) def create_scroll(self, text, x, y): return Scroll(text, (x, y), self.batch) def remove_scroll(self, scroll): scroll.delete() def create_sprite(self, name, x, y): return Sprite(self.sprites[name], x, y, batch=self.batch) def draw(self): gl.glMatrixMode(gl.GL_PROJECTION) gl.glLoadIdentity() gl.glOrtho(0, self.width, 0, self.height, 1, -1) gl.glMatrixMode(gl.GL_MODELVIEW) gl.glLoadIdentity() self.batch.draw()
def draw_falling_parts(self): pxl_batch = Batch() for bl in self.falling_parts: bl.update(self.tick) self.falling_parts[:] = [val for val in self.falling_parts if not val.is_vanished] num_of = 0 px_vertices = [] colours = [] px: FallingBlock for px in self.falling_parts: num_of += 4 px_vertices.extend((px.x, px.y, px.x, px.y + px.size, px.x + px.size, px.y + px.size, px.x + px.size, px.y)) colours.extend(px.colour) pxl_batch.add(num_of, GL_QUADS, None, ('v2f', px_vertices), ('c3B', colours)) pxl_batch.draw()
def draw_display_txt(self, lines, font_sizes): y_padding = self.main_width // 35 origin_y = 0.6 * self.height y_add = 0 txt_batch = Batch() for i, line in enumerate(lines): lbl = pyglet.text.Label( line, batch=txt_batch, font_name='8Bit Wonder', font_size=font_sizes[i], width=self.main_width // 4, height=self.header_height * 2, x=self.main_width // 2, y=origin_y - y_add, anchor_x='center', anchor_y='center', color=(255, 255, 255, 255)) y_add += font_sizes[i] + y_padding txt_batch.draw()
def draw_flame(self, x, y, width): flame_height = (self.main_height + self.main_width) // 90 rocket_width = 8 * width // 64 flame_width_reduct = 0 offset = 15 * width // 64 padding = 29 * width // 65 if random.random() < 0.2: self.reset_flame_colours() flame_batch = Batch() srcs = [[x + offset + i * padding, x + offset + rocket_width + i * padding] for i in range(0, 2)] for i, [src_x1, src_x2] in enumerate(srcs): flame_batch.add(4, GL_QUADS, None, ('v2f', [src_x1, y, src_x1 + flame_width_reduct, y - flame_height, src_x2 - flame_width_reduct, y - flame_height, src_x2, y]), ('c4B', self.flame_colours[i])) flame_batch.draw()
class CloudRenderer(CloudChunk): def __init__(self, X, Generator): super(CloudRenderer, self).__init__(X, Generator) self.Batch = Batch() def GenerateFinshed(self): super(CloudRenderer, self).GenerateFinshed() self.Batch.add(self.Length, GL_POINTS, None, ('v2i/static', self.Points), ('c4f/static', self.Colours) ) def Draw(self, X): super(CloudRenderer, self).Draw(X) self.Batch.draw()
class Surface: def __init__(self, poses, material=None): self.poses = poses self.N = (poses[1] - poses[0]).cross(poses[2] - poses[0]).normalize() self.batch = Batch() norms = list(self.N.arr) * len(poses) verts = reduce(lambda x, y: list(x) + list(y), poses) self.batch.add(len(poses), GL_TRIANGLE_FAN, None, ('v3f', verts), ('n3f', norms)) self.material = material def draw(self): if self.material is not None: self.material.set() self.batch.draw() def d(self, p): return self.N.dot(self.poses[0] - p)
def draw_point_lbls(self): pts: FadingPoints font_size = self.main_width // 140 pts_batch = Batch() for pts in self.pt_lbls: pts.update() if pts.is_vanished: self.pt_lbls.remove(pts) else: pts_lbl = pyglet.text.Label(pts.txt, font_name='8Bit Wonder', font_size=font_size, width=self.main_width // 10, height=self.header_height // 2, x=pts.x, y=pts.y, anchor_x='left', anchor_y='top', color=(255, 255, 255, pts.alpha), batch=pts_batch) pts_batch.draw()
def draw_scores(self): """Draw the ui containing player statistics. """ batch = Batch() labels = [] header = [ 'pl', 'population', 'room', 'happiness', 'turn reward', 'total reward' ] sep = ' | ' score_strings = [sep + sep.join(header) + sep] for player in self.game.players: scores = map(lambda x: str(round(x, 3)), [ player.player_id, player.population, player.room, player.happiness_penalty, player.current_reward, player.total_reward ]) line = '' for i, score in enumerate(scores): score_len = len(str(score)) head_len = len(header[i]) line += ' ' * (head_len + len(sep) - score_len) line += score score_strings.append(line) # .75 for pt to px font_size = self.font_height / 0.75 # int(.75 * self.window_height * self.score_space / self.game.n_players) for i, score_str in enumerate(score_strings, start=1): if i > 1: c = self._get_player_color(self.game.players[i - 2]) + (255, ) c = self.brighten(c, 50) else: c = (255, ) * 4 label = Label(score_str, x=0, y=self.height - 2 * self.font_height * i, font_name='Consolas', font_size=font_size, color=c, batch=batch) labels.append(label) batch.draw()
class Starfield(object): def __init__(self): self.batch = Batch() self.starfield_block = StarfieldBlock(rect=Rect.from_cwh( v(0, 0), BLOCK_SIZE, BLOCK_SIZE), batch=self.batch) self.blocks = {} def draw(self, camera): # set up projection matrix gl.glMatrixMode(gl.GL_PROJECTION) gl.glPushMatrix() gl.glLoadIdentity() gl.gluPerspective(FOVY, camera.aspect(), NEAR_PLANE, FAR_PLANE) gl.glMatrixMode(gl.GL_MODELVIEW) gl.glEnable(gl.GL_DEPTH_TEST) # compute correct clip rect on far plane l, b = camera.position + camera.offset * FAR_PLANE_SCALE r, t = camera.position - camera.offset * FAR_PLANE_SCALE # Create blocks l = int(floor(l / BLOCK_SIZE)) r = int(ceil(r / BLOCK_SIZE)) b = int(floor(b / BLOCK_SIZE)) t = int(ceil(t / BLOCK_SIZE)) for y in range(b, t): for x in range(l, r): c = v(x, y) * BLOCK_SIZE gl.glPushMatrix() gl.glTranslatef(c.x, c.y, 0) self.batch.draw() gl.glPopMatrix() gl.glMatrixMode(gl.GL_PROJECTION) gl.glPopMatrix() gl.glMatrixMode(gl.GL_MODELVIEW) gl.glDisable(gl.GL_DEPTH_TEST)
class MapView(object): def __init__(self, tilemap): self.tilemap = tilemap self.batch = Batch() self.layerviews = [LayerView(self, layer) for layer in tilemap.layers] self.refresh() def refresh(self): for layerview in self.layerviews: layerview.refresh() def draw(self): self.batch.draw() def move(self, movement): dx, dy = movement for layerview in self.layerviews: x, y = layerview.group.translation layerview.group.translation = (x+dx, y+dy)
class AboutScene(Scene): def __init__(self, world, previous): super(AboutScene, self).__init__(world) self.old_scene = previous self.text_batch = Batch() self._generate_text() self.key_handlers = { (key.ESCAPE, 0) : self._resume } def on_draw(self): self.window.clear() # Display the previous scene, then tint it self.text_batch.draw() def on_key_press(self, button, modifiers): key = (button, modifiers) handler = self.key_handlers.get(key, lambda: None) handler() def _resume(self): self.world.reload(self.old_scene) def _generate_text(self): real_cord = lambda x,y: (x + self.camera.offset_x, y + self.camera.offset_y) author_x, author_y = real_cord(200, 500) Label("Written by John Mendelewski", font_name='Times New Roman', font_size=36, x=author_x, y=author_y - 20, batch=self.text_batch) hint_x, hint_y = real_cord(400, 30) Label("Use Escape to return to the menu", font_name='Times New Roman', font_size=18, x=hint_x, y=hint_y - 20, batch=self.text_batch)
class Dummy(Actor): def __init__(self, *args, **kwargs): """ Draw a dummy actor for testing """ super(Dummy, self).__init__() self.batch = Batch() pyglet.text.Label('Hello, world', font_name='Times New Roman', font_size=36, dpi=250, # x=window.width//2, y=window.height//2, anchor_x='center', anchor_y='center', batch = self.batch) pyglet.text.Label('Hi', font_name='Times New Roman', font_size=26, dpi=100, # x=window.width//2, y=window.height//2, anchor_x='center', anchor_y='center', batch = self.batch) def update(self, dt): pass def draw(self): pass glPushMatrix() #glRotatef(5.0, 0, 1, 0) glTranslatef(-100,0,0) self.batch.draw() glPopMatrix()
class Composite(object): ''' a list of shapes has its own peg and vel" ''' _instances = set() def __init__(self, *args, **kwargs): self.shapes = [] self.get_batch if args: self.add_items(args) for i in kwargs: setattr(self,i,kwargs[i]) if not hasattr(self,'peg'): # peg must be tuple (x, y, a) self.peg = DOCKED if not hasattr(self,'vel'): # peg must be tuple (vx, vy, av) self.vel = IDLE self._instances.add(weakref.ref(self)) print "::" print ":: new C shape ::::::::::::::::::::::::::::::::::::::::::::::::" print "::" dumpObj(self) @classmethod def get_instances(cls): dead = set() for ref in cls._instances: obj = ref() if obj is not None: yield obj else: dead.add(ref) cls._instances -= dead def add_items(self, items): ''' Add a list containing shapes and shapes ''' for item in items: if isinstance(item, Composite): #item is a C-shape for ssh in item.shapes: #decompose item into shapes ssh=ssh.copy() #mke a copy move it at new pos ssh.verts = offset(ssh.verts, item.peg.x+ssh.peg.x, \ item.peg.y+ssh.peg.y) self.shapes.append(ssh) #add it ssh.peg = DOCKED ssh.vel = IDLE elif isinstance(item, Shape): ssh=item.copy() print ssh.verts, ssh.peg.x, ssh.peg.y ssh.verts = offset(ssh.verts, ssh.peg.x, ssh.peg.y) print ssh.verts self.shapes.append(ssh) # item is a shape, add a copy of it ssh.peg = DOCKED ssh.vel = IDLE else: pass def get_batch(self): self.batch = Batch() print ':: new batch :' for ssh in self.shapes: print ':: shape :', ssh flatverts = ssh.get_flat_verts() numverts = len(flatverts) / 2 self.batch.add( numverts, ssh.primtype, None, ('v2f/static', flatverts), ('c4B/static', ssh.color * numverts) ) def paint(self): if self.batch is None: self.get_batch() glPushMatrix() glTranslatef(self.peg.x, self.peg.y, self.peg.z) glRotatef(self.peg.angle, 0, 0, 1) self.batch.draw() # OPTIMISATION : cs.batch.draw() directement avec batch déjà à jour TODO glPopMatrix() print '+',
class World: def __init__(self): self.current_lists = {} self.old_lists = {} self.zone_size = 30.0 self.patch_size = 0.5 self.zone_x = None self.zone_z = None self.terrain_batch = Batch() self.sea_batch = Batch() self.tree_batch = Batch() def gen_terrain(self, mutex, x, z): zone_size = self.zone_size patch_size = self.patch_size w = zone_size / patch_size + 1 assert w == int(w) w = int(w) xmin = (x - 0.5) * zone_size xmax = (x + 0.5) * zone_size zmin = (z - 0.5) * zone_size zmax = (z + 0.5) * zone_size v = [] v_sea = [] n = [] c = [] t = [] for i in np.linspace(xmin, xmax, w): time.sleep(0.2) for j in np.linspace(zmin, zmax, w): y = self.get_v(i, j) vv = [i, y, j] vv_sea = [i, 0.0, j] nn = self.get_n(i, j) v += vv v_sea += vv_sea n += nn if y > 10.0: c += [255, 255, 255] elif y > 7.0: c += [255, 120, 0] elif y > 1.0: c += [0, 255, 0] if random.random() > 0.5: t.append([i, y, j]) elif y > 0.0: c += [255, 255, 150] else: c += [0, 0, 255] index = [] for i in range(0, w-1): for j in range(0, w-1): index += [ i + j * w, i + j * w + 1, i + j * w + 1 + w, i + j * w + w] data = [index, v, n, c, v_sea, t] mutex.acquire() self.current_lists[(x, z)] = data mutex.release() #np.savez('save/{0}_{1}.npz'.format(x,z), data) def draw(self): self.terrain_batch.draw() self.sea_batch.draw() self.tree_batch.draw() def zone_lists_changed(self): tmp_lists = self.current_lists.copy() if tmp_lists != self.old_lists: self.old_lists = self.current_lists.copy() return True return False def zone_changed(self): size = self.zone_size player_x = int(np.floor(self.player.position[0] / size + 0.5)) player_z = int(np.floor(self.player.position[2] / size + 0.5)) return (player_x != self.zone_x or player_z != self.zone_z) def draw_terrain(self, l, w2): vlist = self.terrain_batch.add_indexed( w2, GL_QUADS, None, l[0], ('v3f/static', l[1]), ('n3f/static', l[2]), ('c3B/static', l[3])) def draw_sea(self, l, w2): n = [0, 0, 255] * w2 vlist = self.sea_batch.add_indexed( w2, GL_QUADS, None, l[0], ('v3f/static', l[4]), ('n3f/static', n), ('c3B/static', l[3])) def draw_tree(self, l, w2): for [x, y, z] in l[5]: self.add_tree(self.tree_batch, x, y, z) def draw_sea_simple(self): tmp_lists = self.current_lists.copy() v = [minx, 0, minz, minx, 0, maxz, maxx, 0, maxz, maxx, 0, minz] n = [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0] c = [0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255] self.sea_batch = Batch() self.sea_batch.add(4, GL_QUADS, None, ('v3f/static', v), ('n3f/static', n), ('c3B/static', c)) def update_batch(self): self.terrain_batch = Batch() self.sea_batch = Batch() self.tree_batch = Batch() tmp_lists = self.current_lists.copy() for i in tmp_lists: l = tmp_lists[i] w2 = len(l[1]) / 3 self.draw_sea(l, w2) self.draw_terrain(l, w2) self.draw_tree(l, w2) def update_zone_lists(self): size = self.zone_size player_x = int(np.floor(self.player.position[0] / size + 0.5)) player_z = int(np.floor(self.player.position[2] / size + 0.5)) new_set = set() for i in range(player_x - 1, player_x + 2): for j in range(player_z - 1, player_z + 2): new_set.add((i, j)) to_be_deleted = set() for i in self.current_lists: if i not in new_set: to_be_deleted.add(i) mutex = threading.Lock() for i in new_set: if i not in self.current_lists: x, z = i print 'Generating:', i threading.Thread( target=self.gen_terrain, args=(mutex, x, z)).start() for i in to_be_deleted: self.current_lists.pop(i) self.zone_x = player_x self.zone_z = player_z def update(self, dt): if self.zone_lists_changed(): self.update_batch() if self.zone_changed(): self.update_zone_lists() return def get_v(self, x, z): ratio = 0.01 ratio2 = 50.0 #return 0.0 return pnoise2(x*ratio, z*ratio, 5, persistence=0.5)*ratio2 def get_n(self, x, z): d = self.patch_size / 50.0 dydx = (self.get_v(x+d, z) - self.get_v(x-d, z)) / (2 * d) dydz = (self.get_v(x, z+d) - self.get_v(x, z-d)) / (2 * d) n = -np.cross([1.0, dydx, 0.0], [0.0, dydz, 1.0]) return list(n) def add_tree(self, batch, x, y, z): batch.add( 6, GL_TRIANGLES, None, ('v3f/static', ( -0.2+x, y, 0.0+z, 0.0+x, y+0.4, 0.0+z, 0.2+x, y, 0.0+z, 0.0+x, y, -0.2+z, 0.0+x, y+0.4, 0.0+z, 0.0+x, y, 0.2+z,)), ('c3B/static', ( 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0,)), ('n3f/static', ( 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,)))
class GameScene(Scene): # Game map constants MAP_START_X, MAP_START_Y = 400, 570 GRID_WIDTH, GRID_HEIGHT = 100, 50 MAP_WIDTH = MAP_HEIGHT = 10 # The modes the game scene can be in NOTIFY, SELECT_MODE, ACTION_MODE, MOVE_TARGET_MODE, ATTACK_TARGET_MODE = range(5) def __init__(self, world): super(GameScene, self).__init__(world) self.map_batch = Batch() self.map = self._generate_map() self.players = self._initialize_teams() self.current_turn = 1 #import knight #knight_x, knight_y = self.map.get_coordinates(5, 5) #self.characters = [knight.Knight.Sprite(knight_x, knight_y, 2, 0, 0.0)] #self.selected = None self.selected = 0, 0 self.selected_character = None self.mode = GameScene.SELECT_MODE # Items for action menu self.text_batch = Batch() self.cursor_pos = 0 self.cursor = Label(">", font_name='Times New Roman', font_size=36, x=10 + self.camera.offset_x, y=140 + self.camera.offset_y, batch=self.text_batch) self.action_menu_texts = [] self.action_menu_items = { "Move" : self._initiate_movement, "Attack" : self._initiate_attack, "Cancel" : self._close_action_menu, } # Sprites which need hilighting from different modes self.movement_hilight = [] self.attack_hilight = [] self.key_handlers = { GameScene.SELECT_MODE : { (key.ESCAPE, 0) : self.game_menu, (key.LEFT, 0) : lambda: self.move_hilight(-1, 0), (key.RIGHT, 0) : lambda: self.move_hilight(1, 0), (key.UP, 0) : lambda: self.move_hilight(0, -1), (key.DOWN, 0) : lambda: self.move_hilight(0, 1), (key.ENTER, 0) : self._open_action_menu, }, GameScene.ACTION_MODE : { (key.ESCAPE, 0) : self._close_action_menu, (key.UP, 0) : lambda: self._move_cursor(1), (key.DOWN, 0) : lambda: self._move_cursor(-1), (key.ENTER, 0) : self._menu_action }, GameScene.MOVE_TARGET_MODE : { (key.LEFT, 0) : lambda: self.move_hilight(-1, 0), (key.RIGHT, 0) : lambda: self.move_hilight(1, 0), (key.UP, 0) : lambda: self.move_hilight(0, -1), (key.DOWN, 0) : lambda: self.move_hilight(0, 1), (key.ENTER, 0) : self._execute_move, (key.ESCAPE, 0) : self._open_action_menu, }, GameScene.ATTACK_TARGET_MODE : { (key.LEFT, 0) : lambda: self.move_hilight(-1, 0), (key.RIGHT, 0) : lambda: self.move_hilight(1, 0), (key.UP, 0) : lambda: self.move_hilight(0, -1), (key.DOWN, 0) : lambda: self.move_hilight(0, 1), (key.ENTER, 0) : self._execute_attack, (key.ESCAPE, 0) : self._open_action_menu, }, } self.change_player() def _all_characters(self): return reduce(lambda chars, player: player + chars, self.players) def _other_characters(self): if self.current_turn: return self.players[0] else: return self.players[1] def change_player(self): old_turn = self.current_turn self.current_turn = (self.current_turn + 1) % 2 if not self.players[self.current_turn]: self.world.transition(VictoryScene, winner=old_turn + 1) else: self.display_turn_notice(self.current_turn) def display_turn_notice(self, current_turn): if hasattr(self, 'turn_notice'): self.turn_notice.delete() self.turn_notice = Label( "Player %s's Turn" % (current_turn + 1), font_name='Times New Roman', font_size=36, x= 500 + self.camera.offset_x, y= 560 + self.camera.offset_y) self.turn_notice.color = 255 - (100 * current_turn), 255 - (100 * ((current_turn + 1) % 2)), 255, 255 def _initialize_teams(self): def load_knight(hue): knight_x, knight_y = self.map.get_coordinates(9 * hue, 9 * hue) direction = hue and Direction.WEST or Direction.SOUTH knight = Knight(knight_x, knight_y, direction) knight.zindex=10 knight.color = 255 - (150 * hue), 255 - (150 * ((hue + 1) % 2)), 255 mage_x, mage_y = self.map.get_coordinates(7 * hue + 1, 7 * hue + 1) mage = Mage(mage_x, mage_y, direction) mage.zindex=10 mage.color = 255 - (150 * hue), 255 - (150 * ((hue + 1) % 2)), 255 return [knight, mage] return [load_knight(i) for i in range(2)] def move_hilight(self, x, y): current_x, current_y = self.selected self.selected = max(0, min(x + current_x, GameScene.MAP_WIDTH - 1)),\ max(0, min(y + current_y, GameScene.MAP_HEIGHT - 1)) newx, newy = self.map.get_coordinates(*self.selected) self.camera.look_at((newx + self.camera.x) / 2, (newy + self.camera.y) / 2) def enter(self): blue = 0.6, 0.6, 1, 0.8 pyglet.gl.glClearColor(*blue) clock.schedule(self._update_characters) def exit(self): clock.unschedule(self._update_characters) def on_draw(self): self.window.clear() selected_x, selected_y = self.map.get_coordinates(*self.selected) # if selected_x <= 100 or selected_x >= 500 \ # or selected_y <= 100 or selected_y >= 700: for sprite in self.map.sprites: if (selected_x, selected_y) == (sprite.x, sprite.y): sprite.color = 100, 100, 100 elif sprite in self.movement_hilight: sprite.color = 100, 100, 255 elif sprite in self.attack_hilight: sprite.color = 255, 100, 100 else: sprite.color = 255, 255, 255 self.map_batch.draw() if hasattr(self, 'turn_notice'): self.turn_notice.x = 500 + self.camera.offset_x self.turn_notice.y = 560 + self.camera.offset_y self.turn_notice.draw() for character in sorted(self._all_characters(), lambda c,d: int(d.y - c.y)): # if (selected_x, selected_y) == (character.x, character.y): # character.color = 100, 100, 100 # else: # character.color = 255, 255, 255 character.draw() # #character.image.blit(character.x, character.y) if self.mode == GameScene.ACTION_MODE: self._draw_action_menu() self.text_batch.draw() self.camera.focus(self.window.width, self.window.height) def _menu_action(self): actions = list(reversed(self.action_menu_items.values())) actions[self.cursor_pos]() def _move_cursor(self, direction): self.cursor_pos = (self.cursor_pos - direction) % len(self.action_menu_items) self.cursor.x = 10 + self.camera.offset_x self.cursor.y = 150 + self.camera.offset_y - 50 * self.cursor_pos def _draw_action_menu(self): pattern = SolidColorImagePattern((0, 0, 150, 200)) overlay_image = pattern.create_image(1000, 200) overlay_image.anchor_x = overlay_image.width / 2 overlay_image.anchor_y = overlay_image.height + 100 overlay = Sprite(overlay_image, self.camera.x, self.camera.y) overlay.draw() self._generate_text() def _generate_text(self): real_cord = lambda x,y: (x + self.camera.offset_x, y + self.camera.offset_y) menu_texts = reversed(self.action_menu_items.keys()) for label in self.action_menu_texts: label.delete() for i, text in enumerate(menu_texts): text_x, text_y = real_cord(40, 150 - 50 * i) self.action_menu_texts.append( Label(text, font_name='Times New Roman', font_size=36, x=text_x, y=text_y, batch=self.text_batch)) # def on_mouse_press(self, x, y, button, modifiers): # real_x, real_y = int(self.camera.offset_x + x),\ # int(self.camera.offset_y + y) # inside_map = self.map.find_sprite(x, y) # inside_chars = [c for c in self.characters if c.contains(real_x, real_y)] # taken = [self.map.get_row_column(c.x, c.y) for c in self.characters] # # # Reset everything # if self.selected: self.selected.color = 255, 255, 255 # for msprite in self.map.sprites: # msprite.color = 255, 255, 255 # # if inside_chars or inside_map: # if inside_chars: # selected = inside_chars[0] # else: # selected = inside_map # last, self.selected = self.selected, selected # self.selected.color = 100, 100, 100 # rx = self.selected.x + self.camera.offset_x # ry = self.selected.y + self.camera.offset_y # column, row = self.map.get_row_column(selected.x, selected.y) # if hasattr(self.selected, "is_player"): # in_range = self._points_in_range(column, row, 4) # for column, row in in_range: # if (column, row) not in taken: # self.map.get_sprite(column, row).color = 100, 100, 255 # elif hasattr(last, "is_player"): # last_column, last_row = self.map.get_row_column(last.x, last.y) # last_pair = last_column, last_row # new_indexes = self.map.get_row_column(selected.x, selected.y) # new_pair = int(selected.x), int(selected.y) # in_range = self._points_in_range(last_column, last_row, 4) # if new_indexes in in_range and new_pair not in taken: # self._schedule_movement(last, new_pair) # else: # self.selected = None def _initiate_movement(self): self.mode = GameScene.MOVE_TARGET_MODE self.movement_hilight = [] character = self.selected_character taken = [self.map.get_row_column(c.x, c.y) for c in self._all_characters()] column, row = self.map.get_row_column(character.x, character.y) in_range = self._points_in_range(column, row, character.speed) for column, row in in_range: if (column, row) not in taken: self.movement_hilight.append(self.map.get_sprite(column, row)) def _execute_move(self): taken = [self.map.get_row_column(c.x, c.y) for c in self._all_characters()] if self.selected not in taken: sprite = self.map.get_sprite(*self.selected) if sprite in self.movement_hilight: last = self.map.get_coordinates(*self.selected) self._schedule_movement(self.selected_character, last) self.movement_hilight = [] self.change_player() self._close_action_menu() def _initiate_attack(self): self.mode = GameScene.ATTACK_TARGET_MODE self.attack_hilight = [] character = self.selected_character column, row = self.map.get_row_column(character.x, character.y) in_range = self._points_in_range(column, row, character.range) in_range.remove(self.selected) for column, row in in_range: self.attack_hilight.append(self.map.get_sprite(column, row)) def _execute_attack(self): sprite = self.map.get_sprite(*self.selected) attacker = self.selected_character attacked = None if sprite in self.attack_hilight: for character in self._other_characters(): char_loc = self.map.get_row_column(character.x, character.y) if char_loc == self.selected: attacked = character if attacked: attack = random.randrange(attacker.strength) defense = random.randrange(attacked.defense) hit = max(1, defense - attack) print "Hit for ", hit attacker.attack_sound.play() attacked.current_health = attacked.current_health - hit if attacked.current_health <= 0: self._other_characters().remove(attacked) attacked.delete() self.attack_hilight = [] self.change_player() self._close_action_menu() def on_key_press(self, button, modifiers): key = (button, modifiers) handler = self.key_handlers[self.mode].get(key, lambda: None) handler() def _generate_map(self): x, y = GameScene.MAP_START_X, GameScene.MAP_START_Y x_offset, y_offset = self.GRID_WIDTH / 2, self.GRID_HEIGHT / 2 columns, rows = GameScene.MAP_WIDTH, GameScene.MAP_HEIGHT column_starts = [(x + i * x_offset, y - i * y_offset) for i in range(columns)] map_points = [[(x - i * x_offset, y - i * y_offset) for i in range(rows)] for x, y in column_starts] map = Map(columns, rows) for i, column in enumerate(map_points): for j, (x, y) in enumerate(column): image = load_sprite_asset("grass") image.anchor_x = image.width / 2 image.anchor_y = image.height / 2 sprite = PixelAwareSprite(image, x, y, batch=self.map_batch, centery=True) sprite.scale = 1 sprite.zindex = 0 map.add_sprite(i, j, sprite) return map def _load_characters(self): # Just load the knight for now knight_north = load_sprite_asset("knight/look_north") knight_west = load_sprite_asset("knight/look_west") knight_walk_west = load_sprite_animation("knight", "walk_west", 8, 0.15) knight_walk_north = load_sprite_animation("knight", "walk_north", 8, 0.15) #knight_walk_west = knight_walk_north = pyglet.image.load_animation("assets/knight/walk_west.gif") # knight_walk_west.anchor_x = knight_walk_west.width / 2 knight_x, knight_y = self.map.get_coordinates(5, 5) knight_faces = faces_from_images(north=knight_north, west=knight_west) knight_walks = [knight_walk_north, knight_walk_west, knight_walk_north, knight_walk_west] knight = MovingSprite(knight_x, knight_y, knight_faces, knight_walks) knight.scale=1 knight.is_player=True knight.zindex=10 knight_x, knight_y = self.map.get_coordinates(5, 0) knight2 = MovingSprite(knight_x, knight_y, knight_faces, knight_walks) knight2.scale=1 knight2.is_player=True knight2.zindex=10 knight2.look(2) return [knight, knight2] def _points_in_range(self, column, row, length): if not 0 <= column < self.MAP_HEIGHT: return [] if length == 0: return [(column, row)] else: return self._points_in_range(column - 1, row, length - 1) +\ [(column, min(max(0, row - length + i), self.MAP_WIDTH - 1)) for i in range(2 * length + 1)] + \ self._points_in_range(column + 1, row, length - 1) def _schedule_movement(self, sprite, pos): end_x, end_y = pos path = find_path(self.map.coordinates, sprite.x, sprite.y, end_x, end_y) for x, y in path: sprite.move_to(x, y, 0.3) def _update_characters(self, dt): for character in self._all_characters(): character.update(dt) def _close_action_menu(self): self.selected_character = None self.mode = GameScene.SELECT_MODE def _open_action_menu(self): if not self.selected_character: selected_x, selected_y = self.map.get_coordinates(*self.selected) for character in self.players[self.current_turn]: if (character.x, character.y) == (selected_x, selected_y): self.selected_character = character if self.selected_character: self.movement_hilight = [] self.attack_hilight = [] self.camera.stop() self.cursor_pos = 0 self.cursor.x = 10 + self.camera.offset_x self.cursor.y = 150 + self.camera.offset_y self.mode = GameScene.ACTION_MODE self.selected = self.map.get_row_column(self.selected_character.x, self.selected_character.y) def game_menu(self): self.camera.stop() self.world.transition(InGameMenuScene, previous=self)
class Drawing: def __init__(self, width, height, fbo, background=[255,255,255]): self.width = width self.height = height self.triangles = [] self.batch = Batch() self.bg_colour = background self.fb = fbo self.bg = self.batch.add( 6, gl.GL_TRIANGLES,None, ("v2i/static", (0,0,0,height,width,height,width,height,width,0,0,0)), ("c3B/static",background*6) ) def clone(self): global group d = Drawing(self.width, self.height, self.fb, self.bg_colour) bufferlength = len(self.triangles) d.vertex_list = d.batch.add( bufferlength*3, gl.GL_TRIANGLES, group, ("v2i/stream", [0]*bufferlength*6), ("c4B/stream", [0]*bufferlength*12) ) d.triangles = [t.clone() for t in self.triangles] d.refresh_batch() return d def mutate(self, num_mutations): triangles = self.triangles for i in xrange(0, num_mutations): e = randint(0,2) if e == 0: choice = randint(0, len(triangles)-1) triangles[choice].recolor_self_delta(5) self.update_index(choice) elif e == 1: choice = randint(0, len(triangles)-1) triangles[choice].reshape_delta(self.width, self.height, 25) self.update_index(choice) elif e == 2: c1 = randint(0, len(triangles)-1) c2 = clamp(c1 + randint(-5,5), 0, len(triangles)-1) triangles[c1],triangles[c2] = triangles[c2],triangles[c1] self.update_index(c1) self.update_index(c2) def update_index(self, i): vl = self.vertex_list t = self.triangles[i] i1 = i*6 vl.vertices[i1:i1+6] = t.serialize_points() i1 *= 2 vl.colors[i1:i1+12] = t.serialize_color()*3 def draw(self): gl.glBindFramebufferEXT(gl.GL_FRAMEBUFFER_EXT, self.fb) gl.glClear(gl.GL_COLOR_BUFFER_BIT) self.batch.draw() def refresh_batch(self): for i in xrange(0, len(self.triangles)): self.update_index(i) def generate(self, number_triangles): vertices = [] colors = [] for i in xrange(0, number_triangles): t = Triangle() t.generate(self.width, self.height) self.triangles.append(t) vertices.extend(t.serialize_points()) colors.extend(t.serialize_color()*3) self.vertex_list = self.batch.add( number_triangles*3, gl.GL_TRIANGLES, None, ("v2i/stream", vertices), ("c4B/stream", colors) ) self.refresh_batch() def svg_import(self, svg_file): """ Import the drawing from an SVG file. """ xml = open(svg_file).read() soup = BeautifulStoneSoup(xml).svg # Width and Height w = int(soup['width'].replace('px', '')) h = int(soup['height'].replace('px', '')) if w != self.width or h != self.height: raise Exception("Image dimensions don't match.") # two clockwise round triangles make a square self.bg.vertices = [ 0,0, 0,h, w,h, w,h, w,0, 0,0] # Background colours try: name,value = soup.rect['style'].split(':') except ValueError: pass if name == 'fill': self.bg_colour[0] = int(value[1:3], 16) self.bg_colour[1] = int(value[3:5], 16) self.bg_colour[2] = int(value[5:7], 16) self.bg.colors = self.bg_colour*6 # Polygons polygons = soup.findAll('polygon') vertices = [] colors = [] for p in polygons: T = Triangle() T.svg_soup_import(p, self.height) self.triangles.append(T) vertices.extend(T.serialize_points()) colors.extend(T.serialize_color()*3) self.vertex_list = self.batch.add( len(polygons)*3, gl.GL_TRIANGLES, XTranslationGroup(self.width * 2, 1), ("v2i/stream", vertices), ("c4B/stream", colors) ) self.refresh_batch() def svg_export(self, image_file, svg_file): """ Export the drawing to an SVG file. """ f = open(svg_file,"w") f.write('''<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="%dpx" height="%dpx" viewport="0 0 %d %d" version="1.1" xmlns="http://www.w3.org/2000/svg">''' % (self.width,self.height,self.width,self.height)) f.write('\n\t<rect width="100%%" height="100%%" style="fill:#%02x%02x%02x;" />' % ( self.bg_colour[0],self.bg_colour[1],self.bg_colour[2] ) ) for t in self.triangles: f.write('''\n\t<polygon points="%d,%d %d,%d %d,%d" style="fill:#%02x%02x%02x; fill-opacity:%f;" />''' % ( t.points[0][0], self.height - t.points[0][1], t.points[1][0], self.height - t.points[1][1], t.points[2][0], self.height - t.points[2][1], t.color[0],t.color[1],t.color[2],t.color[3]/255.0 )) f.write("\n</svg>") f.close()
class ProjectileViewer(object): """docstring for ProjectileViewer""" def __init__(self, get_cent): super(ProjectileViewer, self).__init__() self.projs = {} self.data = proto.Projectile() from pyglet.graphics import Batch self.batch = Batch() self.get_center = get_cent def process_proj(self, datagram): self.data.CopyFrom(datagram) ind = self.data.projId if not self.data.toDelete: vel = vec2(self.data.velx, self.data.vely) pos = vec2(self.data.posx, self.data.posy) if ind in self.projs: self.projs[ind].update(*pos) else: if self.data.type == proto.melee: self.projs[ind] = Rect(pos.x, pos.y, width=70, height=70, color=(255, 0, 0), batch=self.batch) self.projs[ind].vel = vel elif self.data.type == proto.blaster: self.projs[ind] = Rect(pos.x, pos.y, width=15, height=15, color=weaponcolors['w3'], batch=self.batch) self.projs[ind].vel = vel elif self.data.type == proto.explBlaster: self.projs[ind] = Rect(pos.x, pos.y, width=250, height=250, color=(255, 0, 150), batch=self.batch) self.projs[ind].vel = vel elif self.data.type == proto.lg: id = self.data.playerId length = self.data.posx playerhit = self.data.posy center, mpos = self.get_center(id) mpos = vec2(*mpos) dr = mpos - center line = DrawaAbleLine(center.x, center.y, dr.x, dr.y, length=length, batch=self.batch, color=weaponcolors['w2']) if playerhit: line.update_color((255, 0, 0)) line.time = 0.05 line.id = id self.projs[ind] = line elif self.data.type == proto.sg: id = self.data.playerId playerhit = self.data.posy center, mpos = self.get_center(id) mpos = vec2(*mpos) dr = mpos - center dys = spread(dr.x, dr.y, angle=0.2, num=6) cont = ProjContainer(0.05, id) for dy in dys: un = vec2(dr.x, dy) un = un / un.mag() line = DrawaAbleLine(center.x + un.x * 40, center.y + un.y * 40, dr.x, dy, length=100, batch=self.batch, color=weaponcolors['w1']) if playerhit: line.update_color((255, 0, 0)) cont.append(line) self.projs[ind] = cont else: raise ValueError else: try: self.projs[ind].remove() del self.projs[ind] except KeyError: pass def update(self, dt): todelete = [] for key, proj in self.projs.iteritems(): if isinstance(proj, Rect): pos = proj.pos + proj.vel * dt proj.update(*pos) elif isinstance(proj, Line): proj.time -= dt if proj.time <= 0: proj.remove() todelete.append(key) center, mpos = self.get_center(proj.id) proj.update(center.x, center.y, mpos[0], mpos[1]) elif isinstance(proj, ProjContainer): proj.time -= dt if proj.time <= 0: for p in proj: p.remove() todelete.append(key) for p in proj: u = p.unit m = p.pos + u + u*50 p.update(p.pos.x + u.x*50, p.pos.y + u.y*50, m.x, m.y) for key in todelete: del self.projs[key] def draw(self): self.batch.draw()
class VictoryScene(Scene): def __init__(self, world, winner): super(VictoryScene, self).__init__(world) self.winner = winner self.text_batch = Batch() self.cursor = Label(">", font_name='Times New Roman', font_size=36, x=280 + self.camera.offset_x, y=200 + self.camera.offset_y, batch=self.text_batch) self.cursor_pos = 0 self.menu_items = { "Main Menu" : self._main_menu } self._generate_text() self.key_handlers = { (key.UP, 0) : lambda: self._move_cursor(1), (key.DOWN, 0) : lambda: self._move_cursor(-1), (key.ENTER, 0) : self._menu_action } def on_draw(self): self.window.clear() # Display the previous scene, then tint it self.text_batch.draw() def on_key_press(self, button, modifiers): key = (button, modifiers) handler = self.key_handlers.get(key, lambda: None) handler() def _draw_overlay(self): pattern = SolidColorImagePattern((0, 0, 100, 200)) overlay_image = pattern.create_image(1000, 1000) overlay_image.anchor_x = overlay_image.width / 2 overlay_image.anchor_y = overlay_image.height / 2 overlay = Sprite(overlay_image, self.camera.x, self.camera.y) overlay.draw() def _generate_text(self): real_cord = lambda x,y: (x + self.camera.offset_x, y + self.camera.offset_y) menu_texts = reversed(self.menu_items.keys()) for i, text in enumerate(menu_texts): text_x, text_y = real_cord(300, 200 - 40 * i) Label(text, font_name='Times New Roman', font_size=36, x=text_x, y=text_y, batch=self.text_batch) hint_x, hint_y = real_cord(400, 30) Label("Use Up and Down Arrows to navigate", font_name='Times New Roman', font_size=18, x=hint_x, y=hint_y, batch=self.text_batch) Label("Use Enter to choose", font_name='Times New Roman', font_size=18, x=hint_x, y=hint_y - 20, batch=self.text_batch) Label("Player %s Won!" % self.winner, font_name='Times New Roman', font_size=48, x=hint_x - 150, y=hint_y + 370, batch=self.text_batch) def _menu_action(self): actions = list(reversed(self.menu_items.values())) actions[self.cursor_pos]() def _move_cursor(self, direction): self.cursor_pos = (self.cursor_pos - direction) % len(self.menu_items) self.cursor.y = 500 + self.camera.offset_y - 40 * self.cursor_pos def _main_menu(self): self.world.transition(MainMenuScene)
class Game(Window): def __init__(self): """This is run when the game is created""" super(Game, self).__init__() # A handler that watches the keyboard state self.keyboard = key.KeyStateHandler() self.set_handlers(self.keyboard) #label for the pause menu # self.label = pyglet.text.Label # Create the sprites self.player = Player(self, self.keyboard, images['arch'], x=100, y=50) self.bullet_batch = Batch() self.bullets = [] #background stars self.star_batch = Batch() self.stars = [] self.fast_star_batch = Batch() self.fast_stars = [] #windows enemies self.enemy_batch = Batch() self.win_enemy = [] # Display the current FPS on screen self.fps_display = clock.ClockDisplay() clock.schedule_interval(self.update_bullets, 1/30.0) clock.schedule_interval(self.fire_bullets, 1/15.0) #update background clock.schedule_interval(self.update_stars, 1/15.0) clock.schedule_interval(self.background_1, 1/10.0) clock.schedule_interval(self.update_back_stars, 1/30.0) clock.schedule_interval(self.background_2, 1/20.0 ) time = random.uniform(2.0, 5.0) #update enemies clock.schedule_interval(self.update_enemy, 1/60.0) clock.schedule_interval(self.enemy, 1/time) #update enemy hit clock.schedule_interval(self.on_hit, 1/60.0) #check players health clock.schedule_interval(self.checkHealth, 1/60.0) #refreshes player info clock.schedule_interval(self.gui_update, 1/60.0) #update player hit clock.schedule_interval(self.on_hit_player, 1/59.0) def gui_update(self, dt): self.player_points = pyglet.text.Label('Player Points: %d' % self.player.points, font_size=14, x= 100, y= 25, anchor_x='center', ) self.player_health = pyglet.text.Label('Player Health: %d' % self.player.health, font_size=14, x= 275, y= 25, anchor_x='center', ) #change border to allow sprites off screen def is_sprite_in_bounds(self, sprite, border=-50): """Returns true if a sprite is in the window""" x = sprite.x + sprite.width / 2 y = sprite.y + sprite.height / 2 return (border < x < self.width - border and border < y < self.height - border) #-------------------------------------Enemies section --------------------------# def update_enemy(self, dt): for enemy in self.win_enemy: enemy.x = enemy.x - dt * 200 enemy.y = enemy.startY + math.sin((enemy.x + enemy.startY) / 50)*50 if not self.is_sprite_in_bounds(enemy): self.win_enemy.remove(enemy) def enemy(self, dt): """creates enemies """ enemy = Sprite(images['windows'], batch=self.enemy_batch) enemy.y = random.uniform(0, self.width) enemy.x = self.width enemy.startX = enemy.x enemy.startY = enemy.y self.win_enemy.append(enemy) #--------------------------------------Background stuff -------------------------# def update_back_stars(self, dt): for fast_star in self.fast_stars: fast_star.x = fast_star.x + (fast_star.scale-10)*1.0 if not self.is_sprite_in_bounds(fast_star): self.fast_stars.remove(fast_star) def background_2(self, dt): """Random stars created in back moving faster""" fast_star = Sprite(images['star'], batch=self.fast_star_batch) fast_star.y = random.uniform(0, self.height) fast_star.x = self.width fast_star.scale = random.uniform(0.2, 2) self.fast_stars.append(fast_star) #creates a load of left moving stars for background def update_stars(self, dt): for star in self.stars: star.x = star.x + (star.scale-10)*1.0 if not self.is_sprite_in_bounds(star): self.stars.remove(star) def background_1(self, dt): """create random number of stars at random y co ordinates""" #for star in self.star: star = Sprite(images['star'], batch=self.star_batch) star.y = random.uniform(0,self.width-2) star.x = self.width star.scale = random.uniform(0.2, 2) self.stars.append(star) #-----------------------------------bullet update and collision------------------# def update_bullets(self, dt): for bullet in self.bullets: bullet.x = bullet.x + dt * 800 if not self.is_sprite_in_bounds(bullet): self.bullets.remove(bullet) def fire_bullets(self, dt): if self.keyboard[key.SPACE]: self.fire() def on_hit(self, dt): for bullet in self.bullets: for enemy in self.win_enemy: # print bullet.x if bullet.x > enemy.x and bullet.x < (enemy.x + enemy.width) and bullet.y < enemy.y+enemy.height and bullet.y > enemy.y-enemy.height: self.bullets.remove(bullet) self.win_enemy.remove(enemy) self.player.points += 1 print "Points: %d" % (self.player.points) ################################################################# Check player health if <= 0 clear screen display game over def checkHealth(self, dt): if self.player.health <= 0: self.clear_schedules() self.player.health = 5 def clear_schedules(self): clock.unschedule(self.update_bullets) clock.unschedule(self.fire_bullets) clock.unschedule(self.update_stars) clock.unschedule(self.background_1) clock.unschedule(self.update_back_stars) clock.unschedule(self.background_2) clock.unschedule(self.update_enemy) clock.unschedule(self.enemy) clock.unschedule(self.on_hit) clock.unschedule(self.checkHealth) clock.unschedule(self.gui_update) clock.unschedule(self.on_hit_player) clock.unschedule(self.player.move) #self.clear(); def resume(self): clock.schedule_interval(self.update_bullets, 1/30.0) clock.schedule_interval(self.fire_bullets, 1/15.0) clock.schedule_interval(self.update_stars, 1/15.0) clock.schedule_interval(self.background_1, 1/10.0) clock.schedule_interval(self.update_back_stars, 1/30.0) clock.schedule_interval(self.background_2, 1/20.0 ) clock.schedule_interval(self.update_enemy, 1/60.0) time = random.uniform(2.0, 5.0) clock.schedule_interval(self.enemy, 1/time) clock.schedule_interval(self.on_hit, 1/60.0) clock.schedule_interval(self.checkHealth, 1/60.0) clock.schedule_interval(self.gui_update, 1/60.0) clock.schedule_interval(self.on_hit_player, 1/59.0) clock.schedule_interval(self.player.move, 1/60.0) ################################################################### def on_hit_player(self, dt): for enemy in self.win_enemy: if enemy.x < self.player.x and enemy.x > self.player.x-self.player.width and enemy.y < self.player.y+self.player.height and enemy.y > self.player.y-self.player.height: self.win_enemy.remove(enemy) self.player.health = self.player.health -1 print "Health: %d" % self.player.health def on_draw(self): """Clear the window, display the framerate and draw the sprites""" self.clear() self.fps_display.draw() # Draw the sprites self.star_batch.draw() self.fast_star_batch.draw() self.enemy_batch.draw() self.player.draw() self.bullet_batch.draw() self.player_points.draw() self.player_health.draw() def fire(self): """Create a new bullet""" bullet = Sprite(images['bullet'], batch=self.bullet_batch) bullet.x = self.player.x + self.player.width bullet.y = self.player.y + self.player.height / 2 - bullet.height / 2 self.bullets.append(bullet) def on_mouse_press(self, x, y, button, modifiers): """This is run when a mouse button is pressed""" if button == mouse.LEFT: print "The left mouse button was pressed." elif button == mouse.RIGHT: print "The right mouse button was pressed."
class NewMenu(object): """docstring for NewMenu""" def __init__(self, vool=None, window=None): super(NewMenu, self).__init__() #self.text_boxes = {} self.m_pos = [0, 0] self.keys = key_.KeyStateHandler() self.keys_old = key_.KeyStateHandler() self.listeners = {} self.bool = vool self.keys_old[key_.ESCAPE] = True self.batch = Batch() self.window = window self.scale = vec2(window.width / 1280., window.height / 720.) self.layout = MenuLayout(self.batch, self.scale) def update(self, dt): buttons = 0 for key, button in self.layout: if button.over_button(*self.m_pos): button.highlight() buttons += 1 try: if self.keys[1338]: self.handle_clicks(key) except KeyError: continue else: button.restore() if not buttons and self.keys[1338] and not self.keys_old[1338]: self.handle_empty() self.add_update(dt) self.keys_old.update(self.keys) # receive events def receive_event(self, event, msg): if event == 'changed_mouse': self.m_pos = msg if event == 'all_input': self.keys = msg # send events def register(self, listener, events=None): self.listeners[listener] = events def send_message(self, event, msg=None): for listener, events in self.listeners.items(): #try: listener(event, msg) #except (Exception, ): # self.unregister(listener) def unregister(self, listener): print '%s deleted' % listener del self.listeners[listener] def draw(self): self.batch.draw() def handle_clicks(self, key): pass def handle_empty(self): pass def add_update(self, dt): pass def restore(self): self.layout.restore()
class InGameMenuScene(Scene): def __init__(self, world, previous): super(InGameMenuScene, self).__init__(world) self.text_batch = Batch() self.old_scene = previous self.cursor = Label(">", font_name='Times New Roman', font_size=36, x=360 + self.camera.offset_x, y=500 + self.camera.offset_y, batch=self.text_batch) self.cursor_pos = 0 self.menu_items = { "Resume" : self._resume_game, "Help" : self._launch_help, "Quit Current Game" : self._quit_game } self._generate_text() self.key_handlers = { (key.ESCAPE, 0) : self._resume_game, (key.UP, 0) : lambda: self._move_cursor(1), (key.DOWN, 0) : lambda: self._move_cursor(-1), (key.ENTER, 0) : self._menu_action } def on_draw(self): self.window.clear() # Display the previous scene, then tint it self.old_scene.on_draw() self._draw_overlay() self.text_batch.draw() def on_key_press(self, button, modifiers): key = (button, modifiers) handler = self.key_handlers.get(key, lambda: None) handler() def _draw_overlay(self): pattern = SolidColorImagePattern((0, 0, 0, 200)) overlay_image = pattern.create_image(1000, 1000) overlay_image.anchor_x = overlay_image.width / 2 overlay_image.anchor_y = overlay_image.height / 2 overlay = Sprite(overlay_image, self.camera.x, self.camera.y) overlay.draw() def _generate_text(self): real_cord = lambda x,y: (x + self.camera.offset_x, y + self.camera.offset_y) pause_x, pause_y = real_cord(10, 10) Label('Paused', font_name='Times New Roman', font_size=56, x=pause_x, y=pause_y, batch=self.text_batch) menu_texts = reversed(self.menu_items.keys()) for i, text in enumerate(menu_texts): text_x, text_y = real_cord(400, 500 - 40 * i) Label(text, font_name='Times New Roman', font_size=36, x=text_x, y=text_y, batch=self.text_batch) hint_x, hint_y = real_cord(400, 30) Label("Use Up and Down Arrows to navigate", font_name='Times New Roman', font_size=18, x=hint_x, y=hint_y, batch=self.text_batch) Label("Use Enter to choose", font_name='Times New Roman', font_size=18, x=hint_x, y=hint_y - 20, batch=self.text_batch) def _menu_action(self): actions = list(reversed(self.menu_items.values())) actions[self.cursor_pos]() def _move_cursor(self, direction): self.cursor_pos = (self.cursor_pos - direction) % len(self.menu_items) self.cursor.y = 500 + self.camera.offset_y - 40 * self.cursor_pos def _resume_game(self): self.world.reload(self.old_scene) def _launch_help(self): pass def _quit_game(self): self.world.transition(MainMenuScene)
class MainMenuScene(Scene): def __init__(self, world): super(MainMenuScene, self).__init__(world) self.text_batch = Batch() self.cursor = Label(">", font_name='Times New Roman', font_size=36, x=200 + self.camera.offset_x, y=300 + self.camera.offset_y, batch=self.text_batch) self.cursor_pos = 0 self.moogle = self._load_moogle() self.menu_items = { "Start Game" : self._new_game, "About" : self._launch_about, "Quit Program" : self.window.close } self._generate_text() self.key_handlers = { (key.ESCAPE, 0) : self.window.close, (key.UP, 0) : lambda: self._move_cursor(1), (key.DOWN, 0) : lambda: self._move_cursor(-1), (key.ENTER, 0) : self._menu_action } def enter(self): black = 0, 0, 0, 0 pyglet.gl.glClearColor(*black) def on_draw(self): self.world.window.clear() self.moogle.draw() self.text_batch.draw() self.camera.focus(self.window.width, self.window.height) def on_key_press(self, button, modifiers): key = (button, modifiers) handler = self.key_handlers.get(key, lambda: None) handler() def _generate_text(self): real_cord = lambda x,y: (x + self.camera.offset_x, y + self.camera.offset_y) title_x, title_y = real_cord(10, 520) Label('FF:Tactics.py', font_name='Times New Roman', font_size=56, x=title_x, y=title_y, batch=self.text_batch) menu_texts = self.menu_items.keys() for i, text in enumerate(menu_texts): text_x, text_y = real_cord(240, 300 - 40 * i) Label(text, font_name='Times New Roman', font_size=36, x=text_x, y=text_y, batch=self.text_batch) hint_x, hint_y = real_cord(400, 30) Label("Use Up and Down Arrows to navigate", font_name='Times New Roman', font_size=18, x=hint_x, y=hint_y, batch=self.text_batch) Label("Use Enter to choose", font_name='Times New Roman', font_size=18, x=hint_x, y=hint_y - 20, batch=self.text_batch) def _load_moogle(self): moogle_image = load_sprite_asset("moogle") moogle_image.anchor_x = moogle_image.width / 2 moogle_image.anchor_y = moogle_image.height / 2 moog_sprite = Sprite(moogle_image, 40 + self.camera.offset_x, 40 + self.camera.offset_y) return moog_sprite def _new_game(self): self.world.transition(GameScene) def _launch_about(self): self.world.transition(AboutScene, previous=self) def _menu_action(self): actions = self.menu_items.values() actions[self.cursor_pos]() def _move_cursor(self, direction): self.cursor_pos = (self.cursor_pos - direction) % len(self.menu_items) self.cursor.y = 300 + self.camera.offset_y - 40 * self.cursor_pos
class Map(object): """docstring for Map""" def __init__(self, mapname, server=False): super(Map, self).__init__() self.name = mapname self.rects = [] self.quad_tree = None self.server = server if server: self.Rect = AABB self.Armor = Armor self.batch = None else: self.Rect = Rect self.Armor = DrawableArmor from pyglet.graphics import Batch self.batch = Batch() self.items = ItemManager(self.batch) try: self.load(''.join(('maps/', mapname, '.svg'))) except ET.ParseError: pass def load(self, mapname): tree = ET.parse(mapname) root = tree.getroot() rects = [] for child in root.getchildren(): if child.attrib['id'] == 'layer1': for rect in child: atr = rect.attrib x = float(atr['x']) y = float(atr['y']) width = float(atr['width']) height = float(atr['height']) color = (255, 255, 255) rects.append(self.Rect(x, - y - height, width, height, color, batch=self.batch)) max_x = max(rect.pos.x + rect.width for rect in rects) max_y = max(rect.pos.y + rect.height for rect in rects) self.quad_tree = QuadTree(0, self.Rect(0, 0, max_x, max_y), server=self.server) self.rects = rects self.quad_tree.clear() for rect in rects: self.quad_tree.insert(rect) self.spawns = [] for child in root.getchildren(): if child.attrib['id'] == 'layer2': for recht in child: atr = recht.attrib x = float(atr['x']) y = float(atr['y']) height = float(atr['height']) self.spawns.append(vec2(x, -y - height)) #armors self.ind = 0 for child in root.getchildren(): if child.attrib['id'] == 'armors': for rect in child: atr = rect.attrib x = float(atr['x']) y = float(atr['y']) width = float(atr['width']) height = float(atr['height']) avalue = int(atr['armor']) color, maxarmor = armors[avalue] respawn = timers['armor'] armor = self.Armor(x=x, y=-y-height, width=width, height=height, value=avalue, bonus=False, respawn=respawn, color=color, ind=self.ind, maxarmor=maxarmor, batch=self.batch) self.items.add(armor) self.ind += 1 #healths for child in root.getchildren(): if child.attrib['id'] == 'health': for rect in child: atr = rect.attrib x = float(atr['x']) y = float(atr['y']) width = float(atr['width']) height = float(atr['height']) hvalue = int(atr['health']) color, maxhp = health[hvalue] respawn = timers['health'] if self.server: health_ = Health(x=x, y=-y-height, width=width, height=height, value=hvalue, bonus=False, respawn=respawn, color=color, ind=self.ind, maxhp=maxhp, batch=self.batch) else: health_ = HealthBox(x, -y - height, width, height, color=color, batch=self.batch, ind=self.ind) self.items.add(health_) self.ind += 1 #weapons for child in root.getchildren(): if child.attrib['id'] == 'weapons': for rect in child: atr = rect.attrib x = float(atr['x']) y = float(atr['y']) width = float(atr['width']) height = float(atr['height']) weapstr = atr['weapon'] color = weaponcolors[weapstr] respawn = timers['weapons'] if self.server: w = allweapons[weapstr] w_ = w(0, 0, x=x, y=-y-height, width=width, height=height, respawn=respawn, color=color, ind=self.ind, batch=self.batch) self.items.add(w_) else: w_ = Triangle(x=x, y=-y-height, width=width, height=height, color=color, ind=self.ind, batch=self.batch, keystr=weapstr) self.items.add(w_) self.ind += 1 #ammo for child in root.getchildren(): if child.attrib['id'] == 'ammo': for rect in child: atr = rect.attrib x = float(atr['x']) y = float(atr['y']) width = float(atr['width']) height = float(atr['height']) weapstr = atr['weapon'] color = weaponcolors[weapstr] max_ammo, ammoval = ammo_values[weapstr] respawn = timers['weapons'] if self.server: w_ = Ammo(x=x, y=-y-height, width=width, height=height, respawn=respawn, color=color, ind=self.ind, batch=self.batch, max_ammo=max_ammo, ammoval=ammoval, keystring=weapstr) self.items.add(w_) else: w_ = AmmoTriangle(x=x, y=-y-height, width=width, height=height, color=color, ind=self.ind, batch=self.batch, keystr=weapstr) self.items.add(w_) self.ind += 1 #tele for child in root.getchildren(): if child.attrib['id'] == 'teles': for rect in child: atr = rect.attrib x = float(atr['x']) y = float(atr['y']) width = float(atr['width']) height = float(atr['height']) destination = vec2(float(atr['dest_x']), float(atr['dest_y'])) dest_sign = int(atr['dest_sign']) color = (255, 255, 0) max_ammo, ammoval = ammo_values[weapstr] if self.server: w_ = Teleporter(x=x, y=-y-height, width=width, height=height, color=color, ind=self.ind, destination=destination, dest_sign=dest_sign) self.items.add(w_) else: w_ = DrawableTeleporter(x=x, y=-y-height, width=width, height=height, color=color, batch=self.batch) self.items.add(w_) self.ind += 1 def draw(self): self.batch.draw() def serverupdate(self, itemid, spawn): self.items.fromserver(itemid, spawn)
class Piece(object): # TODO: Different piece color per player (duh) command_count = 0 # number of pieces this can command speed = 0 # number of movement squares rotation_angle = 360 # rotations must be a multiple of this number rotation_offset = 0 # number of degress offset it starts at # piece state moved = False # TODO: this probably is no longer necessary # rendering _model = None def __init__(self, board, player, x, y, direction): self.board = weakref.proxy(board) self.player = player # TODO: weakref? # place the piece on the board self.position = Vector3(x - 3.5, y - 3.5, 0) # load the model # TODO: Cached loading model_filename = 'skins/pieces/default/models/player{}/{}.obj'.format( self.player.player_index, self.__class__.__name__) self._obj = OBJ(model_filename, texture_path='skins/pieces/default/textures/') self.batch = Batch() self._obj.add_to(self.batch) # set the rotation self.direction = direction self.old_direction = self.direction # TODO: is angle necessary anymore? self.angle = (self.direction.angle(X_AXIS)*180/math.pi - self.rotation_offset) # generate a color key # TODO: Ensure this *never* collides (it definitely has a chance) self.color_key = (randint(1, 254) / 255., randint(1, 254) / 255., randint(1, 254) / 255.) self._color_key_processed = [int(round(_*255)) for _ in self.color_key] # set remaining_move to speed self.remaining_move = self.speed def draw(self, scale=1): gl.glPushMatrix() gl.glEnable(gl.GL_TEXTURE_2D) gl.glTranslatef(*self.position) gl.glRotatef(self.angle, 0, 0, 1) gl.glScalef(scale, scale, scale) self.batch.draw() gl.glPopMatrix() def draw_for_picker(self, scale=1): # disable stuff gl.glDisable(gl.GL_TEXTURE_2D) gl.glDisable(gl.GL_LIGHTING) gl.glColor3f(*self.color_key) gl.glPushMatrix() gl.glTranslatef(*self.position) gl.glRotatef(self.angle, 0, 0, 1) gl.glScalef(scale, scale, scale) # This is a weird way of doing it, but hey, whatever for v1 in self.batch.group_map.values(): for v2 in v1.values(): v2.draw(gl.GL_TRIANGLES) gl.glPopMatrix() # re-enable stuff gl.glEnable(gl.GL_LIGHTING) gl.glEnable(gl.GL_TEXTURE_2D) @property def rotated(self): return roundvec(self.direction) != roundvec(self.old_direction) def rotate(self): self.direction = self.direction.rotate_around( Z_AXIS, self.rotation_angle * math.pi / 180) self.angle += self.rotation_angle def reset(self): self.moved = False self.remaining_move = self.speed self.old_direction = self.direction def move(self): # This is always an *attempted* move, so it's marked such. self.moved = True # Decrement the recursion counter or exit if self.remaining_move: self.remaining_move -= 1 else: return # Make the vector have all 1s, 0s, and -1s. v = roundvec(self.direction, 0) # Check out of bounds target = self.position + v # Only move one square at a time # Adjust because board center is (0, 0) w, h = self.board.width / 2, self.board.height / 2 if abs(target.x) > w or abs(target.y) > h: return # Check the board for pieces existing at the target for p in self.board.pieces[:]: if p.position == target: engaged = roundvec(p.direction) == roundvec(-self.direction) can_capture = not engaged or p.rotation_angle == 360 if p.player != self.player and can_capture: self.board.pieces.remove(p) else: return # All's clear! Move. self.position = target # Recurse self.move() @property def square_center(self): x, y = self.position.x, self.position.y return int(x) + copysign(.5, x), int(y) + copysign(.5, y) def matches_color(self, color): return self._color_key_processed == color
class Shape(object): ''' Shapes have Vertices, a single color a single OpenGL primitive : GL_LINE_STRIP,GL_TRIANGLE_STRIP, GL_POINTS, GL_LINES ''' _instances = set() def __init__(self, **kwargs): for key in kwargs: setattr(self,key,kwargs[key]) if not hasattr(self,'peg'): # peg must be tuple (x, y, a) self.peg = DOCKED if not hasattr(self,'vel'): # peg must be tuple (vx, vy, av) self.vel = IDLE self.build() self.aabb=get_aabb(self.verts) self.flat_verts = None self.batch=None self._instances.add(weakref.ref(self)) print "::" print ":: new shape ::::::::::::::::::::::::::::::::::::::::::::::::::" print "::" dumpObj(self) @classmethod def get_instances(cls): dead = set() for ref in cls._instances: obj = ref() if obj is not None: yield obj else: dead.add(ref) cls._instances -= dead def copy(self): ssh=Shape(verts=self.verts, color=self.color,\ primtype=self.primtype, peg=self.peg, vel=self.vel) return(ssh) def get_flat_verts(self): if self.flat_verts is None: self.flat_verts = \ list(self.verts[0]) + \ [x for x in chain(*self.verts)] + \ list(self.verts[-1]) return self.flat_verts def get_batch(self): self.batch = Batch() flatverts = self.get_flat_verts() numverts = len(flatverts) / 2 self.batch.add( numverts, self.primtype, None, ('v2f/static', flatverts), ('c4B/static', self.color * numverts) ) def paint(self): if self.batch is None: self.get_batch() glPushMatrix() glTranslatef(self.peg.x, self.peg.y, self.peg.z) glRotatef(self.peg.angle, 0, 0, 1) self.batch.draw() glPopMatrix() print'.', def build(self): pass
class Swept: def __init__(self, data, slices, rings): self.type = data.type self.sections = data.sections self.scales = CMSpline(data.scales, None, False) self.translates = CMSpline(data.translates, None, False) self.orients = CMSpline(data.orients, Quaternion, False) self.curves = [] self.slices = slices self.rings = rings self.positions = [] # loops for i in range(len(self.scales.pieces)): self.curves.insert(i, self.type(data.curves[i],None, True)) # positions print "making positions" for i in range(len(self.scales.pieces)): scale = n.dot(BezBase, self.scales.pieces[i]) translate = n.dot(BezBase, self.translates.pieces[i]) rotate = self.orients.pieces[i] for j in n.linspace(0, 1, self.rings, endpoint=False): mono = n.array([j**3, j**2, j, 1], dtype=GLfloat).reshape((1,4)) scale_ = n.dot(mono, scale) translate_ = n.dot(mono, translate) s0 = Quaternion.slerp(j, rotate[0], rotate[1]) s1 = Quaternion.slerp(j, rotate[1], rotate[2]) s2 = Quaternion.slerp(j, rotate[2], rotate[3]) s3 = Quaternion.slerp(j, s0, s1) s4 = Quaternion.slerp(j, s1, s2) rotate_ = Quaternion.slerp(j, s3, s4) poses = [] for l in self.curves[i].pieces: for k in n.linspace(0, 1, self.slices, endpoint=False): mono_ = n.array([k**3, k**2, k, 1], dtype=GLfloat) pos = n.dot(n.dot(mono_, self.type.base), l) pos = scale_[0]*pos pos = (rotate_*Quaternion(0, *pos)*rotate_.inv()).arr pos = pos + translate_ poses.append(*pos) self.positions.append(poses) # normals print "making normals" self.normals = [] norms = [] l = len(self.positions[0]) center = sum(self.positions[0])/l for i in range(l): v1 = self.positions[0][(i+1)%l] - self.positions[0][i] v2 = self.positions[1][i] - self.positions[0][i] v3 = self.positions[0][i-1] - self.positions[0][i] n1 = Vec3(*n.cross(v1, v2)).normalized() n2 = Vec3(*n.cross(v2, v3)).normalized() norm = (n1+n2).normalized().arr if n.dot(self.positions[0][i] - center, norm) < 0: norm = -norm norms.append(norm) self.normals.append(norms) for i in range(1, len(self.positions) - 1): norms = [] center = sum(self.positions[i])/l for j in range(l): v1 = self.positions[i][(j+1)%l] - self.positions[i][j] v2 = self.positions[i+1][j] - self.positions[i][j] v3 = self.positions[i][j-1] - self.positions[i][j] v4 = self.positions[i-1][j] - self.positions[i][j] n1 = Vec3(*n.cross(v1, v2)).normalized() n2 = Vec3(*n.cross(v2, v3)).normalized() n3 = Vec3(*n.cross(v3, v4)).normalized() n4 = Vec3(*n.cross(v4, v1)).normalized() norm = (n1+n2+n3+n4).normalized().arr if n.dot(self.positions[i][j] - center, norm) < 0: norm = -norm norms.append(norm) self.normals.append(norms) norms = [] center = sum(self.positions[-1])/l for i in range(l): v1 = self.positions[-1][i-1] - self.positions[-1][i] v2 = self.positions[-2][i] - self.positions[-1][i] v3 = self.positions[-1][(i+1)%l] - self.positions[-1][i] n1 = Vec3(*n.cross(v1, v2)).normalized() n2 = Vec3(*n.cross(v2, v3)).normalized() norm = (n1+n2).normalized().arr if n.dot(self.positions[-1][i] - center, norm) < 0: norm = -norm norms.append(norm) self.normals.append(norms) # making vertexes gl print "batching" self.batch = Batch() for i in range(1, len(self.positions)): poses = reduce(lambda x,y:x+y, map(lambda x,y:list(x)+list(y), self.positions[i-1], self.positions[i])) poses += poses[0:6] norms = reduce(lambda x,y:x+y, map(lambda x,y:list(x)+list(y), self.normals[i-1], self.normals[i])) norms += norms[0:6] self.batch.add(len(poses)/3, GL_TRIANGLE_STRIP, None, ('v3f/static', poses),('n3f/static', norms)) def draw(self): self.batch.draw()
class Snake(pyglet.event.EventDispatcher): MOVE_UP, MOVE_DOWN, MOVE_LEFT, MOVE_RIGHT = range(4) LIFE_ENERGY_COEFFICIENT_DX = 4 def __init__(self): super(Snake, self).__init__() self._batch = Batch() self.reset() def _opacity_gen(self): deg = 45 while True: if deg >= 45: yield 255 elif deg <= 10: yield 44 else: yield int(255*math.tan(math.radians(deg+1))) if deg > 0: deg -= 1 def reset(self): self._direction = Snake.MOVE_UP self._opacity_gen_obj = self._opacity_gen() self._life_energy = 100 self._init_body() def _init_body(self): #3 items at start head_value_x, head_value_y = SPRITES_COUNT_BY_X//2, 2 self._head = SnakeItem(head_value_x, head_value_y, opacity=self._opacity_gen_obj.next(), color=(0,255,32), batch=self._batch) nextItem = SnakeItem(head_value_x, head_value_y - 1, opacity=self._opacity_gen_obj.next(), batch=self._batch) self._head.next = nextItem self._last_tail_item = SnakeItem(head_value_x, head_value_y - 2, opacity=self._opacity_gen_obj.next(), batch=self._batch) nextItem.next = self._last_tail_item self._units_list = [(head_value_x, head_value_y), (head_value_x, head_value_y - 1), (head_value_x, head_value_y -2)] self._last_position = self._units_list[-1] def grow_tail(self): item = SnakeItem(*self._last_position, opacity=self._opacity_gen_obj.next(), batch=self._batch) self._last_tail_item.next = item self._last_tail_item = item self._units_list.append(item) @property def units_list(self): return self._units_list def __iter__(self): item = self.head while item is not None: yield item item = item.next def __len__(self): l = 0 for item in self: l += 1 return l @property def life_energy(self): return self._life_energy def inc_life_energy(self, value): self._life_energy += value @property def head(self): return self._head @head.setter def head(self, value): self._head = value @property def head_units(self): return self.head.x_units, self.head.y_units def draw(self): self._batch.draw() def update_direction(self, curr_pressed_key): if curr_pressed_key == key.LEFT: if self._direction == Snake.MOVE_UP: self._direction = Snake.MOVE_LEFT elif self._direction == Snake.MOVE_LEFT: self._direction = Snake.MOVE_DOWN elif self._direction == Snake.MOVE_DOWN: self._direction = Snake.MOVE_RIGHT else: assert(self._direction == Snake.MOVE_RIGHT) self._direction = Snake.MOVE_UP elif curr_pressed_key == key.RIGHT: if self._direction == Snake.MOVE_UP: self._direction = Snake.MOVE_RIGHT elif self._direction == Snake.MOVE_LEFT: self._direction = Snake.MOVE_UP elif self._direction == Snake.MOVE_DOWN: self._direction = Snake.MOVE_LEFT else: assert(self._direction == Snake.MOVE_RIGHT) self._direction = Snake.MOVE_DOWN def update(self, dt): self._life_energy -= dt*Snake.LIFE_ENERGY_COEFFICIENT_DX if self._life_energy <= 0: self.dec_life() tmp_item_x_units, tmp_item_y_units = self.head_units #update head position if self._direction == Snake.MOVE_UP: if self.head.y_units == SPRITES_COUNT_BY_Y-1: self.dec_life() return self.head.y_units += 1 elif self._direction == Snake.MOVE_DOWN: if self.head.y_units == 0: self.dec_life() return self.head.y_units -= 1 elif self._direction == Snake.MOVE_LEFT: if self.head.x_units == 0: self.dec_life() return self.head.x_units -= 1 else: assert(self._direction == Snake.MOVE_RIGHT) if self.head.x_units == SPRITES_COUNT_BY_X-1: self.dec_life() return self.head.x_units += 1 self._units_list[0] = self.head_units #check if a new head position hit the snake's tail if self._units_list.count(self._units_list[0]) > 1: self.dec_life() return #remember the last tail position self._last_position = self._units_list[-1] #update tail positions item = self.head.next i = 1 while item is not None: new_tmp_item_x_units, new_tmp_item_y_units = item.x_units, item.y_units self._units_list[i] = (item.x_units, item.y_units) = tmp_item_x_units, tmp_item_y_units tmp_item_x_units, tmp_item_y_units = new_tmp_item_x_units, new_tmp_item_y_units item = item.next i += 1 def dec_life(self): self._life_energy = 0 self.dispatch_event('on_death')
class MenuClass(object): """docstring for MenuClass base class for other menus to inherit from""" def __init__(self, vool=False, window=None): super(MenuClass, self).__init__() from pyglet.graphics import Batch from pyglet.window import key as key_ self.buttons = {} #self.text_boxes = {} self.m_pos = [0, 0] self.keys = key_.KeyStateHandler() self.keys_old = key_.KeyStateHandler() self.listeners = {} self.bool = vool self.keys_old[key_.ESCAPE] = True self.batch = Batch() self.window = window self.scale = vec2(window.width / 1280., window.height / 720.) @window def on_resize(width, height): self.scale = vec2(width / 1280., height / 720.) def update(self, dt): for key, button in self.buttons.items(): if button.in_box(self.m_pos): button.highlight() try: if self.keys[1338]: self.handle_clicks(key) except KeyError: continue else: button.restore() #self.animate(dt) self.add_update(dt) self.keys_old.update(self.keys) #for key, value in self.keys.items(): # self.keys_old[key] = value def draw(self): self.batch.draw() def handle_clicks(self, key): pass def add_update(self, dt): pass def on_draw(self): pass # receive events def receive_event(self, event, msg): if event == 'changed_mouse': self.m_pos = msg if event == 'all_input': self.keys = msg # send events def register(self, listener, events=None): self.listeners[listener] = events def send_message(self, event, msg=None): for listener, events in self.listeners.items(): #try: listener(event, msg) #except (Exception, ): # self.unregister(listener) def unregister(self, listener): print '%s deleted' % listener del self.listeners[listener] # animation def animate(self, dt): for key, panel in self.buttons.items(): panel.pos[0] -= (panel.pos[0] - panel.target_pos[0])*dt * 0.15*30 panel.update()
class TileMap(object): def __init__(self): self._batch = Batch() self.tile_images = [] self.tiles = [] self.tile_width = 0 self.tile_height = 0 self.camera_position = Vector() def load_from_file(self, filename): mapfile = resource.file(filename) data = json.load(mapfile) self._load_images(data['images']) self.tiles = [] for line in reversed(data['tiles']): tile_line = [] for tile_number in line: image = self.tile_images[tile_number] tile = Tile(image=image, batch=self._batch) tile.solid = image.solid tile_line.append(tile) self.tiles.append(tile_line) self.set_camera_position(0, 0) def draw(self): self._batch.draw() def set_camera_position(self, x, y): self.camera_position.set(x, y) self._adjust_position() def move_camera(self, x, y): self.camera_position.move(x, y) self._adjust_position() def get_tile_at(self, x, y): tile_x = x / self.tile_width tile_y = y / self.tile_height return self.tiles[tile_y][tile_x] def get_solid_tiles(self, tiles): for tile in tiles: if tile.solid: return tile def _adjust_position(self): x, y = self.camera_position.xy for pos_y, line in enumerate(self.tiles): for pos_x, tile in enumerate(line): if tile is not None: tile.x = pos_x * self.tile_width - x tile.y = pos_y * self.tile_height - y def _load_images(self, tiles): self.tile_images = [] for path, solid in tiles: image = resource.image(path) image.solid = solid self.tile_images.append(image) self.tile_width = max(image.width for image in self.tile_images) self.tile_height = max(image.height for image in self.tile_images)
class City: grid_size = STREET_GRID_SIZE offset_1 = (Vector(1, 1) * STREET_GRID_SIZE * 0.5,) offset_2 = (offset_1[0] + Vector( 0.5, 0.5) * STREET_GRID_SIZE * 0.5, offset_1[0] + Vector(-0.5, -0.5) * STREET_GRID_SIZE * 0.5) offset_3 = (offset_1[0] + Vector( 0.0, 0.5) * STREET_GRID_SIZE * 0.5, offset_1[0] + Vector(-0.5, -0.5) * STREET_GRID_SIZE * 0.5, offset_1[0] + Vector( 0.5, -0.5) * STREET_GRID_SIZE * 0.5) offset_4 = (offset_1[0] + Vector( 0.5, 0.5) * STREET_GRID_SIZE * 0.5, offset_1[0] + Vector(-0.5, 0.5) * STREET_GRID_SIZE * 0.5, offset_1[0] + Vector(-0.5, -0.5) * STREET_GRID_SIZE * 0.5, offset_1[0] + Vector( 0.5, -0.5) * STREET_GRID_SIZE * 0.5) offsets = (offset_1, offset_2, offset_3, offset_4) def __init__(self): self._tiles = [] self._height = 0 self._width = 0 self._batch = Batch() self.pawns = {} def build(self, width, height, tiles): for row in range(height): for col in range(width): index = len(self._tiles) tile_type = tiles[index] if tile_type: street = Street(col, row, tile_type, self.grid_size, self._batch) else: street = None self._tiles.append(street) self._width = width self._height = height def place_pawn(self, x, y, image): pawn = Pawn(image) pos = Vector(x, y) index = pos.to_index(self._width) container = self.pawns.get(index, []) count = len(container) container.append(pawn) self.pawns[index] = container offsets = self.offsets[len(container) - 1] for offset, pawn in zip(offsets, container): pawn.set_position(pos, offset) return pawn def remove_pawn(self, pawn): index = pawn.position.to_index(self._width) container = self.pawns[index] container.remove(pawn) def _recalc_positions(self, pos): index = pos.to_index(self._width) container = self.pawns[index] offsets = self.offsets[len(container) - 1] for offset, pawn in zip(offsets, container): pawn.set_position(pos, offset) def try_move(self, pawn, movement): pos = pawn.position new_pos = pos + movement if self.collide(new_pos): return Event(EVENT_OBSTACLE_HIT) old_index = pos.to_index(self._width) # Remove pawn self.pawns[old_index].remove(pawn) self._recalc_positions(pos) new_index = new_pos.to_index(self._width) container = self.pawns.get(new_index, []) event = Event(EVENT_EMPTY) if container: event = Event(EVENT_PAWN_HIT) event.pawns = list(container) # Add pawn container.append(pawn) self.pawns[new_index] = container self._recalc_positions(new_pos) return event def move(self, pawn, dest): old_index = pawn.position.to_index(self._width) new_index = dest.to_index(self._width) # Remove pawn self.pawns[old_index].remove(pawn) self._recalc_positions(pawn.position) # Add pawn container = self.pawns.get(new_index, []) container.append(pawn) self.pawns[new_index] = container self._recalc_positions(dest) def get_pawns(self, x, y): index = Vector(x, y).to_index(self._width) return list(self.pawns[index]) def render(self): self._batch.draw() for container in self.pawns.itervalues(): for pawn in container: pawn.render() def collide(self, pos): if not (0 <= pos.x < self._width): return True elif not (0 <= pos.y < self._height): return True else: return self._tiles[int(pos.y) * self._width + int(pos.x)] is None