Class: Entity::Gecko

Inherits:
Entity show all
Includes:
Comparable, Player
Defined in:
lib/game_2d/entity/gecko.rb

Constant Summary collapse

MAX_HP =
1
BUILD_TIME =

Game ticks it takes before a block’s HP is raised by 1

7
BRAKE_SPEED =

Amount to decelerate each tick when braking

4
MOVES_FOR_KEY_HELD =
{
  Gosu::KbLeft         => :slide_left,
  Gosu::KbA            => :slide_left,
  Gosu::KbRight        => :slide_right,
  Gosu::KbD            => :slide_right,
  Gosu::KbRightControl => :brake,
  Gosu::KbLeftControl  => :brake,
  Gosu::KbDown         => :build,
  Gosu::KbS            => :build,
}

Constants included from EntityConstants

EntityConstants::CELL_WIDTH_IN_PIXELS, EntityConstants::MAX_VELOCITY, EntityConstants::PIXEL_WIDTH, EntityConstants::WIDTH

Instance Attribute Summary collapse

Attributes included from Player

#complex_move, #player_name, #score

Attributes inherited from Entity

#a, #moving, #space, #x, #x_vel, #y, #y_vel

Instance Method Summary collapse

Methods included from Player

#add_move, #die, #draw, #draw_zorder, #initialize_player, #next_move, #perform_complex_move, #replace_player_entity, #to_s

Methods inherited from Entity

#above, #accelerate, #angle_to_vector, #beneath, #bottom_cell_y, #cx, #cy, #direction, #direction_to, #doomed?, #draw, #draw_angle, #draw_animation, #draw_image, #draw_zorder, #drop_diagonal, #empty_above?, #empty_on_left?, #empty_on_right?, #empty_underneath?, #entities_obstructing, #going_past_entity, #grab!, #grabbed?, #i_hit, #left_cell_x, #move, #move_x, #move_y, #moving?, #next_to, #occupied_cells, #on_left, #on_right, #opaque, #pixel_x, #pixel_y, #release!, #right_cell_x, #slide_around, #slow_by, #slower_speed, #teleportable?, #to_s, #top_cell_y, #underfoot, #vector_to_angle, #wake!, #warp

Methods included from ClassMethods

#bottom_cell_y_at, #constrain_velocity, #left_cell_x_at, #right_cell_x_at, #top_cell_y_at

Methods included from Transparency

#transparent?

Methods included from Registerable

#nullsafe_registry_id, #registry_id, #registry_id=, #registry_id?, #registry_id_safe

Methods included from Serializable

#<=>, #==, as_json, #eql?, from_json, #hash, #to_json, #to_s

Constructor Details

#initialize(player_name = "<unknown>") ⇒ Gecko

Returns a new instance of Gecko.



38
39
40
41
42
43
44
45
46
# File 'lib/game_2d/entity/gecko.rb', line 38

def initialize(player_name = "<unknown>")
  super
  initialize_player
  @player_name = player_name
  @score = 0
  @hp = MAX_HP
  @build_block_id = nil
  @build_level = 0
end

Instance Attribute Details

#build_block_idObject

Returns the value of attribute build_block_id.



36
37
38
# File 'lib/game_2d/entity/gecko.rb', line 36

def build_block_id
  @build_block_id
end

#hpObject

Returns the value of attribute hp.



36
37
38
# File 'lib/game_2d/entity/gecko.rb', line 36

def hp
  @hp
end

Instance Method Details

#all_stateObject



209
210
211
212
213
# File 'lib/game_2d/entity/gecko.rb', line 209

def all_state
  # Player name goes first, so we can sort on that
  super.unshift(player_name).push(
    score, @hp, build_block_id, @complex_move)
end

#as_jsonObject



215
216
217
218
219
220
221
222
223
# File 'lib/game_2d/entity/gecko.rb', line 215

def as_json
  super.merge!(
    :player_name => player_name,
    :score => score,
    :hp => @hp,
    :build_block => @build_block_id,
    :complex_move => @complex_move.as_json
  )
end

#brakeObject



122
# File 'lib/game_2d/entity/gecko.rb', line 122

def brake; slow_by BRAKE_SPEED; end

#buildObject

Create the actual block



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/game_2d/entity/gecko.rb', line 134

def build
  if building?
    @build_level += 1
    if @build_level >= BUILD_TIME
      @build_level = 0
      build_block.hp += 1
    end
  else
    bb = Entity::Block.new(@x, @y)
    bb.owner_id = registry_id
    bb.hp = 1
    if @space << bb # generates an ID
      @build_block_id = bb.registry_id
      @build_level = 0
    end
  end
end

#build_blockObject



60
61
62
63
64
# File 'lib/game_2d/entity/gecko.rb', line 60

def build_block
  return nil unless building?
  fail "Can't look up build_block when not in a space" unless @space
  @space[@build_block_id] or fail "Don't have build_block #{@build_block_id}"
end

#building?Boolean

Returns:

  • (Boolean)


58
# File 'lib/game_2d/entity/gecko.rb', line 58

def building?; @build_block_id; end

#check_for_disown_blockObject



154
155
156
157
158
159
160
# File 'lib/game_2d/entity/gecko.rb', line 154

def check_for_disown_block
  return unless building?
  return if @space.entities_overlapping(@x, @y).include?(build_block)
  build_block.owner_id = nil
  build_block.wake!
  disown_block
