#!/usr/local/bin/ruby # Copyright 2007 Jay McGavren, jay@mcgavren.com. # # This file is part of Zyps. # # Zyps is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . gems_loaded = false begin require 'optparse' require 'zyps' require 'zyps/actions' require 'zyps/conditions' require 'zyps/environmental_factors' require 'zyps/remote' require 'zyps/views/trails' require 'drb' rescue LoadError if gems_loaded == false require 'rubygems' gems_loaded = true retry else raise end end include Zyps DEFAULT_VIEW_WIDTH = 800 DEFAULT_VIEW_HEIGHT = 600 DEFAULT_MAX_SPEED = 500 DEFAULT_MAX_POPULATION = 100 DEFAULT_FPS = 60 #A server for a Zyps Environment. class ZypsServer #Port to open service on. attr_accessor :uri #Maximum allowed number of objects. attr_accessor :max_population #View dimensions. attr_accessor :view_width, :view_height #Set up default values. def initialize( uri = nil, view_width = DEFAULT_VIEW_WIDTH, view_height = DEFAULT_VIEW_HEIGHT, fps = DEFAULT_FPS, max_population = DEFAULT_MAX_POPULATION, max_speed = DEFAULT_MAX_SPEED, enclosure = true ) @uri, @view_width, @view_height, @fps, @max_population, @max_speed, @enclosure = uri, view_width, view_height, fps, max_population, max_speed, enclosure end #Create app window, game environment, view, and network service. def main #A clock to track frames to draw this second. clock = Clock.new time_per_frame = 1.0 / @fps #Create a window, and set GTK up to quit when it is closed. window = Gtk::Window.new window.signal_connect("delete_event") {false} window.signal_connect("destroy") {Gtk.main_quit} #Add view to window. view = TrailsView.new(@view_width, @view_height) window.add(view.canvas) window.show_all #Create environment. environment = Environment.new #Point view at environment. environment.add_observer(view) #Limit population. environment.environmental_factors << PopulationLimit.new(environment, @max_population) if @max_population #Limit speed of objects. environment.environmental_factors << SpeedLimit.new(@max_speed) if @max_speed #Keep objects on screen. if @enclosure enclosure = Enclosure.new() enclosure.left = 0 enclosure.bottom = 0 enclosure.top = @view_height enclosure.right = @view_width environment.environmental_factors << enclosure end #Create thread to update environment. update_thread = Thread.new do begin loop do begin environment.interact rescue Exception => exception puts exception, exception.backtrace puts environment.inspect end #Control population. environment.objects.shift while environment.objects.length > @max_population #Determine how much time is left in this frame. time_left_in_frame = time_per_frame - clock.elapsed_time #Sleep for the remaining time. if time_left_in_frame > 0 sleep time_left_in_frame #Skip a frame if things are going too slow. else sleep time_per_frame end end rescue Exception => exception puts exception, exception.backtrace end end #Start a network service. server = EnvironmentServer.new(environment, @uri) server.start #Display our URI. puts "Zyps server active at #{server.uri}" #Disable file system access. $SAFE = 2 #Activate the GUI. Gtk.main end #Set attributes according to command-line arguments. def process_options(arguments) #Set up option parser. options = OptionParser.new #Define valid options. options.on("-h", "--help", TrueClass, "Display program help.") { puts options.help exit } options.on( "-m", "--max-population [number]", Integer, "The maximum number of allowed game objects. #{DEFAULT_MAX_POPULATION} by default." ) {|value| @max_population = value} options.on( "-s", "--max-speed [number]", Integer, "The fastest an object can go. #{DEFAULT_MAX_SPEED ? DEFAULT_MAX_SPEED : 'No limit'} by default." ) {|value| @max_speed = value} options.on( "-n", "--no-enclosure", "Disables the barrier that normally keeps objects on the screen." ) {|value| @enclosure = false} options.on( "-u", "--uri [uri]", String, "dRuby URI to run the server on. If not defined, one will be selected and printed to STDOUT." ) {|value| @uri = value} options.on( "-f", "--fps [frames]", Integer, "Number of frames to draw per second. #{DEFAULT_FPS} by default." ) {|value| @fps = value} options.on( "--view-width [pixels]", Integer, "Window width. #{DEFAULT_VIEW_WIDTH} by default." ) {|value| @view_width = value} options.on( "--view-height [pixels]", Integer, "Window height. #{DEFAULT_VIEW_HEIGHT} by default." ) {|value| @view_height = value} #Parse the options, printing usage if parsing fails. options.parse(arguments) rescue puts "#{$!}\nType '#{$0} --help' for valid options." end end begin #Create a server. server = ZypsServer.new #Parse the command line. server.process_options(ARGV) #Start the server. server.main rescue => exception #Print error to STDERR and exit with an abnormal status. abort "Error: " + exception.message + exception.backtrace.join("\n") end