From 826dd0749a597b1cc227b5b241487c7a2d875c3c Mon Sep 17 00:00:00 2001 From: Ronen Date: Thu, 1 Oct 2015 02:40:47 +0300 Subject: [PATCH] added self-factor and other-factor to repel function so you can move both objects when repeling --- dist/dev/sscd.dev.js | 14 +++++++++++--- dist/dev/sscd.dev.min.js | 2 +- src/shapes/shape.js | 14 +++++++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/dist/dev/sscd.dev.js b/dist/dev/sscd.dev.js index 9fa9c63..11f44b5 100644 --- a/dist/dev/sscd.dev.js +++ b/dist/dev/sscd.dev.js @@ -1184,16 +1184,23 @@ SSCD.Shape.prototype = { // obj: object or vector to repeal (must have move() function). // force: force factor, the bigger this is the stronger / faster the repealing will be. default to 1. // iterations: max iterations of repeal-and-test-again routines. default to 1. + // factor_self: factor to multiply force that will apply on this shape. default to 0. + // factor_other: factor to multiply force that will apply on this shape. default to 1. // NOTE: this function assume there's collision on start, meaning first iteration of repeal will ALWAYS happen. // return: total movement due to repeling (vector) - repel: function(obj, force, iterations) + repel: function(obj, force, iterations, factor_self, factor_other) { // set defaults force = force || 1; iterations = iterations || 1; + if (factor_self === undefined) factor_self = 0; + if (factor_other === undefined) factor_other = 1; - // get direction vector + // get push vectors + var push_vector_other, push_vector_self; var push_vector = this.get_repel_direction(obj).multiply_scalar_self(force); + if (factor_other) push_vector_other = push_vector.multiply_scalar(factor_other); + if (factor_self) push_vector_self = push_vector.multiply_scalar(factor_self * -1); // for return value var ret = SSCD.Vector.ZERO.clone(); @@ -1206,7 +1213,8 @@ SSCD.Shape.prototype = { iterations--; // do pushing - obj.move(push_vector); + if (push_vector_other) obj.move(push_vector_other); + if (push_vector_self) this.move(push_vector_self); ret.add_self(push_vector); // check if still colliding diff --git a/dist/dev/sscd.dev.min.js b/dist/dev/sscd.dev.min.js index 72b24f6..d835a77 100644 --- a/dist/dev/sscd.dev.min.js +++ b/dist/dev/sscd.dev.min.js @@ -1 +1 @@ -var SSCD=SSCD||{};SSCD.VERSION=1.3,SSCD.World=function(t){t=t||{},t.grid_size=t.grid_size||512,t.grid_error=void 0!==t.grid_error?t.grid_error:2,this.__grid={},this.__params=t,this.__all_shapes={},this.__collision_tags={},this.__next_coll_tag=0},SSCD.World.prototype={__create_collision_tag:function(t){if(this.__collision_tags[t])throw new SSCD.IllegalActionError("Collision tag named '"+t+"' already exist!");this.__collision_tags[t]=1<this.__params.grid_error||Math.abs(i.position.y-t.__last_insert_aabb.position.y)>this.__params.grid_error||Math.abs(i.size.x-t.__last_insert_aabb.size.x)>this.__params.grid_error||Math.abs(i.size.y-t.__last_insert_aabb.size.y)>this.__params.grid_error)&&(this.remove(t),this.add(t))},pick_object:function(t,i){var _=[];return this.test_collision(t,i,_,1)?_[0]:null},test_collision:function(t,i,_,e){return i=this.__get_tags_value(i),t instanceof SSCD.Vector?this.__test_collision_point(t,i,_,e):t.is_shape?this.__test_collision_shape(t,i,_,e):void 0},__test_collision_point:function(t,i,_,e){var s=this.__params.grid_size,o=Math.floor(t.x/s),n=Math.floor(t.y/s);if(void 0===this.__grid[o]||void 0===this.__grid[o][n])return!1;for(var r=this.__grid[o][n],a=0,o=0;o=e)return!0}}return a>0},__test_collision_shape:function(t,i,_,e){var s;s=t.__world===this?t.__grid_bounderies:this.__get_grid_range(t);for(var o=0,n={},r=s.min_x;r<=s.max_x;++r)if(void 0!==this.__grid[r])for(var a=s.min_y;a<=s.max_y;++a){var l=this.__grid[r][a];if(void 0!==l)for(var h=0;h=e)return!0}}}return o>0},__do_collision:function(t,i){return t.test_collide_with(i)},render:function(t,i,_,e){i=i||SSCD.Vector.ZERO,void 0===_&&(_=!0),void 0===e&&(e=!0);var s=t.getContext("2d");s.setTransform(1,0,0,1,0,0);for(var o=this.__params.grid_size,n=Math.floor(i.x/o),r=Math.floor(i.y/o),a=n+Math.ceil(t.width/o),l=r+Math.ceil(t.height/o),h=[],c=n;a>=c;++c)for(var S=r;l>=S;++S){var p=void 0;if(this.__grid[c]&&(p=this.__grid[c][S]),_){var u=new SSCD.Vector(c*o,S*o).sub_self(i);s.beginPath(),s.rect(u.x,u.y,o-1,o-1),s.lineWidth="1",s.strokeStyle=void 0===p||0===p.length?"rgba(100, 100, 100, 0.255)":"rgba(255, 0, 0, 0.3)",s.stroke()}if(void 0!==p)for(var f=0;fs?SSCD.Math.distance(t,i):s>1?SSCD.Math.distance(t,_):SSCD.Math.distance(t,{x:i.x+s*(_.x-i.x),y:i.y+s*(_.y-i.y)})},SSCD.Math.line_intersects=function(t,i,_,e){var s,o,n,r;s=i.x-t.x,o=i.y-t.y,n=e.x-_.x,r=e.y-_.y;var a,l;return a=(-o*(t.x-_.x)+s*(t.y-_.y))/(-n*o+s*r),l=(n*(t.y-_.y)-r*(t.x-_.x))/(-n*o+s*r),a>=0&&1>=a&&l>=0&&1>=l?1:0},SSCD.Math.is_on_line=function(t,i,_){return SSCD.Math.distance_to_line(t,i,_)<=5};var SSCD=SSCD||{};SSCD.Vector=function(t,i){this.x=t,this.y=i},SSCD.Vector.prototype={get_name:function(){return"vector"},clone:function(){return new SSCD.Vector(this.x,this.y)},set:function(t){this.x=t.x,this.y=t.y},negative:function(){return this.multiply_scalar(-1)},negative_self:function(){return this.multiply_scalar_self(-1),this},distance_from:function(t){return SSCD.Math.distance(this,t)},angle_from:function(t){return SSCD.Math.angle(this,t)},move:function(t){return this.x+=t.x,this.y+=t.y,this},normalize_self:function(){var t=Math.sqrt(this.x*this.x+this.y*this.y);return 0===t?this:(this.x/=t,this.y/=t,this)},normalize:function(){return this.clone().normalize_self()},add_self:function(t){return this.x+=t.x,this.y+=t.y,this},sub_self:function(t){return this.x-=t.x,this.y-=t.y,this},divide_self:function(t){return this.x/=t.x,this.y/=t.y,this},multiply_self:function(t){return this.x*=t.x,this.y*=t.y,this},add_scalar_self:function(t){return this.x+=t,this.y+=t,this},sub_scalar_self:function(t){return this.x-=t,this.y-=t,this},divide_scalar_self:function(t){return this.x/=t,this.y/=t,this},multiply_scalar_self:function(t){return this.x*=t,this.y*=t,this},add:function(t){return this.clone().add_self(t)},sub:function(t){return this.clone().sub_self(t)},multiply:function(t){return this.clone().multiply_self(t)},divide:function(t){return this.clone().divide_self(t)},add_scalar:function(t){return this.clone().add_scalar_self(t)},sub_scalar:function(t){return this.clone().sub_scalar_self(t)},multiply_scalar:function(t){return this.clone().multiply_scalar_self(t)},divide_scalar:function(t){return this.clone().divide_scalar_self(t)},clamp:function(t,i){return this.xi&&(this.x=i),this.y>i&&(this.y=i),this},from_angle:function(t){return this.x=Math.cos(t),this.y=Math.sin(t),this},apply_self:function(t){return this.x=t(this.x),this.y=t(this.y),this},apply:function(t){return this.clone().apply_self(t)},debug:function(){console.debug(this.x+", "+this.y)}},SSCD.Vector.ZERO=new SSCD.Vector(0,0),SSCD.Vector.ONE=new SSCD.Vector(1,1),SSCD.Vector.UP=new SSCD.Vector(0,-1),SSCD.Vector.DOWN=new SSCD.Vector(0,1),SSCD.Vector.LEFT=new SSCD.Vector(-1,0),SSCD.Vector.RIGHT=new SSCD.Vector(1,0),SSCD.Vector.UP_LEFT=new SSCD.Vector(-1,-1),SSCD.Vector.DOWN_LEFT=new SSCD.Vector(-1,1),SSCD.Vector.UP_RIGHT=new SSCD.Vector(1,-1),SSCD.Vector.DOWN_RIGHT=new SSCD.Vector(1,1);var SSCD=SSCD||{};SSCD.extend=function(t,i){for(var _ in t)i[_]||(i[_]=t[_]);i.__inits=i.__inits||[],t.__init__&&i.__inits.push(t.__init__),i.init=function(){for(var t=0;t0&&(this.position.x-=i,this.size.x+=i);var _=this.position.y-t.y;_>0&&(this.position.y-=_,this.size.y+=_);var e=t.x-(this.position.x+this.size.x);e>0&&(this.size.x+=e);var s=t.y-(this.position.y+this.size.y);s>0&&(this.size.y+=s)},clone:function(){return new SSCD.AABB(this.position,this.size)}};var SSCD=SSCD||{};SSCD.Shape=function(){},SSCD.Shape.prototype={__type:"shape",is_shape:!0,__data:null,__next_id:0,__collision_tags:[],__collision_tags_val:SSCD.World.prototype._ALL_TAGS_VAL,__init__:function(){this.__position=new SSCD.Vector,this.__grid_chunks=[],this.__world=null,this.__grid_bounderies=null,this.__last_insert_aabb=null,this.__id=SSCD.Shape.prototype.__next_id++},get_id:function(){return this.__id},set_collision_tags:function(t){if(null===this.__world)throw new SSCD.IllegalActionError("Can't set tags for a shape that is not inside a collision world!");return this.__collision_tags_val=this.__world.__get_tags_value(t),!t instanceof Array&&(t=[t]),this.__collision_tags=t,this.__update_tags_hook&&this.__update_tags_hook(),this},__update_tags_hook:null,get_collision_tags:function(){return this.__collision_tags},collision_tags_match:function(t){if(isNaN(t)){if(null===this.__world)throw new SSCD.IllegalActionError("If you provide tags as string(s) the shape must be inside a collision world to convert them!");t=this.__world.__get_tags_value(t)}return 0!==(this.__collision_tags_val&t)},test_collide_with:function(t){return SSCD.CollisionManager.test_collision(this,t)},repel:function(t,i,_){i=i||1,_=_||1;for(var e=this.get_repel_direction(t).multiply_scalar_self(i),s=SSCD.Vector.ZERO.clone(),o=!0;o&&_>0;)_--,t.move(e),s.add_self(e),o=this.test_collide_with(t);return s},get_repel_direction:function(t){var i,_=this.get_abs_center();return i=t instanceof SSCD.Vector?t:t.get_abs_center(),i.sub(_).normalize_self()},__get_render_fill_color:function(t){return this.__override_fill_color?this.__override_fill_color:this.__collision_tags_to_color(this.__collision_tags_val,t)},__get_render_stroke_color:function(t){return this.__override_stroke_color?this.__override_stroke_color:this.__collision_tags_to_color(this.__collision_tags_val,t)},set_debug_render_colors:function(t,i){this.__override_fill_color=t,this.__override_stroke_color=i},__override_fill_color:null,__override_stroke_color:null,__collision_tags_to_color:function(t,i){var _=Math.round(255*Math.abs(Math.sin(t))),e=Math.round(255*Math.abs(Math.cos(t))),s=Math.round(_^e);return"rgba("+_+","+e+","+s+","+i+")"},set_data:function(t){return this.__data=t,this},get_data:function(){return this.__data},get_name:function(){return this.__type},render_aabb:function(t,i){var _=this.get_aabb();t.beginPath(),t.rect(_.position.x-i.x,_.position.y-i.y,_.size.x,_.size.y),t.lineWidth="1",t.strokeStyle="rgba(50, 175, 45, 0.5)",t.stroke()},set_position:function(t){return this.__position.x=t.x,this.__position.y=t.y,this.__update_position(),this},get_position:function(){return this.__position.clone()},move:function(t){return this.set_position(this.__position.add(t)),this},__update_position:function(){this.__update_position_hook&&this.__update_position_hook(),this.__aabb&&this.__update_aabb_pos(),this.__update_parent_world()},__update_aabb_pos:function(){this.__aabb.position=this.__position},get_abs_center:function(){var t=this.get_aabb();return t.position.add(t.size.multiply_scalar(.5))},reset_aabb:function(){this.__aabb=void 0},__update_parent_world:function(){this.__world&&this.__world.__update_shape_grid(this)},__update_position_hook:null,render:function(){throw new SSCD.NotImplementedError},build_aabb:function(){throw new SSCD.NotImplementedError},get_aabb:function(){return this.__aabb=this.__aabb||this.build_aabb(),this.__aabb}};var SSCD=SSCD||{};SSCD.Circle=function(t,i){this.init(),this.__radius=i,this.__size=new SSCD.Vector(i,i).multiply_scalar_self(2),this.set_position(t)},SSCD.Circle.prototype={__type:"circle",render:function(t,i){var _=this.__position.sub(i);t.beginPath(),t.arc(_.x,_.y,this.__radius,0,2*Math.PI,!1),t.lineWidth="7",t.strokeStyle=this.__get_render_stroke_color(.75),t.stroke(),t.fillStyle=this.__get_render_fill_color(.35),t.fill()},get_radius:function(){return this.__radius},__update_aabb_pos:function(){this.__aabb.position=this.__position.sub_scalar(this.__radius)},build_aabb:function(){return new SSCD.AABB(this.__position.sub_scalar(this.__radius),this.__size)},get_abs_center:function(){return this.__position.clone()}},SSCD.extend(SSCD.Shape.prototype,SSCD.Circle.prototype);var SSCD=SSCD||{};SSCD.Rectangle=function(t,i){this.init(),this.__size=i,this.set_position(t)},SSCD.Rectangle.prototype={__type:"rectangle",render:function(t,i){var _=this.__position.sub(i);t.beginPath(),t.rect(_.x,_.y,this.__size.x,this.__size.y),t.lineWidth="7",t.strokeStyle=this.__get_render_stroke_color(.75),t.stroke(),t.fillStyle=this.__get_render_fill_color(.35),t.fill()},get_size:function(){return this.__size.clone()},build_aabb:function(){return new SSCD.AABB(this.__position,this.__size)},get_top_left:function(){return this.__top_left_c=this.__top_left_c||this.__position.clone(),this.__top_left_c},get_bottom_left:function(){return this.__bottom_left_c=this.__bottom_left_c||this.__position.add(new SSCD.Vector(0,this.__size.y)),this.__bottom_left_c},get_top_right:function(){return this.__top_right_c=this.__top_right_c||this.__position.add(new SSCD.Vector(this.__size.x,0)),this.__top_right_c},get_bottom_right:function(){return this.__bottom_right_c=this.__bottom_right_c||this.__position.add(new SSCD.Vector(this.__size.x,this.__size.y)),this.__bottom_right_c},get_abs_center:function(){return this.__abs_center_c=this.__abs_center_c||this.__position.add(this.__size.divide_scalar(2)),this.__abs_center_c},__update_position_hook:function(){this.__top_left_c=void 0,this.__top_right_c=void 0,this.__bottom_left_c=void 0,this.__bottom_right_c=void 0,this.__abs_center_c=void 0}},SSCD.extend(SSCD.Shape.prototype,SSCD.Rectangle.prototype);var SSCD=SSCD||{};SSCD.Line=function(t,i){this.init(),this.__dest=i,this.set_position(t)},SSCD.Line.prototype={__type:"line",render:function(t){t.beginPath(),t.moveTo(this.__position.x,this.__position.y);var i=this.__position.add(this.__dest);t.lineTo(i.x,i.y),t.lineWidth="7",t.strokeStyle=this.__get_render_stroke_color(.75),t.stroke()},build_aabb:function(){var t=new SSCD.Vector(0,0);t.x=this.__dest.x>0?this.__position.x:this.__position.x-this.__dest.x,t.y=this.__dest.y>0?this.__position.y:this.__position.y-this.__dest.y;var i=this.__dest.apply(Math.abs);return new SSCD.AABB(t,i)},get_p1:function(){return this.__p1_c=this.__p1_c||this.__position.clone(),this.__p1_c},get_p2:function(){return this.__p2_c=this.__p2_c||this.__position.add(this.__dest),this.__p2_c},__update_position_hook:function(){this.__p1_c=void 0,this.__p2_c=void 0}},SSCD.extend(SSCD.Shape.prototype,SSCD.Line.prototype);var SSCD=SSCD||{};SSCD.LineStrip=function(t,i,_){if(this.init(),this.__points=i,i.length<=1)throw new SSCD.IllegalActionError("Not enough vectors for LineStrip (got to have at least two vectors)");_&&this.__points.push(this.__points[0]),this.set_position(t)},SSCD.LineStrip.prototype={__type:"line-strip",render:function(t){var i=void 0;t.beginPath();for(var _=0;_=t.__position.x&&i.y>=t.__position.y&&i.x<=t.__position.x+t.__size.x&&i.y<=t.__position.y+t.__size.y},_test_collision_vector_line:function(t,i){return SSCD.Math.is_on_line(t,i.get_p1(),i.get_p2())},_test_collision_vector_linestrip:function(t,i){for(var _=i.get_abs_lines(),e=0;e<_.length;++e)if(SSCD.Math.is_on_line(t,_[e][0],_[e][1]))return!0;return!1},_test_collision_circle_line:function(t,i){return SSCD.Math.distance_to_line(t.__position,i.get_p1(),i.get_p2())<=t.__radius},_test_collision_circle_linestrip:function(t,i){for(var _=i.get_abs_lines(),e=0;e<_.length;++e)if(SSCD.Math.distance_to_line(t.__position,_[e][0],_[e][1])<=t.__radius)return!0;return!1},_test_collision_linestrip_line:function(t,i){for(var _=t.get_abs_lines(),e=i.get_p1(),s=i.get_p2(),o=0;o<_.length;++o)if(SSCD.Math.line_intersects(e,s,_[o][0],_[o][1]))return!0;return!1},_test_collision_line_line:function(t,i){return SSCD.Math.line_intersects(t.get_p1(),t.get_p2(),i.get_p1(),i.get_p2())},_test_collision_rect_line:function(t,i){var _=i.get_p1(),e=i.get_p2();if(SSCD.CollisionManager._test_collision_rect_vector(t,_)||SSCD.CollisionManager._test_collision_rect_vector(t,e))return!0;var s=t.get_top_left(),o=t.get_bottom_left();if(SSCD.Math.line_intersects(_,e,s,o))return!0;var n=t.get_top_right(),r=t.get_bottom_right();return SSCD.Math.line_intersects(_,e,n,r)?!0:SSCD.Math.line_intersects(_,e,s,n)?!0:SSCD.Math.line_intersects(_,e,o,r)?!0:!1},_test_collision_rect_linestrip:function(t,i){for(var _=i.get_abs_points(),e=0;e<_.length;++e)if(this._test_collision_rect_vector(t,_[e]))return!0;for(var s=t.get_top_left(),o=t.get_bottom_left(),n=t.get_top_right(),r=t.get_bottom_right(),a=i.get_abs_lines(),e=0;e_.x?[i.get_top_left(),i.get_bottom_left()]:[i.get_top_right(),i.get_bottom_right()]),o.push(s.y>_.y?[i.get_top_left(),i.get_top_right()]:[i.get_bottom_left(),i.get_bottom_right()]);for(var n=0;n_.right||e.right<_.left||e.top>_.bottom||e.bottom<_.top)}},SSCD.UnsupportedShapes=function(t,i){this.name="Unsupported Shapes",this.message="Unsupported shapes collision test! '"+t.get_name()+"' <-> '"+i.get_name()+"'."},SSCD.UnsupportedShapes.prototype=Error.prototype,"undefined"!=typeof exports&&(exports.sscd=SSCD); \ No newline at end of file +var SSCD=SSCD||{};SSCD.VERSION=1.3,SSCD.World=function(t){t=t||{},t.grid_size=t.grid_size||512,t.grid_error=void 0!==t.grid_error?t.grid_error:2,this.__grid={},this.__params=t,this.__all_shapes={},this.__collision_tags={},this.__next_coll_tag=0},SSCD.World.prototype={__create_collision_tag:function(t){if(this.__collision_tags[t])throw new SSCD.IllegalActionError("Collision tag named '"+t+"' already exist!");this.__collision_tags[t]=1<this.__params.grid_error||Math.abs(i.position.y-t.__last_insert_aabb.position.y)>this.__params.grid_error||Math.abs(i.size.x-t.__last_insert_aabb.size.x)>this.__params.grid_error||Math.abs(i.size.y-t.__last_insert_aabb.size.y)>this.__params.grid_error)&&(this.remove(t),this.add(t))},pick_object:function(t,i){var _=[];return this.test_collision(t,i,_,1)?_[0]:null},test_collision:function(t,i,_,e){return i=this.__get_tags_value(i),t instanceof SSCD.Vector?this.__test_collision_point(t,i,_,e):t.is_shape?this.__test_collision_shape(t,i,_,e):void 0},__test_collision_point:function(t,i,_,e){var s=this.__params.grid_size,o=Math.floor(t.x/s),n=Math.floor(t.y/s);if(void 0===this.__grid[o]||void 0===this.__grid[o][n])return!1;for(var r=this.__grid[o][n],a=0,o=0;o=e)return!0}}return a>0},__test_collision_shape:function(t,i,_,e){var s;s=t.__world===this?t.__grid_bounderies:this.__get_grid_range(t);for(var o=0,n={},r=s.min_x;r<=s.max_x;++r)if(void 0!==this.__grid[r])for(var a=s.min_y;a<=s.max_y;++a){var l=this.__grid[r][a];if(void 0!==l)for(var h=0;h=e)return!0}}}return o>0},__do_collision:function(t,i){return t.test_collide_with(i)},render:function(t,i,_,e){i=i||SSCD.Vector.ZERO,void 0===_&&(_=!0),void 0===e&&(e=!0);var s=t.getContext("2d");s.setTransform(1,0,0,1,0,0);for(var o=this.__params.grid_size,n=Math.floor(i.x/o),r=Math.floor(i.y/o),a=n+Math.ceil(t.width/o),l=r+Math.ceil(t.height/o),h=[],c=n;a>=c;++c)for(var S=r;l>=S;++S){var p=void 0;if(this.__grid[c]&&(p=this.__grid[c][S]),_){var u=new SSCD.Vector(c*o,S*o).sub_self(i);s.beginPath(),s.rect(u.x,u.y,o-1,o-1),s.lineWidth="1",s.strokeStyle=void 0===p||0===p.length?"rgba(100, 100, 100, 0.255)":"rgba(255, 0, 0, 0.3)",s.stroke()}if(void 0!==p)for(var f=0;fs?SSCD.Math.distance(t,i):s>1?SSCD.Math.distance(t,_):SSCD.Math.distance(t,{x:i.x+s*(_.x-i.x),y:i.y+s*(_.y-i.y)})},SSCD.Math.line_intersects=function(t,i,_,e){var s,o,n,r;s=i.x-t.x,o=i.y-t.y,n=e.x-_.x,r=e.y-_.y;var a,l;return a=(-o*(t.x-_.x)+s*(t.y-_.y))/(-n*o+s*r),l=(n*(t.y-_.y)-r*(t.x-_.x))/(-n*o+s*r),a>=0&&1>=a&&l>=0&&1>=l?1:0},SSCD.Math.is_on_line=function(t,i,_){return SSCD.Math.distance_to_line(t,i,_)<=5};var SSCD=SSCD||{};SSCD.Vector=function(t,i){this.x=t,this.y=i},SSCD.Vector.prototype={get_name:function(){return"vector"},clone:function(){return new SSCD.Vector(this.x,this.y)},set:function(t){this.x=t.x,this.y=t.y},negative:function(){return this.multiply_scalar(-1)},negative_self:function(){return this.multiply_scalar_self(-1),this},distance_from:function(t){return SSCD.Math.distance(this,t)},angle_from:function(t){return SSCD.Math.angle(this,t)},move:function(t){return this.x+=t.x,this.y+=t.y,this},normalize_self:function(){var t=Math.sqrt(this.x*this.x+this.y*this.y);return 0===t?this:(this.x/=t,this.y/=t,this)},normalize:function(){return this.clone().normalize_self()},add_self:function(t){return this.x+=t.x,this.y+=t.y,this},sub_self:function(t){return this.x-=t.x,this.y-=t.y,this},divide_self:function(t){return this.x/=t.x,this.y/=t.y,this},multiply_self:function(t){return this.x*=t.x,this.y*=t.y,this},add_scalar_self:function(t){return this.x+=t,this.y+=t,this},sub_scalar_self:function(t){return this.x-=t,this.y-=t,this},divide_scalar_self:function(t){return this.x/=t,this.y/=t,this},multiply_scalar_self:function(t){return this.x*=t,this.y*=t,this},add:function(t){return this.clone().add_self(t)},sub:function(t){return this.clone().sub_self(t)},multiply:function(t){return this.clone().multiply_self(t)},divide:function(t){return this.clone().divide_self(t)},add_scalar:function(t){return this.clone().add_scalar_self(t)},sub_scalar:function(t){return this.clone().sub_scalar_self(t)},multiply_scalar:function(t){return this.clone().multiply_scalar_self(t)},divide_scalar:function(t){return this.clone().divide_scalar_self(t)},clamp:function(t,i){return this.xi&&(this.x=i),this.y>i&&(this.y=i),this},from_angle:function(t){return this.x=Math.cos(t),this.y=Math.sin(t),this},apply_self:function(t){return this.x=t(this.x),this.y=t(this.y),this},apply:function(t){return this.clone().apply_self(t)},debug:function(){console.debug(this.x+", "+this.y)}},SSCD.Vector.ZERO=new SSCD.Vector(0,0),SSCD.Vector.ONE=new SSCD.Vector(1,1),SSCD.Vector.UP=new SSCD.Vector(0,-1),SSCD.Vector.DOWN=new SSCD.Vector(0,1),SSCD.Vector.LEFT=new SSCD.Vector(-1,0),SSCD.Vector.RIGHT=new SSCD.Vector(1,0),SSCD.Vector.UP_LEFT=new SSCD.Vector(-1,-1),SSCD.Vector.DOWN_LEFT=new SSCD.Vector(-1,1),SSCD.Vector.UP_RIGHT=new SSCD.Vector(1,-1),SSCD.Vector.DOWN_RIGHT=new SSCD.Vector(1,1);var SSCD=SSCD||{};SSCD.extend=function(t,i){for(var _ in t)i[_]||(i[_]=t[_]);i.__inits=i.__inits||[],t.__init__&&i.__inits.push(t.__init__),i.init=function(){for(var t=0;t0&&(this.position.x-=i,this.size.x+=i);var _=this.position.y-t.y;_>0&&(this.position.y-=_,this.size.y+=_);var e=t.x-(this.position.x+this.size.x);e>0&&(this.size.x+=e);var s=t.y-(this.position.y+this.size.y);s>0&&(this.size.y+=s)},clone:function(){return new SSCD.AABB(this.position,this.size)}};var SSCD=SSCD||{};SSCD.Shape=function(){},SSCD.Shape.prototype={__type:"shape",is_shape:!0,__data:null,__next_id:0,__collision_tags:[],__collision_tags_val:SSCD.World.prototype._ALL_TAGS_VAL,__init__:function(){this.__position=new SSCD.Vector,this.__grid_chunks=[],this.__world=null,this.__grid_bounderies=null,this.__last_insert_aabb=null,this.__id=SSCD.Shape.prototype.__next_id++},get_id:function(){return this.__id},set_collision_tags:function(t){if(null===this.__world)throw new SSCD.IllegalActionError("Can't set tags for a shape that is not inside a collision world!");return this.__collision_tags_val=this.__world.__get_tags_value(t),!t instanceof Array&&(t=[t]),this.__collision_tags=t,this.__update_tags_hook&&this.__update_tags_hook(),this},__update_tags_hook:null,get_collision_tags:function(){return this.__collision_tags},collision_tags_match:function(t){if(isNaN(t)){if(null===this.__world)throw new SSCD.IllegalActionError("If you provide tags as string(s) the shape must be inside a collision world to convert them!");t=this.__world.__get_tags_value(t)}return 0!==(this.__collision_tags_val&t)},test_collide_with:function(t){return SSCD.CollisionManager.test_collision(this,t)},repel:function(t,i,_,e,s){i=i||1,_=_||1,void 0===e&&(e=0),void 0===s&&(s=1);var o,n,r=this.get_repel_direction(t).multiply_scalar_self(i);s&&(o=r.multiply_scalar(s)),e&&(n=r.multiply_scalar(-1*e));for(var a=SSCD.Vector.ZERO.clone(),l=!0;l&&_>0;)_--,o&&t.move(o),n&&this.move(n),a.add_self(r),l=this.test_collide_with(t);return a},get_repel_direction:function(t){var i,_=this.get_abs_center();return i=t instanceof SSCD.Vector?t:t.get_abs_center(),i.sub(_).normalize_self()},__get_render_fill_color:function(t){return this.__override_fill_color?this.__override_fill_color:this.__collision_tags_to_color(this.__collision_tags_val,t)},__get_render_stroke_color:function(t){return this.__override_stroke_color?this.__override_stroke_color:this.__collision_tags_to_color(this.__collision_tags_val,t)},set_debug_render_colors:function(t,i){this.__override_fill_color=t,this.__override_stroke_color=i},__override_fill_color:null,__override_stroke_color:null,__collision_tags_to_color:function(t,i){var _=Math.round(255*Math.abs(Math.sin(t))),e=Math.round(255*Math.abs(Math.cos(t))),s=Math.round(_^e);return"rgba("+_+","+e+","+s+","+i+")"},set_data:function(t){return this.__data=t,this},get_data:function(){return this.__data},get_name:function(){return this.__type},render_aabb:function(t,i){var _=this.get_aabb();t.beginPath(),t.rect(_.position.x-i.x,_.position.y-i.y,_.size.x,_.size.y),t.lineWidth="1",t.strokeStyle="rgba(50, 175, 45, 0.5)",t.stroke()},set_position:function(t){return this.__position.x=t.x,this.__position.y=t.y,this.__update_position(),this},get_position:function(){return this.__position.clone()},move:function(t){return this.set_position(this.__position.add(t)),this},__update_position:function(){this.__update_position_hook&&this.__update_position_hook(),this.__aabb&&this.__update_aabb_pos(),this.__update_parent_world()},__update_aabb_pos:function(){this.__aabb.position=this.__position},get_abs_center:function(){var t=this.get_aabb();return t.position.add(t.size.multiply_scalar(.5))},reset_aabb:function(){this.__aabb=void 0},__update_parent_world:function(){this.__world&&this.__world.__update_shape_grid(this)},__update_position_hook:null,render:function(){throw new SSCD.NotImplementedError},build_aabb:function(){throw new SSCD.NotImplementedError},get_aabb:function(){return this.__aabb=this.__aabb||this.build_aabb(),this.__aabb}};var SSCD=SSCD||{};SSCD.Circle=function(t,i){this.init(),this.__radius=i,this.__size=new SSCD.Vector(i,i).multiply_scalar_self(2),this.set_position(t)},SSCD.Circle.prototype={__type:"circle",render:function(t,i){var _=this.__position.sub(i);t.beginPath(),t.arc(_.x,_.y,this.__radius,0,2*Math.PI,!1),t.lineWidth="7",t.strokeStyle=this.__get_render_stroke_color(.75),t.stroke(),t.fillStyle=this.__get_render_fill_color(.35),t.fill()},get_radius:function(){return this.__radius},__update_aabb_pos:function(){this.__aabb.position=this.__position.sub_scalar(this.__radius)},build_aabb:function(){return new SSCD.AABB(this.__position.sub_scalar(this.__radius),this.__size)},get_abs_center:function(){return this.__position.clone()}},SSCD.extend(SSCD.Shape.prototype,SSCD.Circle.prototype);var SSCD=SSCD||{};SSCD.Rectangle=function(t,i){this.init(),this.__size=i,this.set_position(t)},SSCD.Rectangle.prototype={__type:"rectangle",render:function(t,i){var _=this.__position.sub(i);t.beginPath(),t.rect(_.x,_.y,this.__size.x,this.__size.y),t.lineWidth="7",t.strokeStyle=this.__get_render_stroke_color(.75),t.stroke(),t.fillStyle=this.__get_render_fill_color(.35),t.fill()},get_size:function(){return this.__size.clone()},build_aabb:function(){return new SSCD.AABB(this.__position,this.__size)},get_top_left:function(){return this.__top_left_c=this.__top_left_c||this.__position.clone(),this.__top_left_c},get_bottom_left:function(){return this.__bottom_left_c=this.__bottom_left_c||this.__position.add(new SSCD.Vector(0,this.__size.y)),this.__bottom_left_c},get_top_right:function(){return this.__top_right_c=this.__top_right_c||this.__position.add(new SSCD.Vector(this.__size.x,0)),this.__top_right_c},get_bottom_right:function(){return this.__bottom_right_c=this.__bottom_right_c||this.__position.add(new SSCD.Vector(this.__size.x,this.__size.y)),this.__bottom_right_c},get_abs_center:function(){return this.__abs_center_c=this.__abs_center_c||this.__position.add(this.__size.divide_scalar(2)),this.__abs_center_c},__update_position_hook:function(){this.__top_left_c=void 0,this.__top_right_c=void 0,this.__bottom_left_c=void 0,this.__bottom_right_c=void 0,this.__abs_center_c=void 0}},SSCD.extend(SSCD.Shape.prototype,SSCD.Rectangle.prototype);var SSCD=SSCD||{};SSCD.Line=function(t,i){this.init(),this.__dest=i,this.set_position(t)},SSCD.Line.prototype={__type:"line",render:function(t){t.beginPath(),t.moveTo(this.__position.x,this.__position.y);var i=this.__position.add(this.__dest);t.lineTo(i.x,i.y),t.lineWidth="7",t.strokeStyle=this.__get_render_stroke_color(.75),t.stroke()},build_aabb:function(){var t=new SSCD.Vector(0,0);t.x=this.__dest.x>0?this.__position.x:this.__position.x-this.__dest.x,t.y=this.__dest.y>0?this.__position.y:this.__position.y-this.__dest.y;var i=this.__dest.apply(Math.abs);return new SSCD.AABB(t,i)},get_p1:function(){return this.__p1_c=this.__p1_c||this.__position.clone(),this.__p1_c},get_p2:function(){return this.__p2_c=this.__p2_c||this.__position.add(this.__dest),this.__p2_c},__update_position_hook:function(){this.__p1_c=void 0,this.__p2_c=void 0}},SSCD.extend(SSCD.Shape.prototype,SSCD.Line.prototype);var SSCD=SSCD||{};SSCD.LineStrip=function(t,i,_){if(this.init(),this.__points=i,i.length<=1)throw new SSCD.IllegalActionError("Not enough vectors for LineStrip (got to have at least two vectors)");_&&this.__points.push(this.__points[0]),this.set_position(t)},SSCD.LineStrip.prototype={__type:"line-strip",render:function(t){var i=void 0;t.beginPath();for(var _=0;_=t.__position.x&&i.y>=t.__position.y&&i.x<=t.__position.x+t.__size.x&&i.y<=t.__position.y+t.__size.y},_test_collision_vector_line:function(t,i){return SSCD.Math.is_on_line(t,i.get_p1(),i.get_p2())},_test_collision_vector_linestrip:function(t,i){for(var _=i.get_abs_lines(),e=0;e<_.length;++e)if(SSCD.Math.is_on_line(t,_[e][0],_[e][1]))return!0;return!1},_test_collision_circle_line:function(t,i){return SSCD.Math.distance_to_line(t.__position,i.get_p1(),i.get_p2())<=t.__radius},_test_collision_circle_linestrip:function(t,i){for(var _=i.get_abs_lines(),e=0;e<_.length;++e)if(SSCD.Math.distance_to_line(t.__position,_[e][0],_[e][1])<=t.__radius)return!0;return!1},_test_collision_linestrip_line:function(t,i){for(var _=t.get_abs_lines(),e=i.get_p1(),s=i.get_p2(),o=0;o<_.length;++o)if(SSCD.Math.line_intersects(e,s,_[o][0],_[o][1]))return!0;return!1},_test_collision_line_line:function(t,i){return SSCD.Math.line_intersects(t.get_p1(),t.get_p2(),i.get_p1(),i.get_p2())},_test_collision_rect_line:function(t,i){var _=i.get_p1(),e=i.get_p2();if(SSCD.CollisionManager._test_collision_rect_vector(t,_)||SSCD.CollisionManager._test_collision_rect_vector(t,e))return!0;var s=t.get_top_left(),o=t.get_bottom_left();if(SSCD.Math.line_intersects(_,e,s,o))return!0;var n=t.get_top_right(),r=t.get_bottom_right();return SSCD.Math.line_intersects(_,e,n,r)?!0:SSCD.Math.line_intersects(_,e,s,n)?!0:SSCD.Math.line_intersects(_,e,o,r)?!0:!1},_test_collision_rect_linestrip:function(t,i){for(var _=i.get_abs_points(),e=0;e<_.length;++e)if(this._test_collision_rect_vector(t,_[e]))return!0;for(var s=t.get_top_left(),o=t.get_bottom_left(),n=t.get_top_right(),r=t.get_bottom_right(),a=i.get_abs_lines(),e=0;e_.x?[i.get_top_left(),i.get_bottom_left()]:[i.get_top_right(),i.get_bottom_right()]),o.push(s.y>_.y?[i.get_top_left(),i.get_top_right()]:[i.get_bottom_left(),i.get_bottom_right()]);for(var n=0;n_.right||e.right<_.left||e.top>_.bottom||e.bottom<_.top)}},SSCD.UnsupportedShapes=function(t,i){this.name="Unsupported Shapes",this.message="Unsupported shapes collision test! '"+t.get_name()+"' <-> '"+i.get_name()+"'."},SSCD.UnsupportedShapes.prototype=Error.prototype,"undefined"!=typeof exports&&(exports.sscd=SSCD); \ No newline at end of file diff --git a/src/shapes/shape.js b/src/shapes/shape.js index 5dcbcea..e86da5c 100644 --- a/src/shapes/shape.js +++ b/src/shapes/shape.js @@ -129,16 +129,23 @@ SSCD.Shape.prototype = { // obj: object or vector to repeal (must have move() function). // force: force factor, the bigger this is the stronger / faster the repealing will be. default to 1. // iterations: max iterations of repeal-and-test-again routines. default to 1. + // factor_self: factor to multiply force that will apply on this shape. default to 0. + // factor_other: factor to multiply force that will apply on this shape. default to 1. // NOTE: this function assume there's collision on start, meaning first iteration of repeal will ALWAYS happen. // return: total movement due to repeling (vector) - repel: function(obj, force, iterations) + repel: function(obj, force, iterations, factor_self, factor_other) { // set defaults force = force || 1; iterations = iterations || 1; + if (factor_self === undefined) factor_self = 0; + if (factor_other === undefined) factor_other = 1; - // get direction vector + // get push vectors + var push_vector_other, push_vector_self; var push_vector = this.get_repel_direction(obj).multiply_scalar_self(force); + if (factor_other) push_vector_other = push_vector.multiply_scalar(factor_other); + if (factor_self) push_vector_self = push_vector.multiply_scalar(factor_self * -1); // for return value var ret = SSCD.Vector.ZERO.clone(); @@ -151,7 +158,8 @@ SSCD.Shape.prototype = { iterations--; // do pushing - obj.move(push_vector); + if (push_vector_other) obj.move(push_vector_other); + if (push_vector_self) this.move(push_vector_self); ret.add_self(push_vector); // check if still colliding