CPU_object.gd 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. extends Sprite
  2. export var radius=0 # 512 256 64 32
  3. export var mass=0
  4. export var is_static=false # static does not move by gravity
  5. export var can_collide=true # collision enable
  6. # bounce include gravity vector and reflect it, false to disable
  7. export var reflect_gravity_on_hit=false
  8. export var bval=1.0 # 1.0 is bounce value, set <1
  9. # enable/disable self gravity
  10. export var self_gravity=true
  11. # enable/disable self gravity
  12. export var react_gravity=true
  13. export var coll_level_3_active=false
  14. export var start_heading=Vector2()
  15. var is_active=true # if false this object ignored
  16. var heading=Vector2() #velocity
  17. onready var root_node=get_node("../")
  18. var node_list=Array()
  19. # colors
  20. # black static object with gravity
  21. # red movable object with gravity, and do not react on other gravity
  22. # blue moving object without gravity
  23. # green moving object without gravity and collision
  24. #texture used to have mipmaps
  25. func _ready():
  26. if(radius==512):
  27. self.texture=load("res://round.png") as Texture
  28. elif(radius==256):
  29. self.texture=load("res://round2.png") as Texture
  30. elif(radius==64):
  31. self.texture=load("res://round3.png") as Texture
  32. elif(radius==32):
  33. self.texture=load("res://round4.png") as Texture
  34. else:
  35. radius=0
  36. if(radius==0)||(mass==0):
  37. is_active=false
  38. self.visible=false
  39. for a in range(get_node("../").get_child_count()):
  40. var el=get_node("../").get_child(a)
  41. node_list.append(el)
  42. var self_color=Color()
  43. self.material=self.material.duplicate()
  44. if(is_static):
  45. self_color=Color.black
  46. elif(can_collide)&&(self_gravity)&&(!react_gravity):
  47. self_color=Color.red
  48. elif(can_collide)&&(!self_gravity)&&(react_gravity):
  49. self_color=Color.blue
  50. elif(!can_collide)&&(!self_gravity)&&(react_gravity):
  51. self_color=Color.green
  52. self.material.set("shader_param/color",self_color)
  53. heading=start_heading
  54. func _process(delta):
  55. if(!is_active):
  56. return #can be free() node instead
  57. sumVector()
  58. slow_it(delta)
  59. lim_heading()
  60. self.position+=heading
  61. update_text()
  62. process_input()
  63. func update_text():
  64. self.material.set("shader_param/len",str(mass).length())
  65. self.material.set("shader_param/value",int(mass))
  66. self.material.set("shader_param/zoom_val",root_node.scale.x)
  67. # mass change by mouse
  68. func process_input():
  69. if !(self_gravity&&is_active):
  70. return
  71. var iResolution=Vector2(1280,720)
  72. var iMouse=get_viewport().get_mouse_position()/iResolution
  73. iMouse=(iMouse-Vector2(0.5,0.5))*iResolution
  74. if((self.position*root_node.scale-iMouse).length()<(radius/2)*root_node.scale.x):
  75. root_node.mouse_block=true
  76. if(Input.is_action_pressed("l_click")):
  77. mass+=int(250+20000*smoothstep(5000,500000,mass))
  78. if(Input.is_action_pressed("r_click")):
  79. mass+=-int(250+20000*smoothstep(5000,500000,mass))
  80. mass=clamp(mass,10,9999999)
  81. # max speed limit, slowdown
  82. const max_speed=10
  83. func lim_heading():
  84. if(heading.length()>max_speed):
  85. heading=heading.normalized()*max_speed
  86. func angle2d(c,e):
  87. var theta = atan2(e.y-c.y,e.x-c.x)
  88. return theta
  89. # move back to center when position too far
  90. const max_length=10000
  91. func slow_it(delta):
  92. if(self.position.length()>max_length):
  93. var angl=-PI/2+angle2d(Vector2(),self.position)
  94. var tva=max_speed*Vector2(sin(-angl),cos(-angl))
  95. heading+=-tva*delta
  96. # void
  97. func distance_length(a,b):
  98. return (a-b).length()
  99. # float
  100. func calculateGravity(body):
  101. if(body==self):
  102. return 0
  103. var mass1=mass
  104. var mass2=body.mass
  105. var distanceBetween=distance_length(self.position,body.position)
  106. distanceBetween=max(distanceBetween,0.0001)
  107. return ((mass1 * mass2) / pow(distanceBetween, 2))
  108. # vec2
  109. func findVector(body):
  110. var forceBetween = calculateGravity(body);
  111. var hvDist=body.position-self.position
  112. var totalDistance = abs(hvDist.x) + abs(hvDist.y);
  113. totalDistance=max(totalDistance,0.0001)
  114. return (forceBetween / totalDistance) * hvDist;
  115. # bool
  116. func collides(body):
  117. var temp=self.position+heading
  118. var distance = distance_length(temp,body.position);
  119. if (distance < radius/2+body.radius/2):
  120. return true
  121. else:
  122. return false
  123. # vec2
  124. func bounce(body,fi,dyn):
  125. var tangentVector=Vector2()
  126. tangentVector.y = -(body.position.x - self.position.x)
  127. tangentVector.x = body.position.y - self.position.y
  128. tangentVector = tangentVector.normalized()
  129. var tfi=Vector2()
  130. if(reflect_gravity_on_hit):
  131. tfi=fi
  132. var relativeVelocity = self.heading - body.heading + tfi
  133. var leng = relativeVelocity.dot(tangentVector)
  134. var velComponentOnTangent = leng*tangentVector
  135. var velComponentPerpendicularToTangent=relativeVelocity - velComponentOnTangent
  136. var ret=velComponentPerpendicularToTangent
  137. if(dyn):
  138. var tret=2*ret/(mass+body.mass)
  139. body.heading+=tret*mass
  140. return -tret*body.mass
  141. else:
  142. return -2*ret
  143. # vec2
  144. func unstuck(body):
  145. var angl=-PI/2+angle2d(self.position,body.position)
  146. var temp=self.position+heading
  147. var distance = distance_length(temp,body.position);
  148. var distanceToMove = radius/2 + body.radius/2 - distance
  149. var tva=distanceToMove*Vector2(sin(-angl),cos(-angl))
  150. self.position+=-tva
  151. # void
  152. func sumVector():
  153. if(is_static):
  154. return
  155. var final=heading
  156. for a in range(node_list.size()):
  157. var el=node_list[a]
  158. if(el==self)||(!el.is_active):
  159. continue
  160. if(!is_static)&&(react_gravity)&&(el.self_gravity):
  161. var tv=findVector(el) # gravity
  162. final+=tv
  163. if(!is_static)&&(can_collide)&&(el.can_collide):
  164. if(collides(el)): # collision
  165. if(el.is_static):
  166. final=heading+bounce(el,final,false)*bval # bounce static
  167. else:
  168. final=heading+bounce(el,final,true)*bval # bounce dyn
  169. unstuck(el)
  170. #break
  171. heading=final