indexing description: "Brick Breaker Bars" date: "$Date$" revision: "$Revision$" class BB_BAR inherit BB_OBJECT creation make feature -- Initialization make (a_x, a_y: DOUBLE; a_level: like level) is -- create `Current'with (`a_x', `a_y') as center do load_image ("./images/bar.gif") create center.make (a_x, a_y) initialize level := a_level object_type := Object_type_bar level.collision_detector.add (Current, object_type) level.bars.force_last (Current) create balls_on_bar.make -- set speeds create speed_array.make (1, 3) inspect level.difficulty when Difficulty_foolproof then speed_array.put (speed_low_foolproof, Low_speed) speed_array.put (speed_normal_foolproof, Normal_speed) speed_array.put (speed_high_foolproof, High_speed) when Difficulty_easy then speed_array.put (speed_low_easy, Low_speed) speed_array.put (speed_normal_easy, Normal_speed) speed_array.put (speed_high_easy, High_speed) when Difficulty_normal then speed_array.put (speed_low_normal, Low_speed) speed_array.put (speed_normal_normal, Normal_speed) speed_array.put (speed_high_normal, High_speed) when Difficulty_hard then speed_array.put (speed_low_hard, Low_speed) speed_array.put (speed_normal_hard, Normal_speed) speed_array.put (speed_high_hard, High_speed) when Difficulty_insane then speed_array.put (speed_low_insane, Low_speed) speed_array.put (speed_normal_insane, Normal_speed) speed_array.put (speed_high_insane, High_speed) else speed_array.put (speed_low_normal, Low_speed) speed_array.put (speed_normal_normal, Normal_speed) speed_array.put (speed_high_normal, High_speed) end speed := speed_array.item (Normal_speed) has_moved_left_last_frame := False has_moved_right_last_frame := False is_large := False is_small := False is_transparent := False is_frozen := False is_inverted := False is_fast := False is_slow := False is_understeering := False is_oversteering := False is_sticky := False set_no_driving end feature -- Status report balls_on_bar: DS_LINKED_LIST [BB_BALL] -- balls sticking on `Current' is_small: BOOLEAN -- is `Current' small? is_large: BOOLEAN -- is `Current' large? is_transparent: BOOLEAN -- is `Current' transparent? is_frozen: BOOLEAN -- is `Current' frozen? is_inverted: BOOLEAN -- is `Current' inverted? is_fast: BOOLEAN -- is `Current' fast? is_slow: BOOLEAN -- is `Current' slow? is_understeering: BOOLEAN -- is `Current' understeering? is_oversteering: BOOLEAN -- is `Current' oversteering? is_sticky: BOOLEAN -- is `Current' sticky? (balls stick on `Current' when they hit the top side) is_driving_left: BOOLEAN -- is `Current' driving left? is_driving_right: BOOLEAN -- is `Current' driving right? feature -- Status setting set_small is -- make the bar small local ball_cursor: DS_LINKED_LIST_CURSOR [BB_BALL] do if is_transparent then load_image ("images/small_bar_transparent.gif") image.set_transparent_color (0, 255, 0) else load_image ("images/small_bar.gif") end -- drop all `balls_on_bar' which aren't on `Current' anymore create ball_cursor.make (balls_on_bar) from ball_cursor.start until ball_cursor.after loop if ball_cursor.item.border_right < border_left or ball_cursor.item.border_left > border_right then -- drop the ball ball_cursor.item.set_stopped (False) ball_cursor.item.set_movement_angle (Pi * 3 / 2) ball_cursor.remove else ball_cursor.forth end end is_large := False is_small := True ensure is_small: is_small and not is_large end set_large is -- make the bar large do if is_transparent then load_image ("images/large_bar_transparent.gif") image.set_transparent_color (0, 255, 0) else load_image ("images/large_bar.gif") end is_large := True is_small := False ensure is_large: is_large and not is_small end set_normal_size is -- make the bar normal local ball_cursor: DS_LINKED_LIST_CURSOR [BB_BALL] do if is_transparent then load_image ("images/bar_transparent.gif") image.set_transparent_color (0, 255, 0) else load_image ("images/bar.gif") end -- drop all `balls_on_bar' which aren't on `Current' anymore create ball_cursor.make (balls_on_bar) from ball_cursor.start until ball_cursor.after loop if ball_cursor.item.border_right < border_left or ball_cursor.item.border_left > border_right then -- drop the ball ball_cursor.item.set_stopped (False) ball_cursor.item.set_movement_angle (Pi * 3 / 2) ball_cursor.remove else ball_cursor.forth end end is_large := False is_small := False ensure is_normal_sized: not is_large and not is_small end set_transparent is -- make the bar transparent do if is_small then load_image ("images/small_bar_transparent.gif") elseif is_large then load_image ("images/large_bar_transparent.gif") else load_image ("images/bar_transparent.gif") end image.set_transparent_color (0, 255, 0) is_transparent := True ensure is_transparent: is_transparent = True end set_opaque is -- make the bar opaque do if is_small then load_image ("images/small_bar.gif") elseif is_large then load_image ("images/large_bar.gif") else load_image ("images/bar.gif") end is_transparent := False ensure is_opaque: is_transparent = False end set_frozen (a_boolean: BOOLEAN) is -- set `is_frozen' do is_frozen := a_boolean ensure value_set: is_frozen = a_boolean end set_inverted (a_boolean: BOOLEAN) is -- set `is_inverted' do is_inverted := a_boolean ensure value_set: is_inverted = a_boolean end set_fast is -- make `Current' fast do speed := speed_array.item (High_speed) is_fast := True is_slow := False ensure value_set: is_fast and not is_slow end set_slow is -- make `Current' slow do speed := speed_array.item (Low_speed) is_fast := False is_slow := True ensure value_set: not is_fast and is_slow end set_normal_speed is -- set `Current' to normal speed do speed := speed_array.item (Normal_speed) is_fast := False is_slow := False ensure value_set: not is_fast and not is_slow end set_oversteering is -- make `Current' oversteering do is_oversteering := True is_understeering := False ensure values_set: is_oversteering and not is_understeering end set_understeering is -- make `Current' understeering do is_oversteering := False is_understeering := True ensure values_set: not is_oversteering and is_understeering end set_normal_steering is -- set `Current' to normal steering behaviour do is_oversteering := False is_understeering := False ensure values_set: not is_oversteering and not is_understeering end set_sticky (a_boolean: BOOLEAN) is -- set whether `Current' is sticky or not do is_sticky := a_boolean ensure value_set: is_sticky = a_boolean end set_drive_left is -- set `Current' driving left do is_driving_left := True is_driving_right := False ensure is_driving_left: is_driving_left and not is_driving_right end set_drive_right is -- set `Current' driving right do is_driving_left := False is_driving_right := True ensure is_driving_left: not is_driving_left and is_driving_right end set_no_driving is -- remove the driving effect do is_driving_left := False is_driving_right := False ensure is_driving_left: not is_driving_left and not is_driving_right end feature -- Movement move_right (speed_reduction: DOUBLE) is -- move the bar right do if is_frozen then move_not elseif is_inverted then move_real_left (speed_reduction) else move_real_right (speed_reduction) end ensure bar_on_field: Current.border_right <= bb_window_width end move_left (speed_reduction: DOUBLE) is -- move the bar right do if is_frozen then move_not elseif is_inverted then move_real_right (speed_reduction) else move_real_left (speed_reduction) end ensure bar_on_field: Current.border_left >= 0 end move_not is -- set variables to ensure correct acceleration is the bar not moves -- has to be called every frame when the bar does not move do has_moved_right_last_frame := False has_moved_left_last_frame := False -- reset `last_center' move_by (0,0) move_driving set_into_field ensure was_not_moved: not has_moved_right_last_frame and not has_moved_left_last_frame end start_balls_on_bar is -- start all balls on `Current' local ball_cursor: DS_LINKED_LIST_CURSOR [BB_BALL] do create ball_cursor.make (balls_on_bar) from ball_cursor.start until ball_cursor.after loop level.random.forth ball_cursor.item.set_stopped (False) ball_cursor.item.set_movement_angle (((level.random.item \\ 1000) / 1000 * (Pi - 2 * Minimum_start_angle)) + Minimum_start_angle) ball_cursor.forth end balls_on_bar.wipe_out ensure no_balls_on_bar: balls_on_bar.is_empty end feature -- Implementation move_real_right (speed_reduction: DOUBLE) is -- move `Current' really to the right do if not has_moved_right_last_frame then last_speed := 0 end last_speed := last_speed + (level.frame_delay * (speed / Acceleration_time)) if last_speed > speed * speed_reduction then last_speed := speed * speed_reduction end move_by (last_speed * (level.frame_delay / 1000), 0.0) move_balls_on_bar (last_speed * (level.frame_delay / 1000)) move_driving set_into_field has_moved_right_last_frame := True has_moved_left_last_frame := False ensure has_moved_right: has_moved_right_last_frame and not has_moved_left_last_frame end move_real_left (speed_reduction: DOUBLE) is -- move `Current' really to the left do if not has_moved_left_last_frame then last_speed := 0 end last_speed := last_speed + (level.frame_delay * (speed / Acceleration_time)) if last_speed > speed * speed_reduction then last_speed := speed * speed_reduction end move_by (-last_speed * (level.frame_delay / 1000), 0.0) move_balls_on_bar (-last_speed * (level.frame_delay / 1000)) move_driving set_into_field has_moved_right_last_frame := False has_moved_left_last_frame := True ensure has_moved_left: not has_moved_right_last_frame and has_moved_left_last_frame end move_balls_on_bar (a_x: DOUBLE) is -- move all balls on `Current' by (`a_x', 0) local ball_cursor: DS_LINKED_LIST_CURSOR [BB_BALL] do create ball_cursor.make (balls_on_bar) from ball_cursor.start until ball_cursor.after loop ball_cursor.item.move_by (a_x,0) ball_cursor.forth end end move_driving is -- move `Current' when it's driving do if is_driving_right then center.set_x (center.x + speed * Driving_factor / 1000 * level.frame_delay) move_balls_on_bar (speed * Driving_factor / 1000 * level.frame_delay) elseif is_driving_left then center.set_x (center.x - speed * Driving_factor / 1000 * level.frame_delay) move_balls_on_bar (- speed * Driving_factor / 1000 * level.frame_delay) end end set_into_field is -- reset `Current' into the game field do if border_right > bb_window_width then move_balls_on_bar (bb_window_width - half_width - center.x) center.set_x (bb_window_width - half_width) elseif border_left < 0 then move_balls_on_bar (half_width - center.x) center.set_x (half_width) end end speed_array: ARRAY [DOUBLE] -- array of speeds for current difficulty speed: DOUBLE -- current speed last_speed: DOUBLE -- speed in last frame has_moved_right_last_frame: BOOLEAN -- did `Current' move right last frame? has_moved_left_last_frame: BOOLEAN -- did `Current' move left last frame? -- speed constants speed_low_foolproof: DOUBLE is 200.0 speed_normal_foolproof: DOUBLE is 350.0 speed_high_foolproof: DOUBLE is 550.0 speed_low_easy: DOUBLE is 150.0 speed_normal_easy: DOUBLE is 350.0 speed_high_easy: DOUBLE is 600.0 speed_low_normal: DOUBLE is 150.0 speed_normal_normal: DOUBLE is 350.0 speed_high_normal: DOUBLE is 600.0 speed_low_hard: DOUBLE is 132.0 speed_normal_hard: DOUBLE is 300.0 speed_high_hard: DOUBLE is 650.0 speed_low_insane: DOUBLE is 125.0 speed_normal_insane: DOUBLE is 200.0 speed_high_insane: DOUBLE is 1000.0 end