simplay/bofrev

View on GitHub
demos/sokoban/sokoban_map.rb

Summary

Maintainability
A
25 mins
Test Coverage
require 'map'
require 'game_settings'
require 'color'
require_relative 'level_parser'

class SokobanMap < Map

  def initialize(game)
    super(game, :placed)

    lp = LevelParser.new(@grid, 'lvl1')

    @player = lp.player
    @chest = lp.chest
    @target = lp.target

    @chest_init_pos = @chest.value
    @target_init_pos = @target.value

  end

  # defines how user input should be handled to update the game state.
  def process_event(message)
    pp = @player.value
    case message.type
    when D_KEY
      new_pp = Point2f.new(pp.x+1, pp.y)
      handle_update(new_pp, pp, Point2f.new(1,0))
    when A_KEY
      new_pp = Point2f.new(pp.x-1, pp.y)
      handle_update(new_pp, pp,Point2f.new(-1,0))
    when S_KEY
      new_pp = Point2f.new(pp.x, pp.y+1)
      handle_update(new_pp, pp, Point2f.new(0,1))
    when W_KEY
      new_pp = Point2f.new(pp.x, pp.y-1)
      handle_update(new_pp, pp, Point2f.new(0,-1))
    end
  end

  # does nothing
  def process_ticker
  end

  private

  def handle_update(new_pp, pp, del)

    if hist_chest?(new_pp)
      unless hit_wall?(Point2f.new(@chest.value.x+del.x, @chest.value.y+del.y))
        set_entities(@chest.value.x+del.x, @chest.value.y+del.y)
        @player = @grid.field_at(new_pp.x, new_pp.y)
        @player.color = Color.red
        @player.value = Point2f.new(new_pp.x, new_pp.y)
        reset_player_pos_at(pp)
      end
    elsif hit_target?(new_pp)

    elsif !hit_wall?(new_pp)
      @player = @grid.field_at(new_pp.x, new_pp.y)
      @player.color = Color.red
      @player.value = Point2f.new(new_pp.x, new_pp.y)
      reset_player_pos_at(pp)
      set_entities(@chest.value.x, @chest.value.y)
    end

  end

  def reset_player_pos_at(pp)
    old_p = @grid.field_at(pp.x, pp.y)
    old_p.color = Color.white
    old_p.value = nil
  end

  def set_entities(x, y)
    @chest = @grid.field_at(x, y)
    @chest.color = Color.blue
    @chest.value = Point2f.new(x,y)

    reset_target

    if hit_target?(@chest.value)
      initiate_game_over
    end

  end

  def reset_target
    @target = @grid.field_at(@target_init_pos.x, @target_init_pos.y)
    @target.color = Color.green
    @target.value = Point2f.new(@target_init_pos.x,@target_init_pos.y)
  end

  def hist_chest?(point)
    point == @chest.value
  end

  def hit_wall?(point)
    @grid.field_at(point.x, point.y).border?
  end

  def hit_target?(point)
    point.x == @target.value.x && point.y == @target.value.y
  end

end