essytas 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. data/LICENSE +19 -0
  2. data/README +3 -0
  3. data/Rakefile +44 -0
  4. data/bin/essytas +2 -0
  5. data/lib/animation.rb +74 -0
  6. data/lib/config.rb +63 -0
  7. data/lib/core.rb +242 -0
  8. data/lib/cursor.rb +43 -0
  9. data/lib/def/animations/explosion1.anim +103 -0
  10. data/lib/def/characters.def +132 -0
  11. data/lib/def/de/dialogues/test.dlg +4 -0
  12. data/lib/def/de/enemies.trans +6 -0
  13. data/lib/def/de/items.trans +84 -0
  14. data/lib/def/de/skills.trans +48 -0
  15. data/lib/def/de/spells.trans +31 -0
  16. data/lib/def/en/dialogues/test.dlg +4 -0
  17. data/lib/def/en/enemies.trans +6 -0
  18. data/lib/def/en/items.trans +78 -0
  19. data/lib/def/en/skills.trans +48 -0
  20. data/lib/def/en/spells.trans +31 -0
  21. data/lib/def/enemies.def +8 -0
  22. data/lib/def/enemies/wolf.bhv +11 -0
  23. data/lib/def/init.def +5 -0
  24. data/lib/def/items.def +153 -0
  25. data/lib/def/loot.def +2 -0
  26. data/lib/def/particles.def +66 -0
  27. data/lib/def/recipies.def +18 -0
  28. data/lib/def/skills.def +40 -0
  29. data/lib/def/spells.def +42 -0
  30. data/lib/def/spells.rb +16 -0
  31. data/lib/def/weapons.def +9 -0
  32. data/lib/ext/astar/AMap.rb +146 -0
  33. data/lib/ext/astar/node.rb +72 -0
  34. data/lib/ext/astar/priority_queue.rb +44 -0
  35. data/lib/ext/shader.rb +116 -0
  36. data/lib/game/alchemy/recipe.rb +26 -0
  37. data/lib/game/character.rb +102 -0
  38. data/lib/game/combat/bar.rb +119 -0
  39. data/lib/game/combat/battle.rb +345 -0
  40. data/lib/game/combat/control.rb +18 -0
  41. data/lib/game/combat/gui.rb +190 -0
  42. data/lib/game/combat/gui/select_item.rb +11 -0
  43. data/lib/game/combat/gui/select_spell.rb +38 -0
  44. data/lib/game/constitution.rb +48 -0
  45. data/lib/game/equipment.rb +34 -0
  46. data/lib/game/inventory.rb +37 -0
  47. data/lib/game/item.rb +54 -0
  48. data/lib/game/magic.rb +33 -0
  49. data/lib/game/map/events.rb +29 -0
  50. data/lib/game/map/fog.rb +41 -0
  51. data/lib/game/map/map.rb +247 -0
  52. data/lib/game/map/map_animation.rb +26 -0
  53. data/lib/game/map/map_loader.rb +177 -0
  54. data/lib/game/map/map_object.rb +208 -0
  55. data/lib/game/map/map_particle.rb +27 -0
  56. data/lib/game/map/player.rb +78 -0
  57. data/lib/game/map/tile.rb +35 -0
  58. data/lib/game/mind.rb +24 -0
  59. data/lib/game/npc/behaviour.rb +45 -0
  60. data/lib/game/npc/bubble.rb +28 -0
  61. data/lib/game/npc/goal.rb +93 -0
  62. data/lib/game/npc/npc.rb +95 -0
  63. data/lib/game/npc/task.rb +73 -0
  64. data/lib/game/osd/magic.rb +24 -0
  65. data/lib/game/party.rb +42 -0
  66. data/lib/game/skills.rb +64 -0
  67. data/lib/game/spell.rb +35 -0
  68. data/lib/game_window.rb +95 -0
  69. data/lib/glsl/contrast.frag +12 -0
  70. data/lib/glsl/fade.frag +11 -0
  71. data/lib/glsl/mezzotint.frag +20 -0
  72. data/lib/glsl/noise.frag +20 -0
  73. data/lib/glsl/pixelate.frag +42 -0
  74. data/lib/glsl/radialblur.frag +28 -0
  75. data/lib/glsl/sepia.frag +15 -0
  76. data/lib/glsl/shockwave.frag +24 -0
  77. data/lib/glsl/tv_screen.frag +17 -0
  78. data/lib/graphics/animations/credits.txt +1 -0
  79. data/lib/graphics/animations/explosion2.png +0 -0
  80. data/lib/graphics/backgrounds/white_ties_grass.png +0 -0
  81. data/lib/graphics/chars/ejera.png +0 -0
  82. data/lib/graphics/chars/salyjea.png +0 -0
  83. data/lib/graphics/chars/tharat.png +0 -0
  84. data/lib/graphics/combat/tharat.png +0 -0
  85. data/lib/graphics/cursors/normal.png +0 -0
  86. data/lib/graphics/fog/clouds1.png +0 -0
  87. data/lib/graphics/gui/bar_center.png +0 -0
  88. data/lib/graphics/gui/bar_left.png +0 -0
  89. data/lib/graphics/gui/bar_right.png +0 -0
  90. data/lib/graphics/gui/button_background.png +0 -0
  91. data/lib/graphics/gui/button_close.png +0 -0
  92. data/lib/graphics/gui/button_close_hi.png +0 -0
  93. data/lib/graphics/gui/button_highlight.png +0 -0
  94. data/lib/graphics/gui/charequip_background.png +0 -0
  95. data/lib/graphics/gui/charselect_background.png +0 -0
  96. data/lib/graphics/gui/container_background.png +0 -0
  97. data/lib/graphics/gui/drop_item.png +0 -0
  98. data/lib/graphics/gui/equip_Etarae.png +0 -0
  99. data/lib/graphics/gui/equip_Mensch.png +0 -0
  100. data/lib/graphics/gui/equipslot_background.png +0 -0
  101. data/lib/graphics/gui/iteminfo_background.png +0 -0
  102. data/lib/graphics/gui/msg_background.png +0 -0
  103. data/lib/graphics/gui/scrollbar_background.png +0 -0
  104. data/lib/graphics/gui/scroller.png +0 -0
  105. data/lib/graphics/gui/tile_32.png +0 -0
  106. data/lib/graphics/gui/tile_32_highlight.png +0 -0
  107. data/lib/graphics/icons/items/arrow.png +0 -0
  108. data/lib/graphics/icons/items/bandage.png +0 -0
  109. data/lib/graphics/icons/items/boots_leather.png +0 -0
  110. data/lib/graphics/icons/items/bow.png +0 -0
  111. data/lib/graphics/icons/items/credits.txt +8 -0
  112. data/lib/graphics/icons/items/harness_leather.png +0 -0
  113. data/lib/graphics/icons/items/knife.png +0 -0
  114. data/lib/graphics/icons/items/shirt_linen.png +0 -0
  115. data/lib/graphics/items/none.png +0 -0
  116. data/lib/graphics/menu/ingame_background.png +0 -0
  117. data/lib/graphics/menu/ingame_background.xcf +0 -0
  118. data/lib/graphics/menu/start_background.png +0 -0
  119. data/lib/graphics/missing.png +0 -0
  120. data/lib/graphics/osd/magic_bg.png +0 -0
  121. data/lib/graphics/particles/leaf.png +0 -0
  122. data/lib/graphics/particles/smoke.png +0 -0
  123. data/lib/graphics/pixel.png +0 -0
  124. data/lib/graphics/tiles/test.png +0 -0
  125. data/lib/gui/base.rb +278 -0
  126. data/lib/gui/button.rb +93 -0
  127. data/lib/gui/char_equip.rb +118 -0
  128. data/lib/gui/char_selector.rb +54 -0
  129. data/lib/gui/context_menu.rb +115 -0
  130. data/lib/gui/draggable.rb +18 -0
  131. data/lib/gui/grid.rb +118 -0
  132. data/lib/gui/image.rb +17 -0
  133. data/lib/gui/inventory.rb +42 -0
  134. data/lib/gui/item_info.rb +33 -0
  135. data/lib/gui/slider.rb +10 -0
  136. data/lib/gui/textfield.rb +57 -0
  137. data/lib/layer.rb +64 -0
  138. data/lib/load.rb +31 -0
  139. data/lib/main.rb +18 -0
  140. data/lib/maps/def/test.bhv +26 -0
  141. data/lib/maps/def/test.rb +14 -0
  142. data/lib/maps/test.tmx +133 -0
  143. data/lib/maps/test2.tmx +94 -0
  144. data/lib/maps/test3.tmx +29 -0
  145. data/lib/maps/test3_lower.tmx +25 -0
  146. data/lib/maps/test3_upper.tmx +25 -0
  147. data/lib/maps/test_left.tmx +25 -0
  148. data/lib/maps/test_upper.tmx +25 -0
  149. data/lib/music/Butterfly Tea - A New Hope 2K11.mp3 +0 -0
  150. data/lib/music/Greendjohn - Rebirth.mp3 +0 -0
  151. data/lib/music/credits.txt +8 -0
  152. data/lib/parse.rb +605 -0
  153. data/lib/parse_tmx.rb +114 -0
  154. data/lib/particles.rb +127 -0
  155. data/lib/sample.rb +29 -0
  156. data/lib/save.rb +44 -0
  157. data/lib/song.rb +41 -0
  158. data/lib/sounds/click1.wav +0 -0
  159. data/lib/sounds/credits.txt +2 -0
  160. data/lib/sounds/error1.wav +0 -0
  161. data/lib/sprite.rb +35 -0
  162. data/lib/states/menus.rb +17 -0
  163. data/lib/states/menus/alchemy.rb +53 -0
  164. data/lib/states/menus/equip.rb +79 -0
  165. data/lib/states/menus/ingame.rb +34 -0
  166. data/lib/states/menus/magic.rb +31 -0
  167. data/lib/states/menus/options.rb +54 -0
  168. data/lib/states/menus/start.rb +38 -0
  169. data/lib/states/states.rb +154 -0
  170. data/lib/tileset.rb +42 -0
  171. data/lib/tools/world.rb +103 -0
  172. data/lib/tools/worldmap_editor.rb +221 -0
  173. data/lib/translate.rb +368 -0
  174. metadata +255 -0
