A game created for the Godot Wild Jam #21
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
8.3KB

  1. extends RigidBody2D
  2. const COLLISION_MINOR_SPEED_THRESHOLD = 150
  3. const COLLISION_MAJOR_SPEED_THRESHOLD = 400
  4. const COLLISION_TIMEDT_THRESHOLD = 0.1
  5. const ANIM_RATE_DEFAULT = 3.5
  6. const ANIM_RATE_AGGRESSIVE = 6.0
  7. const ANIM_RATE_CONTENT = 1.0
  8. # The maximum distance from the player in which the mouse will adjust the push force.
  9. # at max_mouse_distance the full base_push_force <+ modifiers> will be applied.
  10. var max_mouse_distance = 256
  11. # The maximum the mouse can be from the player before player becomes "uncomfortable"
  12. var max_comfort_distance = 10
  13. # The base tangential acceleration that will be applied to the particles to give the
  14. # player the illusion it's trying to move on it's own. This is just effects things visually (ATM)
  15. export var base_tangential_accel = 32 setget _set_base_tangential_accel
  16. # The base force applied when being pushed.
  17. export var base_push_force = 64 setget _set_base_push_force
  18. # Mood = r: <aggression>, g: <neediness>, b: <contentment>
  19. # <aggression> Affects how strong a players push is and how strong the player's collision with the world will be.
  20. # <neediness> Affects how quickly and strongly the player will follow the mouse
  21. # <contentment> Affects how slowly mood color is shifted back to neutral and widens comfort distance
  22. var mood = Color.black
  23. var neutral_rim = Color(0.9, 0.9, 0.9, 1.0)
  24. var mouse_position = Vector2.ZERO
  25. var mouse_down = false
  26. var push = false
  27. var in_air = true
  28. var air_time = 0
  29. var last_speed = 0
  30. func set_colors(prime, alt):
  31. $Sprite.material.set_shader_param("rim_color", alt);
  32. $Particles.process_material.color = alt
  33. if alt.r > alt.g and alt.r > alt.b:
  34. _set_color_collision_mask(1)
  35. elif alt.g > alt.r and alt.g > alt.b:
  36. _set_color_collision_mask(2)
  37. elif alt.b > alt.r and alt.b > alt.g:
  38. _set_color_collision_mask(3)
  39. else:
  40. # This should reset all of the collision masks to ON!
  41. _set_color_collision_mask(0)
  42. if prime.r != prime.g or prime.r != prime.b: # Only adjust mood if not all values are the same.
  43. # Even if not all the same, there must be a single dominant color for mood to be adjusted.
  44. if prime.r > prime.g and prime.r > prime.b:
  45. adjust_mood(0.25, 0.0, 0.0)
  46. if prime.g > prime.r and prime.g > prime.b:
  47. adjust_mood(0.0, 0.25, 0.0)
  48. if prime.b > prime.r and prime.b > prime.g:
  49. adjust_mood(0.0, 0.0, 0.25)
  50. func get_colors():
  51. return {
  52. "prime": $Sprite.material.get_shader_param("cell_color"),
  53. "alt": $Sprite.material.get_shader_param("rim_color")
  54. };
  55. func adjust_mood(r, g, b):
  56. mood.r = clamp(mood.r + r, 0.0, 1.0)
  57. mood.g = clamp(mood.g + g, 0.0, 1.0)
  58. mood.b = clamp(mood.b + b, 0.0, 1.0)
  59. $Sprite.material.set_shader_param("cell_color", mood);
  60. if is_aggressive():
  61. $Sprite.material.set_shader_param("cell_energy", ANIM_RATE_AGGRESSIVE)
  62. elif is_content():
  63. $Sprite.material.set_shader_param("cell_energy", ANIM_RATE_CONTENT)
  64. else:
  65. $Sprite.material.set_shader_param("cell_energy", ANIM_RATE_DEFAULT)
  66. func is_aggressive():
  67. return mood.r > mood.g and mood.r > mood.b
  68. func is_needie():
  69. return mood.g > mood.r and mood.g > mood.b
  70. func is_content():
  71. return mood.b > mood.r and mood.b > mood.g
  72. func get_tangential_acceleration():
  73. return get_discomfort_adjustment(base_tangential_accel)
  74. func get_push_force():
  75. var dist = (position - mouse_position).length() - get_body_radius()
  76. if dist <= 0.0:
  77. return 0.0
  78. var push = base_push_force * (dist / (max_mouse_distance))
  79. if mood.r > mood.b:
  80. if mood.r > 0.1 and mood.r < 0.5:
  81. push *= 1.25
  82. elif mood.r >= 0.5:
  83. push *= 1.5
  84. elif is_aggressive():
  85. push *= 2
  86. elif mood.b > mood.r:
  87. if mood.b > 0.1 and mood.b < 0.5:
  88. push *= 0.75
  89. elif mood.b >= 0.5:
  90. push *= 0.5
  91. return push
  92. func get_discomfort_adjustment(v):
  93. return v * mood.g
  94. func get_body_radius():
  95. return $CollisionShape2D.shape.radius
  96. func _set_color_collision_mask(id):
  97. set_collision_mask_bit(10, true)
  98. set_collision_mask_bit(11, true)
  99. set_collision_mask_bit(12, true)
  100. if id >= 1 and id <= 3:
  101. set_collision_mask_bit(9 + id, false)
  102. func _set_base_tangential_accel(v):
  103. base_tangential_accel = max(1.0, v)
  104. func _set_base_push_force(v):
  105. base_push_force = max(1.0, v)
  106. # Called when the node enters the scene tree for the first time.
  107. func _ready():
  108. set_process(true)
  109. set_physics_process(true)
  110. set_process_input(true)
  111. max_comfort_distance = $CollisionShape2D.shape.radius
  112. $Sprite.material.set_shader_param("rim_color", neutral_rim);
  113. $Particles.process_material.color = neutral_rim
  114. func _input(event):
  115. if Input.is_action_just_pressed("ButtonA"):
  116. mouse_down = true
  117. elif Input.is_action_just_released("ButtonA"):
  118. mouse_down = false
  119. push = true
  120. func _shift_mood(delta):
  121. var nr = 0.0
  122. var ng = 0.0
  123. var nb = 0.0
  124. if in_air:
  125. if last_speed >= COLLISION_MINOR_SPEED_THRESHOLD:
  126. if last_speed >= COLLISION_MAJOR_SPEED_THRESHOLD:
  127. nr += 0.1
  128. else:
  129. nr += 0.05
  130. else:
  131. nr -= 0.1
  132. nb += 0.05
  133. # first handle red (aggression)
  134. if mood.r > 0:
  135. if mood.b > 0.0:
  136. if mood.b >= mood.r * 0.5:
  137. nr += -0.1
  138. if mood.b < mood.r * 0.5:
  139. nr += -0.05
  140. if mood.r > mood.b:
  141. nr += 0.05
  142. nr *= delta
  143. # Then handle green <neediness>
  144. # green <neediness> is based on how far the mouse is from the player. The greater the distance
  145. # the more <neediness> grows. This can be affected by <contentment> and <aggression> as well.
  146. var mdist = (position - mouse_position).length()
  147. if not in_air:
  148. if is_content():
  149. if mdist <= max_comfort_distance:
  150. ng += -0.1
  151. elif mdist < (max_mouse_distance * 0.5):
  152. ng += -0.05
  153. elif is_needie():
  154. if mdist <= max_comfort_distance:
  155. ng += -0.05
  156. elif mdist >= (max_mouse_distance * 0.5):
  157. ng += 0.1
  158. else:
  159. ng += 0.05
  160. elif is_aggressive():
  161. # If player is <aggressive>, then neediness is kinda forgotten about.
  162. if mood.r > 0.25 and mood.r < 0.5:
  163. ng += -0.05
  164. elif mood.r >= 0.5:
  165. ng += -0.15
  166. else:
  167. if mdist > max_comfort_distance:
  168. ng += 0.05
  169. ng *= delta
  170. # Finally handle blue <contentment>
  171. # If red <aggression> is half as high or more than blue <contentment>, then contentment goes down.
  172. if mood.r >= mood.b * 0.5:
  173. nb += -0.1
  174. elif mood.g > 0.0:
  175. nb += -0.025
  176. if mdist < max_comfort_distance:
  177. nb += 0.015
  178. else:
  179. nb += -0.1
  180. nb *= delta
  181. # Finalize changes!
  182. adjust_mood(nr, ng, nb)
  183. func _physics_process(delta):
  184. mouse_position = get_global_mouse_position()
  185. if mouse_down:
  186. return # We don't follow the mouse or move the squiq when mouse is down.
  187. if push:
  188. push = false
  189. var v_direction = (position - mouse_position).normalized()
  190. apply_central_impulse(v_direction * abs(v_direction.length()) * get_push_force())
  191. elif in_air:
  192. air_time += delta
  193. else:
  194. var distance = clamp(mouse_position.x - position.x, -max_mouse_distance, max_mouse_distance)
  195. var dpercent = distance / max_mouse_distance
  196. if !is_content() and abs(distance) > get_body_radius():
  197. var v_horizontal = Physics2DServer.area_get_param(get_world_2d().get_space(), Physics2DServer.AREA_PARAM_GRAVITY_VECTOR).rotated(deg2rad(-90))
  198. $Particles.process_material.tangential_accel = dpercent * get_tangential_acceleration();
  199. apply_central_impulse(v_horizontal * get_discomfort_adjustment(distance) * delta)
  200. else:
  201. $Particles.process_material.tangential_accel = 0
  202. _shift_mood(delta)
  203. last_speed = linear_velocity.length()
  204. func _process(delta):
  205. update()
  206. func _draw():
  207. if mouse_down:
  208. var distance = min(position.distance_to(mouse_position), max_mouse_distance)
  209. var v_direction = (position - mouse_position).normalized().rotated(-rotation)
  210. var v_start = v_direction * get_body_radius()
  211. var v_end = v_direction * distance
  212. var v_tipA = v_end - (v_direction.rotated(deg2rad(30)) * min(distance, 16))
  213. var v_tipB = v_end - (v_direction.rotated(-deg2rad(30)) * min(distance, 16))
  214. var c_line = Color(0.25, 1.0, 0.0)
  215. draw_line(v_start, v_end, c_line)
  216. draw_line(v_end, v_tipA, c_line)
  217. draw_line(v_end, v_tipB, c_line)
  218. func _on_Player_body_entered(body):
  219. in_air = false
  220. #print(linear_velocity)
  221. if air_time > COLLISION_TIMEDT_THRESHOLD:
  222. #var lvlen = linear_velocity.length()
  223. #print("Last Speed: ", last_speed)
  224. if last_speed >= COLLISION_MINOR_SPEED_THRESHOLD and last_speed < COLLISION_MAJOR_SPEED_THRESHOLD:
  225. adjust_mood(0.1, 0.0, -0.1)
  226. $Camera/ScreenShake.start()
  227. elif last_speed >= COLLISION_MAJOR_SPEED_THRESHOLD:
  228. adjust_mood(0.25, 0.0, -0.25)
  229. $Camera/ScreenShake.start(0.4, 15, 24)
  230. air_time = 0
  231. func _on_Player_body_exited(body):
  232. in_air = true