ippa-chingu 0.2.0

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.
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,109 @@
1
+ module Chingu
2
+ #
3
+ # The Animation-class helps you load and manage a tileanimation.
4
+ # A Tileanimation is a file where all the frames are put after eachother.
5
+ #
6
+ # An easy to use program to create tileanimations is http://tilestudio.sourceforge.net/
7
+ #
8
+ class Animation
9
+ attr_accessor :frames
10
+
11
+ #
12
+ # Create a new Animation.
13
+ #
14
+ # - loop: [true|false]. After the last frame is used, start from the beginning.
15
+ # - bounce: [true|false]. After the last frame is used, play it backwards untill the first frame is used again, then start playing forwards again.
16
+ # - file: Tile-file to cut up animation frames from.
17
+ # - width: width of each frame in the tileanimation
18
+ # - height: width of each frame in the tileanimation
19
+ #
20
+ #
21
+ def initialize(options)
22
+ @loop = options[:loop] || true
23
+ @bounce = options[:bounce] || false
24
+ @file = options[:file]
25
+ @height = options[:height] || 32
26
+ @width = options[:width] || 32
27
+ @index = options[:index] || 0
28
+ @delay = options[:delay] || 100
29
+ @ticks = 0
30
+
31
+ @frame_actions = []
32
+ @frames = Gosu::Image.load_tiles($window, @file, @width, @height, true)
33
+ @step = 1
34
+ end
35
+
36
+ #
37
+ # Fetch a certain frame (a Gosu#Image), starts at 0.
38
+ #
39
+ def [](index)
40
+ @frames[index]
41
+ end
42
+
43
+ #
44
+ # Get the current frame (a Gosu#Image)
45
+ #
46
+ def image
47
+ @frames[@index]
48
+ end
49
+
50
+ #
51
+ # Resets the animation, re-starts it at frame 0
52
+ #
53
+ def reset!
54
+ @index = 0
55
+ end
56
+
57
+ #
58
+ # Returns a new animation with the frames from the original animation.
59
+ # Specify which frames you want with "range", for example "0..3" for the 4 first frames.
60
+ #
61
+ def new_from_frames(range)
62
+ new_animation = self.dup
63
+ new_animation.frames = []
64
+ range.each do |nr|
65
+ new_animation.frames << self.frames[nr]
66
+ end
67
+ return new_animation
68
+ end
69
+
70
+ #
71
+ # Propelles the animation forward. Usually called in #update within the class which holds the animation.
72
+ # #next! will look at bounce and loop flags to always return a correct frame (a Gosu#Image)
73
+ #
74
+ def next!
75
+ if (@ticks += $window.tick) > @delay
76
+ @ticks = 0
77
+ @index += @step
78
+
79
+ # Has the animation hit end or beginning... time for bounce or loop?
80
+ if (@index >= @frames.size || @index < 0)
81
+ if @bounce
82
+ if @step == 1
83
+ @step = -1
84
+ else
85
+ @step = 1
86
+ end
87
+ @index += @step
88
+ elsif @loop
89
+ @index = 0
90
+ end
91
+ end
92
+ @frame_actions[@index].call if @frame_actions[@index]
93
+ end
94
+ @frames[@index]
95
+ end
96
+
97
+ #
98
+ # Execute a certain block of code when a certain frame in the animation is active.
99
+ # This could be used for pixel perfect animation/movement.
100
+ #
101
+ def on_frame(frames, &block)
102
+ if frames.kind_of? Array
103
+ frames.each { |frame| @frame_actions[frame] = block }
104
+ else
105
+ @frame_actions[frames] = block
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,50 @@
1
+ #
2
+ # Rubygames Named Resources for GOSU
3
+ # Assumes a global variable $window having the Gosu::Window instance.
4
+ # Quick 'n easy access to sprites, sounds and tiles!
5
+ #
6
+ module Chingu
7
+
8
+ def media_path(file)
9
+ File.join($window.root, "media", file)
10
+ end
11
+
12
+ def image_path(file)
13
+ File.join($window.root, "gfx", file)
14
+ end
15
+
16
+ class ImagePath
17
+ include Chingu::NamedResource
18
+
19
+ def self.autoload(name)
20
+ find_file(name)
21
+ end
22
+ end
23
+ end
24
+
25
+ module Gosu
26
+ class Image
27
+ include Chingu::NamedResource
28
+
29
+ def self.autoload(name)
30
+ (path = find_file(name)) ? Gosu::Image.new($window, path, true) : nil
31
+ end
32
+ end
33
+
34
+ class Sample
35
+ include Chingu::NamedResource
36
+
37
+ def self.autoload(name)
38
+ (path = find_file(name)) ? Gosu::Sample.new($window, path) : nil
39
+ end
40
+ end
41
+ Sound = Sample
42
+
43
+ class Tile
44
+ include Chingu::NamedResource
45
+
46
+ def self.autoload(name)
47
+ (path = find_file(name)) ? Gosu::Image.load_tiles($window, path, 32, 32, true) : nil
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,117 @@
1
+ module Chingu
2
+ #
3
+ # A basic class, all your gameobjects / actors should be built on this. Encapsulates
4
+ # Gosus draw_rot and it's parameters.
5
+ #
6
+ # All objects that inherits from this class will automaticly be updated and drawn.
7
+ #
8
+ class Actor
9
+ attr_accessor :image, :x, :y, :angle, :center_x, :center_y, :factor_x, :factor_y, :mode
10
+ attr_accessor :update, :draw, :keymap
11
+ attr_reader :options
12
+
13
+ #
14
+ # Class-level default values.
15
+ # This allows you to set default-values that affect all created actors after that.
16
+ # You might want to draw screenobjects from the top-left @ x/y instead of putting it's center there:
17
+ #
18
+ # in Gosu::Window#initialize: Actor.center_x = Actor.center_y = 0
19
+ #
20
+ @@zorder = 100
21
+ @@center_x = 0.5
22
+ @@center_y = 0.5
23
+ @@factor_x = 1.0
24
+ @@factor_y = 1.0
25
+
26
+ def self.zorder; @@zorder; end
27
+ def self.zorder=(value); @@zorder = value; end
28
+
29
+ def self.center_x; @@center_x; end
30
+ def self.center_x=(value); @@center_x = value; end
31
+
32
+ def self.center_y; @@center_y; end
33
+ def self.center_y=(value); @@center_y = value; end
34
+
35
+ def self.factor_x; @@factor_x; end
36
+ def self.factor_x=(value); @@factor_x = value; end
37
+
38
+ def self.factor_y; @@factor_y; end
39
+ def self.factor_y=(value); @@factor_y = value; end
40
+
41
+ #
42
+ # Create a new Actor. Arguments are given in hash-format:
43
+ #
44
+ # :x screen x-coordinate (default 0, to the left)
45
+ # :y screen y-coordinate (default 0, top of screen)
46
+ # :angle angle of object, used in draw_rot, (default 0, no rotation)
47
+ # :zorder a gameclass "foo" with higher zorder then gameclass "bar" is drawn on top of "foo".
48
+ # :center_x relative horizontal position of the rotation center on the image.
49
+ # 0 is the left border, 1 is the right border, 0.5 is the center (default 0.5)
50
+ # :center_y see center_x. (default 0.5)
51
+ # :factor_x horizontal zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
52
+ # :factor_y vertical zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
53
+ #
54
+ # :update [true|false] Automaticly call #update on object each gameloop. Default +true+.
55
+ # :draw [true|false] Automaticly call #update on object each gameloop. Default +true+.
56
+ #
57
+ def initialize(options = {})
58
+ @options = options
59
+
60
+ # draw_rot arguments
61
+ @image = options[:image] if options[:image].is_a? Gosu::Image
62
+ @image = Image[options[:image]] if options[:image].is_a? String
63
+
64
+ @x = options[:x] || 0
65
+ @y = options[:y] || 0
66
+ @angle = options[:angle] || 0
67
+ @zorder = options[:zorder] || @@zorder
68
+ @center_x = options[:center_x] || options[:center] || @@center_x
69
+ @center_y = options[:center_y] || options[:center] || @@center_y
70
+ @factor_x = options[:factor_x] || options[:factor] || @@factor_x
71
+ @factor_y = options[:factor_y] || options[:factor] || @@factor_y
72
+ @mode = options[:mode] || :additive
73
+
74
+ # gameloop logic
75
+ @update = options[:update] || true
76
+ @draw = options[:draw] || true
77
+
78
+ automatic_update! if @update
79
+ automatic_draw! if @draw
80
+ end
81
+
82
+ #
83
+ # Add self to the list of objects that Chingu calls #update on each update-loop.
84
+ # This is done by default except if you create a gameobject with {:update => false}
85
+ #
86
+ def automatic_update!
87
+ $window.automatic_update_for(self)
88
+ end
89
+ #
90
+ # Add self to the list of objects that Chingu calls #draw on each update-loop.
91
+ # This is done by default except if you create a gameobject with {:draw => false}
92
+ #
93
+ def automatic_draw!
94
+ $window.automatic_draw_for(self)
95
+ end
96
+
97
+ def keymap=(keymap)
98
+ @keymap = keymap
99
+ $window.key_recievers << self unless $window.key_recievers.include? self
100
+ end
101
+
102
+ #
103
+ # Override this with your own actor/game-logic
104
+ #
105
+ def update
106
+
107
+ end
108
+
109
+ #
110
+ # The core of the gameclass, the draw_rot encapsulation. Draws the sprite on screen.
111
+ # Calling #to_i on @x and @y enables thoose to be Float's, for subpixel slow movement in #update
112
+ #
113
+ def draw
114
+ @image.draw_rot(@x.to_i, @y.to_i, @zorder, @angle, @center_x, @center_y, @factor_x, @factor_y, @mode)
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,6 @@
1
+ module Chingu
2
+ Velocity = Struct.new(:x, :y, :z)
3
+ Position = Struct.new(:x, :y, :z)
4
+ Point = Struct.new(:x, :y)
5
+ #Rect = Struct.new(:x, :y, :width, :height)
6
+ end
@@ -0,0 +1,21 @@
1
+ module Chingu
2
+ class FPSCounter
3
+ attr_reader :fps
4
+
5
+ def initialize
6
+ @current_second = Gosu::milliseconds / 1000
7
+ @accum_fps = 0
8
+ @fps = 0
9
+ end
10
+
11
+ def register_tick
12
+ @accum_fps += 1
13
+ current_second = Gosu::milliseconds / 1000
14
+ if current_second != @current_second
15
+ @current_second = current_second
16
+ @fps = @accum_fps
17
+ @accum_fps = 0
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,101 @@
1
+ module Chingu
2
+ #
3
+ # A basic class, all your ingame objects should be built on this. Encapsulates
4
+ # Gosus draw_rot and it's parameters.
5
+ #
6
+ # All objects that inherits from this class will automaticly be updated and drawn.
7
+ #
8
+ class GameObject
9
+ attr_accessor :image, :x, :y, :angle, :center_x, :center_y, :factor_x, :factor_y, :mode
10
+ attr_accessor :update, :draw, :input
11
+ attr_reader :options
12
+
13
+ #
14
+ # Class-level default values.
15
+ # This allows you to set default-values that affect all created GameObjects after that.
16
+ # You might want to draw gameobjects from the top-left @ x/y instead of putting it's center there:
17
+ #
18
+ # in Gosu::Window#initialize: GameObject.center_x = GameObject.center_y = 0
19
+ #
20
+ @@zorder = 100
21
+ @@center_x = 0.5
22
+ @@center_y = 0.5
23
+ @@factor_x = 1.0
24
+ @@factor_y = 1.0
25
+
26
+ def self.zorder; @@zorder; end
27
+ def self.zorder=(value); @@zorder = value; end
28
+
29
+ def self.center_x; @@center_x; end
30
+ def self.center_x=(value); @@center_x = value; end
31
+
32
+ def self.center_y; @@center_y; end
33
+ def self.center_y=(value); @@center_y = value; end
34
+
35
+ def self.factor_x; @@factor_x; end
36
+ def self.factor_x=(value); @@factor_x = value; end
37
+
38
+ def self.factor_y; @@factor_y; end
39
+ def self.factor_y=(value); @@factor_y = value; end
40
+
41
+ #
42
+ # Create a new GameObject. Arguments are given in hash-format:
43
+ #
44
+ # :x screen x-coordinate (default 0, to the left)
45
+ # :y screen y-coordinate (default 0, top of screen)
46
+ # :angle angle of object, used in draw_rot, (default 0, no rotation)
47
+ # :zorder a gameclass "foo" with higher zorder then gameclass "bar" is drawn on top of "foo".
48
+ # :center_x relative horizontal position of the rotation center on the image.
49
+ # 0 is the left border, 1 is the right border, 0.5 is the center (default 0.5)
50
+ # :center_y see center_x. (default 0.5)
51
+ # :factor_x horizontal zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
52
+ # :factor_y vertical zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
53
+ #
54
+ # :update [true|false] Automaticly call #update on object each gameloop. Default +true+.
55
+ # :draw [true|false] Automaticly call #update on object each gameloop. Default +true+.
56
+ #
57
+ def initialize(options = {})
58
+ @options = options
59
+
60
+ # draw_rot arguments
61
+ @image = options[:image] if options[:image].is_a? Gosu::Image
62
+ @image = Image[options[:image]] if options[:image].is_a? String
63
+
64
+ @x = options[:x] || 0
65
+ @y = options[:y] || 0
66
+ @angle = options[:angle] || 0
67
+ @zorder = options[:zorder] || @@zorder
68
+ @center_x = options[:center_x] || options[:center] || @@center_x
69
+ @center_y = options[:center_y] || options[:center] || @@center_y
70
+ @factor_x = options[:factor_x] || options[:factor] || @@factor_x
71
+ @factor_y = options[:factor_y] || options[:factor] || @@factor_y
72
+ @color = options[:color] || 0xFFFFFFFF
73
+ @mode = options[:mode] || :default # :additive is also available.
74
+
75
+ # gameloop/framework logic
76
+ @update = options[:update] || true
77
+ @draw = options[:draw] || true
78
+ @input = options[:input] || nil
79
+
80
+ #
81
+ # A GameObject can either belong to a GameState or our mainwindow ($window)
82
+ # .. or live in limbo with manual updates
83
+ #
84
+ @parent = $window.game_state_manager.inside_state || $window
85
+ @parent.add_game_object(self) if @parent
86
+ end
87
+
88
+
89
+ def update
90
+ # Objects gamelogic here
91
+ end
92
+
93
+ #
94
+ # The core of the gameclass, the draw_rot encapsulation. Draws the sprite on screen.
95
+ # Calling #to_i on @x and @y enables thoose to be Float's, for subpixel slow movement in #update
96
+ #
97
+ def draw
98
+ @image.draw_rot(@x.to_i, @y.to_i, @zorder, @angle, @center_x, @center_y, @factor_x, @factor_y, @color, @mode)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,39 @@
1
+ module Chingu
2
+ class GameState
3
+ include Chingu::GameStateHelpers # Easy access to the global game_state-queue
4
+ include Chingu::DrawHelpers # Adds fill(), fade() etc to each gamestate.
5
+
6
+ attr_reader :options # so jac can access his :level-number
7
+ attr_reader :game_objects
8
+ attr_accessor :input
9
+
10
+ def initialize(options = {})
11
+ @options = options
12
+ @game_objects = Array.new
13
+ @input = options[:input]
14
+ $window.game_state_manager.inside_state = self
15
+ setup
16
+ end
17
+
18
+ def add_game_object(game_object)
19
+ @game_objects.push(game_object) unless @game_objects.include?(game_object)
20
+ end
21
+
22
+ def setup
23
+ end
24
+
25
+ def button_down(id)
26
+ end
27
+
28
+ def button_up(id)
29
+ end
30
+
31
+ def update
32
+ @game_objects.each { |object| object.update }
33
+ end
34
+
35
+ def draw
36
+ @game_objects.each { |object| object.draw }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,84 @@
1
+ module Chingu
2
+ class GameStateManager
3
+ attr_accessor :inside_state
4
+ attr_reader :states
5
+
6
+ def initialize
7
+ @inside_state = nil
8
+ @states = []
9
+ end
10
+
11
+ #
12
+ # Gets the currently active gamestate (top of stack)
13
+ #
14
+ def state
15
+ @states.last
16
+ end
17
+
18
+ #
19
+ # Adds a state to the gamestate-stack
20
+ #
21
+ def push_state(state)
22
+ @states.push(state)
23
+ end
24
+
25
+ #
26
+ # Pops a state off the gamestate-stack
27
+ #
28
+ def pop_state
29
+ @states.pop
30
+ end
31
+
32
+ #
33
+ # Returns the previous gamestate
34
+ #
35
+ def previous_state
36
+ @states[@states.index(state)-1]
37
+ end
38
+
39
+ alias :prev_state previous_state
40
+
41
+ #
42
+ # Pops through all gamestates until matching a given gamestate
43
+ #
44
+ def switch_state(new_state)
45
+ while (state = @states.pop)
46
+ break if state == new_state
47
+ end
48
+ end
49
+
50
+ #
51
+ # Bellow follows a set of auto-called Gosu::Window methods.
52
+ # We define them game_state_manager so Gosu::Window can call them here.
53
+ # Then the game_state_manager is responsible to resend them to the active state.
54
+ # Or in the future many states.
55
+ #
56
+
57
+ #
58
+ # Called before #update when the user pressed a button while the window had the focus.
59
+ #
60
+ def button_down(id)
61
+ state.button_down(id) if state
62
+ end
63
+
64
+ #
65
+ # Called when the user released a button.
66
+ #
67
+ def button_up(id)
68
+ state.button_up(id) if state
69
+ end
70
+
71
+ #
72
+ # Calls #update on the current gamestate, if there is one.
73
+ #
74
+ def update
75
+ state.update if state
76
+ end
77
+ #
78
+ # Calls draw() on the current gamestate, if there is one.
79
+ #
80
+ def draw
81
+ state.draw if state
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,41 @@
1
+ module Chingu
2
+ module GameStateHelpers
3
+
4
+ #
5
+ # push_gamestate accepts either a class inherited from GameState or an object-instance from such a class.
6
+ #
7
+ # push_gamestate(Intro) is the same as:
8
+ # push_gamestate(Intro.new)
9
+ #
10
+ # The first line ends upp calling "new" to Intro before activating the newlycreated gamestate.
11
+ #
12
+ def push_gamestate(state)
13
+ if state.is_a? Chingu::GameState
14
+ $window.game_state_manager.push_state(state)
15
+ elsif state.superclass == Chingu::GameState
16
+ $window.game_state_manager.push_state(state.new)
17
+ end
18
+ end
19
+
20
+ def pop_gamestate
21
+ $window.game_state_manager.pop_state
22
+ end
23
+
24
+ def current_gamestate
25
+ $window.game_state_manager.state
26
+ end
27
+
28
+ def previous_gamestate
29
+ $window.game_state_manager.previous_state
30
+ end
31
+ end
32
+
33
+ module DrawHelpers
34
+ def fill(color)
35
+ $window.draw_quad(0, 0, color, $window.width, 0, color, $window.width, $window.width, color, 0, $window.height, color, 0, :default)
36
+ end
37
+
38
+ def fade(options = {})
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,100 @@
1
+ module Chingu
2
+ module Input
3
+ include Gosu::Button
4
+
5
+ #
6
+ # Ruby symbols describing http://www.libgosu.org/rdoc/classes/Gosu.html
7
+ #
8
+ CONSTANT_TO_SYMBOL = {
9
+ Kb0 => [:zero],
10
+ Kb1 => [:one],
11
+ Kb2 => [:two],
12
+ Kb3 => [:three],
13
+ Kb4 => [:four],
14
+ Kb5 => [:five],
15
+ Kb6 => [:six],
16
+ Kb7 => [:seven],
17
+ Kb8 => [:eight],
18
+ Kb9 => [:nine],
19
+
20
+ KbBackspace => [:backspace],
21
+ KbDelete => [:delete, :del],
22
+ KbDown => [:down],
23
+ KbEnd => [:end],
24
+ KbEnter => [:enter],
25
+ KbEscape => [:escape, :esc],
26
+
27
+ KbHome => [:home],
28
+ KbInsert => [:insert, :ins],
29
+ KbLeft => [:left],
30
+ KbLeftAlt => [:left_alt, :lalt],
31
+ KbLeftControl => [:left_control, :left_ctrl, :lctrl],
32
+ KbLeftShift => [:left_shift, :lshift],
33
+
34
+
35
+ KbNumpadAdd => [:"+", :add],
36
+ KbNumpadDivide => [:"/", :divide],
37
+ KbNumpadMultiply => [:"*", :multiply],
38
+ KbNumpadSubtract => [:"-", :subtract],
39
+ KbPageDown => [:page_down],
40
+ KbPageUp => [:page_up],
41
+ # KbPause => [:pause],
42
+ KbReturn => [:return],
43
+ KbRight => [:right],
44
+ KbRightAlt => [:right_alt, :ralt],
45
+ KbRightControl => [:right_control, :right_ctrl, :rctrl],
46
+ KbRightShift => [:right_shift, :rshift],
47
+ KbSpace => [:" ", :space],
48
+ KbTab => [:tabulator, :tab],
49
+ KbUp => [:up],
50
+
51
+ MsLeft => [:left_mouse_button, :mouse_left],
52
+ MsMiddle => [:middle_mouse_button, :mouse_middle],
53
+ MsRight => [:right_mouse_button, :mouse_right],
54
+ MsWheelDown => [:mouse_wheel_down, :wheel_down],
55
+ MsWheelUp => [:mouse_wheel_up, :wheel_up],
56
+
57
+ GpDown => [:gamepad_down, :gp_down, :pad_down],
58
+ GpLeft => [:gamepad_left, :gp_left, :pad_left],
59
+ GpRight => [:gamepad_right, :gp_right, :pad_right],
60
+ GpUp => [:gamepad_up, :gp_up, :pad_up]
61
+ }
62
+
63
+ # Letters, A-Z
64
+ ("A".."Z").each do |letter|
65
+ CONSTANT_TO_SYMBOL[eval("Kb#{letter}")] = [letter.downcase.to_sym]
66
+ end
67
+
68
+ # Numbers, 0-9
69
+ (0..9).each do |number|
70
+ CONSTANT_TO_SYMBOL[eval("Kb#{number.to_s}")] = [number.to_s.to_sym]
71
+ end
72
+
73
+ # Numpad-numbers, 0-9
74
+ (0..9).each do |number|
75
+ CONSTANT_TO_SYMBOL[eval("KbNumpad#{number.to_s}")] = ["numpad_#{number.to_s}".to_sym]
76
+ end
77
+
78
+ #F-keys, F1-F12
79
+ (1..12).each do |number|
80
+ CONSTANT_TO_SYMBOL[eval("KbF#{number.to_s}")] = ["f#{number.to_s}".to_sym]
81
+ end
82
+
83
+ # Gamepad-buttons 0-15
84
+ (0..15).each do |number|
85
+ CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["gamepad_button_#{number.to_s}"]
86
+ end
87
+
88
+ #
89
+ # Reverse CONSTANT_TO_SYMBOL -> SYMBOL_TO_CONSTNT
90
+ # like: SYMBOL_TO_CONSTANT = CONSTANT_TO_SYMBOL.invert.dup
91
+ #
92
+ SYMBOL_TO_CONSTANT = Hash.new
93
+ CONSTANT_TO_SYMBOL.each_pair do |constant, symbols|
94
+ symbols.each do |symbol|
95
+ SYMBOL_TO_CONSTANT[symbol] = constant
96
+ end
97
+ end
98
+
99
+ end
100
+ end