rage 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/COPYING +8 -0
- data/LICENSE +674 -0
- data/README.rdoc +48 -0
- data/Rakefile +46 -0
- data/bin/mesh-viewer.rb +91 -0
- data/lib/rage.rb +30 -0
- data/lib/rage/camera.rb +59 -0
- data/lib/rage/color.rb +18 -0
- data/lib/rage/common.rb +52 -0
- data/lib/rage/dsl.rb +36 -0
- data/lib/rage/game.rb +64 -0
- data/lib/rage/input.rb +91 -0
- data/lib/rage/loader.rb +33 -0
- data/lib/rage/location.rb +141 -0
- data/lib/rage/mesh.rb +147 -0
- data/lib/rage/resource.rb +49 -0
- data/lib/rage/viewport.rb +50 -0
- data/lib/rage/window.rb +58 -0
- data/spec/location_spec.rb +112 -0
- data/spec/mesh_spec.rb +84 -0
- data/spec/spec_helper.rb +13 -0
- metadata +75 -0
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
== RAGE - The Ruby Advanced Gaming Engine
|
2
|
+
|
3
|
+
Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
|
5
|
+
RAGE is made available under the GNU GENERAL PUBLIC LICENSE
|
6
|
+
as published by the Free Software Foundation, either version 3
|
7
|
+
of the License, or (at your option) any later version.
|
8
|
+
|
9
|
+
== Info
|
10
|
+
RAGE is a Ruby dsl geared towards providing a simple / intuitive
|
11
|
+
interface to perform 3D graphics and many other types of operations
|
12
|
+
in the context of a simulation/gaming environment.
|
13
|
+
|
14
|
+
The goal is to provide the developer w/ simple syntax that they can use to easily
|
15
|
+
display a window w/ viewports, render 3D geometries and textures/materials,
|
16
|
+
handle user input, play audio files, and execute a slew of other actions.
|
17
|
+
|
18
|
+
== Installation
|
19
|
+
|
20
|
+
To install rage simply run:
|
21
|
+
gem install rage
|
22
|
+
|
23
|
+
Source code is available via:
|
24
|
+
git clone http://github.com/movitto/rage
|
25
|
+
|
26
|
+
== Usage
|
27
|
+
|
28
|
+
# create a mesh w/ blender and export it to /home/user/mesh.x3d using File > Export > X3D
|
29
|
+
|
30
|
+
require 'rage'
|
31
|
+
|
32
|
+
resource :type => :mesh, :uri => "file:///home/user/mesh.x3d" do |mesh|
|
33
|
+
mesh.show_at 0, 0, 0
|
34
|
+
end
|
35
|
+
|
36
|
+
window(:width => 512, :height => 512) { |win|
|
37
|
+
win.create_viewport
|
38
|
+
}.show
|
39
|
+
|
40
|
+
game.run
|
41
|
+
|
42
|
+
== Mesh Viewer
|
43
|
+
|
44
|
+
Also see bin/mesh-viewer.rb in the project which can be run like so:
|
45
|
+
|
46
|
+
ruby bin/mesh-viewer.rb -m file:///path/to/rage/spec/content/cube.x3d
|
47
|
+
|
48
|
+
The -m may be specified any number of times to view multiple meshes simultaneously.
|
data/Rakefile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# rage project Rakefile
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
|
5
|
+
|
6
|
+
require 'rake/rdoctask'
|
7
|
+
require 'spec/rake/spectask'
|
8
|
+
require 'rake/gempackagetask'
|
9
|
+
|
10
|
+
|
11
|
+
GEM_NAME="rage"
|
12
|
+
PKG_VERSION='0.1'
|
13
|
+
|
14
|
+
desc "Run all specs"
|
15
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
16
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
17
|
+
end
|
18
|
+
|
19
|
+
Rake::RDocTask.new do |rd|
|
20
|
+
rd.main = "README.rdoc"
|
21
|
+
rd.rdoc_dir = "doc/site/api"
|
22
|
+
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
23
|
+
end
|
24
|
+
|
25
|
+
PKG_FILES = FileList['bin/**/*', 'lib/**/*.rb', 'COPYING', 'LICENSE', 'Rakefile', 'README.rdoc', 'spec/**/*.rb' ]
|
26
|
+
|
27
|
+
SPEC = Gem::Specification.new do |s|
|
28
|
+
s.name = GEM_NAME
|
29
|
+
s.version = PKG_VERSION
|
30
|
+
s.files = PKG_FILES
|
31
|
+
|
32
|
+
s.required_ruby_version = '>= 1.8.1'
|
33
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.3.3")
|
34
|
+
|
35
|
+
s.author = "Mohammed Morsi"
|
36
|
+
s.email = "movitto@yahoo.com"
|
37
|
+
s.date = %q{2010-03-20}
|
38
|
+
s.description = %q{The Ruby Advanced Gaming Engine}
|
39
|
+
s.summary = %q{The Ruby Advanced Gaming Engine}
|
40
|
+
s.homepage = %q{http://morsi.org/projects/RAGE}
|
41
|
+
end
|
42
|
+
|
43
|
+
Rake::GemPackageTask.new(SPEC) do |pkg|
|
44
|
+
pkg.need_tar = true
|
45
|
+
pkg.need_zip = true
|
46
|
+
end
|
data/bin/mesh-viewer.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# use rage to view meshes
|
3
|
+
#
|
4
|
+
# Flags:
|
5
|
+
# -h --help
|
6
|
+
# -m --mesh [file]
|
7
|
+
#
|
8
|
+
# Multiple -m options may be specified
|
9
|
+
#
|
10
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
11
|
+
# Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'optparse'
|
15
|
+
|
16
|
+
require 'lib/rage'
|
17
|
+
|
18
|
+
include RAGE
|
19
|
+
|
20
|
+
# process cmd line args and run main routines
|
21
|
+
def main()
|
22
|
+
meshes = []
|
23
|
+
|
24
|
+
# setup cmd line options
|
25
|
+
opts = OptionParser.new do |opts|
|
26
|
+
opts.on("-h", "--help", "Print help message") do
|
27
|
+
puts opts
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
opts.on("-m", "--mesh [uri]", "URI to the mesh file to load (eg file://path)") do |path|
|
31
|
+
meshes.push path
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# TODO display any number of meshes (set coordinates/camera appropriately)
|
36
|
+
|
37
|
+
# parse cmd line
|
38
|
+
begin
|
39
|
+
opts.parse!(ARGV)
|
40
|
+
rescue OptionParser::InvalidOption
|
41
|
+
puts opts
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
if meshes.size == 0
|
46
|
+
puts "at least one valid mesh path required"
|
47
|
+
puts opts
|
48
|
+
return
|
49
|
+
end
|
50
|
+
|
51
|
+
resources = []
|
52
|
+
tx = ty = tz = 0
|
53
|
+
meshes.each do |mesh|
|
54
|
+
resource :type => :mesh, :uri => mesh do |mr|
|
55
|
+
resources << mr
|
56
|
+
boundaries = mr.boundaries
|
57
|
+
scale = mr.scale
|
58
|
+
tx += (boundaries[0] - boundaries[3]) * scale[0]
|
59
|
+
ty += (boundaries[1] - boundaries[4]) * scale[1]
|
60
|
+
tz += (boundaries[2] - boundaries[5]) * scale[2]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# add in addition tenth for padding
|
65
|
+
tx += 0.1 * tx
|
66
|
+
ty += 0.1 * ty
|
67
|
+
tz += 0.1 * tz
|
68
|
+
|
69
|
+
# go through each object, set center to iterator * total length / (number_of_meshes - 1) - total_length / 2
|
70
|
+
resources.each_index do |i|
|
71
|
+
mx = my = mz = 0
|
72
|
+
unless resources.size == 1
|
73
|
+
mx = i * tx / (resources.size - 1) - tx / 2
|
74
|
+
my = i * ty / (resources.size - 1) - ty / 2
|
75
|
+
mz = i * tz / (resources.size - 1) - tz / 2
|
76
|
+
end
|
77
|
+
resources[i].show_at :x => mx, :y => my, :z => mz
|
78
|
+
end
|
79
|
+
|
80
|
+
window(:width => 512, :height => 512) { |win|
|
81
|
+
win.create_viewport
|
82
|
+
}.show
|
83
|
+
|
84
|
+
game.run
|
85
|
+
end
|
86
|
+
|
87
|
+
begin
|
88
|
+
main()
|
89
|
+
rescue Exception => e
|
90
|
+
puts "#{e} #{e.backtrace.join("\n")}"
|
91
|
+
end
|
data/lib/rage.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# include all rage modules
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
|
5
|
+
|
6
|
+
lib = File.dirname(__FILE__)
|
7
|
+
|
8
|
+
$: << lib + '/rage/'
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
|
12
|
+
require 'sdl'
|
13
|
+
require "gl"
|
14
|
+
require "glu"
|
15
|
+
|
16
|
+
# The Ruby Advanced Gaming Engine
|
17
|
+
module RAGE ; end
|
18
|
+
|
19
|
+
require lib + '/rage/common'
|
20
|
+
require lib + '/rage/window'
|
21
|
+
require lib + '/rage/resource'
|
22
|
+
require lib + '/rage/game'
|
23
|
+
require lib + '/rage/input'
|
24
|
+
require lib + '/rage/location'
|
25
|
+
require lib + '/rage/loader'
|
26
|
+
require lib + '/rage/color'
|
27
|
+
require lib + '/rage/mesh'
|
28
|
+
require lib + '/rage/camera'
|
29
|
+
require lib + '/rage/viewport'
|
30
|
+
require lib + '/rage/dsl'
|
data/lib/rage/camera.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Camera constructs and methods
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
|
5
|
+
|
6
|
+
module RAGE
|
7
|
+
|
8
|
+
# Camera is the end user's view into the world.
|
9
|
+
# It is instantiated as part of a viewport and controls the
|
10
|
+
# projection matrix through which the 3D world is viewed.
|
11
|
+
class Camera
|
12
|
+
|
13
|
+
# Projection matrix to use, managed internally
|
14
|
+
attr_accessor :projection
|
15
|
+
|
16
|
+
# Camera coordinates
|
17
|
+
attr_accessor :pos
|
18
|
+
|
19
|
+
# Degrees to rotate camera around x,y,z axes
|
20
|
+
attr_accessor :xrotate, :yrotate, :zrotate
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
# FIXME this needs to be parameterized more
|
24
|
+
|
25
|
+
# initialize projection params from window
|
26
|
+
depth = (Window.width + Window.height)/4
|
27
|
+
@projection = [45, Window.width / Window.height, 1, depth]
|
28
|
+
|
29
|
+
# initialize lookat params
|
30
|
+
@pos = [0, 0, 1]
|
31
|
+
|
32
|
+
# initial rotation params
|
33
|
+
@xrotate, @yrotate, @zrotate = 0,0,0
|
34
|
+
end
|
35
|
+
|
36
|
+
# Invoked during draw cycle to setup projection matrix
|
37
|
+
def draw
|
38
|
+
# setup projection matrix
|
39
|
+
Gl.glMatrixMode(Gl::GL_PROJECTION)
|
40
|
+
Gl.glLoadIdentity
|
41
|
+
|
42
|
+
# TODO at some point make this more modular, allowing user to
|
43
|
+
# select glOrtho or glFrustrum w/ configurable params
|
44
|
+
Glu.gluPerspective(*@projection)
|
45
|
+
|
46
|
+
Gl.glMatrixMode(Gl::GL_MODELVIEW)
|
47
|
+
Gl.glLoadIdentity
|
48
|
+
|
49
|
+
# translate the world by inverse camera position
|
50
|
+
Gl.glTranslatef *(@pos.collect { |p| p * -1 })
|
51
|
+
|
52
|
+
# rotate camera according to params
|
53
|
+
Gl.glRotatef(@xrotate, 1, 0, 0)
|
54
|
+
Gl.glRotatef(@yrotate, 0, 1, 0)
|
55
|
+
Gl.glRotatef(@zrotate, 0, 0, 1)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
data/lib/rage/color.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Color Resource
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
|
5
|
+
|
6
|
+
module RAGE
|
7
|
+
|
8
|
+
# Represents a rgb color in the framework
|
9
|
+
class Color
|
10
|
+
attr_accessor :color
|
11
|
+
|
12
|
+
def initialize(args = {})
|
13
|
+
rgb = args[:rgb]
|
14
|
+
@color = Window.screen.format.map_rgb(*rgb)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/lib/rage/common.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Things that don't fit elsewhere
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
|
5
|
+
|
6
|
+
# logger support
|
7
|
+
require 'logger'
|
8
|
+
|
9
|
+
# Override default logger format
|
10
|
+
class Logger
|
11
|
+
def format_message(severity, timestamp, progname, msg)
|
12
|
+
"#{severity} #{timestamp} (#{$$}) #{msg}\n"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module RAGE
|
17
|
+
# Logger helper class
|
18
|
+
class Logger
|
19
|
+
private
|
20
|
+
LOG_LEVEL = ::Logger::FATAL # FATAL ERROR WARN INFO DEBUG
|
21
|
+
|
22
|
+
def self._instantiate_logger
|
23
|
+
unless defined? @@logger
|
24
|
+
@@logger = ::Logger.new(STDOUT)
|
25
|
+
@@logger.level = LOG_LEVEL
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
public
|
30
|
+
def self.method_missing(method_id, *args)
|
31
|
+
_instantiate_logger
|
32
|
+
@@logger.send(method_id, args)
|
33
|
+
end
|
34
|
+
def self.logger
|
35
|
+
_instantiate_logger
|
36
|
+
@@logger
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Module
|
42
|
+
|
43
|
+
# Helper method to define class attributes
|
44
|
+
def class_attr(*sym)
|
45
|
+
syms = [sym].flatten # can pass either a single value or array to this method
|
46
|
+
syms.each { |sym|
|
47
|
+
module_eval "def self.#{sym}() @@#{sym} end"
|
48
|
+
module_eval "def self.#{sym}=(x) @@#{sym}=x end"
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/lib/rage/dsl.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# RAGE DSL
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
|
5
|
+
|
6
|
+
# Sets attributes on the Window w/ any specified arguments and then
|
7
|
+
# invokes block w/ the Window class. Finally Window is returned.
|
8
|
+
def window(args = {}, &block)
|
9
|
+
Window.set_attrs args
|
10
|
+
block.call Window unless block.nil?
|
11
|
+
return Window
|
12
|
+
end
|
13
|
+
|
14
|
+
# Instantiate new viewport w/ specified args and invoke block, using
|
15
|
+
# viewport as an arg. Finally return viewport
|
16
|
+
def viewport(args = {}, &block)
|
17
|
+
vp = Viewport.new args
|
18
|
+
block.call vp unless block.nil?
|
19
|
+
return vp
|
20
|
+
end
|
21
|
+
|
22
|
+
# Load resource w/ specified args and invoke blockm using resource as an arg.
|
23
|
+
# Finally return resource.
|
24
|
+
def resource(args = {}, &block)
|
25
|
+
resource = ResourcesManager.instance.load_resource args
|
26
|
+
block.call resource unless block.nil?
|
27
|
+
return resource
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set attributes on Game w/ specified args and invoke block
|
31
|
+
# using Game as an arg. Finally return Game
|
32
|
+
def game(args = {}, &block)
|
33
|
+
#Game.set_attrs(args)
|
34
|
+
block.call Game unless block.nil?
|
35
|
+
return Game
|
36
|
+
end
|
data/lib/rage/game.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# High level game constructs and methods
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the GPLv3+ http://www.gnu.org/licenses/gpl.txt
|
5
|
+
|
6
|
+
require 'singleton'
|
7
|
+
|
8
|
+
module RAGE
|
9
|
+
|
10
|
+
# Manages the overall game execution, end users only need to call run
|
11
|
+
# on this class.
|
12
|
+
class Game
|
13
|
+
include Singleton
|
14
|
+
|
15
|
+
class_attr :current_viewport
|
16
|
+
|
17
|
+
# Invoked during main game execution cycle to run through a single game draw operation
|
18
|
+
def self.draw
|
19
|
+
Window.draw
|
20
|
+
|
21
|
+
Window.viewports.each { |vp|
|
22
|
+
@@current_viewport = vp
|
23
|
+
vp.draw
|
24
|
+
|
25
|
+
# draw each location
|
26
|
+
LocationsManager.instance.locations.each { |lm|
|
27
|
+
lm.draw
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
Window.refresh
|
32
|
+
end
|
33
|
+
|
34
|
+
# Run game and block
|
35
|
+
def self.run
|
36
|
+
Gl.glEnable( Gl::GL_TEXTURE_2D )
|
37
|
+
Gl.glEnable(Gl::GL_DEPTH_TEST)
|
38
|
+
Gl.glDepthMask(Gl::GL_TRUE)
|
39
|
+
|
40
|
+
@@wireframe_mode = false
|
41
|
+
|
42
|
+
while true
|
43
|
+
while event = SDL::Event2.poll
|
44
|
+
InputHandler.handle event
|
45
|
+
end
|
46
|
+
|
47
|
+
draw
|
48
|
+
sleep 0.01
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
# Bool indicating if game should be run in wireframe mode or not
|
54
|
+
class_attr :wireframe_mode
|
55
|
+
|
56
|
+
# Set wireframe mode on / off
|
57
|
+
def self.wireframe_mode=(val)
|
58
|
+
@@wireframe_mode= val
|
59
|
+
Gl.glPolygonMode( Gl::GL_FRONT_AND_BACK, val ? Gl::GL_LINE : Gl::GL_FILL )
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|