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,40 @@
1
+
2
+ {
3
+ name = healing
4
+ icon = "skills/healing"
5
+ }
6
+
7
+ {
8
+ name = crafting
9
+ icon = "skills/crafting"
10
+ }
11
+
12
+ {
13
+ name = botany
14
+ icon = "skills/botany"
15
+ }
16
+
17
+ {
18
+ name = healing_magic
19
+ icon = "skills/healing_magic"
20
+ }
21
+
22
+ {
23
+ name = mind
24
+ icon = "skills/mind"
25
+ }
26
+
27
+ {
28
+ name = elemental
29
+ icon = "skills/elemental"
30
+ }
31
+
32
+ {
33
+ name = ranged
34
+ icon = "skills/ranged"
35
+ }
36
+
37
+ {
38
+ name = melee
39
+ icon = "skills/melee"
40
+ }
@@ -0,0 +1,42 @@
1
+
2
+ # Healing
3
+
4
+ {
5
+ name = stop_bleed
6
+ icon = "spells/stop_bleed"
7
+ type = healing
8
+ cost = 2
9
+ }
10
+
11
+ # Mind
12
+
13
+ {
14
+ name = protect
15
+ icon = "spells/protect"
16
+ type = mind
17
+ cost = 1
18
+ }
19
+
20
+ # Elemental
21
+
22
+ {
23
+ name = heat
24
+ icon = "spells/heat"
25
+ type = elemental
26
+ cost = 10
27
+ }
28
+
29
+ {
30
+ name = cold
31
+ icon = "spells/cold"
32
+ type = elemental
33
+ cost = 10
34
+ }
35
+
36
+ #EOF
37
+ {
38
+ name =
39
+ icon = "spells/"
40
+ type =
41
+ cost =
42
+ }
@@ -0,0 +1,16 @@
1
+
2
+ module Core::Game::Spells
3
+
4
+ def self.stop_bleed
5
+ puts("stop_bleed")
6
+ end
7
+
8
+ def self.heat
9
+ puts("heat")
10
+ end
11
+
12
+ def self.cold
13
+ puts("cold")
14
+ end
15
+
16
+ end
@@ -0,0 +1,9 @@
1
+
2
+ # Only used for weapons which do not have an item
3
+
4
+ claw
5
+ {
6
+ icon = "claw"
7
+ type = melee
8
+ effects = [damage, bleed_rare]
9
+ }
@@ -0,0 +1,146 @@
1
+ #AStar Map
2
+ #by Marcin Coles
3
+ #27/Sep/2007
4
+ require_relative 'priority_queue.rb'
5
+ require_relative 'node.rb'
6
+
7
+ module AStar
8
+
9
+ class AMap
10
+ attr_reader :nodes
11
+ def initialize(costmap)
12
+ #cost map is a 2D array - eg a 2x2 map is AMap.new([[3,5],[3,2]])
13
+ # the values are the movement cost for the node at those co-ordinates
14
+ #should do some error checking for size of the map, but anyway
15
+ # note that the costmap array is indexed @costmap[y][x],
16
+ # which is the opposite way to Node(x,y)
17
+ ##note that it's probably easier to use AMap.load(file)
18
+ @costmap=costmap
19
+ @height=costmap.size
20
+ @width=costmap.first.size
21
+ @nodes=[]
22
+ @output="\n"
23
+ costmap.each_index do |row|
24
+ costmap[row].each_index do |col|
25
+ @nodes.push(Node.new(col,row,costmap[row][col]))
26
+ @output<<"|#{costmap[row][col]}"
27
+ end
28
+ @output<<"|\n"
29
+ end
30
+ end
31
+
32
+ def self.load(filename)
33
+ #loads a map from a text file - see map.txt for example, reproduced here
34
+ #~ 1,1,1,1,1,1
35
+ #~ 1,2,2,2,2,1
36
+ #~ 1,3,3,3,3,1
37
+ #~ 1,3,3,3,3,1
38
+ #~ 1,2,2,2,2,1
39
+ #~ 1,1,1,1,1,1
40
+ mmap=[]
41
+ File.open(filename) do |f|
42
+ f.each_line do |line|
43
+ linearr=[]
44
+ line.chomp.split(',').each do |e|
45
+ linearr.push(e.to_i)
46
+ end
47
+ mmap.push(linearr)
48
+ end
49
+ end
50
+ return AMap.new(mmap)
51
+ end
52
+
53
+ def generate_successor_nodes(anode)
54
+ # determine nodes bordering this one - only North,S,E,W for now
55
+ # no boundary condition check, eg if anode.x==-4
56
+ # considers a wall to be a 0 so therefore not allow that to be a neighbour
57
+ north=@costmap[anode.y-1][(anode.x)] unless (anode.y-1)<0 #boundary check for -1
58
+ south=@costmap[anode.y+1][(anode.x)] unless (anode.y+1)>(@height-1)
59
+ east=@costmap[anode.y][(anode.x+1)] unless (anode.x+1)>(@width-1)
60
+ west=@costmap[anode.y][(anode.x-1)] unless (anode.x-1)<0 #boundary check for -1
61
+
62
+ if (west && west>0) then # not on left edge, so provide a left-bordering node
63
+ newnode=Node.new((anode.x-1),anode.y,@costmap[anode.y][(anode.x-1)])
64
+ yield newnode
65
+ end
66
+ if (east && east>0) then # not on right edge, so provide a right-bordering node
67
+ newnode=Node.new((anode.x+1),anode.y,@costmap[anode.y][(anode.x+1)])
68
+ yield newnode
69
+ end
70
+ if (north && north>0) then # not on left edge, so provide a left-bordering node
71
+ newnode=Node.new(anode.x,(anode.y-1),@costmap[(anode.y-1)][anode.x])
72
+ yield newnode
73
+ end
74
+ if (south && south>0) then # not on right edge, so provide a right-bordering node
75
+ newnode=Node.new(anode.x,(anode.y+1),@costmap[(anode.y+1)][anode.x])
76
+ yield newnode
77
+ end
78
+ end
79
+
80
+ def astar(node_start,node_goal)
81
+ iterations=0
82
+ open=PriorityQueue.new()
83
+ closed=PriorityQueue.new()
84
+ node_start.calc_h(node_goal)
85
+ open.push(node_start)
86
+ while !open.empty? do
87
+ iterations+=1 #keep track of how many times this itersates
88
+ node_current=open.find_best
89
+ if node_current==node_goal then #found the solution
90
+ puts "Iterations: #{iterations}"
91
+ return node_current
92
+ end
93
+ generate_successor_nodes(node_current) do |node_successor|
94
+ #now doing for each successor node of node_current
95
+ node_successor.calc_g(node_current)
96
+ #skip to next node_successor if better one already on open or closed list
97
+ if open_successor=open.find(node_successor) then
98
+ if open_successor<=node_successor then next end #need to account for nil result
99
+ end
100
+ if closed_successor=closed.find(node_successor) then
101
+ if closed_successor<=node_successor then next end
102
+ end
103
+ #still here, then there's no better node yet, so remove any copies of this node on open/closed lists
104
+ open.remove(node_successor)
105
+ closed.remove(node_successor)
106
+ # set the parent node of node_successor to node_current
107
+ node_successor.parent=node_current
108
+ # set h to be the estimated distance to node_goal using the heuristic
109
+ node_successor.calc_h(node_goal)
110
+ # so now we know this is the best copy of the node so far, so put it onto the open list
111
+ open.push(node_successor)
112
+ end
113
+ #now we've gone through all the successors, so the current node can be closed
114
+ closed.push(node_current)
115
+ end
116
+ end
117
+
118
+ def co_ord(x,y)
119
+ a=Node.new(x,y)
120
+ @nodes.find {|n| n==a}
121
+ end
122
+
123
+ def to_s
124
+ @output
125
+ end
126
+
127
+ def show_path(anode)
128
+ #shows the path back from node 'anode' by following the parent pointer
129
+ curr=anode
130
+ pathmap=@costmap.clone
131
+ while curr.parent do
132
+ pathmap[curr.y][curr.x]='*'
133
+ curr=curr.parent
134
+ end
135
+ pathmap[curr.y][curr.x]='*'
136
+ pathstr="\n"
137
+ pathmap.each_index do |row|
138
+ pathmap[row].each_index do |col|
139
+ pathstr<<"|#{pathmap[row][col]}"
140
+ end
141
+ pathstr<<"|\n"
142
+ end
143
+ pathstr
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,72 @@
1
+ #AStar map Node
2
+ #by Marcin Coles
3
+ #27/Sep/2007
4
+ module AStar
5
+
6
+ class Node
7
+ #class Node provides a node on a map which can be used for pathfinding.
8
+ #For Node to work with PriorityQueue and AMap it needs to implement the following
9
+ # <= used for comparing g values
10
+ # == used for finding the same node - using the x,y co-ordinates
11
+ attr_accessor :parent
12
+ attr_reader :x,:y,:g,:h,:m
13
+
14
+ def initialize(x,y,move_cost=0)
15
+ @x,@y,@m=x,y,move_cost
16
+ @g=@m
17
+ @h=0
18
+ end
19
+
20
+ def to_s
21
+ #prints the node in the following format [x,y] f:g:h
22
+ "[#{@x},#{@y}] #{@g+@h}:#{@g}:#{@h}"
23
+ end
24
+
25
+ def <=>(other)
26
+ #can be used for ordering the priority list
27
+ #puts "using <=>" #currently unused - can delete this line if required
28
+ self.f<=>other.f
29
+ end
30
+
31
+ def <=(other)
32
+ #used for comparing cost so far
33
+ @g<=other.g
34
+ end
35
+
36
+ def ==(other)
37
+ # nodes are == if x and y are the same - used for finding and removing same node
38
+ return false if other==nil
39
+ return (@x==other.x)&(@y==other.y)
40
+ end
41
+
42
+ def calc_g(previous)
43
+ #cost so far is total cost of previous step plus the movement cost of this one
44
+ @g=previous.g+@m
45
+ end
46
+
47
+ def calc_h(goal)
48
+ #using manhattan distance to generate a heuristic value
49
+ @h=(@x-goal.x).abs+(@y-goal.y).abs
50
+ end
51
+ def f
52
+ @g+@h
53
+ end
54
+ def better?(other,tbmul=1.01)
55
+ #which is better, self or other
56
+ #can pass a tie-breaker multiplier (tbmul) if required
57
+ if other==nil then return false end
58
+ if self==other then return false end
59
+ if f<other.f then
60
+ return true
61
+ #here's the tie-breaker
62
+ elsif f==other.f then
63
+ nf=@g+tbmul*@h
64
+ bf=other.g+tbmul*other.h
65
+ if nf<bf then return true end
66
+ end
67
+ false
68
+ end
69
+
70
+ end
71
+ end
72
+
@@ -0,0 +1,44 @@
1
+ #AStar PriorityQueue
2
+ #by Marcin Coles
3
+ #27/Sep/2007
4
+ #note - not really a priority queue at this point
5
+
6
+ require_relative "node.rb"
7
+
8
+ module AStar
9
+
10
+ class PriorityQueue
11
+ def initialize(nodes=[])
12
+ @nodes=nodes
13
+ #tie-breaker multiplier (tbmul) is 1+1/(the sqrt of the map size)
14
+ @tbmul=1+1/(Math.sqrt(@nodes.size))
15
+ end
16
+ def method_missing(methodname, *args)
17
+ #if in doubt, act like an array
18
+ @nodes.send(methodname, *args)
19
+ end
20
+ def find_best
21
+ #finds the best node, then pops it out
22
+ best=@nodes.first
23
+ @nodes.each do |node|
24
+ if node.better?(best,@tbmul) then best=node end
25
+ end
26
+ remove(best)
27
+ end
28
+ def find(node)
29
+ #finds a node - requires that node implements ==
30
+ @nodes.find {|x| x==node }
31
+ end
32
+
33
+ def remove(node)
34
+ #removes a node
35
+ @nodes.delete(find(node))
36
+ end
37
+
38
+ def to_s
39
+ output=""
40
+ @nodes.each {|e| output<<"#{e};"}
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,116 @@
1
+
2
+ class Shader
3
+ include Gl
4
+
5
+ attr_reader :window, :shader_filename
6
+ attr_reader :program_id, :vertex_shader_id, :fragment_shader_id
7
+
8
+ @@canvas_texture_id = nil
9
+
10
+ def initialize(window, shader_filename)
11
+ @window = window
12
+ @shader_filename = shader_filename
13
+
14
+ @program_id = nil
15
+ @vertex_shader_id = nil
16
+ @fragment_shader_id = nil
17
+
18
+ create_canvas unless @@canvas_texture_id
19
+ compile
20
+ end
21
+
22
+ def apply
23
+ @window.gl do
24
+ # copy frame buffer to canvas texture
25
+ glBindTexture(GL_TEXTURE_2D, @@canvas_texture_id)
26
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, @window.width, @window.height, 0)
27
+
28
+ # apply shader
29
+ glUseProgram(@program_id)
30
+
31
+ # clear screen
32
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
33
+ glColor4f(1.0, 1.0, 1.0, 1.0)
34
+ glMatrixMode(GL_PROJECTION)
35
+ glPushMatrix
36
+ glLoadIdentity
37
+ glViewport(0, 0, @window.width, @window.height)
38
+ glOrtho(0, @window.width, @window.height, 0, -1, 1)
39
+
40
+ # draw processed canvas texture over the screen
41
+ glBindTexture(GL_TEXTURE_2D, @@canvas_texture_id)
42
+
43
+ glBegin(GL_QUADS)
44
+ glTexCoord2f(0.0, 1.0); glVertex2f(0.0, 0.0)
45
+ glTexCoord2f(1.0, 1.0); glVertex2f(@window.width, 0.0)
46
+ glTexCoord2f(1.0, 0.0); glVertex2f(@window.width, @window.height)
47
+ glTexCoord2f(0.0, 0.0); glVertex2f(0.0, @window.height)
48
+ glEnd
49
+
50
+ # done, disable shader
51
+ glUseProgram(0)
52
+
53
+ # and out
54
+ glPopMatrix
55
+ end
56
+ end
57
+
58
+ def uniform(name, value)
59
+ glUseProgram(@program_id)
60
+ if value.is_a?(Float)
61
+ glUniform1f(glGetUniformLocation(@program_id, name), value)
62
+ elsif value.is_a?(Integer)
63
+ glUniform1i(glGetUniformLocation(@program_id, name), value)
64
+ else
65
+ raise ArgumentError, "Uniform data type not supported"
66
+ end
67
+ glUseProgram(0)
68
+ end
69
+
70
+ alias []= uniform
71
+
72
+ private
73
+
74
+ def create_canvas
75
+ @@canvas_texture_id = glGenTextures(1).first
76
+ glBindTexture(GL_TEXTURE_2D, @@canvas_texture_id)
77
+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 1)
78
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
79
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
80
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, @window.width, @window.height, 0, GL_RGB, GL_UNSIGNED_BYTE, "\0" * @window.width * @window.height * 3)
81
+ return @@canvas_texture_id
82
+ end
83
+
84
+ def compile
85
+ # create program
86
+ @program_id = glCreateProgram
87
+
88
+ # create vertex shader
89
+ @vertex_shader_id = glCreateShader(GL_VERTEX_SHADER)
90
+ puts("INFO: Compiling vertex shader (#{@shader_filename})")
91
+ if File.exist?(@shader_filename + ".vert")
92
+ glShaderSource(@vertex_shader_id, File.read(@shader_filename + ".vert"))
93
+ else
94
+ glShaderSource(@vertex_shader_id, "void main(void)\r\n{\r\ngl_Position = ftransform();\r\ngl_TexCoord[0] = gl_MultiTexCoord0;\r\n}\r\n")
95
+ end
96
+ glCompileShader(@vertex_shader_id)
97
+ glAttachShader(@program_id, @vertex_shader_id)
98
+
99
+ # create fragment shader
100
+ @fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER)
101
+ puts("INFO: Compiling fragment shader (#{@shader_filename})")
102
+ glShaderSource(@fragment_shader_id, File.read(@shader_filename + ".frag"))
103
+ glCompileShader(@fragment_shader_id)
104
+ glAttachShader(@program_id, @fragment_shader_id)
105
+
106
+ # compile program
107
+ glLinkProgram(@program_id)
108
+
109
+ # check for compile errors
110
+ unless glGetProgramiv(@program_id, GL_LINK_STATUS) == GL_TRUE
111
+ raise glGetProgramInfoLog(@program_id).chomp
112
+ end
113
+
114
+ return @program_id
115
+ end
116
+ end