def main(self): pygame.mixer.init(frequency=44100, size=8, channels=1, buffer=4096) os.environ["SDL_VIDEO_CENTERED"] = "1" pygame.init() #pygame.mixer.music.load("music.wav") #pygame.mixer.music.play(-1) icon = pygame.image.load("player.PNG") icon.set_alpha(None) icon.set_colorkey(Color("0xFF0080")) pygame.display.set_icon(icon) self.screen = pygame.display.set_mode((config.tiles_visible_x * config.tiles_size, config.tiles_visible_y * config.tiles_size)) pygame.display.set_caption("Overworld Zero Point Zero One") # Generate world noiselib.init(256) world = defaultdict(Tile) # Add forests source = fBm(5, 0.6, simplex_noise2) source = ScaleBiasNoise(1, 1, source) source = RescaleNoise((-1, 1), (0, 1), source) for y in range(0, config.tiles_world_y): for x in range(0, config.tiles_world_x): if(source((x,y)) < 1.0): world[x,y] = Tile(name = "forest") #source = fBm(4, 0.4, simplex_noise2) #source = ScaleBiasNoise(1, 1, source) #source = RescaleNoise((-1, 1), (0, 1), source) #for y in range(0, config.tiles_world_y): # for x in range(0, config.tiles_world_x): # if(source((x,y)) < 0.9): # world[x,y] = Tile(name = "forest") # Add mountain ranges source = fBm(6, 0.2, simplex_noise2, "ridged") source = ScaleBiasNoise(1, -0.6, source) source = ClampNoise(0,10,source) source_2 = fBm(7, 0, simplex_noise2, "billow") source_2 = ScaleBiasNoise(1, 0.2, source_2) source_2 = InvertNoise(source_2) source_2 = ClampNoise(0,10,source_2) source = MultNoise(source, source_2) for y in range(0, config.tiles_world_y): for x in range(0, config.tiles_world_x): if(source((x,y)) > 0): world[x,y] = Tile(name = "mountains") # Add lakes source = fBm(6, 0.05, simplex_noise2, f = 'billowed') source = ScaleBiasNoise(1, 1.4, source) source = RescaleNoise((-1, 1), (0, 1), source) for y in range(0, config.tiles_world_y): for x in range(0, config.tiles_world_x): if(source((x,y)) < 1.0): world[x,y] = Tile(name = "water") # Add roads with a castle at each end yoffset = 0 xoffset = 0 for i in range(0, config.castles_world): intersect = False #If we run into another road, create an intersection distance = random.randrange(config.road_length-5, config.road_length+6) # Put an equal number of castles in each eighth of the map to even out the distribution y = yoffset + random.randrange(0, config.tiles_world_y / 2 + 1) x = xoffset + random.randrange(0, config.tiles_world_x / 4 + 1) x, y = wrap(x, y) xoffset, yoffset = wrap(xoffset + (config.tiles_world_x / 4), yoffset + (config.tiles_world_y / 2)) horiz = random.random() < 0.5 world[x,y] = Tile(name = "castle") while(distance > 0): if(random.random() > 0.15): if horiz: x+=1 else: y+=1 else: if horiz: y+=1 else: x+=1 distance -= 1 x,y = wrap(x,y) if(world[x,y].name is "road"): intersect = True break world[x,y] = Tile(name = "road") #Create the castle at the other endpoint if not intersect: world[x,y] = Tile(name = "castle") # Add chapels for i in range(0, config.chapels_world): while True: x,y = random.randrange(0, config.tiles_world_x), random.randrange(0, config.tiles_world_y) if(world[x,y].name is "ground"): break world[x,y] = Tile(name = "chapel") # Add inns for i in range(0, config.inns_world): while True: x,y = random.randrange(0, config.tiles_world_x), random.randrange(0, config.tiles_world_y) if(world[x,y].name is "ground"): break world[x,y] = Tile(name = "inn") # Place the player while True: px, py = random.randrange(0, config.tiles_world_x), random.randrange(0, config.tiles_world_y) if(world[px,py].passable): break player = Monster(pos = (px, py), kind="player", camp=None) world[px,py].occupied_by = player # Populate with monsters monsters = [] camps = [] for i in range(0, config.camps_world): generate_camp(world, camps) #Are we currently recording? recording = False frame = 0 capture_run = 0 #Is this the first draw where monsters shouldnt move? initialize = True #Is the game over? dead = False #Main game loop while 1: if not initialize: event = pygame.event.wait() if event.type == QUIT: return if event.type == KEYDOWN: if event.key is K_q: return elif event.key is K_r: if not recording: capture_run += 1 export_world(world, capture_run) recording = not recording initialize = True elif event.key in moves.keys(): moving = moves[event.key] else: continue else: continue if(dead): return self.screen.fill(Color(0,0,0)) mess = [] #Make the player's move first, and move each monster in monsters if not initialize: if moving != (0,0): mess, dummy = player.move(moving, world, camps, monsters) # Be careful here; modifying a list mid-iteration is tricky i = 0 while i < len(monsters): m = monsters[i] # No need to increment i if a monster has been removed earlier in the list messages, result = m.move(m.ai_move(world), world, camps, monsters) mess.extend(messages) if not result: i += 1 # Spawn at camps for c in camps: if(c.population < config.camps_pop): c.countdown -= 1 if(c.countdown <= 0): t = world[c.x,c.y] if t.occupied_by is None: c.countdown = config.camps_countdown c.population += 1 m = Monster((c.x,c.y), c.kind, c) monsters.append(m) t.occupied_by = m if(player.exp > 0): player.graphic = graphics["player_bloody"] #Detect if the player has died. if(player.hp <= 0): player.graphic = new_graphic("player-dead.PNG") dead = True initialize = False for x in range(0, config.tiles_visible_x): for y in range(0, config.tiles_visible_y): t_coord = wrap(player.x - (config.tiles_visible_x / 2) + x, player.y - (config.tiles_visible_y / 2) + y) t = world[t_coord] self.screen.blit(t.graphic, (x * config.tiles_size, y * config.tiles_size)) if(t.occupied_by): self.screen.blit(t.occupied_by.graphic, (x * config.tiles_size, y * config.tiles_size)) if(t.gold > 0): self.screen.blit(graphics["gold"], (x * config.tiles_size, y * config.tiles_size)) self.hudprint("X: " + str(player.x) + " Y: " + str(player.y), 0, 0) self.messprint(mess) self.hudprint("LV: " + str(player.level), 0, self.screen.get_height()-18) self.hudprint("HP: " + str(player.hp) + "/" + str(player.totalhp), 50, self.screen.get_height()-18) self.hudprint("GP: " + str(player.gold), 150, self.screen.get_height()-18) self.hudprint("XP: " + str(player.exp) + "/" + str(config.exp_req(player.level)), 250, self.screen.get_height()-18) #Swap display buffers pygame.display.update() if(recording): #Export the screen surface to a PNG file for making videos. This can use a lot of disk space if you record for more #than a few seconds. PNG compression kills the frame rate, but the file sizes are much more manageable. pygame.image.save(self.screen, "cap/" + "run" + str(capture_run).zfill(2) + "_f" + str(frame).zfill(5) + ".PNG") frame += 1
def move(self, direction, world, camps, monsters): newx, newy = wrap(self.x + direction[0], self.y + direction[1]) t = world[newx, newy] messages = [] #Return a killed monster/player, or None if nothing is killed killed = None if t.passable: if(t.occupied_by is None): world[self.x, self.y].occupied_by = None t.occupied_by = self self.x = newx self.y = newy if(self.kind is "player" and t.gold > 0): messages.append("You picked up " + str(t.gold) + " GP.") self.gold += t.gold t.gold = 0 # Disband any camp here if t.camp and (t.camp.kind is not self.kind): if(self.kind is "player"): messages.append(t.camp.kind + " camp disbanded.") camps.remove(t.camp) self.gold += (kinds[t.camp.kind][0] * 5) #Gold bonus for disbanding the camp t.camp = None t.name = "camp_destroyed" t.graphic = graphics["camp_destroyed"] generate_camp(world, camps) if(self.kind is "player" and t.name is "inn" and self.hp < self.totalhp): if(self.gold >= config.inn_cost): messages.append("You heal at the inn.") self.gold = self.gold - config.inn_cost self.hp = self.totalhp else: messages.append("Come back when you have " + str(config.inn_cost) + " gold.") elif(t.occupied_by.kind is not self.kind): if(random.random() < 0.4): if(self.kind is "player"): messages.append("You hit the " + t.occupied_by.kind + " for " + str(self.atk + self.level) + " HP") if(t.occupied_by.kind is "player"): messages.append("The " + self.kind + " hit you for " + str(self.atk + self.level) + " HP") t.occupied_by.hp = t.occupied_by.hp - (self.atk + self.level) #level damage bonus if(t.occupied_by.hp <= 0): killed = t.occupied_by if(self.kind is "player"): messages.append("You killed the " + killed.kind + ", gaining " + str(killed.level) + " XP") if(killed.kind is "player"): messages.append("You have been killed by the " + self.kind) self.exp += killed.level if(self.exp >= config.exp_req(self.level)): self.level += 1 #Level up self.totalhp += 2 self.hp += 2 if(self.kind is "player"): messages.append("You have leveled up.") if(killed.kind is not "player"): #Leave the player's corpse visible t.occupied_by = None t.gold = killed.gold if(killed.camp): killed.camp.population -= 1 oldmonsters = monsters[:] if killed.kind is not "player": monsters.remove(killed) if (self.kind is not "player" and oldmonsters.index(killed) <= oldmonsters.index(self)): return messages, True else: if(self.kind is "player"): messages.append("You missed the " + t.occupied_by.kind) if(t.occupied_by.kind is "player"): messages.append("The " + self.kind + " missed you") return messages, False