Skip to content

Commit

Permalink
added NinjaHook, example Player Controller and made NinjaRope customi…
Browse files Browse the repository at this point in the history
…zable

Added a NinjaHook script to have a dynamic hook. Included is also an
example, "NinjaRopePlayerController" (note that the
"ExamplePlayerController" has been renamed to
"PermanentRopePlayerController").
Also, made the NinjaRope be able to have an unlimited size.
  • Loading branch information
Pampattitude committed Oct 5, 2015
1 parent 6b90be4 commit 1c9b322
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 8 deletions.
88 changes: 88 additions & 0 deletions NinjaHook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using UnityEngine;
using System.Collections;

public class NinjaHook: MonoBehaviour {
public Vector3 direction;
public float speed;

private bool isHooked_ = false;
public delegate void HookAction();
public event HookAction onHooked;

private Rigidbody2D rigidbody_;

protected void Start() {
this.initRigidbody_();

// Normalize direction and adapt hook angle
this.direction.Normalize();
gameObject.transform.eulerAngles = new Vector3(0f, 0f, NinjaHook.pointsToAngle(Vector3.zero, this.direction));
}

protected void FixedUpdate() {
// When hooked, the hook stops moving
if (this.isHooked_)
return ;

// Make sure the rotation is right (because of the parent)...
gameObject.transform.eulerAngles = new Vector3(0f, 0f, NinjaHook.pointsToAngle(Vector3.zero, this.direction));
// ... and also make sure the velocity hasn't changed
this.rigidbody_.velocity = this.direction * this.speed;
}


// Initialization
private void initRigidbody_() {
this.rigidbody_ = gameObject.GetComponent<Rigidbody2D>();
if (!this.rigidbody_) {
this.rigidbody_ = gameObject.AddComponent<Rigidbody2D>();

// No mass, no gravity. The entity is entirely managed by script
this.rigidbody_.mass = 0f;
this.rigidbody_.gravityScale = 0f;
}

this.rigidbody_.interpolation = RigidbodyInterpolation2D.Interpolate;
this.rigidbody_.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
this.rigidbody_.sleepMode = RigidbodySleepMode2D.StartAwake;
}
// !Initialization


// Listeners
protected void OnCollisionEnter2D(Collision2D c) {
// Make kinematic to ensure the hook won't move anymore
this.rigidbody_.isKinematic = true;

// Stick it to the collided obstacle
gameObject.transform.position = Physics2D.Raycast(gameObject.transform.position, this.direction).point;
gameObject.transform.eulerAngles = new Vector3(0f, 0f, NinjaHook.pointsToAngle(Vector3.zero, this.direction));

this.isHooked_ = true;
if (null != this.onHooked)
this.onHooked();
}
protected void OnTriggerEnter2D(Collider2D c) {
// Make kinematic to ensure the hook won't move anymore
this.rigidbody_.isKinematic = true;

// Stick it to the collided obstacle
gameObject.transform.position = Physics2D.Raycast(gameObject.transform.position, this.direction).point;
gameObject.transform.eulerAngles = new Vector3(0f, 0f, NinjaHook.pointsToAngle(Vector3.zero, this.direction));

this.isHooked_ = true;
if (null != this.onHooked)
this.onHooked();
}
// !Listeners


// Util
public bool isHooked() { return this.isHooked_; }

private static float pointsToAngle(Vector2 anc1, Vector2 anc2) {
// Returns the angle between both vectors; note that the angle is NOT between -180 and 180
return (Mathf.Atan2(anc2.y - anc1.y, anc2.x - anc1.x) * Mathf.Rad2Deg - 90f);
}
// !Util
}
39 changes: 32 additions & 7 deletions NinjaRope.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
using UnityEngine;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/*
* Game object must have:
* - the script (duh)
* - a line renderer
*/
[RequireComponent(typeof(LineRenderer))]
public class NinjaRope: MonoBehaviour {
private Rigidbody2D rigidbody_;
Expand Down Expand Up @@ -142,8 +137,16 @@ private void updateJoint_() {
DistanceJoint2D joint = gameObject.GetComponent<DistanceJoint2D>();
if (!joint) {
joint = gameObject.AddComponent<DistanceJoint2D>();
joint.maxDistanceOnly = false;

if (float.MaxValue - 0.001f > this.ropeLength)
joint.maxDistanceOnly = false;
else
joint.maxDistanceOnly = true;
}
if (float.MaxValue - 0.001f > this.ropeLength)
joint.maxDistanceOnly = false;
else
joint.maxDistanceOnly = true;

joint.anchor = gameObject.transform.InverseTransformPoint(this.lastAnchor.anchor);
joint.connectedBody = this.endEntity.GetComponent<Rigidbody2D>();
Expand Down Expand Up @@ -231,5 +234,27 @@ private float getActualRopeLength_() {
dist += Vector3.Distance(this.anchors_[i].anchor, this.anchors_[i + 1].anchor);
return dist;
}
// Different from the previous one because it also accounts for the last chunk, ending with the target
public float getRopeLength() {
float dist = 0f;
for (int i = 0 ; this.anchors_.Count > i + 1 ; ++i)
dist += Vector3.Distance(this.anchors_[i].anchor, this.anchors_[i + 1].anchor);
return dist;
}

public void setLength(float len) {
this.ropeLength = len;

DistanceJoint2D joint = gameObject.GetComponent<DistanceJoint2D>();
if (joint)
joint.maxDistanceOnly = false;
}
public void removeLength() {
this.ropeLength = float.MaxValue;

DistanceJoint2D joint = gameObject.GetComponent<DistanceJoint2D>();
if (joint)
joint.maxDistanceOnly = true;
}
// !Utils
}
96 changes: 96 additions & 0 deletions NinjaRopePlayerController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using UnityEngine;
using System.Collections;

public class NinjaRopePlayerController: MonoBehaviour {
private float speed_ = 120f, ropeSpeed_ = 5f;
private float minRopeLength_ = 0.1f, maxRopeLength_ = 12f;
private float ropeAngle_ = 20f;

public GameObject hookPrefab;
private GameObject hook_;
private bool isHooking_ = false;

public GameObject ropePrefab;
private GameObject rope_;

void Update() {
if (!this.isHooking_) {
// No hook launched / hooked, so can launch it
if (Input.GetKeyDown(KeyCode.A))
this.launchHook_(Quaternion.Euler(0f, 0f, this.ropeAngle_) * Vector3.up);
if (Input.GetKeyDown(KeyCode.D))
this.launchHook_(Quaternion.Euler(0f, 0f, -this.ropeAngle_) * Vector3.up);
}
else {
// Hook is either launched or hooked
NinjaRope rope = this.rope_.GetComponent<NinjaRope>();

// No input, remove the hook
if (Input.GetKeyUp(KeyCode.A) ||
Input.GetKeyUp(KeyCode.D)) {
this.removeHook_();
return ;
}

if (!this.hook_.GetComponent<NinjaHook>().isHooked()) {
// The hook is launched, but not yet hooked
if (this.maxRopeLength_ < Vector3.Distance(this.hook_.transform.position, gameObject.transform.position)) // Remove hook if it took too long to find a spot to hook on
this.removeHook_();
}
else {
// The hook is hooked on a surface
Vector3 upVector = (rope.lastAnchor.anchor - gameObject.transform.position).normalized,
rightVector = (Quaternion.Euler(0f, 0f, -90f) * upVector).normalized;
Vector3 posDelta = Vector3.zero;

// Move the player
if (Input.GetKey(KeyCode.A))
posDelta -= rightVector * this.speed_ * Time.fixedDeltaTime;
if (Input.GetKey(KeyCode.D))
posDelta += rightVector * this.speed_ * Time.fixedDeltaTime;

if (0.0001f < posDelta.magnitude)
gameObject.GetComponent<Rigidbody2D>().AddForce(posDelta);

// Move up or down the rope
if (Input.GetKey(KeyCode.W))
rope.ropeLength -= this.ropeSpeed_ * Time.fixedDeltaTime;
if (Input.GetKey(KeyCode.S))
rope.ropeLength += this.ropeSpeed_ * Time.fixedDeltaTime;

if (this.minRopeLength_ > rope.ropeLength)
rope.ropeLength = this.minRopeLength_;
if (this.maxRopeLength_ < rope.ropeLength)
rope.ropeLength = this.maxRopeLength_;
}
}
}

private void launchHook_(Vector3 spd) {
// Instantiate hook, and make the player the hook parent to ensure the hook position is affected by the player (TMP: DOES NOT WORK)
this.hook_ = Object.Instantiate(this.hookPrefab, gameObject.transform.position, Quaternion.identity) as GameObject;
this.hook_.GetComponent<NinjaHook>().direction = spd;

this.rope_ = Object.Instantiate<GameObject>(this.ropePrefab);
this.rope_.GetComponent<NinjaRope>().baseEntity = this.hook_;
this.rope_.GetComponent<NinjaRope>().endEntity = gameObject;
this.rope_.GetComponent<NinjaRope>().removeLength(); // Remove the max length of the rope

this.hook_.GetComponent<NinjaHook>().onHooked += this.onHooked;

this.isHooking_ = true;
}

private void removeHook_() {
// Destroy both the hook and the rope (duh!)
Destroy(this.hook_);
Destroy(this.rope_);

this.isHooking_ = false;
}

public void onHooked() {
// Reset the max length of the rope
this.rope_.GetComponent<NinjaRope>().setLength(this.rope_.GetComponent<NinjaRope>().getRopeLength() + gameObject.GetComponent<Rigidbody2D>().velocity.magnitude * Time.deltaTime);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using UnityEngine;
using System.Collections;

public class ExamplePlayerController: MonoBehaviour {
public class PermanentRopePlayerController: MonoBehaviour {
private float speed_ = 104f, ropeSpeed_ = 5f;
private float minRopeLength_ = 1f, maxRopeLength_ = 8f;

Expand Down

0 comments on commit 1c9b322

Please sign in to comment.