smagacor 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/COPYING +340 -0
- data/ChangeLog +111 -0
- data/README +48 -0
- data/Rakefile +255 -0
- data/TODO +19 -0
- data/VERSION +1 -0
- data/bin/smagacor +23 -0
- data/data/smagacor/smagacor.png +0 -0
- data/data/smagacor/tictactoe/game.info +7 -0
- data/data/smagacor/tictactoe/o.png +0 -0
- data/data/smagacor/tictactoe/tictactoe.png +0 -0
- data/data/smagacor/tictactoe/tictactoe.rb +300 -0
- data/data/smagacor/tictactoe/x.png +0 -0
- data/install.rb +21 -0
- data/lib/smagacor/controller.rb +129 -0
- data/lib/smagacor/smagacor-ui.rb +230 -0
- data/setup.rb +1331 -0
- data/test/games/tictactoe/game.info +7 -0
- data/test/runtests.rb +2 -0
- data/test/smagacor/tc_controller.rb +48 -0
- metadata +69 -0
@@ -0,0 +1,129 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
#
|
4
|
+
# $Id: controller.rb 197 2005-02-09 13:42:17Z thomas $
|
5
|
+
#
|
6
|
+
# smagacor - a collection of small games in ruby
|
7
|
+
# Copyright (C) 2004 Thomas Leitner
|
8
|
+
#
|
9
|
+
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
10
|
+
# General Public License as published by the Free Software Foundation; either version 2 of the
|
11
|
+
# License, or (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
14
|
+
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along with this program; if not,
|
18
|
+
# write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
require 'rbconfig'
|
23
|
+
require "yaml"
|
24
|
+
require 'logger'
|
25
|
+
|
26
|
+
class Object
|
27
|
+
|
28
|
+
LOGGER = Logger.new( STDERR )
|
29
|
+
LOGGER.datetime_format = "%Y-%m-%d %H:%M:%S"
|
30
|
+
def logger
|
31
|
+
LOGGER
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class Logger
|
37
|
+
|
38
|
+
def set_log_dev( dev )
|
39
|
+
@logdev = LogDevice.new( dev )
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
module Smagacor
|
45
|
+
|
46
|
+
# The version of this copy of Smagacor
|
47
|
+
VERSION = [0, 0, 1]
|
48
|
+
|
49
|
+
class GameInfo
|
50
|
+
|
51
|
+
Domain = 'thomasleitner,2004'
|
52
|
+
Name = 'gameinfo'
|
53
|
+
|
54
|
+
attr_reader :name
|
55
|
+
attr_reader :icon
|
56
|
+
attr_reader :description
|
57
|
+
attr_reader :file
|
58
|
+
attr_accessor :directory
|
59
|
+
attr_reader :classname
|
60
|
+
attr_reader :category
|
61
|
+
|
62
|
+
def get_class_object
|
63
|
+
@classname.split( /::/ ).inject( Object ) {|mod, name| mod.const_get( name )}
|
64
|
+
end
|
65
|
+
|
66
|
+
def ==( other )
|
67
|
+
@name == other.name && \
|
68
|
+
@icon == other.icon && \
|
69
|
+
@description == other.description && \
|
70
|
+
@file == other.file && \
|
71
|
+
@directory == other.directory && \
|
72
|
+
@classname == other.classname && \
|
73
|
+
@category == other.category
|
74
|
+
end
|
75
|
+
|
76
|
+
alias :to_s :to_yaml
|
77
|
+
|
78
|
+
def to_yaml_type
|
79
|
+
"!#{Domain}/#{Name}"
|
80
|
+
end
|
81
|
+
|
82
|
+
YAML::add_domain_type( Domain, Name ) do |type, val|
|
83
|
+
YAML::object_maker( GameInfo, val )
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
class Controller
|
90
|
+
|
91
|
+
attr_reader :gamespath
|
92
|
+
attr_reader :games
|
93
|
+
|
94
|
+
def initialize
|
95
|
+
@gamespath = [ File.join( ::Config::CONFIG["datadir"], "smagacor" ), 'data/smagacor' ]
|
96
|
+
if defined? Gem::Cache
|
97
|
+
gem = Gem::Cache.from_installed_gems.search( "smagacor", "=#{::Smagacor::VERSION.join('.')}" ).last
|
98
|
+
@gamespath << File.join( gem.full_gem_path, "data", "smagacor" ) if gem
|
99
|
+
end
|
100
|
+
begin
|
101
|
+
homepath = File.expand_path( '~' )
|
102
|
+
rescue
|
103
|
+
homepath = ENV['USERPROFILE'] || ENV['HOMEDRIVE']+ENV['HOMEPATH']
|
104
|
+
end
|
105
|
+
@gamespath.unshift File.join( homepath, '.smagacor' )
|
106
|
+
@games = []
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_file( file )
|
110
|
+
@gamespath.each do |path|
|
111
|
+
name = File.join( path, file )
|
112
|
+
return name if File.exists?( name )
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def load_games
|
117
|
+
@games = []
|
118
|
+
@gamespath.each do |path|
|
119
|
+
Dir[path + '/*/game.info'].each do |file|
|
120
|
+
gi = YAML::load( File.open( file ) )
|
121
|
+
gi.directory = File.dirname( file )
|
122
|
+
@games.push gi
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
#
|
4
|
+
# $Id: smagacor-ui.rb 195 2005-02-09 13:16:44Z thomas $
|
5
|
+
#
|
6
|
+
# smagacor - a collection of small games in ruby
|
7
|
+
# Copyright (C) 2004 Thomas Leitner
|
8
|
+
#
|
9
|
+
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
10
|
+
# General Public License as published by the Free Software Foundation; either version 2 of the
|
11
|
+
# License, or (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
14
|
+
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along with this program; if not,
|
18
|
+
# write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
require 'logger'
|
23
|
+
require 'fox'
|
24
|
+
require 'fox/colors'
|
25
|
+
require 'smagacor/controller'
|
26
|
+
|
27
|
+
include Fox
|
28
|
+
|
29
|
+
module Smagacor
|
30
|
+
|
31
|
+
# Widget for listing all installed games.
|
32
|
+
class GameMenuShutter < FXShutter
|
33
|
+
|
34
|
+
# Returns a default version of the class.
|
35
|
+
def initialize( p )
|
36
|
+
super( p, nil, 0, FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y )
|
37
|
+
@categories = {}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Initializes the list of games. The +switcher+ parameter has to be an object of class
|
41
|
+
# GameSwitcher. The method uses the list of games supplied by the +controller+ object.
|
42
|
+
def init_game_list( switcher, controller )
|
43
|
+
each_child do |child|
|
44
|
+
removeChild( child )
|
45
|
+
child.destroy
|
46
|
+
end
|
47
|
+
controller.load_games
|
48
|
+
controller.games.each do |game|
|
49
|
+
@categories[game.category] ||= CategoryShutterItem.new( self, game.category )
|
50
|
+
btn = GameShutterButton.new( @categories[game.category].content, game.name )
|
51
|
+
btn.tipText = game.description
|
52
|
+
btn.helpText = game.description
|
53
|
+
btn.icon = SmagacorWindow.load_image( getApp(), File.join( game.directory, game.icon ) )
|
54
|
+
btn.connect( SEL_COMMAND ) { switcher.select_game( game ) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Widget for creating category shutter items easily.
|
62
|
+
class CategoryShutterItem < FXShutterItem
|
63
|
+
|
64
|
+
# Create a new category shutter item for category +text+ with +icon+.
|
65
|
+
def initialize( p, text, icon=nil, opts=0 )
|
66
|
+
super( p, text, icon, opts|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10 )
|
67
|
+
button.padTop = 2
|
68
|
+
button.padBottom = 2
|
69
|
+
self.helpText = text
|
70
|
+
self.tipText = text
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# Widget for creating buttons for games easily.
|
77
|
+
class GameShutterButton < FXButton
|
78
|
+
|
79
|
+
# Create a new game button for the game +name+.
|
80
|
+
def initialize( p, name )
|
81
|
+
super( p, name, nil, nil, 0, BUTTON_TOOLBAR|TEXT_BELOW_ICON|FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT )
|
82
|
+
self.backColor = p.backColor
|
83
|
+
self.textColor = FXRGB(255, 255, 255)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# Game switcher widget. Used to display the different games in the space.
|
90
|
+
class GameSwitcher < FXSwitcher
|
91
|
+
|
92
|
+
# Create a new switcher.
|
93
|
+
def initializer( p )
|
94
|
+
super( p, FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y )
|
95
|
+
end
|
96
|
+
|
97
|
+
# Selects the specified +game+ [GameInfo] for playing. If the game has been selected earlier,
|
98
|
+
# the widget only displays the game area. Otherwise the information in +game+ is used for
|
99
|
+
# loading the necessary game files and for creating the game widget.
|
100
|
+
def select_game( game )
|
101
|
+
game_index = 0
|
102
|
+
children.each_with_index do |child, index|
|
103
|
+
game_index = index if child.userData == game
|
104
|
+
end
|
105
|
+
if game_index == 0
|
106
|
+
begin
|
107
|
+
require File.join( game.directory, game.file )
|
108
|
+
content = game.get_class_object.new( self, game )
|
109
|
+
content.create
|
110
|
+
content.userData = game
|
111
|
+
game_index = children.length - 1
|
112
|
+
rescue StandardError => e
|
113
|
+
FXMessageBox.new( self, "Error loading game",
|
114
|
+
"Could not load the game #{game.name}\nError: #{e.message}\n#{e.backtrace.join("\n")}",
|
115
|
+
nil, MBOX_OK ).execute
|
116
|
+
end
|
117
|
+
end
|
118
|
+
self.current = game_index
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
# Log window for viewing the log statements (information, error descriptions, etc ).
|
125
|
+
class LogWindow < FXDialogBox
|
126
|
+
|
127
|
+
# Create a LogWindow
|
128
|
+
def initialize( p )
|
129
|
+
super( p, "Log Window", DECOR_ALL, 0, 0, 600, 400 )
|
130
|
+
vertical = FXVerticalFrame.new( self, LAYOUT_SIDE_TOP|LAYOUT_SIDE_LEFT|LAYOUT_FILL_X|LAYOUT_FILL_Y )
|
131
|
+
@log = FXText.new( vertical, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y )
|
132
|
+
@log.editable = false
|
133
|
+
FXButton.new( vertical, "Close", nil, self, ID_ACCEPT, FRAME_RAISED|LAYOUT_FILL_X )
|
134
|
+
end
|
135
|
+
|
136
|
+
# Invoked by the logger library for writing log messages. The +message+ is appended to log.
|
137
|
+
def write( message )
|
138
|
+
@log.appendText( message )
|
139
|
+
@log.makePositionVisible( @log.text.length )
|
140
|
+
end
|
141
|
+
|
142
|
+
# Invoked by the logger library for closing the log device. Does nothing.
|
143
|
+
def close() end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
# Main window for Smagacor.
|
149
|
+
class SmagacorWindow < FXMainWindow
|
150
|
+
|
151
|
+
# Small description of Smagacor, for the about view.
|
152
|
+
DESCRIPTION = "\n\nSmagacor #{::Smagacor::VERSION.join('.')}
|
153
|
+
|
154
|
+
Smagacor is a collection of some small games.
|
155
|
+
It provides an easy interface for adding new games and has
|
156
|
+
a pleasing :-) appearance.
|
157
|
+
|
158
|
+
Select a game from the menu on the left side!
|
159
|
+
And have fun with Smagacor!!!
|
160
|
+
|
161
|
+
smagacor.rubyforge.org"
|
162
|
+
|
163
|
+
# Used to load *.png images into FXPNGIcon objects.
|
164
|
+
def self.load_image( app, file )
|
165
|
+
img = FXPNGIcon.new( app, nil, IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP )
|
166
|
+
FXFileStream.open( file, FXStreamLoad ) {|str| img.loadPixels(str) }
|
167
|
+
img.create
|
168
|
+
img
|
169
|
+
end
|
170
|
+
|
171
|
+
# Create the main window, using +app+ [FXApplication] and +controller+ [Controller].
|
172
|
+
def initialize( app, controller )
|
173
|
+
super( app, "Smagacor Game Collection", nil, nil, DECOR_ALL, 100, 100, 800, 600 )
|
174
|
+
@controller = controller
|
175
|
+
|
176
|
+
@logwindow = LogWindow.new( app )
|
177
|
+
logger.set_log_dev( @logwindow )
|
178
|
+
|
179
|
+
menubar = FXMenubar.new( self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X )
|
180
|
+
|
181
|
+
filemenu = FXMenuPane.new( self )
|
182
|
+
FXMenuCommand.new( filemenu, "Quit\tCtl-Q", nil, getApp(), FXApp::ID_QUIT )
|
183
|
+
FXMenuTitle.new( menubar, "&File", nil, filemenu )
|
184
|
+
|
185
|
+
editmenu = FXMenuPane.new( self )
|
186
|
+
FXMenuCommand.new( editmenu, "Undo\tCtl-Z" ).connect( SEL_COMMAND, method( :onUndo ) )
|
187
|
+
FXMenuTitle.new( menubar, "&Edit", nil, editmenu )
|
188
|
+
|
189
|
+
helpmenu = FXMenuPane.new( self )
|
190
|
+
FXMenuCommand.new( helpmenu, "Log Window...\tCtl-L" ).connect( SEL_COMMAND ) { @logwindow.show }
|
191
|
+
FXMenuCommand.new( helpmenu, "About Smagacor\tCtl-A" ).connect( SEL_COMMAND ) { @switcher.current = 0 }
|
192
|
+
FXMenuTitle.new( menubar, "&Help", nil, helpmenu )
|
193
|
+
|
194
|
+
status = FXStatusbar.new( self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER )
|
195
|
+
|
196
|
+
splitter = FXSplitter.new( self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_TRACKING )
|
197
|
+
|
198
|
+
@shutter = GameMenuShutter.new( splitter )
|
199
|
+
@switcher = GameSwitcher.new( splitter )
|
200
|
+
@shutter.init_game_list( @switcher, controller )
|
201
|
+
|
202
|
+
FXLabel.new( @switcher, DESCRIPTION, SmagacorWindow.load_image( getApp(), controller.get_file( 'smagacor.png' ) ), ICON_ABOVE_TEXT )
|
203
|
+
end
|
204
|
+
|
205
|
+
def create
|
206
|
+
super
|
207
|
+
@shutter.width = 150
|
208
|
+
show
|
209
|
+
end
|
210
|
+
|
211
|
+
def onUndo( sender, sel, event )
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
# Wraps the creation of the Smagacor Application.
|
218
|
+
class SmagacorUI
|
219
|
+
|
220
|
+
# Builds the application and runs it.
|
221
|
+
def start
|
222
|
+
app = FXApp.new( "Smagacor Game Collection", "Smagacor Game Collection" )
|
223
|
+
window = SmagacorWindow.new( app, Controller.new )
|
224
|
+
app.create
|
225
|
+
app.run
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|