2616bc7d |
# Copyright (c) 2013 Edward Langley
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of the project's author nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2c098630 |
from __future__ import division
import colorsys
import ctypes
import libtcodpy as libtcod
import random
import time
|
7b5ffdd9 |
import yaml
|
2c098630 |
inst = lambda a:a()
@inst
class Settings:
|
7b5ffdd9 |
def __init__(self):
|
de9b8c09 |
with file('data/settings.yaml') as f:
self.settings = yaml.safe_load(f)
def __getattr__(self, attr):
return self.settings[attr]
|
7b5ffdd9 |
SCREEN_WIDTH = 75
|
aa15ba39 |
SCREEN_HEIGHT = 20
|
7b5ffdd9 |
DISPLAY_HEIGHT = property(lambda self: self.SCREEN_HEIGHT+2)
|
2c098630 |
LIMIT_FPS = 20
BASE = 8
LEVELS = 3
libtcod.console_init_root(Settings.SCREEN_WIDTH, Settings.DISPLAY_HEIGHT, 'Mapping', False)
|
aa15ba39 |
libtcod.console_set_custom_font("terminal.png",libtcod.FONT_LAYOUT_ASCII_INROW|libtcod.FONT_TYPE_GREYSCALE)
|
2c098630 |
#libtcod.console_set_fullscreen(True)
con = libtcod.console_new(Settings.SCREEN_WIDTH, Settings.SCREEN_HEIGHT)
blank = libtcod.console_new(Settings.SCREEN_WIDTH, Settings.SCREEN_HEIGHT)
#for x in range(Settings.SCREEN_WIDTH):
#for y in range(Settings.SCREEN_HEIGHT):
message_con = libtcod.console_new(Settings.SCREEN_WIDTH, 2)
|
aa15ba39 |
libtcod.console_set_default_background(message_con,libtcod.red)
|
2c098630 |
#libtcod.console_set_default_background(blank,libtcod.red)
libtcod.sys_set_fps(Settings.LIMIT_FPS)
import map
level = 1
mp = map.Map.rand_new(Settings.LEVELS, Settings.BASE) ## warning: exponential BASE ** LEVELS
mapping = {}
colors = {
':': colorsys.rgb_to_hsv(0.0,0.0,1.0),
|
aa15ba39 |
chr(5): colorsys.rgb_to_hsv(0.0,0.5,0.0),
|
2c098630 |
'*': colorsys.rgb_to_hsv(1.0,1.0,0.0),
}
df = 1/40.0
for x in range(-20,20):
|
aa15ba39 |
char = random.choice(['.','.','.','*','*',';',':','"',"'",chr(5),'`'])
|
2c098630 |
if char in colors:
h,s,v = colors[char]
print s,v
color = colorsys.hsv_to_rgb(h,s/1.75,v/2)
bgcolor = colorsys.hsv_to_rgb(h,s/4,v/4)
else:
hue = x+21 * df
color = colorsys.hsv_to_rgb(1/hue,0.5,0.5)
bgcolor = colorsys.hsv_to_rgb(1/hue,0.25,0.25)
color = [int(h*255) for h in color]
bgcolor = [int(h*255) for h in bgcolor]
mapping[x] = (libtcod.Color(*color), char, libtcod.Color(*bgcolor))
names = {
'.': ('open',True,False),
'*': ('meadow',True,False),
';': ('marsh',1-0.05,False), ## Note: 1-0.05 means a 5% chance of being opaque
':': ('pond',True,True),
'"': ('heath',True,False),
"'": ('marsh',1-0.15,False),
|
aa15ba39 |
chr(5): ('forest',False,True),
|
2c098630 |
'`': ('copse',1-0.5,False),
}
class LevelMap(object):
def __init__(self, map):
self.map = map
self.fovmaps = [None]
def get_tile_type(self, level,x,y):
|
9f8d7155 |
lvl = self.map.get_level(level)
tile_val = mapping.get(lvl[y][x],(None,' '))[1]
|
2c098630 |
return names.get(tile_val,('',True,True))
def get_fovmap(self,level):
if level >= len(self.fovmaps):
|
9f8d7155 |
levelmap = mp.get_level(level)
|
2c098630 |
self.fovmaps.append(libtcod.map_new(len(levelmap), len(levelmap[0])))
libtcod.map_clear(self.fovmaps[-1])
return self.fovmaps[level]
def has_level(self, level):
return 1 <= level < len(self.fovmaps)
def adj_map(self, level, x,y):
fovmap = self.get_fovmap(level)
__, trans,block = self.get_tile_type(level,x,y)
trans = random.random() < trans
libtcod.map_set_properties(fovmap, x,y, trans, not block)
def comp_fov(self, level, player_x, player_y, light_radius=10):
fovmap = self.get_fovmap(level)
libtcod.map_compute_fov(fovmap, player_x, player_y, light_radius, False)
def get_color(self, level,x,y, color):
fovmap = self.get_fovmap(level)
|
aa15ba39 |
if libtcod.map_is_in_fov(fovmap, x,y) and libtcod.map_is_walkable(fovmap,x,y):
|
2c098630 |
#print 'cell in fov', level,x,y, libtcod.map_get_width(fovmap), libtcod.map_get_height(fovmap)
color = [x/255 for x in color]
h,s,v = colorsys.rgb_to_hsv(*color)
r,g,b = [int(x*255) for x in colorsys.hsv_to_rgb(h,s, v+0.15)]
color = libtcod.Color(r,g,b)
return color
def get_walkable(self, level, x,y):
fovmap = self.get_fovmap(level)
return libtcod.map_is_walkable(fovmap,x,y)
def calculate_level(self, level):
if not self.has_level(level):
print 'calculate_level'
|
9f8d7155 |
lvl = mp.get_level(level)
for y,row in enumerate(lvl):
|
2c098630 |
for x,__ in enumerate(row):
lm.adj_map(level, x,y)
|
de9b8c09 |
|
2c098630 |
lm = LevelMap(mp)
lm.calculate_level(level)
libtcod.console_set_default_foreground(message_con, libtcod.white)
for c in [con,message_con]:
libtcod.console_set_default_foreground(c, libtcod.white)
|
aa15ba39 |
libtcod.console_clear(c)
|
2c098630 |
offset_x, offset_y = 0,0
|
9f8d7155 |
levelmap = mp.get_level(level)
MAP_Y,MAP_X = len(levelmap), len(levelmap[0])
|
2c098630 |
player_x, player_y = random.randrange(0,MAP_X),random.randrange(0,MAP_Y)
if not lm.get_walkable(level,player_x,player_y):
player_x,player_y = [(x,y) for x in range(player_x-2,player_x+3) for y in range(player_y-2,player_y+3) if lm.get_walkable(level,x,y)][-1]
import time
ak=0
while not libtcod.console_is_window_closed():
t0 = time.time()
|
aa15ba39 |
if player_x - offset_x >= Settings.SCREEN_WIDTH-5: offset_x += 5
elif player_x - offset_x < 5: offset_x -= 5
|
2c098630 |
|
aa15ba39 |
if player_y - offset_y >= Settings.SCREEN_HEIGHT-5: offset_y += 5
elif player_y - offset_y < 5: offset_y -= 5
|
2c098630 |
offset_y = min(offset_y,MAP_Y-Settings.SCREEN_HEIGHT)
offset_y = max(offset_y,0)
offset_x = min(offset_x,MAP_X-Settings.SCREEN_WIDTH)
offset_x = max(offset_x,0)
t1 = time.time()
lm.comp_fov(level, player_x, player_y,10)
|
aa15ba39 |
player_screen_pos = player_x-offset_x,player_y-offset_y
|
9f8d7155 |
for y,row in enumerate(levelmap[offset_y:offset_y+Settings.SCREEN_HEIGHT]):
|
2c098630 |
for x,cell in enumerate(row[offset_x:offset_x+Settings.SCREEN_WIDTH]):
color,char,bgcolor = mapping.get(cell, (libtcod.Color(0,0,0),' ',libtcod.Color(0,0,0)))
color = lm.get_color(level, x+offset_x, y+offset_y, color)
bgcolor = lm.get_color(level, x+offset_x, y+offset_y, bgcolor)
|
aa15ba39 |
if (x,y) == player_screen_pos:
|
7b5ffdd9 |
color = libtcod.Color(128,128,100)
|
aa15ba39 |
char = '\x01'
|
2c098630 |
libtcod.console_set_char_foreground(con, x,y, color)
libtcod.console_set_char_background(con, x,y, bgcolor)
libtcod.console_set_char(con,x,y,char)
print 'draw loop:', time.time()-t1
libtcod.console_print(message_con, 0,1,lm.get_tile_type(level, player_x,player_y)[0])
libtcod.console_blit(message_con, 0,0, Settings.SCREEN_WIDTH,2, 0, 0,Settings.DISPLAY_HEIGHT-2)
blit_x,blit_y = 0,0
blit_w,blit_h = Settings.SCREEN_WIDTH, Settings.SCREEN_HEIGHT
if blit_x + MAP_X < Settings.SCREEN_WIDTH:
blit_x = (Settings.SCREEN_WIDTH - (blit_x + MAP_X))/2
blit_x = int(blit_x)
blit_w = MAP_X
if blit_y + MAP_Y < Settings.SCREEN_HEIGHT:
blit_y = (Settings.SCREEN_HEIGHT - (blit_y + MAP_Y))/2
blit_y = int(blit_y)
blit_h = MAP_Y
libtcod.console_blit(con, 0,0, blit_w,blit_h , 0,blit_x,blit_y)
libtcod.console_flush()
libtcod.console_clear(message_con)
bk = (time.time()-t0)*1000
print 'time to keypress:', bk
print 'loop time:', ak+bk
key = libtcod.Key()
mouse = libtcod.Mouse()
libtcod.sys_wait_for_event(libtcod.EVENT_KEY_PRESS, key, mouse, False)
t0 = time.time()
olevel = level
diff = 1
if key.shift:
diff *= 10
alt = key.lalt | key.ralt
ox,oy = player_x,player_y
dest_x,dest_y = player_x,player_y
if key.vk == libtcod.KEY_DOWN and player_y < MAP_Y:
dest_y += diff
if alt:
dest_x -= diff
elif key.vk == libtcod.KEY_UP and dest_y > 0:
dest_y -= diff
if alt:
dest_x += diff
elif key.vk == libtcod.KEY_RIGHT and dest_x < MAP_X:
dest_x += diff
if alt:
dest_y += diff
elif key.vk == libtcod.KEY_LEFT and dest_x > 0:
dest_x -= diff
if alt:
dest_y -= diff
|
fe324e6d |
elif key.vk == libtcod.KEY_ESCAPE and any([key.lctrl,key.rctrl]): break
|
2c098630 |
elif key.c == ord('>') and level < mp.depth: level += 1
elif key.c == ord('<') and level > 1: level -= 1
dest_x = min(dest_x,MAP_X-1)
dest_y = min(dest_y,MAP_Y-1)
dest_x = max(dest_x,0)
dest_y = max(dest_y,0)
if olevel == level:
libtcod.line_init(player_x,player_y, dest_x,dest_y)
nx,ny = libtcod.line_step()
while None not in {nx,ny}:
if not lm.get_walkable(level,nx,ny):
|
aa15ba39 |
libtcod.console_print(message_con, 0,0,'You cannot walk through a %s' % lm.get_tile_type(level, nx,ny)[0])
|
2c098630 |
break
print nx,ny
player_x,player_y = nx,ny
nx,ny = libtcod.line_step()
else:
player_prop = player_x/MAP_X, player_y/MAP_Y
offset_prop = offset_x/MAP_X, offset_y/MAP_Y
|
9f8d7155 |
levelmap = mp.get_level(level)
MAP_Y,MAP_X = len(levelmap), len(levelmap[0])
|
2c098630 |
libtcod.console_clear(0)
libtcod.console_clear(con)
print 'before:',offset_x, player_x, offset_x+Settings.SCREEN_WIDTH
player_x = int(MAP_X * player_prop[0])
player_y = int(MAP_Y * player_prop[1])
offset_x = int(player_x - Settings.SCREEN_WIDTH / 2)
if offset_x + Settings.SCREEN_WIDTH > MAP_X:
offset_x -= (offset_x+Settings.SCREEN_WIDTH) - MAP_X
offset_y = int(player_y - Settings.SCREEN_HEIGHT / 2)
if offset_y + Settings.SCREEN_HEIGHT > MAP_Y:
offset_y -= (offset_x+Settings.SCREEN_HEIGHT) - MAP_Y
lm.calculate_level(level)
if not lm.get_walkable(level,player_x,player_y):
player_x,player_y = [(x,y) for x in range(player_x-2,player_x+3) for y in range(player_y-2,player_y+3) if lm.get_walkable(level,x,y)][-1]
print 'time after keypress:', (time.time()-t0)*1000
|