Files
Gnome-s-Bounty/Assets/Scripts/Character.cs
T
2023-07-13 07:49:49 +03:00

267 lines
7.7 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Tilemaps;
public abstract class Character : MonoBehaviour
{
[SerializeField]
protected Animator _animator;
[SerializeField]
private float MovementSpeed = 1.5f;
[SerializeField]
protected GameObject _bonesSide;
[SerializeField]
protected GameObject _bonesBack;
[SerializeField]
protected GameObject _spawnPoint;
[SerializeField]
protected Tilemap _tileMap;
[SerializeField]
private LayerMask _mapLayer;
private Rigidbody2D _body;
private CapsuleCollider2D _capsuleCollider;
protected bool _isOnBridge;
protected bool _isOnLadder = false;
protected bool _isFalling;
protected bool _facingRight = true;
protected bool isAllowVertical = true;
protected bool isAllowRight = true;
protected bool isAllowLeft = true;
private Vector2 _cellSize;
private void Start()
{
_body = GetComponent<Rigidbody2D>();
_capsuleCollider = GetComponent<CapsuleCollider2D>();
_cellSize = new Vector2(_tileMap.cellSize.x, _tileMap.cellSize.y);
}
protected void Spawn()
{
transform.position = _spawnPoint.transform.position;
}
protected void MoveTo(float inputHorizontal, float inputVertical)
{
var downBlock = GetMapElement(Vector2.down);
if (downBlock == MapElementType.Water)
{
Death();
}
_isOnBridge = downBlock == MapElementType.Bridge && !_isFalling;
GetMapElement(Vector2.up);
if (downBlock == MapElementType.Wall || _isOnLadder || _isOnBridge || downBlock == MapElementType.BreakableWall)
{
var leftCheck = GetMapElement(Vector2.left);
var rightCheck = GetMapElement(Vector2.right);
//print($"LeftCheck:{leftCheck} right:{rightCheck}");
isAllowLeft = !(leftCheck == MapElementType.Wall || leftCheck == MapElementType.BreakableWall);
isAllowRight = !(rightCheck == MapElementType.Wall || rightCheck == MapElementType.BreakableWall);
isAllowVertical = false;
_isFalling = false;
float h_movement = inputHorizontal;
if (h_movement > 0 && !_facingRight || h_movement < 0 && _facingRight)
{
FlipCharacter();
}
SetWalkingAnimation(h_movement != 0);
;
_isOnLadder = GetMapElement(Vector2.zero) == MapElementType.Ladder || downBlock == MapElementType.Ladder;
if (_isOnLadder)
{
float v_movement = inputVertical;
isAllowVertical = true;
SetClimbingAnimation(v_movement != 0);
_body.velocity = new Vector2(h_movement * MovementSpeed, v_movement * MovementSpeed);
}
else
{
_body.velocity = new Vector2(h_movement * MovementSpeed, _body.velocity.y);
}
}
else
{
_isFalling = true;
}
if (_isOnLadder || _isOnBridge)
{
_body.gravityScale = 0;
}
else
{
_body.gravityScale = 1;
}
if (_isFalling)
{
_body.velocity = new Vector2(0, _body.velocity.y);
SetWalkingAnimation(false);
if (downBlock == MapElementType.Ladder)
{
_body.velocity = Vector2.zero;
_isOnLadder = true;
}
}
}
private void Death()
{
OnDeath();
}
private MapElementType GetMapElement(Vector3 direction)
{
var bounds = _capsuleCollider.bounds.min;
//var cell = _tileMap.WorldToCell(bounds + direction);
//Vector2 cell2d = new Vector2(cell.x + 0.5f, cell.y + 0.3f);
Vector2 cellSize = _cellSize;
var playerBounds = _capsuleCollider.bounds.center;
//DrawBounds(playerBounds, cellSize, Color.cyan);
playerBounds = playerBounds + direction;
var raycastHit = BoxCast(playerBounds, cellSize, 0f, Vector3.forward, .01f, _mapLayer);
MapElementType returnValue;
Color color = Color.red;
if (raycastHit)
{
var mapElement = raycastHit.transform.GetComponent<MapElement>();
if (!mapElement.IsEnabled)
{
color = Color.white;
returnValue = MapElementType.Empty;
}
else
{
returnValue = mapElement.ElementSO.ElementType;
switch (returnValue)
{
case MapElementType.Wall:
color = Color.green;
break;
case MapElementType.Ladder:
color = Color.yellow;
break;
case MapElementType.BreakableWall:
color = Color.magenta;
break;
}
}
}
else
{
returnValue = MapElementType.Empty;
}
// DrawBounds(playerBounds, cellSize, color);
return returnValue;
}
//private static void DrawBounds(Vector2 cell2d, Vector2 cellSize, Color color)
//{
// Debug.DrawLine(cell2d, cell2d + new Vector2(cellSize.x, 0), color);
// Debug.DrawLine(cell2d + new Vector2(cellSize.x, 0), cell2d + new Vector2(cellSize.x, cellSize.y), color);
// Debug.DrawLine(cell2d, cell2d + new Vector2(0, cellSize.y), color);
// Debug.DrawLine(cell2d + new Vector2(0, cellSize.y), cell2d + new Vector2(cellSize.x, cellSize.y), color);
//}
protected abstract void OnDeath();
protected abstract void SetWalkingAnimation(bool isWalking);
protected abstract void SetClimbingAnimation(bool isClimbing);
private void FlipCharacter()
{
Vector3 currentScale = gameObject.transform.localScale;
currentScale.x *= -1;
gameObject.transform.localScale = currentScale;
_facingRight = !_facingRight;
}
static public RaycastHit2D BoxCast(Vector2 origen, Vector2 size, float angle, Vector2 direction, float distance, int mask)
{
RaycastHit2D hit = Physics2D.BoxCast(origen, size, angle, direction, distance, mask);
//Setting up the points to draw the cast
Vector2 p1, p2, p3, p4, p5, p6, p7, p8;
float w = size.x * 0.5f;
float h = size.y * 0.5f;
p1 = new Vector2(-w, h);
p2 = new Vector2(w, h);
p3 = new Vector2(w, -h);
p4 = new Vector2(-w, -h);
Quaternion q = Quaternion.AngleAxis(angle, new Vector3(0, 0, 1));
p1 = q * p1;
p2 = q * p2;
p3 = q * p3;
p4 = q * p4;
p1 += origen;
p2 += origen;
p3 += origen;
p4 += origen;
Vector2 realDistance = direction.normalized * distance;
p5 = p1 + realDistance;
p6 = p2 + realDistance;
p7 = p3 + realDistance;
p8 = p4 + realDistance;
//Drawing the cast
Color castColor = hit ? Color.red : Color.green;
Debug.DrawLine(p1, p2, castColor);
Debug.DrawLine(p2, p3, castColor);
Debug.DrawLine(p3, p4, castColor);
Debug.DrawLine(p4, p1, castColor);
Debug.DrawLine(p5, p6, castColor);
Debug.DrawLine(p6, p7, castColor);
Debug.DrawLine(p7, p8, castColor);
Debug.DrawLine(p8, p5, castColor);
Debug.DrawLine(p1, p5, Color.grey);
Debug.DrawLine(p2, p6, Color.grey);
Debug.DrawLine(p3, p7, Color.grey);
Debug.DrawLine(p4, p8, Color.grey);
if (hit)
{
Debug.DrawLine(hit.point, hit.point + hit.normal.normalized * 0.2f, Color.yellow);
}
return hit;
}
}