├── README.md ├── running_hero ├── 0.rb ├── 1.rb ├── 2.rb ├── 3.rb ├── 4.rb ├── Gemfile ├── Gemfile.lock ├── README.md └── assets │ ├── background.png │ ├── enemy.png │ ├── enemy_sheet.png │ ├── hero.png │ └── hero_sheet.png └── winner_winner_chicken_spinner ├── .ruby-version ├── Gemfile ├── Gemfile.lock ├── README.md ├── assets ├── arrow.png ├── chicken_plate.png ├── chicken_raw.jpg ├── lose.png └── win.png └── game.rb /README.md: -------------------------------------------------------------------------------- 1 | # Attention Rubyists: you can write video games 2 | 3 | In this repo, you'll find slides and code for my talk on writing games in Ruby using Gosu. 4 | 5 | -------------------------------------------------------------------------------- /running_hero/0.rb: -------------------------------------------------------------------------------- 1 | require 'gosu' 2 | 3 | class RunningHeroWindow < Gosu::Window 4 | def initialize 5 | super(960, 480) 6 | self.caption = "Running Hero Game" 7 | 8 | @hero = Gosu::Image.new("assets/hero.png") 9 | @background = Gosu::Image.new("assets/background.png") 10 | end 11 | 12 | def draw 13 | @background.draw(0, 0, 0) 14 | @hero.draw(50, 348, 1) 15 | end 16 | end 17 | 18 | RunningHeroWindow.new.show -------------------------------------------------------------------------------- /running_hero/1.rb: -------------------------------------------------------------------------------- 1 | require 'gosu' 2 | 3 | 4 | # First, we have a little guy and we want to be able to 5 | # move him around on the ground and maybe to jump. 6 | 7 | class RunningHeroWindow < Gosu::Window 8 | def initialize 9 | super(960, 480) 10 | self.caption = "Running Hero Game" 11 | 12 | @hero = Gosu::Image.new("assets/hero.png") 13 | @background = Gosu::Image.new("assets/background.png") 14 | @hero_position = [50, 348] 15 | end 16 | 17 | def update 18 | if Gosu::button_down?(Gosu::KbRight) 19 | move(:right) 20 | elsif Gosu::button_down?(Gosu::KbLeft) 21 | move(:left) 22 | end 23 | 24 | jump if Gosu::button_down?(Gosu::KbSpace) 25 | 26 | handle_jump if @jumping 27 | end 28 | 29 | def draw 30 | @background.draw(0, 0, 0) 31 | @hero.draw(@hero_position[0], @hero_position[1], 1) 32 | end 33 | 34 | private 35 | 36 | def move(way) 37 | if way == :right 38 | @hero_position = [@hero_position[0] + Hero::SPEED, @hero_position[1]] 39 | else 40 | @hero_position = [@hero_position[0] - Hero::SPEED, @hero_position[1]] 41 | end 42 | end 43 | 44 | def jump 45 | return if @jumping 46 | @jumping = true 47 | @vertical_velocity = 30 48 | end 49 | 50 | def handle_jump 51 | gravity = 1.75 52 | ground_level = 348 # y offset where our hero is on the ground 53 | @hero_position = [@hero_position[0], @hero_position[1] - @vertical_velocity] 54 | 55 | if @vertical_velocity.round == 0 # top of the jump 56 | @vertical_velocity = -1 57 | elsif @vertical_velocity < 0 # falling down -- gravity is increasing our speed 58 | @vertical_velocity = @vertical_velocity * gravity 59 | else # going up -- gravity is reducing our speed 60 | @vertical_velocity = @vertical_velocity / gravity 61 | end 62 | 63 | if @hero_position[1] >= ground_level 64 | @hero_position[1] = ground_level 65 | @jumping = false 66 | end 67 | end 68 | end 69 | 70 | module Hero 71 | SPEED = 5 72 | end 73 | 74 | RunningHeroWindow.new.show -------------------------------------------------------------------------------- /running_hero/2.rb: -------------------------------------------------------------------------------- 1 | require 'gosu' 2 | 3 | 4 | # Now, he moves around but just like a cut out doll. 5 | # With some animation, we can make him look more legit 6 | 7 | class RunningHeroWindow < Gosu::Window 8 | def initialize 9 | super(960, 480) 10 | self.caption = "Running Hero Game" 11 | 12 | @background = Gosu::Image.new("assets/background.png") 13 | @hero_position = [50, 331] 14 | 15 | @hero_direction = :right 16 | 17 | # Gosu::Image::load_tiles will cut all the images out of a big image for us of a certain size 18 | # and stuff them into an Array 19 | # in our case @hero[0] will be the hero standing still, and @hero[1..-1] will be the hero walking 20 | # animation. 21 | @hero = Gosu::Image::load_tiles("assets/hero_sheet.png", 64, 64) 22 | @current_hero_image = @hero.first 23 | end 24 | 25 | def update 26 | if Gosu::button_down?(Gosu::KbRight) 27 | move(:right) 28 | elsif Gosu::button_down?(Gosu::KbLeft) 29 | move(:left) 30 | else 31 | @walking = false 32 | end 33 | 34 | jump if Gosu::button_down?(Gosu::KbSpace) 35 | 36 | handle_jump if @jumping 37 | 38 | # figure out what our hero should look like right now 39 | # the hero's sprite sheet looks like this: 40 | # [standing still, walking1, walking2, walking3, jumping up, falling down] 41 | if @jumping 42 | # use the velocity to figure out if we're rising or falling 43 | @current_hero_image = @vertical_velocity > 0 ? @hero[4] : @hero[5] 44 | elsif @walking 45 | # Gosu::milliseconds returns the number of millis since the game started. We want to see 46 | # a new animation frame about every 100 milliseconds or so, and we have three animation frames 47 | step = (Gosu::milliseconds / 100 % 3) + 1 48 | @current_hero_image = @hero[step] 49 | else 50 | # just standing still 51 | @current_hero_image = @hero[0] 52 | end 53 | end 54 | 55 | def draw 56 | @background.draw(0, 0, 0) 57 | if @hero_direction == :right 58 | @current_hero_image.draw(@hero_position[0], @hero_position[1], 1) 59 | else 60 | # https://www.libgosu.org/cgi-bin/mwf/topic_show.pl?tid=1073 61 | @current_hero_image.draw(@hero_position[0] + @current_hero_image.width, @hero_position[1], 1, -1) 62 | end 63 | end 64 | 65 | private 66 | 67 | def move(way) 68 | @walking = true 69 | if way == :right 70 | @hero_position = [@hero_position[0] + Hero::SPEED, @hero_position[1]] 71 | @hero_direction = :right 72 | else 73 | @hero_position = [@hero_position[0] - Hero::SPEED, @hero_position[1]] 74 | @hero_direction = :left 75 | end 76 | end 77 | 78 | def jump 79 | return if @jumping 80 | @jumping = true 81 | @vertical_velocity = 30 82 | end 83 | 84 | def handle_jump 85 | gravity = 1.5 86 | ground_level = 331 # y offset where our hero is on the ground 87 | @hero_position = [@hero_position[0], @hero_position[1] - @vertical_velocity] 88 | 89 | if @vertical_velocity.round == 0 # top of the jump 90 | @vertical_velocity = -1 91 | elsif @vertical_velocity < 0 # falling down 92 | @vertical_velocity = @vertical_velocity * gravity 93 | else 94 | @vertical_velocity = @vertical_velocity / gravity 95 | end 96 | 97 | if @hero_position[1] >= ground_level 98 | @hero_position[1] = ground_level 99 | @jumping = false 100 | end 101 | end 102 | end 103 | 104 | module Hero 105 | SPEED = 5 106 | end 107 | 108 | RunningHeroWindow.new.show -------------------------------------------------------------------------------- /running_hero/3.rb: -------------------------------------------------------------------------------- 1 | require 'gosu' 2 | 3 | # $DEBUG shows us bounding boxes 4 | $DEBUG = false 5 | 6 | # Now we want our guy to be able to slam into things or to get hurt. 7 | 8 | class RunningHeroWindow < Gosu::Window 9 | def initialize 10 | super(960, 480) 11 | self.caption = "Running Hero Game" 12 | 13 | @background = Gosu::Image.new("assets/background.png") 14 | @hero_position = [50, 331] 15 | @enemy_position = [200, 331] 16 | @hero_direction = :right 17 | 18 | # Gosu::Image::load_tiles will cut all the images out of a big image for us of a certain size 19 | # and stuff them into an Array 20 | # in our case @hero[0] will be the hero standing still, and @hero[1..-1] will be the hero walking 21 | # animation. 22 | @hero = Gosu::Image::load_tiles("assets/hero_sheet.png", 64, 64) 23 | @current_hero_image = @hero.first 24 | 25 | @enemy = Gosu::Image::new("assets/enemy.png") 26 | end 27 | 28 | def update 29 | if Gosu::button_down?(Gosu::KbRight) 30 | move(:right) 31 | elsif Gosu::button_down?(Gosu::KbLeft) 32 | move(:left) 33 | else 34 | @walking = false 35 | end 36 | 37 | jump if Gosu::button_down?(Gosu::KbSpace) 38 | 39 | handle_jump if @jumping 40 | 41 | # figure out what our hero should look like right now 42 | # the hero's sprite sheet looks like this: 43 | # [standing still, walking1, walking2, walking3, jumping up, falling down] 44 | if @hurt_until 45 | @current_hero_image = @hero[6] 46 | @hurt_until = nil if Gosu::milliseconds > @hurt_until 47 | elsif @jumping 48 | # use the velocity to figure out if we're rising or falling 49 | @current_hero_image = @vertical_velocity > 0 ? @hero[4] : @hero[5] 50 | elsif @walking 51 | # Gosu::milliseconds returns the number of millis since the game started. We want to see 52 | # a new animation frame about every 100 milliseconds or so, and we have three animation frames 53 | step = (Gosu::milliseconds / 100 % 3) + 1 54 | @current_hero_image = @hero[step] 55 | else 56 | # just standing still 57 | @current_hero_image = @hero[0] 58 | end 59 | handle_collisions 60 | end 61 | 62 | def draw 63 | @background.draw(0, 0, 0) 64 | @enemy.draw(@enemy_position[0], @enemy_position[1], 1) 65 | if @hero_direction == :right 66 | @current_hero_image.draw(@hero_position[0], @hero_position[1], 1) 67 | else 68 | # https://www.libgosu.org/cgi-bin/mwf/topic_show.pl?tid=1073 69 | @current_hero_image.draw(@hero_position[0] + @current_hero_image.width, @hero_position[1], 1, -1) 70 | end 71 | draw_collision_bodies 72 | end 73 | 74 | private 75 | 76 | def move(way) 77 | return if @hurt_until 78 | @walking = true 79 | if way == :right 80 | @hero_position = [@hero_position[0] + Hero::SPEED, @hero_position[1]] 81 | @hero_direction = :right 82 | else 83 | @hero_position = [@hero_position[0] - Hero::SPEED, @hero_position[1]] 84 | @hero_direction = :left 85 | end 86 | end 87 | 88 | def jump 89 | return if @jumping || @hurt_until 90 | @jumping = true 91 | @vertical_velocity = 30 92 | end 93 | 94 | def handle_jump 95 | gravity = 1.5 96 | ground_level = 331 # y offset where our hero is on the ground 97 | @hero_position = [@hero_position[0], @hero_position[1] - @vertical_velocity] 98 | 99 | if @vertical_velocity.round == 0 # top of the jump 100 | @vertical_velocity = -1 101 | elsif @vertical_velocity < 0 # falling down 102 | @vertical_velocity = @vertical_velocity * gravity 103 | else 104 | @vertical_velocity = @vertical_velocity / gravity 105 | end 106 | 107 | if @hero_position[1] >= ground_level 108 | @hero_position[1] = ground_level 109 | @jumping = false 110 | end 111 | end 112 | 113 | def handle_collisions 114 | # did the enemy and player collide? 115 | @player_rectangle = {:x => @hero_position[0] + 18, 116 | :y => @hero_position[1] + 18, 117 | :width => @current_hero_image.width - 36, 118 | :height => @current_hero_image.height - 18} 119 | @enemy_rectangle = {:x => @enemy_position[0] + 6, 120 | :y => @enemy_position[1] + 20, 121 | :width => @enemy.width - 12, 122 | :height => @enemy.height - 20} 123 | collision = check_for_collisions(@player_rectangle, @enemy_rectangle) 124 | if collision == :left 125 | @hero_position[0] += 30 126 | @hurt_until = Gosu::milliseconds + 200 127 | elsif collision == :right 128 | @hero_position[0] -= 30 129 | @hurt_until = Gosu::milliseconds + 200 130 | elsif collision == :bottom 131 | @jumping = true 132 | @vertical_velocity = 10 133 | end 134 | end 135 | 136 | def draw_collision_bodies 137 | draw_bounding_body(@player_rectangle) 138 | draw_bounding_body(@enemy_rectangle) 139 | end 140 | 141 | def draw_bounding_body(rect, z = 10, color = Gosu::Color::GREEN) 142 | return unless $DEBUG 143 | Gosu::draw_line(rect[:x], rect[:y], color, rect[:x], rect[:y] + rect[:height], color, z) 144 | Gosu::draw_line(rect[:x], rect[:y] + rect[:height], color, rect[:x] + rect[:width], rect[:y] + rect[:height], color, z) 145 | Gosu::draw_line(rect[:x] + rect[:width], rect[:y] + rect[:height], color, rect[:x] + rect[:width], rect[:y], color, z) 146 | Gosu::draw_line(rect[:x] + rect[:width], rect[:y], color, rect[:x], rect[:y], color, z) 147 | end 148 | 149 | def check_for_collisions(rect1, rect2) 150 | # returns :top, :bottom, :left :right for the most intersected part, relative to 151 | # rect1 (so you can tell if you're jumping on a bad guy or running into him) 152 | # nil if no collisions 153 | intersection = rec_intersection([[rect1[:x], rect1[:y]], 154 | [rect1[:x] + rect1[:width], rect1[:y] + rect1[:height]]], 155 | [[rect2[:x], rect2[:y]], 156 | [rect2[:x] + rect2[:width], rect2[:y] + rect2[:height]]]) 157 | if intersection 158 | top_left, bottom_right = intersection 159 | # if wider than tall, which works since our enemies are tallish 160 | if (bottom_right[0] - top_left[0]) > (bottom_right[1] - top_left[1]) 161 | # top or bottom? 162 | if rect1[:y] == top_left[1] 163 | :top 164 | else 165 | :bottom 166 | end 167 | else 168 | # left or right? 169 | if rect1[:x] == top_left[0] 170 | :left 171 | else 172 | :right 173 | end 174 | end 175 | else 176 | nil 177 | end 178 | end 179 | 180 | def rec_intersection(rect1, rect2) 181 | # http://stackoverflow.com/questions/19442068/how-does-this-code-find-the-rectangle-intersection 182 | x_min = [rect1[0][0], rect2[0][0]].max 183 | x_max = [rect1[1][0], rect2[1][0]].min 184 | y_min = [rect1[0][1], rect2[0][1]].max 185 | y_max = [rect1[1][1], rect2[1][1]].min 186 | return nil if ((x_max < x_min) || (y_max < y_min)) 187 | return [[x_min, y_min], [x_max, y_max]] 188 | end 189 | end 190 | 191 | module Hero 192 | SPEED = 5 193 | end 194 | 195 | RunningHeroWindow.new.show -------------------------------------------------------------------------------- /running_hero/4.rb: -------------------------------------------------------------------------------- 1 | require 'gosu' 2 | 3 | # $DEBUG shows us bounding boxes 4 | $DEBUG = false 5 | 6 | # Now let's make enemies with a simple AI, and a score. 7 | 8 | class Enemy 9 | attr_accessor :image, :x, :y, :direction, :alive 10 | SPEED = 7 11 | def initialize(window, images, x, y, direction) 12 | @window = window 13 | @images = images 14 | @x = x 15 | @y = y 16 | @direction = direction 17 | @alive = true 18 | end 19 | 20 | def update 21 | return unless @alive 22 | image = current_image 23 | if(@direction == :left) 24 | @x -= 5 25 | else 26 | @x += 5 27 | end 28 | 29 | if @x + image.width < 0 30 | @direction = :right 31 | elsif @x > @window.width 32 | @direction = :left 33 | end 34 | end 35 | 36 | def draw 37 | if @alive 38 | image = current_image 39 | else 40 | image = @images.last 41 | end 42 | image.draw(@direction == :left ? @x : @x + image.width, @y, 1, @direction == :left ? 1 : -1) 43 | end 44 | 45 | def body 46 | image = current_image 47 | {:x => @x + 6, 48 | :y => @y + 20, 49 | :width => image.width - 12, 50 | :height => image.height - 20} 51 | end 52 | 53 | def current_image 54 | @images[(Gosu::milliseconds / 100 % 4)] 55 | end 56 | end 57 | 58 | class RunningHeroWindow < Gosu::Window 59 | def initialize 60 | super(960, 480) 61 | self.caption = "Running Hero Game" 62 | 63 | @background = Gosu::Image.new("assets/background.png") 64 | @hero_position = [50, 331] 65 | @enemy_position = [200, 331] 66 | @hero_direction = :right 67 | 68 | @hero = Gosu::Image::load_tiles("assets/hero_sheet.png", 64, 64) 69 | @current_hero_image = @hero.first 70 | 71 | @enemy_images = Gosu::Image::load_tiles("assets/enemy_sheet.png", 64, 64) 72 | @enemies = [Enemy.new(self, @enemy_images, 200, 331, :left)] 73 | @score = 0 74 | @font = Gosu::Font.new(64, :name => "assets/Pixeled.ttf") 75 | end 76 | 77 | def update 78 | if Gosu::button_down?(Gosu::KbRight) 79 | move(:right) 80 | elsif Gosu::button_down?(Gosu::KbLeft) 81 | move(:left) 82 | else 83 | @walking = false 84 | end 85 | 86 | jump if Gosu::button_down?(Gosu::KbSpace) 87 | 88 | handle_jump if @jumping 89 | 90 | @enemies.each{|enemy| enemy.update} 91 | # figure out what our hero should look like right now 92 | # the hero's sprite sheet looks like this: 93 | # [standing still, walking1, walking2, walking3, jumping up, falling down] 94 | if @hurt_until 95 | @current_hero_image = @hero[6] 96 | @hurt_until = nil if Gosu::milliseconds > @hurt_until 97 | elsif @jumping 98 | # use the velocity to figure out if we're rising or falling 99 | @current_hero_image = @vertical_velocity > 0 ? @hero[4] : @hero[5] 100 | elsif @walking 101 | # Gosu::milliseconds returns the number of millis since the game started. We want to see 102 | # a new animation frame about every 100 milliseconds or so, and we have three animation frames 103 | step = (Gosu::milliseconds / 100 % 3) + 1 104 | @current_hero_image = @hero[step] 105 | else 106 | # just standing still 107 | @current_hero_image = @hero[0] 108 | end 109 | handle_collisions 110 | end 111 | 112 | def draw 113 | @background.draw(0, 0, 0) 114 | @enemies.each{|enemy| enemy.draw} 115 | if @hero_direction == :right 116 | @current_hero_image.draw(@hero_position[0], @hero_position[1], 1) 117 | else 118 | # https://www.libgosu.org/cgi-bin/mwf/topic_show.pl?tid=1073 119 | @current_hero_image.draw(@hero_position[0] + @current_hero_image.width, @hero_position[1], 1, -1) 120 | end 121 | draw_collision_bodies 122 | @font.draw("Score: #{@score}", 5, 0, 10) 123 | end 124 | 125 | private 126 | 127 | def move(way) 128 | return if @hurt_until 129 | @walking = true 130 | if way == :right 131 | @hero_position = [@hero_position[0] + Hero::SPEED, @hero_position[1]] 132 | @hero_direction = :right 133 | else 134 | @hero_position = [@hero_position[0] - Hero::SPEED, @hero_position[1]] 135 | @hero_direction = :left 136 | end 137 | end 138 | 139 | def jump 140 | return if @jumping || @hurt_until 141 | @jumping = true 142 | @vertical_velocity = 30 143 | end 144 | 145 | def handle_jump 146 | gravity = 1.5 147 | ground_level = 331 # y offset where our hero is on the ground 148 | @hero_position = [@hero_position[0], @hero_position[1] - @vertical_velocity] 149 | 150 | if @vertical_velocity.round == 0 # top of the jump 151 | @vertical_velocity = -1 152 | elsif @vertical_velocity < 0 # falling down 153 | @vertical_velocity = @vertical_velocity * gravity 154 | else 155 | @vertical_velocity = @vertical_velocity / gravity 156 | end 157 | 158 | if @hero_position[1] >= ground_level 159 | @hero_position[1] = ground_level 160 | @jumping = false 161 | end 162 | end 163 | 164 | def handle_collisions 165 | # did the enemy and player collide? 166 | @player_rectangle = {:x => @hero_position[0] + 18, 167 | :y => @hero_position[1] + 18, 168 | :width => @current_hero_image.width - 36, 169 | :height => @current_hero_image.height - 18} 170 | @enemies.each do |enemy| 171 | return if @hurt_until 172 | next unless enemy.alive 173 | collision = check_for_collisions(@player_rectangle, enemy.body) 174 | if collision == :left 175 | @hero_position[0] += 30 176 | @hurt_until = Gosu::milliseconds + 200 177 | elsif collision == :right 178 | @hero_position[0] -= 30 179 | @hurt_until = Gosu::milliseconds + 200 180 | elsif collision == :bottom 181 | @jumping = true 182 | @vertical_velocity = 10 183 | enemy.alive = false 184 | @score += 1 185 | end 186 | end 187 | end 188 | 189 | def draw_collision_bodies 190 | draw_bounding_body(@player_rectangle) 191 | @enemies.each do |enemy| 192 | draw_bounding_body(enemy.body) 193 | end 194 | end 195 | 196 | def draw_bounding_body(rect, z = 10, color = Gosu::Color::GREEN) 197 | return unless $DEBUG 198 | Gosu::draw_line(rect[:x], rect[:y], color, rect[:x], rect[:y] + rect[:height], color, z) 199 | Gosu::draw_line(rect[:x], rect[:y] + rect[:height], color, rect[:x] + rect[:width], rect[:y] + rect[:height], color, z) 200 | Gosu::draw_line(rect[:x] + rect[:width], rect[:y] + rect[:height], color, rect[:x] + rect[:width], rect[:y], color, z) 201 | Gosu::draw_line(rect[:x] + rect[:width], rect[:y], color, rect[:x], rect[:y], color, z) 202 | end 203 | 204 | def check_for_collisions(rect1, rect2) 205 | # returns :top, :bottom, :left :right for the most intersected part, relative to 206 | # rect1 (so you can tell if you're jumping on a bad guy or running into him) 207 | # nil if no collisions 208 | intersection = rec_intersection([[rect1[:x], rect1[:y]], 209 | [rect1[:x] + rect1[:width], rect1[:y] + rect1[:height]]], 210 | [[rect2[:x], rect2[:y]], 211 | [rect2[:x] + rect2[:width], rect2[:y] + rect2[:height]]]) 212 | if intersection 213 | top_left, bottom_right = intersection 214 | # if wider than tall, which works since our enemies are tallish 215 | if (bottom_right[0] - top_left[0]) > (bottom_right[1] - top_left[1]) 216 | # top or bottom? 217 | if rect1[:y] == top_left[1] 218 | :top 219 | else 220 | :bottom 221 | end 222 | else 223 | # left or right? 224 | if rect1[:x] == top_left[0] 225 | :left 226 | else 227 | :right 228 | end 229 | end 230 | else 231 | nil 232 | end 233 | end 234 | 235 | def rec_intersection(rect1, rect2) 236 | # http://stackoverflow.com/questions/19442068/how-does-this-code-find-the-rectangle-intersection 237 | x_min = [rect1[0][0], rect2[0][0]].max 238 | x_max = [rect1[1][0], rect2[1][0]].min 239 | y_min = [rect1[0][1], rect2[0][1]].max 240 | y_max = [rect1[1][1], rect2[1][1]].min 241 | return nil if ((x_max < x_min) || (y_max < y_min)) 242 | return [[x_min, y_min], [x_max, y_max]] 243 | end 244 | end 245 | 246 | module Hero 247 | SPEED = 5 248 | end 249 | 250 | RunningHeroWindow.new.show -------------------------------------------------------------------------------- /running_hero/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem 'gosu', '~> 0.10.9.pre1' -------------------------------------------------------------------------------- /running_hero/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | gosu (0.10.9.pre1) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | gosu (~> 0.10.9.pre1) 11 | 12 | BUNDLED WITH 13 | 1.10.6 14 | -------------------------------------------------------------------------------- /running_hero/README.md: -------------------------------------------------------------------------------- 1 | # Running Hero 2 | 3 | There are 5 progressive versions of this game numbered 0 - 4 as the game develops through the talk. 4 | 5 | Part 0 is just statically drawing the hero on the screen. 6 | 7 | Part 1 is moving the hero around, and allowing the hero to jump. 8 | 9 | Part 2 is adding animation and alternate poses to the hero. 10 | 11 | Part 3 is collision detection with the stationary enemy. 12 | 13 | Part 4 is adding logic to move the enemy around and adding a score to the game, along with refactoring the enemy as an independent entity. 14 | 15 | # Running this game 16 | 17 | You'll need bundler installed, then you can just `bundle install` and e.g. `bundle exec ruby 0.rb` to run the game. 18 | 19 | You need to download the Pixeled font directly into the `assets/` folder before the last part of the game will work. It is available [here](http://www.dafont.com/pixeled.font). 20 | 21 | Credits: 22 | 23 | The license on the font used for scorekeeping does not allow me to distribute it in this package. It is available for free here: http://www.dafont.com/pixeled.font 24 | 25 | The hero and enemy images used in Running Hero are the work of GrafxKid on OpenGameArt and are available [here](http://opengameart.org/content/classic-hero-and-baddies-pack). -------------------------------------------------------------------------------- /running_hero/assets/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/running_hero/assets/background.png -------------------------------------------------------------------------------- /running_hero/assets/enemy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/running_hero/assets/enemy.png -------------------------------------------------------------------------------- /running_hero/assets/enemy_sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/running_hero/assets/enemy_sheet.png -------------------------------------------------------------------------------- /running_hero/assets/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/running_hero/assets/hero.png -------------------------------------------------------------------------------- /running_hero/assets/hero_sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/running_hero/assets/hero_sheet.png -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/.ruby-version: -------------------------------------------------------------------------------- 1 | system 2 | -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem 'gosu', '~> 0.10.9.pre1' -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | gosu (0.10.9.pre1) 5 | 6 | PLATFORMS 7 | ruby 8 | 9 | DEPENDENCIES 10 | gosu (~> 0.10.9.pre1) 11 | 12 | BUNDLED WITH 13 | 1.10.6 14 | -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/README.md: -------------------------------------------------------------------------------- 1 | # Winner Winner Chicken Spinner 2 | 3 | # Running 4 | 5 | `bundle install` 6 | `bundle exec ruby game.rb` 7 | 8 | # Credits 9 | 10 | The chicken image is the work of Stijn Ghesquiere, which is made available under the Creative Commons license here: https://commons.wikimedia.org/wiki/File:Braekel.jpg -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/assets/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/winner_winner_chicken_spinner/assets/arrow.png -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/assets/chicken_plate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/winner_winner_chicken_spinner/assets/chicken_plate.png -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/assets/chicken_raw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/winner_winner_chicken_spinner/assets/chicken_raw.jpg -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/assets/lose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/winner_winner_chicken_spinner/assets/lose.png -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/assets/win.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chamblin/make-games-in-ruby/c6be4f8bb3777ec20491fa30d6963574d99fec64/winner_winner_chicken_spinner/assets/win.png -------------------------------------------------------------------------------- /winner_winner_chicken_spinner/game.rb: -------------------------------------------------------------------------------- 1 | require 'gosu' 2 | 3 | class GameWindow < Gosu::Window 4 | def initialize 5 | super(480, 480) 6 | self.caption = "Winner Winner Chicken Spinner" 7 | 8 | @chicken_plate = Gosu::Image.new("assets/chicken_plate.png") 9 | @arrow = Gosu::Image.new("assets/arrow.png") 10 | @win_image = Gosu::Image.new("assets/win.png") 11 | @lose_image = Gosu::Image.new("assets/lose.png") 12 | 13 | @chicken_angle = 0 14 | @gameover = false 15 | @won = false 16 | end 17 | 18 | def update 19 | return if @gameover 20 | 21 | if Gosu::button_down?(Gosu::KbSpace) 22 | @gameover = true 23 | @won = did_we_win? 24 | return 25 | end 26 | 27 | @chicken_angle += 10 28 | @chicken_angle %= 360 29 | end 30 | 31 | def draw 32 | @arrow.draw(320, 200, 1) 33 | @chicken_plate.draw_rot(240, 240, 0, @chicken_angle) 34 | 35 | 36 | if @gameover 37 | image = @won ? @win_image : @lose_image 38 | image.draw(0, 120, 2) 39 | end 40 | end 41 | 42 | private 43 | 44 | def did_we_win? 45 | return @chicken_angle > 290 || @chicken_angle < 21 46 | end 47 | end 48 | 49 | window = GameWindow.new 50 | window.show --------------------------------------------------------------------------------