flonkerton 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.
@@ -0,0 +1,135 @@
1
+ require '../../lib/flonkerton'
2
+ require '../../examples/extras/random_color'
3
+ include Flonkerton
4
+ include Gosu
5
+
6
+ module GosuTutorial
7
+ module ZOrder
8
+ Background, Stars, Player, UI = *0..3
9
+ end
10
+
11
+ class Player
12
+ attr_reader :score
13
+
14
+ def initialize
15
+ @image = Images[:starfighter]
16
+ @beep = Samples[:beep]
17
+ @x = @y = @vel_x = @vel_y = @angle = 0.0
18
+ @score = 0
19
+ end
20
+
21
+ def warp(x, y)
22
+ @x, @y = x, y
23
+ end
24
+
25
+ def turn_left
26
+ @angle -= 4.5
27
+ end
28
+
29
+ def turn_right
30
+ @angle += 4.5
31
+ end
32
+
33
+ def accelerate
34
+ @vel_x += Gosu::offset_x(@angle, 0.5)
35
+ @vel_y += Gosu::offset_y(@angle, 0.5)
36
+ end
37
+
38
+ def move
39
+ @x += @vel_x
40
+ @y += @vel_y
41
+ @x %= CONFIG[:width]
42
+ @y %= CONFIG[:height]
43
+
44
+ @vel_x *= 0.95
45
+ @vel_y *= 0.95
46
+ end
47
+
48
+ def draw
49
+ @image.draw_rot(@x, @y, ZOrder::Player, @angle)
50
+ end
51
+
52
+ def collect_stars(stars)
53
+ stars.reject! do |star|
54
+ if Gosu::distance(@x, @y, star.x, star.y) < 35 then
55
+ @score += 10
56
+ @beep.play
57
+ true
58
+ else
59
+ false
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ class Star
66
+ attr_reader :x, :y
67
+
68
+ def initialize
69
+ @animation = Tiles[:star]
70
+ @offset = @animation.first.width / 2.0
71
+ @color = Color.random((40..254), (40..254), (40..254))
72
+ @x = rand * CONFIG[:width]
73
+ @y = rand * CONFIG[:height]
74
+ end
75
+
76
+ def draw
77
+ current_frame.draw :x => @x - @offset,
78
+ :y => @y - @offset,
79
+ :z => ZOrder::Stars,
80
+ :color => @color,
81
+ :mode => :additive
82
+ end
83
+
84
+ protected
85
+
86
+ def current_frame
87
+ @animation[Gosu::milliseconds / 100 % @animation.size]
88
+ end
89
+ end
90
+
91
+ class GameScreen < Screen
92
+ def setup
93
+ @background = Images[:space]
94
+ @player = Player.new
95
+ @player.warp(320, 240)
96
+ @stars = Array.new
97
+ @font = Fonts[:default]
98
+ @input = { :up => [KbUp, GpButton0],
99
+ :left => [KbLeft, GpLeft],
100
+ :right => [KbRight, GpRight] }
101
+ end
102
+
103
+ def update
104
+ @player.turn_left if pressed?(:left)
105
+ @player.turn_right if pressed?(:right)
106
+ @player.accelerate if pressed?(:up)
107
+ @player.move
108
+ @player.collect_stars(@stars)
109
+
110
+ if rand(100) < 4 and @stars.size < 25 then
111
+ @stars << Star.new
112
+ end
113
+ end
114
+
115
+ def draw
116
+ @background.draw
117
+ @player.draw
118
+ @stars.each { |star| star.draw }
119
+ @font.draw :text => "Score: #{@player.score}",
120
+ :x => 10,
121
+ :y => 10,
122
+ :z => ZOrder::UI,
123
+ :color => Color::YELLOW
124
+ end
125
+
126
+ protected
127
+
128
+ # Taken from control example.
129
+ def pressed?(key)
130
+ @input[key].detect { |k| @game.button_down?(k) }
131
+ end
132
+ end
133
+ end
134
+
135
+ Game.start
@@ -0,0 +1,241 @@
1
+ require 'gosu'
2
+ require 'yaml'
3
+
4
+ class File
5
+ def self.label(file)
6
+ self.basename(file)[/^\w+/].scan(/[A-Z]*[a-z0-9]+/).join('_').downcase.intern
7
+ end
8
+ end
9
+
10
+ module Flonkerton
11
+ VERSION = '0.0.1'
12
+ LIB_PATH = File.dirname(File.expand_path(__FILE__))
13
+ CURRENT_PATH = File.dirname(File.expand_path($0))
14
+
15
+ if File.exist?(CURRENT_PATH + '/config/defaults.yml')
16
+ CONFIG = YAML.load_file(CURRENT_PATH + '/config/defaults.yml')
17
+ else
18
+ CONFIG = YAML.load_file(LIB_PATH + '/../config/defaults.yml')
19
+ end
20
+
21
+ module Drawable
22
+ def draw(options = {})
23
+ super(*draw_args(defaults.merge(options)))
24
+ end
25
+
26
+ protected
27
+
28
+ def draw_args(options)
29
+ defaults[:order].map { |arg| options[arg] } # 1.8.6 Patch - defaults.keys.map in 1.9
30
+ end
31
+
32
+ def name
33
+ self.class.to_s[/\w+$/].downcase
34
+ end
35
+
36
+ def defaults
37
+ CONFIG[name.intern]
38
+ end
39
+ end
40
+
41
+ class Font < Gosu::Font
42
+ include Drawable
43
+
44
+ def initialize(game, name, height = CONFIG[:font_size])
45
+ super(game, name, height)
46
+ end
47
+ end
48
+
49
+ class Image < Gosu::Image
50
+ include Drawable
51
+
52
+ def self.load_tiles(game, file, width, height, border = true)
53
+ super(game, file, width, height, border).each do |image|
54
+ image.extend(Drawable)
55
+ end
56
+ end
57
+ end
58
+
59
+ class Sample < Gosu::Sample; end
60
+
61
+ class Song < Gosu::Song
62
+ def loop
63
+ play(true)
64
+ end
65
+ end
66
+
67
+ # This class shouldn't be used directly, it provides behavior for subclasses.
68
+ #
69
+ class Resource
70
+ def self.load(game)
71
+ Dir[path].each do |file|
72
+ all[File.label(file)] = klass.new(game, file)
73
+ end
74
+ end
75
+
76
+ def self.all
77
+ @hash ||= Hash.new
78
+ end
79
+
80
+ def self.[](key)
81
+ all[key]
82
+ end
83
+
84
+ protected
85
+
86
+ def self.name
87
+ self.to_s[/\w+$/]
88
+ end
89
+
90
+ def self.klass
91
+ Module.class_eval(name.chop)
92
+ end
93
+
94
+ def self.path
95
+ File.join(CONFIG[:media_path], extension)
96
+ end
97
+
98
+ def self.extension
99
+ CONFIG["#{name.downcase}_ext".intern]
100
+ end
101
+ end
102
+
103
+ class Songs < Resource; end
104
+ class Images < Resource; end
105
+ class Samples < Resource; end
106
+
107
+ class Fonts < Resource
108
+ def self.load(game)
109
+ super(game)
110
+ all[:default] = Font.new(game, Gosu::default_font_name)
111
+ end
112
+ end
113
+
114
+ class Tiles < Resource
115
+ def self.load(game)
116
+ Dir[path].each do |file|
117
+ if File.basename(file) =~ /(\w+)_(\d+)x(\d+)/
118
+ all[$1.intern] = Image.load_tiles(game, file, $2.to_i, $3.to_i, true)
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ class Game
125
+ def self.start screen = nil
126
+ @window = Window.new(screen)
127
+ @window.show
128
+ end
129
+ end
130
+
131
+ class Window < Gosu::Window
132
+ attr_reader :screen
133
+ attr_accessor :next_screen
134
+
135
+ def initialize initial_screen = nil
136
+ super(CONFIG[:width], CONFIG[:height], CONFIG[:fullscreen])
137
+ self.caption = CONFIG[:caption]
138
+ load_resources
139
+ create(initial_screen || default_screen)
140
+ end
141
+
142
+ def update
143
+ @screen.update
144
+ create(@next_screen) if @next_screen
145
+ end
146
+
147
+ def draw
148
+ @screen.draw
149
+ end
150
+
151
+ def button_down(id)
152
+ @screen.button_down(id)
153
+ end
154
+
155
+ def button_up(id)
156
+ @screen.button_up(id)
157
+ end
158
+
159
+ def params
160
+ @params ||= Hash.new
161
+ end
162
+
163
+ protected
164
+
165
+ def load_resources
166
+ [Fonts, Songs, Images, Samples, Tiles].each do |resource|
167
+ resource.load(self)
168
+ end
169
+ end
170
+
171
+ def default_screen
172
+ Module.module_eval(CONFIG[:initial_screen])
173
+ end
174
+
175
+ def create(klass)
176
+ @screen = klass.new(self)
177
+ @next_screen = nil
178
+ end
179
+ end
180
+
181
+ # This class shouldn't be instantiated, it provides behavior for subclasses.
182
+ #
183
+ class Screen
184
+ def initialize game
185
+ @game = game
186
+ setup
187
+ end
188
+
189
+ def setup; end
190
+ def button_up(id); end
191
+
192
+ def button_down(id)
193
+ close if id == Gosu::KbEscape # Don't Panic!
194
+ end
195
+
196
+ def update; end
197
+ def draw; end
198
+
199
+ def width
200
+ @game.width
201
+ end
202
+
203
+ def height
204
+ @game.height
205
+ end
206
+
207
+ def mouse_x
208
+ @game.mouse_x
209
+ end
210
+
211
+ def mouse_y
212
+ @game.mouse_y
213
+ end
214
+
215
+ def button_down?(id)
216
+ @game.button_down?(id)
217
+ end
218
+
219
+ def close
220
+ @game.close
221
+ end
222
+
223
+ def go_to(screen)
224
+ @game.next_screen = screen
225
+ end
226
+
227
+ def params
228
+ @game.params
229
+ end
230
+
231
+ def clip_to(x, y, w, h, &block)
232
+ @game.clip_to(x, y, w, h, &block)
233
+ end
234
+ end
235
+
236
+ class WelcomeScreen < Screen
237
+ def draw
238
+ Fonts[:default].draw :text => 'Welcome'
239
+ end
240
+ end
241
+ end
Binary file
@@ -0,0 +1,4 @@
1
+ ArcadeClassic.ttf - Jacob Fisher - http://www.pizzadude.dk
2
+ background.png - http://blog.medianotions.de/de/artikel/2009/wallpaper-tangled-green
3
+ catch_me_song.ogg - ...
4
+ tiles_32x32.png - http://www.molotov.nu/
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,115 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ Protest.context('A Game example') do
4
+ module Example
5
+ class TextLogo
6
+
7
+ SPEED_X = 16
8
+ SPEED_Y = 10
9
+
10
+ def initialize text, limit
11
+ @text = text
12
+ @limit = limit
13
+ @font = Flonkerton::Fonts[:default]
14
+ @x = 0
15
+ @y = 0
16
+ end
17
+
18
+ def update
19
+ @x += SPEED_X
20
+ @y += SPEED_Y
21
+ end
22
+
23
+ def draw
24
+ @font.draw :text => @text,
25
+ :x => @x,
26
+ :y => @y,
27
+ :factor_x => 4,
28
+ :factor_y => 4
29
+ end
30
+
31
+ def on_screen?
32
+ @y < @limit
33
+ end
34
+ end
35
+
36
+ class LogoScreen < Flonkerton::Screen
37
+ LOGO_TIME = 1000
38
+
39
+ def setup
40
+ @time = Gosu.milliseconds
41
+ @font = Flonkerton::Fonts[:default]
42
+ @image = Flonkerton::Images[:gosu_logo]
43
+ @sample = Flonkerton::Samples[:select]
44
+ @x = (width - @image.width) / 2
45
+ @y = (height - @image.height) / 2
46
+ @song = Flonkerton::Songs[:catch_me_song]
47
+ @song.volume = 0.1
48
+ @song.loop
49
+ end
50
+
51
+ def update
52
+ if time_elapsed? or button_down?(Gosu::KbReturn)
53
+ @song.play
54
+ @sample.play
55
+ params[:health] = 75
56
+ go_to(GameScreen)
57
+ end
58
+ end
59
+
60
+ def draw
61
+ fill
62
+ @image.draw :x => @x, :y => @y
63
+
64
+ @font.draw :x => 10,
65
+ :y => height - @font.height,
66
+ :text => 'Press Enter to continue...',
67
+ :color => Gosu::Color::BLACK
68
+
69
+ @font.draw :text => time_left,
70
+ :color => Gosu::Color::BLACK
71
+ end
72
+
73
+ def fill(color = 0xffffffff)
74
+ @game.draw_quad(0, 0, color, width, 0, color, 0, height, color, width, height, color)
75
+ end
76
+
77
+ def time_left
78
+ Gosu.milliseconds - @time
79
+ end
80
+
81
+ def time_elapsed?
82
+ time_left >= LOGO_TIME
83
+ end
84
+ end
85
+
86
+ class GameScreen < Flonkerton::Screen
87
+ def setup
88
+ @logo = TextLogo.new('LOGO', height)
89
+ @mouse = Flonkerton::Images[:cursor]
90
+ @tiles = Flonkerton::Tiles[:tiles]
91
+ @background = Flonkerton::Images[:background]
92
+ end
93
+
94
+ def draw
95
+ @tiles.first.draw
96
+ clip_to(40, 40, 640, 480) do
97
+ @background.draw
98
+ end
99
+ @logo.draw
100
+ @mouse.draw :x => mouse_x, :y => mouse_y
101
+ end
102
+
103
+ def update
104
+ @logo.update
105
+ close unless @logo.on_screen?
106
+ end
107
+ end
108
+ end
109
+
110
+ it "should work." do
111
+ assert_nothing_raised do
112
+ Flonkerton::Game.start(Example::LogoScreen)
113
+ end
114
+ end
115
+ end