Advertisement
Guest User

Untitled

a guest
Oct 27th, 2016
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.19 KB | None | 0 0
  1. import libtcodpy as libtcod
  2. import math
  3.  
  4. import maps #import maps.py, text with map information
  5.  
  6. #actual size of the window
  7. SCREEN_WIDTH = 80
  8. SCREEN_HEIGHT = 50
  9.  
  10. #size of the map
  11. MAP_WIDTH = 80
  12. MAP_HEIGHT = 30
  13.  
  14. LIMIT_FPS = 20 #20 frames-per-second maximum
  15.  
  16.  
  17. color_dark_wall = libtcod.Color(0, 0, 100)
  18. color_light_wall = libtcod.Color(130, 110, 50)
  19. color_dark_ground = libtcod.Color(50, 50, 150)
  20. color_light_ground = libtcod.Color(200, 180, 50)
  21.  
  22. FOV_ALGO = 0 #default FOV algorithm
  23. FOV_LIGHT_WALLS = True
  24. TORCH_RADIUS = 10
  25.  
  26.  
  27.  
  28. class Tile:
  29. #a tile of the map and its properties
  30. def __init__(self, blocked, block_sight = None):
  31. self.explored = False
  32. self.blocked = blocked
  33. self.field = 0
  34.  
  35. #by default, if a tile is blocked, it also blocks sight
  36. if block_sight is None: block_sight = blocked
  37. self.block_sight = block_sight
  38.  
  39. class Object:
  40. #this is a generic object: the player, a monster, an item, the stairs...
  41. #it's always represented by a character on screen.
  42. def __init__(self, x, y, char, name, color, blocks=False, fighter=None, ai=None):
  43. self.x = x
  44. self.y = y
  45. self.char = char
  46. self.name = name
  47. self.color = color
  48. self.blocks = blocks
  49.  
  50. self.fighter = fighter
  51. if self.fighter: #let the fighter component know who owns it
  52. self.fighter.owner = self
  53.  
  54. self.ai = ai
  55. if self.ai: #let the AI component know who owns it
  56. self.ai.owner = self
  57.  
  58. def move(self, dx, dy):
  59. #move by the given amount, if the destination is not blocked
  60. if not is_blocked(self.x + dx, self.y + dy):
  61. self.x += dx
  62. self.y += dy
  63.  
  64. def move_towards(self, target_x, target_y):
  65. #vector from this object to the target, and distance
  66. dx = target_x - self.x
  67. dy = target_y - self.y
  68. distance = math.sqrt(dx ** 2 + dy ** 2)
  69.  
  70. #normalize it to length 1 (preserving direction), then round it and
  71. #convert to integer so the movement is restricted to the map grid
  72. dx = int(round(dx / distance))
  73. dy = int(round(dy / distance))
  74. self.move(dx, dy)
  75. print "hi"
  76.  
  77. def distance_to(self, other):
  78. #return the distance to another object
  79. dx = other.x - self.x
  80. dy = other.y - self.y
  81. return math.sqrt(dx ** 2 + dy ** 2)
  82.  
  83. def draw(self):
  84. #only show if it's visible to the player
  85. if libtcod.map_is_in_fov(fov_map, self.x, self.y):
  86. #set the color and then draw the character that represents this object at its position
  87. libtcod.console_set_default_foreground(con, self.color)
  88. libtcod.console_put_char(con, self.x, self.y, self.char, libtcod.BKGND_NONE)
  89.  
  90. def clear(self):
  91. #erase the character that represents this object
  92. libtcod.console_put_char(con, self.x, self.y, ' ', libtcod.BKGND_NONE)
  93.  
  94. class Fighter:
  95. #combat-related properties and methods (monster, player, NPC).
  96. def __init__(self, hp, defense, power, death_function=None):
  97. self.max_hp = hp
  98. self.hp = hp
  99. self.defense = defense
  100. self.power = power
  101. self.death_function = death_function
  102.  
  103. def attack(self, target):
  104. #a simple formula for attack damage
  105. damage = self.power - target.fighter.defense
  106.  
  107. if damage > 0:
  108. #make the target take some damage
  109. print self.owner.name.capitalize() + ' attacks ' + target.name + ' for ' + str(damage) + ' hit points.'
  110. target.fighter.take_damage(damage)
  111. else:
  112. print self.owner.name.capitalize() + ' attacks ' + target.name + ' but it has no effect!'
  113.  
  114. def take_damage(self, damage):
  115. #apply damage if possible
  116. if damage > 0:
  117. self.hp -= damage
  118.  
  119. #check for death. if there's a death function, call it
  120. if self.hp <= 0:
  121. function = self.death_function
  122. if function is not None:
  123. function(self.owner)
  124.  
  125. class BasicMonster:
  126. #AI for a basic monster.
  127. def take_turn(self):
  128. #a basic monster takes its turn. if you can see it, it can see you
  129. monster = self.owner
  130. if libtcod.map_is_in_fov(fov_map, monster.x, monster.y):
  131.  
  132. #move towards player if far away
  133. if monster.distance_to(player) >= 2:
  134. monster.move_towards(player.x, player.y)
  135.  
  136. #close enough, attack! (if the player is still alive.)
  137. elif player.fighter.hp > 0:
  138. monster.fighter.attack(player)
  139.  
  140. def is_blocked(x, y):
  141. #first test the map tile
  142. if map[x][y].blocked:
  143. return True
  144.  
  145. #now check for any blocking objects
  146. for object in objects:
  147. if object.blocks and object.x == x and object.y == y:
  148. return True
  149. return False
  150.  
  151. def load_font():
  152. a = 0
  153. for x in range(0,16):
  154. libtcod.console_map_ascii_codes_to_font(a, 16, 0, x)
  155. a+=16
  156.  
  157. def make_customgenericmap(room_number = 0):
  158. global map, objects
  159. if room_number == 0 or room_number == 57:
  160. smap = maps.portal
  161. elif room_number == 64:
  162. smap = maps.portal2
  163.  
  164. objects = [player]
  165.  
  166. MAP_HEIGHT1 = len(smap)
  167. MAP_WIDTH1 = len(smap[0])
  168. map = [[Tile(True) for y in range(MAP_HEIGHT1)] for x in range(MAP_WIDTH1)]
  169.  
  170. for y in range(MAP_HEIGHT1):
  171. for x in range(MAP_WIDTH1):
  172. if smap[y][x] != '#': #black background
  173. map[x][y] = Tile(False)
  174. if smap[y][x] == 'x': #player spawns here
  175. player.x = x
  176. player.y = y
  177. if smap[y][x] == 'w': # walls
  178. map[x][y].field = 1
  179. if smap[y][x] == 'u':
  180. map[x][y].field = 2
  181. if smap[y][x] == 'a':
  182. map[x][y].field = 3 #warp
  183. warp = Object(x, y, 254, 'warp', libtcod.white, blocks=True)
  184. objects.append(warp)
  185. if smap[y][x] == 'o': #Orc
  186.  
  187. fighter_component = Fighter(hp=10, defense=0, power=3)
  188. ai_component = BasicMonster()
  189.  
  190. monster = Object(x, y, 254, 'orc', libtcod.white, blocks=True, fighter=fighter_component, ai=ai_component)
  191.  
  192. objects.append(monster)
  193.  
  194. def render_all():
  195. global fov_map, color_dark_wall, color_light_wall
  196. global color_dark_ground, color_light_ground
  197. global fov_recompute
  198.  
  199. if fov_recompute:
  200. #recompute FOV if needed (the player moved or something)
  201. fov_recompute = False
  202. libtcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO)
  203.  
  204. #go through all tiles, and set their background color according to the FOV
  205. for y in range(MAP_HEIGHT):
  206. for x in range(MAP_WIDTH):
  207. visible = libtcod.map_is_in_fov(fov_map, x, y)
  208. wall = map[x][y].block_sight
  209. if not visible:
  210. #if it's not visible right now, the player can only see it if it's explored
  211. if map[x][y].explored:
  212. if wall:
  213. libtcod.console_set_char_background(con, x, y, color_dark_wall, libtcod.BKGND_SET)
  214. else:
  215. libtcod.console_set_char_background(con, x, y, color_dark_ground, libtcod.BKGND_SET)
  216. else:
  217. #it's visible
  218. if wall:
  219. libtcod.console_set_char_background(con, x, y, color_light_wall, libtcod.BKGND_SET )
  220. else:
  221. libtcod.console_set_char_background(con, x, y, color_light_ground, libtcod.BKGND_SET )
  222. #since it's visible, explore it
  223. map[x][y].explored = True
  224.  
  225.  
  226.  
  227. # if wall:
  228. # libtcod.console_set_char_background(con, x, y, libtcod.black, libtcod.BKGND_SET )
  229. #elif map[x][y].field == 1: #walls
  230. # libtcod.console_put_char(con, x, y, 253, libtcod.BKGND_NONE)
  231. #elif map[x][y].field == 2:
  232. # libtcod.console_put_char(con, x, y, 255)
  233. #elif map[x][y].field == 3:
  234. # libtcod.console_put_char(con, x, y, 254)
  235. #elif map[x][y].field == 4:
  236. #libtcod.console_put_char(con, x, y, "o")
  237. #else:
  238. # libtcod.console_set_char_background(con, x, y, libtcod.black, libtcod.BKGND_SET )
  239.  
  240.  
  241.  
  242. #draw all objects in the list
  243. for object in objects:
  244. object.draw()
  245.  
  246. #blit the contents of "con" to the root console
  247. libtcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0)
  248.  
  249. #show the player's stats
  250. libtcod.console_set_default_foreground(con, libtcod.white)
  251. libtcod.console_print_ex(con, 1, SCREEN_HEIGHT - 2, libtcod.BKGND_NONE, libtcod.LEFT,
  252. 'HP: ' + str(player.fighter.hp) + '/' + str(player.fighter.max_hp))
  253.  
  254. def player_move_or_attack(dx, dy):
  255. global fov_recompute
  256.  
  257. #the coordinates the player is moving to/attacking
  258. x = player.x + dx
  259. y = player.y + dy
  260.  
  261. #try to find an attackable object there
  262. target = None
  263. for object in objects:
  264. if object.fighter and object.x == x and object.y == y:
  265. target = object
  266. break
  267.  
  268. #attack if target found, move otherwise
  269. if target is not None:
  270. player.fighter.attack(target)
  271. else:
  272. player.move(dx, dy)
  273. fov_recompute = True
  274.  
  275. def handle_keys():
  276. #key = libtcod.console_check_for_keypress() #real-time
  277. key = libtcod.console_wait_for_keypress(True) #turn-based
  278.  
  279. if key.vk == libtcod.KEY_ENTER and key.lalt:
  280. #Alt+Enter: toggle fullscreen
  281. libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())
  282.  
  283. elif key.vk == libtcod.KEY_ESCAPE:
  284. return 'exit' #exit game
  285.  
  286. if game_state == 'playing':
  287. #movement keys
  288. if libtcod.console_is_key_pressed(libtcod.KEY_UP):
  289. player_move_or_attack(0, -1)
  290.  
  291. elif libtcod.console_is_key_pressed(libtcod.KEY_DOWN):
  292. player_move_or_attack(0, 1)
  293.  
  294. elif libtcod.console_is_key_pressed(libtcod.KEY_LEFT):
  295. player_move_or_attack(-1, 0)
  296.  
  297. elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT):
  298. player_move_or_attack(1, 0)
  299. else:
  300. return 'didnt-take-turn'
  301.  
  302. #if libtcod.console_is_key_pressed(libtcod.KEY_ENTER):
  303. #Enter warp, if player is on it
  304. #if warp.x == player.x and warp.y == player.y:
  305. #make_customgenericmap(warp_calc)
  306.  
  307.  
  308.  
  309.  
  310. #############################################
  311. # Initialization & Main Loop
  312. #############################################
  313.  
  314. #libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
  315. libtcod.console_set_custom_font("term8x82.png", libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_ASCII_INROW, 16, 16)
  316. libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'Gargoyle', False)
  317. libtcod.sys_set_fps(LIMIT_FPS)
  318. con = libtcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
  319.  
  320. #Player Classes
  321. fighter_component = Fighter(hp=30, defense=2, power=5)
  322.  
  323. #create object representing the player
  324. player = Object( 0, 0, 255, 'player', libtcod.white, blocks=True, fighter=fighter_component, ai=None)
  325.  
  326. #the objects list
  327. objects = []
  328.  
  329. #generate map (at this point it's not drawn to the screen)
  330. #make_map()
  331. make_customgenericmap()
  332.  
  333. #FoV map
  334. fov_map = libtcod.map_new(MAP_WIDTH, MAP_HEIGHT)
  335. for y in range(MAP_HEIGHT):
  336. for x in range(MAP_WIDTH):
  337. libtcod.map_set_properties(fov_map, x, y, not map[x][y].block_sight, not map[x][y].blocked)
  338.  
  339. #Game states
  340. fov_recompute = True
  341. game_state = 'playing'
  342. player_action = None
  343.  
  344. while not libtcod.console_is_window_closed():
  345.  
  346. #render the screen
  347. render_all()
  348.  
  349. libtcod.console_flush()
  350.  
  351. #erase all objects at their old locations, before they move
  352. for object in objects:
  353. object.clear()
  354.  
  355. #handle keys and exit game if needed
  356. exit = handle_keys()
  357. if player_action == 'exit':
  358. break
  359.  
  360. #let monsters take their turn
  361. if game_state == 'playing' and player_action != 'didnt-take-turn':
  362. for object in objects:
  363. if object.ai:
  364. object.ai.take_turn()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement