essytas 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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