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.

271 lines
7.9KB

  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 = 128 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. if alt.r != alt.g or alt.r != alt.b:
  32. # only change the rim if there's a single dominant color.
  33. $Sprite.material.set_shader_param("rim_color", alt);
  34. $Particles.process_material.color = alt
  35. if prime.r != prime.g or prime.r != prime.b: # Only adjust mood if not all values are the same.
  36. # Even if not all the same, there must be a single dominant color for mood to be adjusted.
  37. if prime.r > prime.g and prime.r > prime.b:
  38. adjust_mood(0.25, 0.0, 0.0)
  39. if prime.g > prime.r and prime.g > prime.b:
  40. adjust_mood(0.0, 0.25, 0.0)
  41. if prime.b > prime.r and prime.b > prime.g:
  42. adjust_mood(0.0, 0.0, 0.25)
  43. func get_colors():
  44. return {
  45. "prime": $Sprite.material.get_shader_param("cell_color"),
  46. "alt": $Sprite.material.get_shader_param("rim_color")
  47. };
  48. func adjust_mood(r, g, b):
  49. mood.r = clamp(mood.r + r, 0.0, 1.0)
  50. mood.g = clamp(mood.g + g, 0.0, 1.0)
  51. mood.b = clamp(mood.b + b, 0.0, 1.0)
  52. $Sprite.material.set_shader_param("cell_color", mood);
  53. if is_aggressive():
  54. $Sprite.material.set_shader_param("cell_energy", ANIM_RATE_AGGRESSIVE)
  55. elif is_content():
  56. $Sprite.material.set_shader_param("cell_energy", ANIM_RATE_CONTENT)
  57. else:
  58. $Sprite.material.set_shader_param("cell_energy", ANIM_RATE_DEFAULT)
  59. func is_aggressive():
  60. return mood.r > mood.g and mood.r > mood.b
  61. func is_needie():
  62. return mood.g > mood.r and mood.g > mood.b
  63. func is_content():
  64. return mood.b > mood.r and mood.b > mood.g
  65. func get_tangential_acceleration():
  66. return get_discomfort_adjustment(base_tangential_accel)
  67. func get_push_force():
  68. var dist = (position - mouse_position).length() - get_body_radius()
  69. if dist <= 0.0:
  70. return 0.0
  71. var push = base_push_force * (dist / (max_mouse_distance))
  72. if mood.r > mood.b:
  73. if mood.r > 0.1 and mood.r < 0.5:
  74. push *= 1.25
  75. elif mood.r >= 0.5:
  76. push *= 1.5
  77. elif is_aggressive():
  78. push *= 2
  79. elif mood.b > mood.r:
  80. if mood.b > 0.1 and mood.b < 0.5:
  81. push *= 0.75
  82. elif mood.b >= 0.5:
  83. push *= 0.5
  84. return push
  85. func get_discomfort_adjustment(v):
  86. return v * mood.g
  87. func get_body_radius():
  88. return $CollisionShape2D.shape.radius
  89. func _set_base_tangential_accel(v):
  90. base_tangential_accel = max(1.0, v)
  91. func _set_base_push_force(v):
  92. base_push_force = max(1.0, v)
  93. # Called when the node enters the scene tree for the first time.
  94. func _ready():
  95. set_process(true)
  96. set_physics_process(true)
  97. set_process_input(true)
  98. max_comfort_distance = $CollisionShape2D.shape.radius
  99. $Sprite.material.set_shader_param("rim_color", neutral_rim);
  100. $Particles.process_material.color = neutral_rim
  101. func _input(event):
  102. if Input.is_action_just_pressed("ButtonA"):
  103. mouse_down = true
  104. elif Input.is_action_just_released("ButtonA"):
  105. mouse_down = false
  106. push = true
  107. func _shift_mood(delta):
  108. var nr = 0.0
  109. var ng = 0.0
  110. var nb = 0.0
  111. if in_air:
  112. if last_speed >= COLLISION_MINOR_SPEED_THRESHOLD:
  113. if last_speed >= COLLISION_MAJOR_SPEED_THRESHOLD:
  114. nr += 0.1
  115. else:
  116. nr += 0.05
  117. else:
  118. nr -= 0.1
  119. nb += 0.05
  120. # first handle red (aggression)
  121. if mood.r > 0:
  122. if mood.b > 0.0:
  123. if mood.b >= mood.r * 0.5:
  124. nr += -0.1
  125. if mood.b < mood.r * 0.5:
  126. nr += -0.05
  127. if mood.r > mood.b:
  128. nr += 0.05
  129. nr *= delta
  130. # Then handle green <neediness>
  131. # green <neediness> is based on how far the mouse is from the player. The greater the distance
  132. # the more <neediness> grows. This can be affected by <contentment> and <aggression> as well.
  133. var mdist = (position - mouse_position).length()
  134. if not in_air:
  135. if is_content():
  136. if mdist <= max_comfort_distance:
  137. ng += -0.1
  138. elif mdist < (max_mouse_distance * 0.5):
  139. ng += -0.05
  140. elif is_needie():
  141. if mdist <= max_comfort_distance:
  142. ng += -0.05
  143. elif mdist >= (max_mouse_distance * 0.5):
  144. ng += 0.1
  145. else:
  146. ng += 0.05
  147. elif is_aggressive():
  148. # If player is <aggressive>, then neediness is kinda forgotten about.
  149. if mood.r > 0.25 and mood.r < 0.5:
  150. ng += -0.05
  151. elif mood.r >= 0.5:
  152. ng += -0.15
  153. else:
  154. if mdist > max_comfort_distance:
  155. ng += 0.05
  156. ng *= delta
  157. # Finally handle blue <contentment>
  158. # If red <aggression> is half as high or more than blue <contentment>, then contentment goes down.
  159. if mood.r >= mood.b * 0.5:
  160. nb += -0.1
  161. elif mood.g > 0.0:
  162. nb += -0.025
  163. if mdist < max_comfort_distance:
  164. nb += 0.015
  165. else:
  166. nb += -0.1
  167. nb *= delta
  168. # Finalize changes!
  169. adjust_mood(nr, ng, nb)
  170. func _physics_process(delta):
  171. mouse_position = get_global_mouse_position()
  172. if mouse_down:
  173. return # We don't follow the mouse or move the squiq when mouse is down.
  174. if push:
  175. push = false
  176. var v_direction = (position - mouse_position).normalized()
  177. apply_central_impulse(v_direction * abs(v_direction.length()) * get_push_force())
  178. elif in_air:
  179. air_time += delta
  180. else:
  181. var distance = clamp(mouse_position.x - position.x, -max_mouse_distance, max_mouse_distance)
  182. var dpercent = distance / max_mouse_distance
  183. if !is_content() and abs(distance) > get_body_radius():
  184. var v_horizontal = Physics2DServer.area_get_param(get_world_2d().get_space(), Physics2DServer.AREA_PARAM_GRAVITY_VECTOR).rotated(deg2rad(-90))
  185. $Particles.process_material.tangential_accel = dpercent * get_tangential_acceleration();
  186. apply_central_impulse(v_horizontal * get_discomfort_adjustment(distance) * delta)
  187. else:
  188. $Particles.process_material.tangential_accel = 0
  189. _shift_mood(delta)
  190. last_speed = linear_velocity.length()
  191. func _process(delta):
  192. update()
  193. func _draw():
  194. if mouse_down:
  195. var distance = min(position.distance_to(mouse_position), max_mouse_distance)
  196. var v_direction = (position - mouse_position).normalized().rotated(-rotation)
  197. var v_start = v_direction * get_body_radius()
  198. var v_end = v_direction * distance
  199. var v_tipA = v_end - (v_direction.rotated(deg2rad(30)) * min(distance, 16))
  200. var v_tipB = v_end - (v_direction.rotated(-deg2rad(30)) * min(distance, 16))
  201. var c_line = Color(0.25, 1.0, 0.0)
  202. draw_line(v_start, v_end, c_line)
  203. draw_line(v_end, v_tipA, c_line)
  204. draw_line(v_end, v_tipB, c_line)
  205. func _on_Player_body_entered(body):
  206. in_air = false
  207. #print(linear_velocity)
  208. if air_time > COLLISION_TIMEDT_THRESHOLD:
  209. #var lvlen = linear_velocity.length()
  210. #print("Last Speed: ", last_speed)
  211. if last_speed >= COLLISION_MINOR_SPEED_THRESHOLD and last_speed < COLLISION_MAJOR_SPEED_THRESHOLD:
  212. adjust_mood(0.1, 0.0, -0.1)
  213. $Camera/ScreenShake.start()
  214. elif last_speed >= COLLISION_MAJOR_SPEED_THRESHOLD:
  215. adjust_mood(0.25, 0.0, -0.25)
  216. $Camera/ScreenShake.start(0.4, 15, 24)
  217. air_time = 0
  218. func _on_Player_body_exited(body):
  219. in_air = true