Class: GamesAndRpgParadise::Tetris::Shape

Inherits:
Object
  • Object
show all
Defined in:
lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb

Direct Known Subclasses

ShapeCube, ShapeI, ShapeL, ShapeT, ShapeZ

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(game) ⇒ Shape

#

initialize

#


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 22

def initialize(game)
  # ======================================================================= #
  # === @x
  # ======================================================================= #
  @x = 0
  # ======================================================================= #
  # === @y
  # ======================================================================= #
  @y = 0
  @last_fall_update = Gosu.milliseconds
  @last_move_update = Gosu.milliseconds
  @game = game
  @blocks = [
    GamesAndRpgParadise::Tetris::Block.new(game),
    GamesAndRpgParadise::Tetris::Block.new(game),
    GamesAndRpgParadise::Tetris::Block.new(game),
    GamesAndRpgParadise::Tetris::Block.new(game)
  ]
  # Rotation is done about this block
  @rotation_block = @blocks[1]
  reset_internal_variables
end

Instance Attribute Details

#rotationObject

Returns the value of attribute rotation.



17
18
19
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 17

def rotation
  @rotation
end

Instance Method Details

#apply_rotationObject

#

apply_rotation

#


70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 70

def apply_rotation
  # Each rotation is a 90 degree in the clockwise direction
  unless @rotation_block.nil?
    (1 .. @rotation.modulo(@rotation_cycle)).each { |i|
      @blocks.each { |block|
        old_x = block.x
        old_y = block.y
        block.x = @rotation_block.x + (@rotation_block.y - old_y)
        block.y = @rotation_block.y - (@rotation_block.x - old_x)
      }
    }
  end
end

#collideObject

#

collide

#


197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 197

def collide
  get_blocks.each { |block|
    collision = block.collide_with_other_blocks;
    if collision
      return true
    end
  }
  bounds = get_bounds

  if bounds[3] > @game.height
    return true
  end
  if bounds[2] > @game.width
    return true
  end
  if bounds[0] < 0
    return true
  end
  return false
end

#drawObject

#

draw

#


150
151
152
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 150

def draw
  get_blocks.each { |block| block.draw }
end

#get_boundsObject

#

get_bounds

#


105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 105

def get_bounds
  # Go throug all blocks to find the bounds of this shape.
  x_min = []
  y_min = []
  x_max = []
  y_max = []
  @blocks.each { |block|
    x_min << block.x
    y_min << block.y
    x_max << block.x + block.width
    y_max << block.y + block.height
  }
  return [x_min.min, y_min.min, x_max.max, y_max.max]
end

#needs_fall_update?Boolean

#

needs_fall_update?

Updates to movement are done periodically to allow the player time for reaction.

#

Returns:

  • (Boolean)


126
127
128
129
130
131
132
133
134
135
136
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 126

def needs_fall_update?
  # If the user pressed the down-key.
  if @game.button_down?(Gosu::KbDown)
    updateInterval = 100
  else
    updateInterval = 500 - @game.level*50
  end
  if (Gosu.milliseconds - @last_fall_update) > updateInterval
    @last_fall_update = Gosu.milliseconds
  end
end

#needs_move_update?Boolean

#

needs_move_update?

#

Returns:

  • (Boolean)


141
142
143
144
145
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 141

def needs_move_update?
  if (Gosu.milliseconds - @last_move_update > 100)
    @last_move_update = Gosu.milliseconds
  end
end

#reset_internal_variablesObject

#

reset_internal_variables

#


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 48

def reset_internal_variables
  # ======================================================================= #
  # === @rotation_cycle
  #
  # How many rotations we can do before a full cycle?
  # ======================================================================= #
  @rotation_cycle = 1
  # ======================================================================= #
  # === @rotation
  #
  # The current rotation state is kept in the following instance variable.
  # ======================================================================= #
  @rotation = 0
  # ======================================================================= #
  # === @falling
  # ======================================================================= #
  @falling = true
end

#reverseObject

#

reverse

Note that the following function is defined properly only when the object is unrotated. Otherwise the line of symmetry will be misplaced and wrong results will be produced.

#


91
92
93
94
95
96
97
98
99
100
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 91

def reverse
  # ======================================================================= #
  # Mirror the shape by the y axis, effectively creating shape
  # ======================================================================= #
  # counterparts such as 'L' and 'J'.
  center = (get_bounds[2] + get_bounds[0]) / 2.0
  @blocks.each { |block|
    block.x = 2*center - block.x - @game.block_width
  }
end

#updateObject

#

update

#


157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/games_and_rpg_paradise/gui/gosu/tetris/shape.rb', line 157

def update
  if @falling
    # ===================================================================== #
    # After a movement or gravity update, we check if the moved shape
    # collides with the world. If it does, we restore its position
    # to the last known good position.
    # ===================================================================== #
    old_x = @x
    old_y = @y
    if needs_fall_update?
      @y = (@y + @game.block_height)
    end

    # Important to note is that we do 2 collision checks - once we moved on the x axis and once we moved on the y axis
    # This way we can determine which of the 2 movements is responisble for the collision and learn on which side of the colliding block
    # the collision occured.
    if collide
      @y = old_y
      @falling = false
      @game.spawn_next_shape
      @game.delete_lines_of(self)
    else
      if needs_move_update?
        if (@game.button_down?(Gosu::KbLeft))
          @x = (@x - @game.block_width)
        end
        if (@game.button_down?(Gosu::KbRight))
          @x = ( @x + @game.block_width)
        end
        if collide
          @x = old_x
        end
      end
    end
  end
end