def on_mouse_press(self, x, y, button, modifiers): """ Called when a mouse button is pressed. See pyglet docs for button amd modifier mappings. Parameters ---------- x, y : int The coordinates of the mouse click. Always center of the screen if the mouse is captured. button : int Number representing mouse button that was clicked. 1 = left button, 4 = right button. modifiers : int Number representing any modifying keys that were pressed when the mouse button was clicked. """ if self.exclusive: vector = self.get_sight_vector() block, previous = self.model.hit_test(self.position, vector) if (button == mouse.RIGHT) or \ ((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)): # ON OSX, control + left click = right click. if previous: px, py, pz = util.normalize(self.position) if not (previous == (px, py, pz) or previous == (px, py-1, pz)): self.model.sectors[util.sectorize(previous)].add_block(previous, BLOCK_ID[self.block]) # # self.model.add_block(previous, self.block) elif button == pyglet.window.mouse.LEFT and block: # texture = self.model[block] # if texture != STONE: self.model.sectors[util.sectorize(block)].remove_block(block) else: self.set_exclusive_mouse(True)
def __getitem__(self, position): """ retrieves the block at the (x,y,z) coordinate tuple `position` """ try: return self.sectors[sectorize(position)][position] except: return None
def neighbor_sectors(self, pos): """ return a tuple (dx, dz, sector) of currently loaded neighbors to the sector at pos """ pos = sectorize(pos) for x in ((-1,0),(1,0),(0,-1),(0,1)): npos = (pos[0]+x[0]*SECTOR_SIZE,0,pos[2]+x[1]*SECTOR_SIZE) if npos in self.sectors: yield x[0],x[1],self.sectors[npos]
def on_mouse_press(self, x, y, button, modifiers): """ Called when a mouse button is pressed. See pyglet docs for button amd modifier mappings. Parameters ---------- x, y : int The coordinates of the mouse click. Always center of the screen if the mouse is captured. button : int Number representing mouse button that was clicked. 1 = left button, 4 = right button. modifiers : int Number representing any modifying keys that were pressed when the mouse button was clicked. """ if self.exclusive: vector = self.get_sight_vector() block, previous = self.model.hit_test(self.position, vector) if (button == mouse.RIGHT) or \ ((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)): # ON OSX, control + left click = right click. if previous: px, py, pz = util.normalize(self.position) if not (previous == (px, py, pz) or previous == (px, py - 1, pz)): self.model.sectors[util.sectorize(previous)].add_block( previous, BLOCK_ID[self.block]) # # self.model.add_block(previous, self.block) elif button == pyglet.window.mouse.LEFT and block: # texture = self.model[block] # if texture != STONE: self.model.sectors[util.sectorize(block)].remove_block(block) else: self.set_exclusive_mouse(True)
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) b = self[key] if not BLOCK_SOLID[b] or b is None: continue # self.update_block(key) self.sectors[sectorize(key)].update_block(key)
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.world[position] self.sectors[sectorize(position)].remove(position) if immediate: if position in self.shown: self.hide_block(position) self.check_neighbors(position)
def update(self, dt): """ This method is scheduled to be called repeatedly by the pyglet clock. Parameters ---------- dt : float The change in time since the last call. """ # self.model.process_queue() sector = util.sectorize(self.position) if sector != self.sector: print('changing sectors',self.sector,'to',sector) self.model.change_sectors(self.sector, sector) self.sector = sector m = 20 dt = min(dt, 0.2) for _ in xrange(m): self._update(dt / m)
def update(self, dt): """ This method is scheduled to be called repeatedly by the pyglet clock. Parameters ---------- dt : float The change in time since the last call. """ # self.model.process_queue() sector = util.sectorize(self.position) if sector != self.sector: print('changing sectors', self.sector, 'to', sector) self.model.change_sectors(self.sector, sector) self.sector = sector m = 20 dt = min(dt, 0.2) for _ in xrange(m): self._update(dt / m)
def update(self, dt): """ This method is scheduled to be called repeatedly by the pyglet clock. Parameters ---------- dt : float The change in time since the last call. """ self.model.process_queue() sector = sectorize(self.position) if sector != self.sector: self.model.change_sectors(self.sector, sector) if self.sector is None: self.model.process_entire_queue() self.sector = sector m = 8 dt = min(dt, 0.2) for _ in range(m): self._update(dt / m)
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.world: self.remove_block(position, immediate) self.world[position] = texture self.sectors.setdefault(sectorize(position), []).append(position) if immediate: if self.exposed(position): self.show_block(position) self.check_neighbors(position)
def _load_sectors(self, old_sectors_pos, new_pos): #TODO: Need to update the edges of blocks that are at the edge of the map dt = 1e-4 adds = 0 G = range(-LOADED_SECTORS,LOADED_SECTORS+1) sectors_pos = set() for dx,dy,dz in itertools.product(G,(0,),G): pos = numpy.array([new_pos[0],new_pos[1],new_pos[2]]) \ + numpy.array([dx*SECTOR_SIZE,dy,dz*SECTOR_SIZE]) pos = sectorize(pos) sectors_pos.add(pos) if pos not in old_sectors_pos: t = time.time() adds += 1 s = Sector(pos,self.group,self,False) s._initialize() time.sleep(dt) s.calc_exposed_faces() with self.sector_lock: self.sectors[pos] = s s.invalidate() s.check_show(add_to_batch = False) s.shown = True with self.sector_lock: for dx,dz,ns in self.neighbor_sectors(pos): ns.update_edge(-dx,-dz,s) time.sleep(dt) print 'sector',pos,'took',time.time()-t #TODO: should probably lock the mutex for this removes = 0 with self.sector_lock: for pos in old_sectors_pos: if pos not in sectors_pos: del self.sectors[pos] removes += 1 self.thread=None print 'added',adds print 'removed',removes
def __init__(self): # A TextureGroup manages an OpenGL texture. self.group = TextureGroup(image.load(TEXTURE_PATH).get_texture()) mapgen.initialize_map_generator() # The world is stored in sector chunks. self.sectors = {} self.sector_lock = threading.Lock() self.thread = None # Simple function queue implementation. The queue is populated with # _show_block() and _hide_block() calls # self.queue = deque() d = range(-SECTOR_SIZE,SECTOR_SIZE+1,SECTOR_SIZE) #d = range(-128,128+1,SECTOR_SIZE) for pos in itertools.product(d,(0,),d): s=Sector(pos, self.group, self) self.sectors[sectorize(pos)] = s s._initialize() for s in self.sectors: self.sectors[s].check_show()
def edge_blocks(self,dx=0,dz=0): pos = self.position try: s=self.model.sectors[sectorize((pos[0]+dx*SECTOR_SIZE,pos[1],pos[2]+dz*SECTOR_SIZE))] except KeyError: s=None if s is not None: if dx>0: return BLOCK_SOLID[s.blocks[0,:,:]]==0 elif dx<0: return BLOCK_SOLID[s.blocks[-1,:,:]]==0 elif dz>0: return BLOCK_SOLID[s.blocks[:,:,0]]==0 elif dz<0: return BLOCK_SOLID[s.blocks[:,:,-1]]==0 else: if dx>0: return numpy.zeros((SECTOR_HEIGHT,SECTOR_SIZE),dtype=bool) elif dx<0: return numpy.zeros((SECTOR_HEIGHT,SECTOR_SIZE),dtype=bool) elif dz>0: return numpy.zeros((SECTOR_SIZE,SECTOR_HEIGHT),dtype=bool) elif dz<0: return numpy.zeros((SECTOR_SIZE,SECTOR_HEIGHT),dtype=bool)