Class: GamesParadise::GUI::Sokoban::Game

Inherits:
Gosu::Window show all
Defined in:
lib/games_paradise/gui/gosu/sokoban/sokoban.rb

Constant Summary collapse

FILE_LEVELS =
#

FILE_LEVELS

#
GamesParadise.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

#


31
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
# File 'lib/games_paradise/gui/gosu/sokoban/sokoban.rb', line 31

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,
      "#{GamesParadise.project_base_directory?}"\
      "gui/gosu/sokoban/media/#{key}.png",
      50,
      50,
      false
    )
  }
  reset
  @deforms = Hash.new { |hash, key|
    zlevel = rand(GamesParadise::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

#


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

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

#


137
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
# File 'lib/games_paradise/gui/gosu/sokoban/sokoban.rb', line 137

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
        GamesParadise::GUI::Sokoban::ZLevel::WallFirst
      when 1
        GamesParadise::GUI::Sokoban::ZLevel::FloorFirst
      when 2
        GamesParadise::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, GamesParadise::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, GamesParadise::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.

#


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

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(//)
    }
    ::GamesParadise::GUI::Sokoban::Level.new(tiles, player)
  }
end

#next_levelObject

#

next_level

Progress to the next level via this method.

#


98
99
100
101
# File 'lib/games_paradise/gui/gosu/sokoban/sokoban.rb', line 98

def next_level
  @level_number += 1
  reload_level
end

#reload_levelObject

#

reload_level

#


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

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

#


65
66
67
# File 'lib/games_paradise/gui/gosu/sokoban/sokoban.rb', line 65

def reset
  @level_number = 0
end

#set_view(x, y) ⇒ Object

#

set_view

#


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

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

#


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

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

#updateObject

#

update

#


118
119
120
# File 'lib/games_paradise/gui/gosu/sokoban/sokoban.rb', line 118

def update
  next_level if @level.finished?
end