indexing description: "[ A sample classing implementing an EM network object. ]" date: "$Date$" revision: "$Revision$" class SQUARE_ON_CIRCLE inherit EM_NET_OBJECT redefine is_synchronisation_needed, make_set_type end EM_DRAWABLE MATH_CONST EM_TIME_SINGLETON create make_set_type feature -- Initialisation make_set_type (a_type_id: INTEGER) is -- creation local i: INTEGER do Precursor {EM_NET_OBJECT} (a_type_id) create states.make states.put_first (create {SQUARE_ON_CIRCLE_STATE}.set_x_y_t (0,0,i.min_value)) create ix.make create iy.make interpolation_level := 3 x:=0 y:=0 angle:=0 radius:= 120 -- Init color create white.make_with_rgb (255, 255, 255) create grey.make_with_rgb (200, 200, 200) end feature -- behaviour move is -- move the square on a circle (server side) local math : DOUBLE_MATH a_new_state: SQUARE_ON_CIRCLE_STATE tmp_x, tmp_y: REAL x_list,y_list: DS_LINKED_LIST[EM_PAIR[REAL,REAL]] dt: REAL do create math dt := time.ticks - state_time state_time := (time.ticks).to_real angle := angle+dt / 1000 if angle > 2*Pi then angle := angle - 2*Pi end rx := center_x + math.cosine (angle) * radius ry := center_y + math.sine (angle ) * radius -- truncation needed for widget drawing x := rx.truncated_to_integer y := ry.truncated_to_integer -- the following code is copy&pasted to show interpolation on the server... tmp_x := rx tmp_y := ry if states.count < interpolation_level then create a_new_state.set_x_y_t (tmp_x, tmp_y, state_time) states.put_last(a_new_state) else oldest_state.set_x_y_t (tmp_x, tmp_y,state_time) end create x_list.make create y_list.make from states.start until states.after loop x_list.put_first (create {EM_PAIR[REAL,REAL]}.make(states.item_for_iteration.t,states.item_for_iteration.x)) y_list.put_first (create {EM_PAIR[REAL,REAL]}.make(states.item_for_iteration.t,states.item_for_iteration.y)) states.forth end ix.set_samples (x_list) iy.set_samples (y_list) end has_states_two_of_the_same_time is -- testing only local found_list: DS_LINKED_LIST[REAL] do create found_list.make from states.start until states.after loop from found_list.start until found_list.after loop if states.item_for_iteration.t = found_list.item_for_iteration then io.put_string("double%N") end found_list.forth end found_list.put_first(states.item_for_iteration.t) states.forth end end move_interpolated is -- interpolate the current state from previous states... (client side) do ox:=ox*0.9 oy:=oy*0.9 rx := ix.evaluate (time.ticks - timenudge) + ox ry := iy.evaluate (time.ticks - timenudge) + oy -- truncation needed for widget drawing x := rx.truncated_to_integer y := ry.truncated_to_integer end draw(a_surface : EM_SURFACE) is -- draw a square local points: DS_LINKED_LIST[EM_VECTOR_2D] t, end_ticks: INTEGER do a_surface.put_circle (center_x, center_y, radius.truncated_to_integer, grey) create points.make from t := time.ticks - 3000 end_ticks := time.ticks + 3000 until t > end_ticks loop points.put_last(create {EM_VECTOR_2D}.make(ix.evaluate (t).truncated_to_integer,iy.evaluate (t).truncated_to_integer)) t := t + 50 end a_surface.draw_polyline (points) if just_updated then a_surface.put_rectangle_filled (x-10,y-10,x+10,y+10,white) just_updated := false else a_surface.put_rectangle_filled (x-10,y-10,x+10,y+10,grey) end end serialize(o : EM_NET_SERIALIZER) is -- serialize to the given stream do o.put_real (x.to_real) o.put_real (y.to_real) just_updated := true end serialization_byte_count: INTEGER is -- Count of bytes needed for a successful serialization do Result := 8 end unserialize(i : EM_NET_UNSERIALIZER) is -- unserialize from the given stream local a_new_state: SQUARE_ON_CIRCLE_STATE tmp_x, tmp_y: REAL x_list,y_list: DS_LINKED_LIST[EM_PAIR[REAL,REAL]] do state_time := (time.ticks - time_offset).to_real if state_time > oldest_state.t and not is_update_blocking_enabled then move_interpolated just_updated := True i.read_real tmp_x := i.last_real i.read_real tmp_y := i.last_real if states.count < interpolation_level then create a_new_state.set_x_y_t (tmp_x, tmp_y, state_time) states.put_last(a_new_state) else oldest_state.set_x_y_t (tmp_x, tmp_y, state_time) end create x_list.make create y_list.make from states.start until states.after loop x_list.put_first (create {EM_PAIR[REAL,REAL]}.make(states.item_for_iteration.t,states.item_for_iteration.x)) y_list.put_first (create {EM_PAIR[REAL,REAL]}.make(states.item_for_iteration.t,states.item_for_iteration.y)) states.forth end ix.set_samples (x_list) iy.set_samples (y_list) if is_movement_smoothing_enabled then ox := rx - ix.evaluate (time.ticks) oy := ry - iy.evaluate (time.ticks) else ox := 0 oy := 0 end else -- Read the data to avoid a corrupt stream i.read_real; i.read_real end end feature -- Element change set_timenudge (tn: INTEGER) is -- is do timenudge:=tn end set_is_master_object(a_boolean: BOOLEAN) is -- set 'is_master_object' to 'a_boolean' do is_master_object := a_boolean ensure is_master_object_set: is_master_object = a_boolean end set_radius (a_radius: REAL) is -- Set 'radius' to 'a_radius' do radius := a_radius ensure radius_set: radius = a_radius end set_interpolation_level (an_interpolation_level: INTEGER) is -- Set the interpolation level require an_interpolation_level_not_negative: an_interpolation_level >= 1 do interpolation_level := an_interpolation_level from variant states.count until states.count <= interpolation_level loop states.delete(oldest_state) end end set_movement_smoothing(a_boolean: BOOLEAN) is -- Enable/disable movement smoothing do is_movement_smoothing_enabled := a_boolean ensure is_movement_smoothing_enabled_set: is_movement_smoothing_enabled = a_boolean end set_block_updates(a_boolean: BOOLEAN) is -- Enable/disable movement smoothing do is_update_blocking_enabled := a_boolean ensure is_update_blocking_enabled_set: is_update_blocking_enabled = a_boolean end feature -- Status is_synchronisation_needed : BOOLEAN is -- Is synchronisation needed? do Result := is_master_object end is_movement_smoothing_enabled: BOOLEAN -- Is movement smoothing enabled? is_update_blocking_enabled: BOOLEAN -- Is update blocking enabled? feature -- Access interpolation_level: INTEGER -- Interpolation level width : INTEGER is 5000 -- Drawable width height : INTEGER is 5000 -- Drawable height timenudge: INTEGER -- Timenudge -- Used to for interpolation fine-tuning. feature -- Status just_updated: BOOLEAN -- Was the object just updated? -- Used to draw it in a different color. is_master_object: BOOLEAN -- Is this the master object in the network? feature {NONE} -- Implementation oldest_state: SQUARE_ON_CIRCLE_STATE is -- Oldest state do from states.start Result := states.first until states.after loop if states.item_for_iteration.t < Result.t then Result := states.item_for_iteration end states.forth end end white: EM_COLOR -- White color grey: EM_COLOR -- Grey color ix,iy: EM_LAGRANGE_INTERPOLATOR[REAL] -- Interpolation for x and y coordinates rx,ry: REAL -- Real representation of square coordinates ox,oy: REAL -- Offset for smooth transition from mispredicted states. states: DS_LINKED_LIST[SQUARE_ON_CIRCLE_STATE] -- Set of states -- Used to interpolate angle : REAL -- Angle radius : REAL -- Radius center_x: INTEGER is 280 -- X coordinate of center center_y: INTEGER is 225 -- Y coordinate of center state_time: REAL end