Legend of the Gold Box... A game written for the LOWREZJAM 2018 game jam
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

766 lines
29KB

  1. from . import gbe
  2. import pygame
  3. class NodeOptions(gbe.nodes.Node2D):
  4. def __init__(self, name="Options", parent=None):
  5. try:
  6. gbe.nodes.Node2D.__init__(self, name, parent)
  7. except gbe.nodes.NodeError as e:
  8. raise e
  9. self._options = []
  10. self._oindex = 0
  11. self._color_select = (255,255,0)
  12. self._color_idle = (255,255,255)
  13. def add_option(self, font_src, size, text, event, params={}):
  14. nodeName = "OpText{}".format(len(self._options))
  15. nodeOption = gbe.nodes.NodeText(nodeName, self)
  16. nodeOption.font_src = font_src
  17. nodeOption.size = size
  18. nodeOption.text = text
  19. nodeOption.antialias = False
  20. if len(self._options) == 0:
  21. nodeOption.set_color(*self._color_select)
  22. else:
  23. nodeOption.set_color(*self._color_idle)
  24. li = len(self._options)-1
  25. lp = self._options[li][0].position
  26. ls = self._options[li][0].size
  27. nodeOption.position = (lp[0], lp[1] + ls + 1)
  28. self._options.append([nodeOption, event, params])
  29. def on_start(self):
  30. self.listen("KEYPRESSED", self.on_keypressed)
  31. def on_pause(self):
  32. self.unlisten("KEYPRESSED", self.on_keypressed)
  33. def on_keypressed(self, event, params):
  34. if params["key_name"] == "w":
  35. if self._oindex > 0:
  36. self._options[self._oindex][0].set_color(*self._color_idle)
  37. self._oindex -= 1
  38. self._options[self._oindex][0].set_color(*self._color_select)
  39. elif params["key_name"] == "s":
  40. if self._oindex < len(self._options) - 1:
  41. self._options[self._oindex][0].set_color(*self._color_idle)
  42. self._oindex += 1
  43. self._options[self._oindex][0].set_color(*self._color_select)
  44. elif params["key_name"] in ["enter", "return"]:
  45. if len(self._options) > 0:
  46. op = self._options[self._oindex]
  47. self.emit(op[1], op[2])
  48. elif params["key_name"] == "escape":
  49. self.emit("QUIT")
  50. class NodeGameMap(gbe.nodes.Node2D):
  51. def __init__(self, name="GameMap", parent=None):
  52. try:
  53. gbe.nodes.Node2D.__init__(self, name, parent)
  54. except gbe.nodes.NodeError as e:
  55. raise e
  56. self._renderMode = 0 # 0 = Top-down | 1 = Perspective
  57. self._layer = {}
  58. self._currentLayer = ""
  59. self._res = {
  60. "env_src":"",
  61. "env":None,
  62. "h_index":0,
  63. "g_index":0,
  64. "wall_src":"",
  65. "walls":None,
  66. "wall_index":-1,
  67. "door_index":-1
  68. }
  69. self._topdown = {
  70. "size":8, # Pixels square
  71. "wall_color":pygame.Color(255, 255, 255),
  72. "blocked_color":pygame.Color(255, 0, 0)
  73. }
  74. self._cellpos = [0,0]
  75. self._orientation = "n"
  76. @property
  77. def environment_source(self):
  78. return self._res["env_src"]
  79. @property
  80. def wall_source(self):
  81. return self._res["wall_src"]
  82. @property
  83. def layer_count(self):
  84. return len(self._layer)
  85. @property
  86. def current_layer(self):
  87. return self._currentLayer
  88. @property
  89. def current_layer_width(self):
  90. if self._currentLayer != "":
  91. return self._layer[self._currentLayer]["w"]
  92. return 0
  93. @property
  94. def current_layer_height(self):
  95. if self._currentLayer != "":
  96. return self._layer[self._currentLayer]["h"]
  97. return 0
  98. @property
  99. def layer_names(self):
  100. names = []
  101. for key in self._layer:
  102. names.append(names)
  103. return names
  104. @property
  105. def orientation(self):
  106. return self._orientation
  107. @property
  108. def cell_position(self):
  109. return (self._cellpos[0], self._cellpos[1])
  110. def set_resources(self, env_src, wall_src):
  111. res = self.resource
  112. if env_src != "" and env_src != self._res["env_src"]:
  113. if res.is_valid("json", env_src):
  114. if not res.has("json", env_src):
  115. res.store("json", env_src)
  116. e = res.get("json", env_src)
  117. if e is not None and e() is not None:
  118. self._res["env_src"] = env_src
  119. self._res["env"] = e
  120. # NOTE: Making a lot of assumptions to the structural validity of the data file.
  121. isrc1 = e().data["horizon"]["src"]
  122. isrc2 = e().data["ground"]["src"]
  123. if res.is_valid("graphic", isrc1) and res.is_valid("graphic", isrc2):
  124. if not res.has("graphic", isrc1):
  125. res.store("graphic", isrc1)
  126. if not res.has("graphic", isrc2):
  127. res.store("graphic", isrc2)
  128. if wall_src != "" and wall_src != self._res["wall_src"]:
  129. if res.is_valid("json", wall_src):
  130. if not res.has("json", wall_src):
  131. print("Storing resource {}".format(wall_src))
  132. res.store("json", wall_src)
  133. w = res.get("json", wall_src)
  134. if w is not None and w() is not None:
  135. self._res["wall_src"] = wall_src
  136. self._res["walls"] = w
  137. # NOTE: I'm making a lot of assumptions to the structural validity of the data file, but...
  138. imgsrc = w().data["src"]
  139. if res.is_valid("graphic", imgsrc):
  140. if not res.has("graphic", imgsrc):
  141. res.store("graphic", imgsrc)
  142. else:
  143. print("Failed to get JSON instance {}".format(wall_src))
  144. else:
  145. print("Invalid JSON {}".format(wall_src))
  146. def add_layer(self, name, w, h):
  147. if name == "" or name in self._layer:
  148. return
  149. self._layer[name] = {
  150. "w":w,
  151. "h":h,
  152. "cells":[]
  153. }
  154. for c in range(0, w*h):
  155. self._layer[name]["cells"].append({
  156. "h":0, # Horizon
  157. "g":0, # Ground
  158. "n":[-1, False, -1, None], # North Wall | [<graphic index, -1 = None>, <blocking>, <door index, -1 = None, 0 = closed, 1=open>, <door target>]
  159. "s":[-1, False, -1, None], # South Wall
  160. "e":[-1, False, -1, None], # East Wall
  161. "w":[-1, False, -1, None], # West Wall
  162. })
  163. if self._currentLayer == "":
  164. self._currentLayer = name
  165. def set_active_layer(self, name, x=0, y=0):
  166. if name == "" or not (name in self._layers):
  167. return
  168. layer = self._layers[name]
  169. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  170. self._currentLayer = name
  171. self._cellpos = [x,y]
  172. def set_cell_env(self, x, y, ceiling=-1, ground=-1):
  173. if self._currentLayer == "":
  174. return
  175. layer = self._layer[self._currentLayer]
  176. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  177. index = (y * layer["w"]) + x
  178. cell = layer["cells"]
  179. if ceiling >= 0:
  180. cell[index]["c"] = ceiling
  181. if ground >= 0:
  182. cell[index]["g"] = ground
  183. def fill_cell_env(self, x1, y1, x2, y2, ceiling=-1, ground=-1):
  184. if self._currentLayer == "":
  185. return
  186. for y in range(y1, y2+1):
  187. for x in range(x1, x2+1):
  188. self.set_cell_env(x, y, ceiling, ground)
  189. def set_cell_face(self, x, y, face, gi=-2, blocking=None):
  190. if self._currentLayer == "" or not (face == "n" or face == "s" or face == "w" or face == "e"):
  191. return
  192. layer = self._layer[self._currentLayer]
  193. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  194. index = (y * layer["w"]) + x
  195. cell = layer["cells"]
  196. if gi <= -2:
  197. gi = self._res["wall_index"]
  198. if gi >= -1:
  199. cell[index][face][0] = gi
  200. if blocking is not None:
  201. cell[index][face][1] = (blocking == True)
  202. else:
  203. if gi == -1: # If gi = -1, there is no wall, so, by default, there is no blocking.
  204. cell[index][face][1] = False
  205. else: # Otherwise, blocking is assumed :)
  206. cell[index][face][1] = True
  207. elif blocking is not None:
  208. blocking = (blocking == True) # Forcing a boolean
  209. cell[index][face][1] = blocking
  210. def next_wall(self):
  211. if self._res["walls"] is not None:
  212. w = self._res["walls"]()
  213. if w is not None:
  214. windex = self._res["wall_index"] + 1
  215. if windex >= len(w.data["walls"]):
  216. windex = -1
  217. self._res["wall_index"] = windex
  218. print("Next Wall Index: {}".format(windex))
  219. def prev_wall(self):
  220. if self._res["walls"] is not None:
  221. w = self._res["walls"]()
  222. if w is not None:
  223. windex = self._res["wall_index"] - 1
  224. if windex < -1:
  225. windex = len(w.data["walls"]) - 1
  226. self._res["wall_index"] = windex
  227. print("Prev Wall Index: {}".format(windex))
  228. def turn_left(self):
  229. onum = self._d_s2n(self._orientation)
  230. onum -= 1
  231. if onum < 0:
  232. onum = 3
  233. self._orientation = self._d_n2s(onum)
  234. def turn_right(self):
  235. onum = self._d_s2n(self._orientation)
  236. onum += 1
  237. if onum > 3:
  238. onum = 0
  239. self._orientation = self._d_n2s(onum)
  240. def move_to(self, x, y):
  241. if x >= 0 and x < self.current_layer_width and y >= 0 and y < self.current_layer_height:
  242. self._cellpos = [x, y]
  243. def move_forward(self, ignore_passible=False):
  244. if ignore_passible or self.is_passible(self._cellpos[0], self._cellpos[1], self._orientation):
  245. x = self._cellpos[0]
  246. y = self._cellpos[1]
  247. if self._orientation == "n":
  248. y -= 1
  249. elif self._orientation == "e":
  250. x += 1
  251. elif self._orientation == "s":
  252. y += 1
  253. elif self._orientation == "w":
  254. x -= 1
  255. self.move_to(x, y)
  256. def move_backward(self, ignore_passible=False):
  257. orient = self._orientation
  258. if self._orientation == "n":
  259. self._orientation = "s"
  260. elif self._orientation == "s":
  261. self._orientation = "n"
  262. elif self._orientation == "e":
  263. self._orientation = "w"
  264. elif self._orientation == "w":
  265. self._orientation = "e"
  266. self.move_forward(ignore_passible)
  267. self._orientation = orient
  268. def is_passible(self, x, y, d):
  269. """
  270. Returns true if it's possible to move forward from the x, y map position in the direction given.
  271. d - 0 = North, 1 = East, 2 = South, 3 = West
  272. """
  273. if self._currentLayer == "" or d < 0 or d >= 4:
  274. return False
  275. layer = self._layer[self._currentLayer]
  276. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  277. index = (y * layer["w"]) + x
  278. d = self._d_n2s(d)
  279. return not layer["cells"][index][d][1]
  280. return False
  281. def toggle_render_mode(self):
  282. if self._renderMode == 0:
  283. self._renderMode = 1
  284. else:
  285. self._renderMode = 0
  286. def set_render_mode(self, mode):
  287. if mode <= 0:
  288. self._renderMode = 0
  289. else:
  290. self._renderMode = 1
  291. def get_render_mode(self):
  292. return self._renderMode
  293. def _d_n2s(self, d): # _(d)irection_(n)umber_to_(s)tring
  294. if d == 0:
  295. return "n"
  296. elif d == 1:
  297. return "e"
  298. elif d == 2:
  299. return "s"
  300. elif d == 3:
  301. return "w"
  302. return ""
  303. def _d_s2n(self, d):
  304. if d == "n":
  305. return 0
  306. elif d == "e":
  307. return 1
  308. elif d == "s":
  309. return 2
  310. elif d == "w":
  311. return 3
  312. return -1
  313. def _indexFromPos(self, x, y):
  314. if x >= 0 and x < self.current_layer_width and y >= 0 and y < self.current_layer_height:
  315. return (y * self.current_layer_width) + x
  316. return -1
  317. def _getCell(self, x, y):
  318. if x >=- 0 and x < self.current_layer_width and y >= 0 and y < self.current_layer_height:
  319. index = self._indexFromPos(x, y)
  320. return self._layer[self._currentLayer]["cells"][index]
  321. return None
  322. def _getOrientVec(self):
  323. if self._orientation == "n":
  324. return (0, -1)
  325. elif self._orientation == "s":
  326. return (0, 1)
  327. elif self._orientation == "e":
  328. return (1, 0)
  329. elif self._orientation == "w":
  330. return (-1, 0)
  331. return (0,0)
  332. def _RenderTopDown(self):
  333. cell_size = self._topdown["size"]
  334. size = self.resolution
  335. pos = self._cellpos
  336. lsize = (self.current_layer_width, self.current_layer_height)
  337. hcells = int(size[0] / cell_size)
  338. vcells = int(size[1] / cell_size)
  339. cx = pos[0] - int(hcells * 0.5)
  340. cy = pos[1] - int(vcells * 0.5)
  341. ry = -int(cell_size*0.5)
  342. for j in range(0, vcells+1):
  343. y = cy + j
  344. if y >= 0 and y < lsize[1]:
  345. rx = -int(cell_size*0.5)
  346. for i in range(0, hcells+1):
  347. x = cx + i
  348. if x >= 0 and x < lsize[0]:
  349. cell = self._getCell(x, y)
  350. if cell["n"][0] >= 0:
  351. self.draw_rect((rx, ry, cell_size, 2), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  352. if cell["e"][0] >= 0:
  353. self.draw_rect((rx+(cell_size-2), ry, 2, cell_size), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  354. if cell["s"][0] >= 0:
  355. self.draw_rect((rx, ry+(cell_size-2), cell_size, 2), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  356. if cell["w"][0] >= 0:
  357. self.draw_rect((rx, ry, 2, cell_size), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  358. if cell["n"][1] == True:
  359. self.draw_lines([(rx+1, ry+1), (rx+(cell_size-2), ry+1)], self._topdown["blocked_color"], 1)
  360. if cell["e"][1] == True:
  361. self.draw_lines([(rx+(cell_size-2), ry+1), (rx+(cell_size-2), ry+(cell_size-2))], self._topdown["blocked_color"], 1)
  362. if cell["s"][1] == True:
  363. self.draw_lines([(rx+1, ry+(cell_size-2)), (rx+(cell_size-2), ry+(cell_size-2))], self._topdown["blocked_color"], 1)
  364. if cell["w"][1] == True:
  365. self.draw_lines([(rx+1, ry+1), (rx+1, ry+(cell_size-2))], self._topdown["blocked_color"], 1)
  366. rx += cell_size
  367. ry += cell_size
  368. def _RenderPersFar(self, pos, size, o, orr, orl, wdat, wsurf):
  369. ovec = self._getOrientVec()
  370. fx = pos[0] + (ovec[0]*2)
  371. fy = pos[1] + (ovec[1]*2)
  372. fcell = self._getCell(fx, fy)
  373. if fcell == None:
  374. return # If we can't see the cell directly ahead, the other's won't be visible either!
  375. lcell = llcell = rcell = rrcell = None
  376. if ovec[0] == 0: # Facing North/South
  377. lcell = self._getCell(fx + ovec[1], fy)
  378. llcell = self._getCell(fx + (ovec[1]*2), fy)
  379. rcell = self._getCell(fx - ovec[1], fy)
  380. rrcell = self._getCell(fx - (ovec[1]*2), fy)
  381. else: # Facing East/West
  382. lcell = self._getCell(fx, fy - ovec[0])
  383. llcell = self._getCell(fx, fy - (ovec[0]*2))
  384. rcell = self._getCell(fx, fy + ovec[0])
  385. rrcell = self._getCell(fx, fy + (ovec[0]*2))
  386. hsw = int(size[0]*0.5)
  387. hsh = int(size[1]*0.5)
  388. # Rendering from edges to center
  389. if llcell is not None:
  390. if llcell[o][0] >= 0:
  391. rect = wdat["walls"][llcell[o][0]]["f_far"]
  392. hw = int(rect[2]*0.5)
  393. hh = int(rect[3]*0.5)
  394. self.draw_image(wsurf, (0, hsh-hh), (rect[0], rect[1], hw, rect[3]))
  395. if rrcell is not None:
  396. if rrcell[o][0] >= 0:
  397. rect = wdat["walls"][rrcell[o][0]]["f_far"]
  398. hw = int(rect[2]*0.5)
  399. hh = int(rect[3]*0.5)
  400. self.draw_image(wsurf, (size[0]-hw, hsh-hh), (rect[0]+hw, rect[1], hw, rect[3]))
  401. if lcell is not None:
  402. if lcell[o][0] >= 0:
  403. rect = wdat["walls"][lcell[o][0]]["f_far"]
  404. hw = int(rect[2]*0.5)
  405. hh = int(rect[3]*0.5)
  406. self.draw_image(wsurf, (hw, hsh-hh), (rect[0], rect[1], rect[2], rect[3]))
  407. if lcell[orl][0] >= 0:
  408. rect = wdat["walls"][lcell[orl][0]]["s_far"]
  409. lsurf = pygame.transform.flip(wsurf.subsurface(rect), True, False)
  410. hh = int(rect[3]*0.5)
  411. self.draw_image(lsurf, (0, hsh-hh))
  412. if rcell is not None:
  413. if rcell[o][0] >= 0:
  414. rect = wdat["walls"][rcell[o][0]]["f_far"]
  415. hw = int(rect[2]*0.5)
  416. hh = int(rect[3]*0.5)
  417. self.draw_image(wsurf, (size[0]-(rect[2]+hw), hsh-hh), (rect[0], rect[1], rect[2], rect[3]))
  418. if rcell[orr][0] >= 0:
  419. rect = wdat["walls"][rcell[orr][0]]["s_far"]
  420. hh = int(rect[3]*0.5)
  421. self.draw_image(wsurf, (size[0]-rect[2], hsh-hh), (rect[0], rect[1], rect[2], rect[3]))
  422. # Rendering the main cell!!
  423. frect = None # This will be used to place walls
  424. if fcell[o][0] >= 0:
  425. frect = wdat["walls"][fcell[o][0]]["f_far"]
  426. hw = int(frect[2]*0.5)
  427. hh = int(frect[3]*0.5)
  428. self.draw_image(wsurf, (hsw-hw, hsh-hh), (frect[0], frect[1], frect[2], frect[3]))
  429. if fcell[orl][0] >= 0:
  430. rect = wdat["walls"][fcell[orl][0]]["s_far"]
  431. if frect is None:
  432. # Kinda cheating in that it's known that all walls are the same size.
  433. frect = wdat["walls"][fcell[orl][0]]["f_far"]
  434. hw = int(frect[2]*0.5)
  435. lsurf = pygame.transform.flip(wsurf.subsurface(rect), True, False)
  436. self.draw_image(lsurf, (hsw-(hw+rect[2]), hsh-int(rect[3]*0.5)))
  437. if fcell[orr][0] >= 0:
  438. rect = wdat["walls"][fcell[orr][0]]["s_far"]
  439. if frect is None:
  440. frect = wdat["walls"][fcell[orr][0]]["f_far"]
  441. hw = int(frect[2]*0.5)
  442. self.draw_image(wsurf, (hsw+hw, hsh-int(rect[3]*0.5)), (rect[0], rect[1], rect[2], rect[3]))
  443. def _RenderPersMid(self, pos, size, o, orr, orl, wdat, wsurf):
  444. ovec = self._getOrientVec()
  445. fx = pos[0] + ovec[0]
  446. fy = pos[1] + ovec[1]
  447. fcell = self._getCell(fx, fy)
  448. if fcell == None:
  449. return # If we can't see the cell directly ahead, the other's won't be visible either!
  450. lcell = rcell = None
  451. if ovec[0] == 0: # Facing North/South
  452. lcell = self._getCell(fx + ovec[1], fy)
  453. rcell = self._getCell(fx - ovec[1], fy)
  454. else: # Facing East/West
  455. lcell = self._getCell(fx, fy - ovec[0])
  456. rcell = self._getCell(fx, fy + ovec[0])
  457. hsw = int(size[0]*0.5)
  458. hsh = int(size[1]*0.5)
  459. # Render from outside inwards!
  460. if lcell is not None:
  461. if lcell[o][0] >= 0:
  462. rect = wdat["walls"][lcell[o][0]]["f_mid"]
  463. hw = int(rect[2]*0.5)
  464. hh = int(rect[3]*0.5)
  465. self.draw_image(wsurf, (0, hsh-hh), (rect[0]+hw, rect[1], int(rect[2]*0.5), rect[3]))
  466. if rcell is not None:
  467. if rcell[o][0] >= 0:
  468. rect = wdat["walls"][rcell[o][0]]["f_mid"]
  469. hw = int(rect[2]*0.5)
  470. hh = int(rect[3]*0.5)
  471. self.draw_image(wsurf, (size[0]-hw, hsh-hh), (rect[0], rect[1], hw, rect[3]))
  472. # Rendering the main cell!!
  473. frect = None # This will be used to place walls
  474. if fcell[o][0] >= 0:
  475. frect = wdat["walls"][fcell[o][0]]["f_mid"]
  476. hw = int(frect[2]*0.5)
  477. hh = int(frect[3]*0.5)
  478. self.draw_image(wsurf, (hsw-hw, hsh-hh), (frect[0], frect[1], frect[2], frect[3]))
  479. if fcell[orl][0] >= 0:
  480. rect = wdat["walls"][fcell[orl][0]]["s_mid"]
  481. if frect is None:
  482. # Kinda cheating in that it's known that all walls are the same size.
  483. frect = wdat["walls"][fcell[orl][0]]["f_mid"]
  484. hw = int(frect[2]*0.5)
  485. lsurf = pygame.transform.flip(wsurf.subsurface(rect), True, False)
  486. self.draw_image(lsurf, (hsw-(hw+rect[2]), hsh-int(rect[3]*0.5)))
  487. if fcell[orr][0] >= 0:
  488. rect = wdat["walls"][fcell[orr][0]]["s_mid"]
  489. if frect is None:
  490. frect = wdat["walls"][fcell[orr][0]]["f_mid"]
  491. hw = int(frect[2]*0.5)
  492. self.draw_image(wsurf, (hsw+hw, hsh-int(rect[3]*0.5)), (rect[0], rect[1], rect[2], rect[3]))
  493. def _RenderPersClose(self, pos, size, o, orr, orl, cell, wdat, wsurf):
  494. fcell = self._getCell(pos[0], pos[1])
  495. hsw = int(size[0]*0.5)
  496. hsh = int(size[1]*0.5)
  497. ovec = self._getOrientVec()
  498. lcell = rcell = None
  499. if ovec[0] == 0: # Facing North/South
  500. lcell = self._getCell(pos[0] + ovec[1], pos[1])
  501. rcell = self._getCell(pos[0] - ovec[1], pos[1])
  502. else: # Facing East/West
  503. lcell = self._getCell(pos[0], pos[1] - ovec[0])
  504. rcell = self._getCell(pos[0], pos[1] + ovec[0])
  505. hsw = int(size[0]*0.5)
  506. hsh = int(size[1]*0.5)
  507. # Render from outside inwards!
  508. if lcell is not None:
  509. if lcell[o][0] >= 0:
  510. rect = wdat["walls"][lcell[o][0]]["f_close"]
  511. hw = int(rect[2]*0.5)
  512. hh = int(rect[3]*0.5)
  513. rw = hsw - hw
  514. self.draw_image(wsurf, (0, hsh-hh), (rect[0]+(rect[2]-rw), rect[1], rw, rect[3]))
  515. if rcell is not None:
  516. if rcell[o][0] >= 0:
  517. rect = wdat["walls"][rcell[o][0]]["f_close"]
  518. hw = int(rect[2]*0.5)
  519. hh = int(rect[3]*0.5)
  520. rw = hsw - hw
  521. self.draw_image(wsurf, (size[0]-rw, hsh-hh), (rect[0], rect[1], rw, rect[3]))
  522. # Rendering the main cell!!
  523. frect = None # This will be used to place walls
  524. if fcell[o][0] >= 0:
  525. idx = fcell[o][0]
  526. frect = wdat["walls"][idx]["f_close"]
  527. hw = int(frect[2]*0.5)
  528. hh = int(frect[3]*0.5)
  529. self.draw_image(wsurf, (hsw-hw, hsh-hh), (frect[0], frect[1], frect[2], frect[3]))
  530. if fcell[orl][0] >= 0:
  531. idx = fcell[orl][0]
  532. rect = wdat["walls"][idx]["s_close"]
  533. if frect is None:
  534. # Kinda cheating in that it's known that all walls are the same size.
  535. frect = wdat["walls"][idx]["f_close"]
  536. hw = int(frect[2]*0.5)
  537. lsurf = pygame.transform.flip(wsurf.subsurface(rect), True, False)
  538. self.draw_image(lsurf, (hsw-(hw+rect[2]), hsh-int(rect[3]*0.5)))
  539. if fcell[orr][0] >= 0:
  540. idx = fcell[orr][0]
  541. rect = wdat["walls"][idx]["s_close"]
  542. if frect is None:
  543. frect = wdat["walls"][idx]["f_close"]
  544. hw = int(frect[2]*0.5)
  545. self.draw_image(wsurf, (hsw+hw, hsh-int(rect[3]*0.5)), (rect[0], rect[1], rect[2], rect[3]))
  546. def _RenderPerspective(self):
  547. # Getting ALL of the core resources
  548. rm = self.resource
  549. edat = self._res["env"]
  550. wdat = self._res["walls"]
  551. if edat is None or wdat is None or edat() is None or wdat() is None:
  552. return
  553. edat = edat().data
  554. wdat = wdat().data
  555. ehsurf = rm.get("graphic", edat["horizon"]["src"])
  556. egsurf = rm.get("graphic", edat["ground"]["src"])
  557. wsurf = rm.get("graphic", wdat["src"])
  558. if ehsurf is None or egsurf is None or wsurf is None:
  559. return
  560. if ehsurf() is None or egsurf() is None or wsurf() is None:
  561. return
  562. oshift = lambda d: d if d >= 0 and d < 4 else (0 if d > 3 else 3)
  563. px = self._cellpos[0]
  564. py = self._cellpos[1]
  565. orl = self._d_n2s(oshift(self._d_s2n(self._orientation) - 1))
  566. orr = self._d_n2s(oshift(self._d_s2n(self._orientation) + 1))
  567. cell = self._getCell(px, py)
  568. # First, output the ground and horizon
  569. # TODO Later, perhaps cut the horizon and ground to represent each possible cell instead of just the current one?
  570. self.draw_image(ehsurf(), (0,0), edat["horizon"]["defs"][cell["h"]]["rect"])
  571. self.draw_image(egsurf(), (0,32), edat["ground"]["defs"][cell["g"]]["rect"])
  572. # Rendering the rest
  573. size = self.resolution
  574. self._RenderPersFar((px, py), size, self._orientation, orr, orl, wdat, wsurf())
  575. self._RenderPersMid((px, py), size, self._orientation, orr, orl, wdat, wsurf())
  576. self._RenderPersClose((px, py), size, self._orientation, orr, orl, cell, wdat, wsurf())
  577. def on_render(self):
  578. if self._renderMode == 0:
  579. self._RenderTopDown()
  580. else:
  581. self._RenderPerspective()
  582. class NodeMapEditor(gbe.nodes.Node2D):
  583. def __init__(self, name="MapEditor", parent=None):
  584. try:
  585. gbe.nodes.Node2D.__init__(self, name, parent)
  586. except gbe.nodes.Node2D as e:
  587. raise e
  588. self._last_orientation = ""
  589. self._size = 0
  590. self._thickness = 1
  591. self._color = pygame.Color(255,255,255)
  592. self._points = None
  593. self.pointer_size = 4
  594. def _getPoints(self, size):
  595. p = self.parent
  596. o = p.orientation
  597. points = self._points[o]
  598. hw = int(size[0]*0.5)
  599. hh = int(size[1]*0.5)
  600. return (
  601. (points[0][0] + hw, points[0][1] + hh),
  602. (points[1][0] + hw, points[1][1] + hh),
  603. (points[2][0] + hw, points[2][1] + hh)
  604. )
  605. @property
  606. def pointer_size(self):
  607. return self._size
  608. @pointer_size.setter
  609. def pointer_size(self, size):
  610. if not isinstance(size, int):
  611. raise TypeError("Size expected to be an integer.")
  612. if size <= 0:
  613. raise ValueError("Size must be greater than zero.")
  614. if size != self._size:
  615. self._size = size
  616. # Now updating all of the pointer... ummm... points
  617. hs = max(1, int(size * 0.5))
  618. self._points = {
  619. "n": ((0,-hs),(hs,hs),(-hs,hs)),
  620. "s": ((0,hs),(hs,-hs),(-hs,-hs)),
  621. "e": ((-hs,hs),(hs,0),(-hs,-hs)),
  622. "w": ((hs,hs),(-hs,0),(hs,-hs))
  623. }
  624. def set_color(self, color):
  625. if isinstance(color, (tuple, list)):
  626. clen = len(color)
  627. if clen == 3 or clen == 4:
  628. iscolor = lambda v : isinstance(v, int) and v >= 0 and v < 256
  629. if iscolor(color[0]) and iscolor(color[1]) and iscolor(color[2]):
  630. if clen == 3:
  631. self._color = pygame.Color(color[0], color[1], color[2])
  632. elif clen == 4 and iscolor(color[3]):
  633. self._color = pygame.Color(color[0], color[1], color[2], color[3])
  634. def get_color(self):
  635. return (self._color.r, self._color.g, self._color.b, self._color.a)
  636. def on_start(self):
  637. self.listen("KEYPRESSED", self.on_keypressed)
  638. def on_pause(self):
  639. self.unlisten("KEYPRESSED", self.on_keypressed)
  640. def on_keypressed(self, event, data):
  641. p = self.parent
  642. if p is None or not isinstance(p, NodeGameMap):
  643. return
  644. if data["key_name"] == "escape":
  645. self.emit("SCENECHANGE", {"scene":"MAIN_MENU", "hold":False})
  646. #self.emit("QUIT")
  647. if data["key_name"] == "tab":
  648. p.toggle_render_mode()
  649. elif data["key_name"] == "w":
  650. p.move_forward(True)
  651. elif data["key_name"] == "s":
  652. p.move_backward(True)
  653. elif data["key_name"] == "a":
  654. p.turn_left()
  655. elif data["key_name"] == "d":
  656. p.turn_right()
  657. elif data["key_name"] == "space":
  658. o = p.orientation
  659. cpos = p.cell_position
  660. p.set_cell_face(cpos[0], cpos[1], o)
  661. elif data["key_name"] == "e":
  662. p.next_wall()
  663. elif data["key_name"] == "q":
  664. p.prev_wall()
  665. def on_render(self):
  666. size = self.resolution
  667. self.draw_lines(self._getPoints(size), self._color, self._thickness, True)