예제 #1
0
    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
예제 #2
0
    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