Created
January 28, 2019 09:30
-
-
Save sherjilozair/8a4901687c8cef0967452213c904b52f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class PlayerController : MonoBehaviour | |
{ | |
public int m_playerID; | |
public float m_shootCooldown; | |
// Audio data | |
public AudioData m_dashSound; | |
public AudioData m_deflectSound; | |
public AudioData m_jumpSound; | |
public AudioData m_landSound; | |
public AudioData m_shootSound; | |
public Animator m_animator; | |
bool was_jump_pressed = false; | |
bool was_dash_pressed = false; | |
bool was_shoot_pressed = false; | |
float jump_speed = 4.3f; | |
float wall_jump_speed = 3f; | |
int jump_buffer = 0; | |
public int jump_buffer_size = 4; | |
int coyote_buffer = 0; | |
public int coyote_buffer_size = 6; | |
public int max_dashes = 1; | |
int dashes_available = 0; | |
public float maxspeed = 1; | |
public float ground_accel = 0.6f; | |
public float ground_deccel = 0.15f; | |
public float air_accel = 0.2f; | |
Vector2 speed; | |
public Vector2Int position; | |
Vector2 remainder; | |
SpriteRenderer spriteRenderer; | |
public Level level; | |
public GameObject ballPrefab; | |
public float ballSpawnSpeed; | |
int width = 12; | |
int height = 16; | |
int dash_effect_time = 0; | |
int dash_effect_time_max = 12; | |
float dash_full = 11f; | |
float dash_target_value = 2f; | |
float dash_accel_value = 2f; | |
Vector2 dash_target; | |
float epsilon = 0.01f; | |
float lastShootTime = 0f; | |
void Start() | |
{ | |
spriteRenderer = gameObject.GetComponent<SpriteRenderer>(); | |
Application.targetFrameRate = 60; | |
} | |
float Sign(float x) | |
{ | |
if (Mathf.Abs(x) < epsilon) return 0f; | |
if (x > 0) return 1f; | |
return -1f; | |
} | |
bool Intersects(RectInt a, RectInt b) | |
{ | |
return (b.xMin < a.xMax && | |
a.xMin < b.xMax && | |
b.yMin < a.yMax && | |
a.yMin < b.yMax); | |
} | |
bool IsSolid(int dx, int dy) | |
{ | |
List<RectInt> solids = level.GetAllSolids(); | |
RectInt player = new RectInt(position.x-width/2+dx, position.y-height/2+dy, width, height); | |
foreach(RectInt solid in solids) | |
{ | |
if(Intersects(player, solid)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
bool OnPlatform(int dy) | |
{ | |
List<RectInt> solids = level.GetAllPlatforms(); | |
RectInt player = new RectInt(position.x - width / 2, position.y - height / 2 + dy, width, height); | |
foreach (RectInt solid in solids) | |
{ | |
if (Intersects(player, solid)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
float Approach(float value, float target, float amount) | |
{ | |
if(value > target) | |
{ | |
return Mathf.Max(value - amount, target); | |
} | |
else if(value < target) | |
{ | |
return Mathf.Min(value + amount, target); | |
} | |
return target; | |
} | |
void Update() | |
{ | |
if (Level.Get().m_paused) | |
return; | |
bool left_pressed = InputSystem.Get().m_playerControllerStates[m_playerID].m_leftStick.x < 0f; | |
bool right_pressed = InputSystem.Get().m_playerControllerStates[m_playerID].m_leftStick.x > 0f; | |
int x_input = 0; | |
if (left_pressed) { | |
x_input--; | |
} | |
if (right_pressed) | |
{ | |
x_input++; | |
} | |
bool up_pressed = InputSystem.Get().m_playerControllerStates[m_playerID].m_leftStick.y > 0f; | |
bool down_pressed = InputSystem.Get().m_playerControllerStates[m_playerID].m_leftStick.y < 0f; | |
int y_input = 0; | |
if (up_pressed) | |
{ | |
y_input++; | |
} | |
if (down_pressed) | |
{ | |
y_input--; | |
} | |
Vector2 input_direction = new Vector2(x_input, y_input); | |
input_direction.Normalize(); | |
bool jump_pressed = InputSystem.Get().m_playerControllerStates[m_playerID].m_aButtonDown; | |
bool jump = jump_pressed && !was_jump_pressed; | |
was_jump_pressed = jump_pressed; | |
if (jump) | |
{ | |
jump_buffer = jump_buffer_size; | |
} | |
else if(jump_buffer > 0) | |
{ | |
jump_buffer--; | |
} | |
bool dash_pressed = InputSystem.Get().m_playerControllerStates[m_playerID].m_xButtonDown; | |
bool dash = dash_pressed && !was_dash_pressed; | |
was_dash_pressed = dash_pressed; | |
bool on_ground = IsSolid(0, -1) || (!OnPlatform(0) && OnPlatform(-1)); | |
if (on_ground) | |
{ | |
coyote_buffer = coyote_buffer_size; | |
if(dashes_available < max_dashes) | |
{ | |
dashes_available = max_dashes; | |
} | |
} | |
else if(coyote_buffer > 0) | |
{ | |
coyote_buffer--; | |
} | |
// Dashing | |
Vector2 dash_accel; | |
dash_accel.x = dash_accel_value; | |
dash_accel.y = dash_accel_value; | |
if (dash_effect_time > 0) | |
{ | |
dash_effect_time--; | |
speed.x = Approach(speed.x, dash_target.x, dash_accel.x); | |
speed.y = Approach(speed.y, dash_target.y, dash_accel.y); | |
} | |
else | |
{ | |
// Moving | |
float accel = ground_accel; | |
if (!on_ground) | |
{ | |
accel = air_accel; | |
} | |
if (Mathf.Abs(speed.x) > maxspeed) | |
{ | |
speed.x = Approach(speed.x, Sign(speed.x) * maxspeed, ground_deccel); | |
} | |
else if (!InputSystem.Get().m_playerControllerStates[m_playerID].m_leftBumper && !InputSystem.Get().m_playerControllerStates[m_playerID].m_rightBumper) | |
{ | |
speed.x = Approach(speed.x, x_input * maxspeed, accel); | |
} | |
else | |
speed.x = 0; | |
// gravity | |
float maxfall = -3f; | |
float gravity = 0.21f; | |
if (Mathf.Abs(speed.y) <= 0.15f) | |
{ | |
gravity *= 0.5f; | |
} | |
// wall slide | |
if (x_input != 0 && IsSolid(x_input, 0)) | |
{ | |
maxfall = -2f; | |
} | |
if (!on_ground) | |
{ | |
speed.y = Approach(speed.y, maxfall, gravity); | |
} | |
// jump | |
if (jump_buffer > 0) | |
{ | |
if (coyote_buffer > 0) | |
{ | |
jump_buffer = 0; | |
coyote_buffer = 0; | |
speed.y = jump_speed; | |
AudioEngine.Play(m_jumpSound); | |
m_animator.SetTrigger("jump"); | |
} | |
else | |
{ | |
int wall_dir = 0; | |
if (IsSolid(-3, 0)) | |
{ | |
wall_dir = -1; | |
} | |
if (IsSolid(3, 0)) | |
{ | |
wall_dir = 1; | |
} | |
if (wall_dir != 0) | |
{ | |
jump_buffer = 0; | |
speed.y = jump_speed; | |
speed.x = -wall_dir * (wall_jump_speed); | |
} | |
} | |
} | |
// dash | |
if (dashes_available > 0 && dash) | |
{ | |
dashes_available--; | |
dash_effect_time = dash_effect_time_max; | |
Vector2 dash_direction = input_direction; | |
if (dash_direction.magnitude < epsilon) | |
{ | |
dash_direction.x = spriteRenderer.flipX ? -1.0f : 1.0f; | |
} | |
speed = dash_direction * dash_full; | |
dash_target.x = Sign(speed.x); | |
dash_target.y = Sign(speed.y); | |
dash_target.Normalize(); | |
dash_target *= dash_target_value; | |
AudioEngine.Play(m_dashSound); | |
m_animator.SetTrigger("jump"); | |
} | |
} | |
// shoot | |
bool shoot_pressed = InputSystem.Get().m_playerControllerStates[m_playerID].m_bButtonDown; | |
bool shoot = shoot_pressed && !was_shoot_pressed; | |
was_shoot_pressed = shoot_pressed; | |
if (shoot && Time.time > lastShootTime + m_shootCooldown) | |
{ | |
lastShootTime = Time.time; | |
Vector2 shoot_direction = InputSystem.Get().m_playerControllerStates[m_playerID].m_leftStick; | |
if(shoot_direction.magnitude < epsilon) | |
{ | |
shoot_direction.x = spriteRenderer.flipX ? -1.0f : 1.0f; | |
} | |
GameObject spawned_ball = Instantiate(ballPrefab); | |
spawned_ball.transform.position = transform.position; | |
Ball ball = spawned_ball.GetComponent<Ball>(); | |
ball.m_owner = m_playerID; | |
Rigidbody2D rb2d = spawned_ball.GetComponent<Rigidbody2D>(); | |
rb2d.velocity = shoot_direction * ballSpawnSpeed + 10f * speed; | |
AudioEngine.Play(m_shootSound); | |
m_animator.SetTrigger("shoot"); | |
} | |
// update | |
Move(speed.x, speed.y); | |
// facing | |
if (Mathf.Abs(speed.x) > epsilon) | |
{ | |
spriteRenderer.flipX = speed.x < 0; | |
} | |
// animation | |
} | |
void Move(float x, float y) | |
{ | |
int amount; | |
remainder.x += x; | |
amount = Mathf.FloorToInt(remainder.x); | |
remainder.x -= amount; | |
MoveX(amount); | |
remainder.y += y; | |
amount = Mathf.FloorToInt(remainder.y); | |
remainder.y -= amount; | |
MoveY(amount); | |
if (m_playerID == 0) | |
position.x = Mathf.Min(position.x, 0); | |
else | |
position.x = Mathf.Max(position.x, 0); | |
transform.position = new Vector3(position.x, position.y, 0); | |
} | |
void MoveX(int amount) | |
{ | |
int step = Mathf.RoundToInt(Sign(amount)); | |
while (amount != 0) | |
{ | |
if (IsSolid(step, 0)) | |
{ | |
speed.x = 0; | |
remainder.x = 0; | |
break; | |
} | |
else | |
{ | |
position.x += step; | |
amount -= step; | |
} | |
} | |
} | |
void MoveY(int amount) | |
{ | |
int step = Mathf.RoundToInt(Sign(amount)); | |
while (amount != 0) | |
{ | |
if (IsSolid(0, step) || (step < 0 && !OnPlatform(0) && OnPlatform(step))) | |
{ | |
speed.y = 0; | |
remainder.y = 0; | |
AudioEngine.Play(m_landSound); | |
break; | |
} | |
else | |
{ | |
position.y += step; | |
amount -= step; | |
} | |
} | |
} | |
//-------------------------------------------------------------------------------------------------- | |
void OnTriggerEnter2D (Collider2D col) | |
{ | |
// Only run this code when colliding with balls | |
if (col.gameObject.layer != LayerMask.NameToLayer("Ball")) | |
return; | |
// See if we can collide with the ball | |
Ball ball = col.GetComponent<Ball>(); | |
// Seems like this will cause a 'feature' where the ball will eventually go through a player if it bounces back and | |
// forth between players a lot | |
if (m_playerID == ball.m_owner && !ball.m_canCollideWithPlayer) | |
return; | |
// Reflect the ball | |
Rigidbody2D ballRigid = col.GetComponent<Rigidbody2D>(); | |
Vector2 normal = (col.transform.position - transform.position).normalized; | |
ballRigid.velocity = Mathf.Max(ballRigid.velocity.magnitude, ballSpawnSpeed) * normal; | |
AudioEngine.Play(m_deflectSound); | |
ball.m_canCollideWithPlayer = false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment