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()
def cif_power_strip(x, y, z, width=1, height=1, depth=1): batch = Batch() outlet = True for i in range(width): for j in range(height): for k in range(depth): if outlet: strip_texture = texture.textures['cif_power_strip'] else: strip_texture = texture.textures['cif_power_outlet'] outlet = not outlet tile = cube_tile.CubeTile((x+i, y+j, z+k), textures={ 'top': texture.textures['cif_power_strip']['master_coordinates'], 'right': strip_texture['master_coordinates'], 'bottom': texture.textures['cif_power_strip']['master_coordinates'], 'left': strip_texture['master_coordinates'], 'front': strip_texture['master_coordinates'], 'back': strip_texture['master_coordinates'], }) vertex_list = tile.get_vertex_list() texture_list = tile.get_texture_list() vertices = len(vertex_list) / 3 batch.add(vertices, GL_QUADS, texture.textures['master']['group'], ('v3f/static', vertex_list), ('t2f/static', texture_list)) return batch
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()
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 Shape(object): ''' A list of primitives ''' def __init__(self, items=None): self.primitives = [] if items: self.add_items(items) self.batch = None def add_items(self, items): "Add a list of primitives and shapes" for item in items: if isinstance(item, Shape): self.add_shape(item) else: self.primitives.append(item) def add_shape(self, other): "Add the primitives from a given shape" for prim in other.primitives: self.primitives.append(prim) def get_batch(self): if self.batch is None: self.batch = Batch() for prim in self.primitives: flatverts = prim.get_flat_verts() numverts = len(flatverts) / 2 self.batch.add( numverts, prim.primtype, None, ('v2f/static', flatverts), ('c3B/static', prim.color * numverts) ) return self.batch def transform(self,M): """ applies matrix M to all self primitives """ for prim in self.primitives: prim.transform(M) def get_aabb(self): aabb = namedtuple('AABB',['xmin','xmax','ymin','ymax']) _allx=[] _ally=[] for prim in self.primitives: for v in prim.verts: _allx.append(v[0]) _ally.append(v[1]) minx=min(_allx) miny=min(_ally) maxx=max(_allx) maxy=max(_ally) box = (minx,miny,maxx,maxy) return (box)
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)
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 __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()
class OrbitingBody(Body, metaclass=ABCMeta): """ An orbiting body in the solarsystem """ def __init__(self, parent, name, texturename, color, radius, orbit, axial_tilt, sidereal_rotation_period, mass, renderer=OrbitingBodyRenderer()): """ Creates a new body with the given parameters :param parent: Parent body in the system :type parent: :class:`Body`, None :param name: Name of the body :type name: str :param texturename: Name of the texture :type texturename: str :param color: Dictionary with r, g and b values :type color: dict :param radius: Radius of the body :type radius: float :param orbit: Orbit of the body :type orbit: :class:`solarsystem.orbit.Orbit` :param axial_tilt: Axial Tilt in degrees :type axial_tilt: float :param sidereal_rotation_period: Rotation period (siderial) around its own axis :type sidereal_rotation_period: float """ super().__init__(parent, name, texturename, color, radius, axial_tilt, sidereal_rotation_period, mass, renderer=renderer) self.orbit = orbit self.orbit.body = self self.orbit_line_batch = Batch() def post_init(self): self.orbit.post_init() # Plot the orbit to a pyglet batch for faster drawing orbit_line = [] for pos in self.orbit.plot(plot_steps): orbit_line.append(pos.x) orbit_line.append(pos.y) orbit_line.append(pos.z) self.orbit_line_batch.add(int(len(orbit_line) / 3), GL_LINE_LOOP, None, ('v3f', tuple(orbit_line))) def update(self, time): """ Update the body (Calculate current orbit position) :param time: Delta Time :type time: float """ super().update(time) self.xyz = self.orbit.calculate(time) if self.parent: self.xyz += self.parent.xyz
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()
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)
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()
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 OrbitalObject(AstronomicalObject): """ An astronomical Object which moves around another """ def __init__(self, parent, name, texture_name, radius, axial_tilt, sidereal_rotation_period, mass, orbit, renderer=AOOrbitingRenderer()): """ Create a new orbiting astronomical Object :param parent: The objects parent (i.e. Sun for Earth) :param name: Name of the object (Earth, Saturn, Pluto, ...) :param texture_name: Name of the texture in the `res` directory :param radius: Radius of object :param axial_tilt: In astronomy, axial tilt is the angle between a planet's rotational axis at its north pole and a line perpendicular to the orbital plane of the planet - given in degrees. :param sidereal_rotation_period: The time required (in days) for a body within the solar system to complete one revolution with respect to the fixed stars—i.e., as observed from some fixed point outside the system. :param mass: Mass of the object in kilograms :param orbit: Orbit Class of this body """ super().__init__(parent, name, texture_name, radius, axial_tilt, sidereal_rotation_period, mass, renderer=renderer) self.orbit = orbit self.orbit.body = self self.orbit_line_batch = Batch() def config(self): """ Configure the Object """ self.orbit.config() orbit_line = [] for pos in self.orbit.pos(1024): orbit_line.append(pos.x) orbit_line.append(pos.y) orbit_line.append(pos.z) self.orbit_line_batch.add(int(len(orbit_line) / 3), GL_LINE_LOOP, None, ('v3f', tuple(orbit_line))) def update(self, time): """ Update the time in the solar system and position the object on its right coordinates :param time: Current solar time """ super().update(time) self.xyz = self.orbit.calculate(time)
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
def __init__(self): self._batch = Batch() self.tile_images = [] self.tiles = [] self.tile_width = 0 self.tile_height = 0 self.camera_position = Vector()
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 __init__(self, tilemap): self.tilemap = tilemap self.batch = Batch() self.layerviews = [LayerView(self, layer) for layer in tilemap.layers] self.refresh()
def __init__(self, parent, name, texturename, color, radius, orbit, axial_tilt, sidereal_rotation_period, mass, renderer=OrbitingBodyRenderer()): """ Creates a new body with the given parameters :param parent: Parent body in the system :type parent: :class:`Body`, None :param name: Name of the body :type name: str :param texturename: Name of the texture :type texturename: str :param color: Dictionary with r, g and b values :type color: dict :param radius: Radius of the body :type radius: float :param orbit: Orbit of the body :type orbit: :class:`solarsystem.orbit.Orbit` :param axial_tilt: Axial Tilt in degrees :type axial_tilt: float :param sidereal_rotation_period: Rotation period (siderial) around its own axis :type sidereal_rotation_period: float """ super().__init__(parent, name, texturename, color, radius, axial_tilt, sidereal_rotation_period, mass, renderer=renderer) self.orbit = orbit self.orbit.body = self self.orbit_line_batch = Batch()
def __init__(self, width, height, background=[255,255,255]): self.width = width self.height = height self.triangles = [] self.batch = Batch() self.bg_colour = background has_fbo = gl.gl_info.have_extension('GL_EXT_framebuffer_object') #setup a framebuffer self.fb = gl.GLuint() gl.glGenFramebuffersEXT(1, ctypes.byref(self.fb)) gl.glBindFramebufferEXT(gl.GL_FRAMEBUFFER_EXT, self.fb) #allocate a texture for the fb to render to tex = image.Texture.create_for_size(gl.GL_TEXTURE_2D, width, height, gl.GL_RGBA) gl.glBindTexture(gl.GL_TEXTURE_2D, tex.id) gl.glFramebufferTexture2DEXT(gl.GL_FRAMEBUFFER_EXT, gl.GL_COLOR_ATTACHMENT0_EXT, gl.GL_TEXTURE_2D, tex.id, 0) status = gl.glCheckFramebufferStatusEXT(gl.GL_FRAMEBUFFER_EXT) assert status == gl.GL_FRAMEBUFFER_COMPLETE_EXT gl.glBindFramebufferEXT(gl.GL_FRAMEBUFFER_EXT, 0) 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 __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 __init__(self, width, height): self.width = width self.height = height self._map = Batch() self._create() self._add_hero() self._add_lost()
def floor(floor_texture, x, y, z, width=1, height=1, depth=1): batch = Batch() for i in range(width): for j in range(height): for k in range(depth): tile = plane_tile.PlaneTile((x+i, y+j, z+k), side='top', textures={ 'top': floor_texture, }) vertex_list = tile.get_vertex_list() texture_list = tile.get_texture_list() vertices = len(vertex_list) / 3 batch.add(vertices, GL_QUADS, texture.textures['master']['group'], ('v3f/static', vertex_list), ('t2f/static', texture_list)) return batch
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 __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 __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()
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 Shape(object): ''' A list of primitives ''' def __init__(self, items=None): self.primitives = [] if items: self.add_items(items) self.batch = None def add_items(self, items): "Add a list of primitives and shapes" for item in items: if isinstance(item, Shape): self.add_shape(item) else: self.primitives.append(item) def add_shape(self, other): "Add the primitives from a given shape" for prim in other.primitives: self.primitives.append(prim) def get_batch(self): if self.batch is None: self.batch = Batch() for prim in self.primitives: flatverts = prim.get_flat_verts() numverts = len(flatverts) / 2 self.batch.add( numverts, prim.primtype, None, ('v2f/static', flatverts), ('c3B/static', prim.color * numverts) ) return self.batch def transform(self,M): """ applies matrix M to all self primitives """ for prim in self.primitives: prim.transform(M)
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 cif_red_shelf(x, y, z): batch = Batch() side = texture.textures['cif_red_shelf_side']['master_coordinates'] front = texture.textures['cif_red_shelf_front']['master_coordinates'] tiles = [ # Left side plane_tile.PlaneTile((x, y, z), side='back', textures={'back': side}), plane_tile.PlaneTile((x, y+1, z), side='back', textures={'back': side}), plane_tile.PlaneTile((x, y+2, z), side='back', textures={'back': side}), plane_tile.PlaneTile((x, y+3, z), side='back', textures={'back': side}), plane_tile.PlaneTile((x, y+4, z), side='back', textures={'back': side}), # Right side plane_tile.PlaneTile((x, y, z), side='front', textures={'front': side}), plane_tile.PlaneTile((x, y+1, z), side='front', textures={'front': side}), plane_tile.PlaneTile((x, y+2, z), side='front', textures={'front': side}), plane_tile.PlaneTile((x, y+3, z), side='front', textures={'front': side}), plane_tile.PlaneTile((x, y+4, z), side='front', textures={'front': side}), # Shelves plane_tile.PlaneTile((x, y, z), side='top', textures={'top': side}), plane_tile.PlaneTile((x, y+1, z), side='top', textures={'top': side}), plane_tile.PlaneTile((x, y+2, z), side='top', textures={'top': side}), plane_tile.PlaneTile((x, y+3, z), side='top', textures={'top': side}), plane_tile.PlaneTile((x, y+4, z), side='top', textures={'top': side}), # Front side plane_tile.PlaneTile((x, y, z), side='right', textures={'right': front}), plane_tile.PlaneTile((x, y+1, z), side='right', textures={'right': front}), plane_tile.PlaneTile((x, y+2, z), side='right', textures={'right': front}), plane_tile.PlaneTile((x, y+3, z), side='right', textures={'right': front}), plane_tile.PlaneTile((x, y+4, z), side='right', textures={'right': front}), ] for tile in tiles: vertex_list = tile.get_vertex_list() texture_list = tile.get_texture_list() vertices = len(vertex_list) / 3 batch.add(vertices, GL_QUADS, texture.textures['master']['group'], ('v3f/static', vertex_list), ('t2f/static', texture_list)) return batch
class World: def __init__(self): # A Batch is a collection of vertex lists for batched rendering. self.batch = Batch() # A TextureGroup manages an OpenGL texture. self.group = TextureGroup(image.load(TEXTURE_PATH).get_texture()) # A mapping from position to the texture of the block at that position. # This defines all the blocks that are currently in the world. self.objects = {} # Same mapping as `world` but only contains blocks that are shown. self.shown = {} # Mapping from position to a pyglet `VertextList` for all shown blocks. self._shown = {} # Which sector the player is currently in. self.sector = None # Mapping from sector to a list of positions inside that sector. self.sectors = {} self.shader = None # Simple function queue implementation. The queue is populated with # _show_block() and _hide_block() calls self.queue = deque() self.init_gl() self._initialize() self.init_shader() def init_gl(self): """Basic OpenGL configuration.""" # Set the color of "clear", i.e. the sky, in rgba. glClearColor(0.5, 0.69, 1.0, 1) # Enable culling (not rendering) of back-facing facets -- facets that aren't # visible to you. glEnable(GL_CULL_FACE) # Set the texture minification/magnification function to GL_NEAREST (nearest # in Manhattan distance) to the specified texture coordinates. GL_NEAREST # "is generally faster than GL_LINEAR, but it can produce textured images # with sharper edges because the transition between texture elements is not # as smooth." glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) self.init_gl_fog() def init_gl_fog(self): """Configure the OpenGL fog properties.""" # Enable fog. Fog "blends a fog color with each rasterized pixel fragment's # post-texturing color." glEnable(GL_FOG) # Set the fog color. glFogfv(GL_FOG_COLOR, (GLfloat * 4)(0.5, 0.69, 1.0, 1)) # Say we have no preference between rendering speed and quality. glHint(GL_FOG_HINT, GL_DONT_CARE) # Specify the equation used to compute the blending factor. glFogi(GL_FOG_MODE, GL_LINEAR) # How close and far away fog starts and ends. The closer the start and end, # the denser the fog in the fog range. glFogf(GL_FOG_START, 20.0) glFogf(GL_FOG_END, 60.0) def _initialize(self): """Initialize the world by placing all the blocks.""" n = 80 # 1/2 width and height of world s = 1 # step size y = 0 # initial y height for x in range(-n, n + 1, s): for z in range(-n, n + 1, s): # create a layer stone an grass everywhere. self.add_block((x, y - 3, z), stone, immediate=False) if x in (-n, n) or z in (-n, n): # create outer walls. for dy in range(-2, 3): self.add_block((x, y + dy, z), stone, immediate=False) else: y_max = int((simplex_noise2(x / 30, z / 30) + 1) * 3) for y_lvl in range(y - 2, y_max): if y_lvl < (y_max - 1): block = brick else: block = grass self.add_block((x, y_lvl, z), block, immediate=False) def hit_test(self, position, vector, max_distance=8): """Line of sight search from current position. If a block is intersected it is returned, along with the block previously in the line of sight. If no block is found, return None, None. Parameters ---------- position : tuple of len 3 The (x, y, z) position to check visibility from. vector : tuple of len 3 The line of sight vector. max_distance : int How many blocks away to search for a hit. """ m = 8 x, y, z = position dx, dy, dz = vector previous = None for _ in range(max_distance * m): key = normalize((x, y, z)) if key != previous and key in self.objects: return key, previous previous = key x, y, z = x + dx / m, y + dy / m, z + dz / m return None, None def exposed(self, position): """Returns False is given `position` is surrounded on all 6 sides by blocks, True otherwise. """ x, y, z = position for dx, dy, dz in FACES: if (x + dx, y + dy, z + dz) not in self.objects: return True return False def add_block(self, position, texture, immediate=True): """Add a block with the given `texture` and `position` to the world. Parameters ---------- position : tuple of len 3 The (x, y, z) position of the block to add. texture : list of len 3 The coordinates of the texture squares. Use `tex_coords()` to generate. immediate : bool Whether or not to draw the block immediately. """ if position in self.objects: self.remove_block(position, immediate) self.objects[position] = texture self.sectors.setdefault(sectorize(position), []).append(position) if immediate: if self.exposed(position): self.show_block(position) self.check_neighbors(position) def remove_block(self, position, immediate=True): """Remove the block at the given `position`. Parameters ---------- position : tuple of len 3 The (x, y, z) position of the block to remove. immediate : bool Whether or not to immediately remove block from canvas. """ del self.objects[position] self.sectors[sectorize(position)].remove(position) if immediate: if position in self.shown: self.hide_block(position) self.check_neighbors(position) def check_neighbors(self, position): """Check all blocks surrounding `position` and ensure their visual state is current. This means hiding blocks that are not exposed and ensuring that all exposed blocks are shown. Usually used after a block is added or removed. """ x, y, z = position for dx, dy, dz in FACES: key = (x + dx, y + dy, z + dz) if key not in self.objects: continue if self.exposed(key): if key not in self.shown: self.show_block(key) else: if key in self.shown: self.hide_block(key) def show_block(self, position, immediate=True): """Show the block at the given `position`. This method assumes the block has already been added with add_block() Parameters ---------- position : tuple of len 3 The (x, y, z) position of the block to show. immediate : bool Whether or not to show the block immediately. """ texture = self.objects[position] self.shown[position] = texture if immediate: self._show_block(position, texture) else: self._enqueue(self._show_block, position, texture) def _show_block(self, position, block): """Private implementation of the `show_block()` method. Parameters ---------- position : tuple of len 3 The (x, y, z) position of the block to show. texture : list of len 3 The coordinates of the texture squares. Use `tex_coords()` to generate. """ x, y, z = position vertex_data = cube_vertices(x, y, z, 0.5) shade_data = cube_shade(1, 1, 1, 1) texture_data = block.texture self._shown[position] = self.batch.add( 24, GL_QUADS, self.group, ('v3f/static', vertex_data), ('c3f/static', shade_data), ('t2f/static', texture_data)) def hide_block(self, position, immediate=True): """Hide the block at the given `position`. Hiding does not remove the block from the world. Parameters ---------- position : tuple of len 3 The (x, y, z) position of the block to hide. immediate : bool Whether or not to immediately remove the block from the canvas. """ self.shown.pop(position) if immediate: self._hide_block(position) else: self._enqueue(self._hide_block, position) def _hide_block(self, position): """Private implementation of the 'hide_block()` method.""" self._shown.pop(position).delete() def show_sector(self, sector): """Ensure all blocks in the given sector that should be shown are drawn to the canvas. """ for position in self.sectors.get(sector, []): if position not in self.shown and self.exposed(position): self.show_block(position, False) def hide_sector(self, sector): """Ensure all blocks in the given sector that should be hidden are removed from the canvas. """ for position in self.sectors.get(sector, []): if position in self.shown: self.hide_block(position, False) def change_sectors(self, before, after): """Move from sector `before` to sector `after`. A sector is a contiguous x, y sub-region of world. Sectors are used to speed up world rendering. """ before_set = set() after_set = set() pad = 4 for dx in range(-pad, pad + 1): for dy in [0]: # range(-pad, pad + 1): for dz in range(-pad, pad + 1): if dx ** 2 + dy ** 2 + dz ** 2 > (pad + 1) ** 2: continue if before: x, y, z = before before_set.add((x + dx, y + dy, z + dz)) if after: x, y, z = after after_set.add((x + dx, y + dy, z + dz)) show = after_set - before_set hide = before_set - after_set for sector in show: self.show_sector(sector) for sector in hide: self.hide_sector(sector) def _enqueue(self, func, *args): """Add `func` to the internal queue.""" self.queue.append((func, args)) def _dequeue(self): """Pop the top function from the internal queue and call it.""" func, args = self.queue.popleft() func(*args) def process_queue(self, ticks_per_sec): """Process the entire queue while taking periodic breaks. This allows the game loop to run smoothly. The queue contains calls to _show_block() and _hide_block() so this method should be called if add_block() or remove_block() was called with immediate=False """ start = time.clock() while self.queue and time.clock() - start < 1.0 / ticks_per_sec: self._dequeue() def process_entire_queue(self): """Process the entire queue with no breaks.""" while self.queue: self._dequeue() def init_shader(self): vertex_shader = "" fragment_shader = "" with open("pycraft/shaders/world.vert") as handle: vertex_shader = handle.read() with open("pycraft/shaders/world.frag") as handle: fragment_shader = handle.read() self.shader = Shader([vertex_shader], [fragment_shader]) def start_shader(self): self.shader.bind() def stop_shader(self): self.shader.unbind()
def __init__(self, *args, **kwargs): self.batch = Batch() super(DinamicObj, self).__init__(*args, **kwargs)
#Limit run time for profiling run_for = 15 #seconds to run test for def done_yet(duration = run_for, start=time.time()): return time.time()-start > duration #Set up window width, height = 640,480 window = pyglet.window.Window(width, height,vsync=False) #window = pyglet.window.Window(fullscreen=True,vsync=False) #width = window.width #height = window.height fps_display = pyglet.clock.ClockDisplay() text = """Unoptimized""" label = pyglet.text.HTMLLabel(text, x=10, y=height-10) main_batch = Batch() def draw(): global main_batch gl.glClearColor(0.2, 0.4, 0.5, 1.0) gl.glBlendFunc (gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable (gl.GL_BLEND) gl.glEnable (gl.GL_LINE_SMOOTH); gl.glLineWidth (3) main_batch.draw() #helper hunction for making polygons def polyOfN(radius,n): r=radius if n < 3:
import pyglet from pyglet.window import Window from pyglet.sprite import Sprite from pyglet.graphics import Batch from pyglet_utils.tutorial import resources game_window = Window() pyglet.gl.glClearColor(0, 0, 0, 1) batch = Batch() @game_window.event def on_draw(): game_window.clear() player_sprite.draw() enemy_sprite.draw() dimple_batch.draw() def update(dt): for dimple in dimple_list: dimple.x += 1 pass if __name__ == '__main__': import random resources.player.width, resources.player.height = 250, 250 resources.enemy.width, resources.enemy.height = 250, 250
from pyglet.window import Window from pyglet.app import run as run_app from pyglet.graphics import Batch from pyglet.clock import schedule from src import * from random import randint from time import time window = Window(1000, 1000) click_count = 0 BATCH = Batch() i, j = 0, 0 I, J = 0, 0 w, h, = 100, 100 color = GRAYS[list(GRAYS.keys())[int(i**j + 1) % len(GRAYS.keys())]] @window.event def on_draw(): if not color: pass Rect(i, j, w, h, color=color, draw=True, batch=BATCH, id_=None) BATCH.draw() def on_call(delta): global i, j, I, J, w, h, color if i < window.width - I: i += w
def __init__(self, lifetime: float): self.crt_time = 0 self.lifetime = lifetime self.particles = set() self.batch = Batch()
class Scene: def __init__(self, window, bus, title='Welcome to tabulr', draw_waves=False): """ Initialize the Scene object. :param window: Pyglet window object. Must be same throughout application. :param bus: Event bus. Used for communicating scene changes to main application thread. """ self.window = window self.window_title = title self.bus = bus self.batch = Batch() self.margin = 36 self.sprites = {} self.inputs = [] # Error message self.error_msg = Text('', size=12, bold=True, batch=self.batch, x=self.margin, color=(236, 64, 122, 255)) self.error_elapsed = 0 self.error_opacity = 0 # Waves background if draw_waves: waves_img = image('side-waves.png') waves_img.anchor_x = waves_img.width waves = Sprite(waves_img, x=window.width, y=0, batch=self.batch) waves.opacity = 160 self.init_sprite('waves', waves, is_button=False) def init_sprite(self, name, sprite, is_button=True): """ Store sprite for easy garbage collection later. :param name: Name of sprite :param sprite: pyglet.sprite.Sprite instance :param is_button: Whether sprite is used as a button. Used in managing hover states. """ self.sprites[name] = (sprite, is_button) def on_destroy(self): """ Removes all registered sprites from video memory. Called just before the scene is changed. """ for sprite in self.sprites.values(): sprite[0].delete() def on_draw(self): """ Draws all objects that are part of this scene's render batch. """ self.batch.draw() # Window title self.window.set_caption(self.window_title) def on_mouse_motion(self, x, y, dx, dy): for text_field in self.inputs: # Change cursor into caret on text input hover if text_field.hit_test(x, y): self.window.set_mouse_cursor( self.window.get_system_mouse_cursor( self.window.CURSOR_TEXT)) break else: # Change button hover state on hover for sprite, is_button in self.sprites.values(): if is_button: if sprite.hit_test(x, y): sprite.on_mouse_enter() break else: sprite.on_mouse_leave() else: self.window.set_mouse_cursor( self.window.get_system_mouse_cursor( self.window.CURSOR_DEFAULT)) def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): if isinstance(self.window.focus, TextInput): self.window.focus.caret.on_mouse_drag(x, y, dx, dy, buttons, modifiers) def on_text(self, text): if isinstance(self.window.focus, TextInput): self.window.focus.caret.on_text(text) def on_text_motion(self, motion): if isinstance(self.window.focus, TextInput): self.window.focus.caret.on_text_motion(motion) def on_text_motion_select(self, motion): if isinstance(self.window.focus, TextInput): self.window.focus.caret.on_text_motion_select(motion) def set_focus(self, focus): if isinstance(self.window.focus, TextInput): self.window.focus.caret.visible = False self.window.focus.caret.mark = self.window.focus.caret.position = 0 self.window.focus = focus if isinstance(focus, TextInput): self.window.focus.caret.visible = True self.window.focus.caret.mark = 0 self.window.focus.caret.position = len( self.window.focus.document.text) def hide_error_message(self): """ Hides the error message. """ self.error_msg.color = (236, 64, 122, 0) self.error_opacity = 0 def set_error_message(self, msg): """ Displays a red error message. :param msg: Error message """ self.error_msg.text = msg self.error_msg.color = (236, 64, 122, 255) self.error_elapsed = 0 self.error_opacity = 255 def update(self, dt): """ Fades out the error message, if any, after 1.5 seconds of initial visibility. :param dt: Time elapsed since last update """ if self.error_msg.text != '': if self.error_opacity > 0: self.error_elapsed += dt if self.error_elapsed > 1.5: self.error_msg.color = (236, 64, 122, self.error_opacity) self.error_opacity -= 10 else: self.hide_error_message()
def elements(self): for item in self._elements: del item self._elements: ElementDict = {} del self._batch self._batch = Batch()
class Menu: def __init__(self, id_: str, batch: Batch = None, logger: RootLogger = None): self._elements: ElementDict = {} self._id = id_ self._mouse_pos = Vector2D() self._batch = batch if batch is not None else Batch() self._logger = logger MENUS[self._id] = self def _log(self, lvl, msg): if self._logger: self._logger.log(lvl, msg) @property def mouse_pos(self) -> Vector2D: return self._mouse_pos @mouse_pos.setter def mouse_pos(self, mouse_pos: Vector2D) -> None: if not isinstance(mouse_pos, Vector2D): errormsg = f"mouse_pos type mismatch: {type(mouse_pos)} != {Vector2D}" self._log(ERROR, errormsg) raise TypeError(errormsg) self._mouse_pos = mouse_pos @mouse_pos.deleter def mouse_pos(self): errormsg = ( f"<Menu>.mouse_pos cannot be deleted without deleting the entire object" ) self._log(ERROR, errormsg) raise AttributeError(errormsg) @property def id(self) -> str: return self._id @id.setter def id(self, _): errormsg = f"<Menu>.id is a read-only attribute" self._log(ERROR, errormsg) raise AttributeError(errormsg) @id.deleter def id(self): errormsg = f"<Menu>.id cannot be deleted without deleting the entire object" self._log(ERROR, errormsg) raise AttributeError(errormsg) @property def elements(self) -> dict: return dict.copy(self._elements) @elements.setter def elements(self, _): errormsg = f"<Menu>.elements is a read-only attribute" self._log(ERROR, errormsg) raise AttributeError(errormsg) @elements.deleter def elements(self): for item in self._elements: del item self._elements: ElementDict = {} del self._batch self._batch = Batch() def add_element(self, element: Type[MenuElement]) -> None: if not isinstance(element, MenuElement): errormsg = f"Unable to add element of type {type(element)} to {self._id}" self._log(ERROR, errormsg) raise TypeError(errormsg) elif element.id in self._elements: errormsg = f"Element with id {element.id} already in {self._id}" self._log(ERROR, errormsg) raise KeyError(errormsg) element.update_data(_batch=self._batch) self._log( INFO, f"Adding element with id {element.id} to menu with id {self.id}") self._elements[element.id] = element def get_element_by_id(self, id_: str) -> MenuElement: if id_ not in list(self._elements.keys()): errormsg = f"No element found with id {id_} in menu {self.id}" self._log(ERROR, errormsg) raise ValueError(errormsg) else: return self._elements[id_] def on_mouse_motion(self, x, y): self.mouse_pos = Vector2D(x, y) def on_mouse_press(self, x, y, button, mod): self.mouse_pos = Vector2D(x, y) for element in list(self._elements.values()): if element.contains(self.mouse_pos): element.on_click() def draw(self): self._batch.draw() @classmethod def from_file(cls, filename: str): from yaml import load as yml_load with open(filename, "r") as file_: yml_str = file_.read() yml_d = yml_load(yml_str) if not "id" in yml_d and "elements" in yml_d: missing = ", ".join( [i for i in ["id", "elements"] if i not in yml_d]) errormsg = f"Missing attribute{'s ' + missing if ',' in missing else missing}. Unable to create menu object from file {filename}" raise AttributeError(errormsg) menu = cls(yml_d["id"]) elements = yml_d["elements"] for item in elements: type_, data = elements[item] menu.add_element(type_._from_attribs(data)) def save_to_file(self, filename: str) -> None: from yaml import dump as yml_dump def get_elements() -> dict: o = {} for num, elem in enumerate(list(self._elements.values())): o[num] = elem.get_data() return o data = {"id": self._id, "elements": get_elements()} with open(filename, "w") as file_: file_.write(yml_dump(data))
class Resources: states = { 'TITLE': 1, 'SETUP': 2, 'HOST': 3, 'JOIN': 4, 'GAME': 5, 'END': 6 } #game states types = ['green', 'lblue', 'red', 'mblue'] #player types window_width = 800 window_height = 600 center_x, center_y = get_center_coordinates(window_width, window_height) # Starting Points of Characters (x,y) starting_points = {} # Object Batches per state # batches = {} batches['title'] = Batch() batches['setup'] = Batch() batches['host'] = Batch() batches['join'] = Batch() batches['game'] = Batch() batches['end'] = Batch() # End of Batches # Declare all of your assets here # fonts = {} fonts_path = './assets/font' font.add_file(join(fonts_path, "nexa.otf")) fonts['nexa'] = font.load('Nexa Bold') audio = {} sfx_path = './assets/sfx' #Sound Effects audio['title_bgm'] = media.load(join(sfx_path, "title_bgm.wav")) audio['end_bgm'] = media.load(join(sfx_path, "end_bgm.wav")) audio['game_bgm'] = media.load(join(sfx_path, "game_bgm.wav")) audio['button'] = media.load(join(sfx_path, "button.wav"), streaming=False) audio['push_all'] = media.load(join(sfx_path, "push.wav"), streaming=False) audio['hit_upgrade'] = media.load(join(sfx_path, "hit_upgrade.mp3"), streaming=False) audio['game_win'] = media.load(join(sfx_path, "game_win.mp3"), streaming=False) audio['transition_to_game'] = media.load( join(sfx_path, "transition_to_game.mp3")) audio['transition_to_end'] = media.load( join(sfx_path, "transition_to_end.mp3")) sprites = {} res_path = './assets/img' #UI Elements sprites['no_sprite'] = image.load(join(res_path, 'blank.png')) sprites['start_button'] = center_image( image.load(join(res_path, 'start_button.gif'))) #sprites['start_button_mv'] = image.load_animation(join(res_path,'start_button.gif')) sprites['play_button'] = center_image( image.load(join(res_path, 'play_button_shadow.gif'))) sprites['host_button'] = center_image( image.load(join(res_path, 'debug_button.gif'))) sprites['join_button'] = center_image( image.load(join(res_path, 'join_button.gif'))) sprites['quit_button'] = center_image( image.load(join(res_path, 'quit_button.gif'))) sprites['logo'] = center_image(image.load(join(res_path, 'logo.png'))) sprites['push_all'] = center_image( image.load(join(res_path, 'push_all.png'))) sprites['marker'] = center_image(image.load(join(res_path, 'marker.png'))) sprites['push_all'] = center_image( image.load(join(res_path, 'push_all.png'))) sprites['info_bar'] = image.load(join(res_path, 'info_bar.png')) sprites['bounces'] = image.load(join(res_path, 'bounces2.png')) sprites['powers'] = image.load(join(res_path, 'powers.png')) sprites['game_over'] = image.load(join(res_path, 'game_over.png')) sprites['game_win'] = image.load(join(res_path, 'game_win2.png')) #Thumbnails sprites['thumb_green'] = image.load( join(res_path, 'thumbnails/thumb_air.png')) sprites['thumb_mblue'] = image.load( join(res_path, 'thumbnails/thumb_earth.png')) sprites['thumb_red'] = image.load( join(res_path, 'thumbnails/thumb_fire.png')) sprites['thumb_lblue'] = image.load( join(res_path, 'thumbnails/thumb_water.png')) #Backgrounds sprites['title_bg'] = center_image( image.load(join(res_path, 'title_bg.jpg'))) sprites['setup_bg'] = center_image( image.load(join(res_path, 'setup_bg.jpg'))) sprites['game_bg'] = center_image(image.load(join(res_path, 'game_bg.jpg'))) #Game Elements sprites['char_green'] = center_image( image.load(join(res_path, 'char_air.png'))) sprites['char_mblue'] = center_image( image.load(join(res_path, 'char_earth.png'))) sprites['char_red'] = center_image( image.load(join(res_path, 'char_fire.png'))) sprites['char_lblue'] = center_image( image.load(join(res_path, 'char_water.png'))) sprites['power_up'] = center_image( image.load(join(res_path, 'power_up.png'))) sprites['bounce_up'] = center_image( image.load(join(res_path, 'bounce_up.png')))
def __init__(self, frame: Frame, grid: Grid, renderbox: RenderBox, mouse: Mouse, game_obj_handler: GameObjectHandler, platform_list: List[Platform] = None, block_queue: Platform = None): self.frame = frame self.grid = grid self.renderbox = renderbox self.mouse = mouse self.game_obj_handler = game_obj_handler self.platform_list = platform_list if platform_list is not None else [] for platform in self.platform_list: self.game_obj_handler.append(platform) self.block_queue = block_queue if block_queue is not None else \ Platform(frame=self.frame, grid=self.grid, renderbox=self.renderbox, batch=Batch(), name=f'Platform{len(self.platform_list)}') self.game_obj_handler.append(self.block_queue) # Block Preview Related self.block_selector_handler = BlockSelectorHandler( [BlockSelector(TileImages), BlockSelector(ItemImages)]) self.block_preview_rect_color = (100, 255, 20) self.block_preview_rect_opacity = 50 self.block_preview_sprite_opacity = 130 self.block_preview_rect = cast(Rectangle, None) self.block_preview_sprite = cast(Sprite, None)
class Shape(object): ''' A list of primitives ''' def __init__(self, items=None, posx=0.0, posy=0.0, angle=0.0, vx=0.0, vy=0.0, va=0.0, drawable=True): self.primitives = [] self.posx = posx * 1.0 self.posy = posy * 1.0 self.angle = angle * 1.0 self.vx = vx * 1.0 self.vy = vy * 1.0 self.va = va * 1.0 # angular velocity self.drawable = drawable self.batch = None Field.display_list.append(self) if items: self.add_items(items) (self.minx, self.miny, self.maxx, self.maxy) = self.get_aabb() else: self.minx.self.maxx, self.miny, self.maxy = 0, 0, 0, 0 self.drawable = False def add_items(self, items): "Add a list of primitives and shapes" for item in items: if isinstance(item, Shape): self.add_shape(item) else: self.primitives.append(item) def add_shape(self, other): "Add the primitives from a given shape" for prim in other.primitives: self.primitives.append(prim) def get_batch(self): if self.batch is None: self.batch = Batch() for prim in self.primitives: flatverts = prim.get_flat_verts() numverts = len(flatverts) / 2 self.batch.add(numverts, prim.primtype, None, ('v2f/static', flatverts), ('c3B/static', prim.color * numverts)) return self.batch def transform(self, M): """ applies matrix M to all self primitives """ for prim in self.primitives: prim.transform(M) def get_aabb(self): aabb = namedtuple('AABB', ['xmin', 'xmax', 'ymin', 'ymax']) _allx = [] _ally = [] for prim in self.primitives: for v in prim.verts: _allx.append(v[0]) _ally.append(v[1]) minx = min(_allx) miny = min(_ally) maxx = max(_allx) maxy = max(_ally) box = (minx, miny, maxx, maxy) return (box) def paint(self): if self.drawable: glPushMatrix() glTranslatef(self.posx, self.posy, 0) glRotatef(self.angle, 0, 0, 1) batch = self.get_batch() batch.draw() glPopMatrix() else: print 'cell', self, 'is not drawable'
class PllStateDrawer: batch: Batch rects: List[shapes.Rectangle] def __init__(self, batch: Batch = None, position: Tuple[float] = None, tile_size: float = 500): if batch is not None: self.batch = batch else: self.batch = Batch() if position is not None: self.position = position else: self.position = (0.0, 0.0) self.state_size = tile_size self.rects = [] def prepare_state(self, pll_state: PllState, state_position: Tuple[float]): state_position = tuple(value - self.state_size / 2 for value in state_position) r, c = pll_state.tiles.shape assert (r == c) num_rows = r # Compute size of components gap_portion = 0.2 gap_size = gap_portion * self.state_size / (num_rows + 1) tile_portion = 1.0 - gap_portion tile_size = tile_portion * self.state_size / num_rows extremes = [0, num_rows - 1] for row_idx in range(num_rows): for col_idx in range(num_rows): color_id = pll_state.tiles[row_idx][col_idx] color = PllState.colors[PllState.color_names[color_id]] tile_x = self.position[0] + state_position[0] + ( col_idx + 1) * gap_size + col_idx * tile_size tile_y = self.position[1] + state_position[1] + ( (row_idx + 1) * (gap_size + tile_size)) # Set batch to None for corners to_draw = (row_idx in extremes) and (col_idx in extremes) batch = None if to_draw else self.batch rect = shapes.Rectangle(tile_x, tile_y, tile_size, tile_size, color=color, batch=batch) self.rects.append(rect) def prepare_pll_list(self, pll_state_list: List[PllState], as_row: bool = True): positions = self.__get_pll_list_positions(pll_state_list, as_row) for state_idx, state in enumerate(pll_state_list): self.prepare_state(state, positions[state_idx]) def __get_pll_list_positions( self, pll_state_list: List[PllState], row_vector: bool = True) -> List[Tuple[float]]: positions = [] for state_idx, state in enumerate(pll_state_list): x_i = self.state_size * (state_idx + 0.5) y_i = self.state_size / 2.0 if row_vector: position = tuple(map(float, (x_i, y_i))) else: position = tuple(map(float, (y_i, x_i))) positions.append(position) return positions def prepare_pll_2d_array(self, pll_states_array: List[List[PllState]]): positions = self.__get_pll_2d_array_positions(pll_states_array) num_rows = len(pll_states_array) num_cols = len(pll_states_array[0]) for row_idx in range(num_rows): for col_idx in range(num_cols): self.prepare_state(pll_states_array[row_idx][col_idx], positions[row_idx][col_idx]) def __get_pll_2d_array_positions( self, pll_states_array: List[List[PllState]] ) -> List[List[Tuple[float]]]: position_table = [] num_rows = len(pll_states_array) num_cols = len(pll_states_array[0]) for row_idx in range(num_rows): row = [] for col_idx in range(num_cols): x_i = self.state_size * (row_idx + 0.5) y_i = self.state_size * (col_idx + 0.5) position = tuple(map(float, (x_i, y_i))) row.append(position) position_table.append(row) return position_table def draw(self): self.batch.draw()
def __init__(self, text): self.setText(text) batch = Batch() text = ''
class Shape(object): """ Stores a list of vertices, a single color, and a primitive type Intended to be rendered as a single OpenGL primitive """ def __init__(self, name, **kwargs): global lmnts if name in lmnts: raise ValueError('duplicate shape name', name) exit(1) elif name == '': raise ValueError('no shape name', name) else: self.name=name lmnts[self.name] = self print ":: new shape :", self.name for i in kwargs: setattr(self,i,kwargs[i]) self.build() self.flat_verts = None self.batch = None def offseted(self, dx, dy): newverts = [(v[0] + dx, v[1] + dy) for v in self.verts] self.verts=newverts def centered(self): pass def transformed(self,M): """ applies matrix M transformation to all self vertexes """ newverts = [ (M[0]*v[0]+M[1]*v[1]+M[2], M[3]*v[0]+M[4]*v[1]+M[5]) for v in self.verts] return Shape(newverts, self.color, primtype=self.primtype) # TODO replace shape verts only def get_aabb(self): _allx=[] _ally=[] for v in self.verts: _allx.append(v[0]) _ally.append(v[1]) lox=min(_allx) loy=min(_ally) hix=max(_allx) hiy=max(_ally) return (AABB(lox,loy,hix,hiy)) 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): if self.batch is None: 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) ) return self.batch def paint(self, peg): batch = self.get_batch() glPushMatrix() glTranslatef(peg.x, peg.y, 0) glRotatef(peg.angle, 0, 0, 1) batch.draw() glPopMatrix()
class SjuanStackDrawer: PAD_X = (CardDrawer.CARD_SIZE.x + CardDrawer.CARD_SIZE.y) // 2 + 12 def __init__(self, sjuan_stack: SjuanCardStack, pos: Vector): self._sjuan_stack = sjuan_stack self._pos = pos self.visible = True self._batch_sevens = Batch() self._upper_batch = Batch() self._lower_batch = Batch() self._dotted_draws = {} self._seven_draws = {} self._upper_draws = {} self._lower_draws = {} self._create_dotted_draws() # @TODO: For now we're assuming the sjuan stack is empty on init # Not likely to be a big problem, but technically # something to fix... def _create_dotted_draws(self): pad = 10 dy = CardDrawer.CARD_SIZE.y + pad pos = Vector(0, dy * (len(CardSuit) - 1) / 2) for suit in CardSuit: self._dotted_draws[suit] = DashedRect(RectangleShape( size=CardDrawer.CARD_SIZE, centre=deepcopy(pos)), dashes=[16, 8], batch=self._batch_sevens) pos.y -= dy def _card_inserted(self, card): if card.value == CardValue.SEVEN: dotted_draw = self._dotted_draws[card.suit] draw = CardDrawer(card, dotted_draw.shape.centre, batch=self._batch_sevens) dotted_draw.delete() del dotted_draw self._seven_draws[card.suit] = draw else: seven = self._seven_draws[card.suit] if card.value.adj_value(aces_lowest=True) > CardValue.SEVEN.value: if card.suit in self._upper_draws: self._upper_draws[card.suit].delete() self._upper_draws[card.suit] = CardDrawer( card, Vector(-seven.pos.y, SjuanStackDrawer.PAD_X), batch=self._upper_batch) else: if card.suit in self._lower_draws: self._lower_draws[card.suit].delete() self._lower_draws[card.suit] = CardDrawer( card, Vector(seven.pos.y, SjuanStackDrawer.PAD_X), batch=self._lower_batch) def position_for(self, card): if card.value == CardValue.SEVEN: r = self._dotted_draws[card.suit].shape.centre elif card.value.adj_value(aces_lowest=True) > CardValue.SEVEN.value: r = self._seven_draws[card.suit].centre + Vector( SjuanStackDrawer.PAD_X, 0) else: r = self._seven_draws[card.suit].centre - Vector( SjuanStackDrawer.PAD_X, 0) return r + self._pos def draw(self): if self.visible: glPushMatrix() glTranslatef(self._pos.x, self._pos.y, 0) self._batch_sevens.draw() glRotatef(-90, 0.0, 0.0, 1.0) self._upper_batch.draw() glRotatef(180, 0.0, 0.0, 1.0) self._lower_batch.draw() glPopMatrix()
def __init__(self, game: "Pong") -> None: self.game = game self.batch = Batch()
def __init__(self, game=None, context=None): self.game = game self.batch = Batch() self.context = context or {}
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))
"""Demonstrates creation of a transparent overlay window in pyglet """ import pyglet from pyglet.graphics import Batch from pyglet.window import Window batch = Batch() window = Window(500, 500, style=Window.WINDOW_STYLE_TRANSPARENT) window.set_caption("Transparent Window") circle = pyglet.shapes.Circle(250, 250, 100, color=(255, 255, 0), batch=batch) @window.event def on_draw(): window.clear() batch.draw() pyglet.app.run()
def __init__(self, X, Generator): super(CloudRenderer, self).__init__(X, Generator) self.Batch = Batch()
class World: def __init__(self): # A Batch is a collection of vertex lists for batched rendering. self.batch = Batch() # A TextureGroup manages an OpenGL texture. self.texture_group = {} # Mapping from position to a pyglet `VertextList` for all shown blocks. self._shown = {} self.show_hide_queue = OrderedDict() # Which sector the player is currently in. self.sector = None # Mapping from sector to a list of positions inside that sector. self.sectors = {} # Same mapping as `world` but only contains blocks that are shown. self.shown = {} self.shader = None PycraftOpenGL() self.init_shader() # A mapping from position to the texture of the block at that position. # This defines all the blocks that are currently in the world. self.area = Area() def add_block(self, coords, block, immediate=True): """Add a block with the given `texture` and `position` to the world. Parameters ---------- coords : tuple of len 3 The (x, y, z) position of the block to add. block : list of len 3 The coordinates of the texture squares. Use `tex_coords()` to generate. immediate : bool Whether or not to draw the block immediately. """ self.area.add_block(coords, block) # self.sectors.setdefault(sectorize(position), []).append(position) if immediate: if self.area.exposed(coords): self.show_block(coords, block, immediate) neighbors = self.area.get_neighbors(coords) for element in neighbors['hide']: self.hide_block(element['coords']) for element in neighbors['show']: self.show_block(element['coords'], element['block']) def remove_block(self, coords): """ Remove a block from the world. And shows the neighbors :param coords: :return: """ self.area.remove_block(coords) self.hide_block(coords) neighbors = self.area.get_neighbors(coords) for element in neighbors['hide']: self.hide_block(element['coords']) for element in neighbors['show']: self.show_block(element['coords'], element['block']) def show_block(self, coords, block, immediate=False): """Ensure all blocks that should be shown are drawn to the canvas. Parameters ---------- coords : tuple of len 3 The (x, y, z) position of the block to show. block : list of len 3 The coordinates of the texture squares. Use `tex_coords()` to generate. immediate : bool Whether or not to immediately remove the block from the canvas. """ if coords in self.shown: return self.shown[coords] = block if not immediate: self.show_hide_queue[coords] = True return self._show_block(coords, block) def _show_block(self, coords, block): """Private implementation of the `show_block()` method. Parameters ---------- coords : tuple of len 3 The (x, y, z) position of the block to show. block : list of len 3 The coordinates of the texture squares. Use `tex_coords()` to generate. """ x, y, z = coords vertex_data = cube_vertices(x, y, z, 0.5) shade_data = cube_shade(1, 1, 1, 1) texture_data = block.texture if block.identifier not in self.texture_group: self.texture_group[block.identifier] = TextureGroup( image.load(block.texture_path).get_texture()) self._shown[coords] = self.batch.add( 24, GL_QUADS, self.texture_group[block.identifier], ('v3f/static', vertex_data), ('c3f/static', shade_data), ('t2f/static', texture_data)) def hide_block(self, coords, immediate=True): """Ensure all blocks that should be hidden are hide from the canvas.""" if coords not in self.shown: return self.shown.pop(coords) if not immediate: self.show_hide_queue[coords] = False self._hide_block(coords) def _hide_block(self, coords): """Private implementation of the 'hide_block()` method.""" if coords not in self._shown: return self._shown.pop(coords).delete() def _dequeue(self): """Pop the top function from the internal queue and call it.""" coords, show = self.show_hide_queue.popitem(last=False) shown = coords in self._shown if show and not shown: self._show_block(coords, self.area.get_block(coords)) elif shown and not show: self._hide_block(coords) def process_queue(self, ticks_per_sec): """Process the entire queue while taking periodic breaks. This allows the game loop to run smoothly. The queue contains calls to _show_block() and _hide_block() so this method should be called if add_block() or remove_block() was called with immediate=False """ start = time.clock() while self.show_hide_queue and time.clock( ) - start < 1.0 / ticks_per_sec: self._dequeue() def process_entire_queue(self): """Process the entire queue with no breaks.""" while self.show_hide_queue: self._dequeue() def init_shader(self): vertex_shader = "" fragment_shader = "" with open("pycraft/shaders/world.vert") as handle: vertex_shader = handle.read() with open("pycraft/shaders/world.frag") as handle: fragment_shader = handle.read() self.shader = Shader([vertex_shader], [fragment_shader]) def start_shader(self): self.shader.bind() def stop_shader(self): self.shader.unbind() def add_sector(self, sector, coords): self.sector = coords self.sectors[coords] = sector # self.sectors.setdefault(coords, []).append(sector) def show_sector(self, coords, immediate=True): """Ensure all blocks in the given sector that should be shown are drawn to the canvas. """ sector = self.sectors.get(coords) if sector: for position in sector.blocks: if position not in self.shown and self.area.exposed(position): self.show_block(position, immediate) else: sector = Sector(coords, self.area) self.add_sector(sector, coords) self.show_sector(coords) def hide_sector(self, coords): """Ensure all blocks in the given sector that should be hidden are removed from the canvas. """ sector = self.sectors.get(coords) for position in sector.blocks: if position in self.shown: self.hide_block(position, False) def change_sectors(self, before, after): """Move from sector `before` to sector `after`. A sector is a contiguous x, y sub-region of world. Sectors are used to speed up world rendering. """ before_set = set() after_set = set() pad = 4 if not before: self.initial_sector(after) for dx in range(-pad, pad + 1): for dy in [0]: # range(-pad, pad + 1): for dz in range(-pad, pad + 1): if dx**2 + dy**2 + dz**2 > (pad + 1)**2: continue if before: x, y, z = before before_set.add((x + dx, y + dy, z + dz)) if after: x, y, z = after after_set.add((x + dx, y + dy, z + dz)) show = after_set - before_set hide = before_set - after_set for coords in hide: self.hide_sector(coords) for coords in show: self.show_sector(coords) def initial_sector(self, coords): """ Creates initial sectors in spiral, to speed up rendering in front of the player :param coords: :return: """ x, y = 0, 0 dx, dy = 0, -1 X = coords[0] + 4 Y = coords[2] + 4 for i in range(max(X, Y)**2): if (-X / 2 < x <= X / 2) and (-Y / 2 < y <= Y / 2): self.show_sector((x, coords[1], y)) if x == y or (x < 0 and x == -y) or (x > 0 and x == 1 - y): dx, dy = -dy, dx # Corner change direction x, y = x + dx, y + dy
def __init__(self, x, y, radius, segments=None, angle=math.tau, start_angle=0, closed=False, color=(255, 255, 255), batch=None, group=None): """Create an Arc. The Arc's anchor point (x, y) defaults to it's center. :Parameters: `x` : float X coordinate of the circle. `y` : float Y coordinate of the circle. `radius` : float The desired radius. `segments` : int You can optionally specifify how many distict line segments the arc should be made from. If not specified it will be automatically calculated using the formula: `max(14, int(radius / 1.25))`. `angle` : float The angle of the arc, in radians. Defaults to tau (pi * 2), which is a full circle. `start_angle` : float The start angle of the arc, in radians. Defaults to 0. `closed` : bool If True, the ends of the arc will be connected with a line. defaults to False. `color` : (int, int, int) The RGB color of the circle, specified as a tuple of three ints in the range of 0-255. `batch` : `~pyglet.graphics.Batch` Optional batch to add the circle to. `group` : `~pyglet.graphics.Group` Optional parent group of the circle. """ self._x = x self._y = y self._radius = radius self._segments = segments or max(14, int(radius / 1.25)) self._num_verts = self._segments * 2 + (2 if closed else 0) self._rgb = color self._angle = angle self._start_angle = start_angle self._closed = closed self._rotation = 0 self._batch = batch or Batch() self._group = _ShapeGroup(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, group) self._vertex_list = self._batch.add(self._num_verts, GL_LINES, self._group, 'v2f', 'c4B') self._update_position() self._update_color()
def draw_stars(self): star_batch = Batch() for i in self.star_pts: star_batch.add(4, GL_QUADS, None, ('v2f', i)) star_batch.draw()
def initialise(): """Initialises the cube render objects. """ global batch batch = Batch() batch.add( 24, GL_QUADS, None, ('v3f', (1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0)), ( 'c3f', ( # green 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, # orange 1.0, 0.5, 0.0, 1.0, 0.5, 0.0, 1.0, 0.5, 0.0, 1.0, 0.5, 0.0, # blue 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, # violet 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, # yellow 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, # red 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, )))
class GameRenderer(Window): """Takes a 2D ExpandoGame and draws it, everytime `step()` is called. """ def __init__(self, game: ExpandoGame, cell_size=50, padding=10, ui_font_size=12): """ :param game: The game to render :param cell_size: the length of each square in pixels :param padding: the padding between cells in pixels :param ui_font_size: size of the font, used to show player statistics. """ self.player_colors = [(84, 22, 180), (255, 106, 0), (204, 255, 0), (244, 147, 242)] self.padding = padding self.cell_size = cell_size self.square_size = self.cell_size - self.padding self.game = game self.board = self.game.board self.font_height = ui_font_size * 0.75 assert len(self.board.grid_size ) == 2, 'only 2d grids can be rendered at the moment' h, w = self.game.grid_size window_height = h * cell_size + padding # extra room for displaying scores self.window_height = window_height + 2 * self.font_height * ( game.n_players + 1) + self.padding self.window_width = w * cell_size + padding super().__init__(width=self.window_width, height=int(self.window_height)) self.batch = Batch() @staticmethod def step(): """Render a single frame. """ pyglet.clock.tick() for window in pyglet.app.windows: window.switch_to() window.dispatch_events() window.dispatch_event('on_draw') window.flip() def on_draw(self): """triggered by pyglet to draw everything. """ self.clear() self.draw_grid() self.draw_cursors() self.draw_scores() def draw_grid(self): """Draws the board's grid. """ h, w = self.board.grid_size pieces = [] for i in range(w): for j in range(h): piece = self.board.get_piece((j, i)) x, y = self._get_canvas_pos(i, j) r = piece.to_drawable(x, y, self.batch, self.square_size, self._get_piece_color(piece)) pieces.append(r) self.batch.draw() def draw_cursors(self): """Draw the cursors of each player. """ rects = [] for player in self.game.players: cursor = tuple(player.cursor) x, y = self._get_canvas_pos(*cursor) color = self._get_player_color(player) color = self.brighten(color, 50) r = Rectangle(y, x, self.square_size, self.square_size, color=color, batch=self.batch) rects.append(r) self.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() def _get_canvas_pos(self, x, y): """Translate a position on the board to a position on the pyglet canvas. :param x: x coordinate :param y: y coordinate :return: canvas position in pixels. """ return x * self.cell_size + self.padding, y * self.cell_size + self.padding def _get_piece_color(self, piece): """Get the color of a piece, depending on it's owner. :param piece: the piece to get the color for. :return: an rgb color tuple """ return self._get_player_color(piece.player) def _get_player_color(self, player): """Get the color assigned to a player, returns gray if None. :param player: the player to get the associated color from. :return: a rgb tuple """ if player is None: return 10, 10, 10 return self.player_colors[player.player_id] @staticmethod def brighten(color, val): """Increase color intensity on all channels, clips anything above 255.0 or below 0.0. :param color: tuple representing the color to brighten. :param val: amount of added brightness. :return: a tuple """ new_color = [] for c in color: x = c + val if 0 <= x <= 255: new_color.append(x) elif x < 0: new_color.append(0) else: new_color.append(255) return new_color
class Map(object): """ Map is an object to describe the virtual world. For `no_collision` task, the `Map` contains a floor and other optional obstacle walls. Drone is rendered as 3D model with flighting pose. For `velocity_control` task, the `Map` ONLY contains a 3D drone model. Moreover, the velocity vector of the drone is shown with an orange arrow; the expected velocity vector of the drone is shown with a yellow arrow. Args: drone_3d_model (str): path to 3D STL model of the drone. horizon_view_size (int): number of blocks to show in horizon view. init_drone_z (float): the initial height of the drone. task (str): name of the task setting. Currently, support `no_collision` and `velocity_control`. """ def __init__(self, drone_3d_model, horizon_view_size=8, init_drone_z=5, task='no_collision', debug_mode=False): self.task = task self.debug_mode = debug_mode # When increase this, show more blocks in current view window self.horizon_view_size = horizon_view_size # A Batch is a collection of vertex lists for batched rendering self.batch = Batch() # Manages an OpenGL texture self.group = TextureGroup(image.load(TEXTURE_PATH).get_texture()) # A mapping from position to the texture for whole, global map self.whole_map = dict() # Same as `whole_map` but only contains the positions to show self.partial_map = dict() # A mapping from position to a pyglet `VertextList` in `partial_map` self._partial_map = dict() # A mapping from sector to a list of positions (contiguous sub-region) # using sectors for fast rendering self.sectors = dict() # Use deque to populate calling of `_show_block` and `_hide_block` self.queue = deque() # A graphics batch to draw drone 3D model self.drone_batch = pyglet.graphics.Batch() # Load drone triangular mesh and scene self.drone_name = os.path.basename(drone_3d_model) self.drone_mesh = trimesh.load(drone_3d_model) self.drone_scene = self.drone_mesh.scene() # Drawer stores drone scene geometry as vertex list in its model space self.drone_drawer = None # Store drone geometry hashes for easy retrival self.drone_vertex_list_hash = '' # Store drone geometry rendering mode, default gl.GL_TRIANGLES self.drone_vertex_list_mode = gl.GL_TRIANGLES # Store drone geometry texture self.drone_texture = None black = np.array([0, 0, 0, 255], dtype=np.uint8) red = np.array([255, 0, 0, 255], dtype=np.uint8) green = np.array([0, 255, 0, 255], dtype=np.uint8) blue = np.array([0, 0, 255, 255], dtype=np.uint8) for i, facet in enumerate(self.drone_mesh.facets): if i < 30: self.drone_mesh.visual.face_colors[facet] = black elif i < 42: self.drone_mesh.visual.face_colors[facet] = red elif i < 54: self.drone_mesh.visual.face_colors[facet] = green elif i < 66: self.drone_mesh.visual.face_colors[facet] = blue else: self.drone_mesh.visual.face_colors[facet] = black # Mark positions of bounding wall and obstacles in the map self._initialize(init_drone_z) def _initialize(self, init_drone_z): if self.task in ['no_collision', 'hovering_control']: h = w = 100 for y in range(0, h): for x in range(0, w): # Pave the floor self._add_block((x, y, 0), TILE, immediate=False) elif self.task == 'velocity_control': h = w = 0 self.drone_pos = [h // 2, w // 2, init_drone_z] self._add_drone() if self.task == 'velocity_control': self.drone_velocity_drawer = self._add_drone_velocity( np.array([0.0, 0.0, 1.0]), color=[255, 95, 63]) # orange self.drone_expected_velocity_drawer = self._add_drone_velocity( np.array([0.0, 0.0, 1.0]), color=[240, 210, 90]) # yellow def _is_exposed(self, position): x, y, z = position for dx, dy, dz in FACES: if (x + dx, y + dy, z + dz) not in self.whole_map: # At least one face is not covered by another cube block. return True return False def _add_drone(self): """ Add the drone 3D model in its own model space. """ for name, geom in self.drone_scene.geometry.items(): if geom.is_empty: continue if geometry_hash(geom) == self.drone_vertex_list_hash: continue if name == self.drone_name: args = rendering.convert_to_vertexlist(geom, smooth=True) self.drone_drawer = self.drone_batch.add_indexed(*args) self.drone_vertex_list_hash = geometry_hash(geom) self.drone_vertex_list_mode = args[1] try: assert len(geom.visual.uv) == len(geom.vertices) has_texture = True except BaseException: has_texture = False if has_texture: self.drone_texture = rendering.material_to_texture( geom.visual.material) def _add_drone_velocity(self, init_velocity_vector, radius=0.008, color=[255, 0, 0]): """ Add the drone velocity vector as a cylinder into drone drawer batch. """ translation = np.eye(4) translation[:3, 3] = [0, 0, 0.5] height = np.linalg.norm(init_velocity_vector) transform_z_axis = init_velocity_vector / height transform = np.eye(4) transform[:3, 2] = transform_z_axis transform = np.dot(translation, transform) velocity_axis = trimesh.creation.cylinder(radius=radius, height=height, transform=transform) velocity_axis.visual.face_colors = color axis_origin = trimesh.creation.uv_sphere(radius=radius * 5, count=[10, 10]) axis_origin.visual.face_colors = color merge = trimesh.util.concatenate([axis_origin, velocity_axis]) args = rendering.convert_to_vertexlist(merge) drawer = self.drone_batch.add_indexed(*args) return drawer def _add_block(self, position, texture, immediate=True): """ Add a block with the given `texture` and `position` to the world. Note that block is a 1x1x1 cube and its position is its centroid. Args: position (tuple): The (x, y, z) position of the block to add. texture (list): The coordinates of the texture squares, e.g. TILE. immediate (bool): Whether or not to draw the block immediately. """ if position in self.whole_map: # Not called for current static map assert False, 'Duplicated block!' self._remove_block(position, immediate) self.whole_map[position] = texture self.sectors.setdefault(sectorize(position), []).append(position) if immediate: if self._is_exposed(position): self.show_block(position) self._check_neighbors(position) def _remove_block(self, position, immediate=True): """ Remove the block at the given `position`. Args: position (tuple): The (x, y, z) position of the block to remove. immediate (bool): Whether or not to remove the block immediately. """ del self.whole_map[position] self.sectors[sectorize(position)].remove(position) if immediate: if position in self.partial_map: self.hide_block(position) self._check_neighbors(position) def _check_neighbors(self, position): x, y, z = position for dx, dy, dz in FACES: pos = (x + dx, y + dy, z + dz) if pos not in self.whole_map: continue if self._is_exposed(pos): if pos not in self.partial_map: self.show_block(pos) else: if pos in self.partial_map: self.hide_block(pos) def _show_block(self, position, texture): vertex_data = cube_vertices(position, 0.5) # 12x6=72 texture_data = list(texture) # 8x6=48 vertex_count = len(vertex_data) // 3 # 24 attributes = [('v3f/static', vertex_data), ('t2f/static', texture_data)] self._partial_map[position] = self.batch.add(vertex_count, gl.GL_QUADS, self.group, *attributes) def _hide_block(self, position): self._partial_map.pop(position).delete() def _enqueue(self, func, *args): self.queue.append((func, args)) def _dequeue(self): func, args = self.queue.popleft() func(*args) def _get_velocity_transform(self, velocity, position): height = np.linalg.norm(velocity) transform = np.eye(4) # Translation x, z, y = position transform[:3, 3] = [x, y, z] # Rescale transform[2, 2] = height # Rotate rotation = np.eye(4) rotation[:3, 2] = velocity / height return np.dot(transform, rotation) def show_drone(self, position, rotation): """ Show the drone 3D model with corresponding translation and rotation. """ # Get the transform matrix for drone 3D model x, z, y = position transform = np.eye(4) transform[:3, 3] = [x, y, z] # NOTE: change the view size of drone 3D model transform[0, 0] = 2.5 transform[1, 1] = 2.5 transform[2, 2] = 2.5 # Match drone model space x-y-z to openGL x-z-y # TODO: read the config.json and match the propeller positions model_space_transform = rotation_transform_mat(-np.pi / 2, 'roll') transform = np.dot(transform, model_space_transform) yaw, pitch, roll = rotation if self.debug_mode: # NOTE: manually set values to debug rotation, # it's useful when input act is in form [c, c, c, c]. yaw = np.pi / 2 # pitch = np.pi / 2 # roll = np.pi / 2 transform = np.dot(transform, rotation_transform_mat(yaw, 'yaw')) transform = np.dot(transform, rotation_transform_mat(pitch, 'pitch')) transform = np.dot(transform, rotation_transform_mat(roll, 'roll')) # Add a new matrix to the model stack to transform the model gl.glPushMatrix() gl.glMultMatrixf(rendering.matrix_to_gl(transform)) # Enable the target texture if self.drone_texture is not None: gl.glEnable(self.drone_texture.target) gl.glBindTexture(self.drone_texture.target, self.drone_texture.id) # Draw the mesh with its transform applied self.drone_drawer.draw(mode=self.drone_vertex_list_mode) gl.glPopMatrix() # Disable texture after using if self.drone_texture is not None: gl.glDisable(self.drone_texture.target) def show_velocity(self, position, velocity, expected_velocity=None): """ Show velocity vector as a thin cylinder arrow. """ if not hasattr(self, 'drone_velocity_drawer'): return transform = self._get_velocity_transform(velocity, position) gl.glPushMatrix() gl.glMultMatrixf(rendering.matrix_to_gl(transform)) self.drone_velocity_drawer.draw(mode=self.drone_vertex_list_mode) gl.glPopMatrix() if expected_velocity is not None and \ hasattr(self, 'drone_expected_velocity_drawer'): transform = self._get_velocity_transform(expected_velocity, position) gl.glPushMatrix() gl.glMultMatrixf(rendering.matrix_to_gl(transform)) self.drone_expected_velocity_drawer.draw( mode=self.drone_vertex_list_mode) gl.glPopMatrix() def show_block(self, position, immediate=True): texture = self.whole_map[position] self.partial_map[position] = texture if immediate: self._show_block(position, texture) else: self._enqueue(self._show_block, position, texture) def hide_block(self, position, immediate=True): self.partial_map.pop(position) if immediate: self._hide_block(position) else: self._enqueue(self._hide_block, position) def show_sector(self, sector): for position in self.sectors.get(sector, []): if position not in self.partial_map and self._is_exposed(position): self.show_block(position, immediate=False) def hide_sector(self, sector): for position in self.sectors.get(sector, []): if position in self.partial_map: self.hide_block(position, immediate=False) def change_sectors(self, before, after): """ Find the changed sectors and trigger show or hide operations """ # TODO: adjust the sector set when add extra view perspective # relative to the drone. # FIXME: when the drone flies high, the green floor immediately # disappear before_set, after_set = set(), set() pad = self.horizon_view_size // 2 for dx in range(-pad, pad + 1): for dy in range(-pad, pad + 1): dz = 0 if dx**2 + dy**2 + dz**2 > (pad + 1)**2: continue if before: x, y, z = before before_set.add((x + dx, y + dy, z + dz)) if after: x, y, z = after after_set.add((x + dx, y + dy, z + dz)) show = after_set - before_set hide = before_set - after_set for sector in show: self.show_sector(sector) for sector in hide: self.hide_sector(sector) def process_queue(self): # NOTE: no scheduled interval timer, we render by manually calling # `RenderWindow.view()`. So we process queue without time contrains. # In other words, it's a copy of `process_entire_queue()` while self.queue: self._dequeue() def process_entire_queue(self): while self.queue: self._dequeue()
def __init__(self, drone_3d_model, horizon_view_size=8, init_drone_z=5, task='no_collision', debug_mode=False): self.task = task self.debug_mode = debug_mode # When increase this, show more blocks in current view window self.horizon_view_size = horizon_view_size # A Batch is a collection of vertex lists for batched rendering self.batch = Batch() # Manages an OpenGL texture self.group = TextureGroup(image.load(TEXTURE_PATH).get_texture()) # A mapping from position to the texture for whole, global map self.whole_map = dict() # Same as `whole_map` but only contains the positions to show self.partial_map = dict() # A mapping from position to a pyglet `VertextList` in `partial_map` self._partial_map = dict() # A mapping from sector to a list of positions (contiguous sub-region) # using sectors for fast rendering self.sectors = dict() # Use deque to populate calling of `_show_block` and `_hide_block` self.queue = deque() # A graphics batch to draw drone 3D model self.drone_batch = pyglet.graphics.Batch() # Load drone triangular mesh and scene self.drone_name = os.path.basename(drone_3d_model) self.drone_mesh = trimesh.load(drone_3d_model) self.drone_scene = self.drone_mesh.scene() # Drawer stores drone scene geometry as vertex list in its model space self.drone_drawer = None # Store drone geometry hashes for easy retrival self.drone_vertex_list_hash = '' # Store drone geometry rendering mode, default gl.GL_TRIANGLES self.drone_vertex_list_mode = gl.GL_TRIANGLES # Store drone geometry texture self.drone_texture = None black = np.array([0, 0, 0, 255], dtype=np.uint8) red = np.array([255, 0, 0, 255], dtype=np.uint8) green = np.array([0, 255, 0, 255], dtype=np.uint8) blue = np.array([0, 0, 255, 255], dtype=np.uint8) for i, facet in enumerate(self.drone_mesh.facets): if i < 30: self.drone_mesh.visual.face_colors[facet] = black elif i < 42: self.drone_mesh.visual.face_colors[facet] = red elif i < 54: self.drone_mesh.visual.face_colors[facet] = green elif i < 66: self.drone_mesh.visual.face_colors[facet] = blue else: self.drone_mesh.visual.face_colors[facet] = black # Mark positions of bounding wall and obstacles in the map self._initialize(init_drone_z)
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
class Renderer: def __init__(self, game): self.game = game self.batch = Batch() self.group = TextureGroup(self.game.textures.texture) self.sector = None self.overlay = None self.rendered = {} self.queue = deque() def drawScene(self): self.batch.draw() self.drawFocusedBlock() __call__ = drawScene def drawFocusedBlock(self): block = self.game.world.hitTest(self.game.player.position, self.game.player.sightVector())[0] if block and self.game.world[block] != self.game.textures.edge: x, y, z, = block glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) draw(24, GL_QUADS, ('v3f/static', cube_vertices(x, y, z, 0.5),), ('c3B/static', (0, 0, 0,) * 24,)) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) def drawOverlay(self): self.overlay() def changeSectors(self, before, after): oldSector, newSector, = set(), set(), padding = 4 for dx in range(-padding, padding + 1): for dy in range(-5, 7): for dz in range(-padding, padding + 1): if dx ** 2 + dy ** 2 + dz ** 2 > (padding + 1) ** 2: continue if before: x, y, z, = before oldSector.add((x + dx, y + dy, z + dz,)) if after: x, y, z, = after newSector.add((x + dx, y + dy, z + dz,)) show = newSector - oldSector hide = oldSector - newSector for sector in show: self.game.world.showSector(sector) for sector in hide: self.game.world.hideSector(sector) def drawBlock(self, position, texture): x, y, z, = position self.rendered[position] = self.batch.add(24, GL_QUADS, self.group, ('v3f/static', cube_vertices(x, y, z, 0.5),), ('t2f/static', list(texture),)) def undrawBlock(self, position): self.rendered.pop(position).delete() def enqueue(self, func, *args): self.queue.append((func, args,)) def dequeue(self): func, args, = self.queue.popleft() func(*args) def processQueue(self): start = clock() while self.queue and clock() - start < 1.0 / self.game.data.engine.ticks: self.dequeue() def processEntireQueue(self): while self.queue: self.dequeue()