@@ -0,0 +1,93 @@
1
+
2
+ module Core::GUI
3
+ # Button to be used in menus.
4
+ # Executes the given lambda when clicked
5
+ class Button < Element
6
+ attr_accessor :background, :proc
7
+ @@sound = Core::Sample.new("click1")
8
+ @@error = Core::Sample.new("error1")
9
+ def initialize(x, y, w, h, text, proc, bg=true, align=:center, text_height=h)
10
+ super(x, y, w, h)
11
+ if bg
12
+ @bg = Core.sprite("gui/button_background")
13
+ end
14
+ @hi = Core.sprite("gui/button_highlight", true)
15
+ @font = Core.font(Core::DEFAULT_FONT, text_height)
16
+ @text = text
17
+ @proc = proc
18
+ @selected = false
19
+ @background = bg
20
+ @align = align
21
+ @enabled = true
22
+ @fw = @font.text_width(@text)
23
+ end
24
+ def hovered?
25
+ return @selected
26
+ end
27
+ def toggle
28
+ @enabled = !@enabled
29
+ end
30
+ def disable
31
+ @enabled = false
32
+ end
33
+ def enable
34
+ @enabled = true
35
+ end
36
+ def update
37
+ @selected = Core.inside?(Core.window.mouse_x, Core.window.mouse_y, @x+@xoff, @y+@yoff, @x+@w+@xoff, @y+@h+@yoff)
38
+ if @selected and Core.window.pressed?(Gosu::MsLeft)
39
+ if @enabled
40
+ @@sound.play(0.25)
41
+ @proc.call
42
+ else
43
+ @@error.play
44
+ end
45
+ end
46
+ end
47
+ def draw
48
+ case @align
49
+ when :center
50
+ @font.draw(@text, @x + @xoff + (@w/2) - (@fw/2), @y + @yoff + (@h/9), Core::GUI_Z + 10 + @zoff, 1, 1, Gosu::Color::BLACK)
51
+ when :left
52
+ @font.draw(@text, @x + @xoff + 4, @y + @yoff + (@h/9), Core::GUI_Z + 10 + @zoff, 1, 1, Gosu::Color::BLACK)
53
+ when :right
54
+ @font.draw(@text, @x + @xoff + (@w-@fw), @y + @yoff + (@h/9), Core::GUI_Z + 10 + @zoff, 1, 1, Gosu::Color::BLACK)
55
+ end
56
+ if @background
57
+ color = Gosu::Color.new(255, 255, 255, 255)
58
+ if !@enabled
59
+ color.saturation = 125
60
+ end
61
+ @bg.draw(@x + @xoff, @y + @yoff, Core::GUI_Z + 9 + @zoff, @w/@bg.width.to_f, @h/@bg.height.to_f, color)
62
+ end
63
+ if @selected and @enabled
64
+ @hi.draw(@x + @xoff, @y + @yoff, Core::GUI_Z + 11 + @zoff, @w/@hi.width.to_f, @h/@hi.height.to_f, 0xff999999, :additive)
65
+ end
66
+ end
67
+ end
68
+
69
+ # Same as Button, but draws an image instead of text
70
+ class ImageButton < Button
71
+ attr_reader :bg
72
+ def initialize(x, y, file, proc, w=-1, h=-1)
73
+ @bg = Core.sprite(file.to_s)
74
+ if w < 0
75
+ @w = w = @bg.width
76
+ end
77
+ if h < 0
78
+ @h = h = @bg.height
79
+ end
80
+ super(x, y, w, h, "", proc, false)
81
+ end
82
+ def draw
83
+ color = Gosu::Color.new(255, 255, 255, 255)
84
+ if !@enabled
85
+ color.saturation = 125
86
+ end
87
+ @bg.draw(@x+@xoff, @y+@yoff, Core::GUI_Z + 10 + @zoff, @w/@bg.width.to_f, @h/@bg.height.to_f, color)
88
+ if @selected and @enabled
89
+ @hi.draw(@x+@xoff, @y+@yoff, Core::GUI_Z + 11 + @zoff, @w/@hi.width.to_f, @h/@hi.height.to_f, 0xff999999, :additive)
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,118 @@
1
+
2
+ module Core::GUI
3
+
4
+ class CharEquip < Element
5
+ attr_reader :slot
6
+ @@positions = {
7
+ :head => [144, 72],
8
+ :torso => [144, 160],
9
+ :rarm => [80, 256],
10
+ :larm => [208, 256],
11
+ :legs => [144, 320],
12
+ :feet => [144, 416],
13
+ :back => [208, 96],
14
+ }
15
+ def initialize(x, y, c)
16
+ super(x, y, 320, 512)
17
+ @bg = Core.sprite("gui/charequip_background")
18
+ @body = Core.sprite("gui/equip_#{c.race}")
19
+ @font = Core.font(Core::DEFAULT_FONT, 24)
20
+ @equipped = {}
21
+ reset_slots
22
+ @char = c
23
+ @equip = false
24
+ @changed = false
25
+ setup_equipment
26
+ end
27
+ def char=(c)
28
+ @char = c
29
+ @body = Core.sprite("gui/equip_#{c.race}")
30
+ setup_equipment
31
+ end
32
+ def reset_slots
33
+ @slots = {}
34
+ @colors = {}
35
+ @@positions.each { |loc, pos|
36
+ @slots.store(loc, ImageButton.new(@x+pos[0], @y+pos[1], "gui/equipslot_background", lambda {}))
37
+ }
38
+ @slots.each { |k, v|
39
+ @colors.store(v, Gosu::Color.new(255, 255, 255, 255))
40
+ }
41
+ end
42
+ def highlight_slots(ary)
43
+ @colors = {}
44
+ red = @slots
45
+ green = {}
46
+ ary.each { |loc|
47
+ green.store(loc, red[loc])
48
+ green[loc].proc = lambda { equip(loc) }
49
+ red.delete(loc)
50
+ }
51
+ red.each_value { |img|
52
+ color = Gosu::Color.new(255, 255, 0, 0)
53
+ @colors.store(img, color)
54
+ }
55
+ green.each_value { |img|
56
+ color = Gosu::Color.new(255, 0, 255, 0)
57
+ @colors.store(img, color)
58
+ }
59
+ @slots = red.merge(green)
60
+ end
61
+ def setup_equipment
62
+ equip = @char.equipment
63
+ @equipped = {}
64
+ equip.each { |loc, item|
65
+ if item
66
+ @equipped.store(loc, ImageButton.new(@x+@@positions[loc][0], @y+@@positions[loc][1], "#{item.icon_file}", lambda { unequip(loc) }, 32, 32))
67
+ end
68
+ }
69
+ end
70
+ def equip(location)
71
+ @equip = true
72
+ @slot = location
73
+ end
74
+ def equip?
75
+ if @equip
76
+ @equip = false
77
+ return true
78
+ else
79
+ return false
80
+ end
81
+ end
82
+ def unequip(location)
83
+ # TODO weight/capacity check
84
+ @char.inventory.add(@char.equipment.remove_at(location))
85
+ setup_equipment
86
+ @changed = true
87
+ end
88
+ def update
89
+ super
90
+ @equipped.each_value { |el|
91
+ el.update
92
+ }
93
+ @slots.each_value { |but|
94
+ but.update
95
+ }
96
+ end
97
+ def draw
98
+ super
99
+ @bg.draw(@x, @y, Core::GUI_Z + 5, @w/@bg.width.to_f, @h/@bg.height.to_f)
100
+ @body.draw(@x+32, @y+32, Core::GUI_Z + 6, (@w-64)/@body.width.to_f, (@h-64)/@body.height.to_f)
101
+ @slots.each_value { |but|
102
+ but.bg.draw(but.x, but.y, Core::GUI_Z + 10, 1, 1, @colors[but])
103
+ }
104
+ @equipped.each_value { |el|
105
+ el.draw
106
+ }
107
+ end
108
+ def changed?
109
+ if @changed
110
+ @changed = false
111
+ return true
112
+ else
113
+ return false
114
+ end
115
+ end
116
+ end
117
+
118
+ end
@@ -0,0 +1,54 @@
1
+
2
+ require_relative "base.rb"
3
+
4
+ module Core::GUI
5
+
6
+ class CharSelector < Element
7
+ attr_reader :index
8
+ def initialize(x, y, party, w=256, h=32)
9
+ super(x, y, w, h)
10
+ @index = 0
11
+ @changed = false
12
+ @party = party
13
+ @background = Core.sprite("gui/charselect_background")
14
+ @font = Core.font(Core::DEFAULT_FONT, 24)
15
+ @left = Button.new(x, y, 32, 32, "<", lambda {left}, false)
16
+ @right = Button.new(x+w-32, y, 32, 32, ">", lambda {right}, false)
17
+ end
18
+ def update
19
+ @left.xoff = @right.xoff = @xoff
20
+ @left.yoff = @right.yoff = @yoff
21
+ @left.update
22
+ @right.update
23
+ end
24
+ def left
25
+ @index -= 1
26
+ if @index < 0
27
+ @index = @party.members.size-1
28
+ end
29
+ @changed = true
30
+ end
31
+ def right
32
+ @index += 1
33
+ if @index >= @party.members.size
34
+ @index = 0
35
+ end
36
+ @changed = true
37
+ end
38
+ def changed?
39
+ if @changed
40
+ @changed = false
41
+ return true
42
+ else
43
+ return false
44
+ end
45
+ end
46
+ def draw
47
+ @background.draw(@x+@xoff, @y+@yoff, Core::GUI_Z + 9, @w/@background.width, @h/@background.height)
48
+ @font.draw(@party.members[@index].name, @x+@xoff+(@w/2)-(@font.text_width(@party.members[@index].name)/2), @y+@yoff+(@h/6), Core::GUI_Z + 10, 1, 1, Gosu::Color::BLACK)
49
+ @left.draw
50
+ @right.draw
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,115 @@
1
+
2
+ module Core::GUI
3
+
4
+ # Small menu available by rightclicking on the map
5
+ class ContextMenu < Element
6
+ def initialize(x, y, obj=nil)
7
+ super(x, y, 128, items(obj) * 24)
8
+ @zoff = 10000
9
+ if @x + @w > 1024
10
+ @x = 1024 - @w
11
+ end
12
+ @buttons = {}
13
+ setup_defaults(obj)
14
+ @buttons.each_value { |but|
15
+ but.zoff = @zoff
16
+ }
17
+ end
18
+ def update
19
+ super
20
+ @buttons.each_value { |but|
21
+ but.update
22
+ }
23
+ end
24
+ def draw
25
+ @buttons.each_value { |but|
26
+ but.draw
27
+ }
28
+ end
29
+
30
+ private
31
+
32
+ def items(obj)
33
+ if obj
34
+ return 3
35
+ else
36
+ return 2
37
+ end
38
+ end
39
+
40
+ def in_window?
41
+ Core.window.state.osd.each_value { |w|
42
+ if Core.inside?(@x, @y, w.x, w.y, w.x+w.w, w.y+w.h)
43
+ return true
44
+ end
45
+ }
46
+ return false
47
+ end
48
+
49
+ def magic_window(p)
50
+ Core.window.state.osd.store(:magic, Core::Game::OSD::Magic.new(@x-320, @y-240, p, p));
51
+ end
52
+
53
+ def setup_defaults(obj)
54
+ if in_window?
55
+ return
56
+ end
57
+ npc = player = false
58
+ if obj
59
+ if obj.class == Core::Game::MapNPC
60
+ label = obj.gamename
61
+ npc = true
62
+ elsif obj.class == Core::Game::Player
63
+ player = true
64
+ label = Core::Trans.menu(:you)
65
+ else
66
+ label = obj.name
67
+ end
68
+ else
69
+ label = Core::Trans.menu(:ground)
70
+ end
71
+
72
+ p = Core.window.state.player
73
+
74
+ @buttons.store(:label, Textfield.new(@x, @y, @w, 24, label, 24))
75
+
76
+ x = @x - Core.window.state.map.xoff
77
+ y = @y - Core.window.state.map.yoff
78
+
79
+ if !player
80
+ if npc
81
+ @buttons.store(:talk_to,
82
+ Button.new(@x, @y+(@buttons.size*24), @w, 24, Core::Trans.menu(:talk_to),
83
+ lambda { puts("STUB: talk_to"); p.find_path_to(x.to_i/32, (y.to_i/32) - (p.y < obj.y ? 1 : -1)); @remove = true }, true, :left))
84
+ else
85
+ @buttons.store(:move,
86
+ Button.new(@x, @y+(@buttons.size*24), @w, 24, Core::Trans.menu(:walk_here),
87
+ lambda { p.find_path_to(x.to_i/32, y.to_i/32); @remove = true }, true, :left))
88
+ if !Core.window.state.map.current.passable?(x, y) or (obj and !obj.through)
89
+ # TODO left/right
90
+ if !obj
91
+ obj = [x, y] # i <3 ruby
92
+ end
93
+ # a* cant find a path to a blocked tile, so shift the position away a bit
94
+ @buttons[:move].proc = lambda { p.find_path_to(x.to_i/32, (y.to_i/32) - (p.y < obj.y ? 1 : -1)); @remove = true }
95
+ # TODO check again if it works, the player *must* move
96
+ end
97
+ end
98
+ end
99
+ if !Core.window.state.osd.has_key?(:magic)
100
+ @buttons.store(:magic,
101
+ Button.new(@x, @y+(@buttons.size*24), @w, 24, Core::Trans.menu(:magic),
102
+ lambda { magic_window(p); @remove = true}, true, :left))
103
+ if npc
104
+ @buttons[:magic].proc = lambda { puts("STUB: othermagic"); @remove = true }
105
+ end
106
+ end
107
+ if $DEBUG and obj
108
+ @buttons.store(:debug_inspect,
109
+ Button.new(@x, @y+(@buttons.size*24), @w, 24, "inspect", lambda { awesome_print(obj); @remove = true }, true, :left))
110
+ end
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,18 @@
1
+
2
+ module Core::GUI
3
+
4
+ class Draggable < Element
5
+ def initialize(x, y, w, h, type, sprite)
6
+ super(x, y, w, h)
7
+ @type = type
8
+ @sprite = sprite
9
+ end
10
+ def update(window)
11
+ super
12
+ end
13
+ def draw
14
+ @sprite.img.draw(@x, @y, Core::GUI_Z + 20, @w/@sprite.width, @h/@sprite.height)
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,118 @@
1
+
2
+ module Core::GUI
3
+
4
+ # Allows EH::GUI::Elements to be placed into a 32x32 px grid.
5
+ # Elements can be selected and dragged
6
+ class Grid < Element
7
+
8
+ attr_reader :selected
9
+
10
+ def initialize(x, y, tx, ty, in_classes=[])
11
+ super(x, y, tx*32, ty*32)
12
+ @classes = in_classes
13
+ @grid = Array.new(tx) { Array.new(ty) }
14
+ @bg = Core.sprite("gui/container_background")
15
+ @tile = Core.sprite("gui/tile_32")
16
+ @hl = Core.sprite("gui/tile_32_highlight")
17
+ @selected = nil
18
+ @highlight = nil
19
+ @hovered = nil
20
+ end
21
+
22
+ def update
23
+ if Core.mouse_inside?(@x+@xoff, @y+@yoff, @x+@xoff+@w, @y+@yoff+@h)
24
+ if Core.window.pressed?(Gosu::MsLeft)
25
+ @highlight = mouse_to_tile(Core.window.mouse_x, Core.window.mouse_y)
26
+ @selected = get_at(@highlight.x, @highlight.y)
27
+ else
28
+ @hovered = mouse_to_tile(Core.window.mouse_x, Core.window.mouse_y)
29
+ end
30
+ else
31
+ @hovered = nil
32
+ if Core.window.button_down?(Gosu::MsLeft)
33
+ @selected = nil
34
+ @highlight = nil
35
+ end
36
+ end
37
+ end
38
+
39
+ def draw
40
+ x = @x + @xoff
41
+ y = @y + @yoff
42
+ @bg.draw(x, y, Core::GUI_Z + @zoff, @w/@bg.width.to_f, @h/@bg.height.to_f)
43
+ @grid.each { |col|
44
+ col.each { |tile|
45
+ tile.icon.draw(x, y, Core::GUI_Z + @zoff + 1) if tile
46
+ @tile.draw(x, y, Core::GUI_Z + @zoff + 1)
47
+ y += 32
48
+ }
49
+ x += 32
50
+ y = @y + @yoff
51
+ }
52
+ if @selected and @highlight
53
+ @hl.draw(@x+@xoff+@highlight.x*32, @y+@yoff+@highlight.y*32, Core::GUI_Z + @zoff + 2)
54
+ end
55
+ if @hovered and (!@highlight or !(@hovered.x == @highlight.x and @hovered.y == @highlight.y))
56
+ @hl.draw(@x+@xoff+@hovered.x*32, @y+@yoff+@hovered.y*32, Core::GUI_Z + @zoff + 2)
57
+ end
58
+ end
59
+
60
+ # Adds obj to the grid at the next free position
61
+ # Returns the position where obj was inserted
62
+ def add(obj)
63
+ if @classes.include?(obj.class)
64
+ x = 0
65
+ @grid.each { |col|
66
+ y = 0
67
+ col.each { |tile|
68
+ if tile == nil
69
+ @grid[x][y] = obj
70
+ return [x, y]
71
+ end
72
+ y += 1
73
+ }
74
+ x += 1
75
+ }
76
+ end
77
+ return [0, 0]
78
+ end
79
+
80
+ # Adds obj at the given position, overwriting any other value
81
+ # Calls add() if the given position is invalid
82
+ def add_at(obj, tx, ty)
83
+ if @classes.include?(obj.class)
84
+ @grid[tx][ty] = obj
85
+ end
86
+ rescue NoMethodError
87
+ warn("WARNING: Tried to insert element at invalid index (#{obj}, #{tx}|#{ty})")
88
+ add(obj)
89
+ end
90
+
91
+ def get_at(tx, ty)
92
+ return @grid[tx][ty]
93
+ rescue NoMethodError
94
+ return nil
95
+ end
96
+
97
+ def mouse_to_tile(mx, my)
98
+ x = (mx - @x - @xoff).to_i / 32
99
+ y = (my - @y - @yoff).to_i / 32
100
+ return [x, y]
101
+ end
102
+
103
+ def empty?
104
+ @grid.each { |col|
105
+ col.each { |tile|
106
+ return false if tile
107
+ }
108
+ }
109
+ return true
110
+ end
111
+
112
+ def clear
113
+ @grid = Array.new(@w/32) { Array.new(@h/32) }
114
+ end
115
+
116
+ end
117
+
118
+ end