Class: GamesAndRpgParadise::GUI::Sokoban::Game

Inherits:
Gosu::Window
  • Object
show all
Defined in:
lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb

Constant Summary collapse

FILE_LEVELS =
#

FILE_LEVELS

#
GamesAndRpgParadise.project_base_directory?+
'gui/gosu/sokoban/levels/levels.md'

Instance Method Summary collapse

Methods inherited from Gosu::Window

#gosu_button_down?, #image, #image10?, #image1?, #image2?, #image3?, #image4?, #image5?, #image6?, #image7?, #image8?, #image9?, #on_left_arrow_pressed?, #on_right_arrow_pressed?, #q_means_quit, #set_font, #set_title, #sqrt, #tab_key?, #write_this_text

Constructor Details

#initializeGame

#

initialize

#


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 32

def initialize
  @screen_width, @screen_height = 800, 600
  @scrolling = 0.95
  super(@screen_width, @screen_height, false)
  self.caption = 'Sokoban'

  # ======================================================================= #
  # All images are stored in a Hash.
  # ======================================================================= #
  @images = Hash.new { |hash, key|
    hash[key] = Gosu::Image.load_tiles(
      self,
      "#{GamesAndRpgParadise.project_base_directory?}"\
      "gui/gosu/sokoban/media/#{key}.png",
      50,
      50,
      false
    )
  }
  reset
  @deforms = Hash.new { |hash, key|
    zlevel = rand(GamesAndRpgParadise::GUI::Sokoban::ZLevel::TileSpan)
    zoom_x = rand / 5 + 1.05
    zoom_y = rand / 5 + 1.05
    angle = rand(4) * 90 + rand(10) - 5
    hash[key] = [zlevel, angle, zoom_x, zoom_y]
  }
  load_levels
  reload_level
end

Instance Method Details

#button_down(button_id) ⇒ Object

#

button_down

#


192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 192

def button_down(button_id)
  case button_id
  when Gosu::Button::KbLeft # left-key
    @level.go_left
  when Gosu::Button::KbRight # right-key
    @level.go_right
  when Gosu::Button::KbUp # up-key
    @level.go_up
  when Gosu::Button::KbDown # down-key
    @level.go_down
  when Gosu::Button::KbEscape # escape-key
    reload_level
  # ======================================================================= #
  # Close the window on "escape" or "q" button.
  # ======================================================================= #
  when Gosu::KbEscape,
       Gosu::KbQ
    close
  end
end

#drawObject

#

draw

#


138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 138

def draw
  set_view(@level.px * 50, @level.py * 50)
  # Draw the map.
  @level.tiles.each_with_index do |line, ty|
    line.each_with_index do |tile, tx|
      ti = tile_to_index(tile)
      x, y = tx * 50 + 25, ty * 50 + 25
      zoff, angle, zoom_x, zoom_y = *@deforms[x + y << 3]
  
      zlevel = zoff + case tile_to_index(tile)
      when 0
        GamesAndRpgParadise::GUI::Sokoban::ZLevel::WallFirst
      when 1
        GamesAndRpgParadise::GUI::Sokoban::ZLevel::FloorFirst
      when 2
        GamesAndRpgParadise::GUI::Sokoban::ZLevel::DropZoneFirst
      end

      dx, dy = x - @view_x / 2, y - @view_y / 2

      @images['tiles'][ti].draw_rot(
        dx, dy, zlevel, angle,
        0.5, 0.5, zoom_x, zoom_y
      )

      if @level.boulder?(tx, ty)
        # The second image is a "boulder".
        @images['objects'][1].draw_rot(
          dx, dy, GamesAndRpgParadise::GUI::Sokoban::ZLevel::Boulder, 0
        )
      end
    end
  end

  # Draw the player.
  dx, dy = @level.px * 50 - @view_x / 2, @level.py * 50 - @view_y / 2
  # Element [0] refers to the player.
  @images['objects'][0].draw(
    dx, dy, GamesAndRpgParadise::GUI::Sokoban::ZLevel::Player
  )
end

#load_levels(i = FILE_LEVELS) ⇒ Object

#

load_levels

This method will load the various level that can be used for sokoban.

#


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 76

def load_levels(
    i = FILE_LEVELS
  )
  dataset = File.read(i)
  @levels = dataset.split(/^\r*$/).map { |data|
    player = nil
    y = 0
    tiles = data.split(/\r*\n/).map { |line|
      if x = line.index(/[@+]/)
        player = [x, y]
      end
      y += 1
      line.tr('@+', ' .').split(//)
    }
    ::GamesAndRpgParadise::GUI::Sokoban::Level.new(tiles, player)
  }
end

#next_levelObject

#

next_level

Progress to the next level via this method.

#


99
100
101
102
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 99

def next_level
  @level_number += 1
  reload_level
end

#reload_levelObject

#

reload_level

#


107
108
109
110
111
112
113
114
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 107

def reload_level
  dataset = Marshal.dump(@levels[@level_number])
  @level = Marshal.load(dataset)
  @view_x = @level.px * 50 - @screen_width / 2
  @view_y = @level.py * 50 - @screen_height / 2
  self.close unless @level
  @deforms.clear
end

#resetObject

#

reset

#


66
67
68
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 66

def reset
  @level_number = 0
end

#set_view(x, y) ⇒ Object

#

set_view

#


126
127
128
129
130
131
132
133
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 126

def set_view(x, y)
  new_view_x = x - @screen_width / 2
  new_view_y = y - @screen_height / 2

  of, nf = @scrolling, 1.0 - @scrolling
  @view_x = (@view_x * of + new_view_x * nf).round
  @view_y = (@view_y * of + new_view_y * nf).round
end

#tile_to_index(tile) ⇒ Object

#

tile_to_index

#


183
184
185
186
187
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 183

def tile_to_index(tile)
  '# .'.index(
    tile.tr('*o', '. ')
  )
end

#updateObject

#

update

#


119
120
121
# File 'lib/games_and_rpg_paradise/gui/gosu/sokoban/sokoban.rb', line 119

def update
  next_level if @level.finished?
end