myhunt/ruby/bin/gosuhunt

135 lines
4.3 KiB
Text
Raw Normal View History

2023-02-09 15:53:48 +01:00
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'gosu'
2023-03-15 14:43:28 +01:00
require 'optparse'
2023-02-09 15:53:48 +01:00
require 'minehunt'
class GosuHunt < Gosu::Window
2023-03-15 14:43:28 +01:00
def initialize( number_of_mines, scale )
@scale = scale
@sprite_size = 6
2023-02-09 15:53:48 +01:00
@number_of_mines = number_of_mines
@field = MineHunt::Board.new( @number_of_mines )
@finished = false
@state = { dead: false, victory: false }
2023-02-09 16:10:28 +01:00
2023-02-09 16:21:33 +01:00
@font = Gosu::Font.new( 20 )
2023-03-15 14:32:41 +01:00
@images = { explorer: Gosu::Image.from_blob( @sprite_size * @scale, @sprite_size * @scale, bits_to_rgbas( '000000001100011110011110001100000000' ) ),
dead_explorer: Gosu::Image.from_blob( @sprite_size * @scale, @sprite_size * @scale, bits_to_rgbas( '100001010010001100001100010010100001' ) ),
door: Gosu::Image.from_blob( @sprite_size * @scale, @sprite_size * @scale, bits_to_rgbas( '010101101010' * ( @sprite_size / 2 ) ) ),
mine: Gosu::Image.from_blob( @sprite_size * @scale, @sprite_size * @scale, bits_to_rgbas( '111111110011100001100001110011111111' ) ),
cell: Gosu::Image.from_blob( @sprite_size * @scale, @sprite_size * @scale, bits_to_rgbas( '1' * @sprite_size * @sprite_size ) ),
visited_cell: Gosu::Image.from_blob( @sprite_size * @scale, @sprite_size * @scale, bits_to_rgbas( '0' * @sprite_size * @sprite_size ) ) }
super ( ( @sprite_size + 1 ) * @field.width * @scale ) + @scale,
( ( @sprite_size + 1 ) * @field.height * @scale ) + @scale + 20
self.caption = 'Gosu Hunt'
end
def bits_to_rgbas( bits )
2023-03-15 14:32:41 +01:00
bits.scan(/.{#{@sprite_size}}/).map do |line|
line.gsub( '0', "\0\0\0\0" * @scale ).gsub( '1', "\255\255\255\255" * @scale ) * @scale
end.join
2023-02-09 16:10:28 +01:00
end
def new_level
@field = MineHunt::Board.new( @number_of_mines )
@finished = false
@state = { dead: false, victory: false }
2023-02-09 15:53:48 +01:00
end
def button_up(id)
2023-02-09 16:10:28 +01:00
if @finished
case id
when Gosu::KB_ESCAPE, Gosu::KB_Q
close
when Gosu::KB_R
new_level
else
super
end
2023-02-09 15:53:48 +01:00
else
2023-02-09 16:10:28 +01:00
case id
when Gosu::KB_ESCAPE, Gosu::KB_Q
close
when Gosu::KB_R
new_level
when Gosu::KB_NUMPAD_1
@state = @field.move 'down-left'
when Gosu::KB_NUMPAD_2, Gosu::KB_DOWN
@state = @field.move 'down'
when Gosu::KB_NUMPAD_3
@state = @field.move 'down-right'
when Gosu::KB_NUMPAD_4, Gosu::KB_LEFT
@state = @field.move 'left'
when Gosu::KB_NUMPAD_6, Gosu::KB_RIGHT
@state = @field.move 'right'
when Gosu::KB_NUMPAD_7
@state = @field.move 'up-left'
when Gosu::KB_NUMPAD_8, Gosu::KB_UP
@state = @field.move 'up'
when Gosu::KB_NUMPAD_9
@state = @field.move 'up-right'
else
super
end
2023-02-09 15:53:48 +01:00
end
@finished = @state[:dead] || @state[:victory]
end
def update; end
def draw
2023-03-14 14:23:15 +01:00
self.caption = if @state[:dead]
"You blew up!! :(, score: #{@field.score} "
2023-03-14 14:23:15 +01:00
elsif @state[:victory]
"You won!! :), score: #{@field.score} "
2023-03-14 14:23:15 +01:00
else
"Near #{@field.count_nearby_mines} mines, score: #{@field.score}"
2023-03-14 14:23:15 +01:00
end
2023-02-09 15:53:48 +01:00
2023-03-14 14:23:15 +01:00
@font.draw_text( caption, 0, 0, 0 )
2023-02-09 15:53:48 +01:00
@field.height.times do |y|
@field.width.times do |x|
2023-02-09 16:10:28 +01:00
( if [@field.explorer_x, @field.explorer_y] == [x, y]
@state[:dead] ? @images[:dead_explorer] : @images[:explorer]
elsif [@field.width, @field.height] == [x + 1, y + 1]
@images[:door]
elsif @field.field[[x, y]].open
@images[:visited_cell]
elsif @field.field[[x, y]].mine && ( @state[:dead] || @state[:victory] )
@images[:mine]
else
@images[:cell]
2023-03-15 14:32:41 +01:00
end ).draw ( ( @sprite_size + 1 ) * x * @scale ) + @scale,
( ( @sprite_size + 1 ) * y * @scale ) + @scale + 20,
0
2023-02-09 15:53:48 +01:00
end
end
end
end
2023-03-15 14:43:28 +01:00
options = { number_of_mines: 20,
scale: 3 }
OptionParser.new do |opts|
opts.banner = 'Usage: gosuhunt <options>'
2023-02-09 15:53:48 +01:00
2023-03-15 14:43:28 +01:00
opts.on( '-m', '--mines INT' ) do |nb_mines|
options[:number_of_mines] = nb_mines.to_i
end
opts.on( '-s', '--scale INT' ) do |scale|
options[:scale] = scale.to_i
end
end
.parse!
GosuHunt.new( options[:number_of_mines], options[:scale] )
.show