end

#destroy!Object



71
72
73
# File 'lib/game_2d/entity/gecko.rb', line 71

def destroy!
  build_block.owner_id = nil if building?
end

#disown_blockObject



152
# File 'lib/game_2d/entity/gecko.rb', line 152

def disown_block; @build_block_id, @build_level = nil, 0; end

#fire(x_vel, y_vel) ⇒ Object

Create the actual pellet



127
128
129
130
131
# File 'lib/game_2d/entity/gecko.rb', line 127

def fire(x_vel, y_vel)
  pellet = Entity::Pellet.new(@x, @y, 0, x_vel, y_vel)
  pellet.owner = self
  @space << pellet
end

#flipObject



124
# File 'lib/game_2d/entity/gecko.rb', line 124

def flip; self.a += 180; end

#generate_move_from_click(x, y) ⇒ Object

Called by GameWindow Should return the move to be sent via ClientConnection (or nil)



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/game_2d/entity/gecko.rb', line 169

def generate_move_from_click(x, y)
  if y < cy # Firing up
    y_vel = -Math.sqrt(2 * (cy - y)).round
    x_vel = (cx - x) / y_vel
  else
    y_vel = 0
    if y == cy
      return if x == cx
      x_vel = (x <=> cx) * MAX_VELOCITY
    else
      range = x - cx
      x_vel = (Math.sqrt(1.0 / (2.0 * (y - cy))) * range).round
    end
  end
  [:fire, {:x_vel => x_vel, :y_vel => y_vel}]
end

#harmed_by(other, damage = 1) ⇒ Object



66
67
68
69
# File 'lib/game_2d/entity/gecko.rb', line 66

def harmed_by(other, damage=1)
  self.hp -= damage
  die if hp <= 0
end

#image_filenameObject



234
# File 'lib/game_2d/entity/gecko.rb', line 234

def image_filename; "gecko.png"; end

#move_for_keypress(keypress) ⇒ Object

Called by GameWindow Should return the move to be sent via ClientConnection (or nil) This is for queued keypresses, i.e. those that happen on key-down only (just once for a press), not continuously for as long as held down



192
193
194
195
196
197
# File 'lib/game_2d/entity/gecko.rb', line 192

def move_for_keypress(keypress)
  case keypress
    when Gosu::KbUp, Gosu::KbW
      return building? ? :rise_up : :flip
  end
end

#moves_for_key_heldObject

Called by GameWindow Should return a map where the keys are… keys, and the values are the corresponding moves to be sent via ClientConnection This is for non-queued keypresses, i.e. those that happen continuously for as long as held down



205
206
207
# File 'lib/game_2d/entity/gecko.rb', line 205

def moves_for_key_held
  MOVES_FOR_KEY_HELD
end

#rise_upObject



162
163
164
# File 'lib/game_2d/entity/gecko.rb', line 162

def rise_up
  self.complex_move = Move::RiseUp.new(self)
end

#should_fall?Boolean

Returns:

  • (Boolean)


52
# File 'lib/game_2d/entity/gecko.rb', line 52

def should_fall?; underfoot.empty?; end

#sleep_now?Boolean

Returns:

  • (Boolean)


50
# File 'lib/game_2d/entity/gecko.rb', line 50

def sleep_now?; false; end

#slide(dir) ⇒ Object



114
115
116
117
118
119
120
# File 'lib/game_2d/entity/gecko.rb', line 114

def slide(dir)
  if opaque(next_to(dir)).empty?
    accelerate(*angle_to_vector(dir))
  else
    self.a = dir + 180
  end
end

#slide_leftObject



111
# File 'lib/game_2d/entity/gecko.rb', line 111

def slide_left; slide(self.a - 90); end

#slide_rightObject



112
# File 'lib/game_2d/entity/gecko.rb', line 112

def slide_right; slide(self.a + 90); end

#updateObject



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/game_2d/entity/gecko.rb', line 75

def update
  fail "No space set for #{self}" unless @space
  check_for_disown_block

  return if perform_complex_move

  if falling = should_fall?
    self.a = 0
    space.fall(self)
  end

  args = next_move
  case (current_move = args.delete(:move).to_sym)
    when :slide_left, :slide_right, :brake, :flip, :build, :rise_up
      send current_move unless falling
    when :fire
      fire args[:x_vel], args[:y_vel]
    else
      puts "Invalid move for #{self}: #{current_move}, #{args.inspect}"
  end if args

  # Only go around corner if sitting on exactly one object
  blocks_underfoot = underfoot
  if blocks_underfoot.size == 1
    # Slide around if we're at the corner; otherwise, move normally
    slide_around(blocks_underfoot.first) or move
  else
    # Straddling two objects, or falling
    move
  end

  # Check again whether we've moved off of a block
  # we were building
  check_for_disown_block
end

#update_from_json(json) ⇒ Object



225
226
227
228
229
230
231
232
# File 'lib/game_2d/entity/gecko.rb', line 225

def update_from_json(json)
  @player_name = json[:player_name] if json[:player_name]
  @score = json[:score] if json[:score]
  @hp = json[:hp] if json[:hp]
  @build_block_id = json[:build_block].try(:to_sym) if json[:build_block]
  @complex_move = Serializable.from_json(json[:complex_move]) if json[:complex_move]
  super
end