engine.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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 datetime # For the FPS meter mainly
  11. # GTK module ( Graphical interface
  12. import gi
  13. gi.require_version('Gtk', '3.0')
  14. from gi.repository import Gtk
  15. from gi.repository import Gdk
  16. import cairo
  17. import threading
  18. # Engine submodules ( Layers )
  19. from modules import ui
  20. # Game scenes ( layers )
  21. from modules import testing
  22. from modules import main_menu
  23. from modules import settings
  24. from modules import editor
  25. def previous(game):
  26. """This function is making an exact copy of game.current
  27. to preserve the values from the previous frame."""
  28. game.previous = {}
  29. for i in game.current:
  30. if type(game.current[i]) == list or type(game.current[i]) is dict:
  31. game.previous[i] = game.current[i].copy()
  32. else:
  33. game.previous[i] = game.current[i]
  34. def run():
  35. """This function will launch the game's engine and make a
  36. window and everything."""
  37. # This is a hack. game will be a Gtk.Window() object. But I
  38. # am going to add into it a lot of other things and pass it
  39. # to all the sub-functions as a kind of container for semi-
  40. # global variables. Anything important goes into the game
  41. # variable.
  42. game = Gtk.Window()
  43. game.set_default_size(1200,720)
  44. game.set_position(Gtk.WindowPosition.CENTER)
  45. game.connect("destroy", Gtk.main_quit)
  46. game.set_default_icon_from_file("icon.png")
  47. game.set_title("I'm Not Even Human - The Game")
  48. # Catching events from keys and mouse clicks
  49. game.connect("button-press-event", mouse_button_press, game)
  50. game.connect("button-release-event", mouse_button_release, game)
  51. game.connect("key-press-event", key_press, game)
  52. game.connect("key-release-event", key_release, game)
  53. # To catch the scroll events from the mouse wheel in GTK I
  54. # need to have a scrolled windows widget. There is no use
  55. # for it. I'm making it only to add this functionality
  56. # which is just an another hack.
  57. scroll = Gtk.ScrolledWindow()
  58. scroll.connect("scroll-event", scrolling, game)
  59. game.scene = "main_menu" # Current menu of the game
  60. game.map = {} # Chunks of the map
  61. game.current = {} # Values for the current frame
  62. game.previous = {} # Values for the previous frame
  63. game.images = {} # All images loaded to memory
  64. game.menus = {} # Metada to navigate buttons using a keyboard
  65. game.FPS = 0 # Frames per second of the game.
  66. game.AFPS = 0 # Average frames per second
  67. game.scroll = {} # Scrolls
  68. <<<<<<< HEAD
  69. settings.update_worlds(game) # Worlds metadata | game.worlds
  70. settings.load_settings(game) # Loading settings | game.settings
  71. =======
  72. game.settings = {
  73. "pixels":4, # How big are pixels on the screen
  74. "fullscreen":False}
  75. >>>>>>> 4f59bf84d5c1dc67fcc03c78488f20af217ceab7
  76. ui.load_palete(game) # game.palete ( colors from assets/palete.json )
  77. game.current["frame"] = 0 # The number of frames from launch
  78. game.current["camera"] = [0,0,0] # Game camera
  79. game.current["testing"] = False # Whether the devmode is on / off
  80. game.current["LMB"] = False # Left Mouse Button
  81. game.current["MMB"] = False # Middle Mouse Button
  82. game.current["RMB"] = False # Right Mouse Button
  83. game.current["keys"] = [] # List of pressed keys ( IDs )
  84. game.current["scroll"] = [0,0]
  85. # Making the copy of all current, so far into previous
  86. previous(game)
  87. # Setting up the FPS meter
  88. game.sFPS = datetime.datetime.now()
  89. # Setting the drawable
  90. gamedraw = Gtk.DrawingArea()
  91. gamedraw.set_size_request(800, 600)
  92. scroll.set_size_request(800, 600)
  93. game.add(scroll)
  94. scroll.add_with_viewport(gamedraw)
  95. gamedraw.connect("draw", gamedrawing, game)
  96. # Running
  97. game.show_all()
  98. Gtk.main()
  99. def gamedrawing(gamedrawing, main_layer, game):
  100. """You can think of this function as one that combines various
  101. layers into a finished image. And handles some logic related
  102. to it."""
  103. # FPS counter
  104. game.fFPS = datetime.datetime.now()
  105. game.tFPS = game.fFPS - game.sFPS
  106. game.FPS = int ( 1.0 / ( game.tFPS.microseconds /1000000))
  107. if game.current["frame"] % 30 == 0:
  108. game.AFPS = game.FPS
  109. game.sFPS = datetime.datetime.now()
  110. # Updating the frame
  111. game.current["frame"] += 1
  112. # Getting mouse data about the frame
  113. game.current['mx'] = game.get_pointer()[0] / game.settings["pixels"]
  114. game.current['my'] = game.get_pointer()[1] / game.settings["pixels"]
  115. game.current['w'] = int(round(game.get_size()[0] / game.settings["pixels"] ))
  116. game.current['h'] = int(round(game.get_size()[1] / game.settings["pixels"] ))
  117. if game.current["frame"] == 1:
  118. previous(game)
  119. # Switching the fullscreen mode on and off. Ctrl-T
  120. # [CTRL] [F]
  121. if 65507 in game.current["keys"] and 102 in game.current["keys"]:
  122. game.settings["fullscreen"] = not game.settings["fullscreen"]
  123. game.current["keys"] = [] # Wiping the press
  124. if game.settings["fullscreen"]:
  125. game.fullscreen()
  126. else:
  127. game.unfullscreen()
  128. layers = [] # Layers to draw
  129. if game.scene == "main_menu":
  130. layers.append(main_menu.layer(game))
  131. elif game.scene == "settings":
  132. layers.append(settings.layer(game))
  133. elif game.scene == "editor":
  134. layers.append(editor.layer(game))
  135. # Switching the testing mode on and off. Ctrl-T
  136. # [CTRL] [T]
  137. if 65507 in game.current["keys"] and 116 in game.current["keys"]:
  138. game.current["testing"] = not game.current["testing"]
  139. game.current["keys"] = [] # Wiping the press
  140. if game.current["testing"]:
  141. layers.append(testing.layer(game))
  142. # Scaling the layer to the window size
  143. main_layer.scale(game.settings["pixels"],
  144. game.settings["pixels"])
  145. ui.color(game, main_layer, "black")
  146. main_layer.rectangle(0,0,
  147. game.current["w"],
  148. game.current["h"])
  149. main_layer.fill()
  150. for layer in layers:
  151. # Setting the layer as a kind of brush
  152. main_layer.set_source_surface(layer, 0 , 0)
  153. # This is making the pixel art look pixalated
  154. p = main_layer.get_source()
  155. p.set_filter(cairo.FILTER_NEAREST)
  156. # Painting the layer
  157. main_layer.paint()
  158. # Update things when window is stretched
  159. if game.current["h"] != game.previous["h"]\
  160. or game.current["w"] != game.previous["w"]:
  161. for i in game.menus:
  162. if "buttons" in game.menus[i]:
  163. game.menus[i]["buttons"] = []
  164. <<<<<<< HEAD
  165. if 65307 in game.current["keys"]:
  166. game.scene = "main_menu"
  167. =======
  168. >>>>>>> 4f59bf84d5c1dc67fcc03c78488f20af217ceab7
  169. previous(game)
  170. # Refreshing the frame automatically
  171. gamedrawing.queue_draw()
  172. # Mouse
  173. def mouse_button_press(widget, event, game):
  174. # This function marks activation of the button. Not it's deactivation.
  175. for i, button in enumerate(["LMB", "MMB", "RMB"]):
  176. if i+1 == int(event.get_button()[1]):
  177. game.current[button] = [event.x / game.settings["pixels"],
  178. event.y / game.settings["pixels"]]
  179. def mouse_button_release(widget, event, game):
  180. # This function reverses the effects of the mouse_button_press() function.
  181. for i, button in enumerate(["LMB", "MMB", "RMB"]):
  182. if i+1 == int(event.get_button()[1]):
  183. game.current[button] = False
  184. def key_press(widget, event, game):
  185. if event.keyval not in game.current["keys"]:
  186. game.current["keys"].append(event.keyval)
  187. game.current["key_letter"] = event.string
  188. def key_release(widget, event, game):
  189. try:
  190. game.current["keys"].remove(event.keyval)
  191. except:
  192. game.current["keys"] = []
  193. # I also want to clean the key letter. Because other wise in the
  194. # script writer I had weird key presses all the time.
  195. if not game.current["keys"]:
  196. game.current["key_letter"] = ""
  197. def scrolling(widget, event, game):
  198. e, x, y = event.get_scroll_deltas()
  199. game.current["scroll"] = [x,y]