class Pacman::GhostsController

handles behaviour of ghosts

Attributes

colission[RW]

Public Class Methods

new(level) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 4
def initialize(level)
  @level = level
  @colission = false
end

Public Instance Methods

update() click to toggle source
# File lib/pacman/ghosts_controller.rb, line 9
def update
  @level.ghosts_frozen -= 1 unless (@level.ghosts_frozen == 0)
  return unless (@level.ghosts_frozen == 0)

  update_blinky ||
  update_pinky ||
  update_inky ||
  update_clyde
end

Private Instance Methods

behave_random(ghost, dirs) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 108
def behave_random(ghost, dirs)
  return if dirs.nil?

  if continue_forward?(ghost, dirs)
    move(ghost, ghost.direction)
  else
    if (dirs.size == 2)
      if (dirs.first == inverse_direction(ghost.direction))
        move(ghost, dirs.last)
      else
        move(ghost, dirs.first)
      end
      return
    end

    dir = random_direction(dirs)

    move(ghost, dir)
  end
end
behave_slow_random(ghost, dirs) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 97
def behave_slow_random(ghost, dirs)
  if ghost.stopped
    ghost.stopped = false
    return
  end

  ghost.stopped = true

  behave_random(ghost, dirs)
end
behave_smart(ghost, dirs) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 51
def behave_smart(ghost, dirs)
  return if dirs.nil?

  if continue_forward?(ghost, dirs)
    move(ghost, ghost.direction)
    return
  end

  return if try_simply_continue(ghost, dirs)

  dir = nil
  if (ghost.x - @level.player.x).abs > (ghost.y - @level.player.y).abs
    # prefer horizontal direction
    if ghost.x - @level.player.x > 1
      dir = :left if can_move_left?(ghost)
    else
      dir = :right if can_move_right?(ghost)
    end

    if dir.nil?
      if ghost.y - @level.player.y > 1
        dir = :up if can_move_up?(ghost)
      else
        dir = :down if can_move_down?(ghost)
      end
    end
  else
    # prefer vertical direction
    if ghost.y - @level.player.y > 1
      dir = :up if can_move_up?(ghost)
    else
      dir = :down if can_move_down?(ghost)
    end

    if dir.nil?
      if ghost.y - @level.player.y > 1
        dir = :left if can_move_left?(ghost)
      else
        dir = :right if can_move_right?(ghost)
      end
    end
  end
  dir = random_direction(dirs) if dir.nil?
  move(ghost, dir)
end
can_move_down?(ghost) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 188
def can_move_down?(ghost)
  return false unless ghost.y < @level.height
  obj = @level.get(ghost.x, ghost.y + 1)
  obj.nil? || obj.passable?
end
can_move_left?(ghost) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 170
def can_move_left?(ghost)
  return false unless ghost.x > 0
  obj = @level.get(ghost.x - 1, ghost.y)
  obj.nil? || obj.passable?
end
can_move_right?(ghost) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 176
def can_move_right?(ghost)
  return false unless ghost.y < @level.width - 1
  obj = @level.get(ghost.x + 1, ghost.y)
  obj.nil? || obj.passable?
end
can_move_up?(ghost) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 182
def can_move_up?(ghost)
  return false unless ghost.y > 0
  obj = @level.get(ghost.x, ghost.y - 1)
  obj.nil? || obj.passable?
end
colission_with_player?(ghost) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 236
def colission_with_player?(ghost)
  ghost.x == @level.player.x && ghost.y == @level.player.y
end
continue_forward?(ghost, dirs) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 194
def continue_forward?(ghost, dirs)
  return false if dirs.size > 2
  return true if dirs.size == 1 && ghost.direction == dirs.first
  (dirs.include?(:left) && dirs.include?(:right) &&
  (ghost.direction == :left || ghost.direction == :right)) ||
  (dirs.include?(:up) && dirs.include?(:down) &&
  (ghost.direction == :up || ghost.direction == :down))
end
inverse_direction(direction) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 203
def inverse_direction(direction)
  case direction
  when :left
    :right
  when :right
    :left
  when :up
    :down
  when :down
    :up
  end
end
move(ghost, direction) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 216
def move(ghost, direction)
  if colission_with_player?(ghost)
    @colission = true
    return
  end

  ghost.direction = direction
  case direction
  when :left
    ghost.x -= 1
  when :right
    ghost.x += 1
  when :up
    ghost.y -= 1
  when :down
    ghost.y += 1
  end
  @colission = true if colission_with_player?(ghost)
end
possible_directions(ghost) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 141
def possible_directions(ghost)
  res = []
  res << :left if can_move_left?(ghost)
  res << :right if can_move_right?(ghost)
  res << :up if can_move_up?(ghost)
  res << :down if can_move_down?(ghost)

  res
end
random_direction(dirs) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 151
def random_direction(dirs)
  dir = nil
  loop do
    d = rand(4)
    case d
    when 0
      dir = :left
    when 1
      dir = :right
    when 2
      dir = :up
    when 3
      dir = :down
    end
    break if dirs.include?(dir)
  end
  dir
end
try_simply_continue(ghost, dirs) click to toggle source
# File lib/pacman/ghosts_controller.rb, line 240
def try_simply_continue(ghost, dirs)
  if (dirs.size == 2)
    # neotoci se uprostred cesty
    if (dirs.first == inverse_direction(ghost.direction))
      move(ghost, dirs.last)
    else
      move(ghost, dirs.first)
    end
    return true
  end
  false
end
update_blinky() click to toggle source
# File lib/pacman/ghosts_controller.rb, line 23
def update_blinky
  ghost = @level.ghosts[:blinky]
  dirs = update_ghost(ghost)

  behave_smart(ghost, dirs)
end
update_clyde() click to toggle source
# File lib/pacman/ghosts_controller.rb, line 44
def update_clyde
  ghost = @level.ghosts[:clyde]
  dirs = update_ghost(ghost)

  behave_slow_random(ghost, dirs)
end
update_ghost(ghost) click to toggle source

return possible directions if decision needed, nil otherwise

# File lib/pacman/ghosts_controller.rb, line 130
def update_ghost(ghost)
  dirs = possible_directions(ghost)
  case
  when dirs.size > 1
    return dirs
  when dirs.size == 1
    move(ghost, dirs.first)
  end
  nil
end
update_inky() click to toggle source
# File lib/pacman/ghosts_controller.rb, line 37
def update_inky
  ghost = @level.ghosts[:inky]
  dirs = update_ghost(ghost)

  behave_random(ghost, dirs)
end
update_pinky() click to toggle source
# File lib/pacman/ghosts_controller.rb, line 30
def update_pinky
  ghost = @level.ghosts[:pinky]
  dirs = update_ghost(ghost)

  behave_random(ghost, dirs)
end