Created
October 16, 2010 07:42
-
-
Save monkstone/629550 to your computer and use it in GitHub Desktop.
Preston Lees multi-threaded star-field application modified to run on linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# asynchronous_object.rb | |
# | |
# Copyright © 2009 Preston Lee. All rights reserved. | |
require 'thread' | |
class AsychronousObject | |
attr_reader :thread | |
attr_reader :update_frequency | |
attr_reader :last_updated | |
def initialize(freq) | |
@update_freqency = freq | |
# puts @update_freqency | |
@mutex = Mutex.new | |
start | |
end | |
def start | |
@last_updated = Time.now | |
@state = :active # or :inactive | |
# puts @mutex | |
@thread = Thread.new do | |
keep_going = true | |
while keep_going do | |
@mutex.synchronize do | |
# puts "going" | |
keep_going = false if @state == :inactive | |
end | |
if keep_going | |
now = Time.now | |
# puts "TL '#{@last_updated}' N #{now} F #{@update_freqency}" | |
update(@last_updated, now) | |
@last_updated = now | |
sleep @update_freqency | |
end | |
end | |
end | |
end | |
def update | |
puts "FAIL!" | |
raise "You need to implement this method!" | |
end | |
def activate | |
@mutex.synchronize do | |
case @state | |
when :active | |
# do nothing | |
when :inactive | |
start | |
end | |
end | |
end | |
def deactivate | |
@mutex.synchronize do | |
@state = :inactive | |
end | |
end | |
def join | |
@thread.join | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# star.rb | |
# | |
# Copyright © 2009 Preston Lee. All rights reserved. | |
require 'asynchronous_object' | |
class Star < AsychronousObject | |
attr_reader :x, :y, :z, :dxs, :dys, :dzs,:clipping_plane | |
DEFAULT_UPDATE_FREQUENCY = 0.20 # In seconds. | |
DEFAULT_CLIPPING_PLANE = 1800 # The universe is a giant cube, with each side being this long. | |
def initialize(freq = DEFAULT_UPDATE_FREQUENCY, clip = DEFAULT_CLIPPING_PLANE) | |
@clipping_plane = clip | |
@dxs = rand(20) - 10 # X-axis movement per wall second. | |
@dys = rand(20) - 10 # Y-axis movement per wall second. | |
@dzs = rand(200) * 2 # Z-axis movement per wall second. | |
set_random_position | |
super(freq) # We have to do this last since a +Thread+ will be created that needs our instance variables instantiated. | |
end | |
def set_random_position | |
@x = rand(clipping_plane * 2) - clipping_plane | |
@y = rand(clipping_plane * 2) - clipping_plane | |
@z = rand(clipping_plane * 2) - clipping_plane | |
end | |
def set_new_position | |
set_random_position | |
@z = -1 * clipping_plane | |
end | |
def update(last, now) | |
# Check if the star is getting too far away from the universe, and move it back to a reasonable starting point if so. | |
# puts "CLIP NIL" if @clipping_plane.nil? | |
set_new_position if x >= clipping_plane | |
set_new_position if y >= clipping_plane | |
set_new_position if z >= clipping_plane | |
# puts "Updating star position. '#{freq}'" | |
# Figure out the translation required along each axis for this time period. | |
dtime = now - last | |
dx = dxs * dtime | |
dy = dys * dtime | |
dz = dzs * dtime | |
# Move the star. | |
@x += dx | |
@y += dy | |
@z += dz | |
#puts "Moving to #{@x}, #{@y}, #{@z}" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright © 2009 Preston Lee. All rights reserved. | |
require 'star' | |
require 'asynchronous_object' | |
class StarfieldStar < Star | |
include Processing::Proxy | |
def draw | |
push_matrix | |
translate(@x, @y, @z) | |
box(8) | |
pop_matrix | |
end | |
end | |
class Starfield < Processing::App | |
load_library :opengl | |
NUM_STARS = 200; | |
CAMERA_SPEED = 20 # Pixels per wall second. | |
CAMERA_ROTATE_SPEED = 0.08 # Radians per wall second. | |
FRAME_RATE = 30 # Target frame per second. | |
attr_accessor :stars, :in_setup | |
full_screen | |
def setup | |
if in_setup == nil # guard against repeatedly setting up opengl? | |
library_loaded?(:opengl) ? setup_opengl : render_mode(P3D) | |
in_setup = true | |
end | |
frame_rate FRAME_RATE | |
@moved = false | |
@x = 0 | |
@y = 0 | |
@z = 0 | |
@rz = 0 | |
@mouse_last_x = nil | |
@mouse_last_y = nil | |
@active = true | |
@active_mutex = Mutex.new | |
@stars = [] | |
NUM_STARS.times do | |
@stars << StarfieldStar.new(1.0 / FRAME_RATE) | |
end | |
text_font load_font("Univers66.vlw.gz"), 10 | |
end | |
def draw | |
background 0 # Paint the entire screen solid black. | |
fill(255) | |
color(100,255,255) | |
sphere(100) | |
# text("Moving starfield demo aoenu hreouh rcohurcoeuh arochuoaentuhoe u.", 0, 0, 0) | |
if !@moved | |
push_matrix | |
scale(5.0, 5.0, 5.0) | |
# translate(0, 100, 0) | |
text("Multi-threaded starfield simulation.", 0, 80, 0) | |
text("Move: A, S, D, W, R, F, Arrow Keys", 0, 100, 0) | |
text("Roll: Z, C", 0, 110, 0) | |
text("Look: click and drag mouse.", 0, 120, 0) | |
text("Pause/Resume: TAB", 0, 130, 0) | |
text("PrestonLee.com", 0, 150, 0) | |
pop_matrix | |
else | |
# puts "MOVED" | |
end | |
@stars.each do |s| | |
push_matrix | |
s.draw | |
pop_matrix | |
end | |
move_camera_for_frame | |
# move_for_frame() | |
# scale(5.0, 5.0, 5.0) | |
# text('aoeuaoeuao euaoeuaoeu') | |
# translate(@x, @y, @z) | |
# rotate_z(@rz) | |
end | |
def setup_opengl | |
render_mode OPENGL | |
hint DISABLE_OPENGL_ERROR_REPORT | |
hint ENABLE_OPENGL_4X_SMOOTH | |
end | |
def mouse_released | |
@mouse_last_x = nil | |
@mouse_last_y = nil | |
end | |
def mouse_dragged | |
@moved = true | |
@mouse_last_x = mouse_x if @mouse_last_x.nil? | |
@mouse_last_y = mouse_y if @mouse_last_y.nil? | |
dx = @mouse_last_x - mouse_x | |
dy = @mouse_last_y - mouse_y | |
begin_camera | |
if dx != 0 | |
# puts "#{mouse_x} #{mouse_y}" | |
rotate_y radians(-dx) * 0.1 | |
end | |
if dy != 0 | |
rotate_x radians(dy) * 0.1 | |
end | |
end_camera | |
@mouse_last_x = mouse_x | |
@mouse_last_y = mouse_y | |
end | |
def key_pressed | |
@moved = true | |
# puts "KEY_PRESSED: #{key_code}" | |
handle_camera_change_start | |
handle_pause_and_resume | |
end | |
def handle_pause_and_resume | |
case key_code | |
when TAB: | |
@active_mutex.synchronize do | |
@stars.each do |s| | |
@active ? s.deactivate : s.activate | |
end | |
@active = !@active | |
end | |
end | |
end | |
def key_released | |
# puts "KEY_RELEASED: #{key_code}" | |
handle_camera_change_stop | |
end | |
def handle_camera_change_start | |
begin_camera | |
case key_code | |
when UP: | |
@camera_move_z = -1 | |
when DOWN, 's', 'o': | |
@camera_move_z = 1 | |
when LEFT: | |
@camera_move_x = -1 | |
when RIGHT: | |
@camera_move_x = 1 | |
end | |
case key | |
when 'w', ',': | |
@camera_move_z = -1 | |
when 's', 'o': | |
@camera_move_z = 1 | |
when 'a': | |
@camera_move_x = -1 | |
when 'd', 'e': | |
@camera_move_x = 1 | |
when 'r', 'p': | |
@camera_move_y = -1 | |
when 'f', 'u': | |
@camera_move_y = 1 | |
when 'z', ';': | |
@camera_rotate_z = -1 | |
when 'c', 'j': | |
@camera_rotate_z = 1 | |
end | |
end_camera | |
end | |
def handle_camera_change_stop | |
begin_camera | |
case key_code | |
when UP, DOWN, 'w', ',', 's', 'o': | |
@camera_move_z = 0 | |
when LEFT, RIGHT, 'a', 'd', 'e': | |
@camera_move_x = 0 | |
end | |
case key | |
when 'w', ',', 's', 'o': | |
@camera_move_z = 0 | |
when 'a', 'd', 'e': | |
@camera_move_x = 0 | |
when 'r', 'p', 'f', 'u': | |
@camera_move_y = 0 | |
when 'z', ';', 'c', 'j': | |
@camera_rotate_z = 0 | |
end | |
end_camera | |
end | |
def move_camera_for_frame | |
begin_camera | |
@dx = (@camera_move_x || 0) * CAMERA_SPEED | |
@dy = (@camera_move_y || 0) * CAMERA_SPEED | |
@dz = (@camera_move_z || 0) * CAMERA_SPEED | |
@drz = (@camera_rotate_z || 0) * CAMERA_ROTATE_SPEED | |
@x += @dx | |
@y += @dy | |
@z += @dz | |
@rz += @drz | |
translate(@dx, 0, 0) if !@camera_move_x.nil? && @camera_move_x != 0 | |
translate(0, @dy, 0) if !@camera_move_y.nil? && @camera_move_y != 0 | |
translate(0, 0, @dz) if !@camera_move_z.nil? && @camera_move_z != 0 | |
rotate_z(@drz) if !@camera_rotate_z.nil? && @camera_rotate_z != 0 | |
end_camera | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment