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