Legend of the Gold Box... A game written for the LOWREZJAM 2018 game jam
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

396 lines
14KB

  1. from . import gbe
  2. import pygame
  3. class NodeInterface(gbe.nodes.NodeSurface):
  4. def __init__(self, name="Interface", parent=None):
  5. try:
  6. gbe.nodes.NodeSurface.__init__(self, name, parent)
  7. except gbe.nodes.NodeError as e:
  8. raise e
  9. def on_render(self):
  10. size = self.resolution
  11. self.draw_rect((0, 0, size[0], 10), pygame.Color(255,0,0,128), 1)
  12. self.draw_circle((int(size[0]/2), int(size[1]/2)), 16, pygame.Color(255,0,0,255), 2, pygame.Color(0,255,0,255))
  13. class NodeGameMap(gbe.nodes.Node2D):
  14. def __init__(self, name="GameMap", parent=None):
  15. try:
  16. gbe.nodes.Node2D.__init__(self, name, parent)
  17. except gbe.nodes.NodeError as e:
  18. raise e
  19. self._renderMode = 0 # 0 = Top-down | 1 = Perspective
  20. self._layer = {}
  21. self._currentLayer = ""
  22. self._res = {
  23. "env_src":"",
  24. "env":None,
  25. "wall_src":"",
  26. "walls":None,
  27. "wall_index":-1,
  28. "door_index":-1
  29. }
  30. self._topdown = {
  31. "size":8, # Pixels square
  32. "wall_color":pygame.Color(255, 255, 255),
  33. "blocked_color":pygame.Color(255, 0, 0)
  34. }
  35. self._cellpos = [0,0]
  36. self._orientation = "n"
  37. @property
  38. def environment_source(self):
  39. return self._res["env_src"]
  40. @property
  41. def wall_source(self):
  42. return self._res["wall_src"]
  43. @property
  44. def layer_count(self):
  45. return len(self._layer)
  46. @property
  47. def current_layer(self):
  48. return self._currentLayer
  49. @property
  50. def current_layer_width(self):
  51. if self._currentLayer != "":
  52. return self._layer[self._currentLayer]["w"]
  53. return 0
  54. @property
  55. def current_layer_height(self):
  56. if self._currentLayer != "":
  57. return self._layer[self._currentLayer]["h"]
  58. return 0
  59. @property
  60. def layer_names(self):
  61. names = []
  62. for key in self._layer:
  63. names.append(names)
  64. return names
  65. @property
  66. def orientation(self):
  67. return self._orientation
  68. @property
  69. def cell_position(self):
  70. return (self._cellpos[0], self._cellpos[1])
  71. def set_resources(self, env_src, wall_src):
  72. res = self.resource
  73. if env_src != "" and env_src != self._res["env_src"]:
  74. if res.is_valid("json", env_src):
  75. if not res.has("json", env_src):
  76. res.store("json", env_src)
  77. e = res.get("json", env_src)
  78. if e is not None and e() is not None:
  79. self._res["env_src"] = env_src
  80. self._res["env"] = e
  81. # TODO: Load the images associated with the environments
  82. if wall_src != "" and wall_src != self._res["wall_src"]:
  83. if res.is_valid("json", wall_src):
  84. if not res.has("json", wall_src):
  85. print("Storing resource {}".format(wall_src))
  86. res.store("json", wall_src)
  87. w = res.get("json", wall_src)
  88. print(w)
  89. if w is not None and w() is not None:
  90. self._res["wall_src"] = wall_src
  91. self._res["walls"] = w
  92. # NOTE: I'm making a lot of assumptions to the structural validity of the data file, but...
  93. imgsrc = w().data["src"]
  94. if res.is_valid("graphic", imgsrc):
  95. if res.has("graphic", imgsrc):
  96. res.store("graphic", imgsrc)
  97. else:
  98. print("Failed to get JSON instance {}".format(wall_src))
  99. else:
  100. print("Invalid JSON {}".format(wall_src))
  101. def add_layer(self, name, w, h):
  102. if name == "" or name in self._layer:
  103. return
  104. self._layer[name] = {
  105. "w":w,
  106. "h":h,
  107. "cells":[]
  108. }
  109. for c in range(0, w*h):
  110. self._layer[name]["cells"].append({
  111. "c":0, # Sky / Ceiling
  112. "g":0, # Ground
  113. "n":[-1, False, -1, None], # North Wall | [<graphic index, -1 = None>, <blocking>, <door index, -1 = None, 0 = closed, 1=open>, <door target>]
  114. "s":[-1, False, -1, None], # South Wall
  115. "e":[-1, False, -1, None], # East Wall
  116. "w":[-1, False, -1, None], # West Wall
  117. })
  118. if self._currentLayer == "":
  119. self._currentLayer = name
  120. def set_active_layer(self, name, x=0, y=0):
  121. if name == "" or not (name in self._layers):
  122. return
  123. layer = self._layers[name]
  124. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  125. self._currentLayer = name
  126. self._cellpos = [x,y]
  127. def set_cell_env(self, x, y, ceiling=-1, ground=-1):
  128. if self._currentLayer == "":
  129. return
  130. layer = self._layer[self._currentLayer]
  131. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  132. index = (y * layer["w"]) + x
  133. cell = layer["cells"]
  134. if ceiling >= 0:
  135. cell[index]["c"] = ceiling
  136. if ground >= 0:
  137. cell[index]["g"] = ground
  138. def fill_cell_env(self, x1, y1, x2, y2, ceiling=-1, ground=-1):
  139. if self._currentLayer == "":
  140. return
  141. for y in range(y1, y2+1):
  142. for x in range(x1, x2+1):
  143. self.set_cell_env(x, y, ceiling, ground)
  144. def set_cell_face(self, x, y, face, gi=-2, blocking=None):
  145. if self._currentLayer == "" or not (face == "n" or face == "s" or face == "w" or face == "e"):
  146. return
  147. layer = self._layer[self._currentLayer]
  148. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  149. index = (y * layer["w"]) + x
  150. cell = layer["cells"]
  151. if gi <= -2:
  152. gi = self._res["wall_index"]
  153. if gi >= -1:
  154. cell[index][face][0] = gi
  155. if blocking is not None:
  156. cell[index][face][1] = (blocking == True)
  157. else:
  158. if gi == -1: # If gi = -1, there is no wall, so, by default, there is no blocking.
  159. cell[index][face][1] = False
  160. else: # Otherwise, blocking is assumed :)
  161. cell[index][face][1] = True
  162. elif blocking is not None:
  163. blocking = (blocking == True) # Forcing a boolean
  164. cell[index][face][1] = blocking
  165. def next_wall(self):
  166. if self._res["walls"] is not None:
  167. w = self._res["walls"]()
  168. if w is not None:
  169. windex = self._res["wall_index"] + 1
  170. if windex >= len(w.data["walls"]):
  171. windex = -1
  172. self._res["wall_index"] = windex
  173. print("Next Wall Index: {}".format(windex))
  174. def prev_wall(self):
  175. if self._res["walls"] is not None:
  176. w = self._res["walls"]()
  177. if w is not None:
  178. windex = self._res["wall_index"] - 1
  179. if windex < -1:
  180. windex = len(w.data["walls"]) - 1
  181. self._res["wall_index"] = windex
  182. print("Prev Wall Index: {}".format(windex))
  183. def turn_left(self):
  184. onum = self._d_s2n(self._orientation)
  185. onum -= 1
  186. if onum < 0:
  187. onum = 3
  188. self._orientation = self._d_n2s(onum)
  189. def turn_right(self):
  190. onum = self._d_s2n(self._orientation)
  191. onum += 1
  192. if onum > 3:
  193. onum = 0
  194. self._orientation = self._d_n2s(onum)
  195. def move_to(self, x, y):
  196. if x >= 0 and x < self.current_layer_width and y >= 0 and y < self.current_layer_height:
  197. self._cellpos = [x, y]
  198. def move_forward(self, ignore_passible=False):
  199. if ignore_passible or self.is_passible(self._cellpos[0], self._cellpos[1], self._orientation):
  200. x = self._cellpos[0]
  201. y = self._cellpos[1]
  202. if self._orientation == "n":
  203. y -= 1
  204. elif self._orientation == "e":
  205. x += 1
  206. elif self._orientation == "s":
  207. y += 1
  208. elif self._orientation == "w":
  209. x -= 1
  210. self.move_to(x, y)
  211. def move_backward(self, ignore_passible=False):
  212. orient = self._orientation
  213. if self._orientation == "n":
  214. self._orientation = "s"
  215. elif self._orientation == "s":
  216. self._orientation = "n"
  217. elif self._orientation == "e":
  218. self._orientation = "w"
  219. elif self._orientation == "w":
  220. self._orientation = "e"
  221. self.move_forward(ignore_passible)
  222. self._orientation = orient
  223. def is_passible(self, x, y, d):
  224. """
  225. Returns true if it's possible to move forward from the x, y map position in the direction given.
  226. d - 0 = North, 1 = East, 2 = South, 3 = West
  227. """
  228. if self._currentLayer == "" or d < 0 or d >= 4:
  229. return False
  230. layer = self._layer[self._currentLayer]
  231. if x >= 0 and x < layer["w"] and y >= 0 and y < layer["h"]:
  232. index = (y * layer["w"]) + x
  233. d = self._d_n2s(d)
  234. return not layer["cells"][index][d][1]
  235. return False
  236. def _d_n2s(self, d): # _(d)irection_(n)umber_to_(s)tring
  237. if d == 0:
  238. return "n"
  239. elif d == 1:
  240. return "e"
  241. elif d == 2:
  242. return "s"
  243. elif d == 3:
  244. return "w"
  245. return ""
  246. def _d_s2n(self, d):
  247. if d == "n":
  248. return 0
  249. elif d == "e":
  250. return 1
  251. elif d == "s":
  252. return 2
  253. elif d == "w":
  254. return 3
  255. return -1
  256. def _indexFromPos(self, x, y):
  257. if x >= 0 and x < self.current_layer_width and y >= 0 and y < self.current_layer_height:
  258. return (y * self.current_layer_width) + x
  259. return -1
  260. def _getCell(self, x, y):
  261. index = self._indexFromPos(x, y)
  262. if index < 0:
  263. return None
  264. return self._layer[self._currentLayer]["cells"][index]
  265. def _RenderTopDown(self):
  266. cell_size = self._topdown["size"]
  267. size = self.resolution
  268. pos = self._cellpos
  269. lsize = (self.current_layer_width, self.current_layer_height)
  270. hcells = int(size[0] / cell_size)
  271. vcells = int(size[1] / cell_size)
  272. cx = pos[0] - int(hcells * 0.5)
  273. cy = pos[1] - int(vcells * 0.5)
  274. ry = -4
  275. for j in range(0, vcells+1):
  276. y = cy + j
  277. if y >= 0 and y < lsize[1]:
  278. rx = -1
  279. for i in range(0, hcells+1):
  280. x = cx + i
  281. if x >= 0 and x < lsize[0]:
  282. cell = self._getCell(x, y)
  283. if cell["n"][0] >= 0:
  284. self.draw_rect((rx, ry, cell_size, 2), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  285. if cell["e"][0] >= 0:
  286. self.draw_rect((rx+(cell_size-2), ry, 2, cell_size), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  287. if cell["s"][0] >= 0:
  288. self.draw_rect((rx, ry+(cell_size-2), cell_size, 2), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  289. if cell["w"][0] >= 0:
  290. self.draw_rect((rx, ry, 2, cell_size), self._topdown["wall_color"], 0, self._topdown["wall_color"])
  291. if cell["n"][1] == True:
  292. self.draw_lines([(rx+1, ry+1), (rx+(cell_size-1), ry+1)], self._topdown["blocked_color"], 1)
  293. if cell["e"][1] == True:
  294. self.draw_lines([(rx+(cell_size-2), ry+1), (rx+(cell_size-2), ry+(cell_size-2))], self._topdown["blocked_color"], 1)
  295. if cell["s"][1] == True:
  296. self.draw_lines([(rx+1, ry+(cell_size-2)), (rx+(cell_size-2), ry+(cell_size-2))], self._topdown["blocked_color"], 1)
  297. if cell["w"][1] == True:
  298. self.draw_lines([(rx+1, ry+1), (rx+1, ry+(cell_size-2))], self._topdown["blocked_color"], 1)
  299. rx += cell_size
  300. ry += cell_size
  301. def _RenderPerspective(self):
  302. pass
  303. def on_render(self):
  304. if self._renderMode == 0:
  305. self._RenderTopDown()
  306. else:
  307. self._RenderPerspective()
  308. class NodeMapEditor(gbe.nodes.Node2D):
  309. def __init__(self, name="MapEditor", parent=None):
  310. try:
  311. gbe.nodes.Node2D.__init__(self, name, parent)
  312. except gbe.nodes.Node2D as e:
  313. raise e
  314. def on_start(self):
  315. self.listen("KEYPRESSED", self.on_keypressed)
  316. def on_pause(self):
  317. self.unlisten("KEYPRESSED", self.on_keypressed)
  318. def on_keypressed(self, event, data):
  319. p = self.parent
  320. if p is None or not isinstance(p, NodeGameMap):
  321. return
  322. if data["key_name"] == "escape":
  323. self.emit("QUIT")
  324. if data["key_name"] == "w":
  325. p.move_forward(True)
  326. elif data["key_name"] == "s":
  327. p.move_backward(True)
  328. elif data["key_name"] == "a":
  329. p.turn_left()
  330. elif data["key_name"] == "d":
  331. p.turn_right()
  332. elif data["key_name"] == "space":
  333. o = p.orientation
  334. cpos = p.cell_position
  335. p.set_cell_face(cpos[0], cpos[1], o)
  336. elif data["key_name"] == "e":
  337. p.next_wall()
  338. elif data["key_name"] == "q":
  339. p.prev_wall()