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.
- data/LICENSE +19 -0
- data/README +3 -0
- data/Rakefile +44 -0
- data/bin/essytas +2 -0
- data/lib/animation.rb +74 -0
- data/lib/config.rb +63 -0
- data/lib/core.rb +242 -0
- data/lib/cursor.rb +43 -0
- data/lib/def/animations/explosion1.anim +103 -0
- data/lib/def/characters.def +132 -0
- data/lib/def/de/dialogues/test.dlg +4 -0
- data/lib/def/de/enemies.trans +6 -0
- data/lib/def/de/items.trans +84 -0
- data/lib/def/de/skills.trans +48 -0
- data/lib/def/de/spells.trans +31 -0
- data/lib/def/en/dialogues/test.dlg +4 -0
- data/lib/def/en/enemies.trans +6 -0
- data/lib/def/en/items.trans +78 -0
- data/lib/def/en/skills.trans +48 -0
- data/lib/def/en/spells.trans +31 -0
- data/lib/def/enemies.def +8 -0
- data/lib/def/enemies/wolf.bhv +11 -0
- data/lib/def/init.def +5 -0
- data/lib/def/items.def +153 -0
- data/lib/def/loot.def +2 -0
- data/lib/def/particles.def +66 -0
- data/lib/def/recipies.def +18 -0
- data/lib/def/skills.def +40 -0
- data/lib/def/spells.def +42 -0
- data/lib/def/spells.rb +16 -0
- data/lib/def/weapons.def +9 -0
- data/lib/ext/astar/AMap.rb +146 -0
- data/lib/ext/astar/node.rb +72 -0
- data/lib/ext/astar/priority_queue.rb +44 -0
- data/lib/ext/shader.rb +116 -0
- data/lib/game/alchemy/recipe.rb +26 -0
- data/lib/game/character.rb +102 -0
- data/lib/game/combat/bar.rb +119 -0
- data/lib/game/combat/battle.rb +345 -0
- data/lib/game/combat/control.rb +18 -0
- data/lib/game/combat/gui.rb +190 -0
- data/lib/game/combat/gui/select_item.rb +11 -0
- data/lib/game/combat/gui/select_spell.rb +38 -0
- data/lib/game/constitution.rb +48 -0
- data/lib/game/equipment.rb +34 -0
- data/lib/game/inventory.rb +37 -0
- data/lib/game/item.rb +54 -0
- data/lib/game/magic.rb +33 -0
- data/lib/game/map/events.rb +29 -0
- data/lib/game/map/fog.rb +41 -0
- data/lib/game/map/map.rb +247 -0
- data/lib/game/map/map_animation.rb +26 -0
- data/lib/game/map/map_loader.rb +177 -0
- data/lib/game/map/map_object.rb +208 -0
- data/lib/game/map/map_particle.rb +27 -0
- data/lib/game/map/player.rb +78 -0
- data/lib/game/map/tile.rb +35 -0
- data/lib/game/mind.rb +24 -0
- data/lib/game/npc/behaviour.rb +45 -0
- data/lib/game/npc/bubble.rb +28 -0
- data/lib/game/npc/goal.rb +93 -0
- data/lib/game/npc/npc.rb +95 -0
- data/lib/game/npc/task.rb +73 -0
- data/lib/game/osd/magic.rb +24 -0
- data/lib/game/party.rb +42 -0
- data/lib/game/skills.rb +64 -0
- data/lib/game/spell.rb +35 -0
- data/lib/game_window.rb +95 -0
- data/lib/glsl/contrast.frag +12 -0
- data/lib/glsl/fade.frag +11 -0
- data/lib/glsl/mezzotint.frag +20 -0
- data/lib/glsl/noise.frag +20 -0
- data/lib/glsl/pixelate.frag +42 -0
- data/lib/glsl/radialblur.frag +28 -0
- data/lib/glsl/sepia.frag +15 -0
- data/lib/glsl/shockwave.frag +24 -0
- data/lib/glsl/tv_screen.frag +17 -0
- data/lib/graphics/animations/credits.txt +1 -0
- data/lib/graphics/animations/explosion2.png +0 -0
- data/lib/graphics/backgrounds/white_ties_grass.png +0 -0
- data/lib/graphics/chars/ejera.png +0 -0
- data/lib/graphics/chars/salyjea.png +0 -0
- data/lib/graphics/chars/tharat.png +0 -0
- data/lib/graphics/combat/tharat.png +0 -0
- data/lib/graphics/cursors/normal.png +0 -0
- data/lib/graphics/fog/clouds1.png +0 -0
- data/lib/graphics/gui/bar_center.png +0 -0
- data/lib/graphics/gui/bar_left.png +0 -0
- data/lib/graphics/gui/bar_right.png +0 -0
- data/lib/graphics/gui/button_background.png +0 -0
- data/lib/graphics/gui/button_close.png +0 -0
- data/lib/graphics/gui/button_close_hi.png +0 -0
- data/lib/graphics/gui/button_highlight.png +0 -0
- data/lib/graphics/gui/charequip_background.png +0 -0
- data/lib/graphics/gui/charselect_background.png +0 -0
- data/lib/graphics/gui/container_background.png +0 -0
- data/lib/graphics/gui/drop_item.png +0 -0
- data/lib/graphics/gui/equip_Etarae.png +0 -0
- data/lib/graphics/gui/equip_Mensch.png +0 -0
- data/lib/graphics/gui/equipslot_background.png +0 -0
- data/lib/graphics/gui/iteminfo_background.png +0 -0
- data/lib/graphics/gui/msg_background.png +0 -0
- data/lib/graphics/gui/scrollbar_background.png +0 -0
- data/lib/graphics/gui/scroller.png +0 -0
- data/lib/graphics/gui/tile_32.png +0 -0
- data/lib/graphics/gui/tile_32_highlight.png +0 -0
- data/lib/graphics/icons/items/arrow.png +0 -0
- data/lib/graphics/icons/items/bandage.png +0 -0
- data/lib/graphics/icons/items/boots_leather.png +0 -0
- data/lib/graphics/icons/items/bow.png +0 -0
- data/lib/graphics/icons/items/credits.txt +8 -0
- data/lib/graphics/icons/items/harness_leather.png +0 -0
- data/lib/graphics/icons/items/knife.png +0 -0
- data/lib/graphics/icons/items/shirt_linen.png +0 -0
- data/lib/graphics/items/none.png +0 -0
- data/lib/graphics/menu/ingame_background.png +0 -0
- data/lib/graphics/menu/ingame_background.xcf +0 -0
- data/lib/graphics/menu/start_background.png +0 -0
- data/lib/graphics/missing.png +0 -0
- data/lib/graphics/osd/magic_bg.png +0 -0
- data/lib/graphics/particles/leaf.png +0 -0
- data/lib/graphics/particles/smoke.png +0 -0
- data/lib/graphics/pixel.png +0 -0
- data/lib/graphics/tiles/test.png +0 -0
- data/lib/gui/base.rb +278 -0
- data/lib/gui/button.rb +93 -0
- data/lib/gui/char_equip.rb +118 -0
- data/lib/gui/char_selector.rb +54 -0
- data/lib/gui/context_menu.rb +115 -0
- data/lib/gui/draggable.rb +18 -0
- data/lib/gui/grid.rb +118 -0
- data/lib/gui/image.rb +17 -0
- data/lib/gui/inventory.rb +42 -0
- data/lib/gui/item_info.rb +33 -0
- data/lib/gui/slider.rb +10 -0
- data/lib/gui/textfield.rb +57 -0
- data/lib/layer.rb +64 -0
- data/lib/load.rb +31 -0
- data/lib/main.rb +18 -0
- data/lib/maps/def/test.bhv +26 -0
- data/lib/maps/def/test.rb +14 -0
- data/lib/maps/test.tmx +133 -0
- data/lib/maps/test2.tmx +94 -0
- data/lib/maps/test3.tmx +29 -0
- data/lib/maps/test3_lower.tmx +25 -0
- data/lib/maps/test3_upper.tmx +25 -0
- data/lib/maps/test_left.tmx +25 -0
- data/lib/maps/test_upper.tmx +25 -0
- data/lib/music/Butterfly Tea - A New Hope 2K11.mp3 +0 -0
- data/lib/music/Greendjohn - Rebirth.mp3 +0 -0
- data/lib/music/credits.txt +8 -0
- data/lib/parse.rb +605 -0
- data/lib/parse_tmx.rb +114 -0
- data/lib/particles.rb +127 -0
- data/lib/sample.rb +29 -0
- data/lib/save.rb +44 -0
- data/lib/song.rb +41 -0
- data/lib/sounds/click1.wav +0 -0
- data/lib/sounds/credits.txt +2 -0
- data/lib/sounds/error1.wav +0 -0
- data/lib/sprite.rb +35 -0
- data/lib/states/menus.rb +17 -0
- data/lib/states/menus/alchemy.rb +53 -0
- data/lib/states/menus/equip.rb +79 -0
- data/lib/states/menus/ingame.rb +34 -0
- data/lib/states/menus/magic.rb +31 -0
- data/lib/states/menus/options.rb +54 -0
- data/lib/states/menus/start.rb +38 -0
- data/lib/states/states.rb +154 -0
- data/lib/tileset.rb +42 -0
- data/lib/tools/world.rb +103 -0
- data/lib/tools/worldmap_editor.rb +221 -0
- data/lib/translate.rb +368 -0
- metadata +255 -0
data/lib/def/skills.def
ADDED
|
@@ -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
|
+
}
|
data/lib/def/spells.def
ADDED
|
@@ -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
|
+
}
|
data/lib/def/spells.rb
ADDED
data/lib/def/weapons.def
ADDED
|
@@ -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
|
data/lib/ext/shader.rb
ADDED
|
@@ -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
|