def shift(self, _delta_chunk): """Updates the EntityBuffer's list of entities based on the player's movement. Args: _delta_chunk (int): Number of chunks the Player crossed after the previous iteration. """ prev_entities = self.entities.copy() if _delta_chunk > 0: for i in range(_delta_chunk): self.entities.append( self.load(self.chunk_buffer.get_end_chunk_ind() + i + 1)) self.save(self.entities[i], self.chunk_buffer.get_start_chunk_ind() + i) self.entities.pop(0) else: for i in range(abs(_delta_chunk)): self.entities.insert( i, self.load(self.chunk_buffer.get_start_chunk_ind() - i - 1)) self.save(self.entities[-i - 1], self.chunk_buffer.get_end_chunk_ind() - i) self.entities.pop(-1) if self.entities != prev_entities: consts.dbg(1, "ENTITY BUFFER - END OF SHIFT - ENTITIES LIST:", self.entities)
def __init__( self, world_name ): """Initializes the Serializer object. Args: world_name (str): Name of the world. """ self.name = "Worlds/" + world_name + '.db' self.world_time = 0 self.day_time = 0 if not os.path.isdir("Worlds"): os.mkdir("Worlds") self.conn = sqlite3.connect( self.name ) c = self.conn.cursor() try: # Create Table c.execute( '''CREATE TABLE terrain(keys INTEGER NOT NULL PRIMARY KEY, list TEXT, local TEXT, chunk_time TEXT, entity TEXT)''' ) self.conn.commit() c.execute( '''CREATE TABLE player(playername TEXT NOT NULL PRIMARY KEY, pickledplayer TEXT)''' ) self.conn.commit() c.execute( '''CREATE TABLE info(world_time TEXT)''' ) self.conn.commit() except Exception as e: consts.dbg(1, "EXCEPTION IN SERIALIZER INIT:", e) self.world_time = self.get_world_time()
def add_entity(self, _entity): """Adds the given Entity or ItemEntity to the EntityBuffer's entity list. Args: _entity (Entity | ItemEntity): Entity or ItemEntity object to be added. _ind (int): Index at which the Entity or ItemEntity is to be added. """ _ind = self.get_curr_chunk_ind(_entity.get_pos().copy()) consts.dbg(1, "ADD ENTITY INDEX:", _ind) self.entities[_ind].append(_entity)
def calc_friction(self): """Updates the Entity's friction based on the tile in contact with the bottom left point in the entity's hitbox. """ try: tile = self.tile((self.friction_point(self.pos)[0], self.friction_point(self.pos)[1] - 1)) consts.dbg(0, "IN CALC FRICTION - TILE:", tile) self.friction = consts.TILE_ATTR[tile][consts.tile_attr.FRICTION] except Exception as e: consts.dbg(0, "IN CALC FRICTION - EXCEPTION", e) self.friction = consts.AIR_FRICTION
def pick_item(self, _pos, _range): items = [] for index in range(self.len - 1, -1, -1): for entity_ind in range(len(self.entities[index]) - 1, -1, -1): entity = self.entities[index][entity_ind] if (isinstance(entity, ItemEntity)) and (consts.dist_between_points( entity.pos, _pos) <= _range): items.append(entity) consts.dbg(1, "ENTITY BUFFER BEFORE PICK ITEM:", self.entities) self.entities[index].pop(entity_ind) return items
def get_world_time( self ): """Gets the pickled world time from the database. Returns: Union[bytes, None]: The pickled world time or None if it does not exist. """ c = self.conn.cursor() c.execute( '''SELECT world_time FROM info''' ) res = c.fetchone() self.conn.commit() try: return bz2.decompress( res[0] ) except Exception as e: consts.dbg( 1, "EXCEPTION IN SERIALIZER GET_WORLD_TIME:", e ) return res
def set_world_time( self, _time ): """Saves/Updates the pickled world time in the database. Args: _time (bytes): Pickled world time. """ c = self.conn.cursor() try: # Set world time for the first time c.execute( '''INSERT INTO info (world_time) VALUES (?)''', ( bz2.compress( _time ), ) ) self.conn.commit() except Exception as e: # Update world time consts.dbg( 1, "EXCEPTION IN SERIALIZER SET_WORLD_TIME:", e ) c.execute( '''UPDATE info SET world_time=?''', ( bz2.compress( _time ), ) ) self.conn.commit()
def set_entity(self, _key, _li): """Saves/Updates the pickled entity list in the database at the given key. Args: _key (int): Key at which the bytes object is to be saved. _li (bytes): Pickled entity list. """ c = self.conn.cursor( ) try: # Save string at new key location c.execute( '''INSERT INTO terrain (entity, keys) VALUES (?,?)''', (bz2.compress( _li ), _key) ) self.conn.commit( ) except Exception as e: consts.dbg(1, "EXCEPTION IN SERIALIZER SET_ENTITY:", e ) # Update string at existing key c.execute( '''UPDATE terrain SET entity =? WHERE keys=?''', (bz2.compress( _li ), _key) ) self.conn.commit( )
def set_chunk_time( self, _key, _time ): """Saves/Updates the pickled chunk time in the database at the given key. Args: _key (int): Key at which the bytes object is to be saved. _time (bytes): Pickled chunk time. """ c = self.conn.cursor() try: # Set world time for the first time c.execute( '''INSERT INTO terrain (chunk_time) VALUES (?) WHERE keys=?''', ( bz2.compress( _time ), _key) ) self.conn.commit() except Exception as e: # Update world time consts.dbg( 1, "EXCEPTION IN SERIALIZER SET_CHUNK_TIME:", e ) c.execute( '''UPDATE terrain SET chunk_time=? WHERE keys=?''', ( bz2.compress( _time ), _key) ) self.conn.commit()
def save_player( self, _id, _pickled_player ): """Saves/Updates the pickled player in the database at the given ID. Args: _id (int): ID at which the pickled player is to be saved. _pickled_player (bytes): Pickled player. """ c = self.conn.cursor() try: # Save pickledplayer at new playername c.execute( '''INSERT INTO player (playername, pickledplayer) VALUES (?,?)''', (_id, bz2.compress( _pickled_player )) ) self.conn.commit() except Exception as e: # Update pickledplayer at existing playername consts.dbg( 1, "EXCEPTION IN SERIALIZER SAVE_PLAYER:", e ) c.execute( '''UPDATE player SET pickledplayer =? WHERE playername=?''', (bz2.compress( _pickled_player ), _id) ) self.conn.commit()
def get_chunk_time( self, _key ): """Gets the pickled chunk time from the database at the given key. Args: _key (int): Key at which the bytes object is to be loaded. Returns: Union[bytes, None]: The pickled chunk time or None if it does not exist. """ c = self.conn.cursor() c.execute( '''SELECT chunk_time FROM terrain WHERE keys=?''', ( _key, )) res = c.fetchone() self.conn.commit() try: return bz2.decompress( res[0] ) except Exception as e: consts.dbg( 1, "EXCEPTION IN SERIALIZER GET_CHUNK_TIME:", e ) return res
def load_player( self, _id ): """Gets the pickled player from the database at the given ID. Args: _id (int): ID at which the pickled player is to be loaded. Returns: Union[bytes, None]: The pickled player or None if it does not exist. """ c = self.conn.cursor() c.execute( '''SELECT pickledplayer FROM player WHERE playername=?''', (_id,) ) res = c.fetchone() self.conn.commit() try: return bz2.decompress( res[0] ) except Exception as e: consts.dbg( 1, "EXCEPTION IN SERIALIZER LOAD_PLAYER:", e ) return res
def set_chunk( self, _key, _t0, _t1 ): """Saves/Updates the pickled chunk tile list and the local tile table in the database at the given key. Args: _key (int): Key at which the bytes object is to be saved. _t0 (bytes): Pickled chunk tile list. _t1 (bytes): Pickled chunk tile table. """ t = _t0, _t1 c = self.conn.cursor() try: # Save string at new key location c.execute( '''INSERT INTO terrain (keys, list, local) VALUES (?,?,?)''', (_key, bz2.compress( t[0 ] ), bz2.compress( t[1 ] )) ) self.conn.commit() except Exception as e: # Update string at existing key consts.dbg( 1, "EXCEPTION IN SERIALIZER SETITEM:", e ) c.execute( 'UPDATE terrain SET list =?, local =? WHERE keys=?', (bz2.compress( t[0] ), bz2.compress( t[1] ), _key) ) self.conn.commit()
def get_entity(self, _key): """Gets the pickled entity list from the database at the given key. Args: _key (int): Key at which the bytes object is to be loaded. Returns: Union[bytes, None]: The pickled entity list or None if it does not exist. """ c = self.conn.cursor() c.execute( '''SELECT entity FROM terrain WHERE keys=?''', (_key,) ) li = c.fetchone() self.conn.commit() try: li = bz2.decompress( li[0] ) return li except Exception as e: consts.dbg( 1, "EXCEPTION IN SERIALIZER GET_ENTITY:", e ) return None
def update(self, _dt): update_index_entities = [] index = 0 entities_copy = [ self.entities[_ind].copy() for _ind in range(self.len) ] while index < self.len: entity_ind = 0 while entity_ind < len(entities_copy[index]): entity = entities_copy[index][entity_ind] prev_entity_ind = entity_ind entity_ind += 1 if entity not in self.entities[index]: continue # prev_entity_pos = entity.get_pos( ).copy( ) chk_a = time.time() entity.run(_dt) entity.update(_dt) consts.dbg(1, "ENTITY UPDATE TIME TAKEN(in milliseconds):", (time.time() - chk_a) * 1000) new_index = self.get_curr_chunk_ind(entity.get_pos()) if new_index != prev_entity_ind: self.entities[index].remove(entity) update_index_entities.append(entity) index += 1 for entity in update_index_entities: consts.dbg(1, "UPDATE ENTITY INDEX:", update_index_entities) index = self.get_curr_chunk_ind(entity.get_pos()) consts.dbg(1, "NEW INDEX OF ENTITY:", index) self.entities[index].append(entity)
def get_chunk(self, _key): """Gets the pickled chunk tile list and the local tile table from the database at the given key. Args: _key (int): Key at which the bytes object is to be loaded. Returns: Union[bytes, None]: The pickled chunk tile list and the local tile table or None if it does not exist. """ c = self.conn.cursor() c.execute( '''SELECT list FROM terrain WHERE keys=?''', (_key,) ) li = c.fetchone() c.execute( '''SELECT local FROM terrain WHERE keys=?''', (_key,) ) lo = c.fetchone() self.conn.commit() try: li = bz2.decompress( li[0] ) lo = bz2.decompress( lo[0] ) return li, lo except Exception as e: consts.dbg( 1, "EXCEPTION IN SERIALIZER GETITEM:", e ) return None
def run(self, _dt): self.acc = [0, 0] player_pos = self.entity_buffer.player.pos if self.grounded: self.vel = [0, 0] self.cooldown = max(0, self.cooldown - _dt) if not self.cooldown: consts.dbg(1, "IN RUN - SLIME TOUCHED GROUND") # self.vel = [0, 0] self.jump() self.cooldown = 2 else: if not self.grounded: if player_pos[0] > self.pos[0]: consts.dbg(1, "SLIME - IN RUN - MOVING RIGHT") self.vel[0] = 0.5 elif player_pos[0] < self.pos[0]: consts.dbg(1, "SLIME - IN RUN - MOVING LEFT") self.vel[0] = -0.5
def check(self, _pos): """Checks whether the hitbox of the Entity collides with a tile. Args: _pos (list): Position of the entity from which the hitbox is computed. Returns: bool: True if the hitbox is colliding else False. """ # For every corresponding tile between hitbox endpoints including the endpoints, # check that the hitbox and the tile don't intersect if self.tangibility: return True hitbox = self.hitbox(_pos) for point in hitbox: consts.dbg(1, "IN CHECK - ENTERED FOR LOOP") if self.tile(point) != consts.tiles.air: consts.dbg(1, "CHECK RETURNED FALSE") return False consts.dbg(1, "CHECK RETURNED TRUE") return True
def run(self, _dt): """Updates the Player's variables to handle the user's input. Args: _dt (float): Time passed between previous and current iteration. """ self.acc[0] = 0 self.acc[1] = 0 self.hitting = False self.placing = False if self.key_state[pygame.K_a] and not self.key_state[pygame.K_d]: consts.dbg(1, "IN RUN - MOVING LEFT") self.move_left() self.texture_strct.run_left(_dt) elif self.key_state[pygame.K_d] and not self.key_state[pygame.K_a]: consts.dbg(1, "IN RUN - MOVING RIGHT") self.move_right() self.texture_strct.run_right(_dt) else: self.texture_strct.run_static() if self.key_state[pygame.K_s] and not self.key_state[pygame.K_w]: consts.dbg(1, "IN RUN - MOVING DOWN") self.move_down() elif (self.tangibility or self.grounded) and self.key_state[ pygame.K_w] and not self.key_state[pygame.K_s]: consts.dbg(1, "IN RUN - MOVING UP") self.jump() if self.mouse_state[pygame.BUTTON_LEFT]: consts.dbg(1, "IN RUN - LEFT MOUSE BUTTON PRESSED") self.left_click(_dt, self.cursor_pos) if self.mouse_state[pygame.BUTTON_RIGHT]: consts.dbg(1, "IN RUN - RIGHT MOUSE BUTTON PRESSED") self.right_click(_dt, self.cursor_pos)
def update(self, _dt): """Updates the Entity's position, velocity and state. Args: _dt (float): Time passed between previous and current iteration. """ self.pick() consts.dbg(1, "IN ENTITY - ENTERING UPDATE") dt2 = _dt _dt = 1 / (consts.MAX_VEL * consts.SCALE_VEL) while dt2 > 0: if dt2 <= _dt: _dt = dt2 dt2 = 0 else: dt2 -= _dt consts.dbg(0, "IN UPDATE WHILE LOOP - AFTER CALCULATING - DT:", _dt) consts.dbg(0, "IN UPDATE WHILE LOOP - AFTER CALCULATING - DT2:", dt2) consts.dbg(1, "INSIDE UPDATE WHILE LOOP") self.calc_friction() consts.dbg(0, "IN UPDATE WHILE LOOP - AFTER CALCULATING - FRICTION:", self.friction) self.check_ground(self.pos) if consts.GRAVITY_ACC and (not self.grounded): self.acc[1] = -consts.GRAVITY_ACC consts.dbg(0, "IN UPDATE - AT START - PLAYER VEL:", self.vel) consts.dbg(0, "IN UPDATE - AT START - PLAYER ACC:", self.acc) for i in range(0, 2): next_pos = self.pos.copy() next_vel = self.vel[i] + self.acc[i] * _dt if next_vel >= abs(self.friction * _dt): self.vel[i] -= self.friction * _dt elif next_vel <= -abs(self.friction * _dt): self.vel[i] += self.friction * _dt else: self.vel[i] = 0 self.acc[i] = 0 if self.acc[i] > consts.MAX_ACC * 2: self.acc[i] = consts.MAX_ACC * 2 elif self.acc[i] < -consts.MAX_ACC * 2: self.acc[i] = -consts.MAX_ACC * 2 self.vel[i] += self.acc[i] * _dt if self.vel[i] < -consts.MAX_VEL * (1 - self.friction * 0.2): self.vel[i] = -consts.MAX_VEL * (1 - self.friction * 0.2) elif self.vel[i] > consts.MAX_VEL * (1 - self.friction * 0.2): self.vel[i] = consts.MAX_VEL * (1 - self.friction * 0.2) next_pos[i] += self.vel[i] * consts.SCALE_VEL * _dt move = self.check(next_pos) if move: if (i == 0) or (i == 1 and consts.CHUNK_HEIGHT_P >= next_pos[i] >= 0): self.pos[i] += self.vel[i] * consts.SCALE_VEL * _dt if consts.CHUNK_HEIGHT_P < self.pos[1]: self.pos[1] = consts.CHUNK_HEIGHT_P consts.dbg( -1, "IN UPDATE WHILE LOOP - IN MOVE - POS > MAX HEIGHT" ) elif 0 > self.pos[1]: self.pos[1] = 0 consts.dbg( -1, "IN UPDATE WHILE LOOP - IN MOVE - POS < MIN HEIGHT" ) else: self.vel[i] = 0 if self.vel == [0, 0]: break
def pick(self): items = self.entity_buffer.pick_item(self.pos.copy(), self.range) if items: consts.dbg(1, "ITEMS TO PICK:", items) for item in items: self.inventory.add_item(item.id, 1)