world.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. # THIS IS A SOURCE CODE FILE FROM I'M NOT EVEN HUMAN THE GAME.
  2. # IT COULD BE USED IN A DIFFERENT PIECE OF SOFTWARE ( LIKE A
  3. # DIFFERENT GAME ), BUT IT WAS ORIGINALLY WRITTEN FOR I'M NOT
  4. # EVEN HUMAN THE GAME.
  5. # THE DEVELOPERS OF THE GAME ARE : (C) J.Y.AMIHUD, AYYZEE AND
  6. # OTHER CONTRIBUTORS. THIS AND OTHER FILES IN THIS GAME,
  7. # UNLESS SPECIFICALLY NOTED, COULD BE USED UNDER THE TERMS OF
  8. # GNU GENERAL PUBLIC LICENSE VERSION 3 OR ANY LATER VERSION.
  9. import os
  10. import json
  11. import math
  12. import cairo
  13. from modules import ui
  14. def draw(game, outlayer, x, y, w, h, grid=True):
  15. """This function will draw the level it self"""
  16. x = int(x)
  17. y = int(y)
  18. w = int(w)
  19. h = int(h)
  20. # To make it a bit more nice, I will use a separate image
  21. # layer for the level.
  22. surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,w,h)
  23. layer = cairo.Context(surface)
  24. layer.set_antialias(cairo.ANTIALIAS_NONE)
  25. if game.current["testing"]:
  26. ui.color(game, layer, "red")
  27. layer.rectangle(0,0,w-1,h-1)
  28. layer.stroke()
  29. sidex = 64
  30. sidey = 36
  31. offsetx = int(sidex / 2)
  32. offsety = int(sidey / 2)
  33. # moving the game world
  34. if game.current["MMB"] and grid\
  35. and int(game.current["mx"]) in range(x, x+w)\
  36. and int(game.current["my"]) in range(y, y+h):
  37. game.current["camera"][0] += (game.current["mx"] - game.previous["mx"])
  38. game.current["camera"][1] += (game.current["my"] - game.previous["my"])
  39. if "world_mo" not in game.current:
  40. game.current["world_mo"] = [0,0,0]
  41. wmod = 1000000000 # Artbitrary large number
  42. wmo = [-500,-500,0] # This updates game.current["world_mo"] for the next frame
  43. # List of chunks in the current rendering
  44. rendered_chunks = []
  45. render_coordinates = "0:0"
  46. # Coordinates of the character
  47. x79 = game.current["state"]["4211D79"]["xyz"][0] + game.current["camera"][0]
  48. y79 = game.current["state"]["4211D79"]["xyz"][1] + game.current["camera"][1]
  49. # Colision to 0
  50. game.current["state"]["4211D79"]["colision"] = False
  51. # MAIN LOOP
  52. for lh in range(-2, 5): # For a few vertical levels
  53. for th in range(int(h/offsety)+6): # For cells from top to bottom
  54. # Calculating the cell offset from the camera
  55. offx = game.current["camera"][0] % sidex
  56. offy = game.current["camera"][1] % sidey
  57. if th % 2 == 0:
  58. offx += offsetx
  59. for tw in range(int(w/sidex)+3): # For cells from right to left
  60. # Where to draw the cell
  61. drawx = (tw-2)*sidex+offx
  62. drawy = (th-3)*offsety+offy
  63. # Where is the cell's center
  64. centerx = offsetx+((tw-2)*sidex+offx)
  65. centery = offsety+((th-3)*offsety+offy)
  66. # What is the cell's coordinates
  67. xaddr = 0-int( (game.current["camera"][0] - drawx) / offsetx )
  68. yaddr = 0-int( (game.current["camera"][1] - drawy) / offsety )
  69. # The address of the cell
  70. celladdr = [xaddr, yaddr]
  71. # Distance of the cell to the mouse
  72. dtox = game.current["mx"]-x
  73. dtoy = game.current["my"]-y
  74. # Position of the character
  75. if not grid:
  76. dtox = x79
  77. dtoy = y79
  78. dtomouse = ui.distance([dtox, dtoy],
  79. [centerx,centery])
  80. # If mouse in screen
  81. if int(game.current["mx"]) in range(int(x), int(x+w))\
  82. and int(game.current["my"]) in range(int(y), int(y+h)):
  83. mouseinscreen = True
  84. else:
  85. mouseinscreen = False
  86. # Figuring out if the cell is closest to the mouse ( mouse over the cell )
  87. if dtomouse < wmod and (mouseinscreen or not grid):
  88. wmo = celladdr
  89. wmod = dtomouse
  90. # The chunk address for the cell ( a json file for the world cache )
  91. chunk = str(int(xaddr/100))+":"+str(int(yaddr/100))+":"+str(game.current["camera"][2]+lh)
  92. # Loading chunk from the json
  93. if chunk not in game.chunks[1]:
  94. load_chunk(game, chunk)
  95. # Checking if the chunk is not rendered, to remove it from cache
  96. if not chunk in rendered_chunks:
  97. rendered_chunks.append(chunk)
  98. # Address inside the chunk
  99. addr = str(xaddr)+":"+str(yaddr)
  100. # If current Vertical Layer
  101. if lh == 0:
  102. if grid:
  103. # Grid
  104. ui.image(game, layer,
  105. drawx,
  106. drawy,
  107. "assets/grid.png", "grid", color=False)
  108. # If mouse over this cell
  109. selectedcells = [game.current["world_mo"]]
  110. if game.current["editor_brush"] > 1:
  111. bax = game.current["world_mo"][0]
  112. bay = game.current["world_mo"][1]
  113. bs = game.current["editor_brush"] - 1
  114. for bx in range(bax-bs, bax+bs):
  115. for by in range(bay-bs, bay+bs):
  116. selectedcells.append([bx,by])
  117. if celladdr in selectedcells:
  118. render_coordinates = addr
  119. # Selection image grid thingy
  120. if grid:
  121. ui.image(game, layer,
  122. drawx,
  123. drawy,
  124. "assets/grid.png", "selected", color=False)
  125. # Pressing RMB to delete things in editor
  126. if game.current["RMB"]:
  127. try:
  128. del game.chunks[1][chunk][addr]
  129. except:
  130. pass
  131. # Pressing LMB to draw
  132. if game.current["LMB"]:
  133. types = game.current["editor_selection"][0]
  134. asset = game.current["editor_selection"][1]
  135. version = game.elements[types][asset][game.current["editor_selection"][2]]["title"]
  136. addfile = types+"/"+asset
  137. # Making sure they are both in the list
  138. for i in (version, addfile):
  139. if i not in game.chunks[0]:
  140. game.chunks[0].append(i)
  141. # Getting their indexes
  142. version = game.chunks[0].index(version)
  143. addfile = game.chunks[0].index(addfile)
  144. game.chunks[1][chunk][addr] = [addfile, version]
  145. # SAVE CHUNK
  146. if (not game.current["LMB"] and game.previous["LMB"])\
  147. or (not game.current["RMB"] and game.previous["RMB"]):
  148. save_chunk(game, chunk)
  149. # Try drawing the asset in this cell
  150. try:
  151. chunkasst = game.chunks[1][chunk][addr]
  152. chunkasst = [ game.chunks[0][chunkasst[0]], game.chunks[0][chunkasst[1]] ]
  153. # Dynamic transparency
  154. dalpha = 1
  155. # [ 0:0 ]
  156. # [ -1:1 ][ 1:1 ]
  157. # [ 0:2 ]
  158. #
  159. seltmp = game.current["world_mo"]
  160. tcolumns = [
  161. seltmp,
  162. [seltmp[0]-1, seltmp[1]+1],
  163. [seltmp[0]+1, seltmp[1]+1],
  164. [seltmp[0], seltmp[1]+2]]
  165. for i in tcolumns:
  166. if celladdr[0] == i[0]\
  167. and celladdr[1] in range( i[1]-(lh*2), i[1]+1)\
  168. and ( mouseinscreen or not grid ):
  169. if celladdr == seltmp and lh == 0 and grid:
  170. dalpha = 1
  171. else:
  172. dalpha = 0.25
  173. if lh > 1:
  174. dalpha = 0.1
  175. # Draw cell
  176. ui.image(game, layer,
  177. drawx,
  178. drawy,
  179. "assets/elements/"+chunkasst[0], chunkasst[1],
  180. offset=True, alpha=dalpha)
  181. # Highlight cell in red when mouse over
  182. if celladdr in selectedcells:
  183. if lh == 0:
  184. if not grid:
  185. game.current["state"]["4211D79"]["colision"] = \
  186. [drawx+offsetx - game.current["camera"][0],
  187. drawy+offsety - game.current["camera"][1]]
  188. else:
  189. ui.color(game, layer, "red", 0.5)
  190. ui.image(game, layer,
  191. drawx,
  192. drawy,
  193. "assets/elements/"+chunkasst[0], chunkasst[1],
  194. offset=True, color=True)
  195. # Select the current thing for the editor.
  196. try:
  197. if game.previous["MMB"] and not game.current["MMB"]\
  198. and int(game.current["mx"]) == int(game.previous["MMB"][0])\
  199. and int(game.current["my"]) == int(game.previous["MMB"][1]):
  200. types = chunkasst[0].split("/")[0]
  201. asset = chunkasst[0].split("/")[1]
  202. for version, names in enumerate(game.elements[types][asset]):
  203. if names["title"] == chunkasst[1]:
  204. break
  205. game.current["editor_selection"][0] = types
  206. game.current["editor_selection"][1] = asset
  207. game.current["editor_selection"][2] = version
  208. except Exception as e:
  209. print(e)
  210. except:
  211. pass
  212. if not grid:
  213. ui.image(game, layer,
  214. x79,
  215. y79,
  216. "assets/elements/characters/4211D79_standing.png", "selected", offset=True)
  217. # If Editor Show the currently selected item
  218. if grid:
  219. types = game.current["editor_selection"][0]
  220. asset = game.current["editor_selection"][1]
  221. version = game.elements[types][asset][game.current["editor_selection"][2]]
  222. ui.image(game, layer,
  223. game.current["mx"]-x-offsetx,
  224. game.current["my"]-y-offsety,
  225. "assets/elements/"+types+"/"+asset, version["title"], offset=True, alpha=0.5)
  226. # Select the mouse over cell
  227. game.current["world_mo"] = wmo
  228. # Removing chunks that are not rendered currently from the memory
  229. for i in list(game.chunks[1].keys()):
  230. if i not in rendered_chunks:
  231. del game.chunks[1][i]
  232. # The current Z ( height ) rendering in top, right corner
  233. ui.color(game, layer, "yellow")
  234. ui.text(game,layer, str(game.current["camera"][2]),
  235. 40,
  236. 40)
  237. ui.text(game,layer, render_coordinates,
  238. 40,
  239. 60)
  240. # Numpad + to go up
  241. if 65451 in game.current["keys"]:
  242. game.current["camera"][2] += 1
  243. game.current["keys"] = []
  244. # Numpad - to go down
  245. if 65453 in game.current["keys"]:
  246. game.current["camera"][2] -= 1
  247. game.current["keys"] = []
  248. # Drawing the world to the outlayer
  249. outlayer.set_source_surface(surface, x , y)
  250. outlayer.paint()
  251. def update_elements(game):
  252. """This function caches all assets"""
  253. game.elements = {}
  254. # elements
  255. # Element type ( blocks, characters, vehicles )
  256. # Image assets
  257. for types in os.listdir(os.getcwd()+"/assets/elements"):
  258. game.elements[types] = {}
  259. for asset in os.listdir(os.getcwd()+"/assets/elements/"+types):
  260. if asset.endswith(".png"):
  261. asseturl = "assets/elements/"+types+"/"+asset
  262. ui.cache_sprite_sheet(game, asseturl, [types, asset])
  263. # Now let's generate the selection for the editor
  264. game.current["editor_selection"] = [
  265. list(game.elements.keys())[0],
  266. list(list(game.elements.values())[0].keys())[0],
  267. 0]
  268. # Make the brush 0
  269. game.current["editor_brush"] = 1
  270. # YANK THAT CODE LATER
  271. # every chunk is 100 by 100
  272. game.chunks = [[],{}]
  273. def save_chunk(game, chunk):
  274. """This function saves the chunk"""
  275. # Getting the raw chunk
  276. savedata = [[], game.chunks[1][chunk].copy()]
  277. # Adding all the asset names to it
  278. for ind in savedata[1]:
  279. i = savedata[1][ind]
  280. savedata[1][ind] = i.copy()
  281. for n, b in enumerate(i):
  282. add = game.chunks[0][b]
  283. if add not in savedata[0]:
  284. savedata[0].append(add)
  285. savedata[1][ind][n] = savedata[0].index(add)
  286. # Save the json
  287. savefilename = "assets/worlds/"+game.settings["world"]+"/"+chunk+".json"
  288. with open(savefilename, 'w') as f:
  289. json.dump(savedata, f)
  290. def load_chunk(game, chunk):
  291. """This function loads a chunk."""
  292. # Load the json
  293. loadfilename = "assets/worlds/"+game.settings["world"]+"/"+chunk+".json"
  294. try:
  295. with open(loadfilename) as f:
  296. loaddata = json.load(f)
  297. except:
  298. loaddata = [[],{}]
  299. for ind in loaddata[1]:
  300. i = loaddata[1][ind]
  301. for n, b in enumerate(i):
  302. add = loaddata[0][b]
  303. if add not in game.chunks[0]:
  304. game.chunks[0].append(add)
  305. loaddata[1][ind][n] = game.chunks[0].index(add)
  306. game.chunks[1][chunk] = loaddata[1]