gameplay.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  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. # GTK module ( Graphical interface
  12. import gi
  13. gi.require_version('Gtk', '3.0')
  14. from gi.repository import Gtk
  15. import cairo
  16. import math
  17. from modules import ui
  18. from modules import world
  19. def layer(game):
  20. # Setting up a cairo layer
  21. surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
  22. game.current['w'],
  23. game.current['h'])
  24. layer = cairo.Context(surface)
  25. layer.set_antialias(cairo.ANTIALIAS_NONE) # Disable AA to prevent blured pixels
  26. # Factor to change speed dependand on FPS
  27. withFPS = (1/game.FPS*60)
  28. # Prepare the layer for gameplay and do not draw the editor grid.
  29. world.draw(game, layer, 0, 0,
  30. game.current["w"],
  31. game.current["h"], grid=False)
  32. ### DRAWING SELECTED CHARACTERS ###
  33. for n, asset in enumerate(game.current["state"]["controlling"]):
  34. if game.current["state"]["controlling"][asset]:
  35. ui.color(game, layer, "orange")
  36. layer.rectangle(
  37. 14,
  38. 14 + (n*15),
  39. 12,12)
  40. layer.fill()
  41. if "following" in game.current["state"]["objects"][asset]:
  42. target = game.current["state"]["objects"][asset]["following"]
  43. # Tiny Visualizer
  44. ui.color(game, layer, "orange")
  45. layer.set_line_width(1)
  46. layer.move_to(
  47. 26,
  48. 14 + (n*15) + 10)
  49. layer.line_to(26 + (n*5) + 5,
  50. 14 + (n*15) + 10)
  51. layer.line_to(26 + (n*5) + 5,
  52. 14 + (target*15) + 2)
  53. layer.line_to(26,
  54. 14 + (target*15) + 2)
  55. layer.stroke()
  56. layer.move_to(28,
  57. 14 + (target*15))
  58. layer.line_to(28,
  59. 14 + (target*15)+3)
  60. layer.stroke()
  61. asset_draw = game.current["state"]["objects"][asset]["asset"]
  62. ui.image(game, layer,
  63. 15,
  64. 15 + (n*15) ,
  65. "assets/elements/"+asset_draw+".png",
  66. "icon")
  67. # Rotations is sequence for the automatic rotation mechanism
  68. rotations = {
  69. "normal":[
  70. "Right",
  71. "Down-Right",
  72. "Down",
  73. "Down-Left",
  74. "Left",
  75. "Up-Left",
  76. "Up",
  77. "Up-Right"]}
  78. #### MOVING CHARACTERS AROUND LOGIC ####
  79. for asset, t in enumerate(game.current["state"]["objects"]):
  80. try:
  81. if "target-orientation" in game.current["state"]["objects"][asset]\
  82. and game.current["frame"] % max(1, int(game.FPS/10)) == 0:
  83. target = game.current["state"]["objects"][asset]["target-orientation"]
  84. current = game.current["state"]["objects"][asset]["orientation"]
  85. if target != current:
  86. tlist = rotations["normal"].copy()
  87. for i in range(2):
  88. for b in rotations["normal"]:
  89. tlist.append(b)
  90. tlist[tlist.index(current)] = "blank"
  91. tlist[tlist.index(current)] = "current"
  92. tlist[tlist.index(current)] = "blank"
  93. tlist[tlist.index(target)] = "option1"
  94. tlist[tlist.index(target)] = "option2"
  95. tlist[tlist.index(target)] = "option3"
  96. add = 1
  97. closest = len(tlist)
  98. for i in ["option1", "option2", "option3"]:
  99. t = tlist.index(i)
  100. c = tlist.index("current")
  101. if max(t,c) - min(t,c) < closest:
  102. closest = max(t,c) - min(t,c)
  103. if t < c:
  104. add = -1
  105. else:
  106. add = 1
  107. index = (rotations["normal"].index(current)+add) % len(rotations["normal"])
  108. put = rotations["normal"][index]
  109. game.current["state"]["objects"][asset]["orientation"] = put
  110. elif game.current["frame"] % max(1, int(game.FPS/10)) == 0:
  111. del game.current["state"]["objects"][asset]["target-orientation"]
  112. except:
  113. pass
  114. xob = game.current["state"]["objects"][asset]["xyz"][0]
  115. yob = game.current["state"]["objects"][asset]["xyz"][1]
  116. asset_draw = game.current["state"]["objects"][asset]["asset"]
  117. orientation = "Down-Left"
  118. try:
  119. image = game.images["assets/elements/"+asset_draw+".png"][orientation][0]["binary"]
  120. image_height = image.get_height()
  121. except:
  122. image_height = 61
  123. # Healthbar
  124. if game.current["state"]["objects"][asset]["health"] <= 0:
  125. game.current["state"]["objects"][asset]["health"] = 0
  126. game.current["state"]["objects"][asset]["orientation"] = "Dead"
  127. try:
  128. del game.current["state"]["controlling"][asset]
  129. except:
  130. pass
  131. continue
  132. else:
  133. #Regenerate
  134. game.current["state"]["objects"][asset]["health"] += 0.0001 * withFPS
  135. if game.current["state"]["objects"][asset]["health"] >= 1:
  136. game.current["state"]["objects"][asset]["health"] = 1
  137. if game.current["state"]["controlling"].get(asset, False):
  138. ui.color(game, layer, "orange")
  139. ui.text(game,layer, game.images["assets/elements/"+asset_draw+".png"].get("title", "Unknown"),
  140. 15,
  141. game.current["h"]-40)
  142. ui.fancy_health_bar(game,
  143. 15,
  144. game.current["h"]-20,
  145. game.current["w"]/3,
  146. 15,
  147. layer,
  148. game.current["state"]["objects"][asset]["health"])
  149. else:
  150. ui.color(game, layer, "red")
  151. layer.set_line_width(2)
  152. layer.move_to(xob + game.current["camera"][0]-10,
  153. yob + game.current["camera"][1] - image_height-5)
  154. layer.line_to(xob + game.current["camera"][0]+10,
  155. yob + game.current["camera"][1] - image_height-5)
  156. layer.stroke()
  157. ui.color(game, layer, "green")
  158. layer.set_line_width(2)
  159. layer.move_to(xob + game.current["camera"][0]-10,
  160. yob + game.current["camera"][1] - image_height-5)
  161. layer.line_to(xob + game.current["camera"][0]-10+(20*game.current["state"]["objects"][asset]["health"]),
  162. yob + game.current["camera"][1] - image_height-5)
  163. layer.stroke()
  164. # THE PLAYER CONTROLLS THIS CHRACTER DIRECTLY
  165. if game.current["state"]["controlling"].get(asset, False):
  166. x79 = game.current["state"]["objects"][asset]["xyz"][0]
  167. y79 = game.current["state"]["objects"][asset]["xyz"][1]
  168. z79 = game.current["state"]["objects"][asset]["xyz"][2]
  169. ui.image(game, layer,
  170. x79 + game.current["camera"][0],
  171. y79 + game.current["camera"][1] + 61 - image_height,
  172. "assets/elements/characters/shadow.png",
  173. "arrow",
  174. offset=True, dynamic=True)
  175. # SELECT FOLLOWING
  176. def do():
  177. if "following" in game.current["state"]["objects"][asset]:
  178. del game.current["state"]["objects"][asset]["following"]
  179. else:
  180. follow_closest(game, asset)
  181. ui.button(game, layer,
  182. int(game.current["w"]) - 36,
  183. 15,
  184. 12,
  185. 12,
  186. icon="radio_transition",
  187. func=do)
  188. # VISUALIZING THIS CHARACTERS FOLLOWING
  189. if "following" in game.current["state"]["objects"][asset]:
  190. target_asset = game.current["state"]["objects"][asset]["following"]
  191. xtar = 0
  192. ytar = 0
  193. ztar = 0
  194. try:
  195. xtar = game.current["state"]["objects"][target_asset]["xyz"][0]
  196. ytar = game.current["state"]["objects"][target_asset]["xyz"][1]
  197. ztar = game.current["state"]["objects"][target_asset]["xyz"][2]
  198. except:
  199. pass
  200. camx = game.current["camera"][0]
  201. camy = game.current["camera"][1]
  202. ui.color(game, layer, "orange")
  203. layer.set_line_width(2)
  204. # layer.arc(xtar+camx, ytar+camy, 20, 0, math.pi)
  205. # layer.stroke()
  206. ui.image(game, layer,
  207. xtar + game.current["camera"][0],
  208. ytar + game.current["camera"][1],
  209. "assets/elements/characters/shadow.png",
  210. "following",
  211. offset=True, dynamic=True)
  212. # CONTROLLS
  213. ori = ""
  214. # UP
  215. if 65362 in game.current["keys"]:
  216. game.current["state"]["objects"][asset]["xyz"][1] -= 4*0.57142857142857142857*withFPS
  217. ori = "Up"
  218. # DOWN
  219. if 65364 in game.current["keys"]:
  220. game.current["state"]["objects"][asset]["xyz"][1] += 4*0.57142857142857142857*withFPS
  221. ori = "Down"
  222. # LEFT
  223. if 65361 in game.current["keys"]:
  224. game.current["state"]["objects"][asset]["xyz"][0] -= 4 *withFPS
  225. if ori:
  226. ori = ori + "-Left"
  227. else:
  228. ori = "Left"
  229. # RIGHT
  230. if 65363 in game.current["keys"]:
  231. game.current["state"]["objects"][asset]["xyz"][0] += 4 *withFPS
  232. if ori:
  233. ori = ori + "-Right"
  234. else:
  235. ori = "Right"
  236. if ori and ori not in rotations["normal"]:
  237. ori = "Down"
  238. # SPACE ( JUMP )
  239. if 32 in game.current["keys"]:
  240. if game.current["state"]["objects"][asset]["grounded"]:
  241. # game.current["state"]["objects"][asset]["xyz"][2] += 0.8
  242. # game.current["state"]["objects"][asset]["xyz"][1] += 0.8*34
  243. game.current["state"]["objects"][asset]["velocity"][2] = 0.05
  244. # F ( toggle Following )
  245. if 102 in game.current["keys"]:
  246. if "following" in game.current["state"]["objects"][asset]:
  247. del game.current["state"]["objects"][asset]["following"]
  248. else:
  249. follow_closest(game, asset)
  250. game.current["keys"].remove(102)
  251. if ori:
  252. game.current["state"]["objects"][asset]["target-orientation"] = ori
  253. # THE OTHER ( FOLLOWING ) CHARACTERS
  254. elif "following" in game.current["state"]["objects"][asset]:
  255. target_asset = game.current["state"]["objects"][asset]["following"]
  256. xtar = 0
  257. ytar = 0
  258. ztar = 0
  259. try:
  260. xtar = game.current["state"]["objects"][target_asset]["xyz"][0]
  261. ytar = game.current["state"]["objects"][target_asset]["xyz"][1]
  262. ztar = game.current["state"]["objects"][target_asset]["xyz"][2]
  263. except:
  264. pass
  265. xob = game.current["state"]["objects"][asset]["xyz"][0]
  266. yob = game.current["state"]["objects"][asset]["xyz"][1]
  267. zob = game.current["state"]["objects"][asset]["xyz"][2]
  268. distance = ui.distance([xob, yob], [xtar, ytar])
  269. if distance > 50:
  270. motions = ["Right",
  271. "Down",
  272. "Left",
  273. "Up",
  274. "Up-Right",
  275. "Down-Right",
  276. "Down-Left",
  277. "Up-Left"]
  278. possibles = [[xob+4*withFPS,yob, zob],
  279. [xob, yob+4*0.57142857142857142857*withFPS, zob],
  280. [xob-4*withFPS, yob, zob],
  281. [xob, yob-4*0.57142857142857142857*withFPS, zob],
  282. [xob+4*withFPS, yob-4*0.57142857142857142857*withFPS, zob],
  283. [xob+4*withFPS, yob+4*0.57142857142857142857*withFPS, zob],
  284. [xob-4*withFPS, yob+4*0.57142857142857142857*withFPS, zob],
  285. [xob-4*withFPS, yob-4*0.57142857142857142857*withFPS, zob]]
  286. closest = 0
  287. for n, i in enumerate(possibles):
  288. thistance = ui.distance([i[0],i[1]], [xtar, ytar])
  289. if thistance < distance:
  290. distance = thistance
  291. closest = n
  292. game.current["state"]["objects"][asset]["xyz"] = possibles[closest]
  293. game.current["state"]["objects"][asset]["target-orientation"] = motions[closest]
  294. if ztar > zob+0.5 and game.current["state"]["objects"][asset]["grounded"]:
  295. game.current["state"]["objects"][asset]["velocity"][2] = 0.05
  296. # VISUALIZE THIS CHARACTERS FOLLOWING COURSE
  297. if game.current["testing"] and "following" in game.current["state"]["objects"][asset]:
  298. xob = game.current["state"]["objects"][asset]["xyz"][0]
  299. yob = game.current["state"]["objects"][asset]["xyz"][1]
  300. zob = game.current["state"]["objects"][asset]["xyz"][2]
  301. target_asset = game.current["state"]["objects"][asset]["following"]
  302. xtar = 0
  303. ytar = 0
  304. ztar = 0
  305. try:
  306. xtar = game.current["state"]["objects"][target_asset]["xyz"][0]
  307. ytar = game.current["state"]["objects"][target_asset]["xyz"][1]
  308. ztar = game.current["state"]["objects"][target_asset]["xyz"][2]
  309. except:
  310. pass
  311. camx = game.current["camera"][0]
  312. camy = game.current["camera"][1]
  313. ui.color(game, layer, "orange")
  314. layer.set_line_width(2)
  315. layer.move_to(xob+camx, yob+camy)
  316. di = ui.distance([xob, yob], [xtar, ytar])
  317. xlar = xob + ((xtar-xob) / di * (di-20))
  318. ylar = yob + ((ytar-yob) / di * (di-20))
  319. layer.line_to(xlar+camx, ylar+camy)
  320. layer.stroke()
  321. layer.arc(xtar+camx, ytar+camy, 20, 0, math.pi)
  322. layer.stroke()
  323. # Respawn if falling for more than specified time
  324. if game.current["state"]["objects"][asset]["grounded"]:
  325. game.current["state"]["objects"][asset]["time-falling"] = 0
  326. if game.current["frame"] % 20 == 0:
  327. game.current["state"]["objects"][asset]["check_mark"] = game.current["state"]["objects"][asset]["xyz"].copy()
  328. else:
  329. game.current["state"]["objects"][asset]["time-falling"] += 1
  330. if game.current["state"]["objects"][asset]["time-falling"] > 100:
  331. game.current["state"]["objects"][asset]["time-falling"] = 0
  332. game.current["state"]["objects"][asset]["xyz"] = game.current["state"]["objects"][asset]["check_mark"].copy()
  333. game.current["state"]["objects"][asset]["xyz"][2] += 1
  334. game.current["state"]["objects"][asset]["xyz"][1] -= 34
  335. game.current["state"]["objects"][asset]["velocity"] = [0,0,0]
  336. # Character switching
  337. # TAB
  338. if 65289 in game.current["keys"]:
  339. #print("asdf")
  340. found = 0
  341. for i, t in enumerate(game.current["state"]["controlling"]):
  342. if game.current["state"]["controlling"][t]:
  343. game.current["state"]["controlling"][t] = False
  344. found = i
  345. found += 1
  346. found = found % len(game.current["state"]["controlling"])
  347. found = list(game.current["state"]["controlling"].keys())[found]
  348. game.current["state"]["controlling"][found] = True
  349. game.current["keys"].remove(65289)
  350. # Camera binding
  351. try:
  352. targetx = 0 - x79 + (game.current["w"] / 2)
  353. targety = 0 - y79 + (game.current["h"] / 2)
  354. game.current["camera"][2] = int(round(z79))
  355. game.current["camera"][0] += (targetx - game.current["camera"][0])/4
  356. game.current["camera"][1] += (targety - game.current["camera"][1])/4
  357. except:
  358. pass
  359. return surface
  360. def follow_closest(game, asset):
  361. follow = 0
  362. dis = 1000000000
  363. xthis = game.current["state"]["objects"][asset]["xyz"][0]
  364. ythis = game.current["state"]["objects"][asset]["xyz"][1]
  365. for n, target_asset in enumerate(game.current["state"]["controlling"]):
  366. if target_asset == asset:
  367. continue
  368. xtar = game.current["state"]["objects"][target_asset]["xyz"][0]
  369. ytar = game.current["state"]["objects"][target_asset]["xyz"][1]
  370. di = ui.distance([xtar,ytar],[xthis,ythis])
  371. if di < dis:
  372. dis = di
  373. follow = target_asset
  374. game.current["state"]["objects"][asset]["following"] = follow
  375. def follow_last(game, asset):
  376. last = list(game.current["state"]["controlling"].keys())[-1]
  377. game.current["state"]["objects"][asset]["following"] = last