Open-sourced some code
@@ -0,0 +1,46 @@
|
|||||||
|
# Last Ember - Open Source
|
||||||
|
|
||||||
|
In this repository are the parts of the game Last Ember that I created myself. This includes the C# scripts, and a few placeholder sprites. Everything else is too tied up to release as open source.
|
||||||
|
|
||||||
|
This game was written in C# for Unity 2018.3.0f2.
|
||||||
|
|
||||||
|
I've included a build of the game that shows off almost everything created so far.
|
||||||
|
|
||||||
|
You can run by double-tapping a direction, jump, wall jump, look up and crouch. There were going to be other moves, but we didn't get around to implementing them.
|
||||||
|
|
||||||
|
## Libraries and Tools Used
|
||||||
|
|
||||||
|
* Carbon Input - https://assetstore.unity.com/packages/tools/input-management/unified-input-manager-56980
|
||||||
|
* SpriterDotNet - https://github.com/loodakrawa/SpriterDotNet
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
* Kayne Ruse - Programming, Management
|
||||||
|
* Evan Hartshorn - Art, Game Design
|
||||||
|
* Shy Monster (Luis Paez, Hayden Blades) - Audio, Music
|
||||||
|
|
||||||
|
Special thanks to Feldi - sorry we didn't get to work with you!
|
||||||
|
|
||||||
|
## $5 Patrons
|
||||||
|
|
||||||
|
* Seth Robinson
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
If you have any questions, you're welcome to ask here:
|
||||||
|
|
||||||
|
kayneruse@gmail.com
|
||||||
|
|
||||||
|
https://discord.gg/FQmz8TN
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
Copyright (c) 2019 KR Game Studios
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class AudioController : MonoBehaviour {
|
||||||
|
//public structures
|
||||||
|
public enum Mode {
|
||||||
|
NONE,
|
||||||
|
ONCE,
|
||||||
|
LOOP,
|
||||||
|
JUMP
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct AudioContainer {
|
||||||
|
public AudioSource source;
|
||||||
|
public Mode mode;
|
||||||
|
public float jumpStart;
|
||||||
|
public float jumpEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
//internals
|
||||||
|
Dictionary<string, AudioContainer> audioDictionary = new Dictionary<string, AudioContainer>();
|
||||||
|
static bool initialized = false;
|
||||||
|
|
||||||
|
//monobehaviour methods
|
||||||
|
void Start() {
|
||||||
|
if (initialized) {
|
||||||
|
Destroy(gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
DontDestroyOnLoad(gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
foreach(KeyValuePair<string, AudioContainer> iter in audioDictionary) {
|
||||||
|
//handle the jump points
|
||||||
|
if (iter.Value.mode == Mode.JUMP && iter.Value.jumpStart >= 0f && iter.Value.jumpEnd > 0f) {
|
||||||
|
if (iter.Value.source.time >= iter.Value.jumpEnd) {
|
||||||
|
iter.Value.source.time = iter.Value.jumpStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy() {
|
||||||
|
foreach(KeyValuePair<string, AudioContainer> iter in audioDictionary) {
|
||||||
|
Resources.UnloadAsset(iter.Value.source.clip);
|
||||||
|
Destroy(iter.Value.source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//public access members
|
||||||
|
public void Load(string name, string filename) {
|
||||||
|
AudioContainer container = new AudioContainer();
|
||||||
|
|
||||||
|
container.source = gameObject.AddComponent(typeof(AudioSource)) as AudioSource;
|
||||||
|
container.source.clip = Resources.Load<AudioClip>(filename) as AudioClip;
|
||||||
|
container.source.volume = 0f;
|
||||||
|
container.mode = Mode.NONE;
|
||||||
|
|
||||||
|
audioDictionary[name] = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Unload(string name) {
|
||||||
|
if (!audioDictionary.ContainsKey(name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioContainer container = audioDictionary[name];
|
||||||
|
|
||||||
|
Resources.UnloadAsset(container.source.clip);
|
||||||
|
Destroy(container.source);
|
||||||
|
|
||||||
|
audioDictionary.Remove(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//controls
|
||||||
|
public void Play(string name, Mode mode = Mode.ONCE, float jumpStart = -1f, float jumpEnd = -1f) {
|
||||||
|
AudioContainer container = audioDictionary[name];
|
||||||
|
|
||||||
|
container.source.Play();
|
||||||
|
container.source.loop = mode == Mode.LOOP;
|
||||||
|
container.source.volume = 1f;
|
||||||
|
container.mode = mode;
|
||||||
|
container.jumpStart = jumpStart;
|
||||||
|
container.jumpEnd = jumpEnd;
|
||||||
|
audioDictionary[name] = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Pause(string name) {
|
||||||
|
AudioContainer container = audioDictionary[name];
|
||||||
|
|
||||||
|
container.source.Pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unpause(string name, Mode mode = Mode.ONCE, float jumpStart = -1f, float jumpEnd = -1f) {
|
||||||
|
AudioContainer container = audioDictionary[name];
|
||||||
|
|
||||||
|
if (container.source.isPlaying) {
|
||||||
|
container.source.UnPause();
|
||||||
|
} else {
|
||||||
|
Play(name, mode, jumpStart, jumpEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop(string name) {
|
||||||
|
AudioContainer container = audioDictionary[name];
|
||||||
|
|
||||||
|
container.source.Stop();
|
||||||
|
container.mode = Mode.NONE;
|
||||||
|
|
||||||
|
audioDictionary[name] = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopAll() {
|
||||||
|
List<string> names = new List<string>();
|
||||||
|
foreach(KeyValuePair<string, AudioContainer> iter in audioDictionary) {
|
||||||
|
names.Add(iter.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(string name in names) {
|
||||||
|
Stop(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//fade controls
|
||||||
|
public void FadeIn(string name, float seconds) {
|
||||||
|
StartCoroutine(FadeInCallback(audioDictionary[name].source, 1f/seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator FadeInCallback(AudioSource source, float amountPerSecond) {
|
||||||
|
source.volume = 0;
|
||||||
|
while (source.volume < 1f) {
|
||||||
|
yield return new WaitForSeconds(0.1f);
|
||||||
|
source.volume += amountPerSecond / 10f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FadeOut(string name, float seconds) {
|
||||||
|
StartCoroutine(FadeOutCallback(audioDictionary[name].source, 1f/seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator FadeOutCallback(AudioSource source, float amountPerSecond) {
|
||||||
|
while (source.volume > 0f) {
|
||||||
|
yield return new WaitForSeconds(0.1f);
|
||||||
|
source.volume -= amountPerSecond / 10f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//hybrid controls
|
||||||
|
public void PlayFadeIn(string name, float seconds, Mode mode = Mode.ONCE, float jumpStart = -1f, float jumpEnd = -1f) {
|
||||||
|
FadeIn(name, seconds);
|
||||||
|
Play(name, mode, jumpStart, jumpEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PauseFadeOut(string name, float seconds) {
|
||||||
|
FadeOut(name, seconds);
|
||||||
|
StartCoroutine(PauseFadeOutCallback(name, seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PauseFadeOutAll(float seconds, List<string> exclude = null) {
|
||||||
|
foreach(KeyValuePair<string, AudioContainer> iter in audioDictionary) {
|
||||||
|
if (exclude != null && exclude.Contains(iter.Key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FadeOut(iter.Key, seconds);
|
||||||
|
StartCoroutine(PauseFadeOutCallback(iter.Key, seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator PauseFadeOutCallback(string name, float seconds) {
|
||||||
|
yield return new WaitForSeconds(seconds);
|
||||||
|
Pause(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnpauseFadeIn(string name, float seconds, Mode mode = Mode.ONCE, float jumpStart = -1f, float jumpEnd = -1f) {
|
||||||
|
Unpause(name, mode, jumpStart, jumpEnd);
|
||||||
|
FadeIn(name, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopFadeOut(string name, float seconds) {
|
||||||
|
FadeOut(name, seconds);
|
||||||
|
StartCoroutine(StopFadeOutCallback(name, seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopFadeOutAll(float seconds, List<string> exclude = null) {
|
||||||
|
foreach(KeyValuePair<string, AudioContainer> iter in audioDictionary) {
|
||||||
|
if (exclude != null && exclude.Contains(iter.Key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FadeOut(iter.Key, seconds);
|
||||||
|
StartCoroutine(StopFadeOutCallback(iter.Key, seconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator StopFadeOutCallback(string name, float seconds) {
|
||||||
|
yield return new WaitForSeconds(seconds);
|
||||||
|
Stop(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//status
|
||||||
|
public bool GetPlaying(string name) {
|
||||||
|
return audioDictionary[name].source.isPlaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mode GetMode(string name) {
|
||||||
|
return audioDictionary[name].mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class CameraController : MonoBehaviour {
|
||||||
|
//public access members
|
||||||
|
public GameObject targetObject;
|
||||||
|
public Vector3 offset;
|
||||||
|
public float lerpSpeed = 2f;
|
||||||
|
|
||||||
|
Vector2 peek = new Vector2(0, 0);
|
||||||
|
|
||||||
|
//private members
|
||||||
|
Vector3 virtualLocation;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
virtualLocation = transform.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
//only continue if the target has been set
|
||||||
|
if (targetObject == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cache the position we want to move to
|
||||||
|
Vector3 targetPosition = targetObject.transform.position + offset + new Vector3(peek.x, peek.y, 0f);
|
||||||
|
|
||||||
|
//If the distance is small, short circuit the lerp, so we don't have sudden pops in camera motion.
|
||||||
|
if ((targetPosition - virtualLocation).sqrMagnitude > 0.01f) {
|
||||||
|
//Interpolate to the target location.
|
||||||
|
virtualLocation = Vector3.Lerp(virtualLocation, targetPosition, lerpSpeed * Time.deltaTime);
|
||||||
|
|
||||||
|
//Snap to pixel coordinates
|
||||||
|
Vector3 snapped = virtualLocation;
|
||||||
|
|
||||||
|
snapped.x = Mathf.Round(snapped.x * 100) / 100;
|
||||||
|
snapped.y = Mathf.Round(snapped.y * 100) / 100;
|
||||||
|
|
||||||
|
snapped.z = transform.position.z; //BUGFIX
|
||||||
|
|
||||||
|
transform.position = snapped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 GetPeek() {
|
||||||
|
return peek;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPeek(Vector2 newPeek, float delay = 0.5f) {
|
||||||
|
peek = new Vector2(0f, 0f);
|
||||||
|
StartCoroutine(SetPeekAfter(delay, newPeek)); //NOTE: a delay to peeking, for smooth gameplay
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator SetPeekAfter(float delay, Vector2 addition) {
|
||||||
|
yield return new WaitForSeconds(delay);
|
||||||
|
peek = addition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetPeek() {
|
||||||
|
peek = new Vector2(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Creatures {
|
||||||
|
public class CockatooController : MonoBehaviour, ICreature {
|
||||||
|
//public access members
|
||||||
|
public GameObject projectilePrefab;
|
||||||
|
|
||||||
|
//components
|
||||||
|
Rigidbody2D rigidBody;
|
||||||
|
|
||||||
|
//gameplay
|
||||||
|
const float moveForce = 10f;
|
||||||
|
const float maxSpeed = 2.5f;
|
||||||
|
|
||||||
|
int _horizontalMoveDirection;
|
||||||
|
public int HorizontalMoveDirection {
|
||||||
|
get {
|
||||||
|
return _horizontalMoveDirection;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_horizontalMoveDirection = value;
|
||||||
|
if (_horizontalMoveDirection >= 0) {
|
||||||
|
transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), Mathf.Abs(transform.localScale.y));
|
||||||
|
} else {
|
||||||
|
transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), Mathf.Abs(transform.localScale.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int VerticalMoveDirection { get; set; }
|
||||||
|
public int DamageValue { get; set; }
|
||||||
|
|
||||||
|
int _healthValue;
|
||||||
|
public int HealthValue {
|
||||||
|
get {
|
||||||
|
return _healthValue;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_healthValue = value;
|
||||||
|
if (_healthValue <= 0) {
|
||||||
|
Destroy(gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//internals
|
||||||
|
float initialPositionY;
|
||||||
|
|
||||||
|
bool detectedPlayer;
|
||||||
|
float detectionDistance = 4f;
|
||||||
|
float lastDetection = float.NegativeInfinity;
|
||||||
|
float detectionDelay = 2f;
|
||||||
|
|
||||||
|
void Awake() {
|
||||||
|
rigidBody = GetComponent<Rigidbody2D>();
|
||||||
|
|
||||||
|
HorizontalMoveDirection = -1;
|
||||||
|
VerticalMoveDirection = 0;
|
||||||
|
|
||||||
|
HealthValue = 1;
|
||||||
|
DamageValue = 1;
|
||||||
|
|
||||||
|
initialPositionY = rigidBody.position.y;
|
||||||
|
|
||||||
|
rigidBody.position = new Vector2(rigidBody.position.x, rigidBody.position.y + 0.5f);
|
||||||
|
|
||||||
|
StartCoroutine(BigFlap(5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedUpdate() {
|
||||||
|
HandleDetection();
|
||||||
|
HandleVerticalMoveDirection();
|
||||||
|
HandleMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCollisionEnter2D(Collision2D collision) {
|
||||||
|
Vector2 normal = collision.GetContact(0).normal;
|
||||||
|
|
||||||
|
if (collision.gameObject.tag == "Monster") {
|
||||||
|
//turn around
|
||||||
|
if (SameSign(collision.gameObject.GetComponent<ICreature>().HorizontalMoveDirection, HorizontalMoveDirection) || collision.gameObject.GetComponent<ICreature>().HorizontalMoveDirection == 0) {
|
||||||
|
rigidBody.velocity = new Vector2(0f, rigidBody.velocity.y);
|
||||||
|
HorizontalMoveDirection = -HorizontalMoveDirection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//collision with the player (when the player is not bouncing)
|
||||||
|
if (collision.gameObject.tag == "Player" && normal != Vector2.down) {
|
||||||
|
//turn around
|
||||||
|
rigidBody.velocity = new Vector2(0f, rigidBody.velocity.y);
|
||||||
|
HorizontalMoveDirection = -HorizontalMoveDirection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleDetection() {
|
||||||
|
bool detectedPlayer = Physics2D.Linecast(transform.position, transform.position + new Vector3((transform.localScale.x > 0 ? 1 : -1) * detectionDistance, -detectionDistance, 0), 1 << LayerMask.NameToLayer("Player"));
|
||||||
|
|
||||||
|
if (detectedPlayer && Time.time - lastDetection > detectionDelay) {
|
||||||
|
lastDetection = Time.time;
|
||||||
|
|
||||||
|
GameObject go = Instantiate(projectilePrefab, transform.position, Quaternion.identity);
|
||||||
|
|
||||||
|
go.GetComponent<CockatooProjectileController>().HorizontalMoveDirection = HorizontalMoveDirection;
|
||||||
|
go.GetComponent<CockatooProjectileController>().VerticalMoveDirection = -1;
|
||||||
|
go.GetComponent<CockatooProjectileController>().DamageValue = DamageValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleVerticalMoveDirection() {
|
||||||
|
if (rigidBody.position.y >= initialPositionY) {
|
||||||
|
VerticalMoveDirection = -1;
|
||||||
|
} else if (rigidBody.position.y < initialPositionY) {
|
||||||
|
VerticalMoveDirection = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleMovement() {
|
||||||
|
//turn around if stopped
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < 0.1f) {
|
||||||
|
StartCoroutine(SetDirectionIfNotMovingAfter(-HorizontalMoveDirection, 0.1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
//move the entity in this direction, if not at max speed
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < maxSpeed) {
|
||||||
|
rigidBody.AddForce(Vector2.right * HorizontalMoveDirection * moveForce);
|
||||||
|
}
|
||||||
|
|
||||||
|
//move the entity in the correct direction vertically
|
||||||
|
if (rigidBody.velocity.y * VerticalMoveDirection < maxSpeed) {
|
||||||
|
rigidBody.AddForce(Vector2.up * VerticalMoveDirection * moveForce);
|
||||||
|
}
|
||||||
|
|
||||||
|
//slow the entity down when it's travelling too fast
|
||||||
|
if (Mathf.Abs (rigidBody.velocity.x) > maxSpeed) {
|
||||||
|
rigidBody.velocity = new Vector2 (Mathf.Sign (rigidBody.velocity.x) * maxSpeed, rigidBody.velocity.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mathf.Abs (rigidBody.velocity.y) > maxSpeed) {
|
||||||
|
rigidBody.velocity = new Vector2 (rigidBody.velocity.x, Mathf.Sign (rigidBody.velocity.y) * maxSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//utilities
|
||||||
|
IEnumerator SetDirectionIfNotMovingAfter(int direction, float delay) {
|
||||||
|
yield return new WaitForSeconds(delay);
|
||||||
|
//turn around if stopped
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < 0.1f) {
|
||||||
|
HorizontalMoveDirection = direction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//BUGFIX
|
||||||
|
IEnumerator BigFlap(float delay) {
|
||||||
|
while (true) {
|
||||||
|
yield return new WaitForSeconds(delay);
|
||||||
|
rigidBody.AddForce(Vector2.up * VerticalMoveDirection * moveForce * 5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDrawGizmos() {
|
||||||
|
Gizmos.color = Color.red;
|
||||||
|
Gizmos.DrawLine(transform.position, transform.position + new Vector3((transform.localScale.x > 0 ? 1 : -1) * detectionDistance, -detectionDistance, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SameSign(float num1, float num2) {
|
||||||
|
if (num1 > 0 && num2 > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (num1 < 0 && num2 < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//if either is zero, return false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Creatures {
|
||||||
|
public class CockatooProjectileController : MonoBehaviour {
|
||||||
|
//public access members
|
||||||
|
public int HorizontalMoveDirection { get; set; }
|
||||||
|
public int VerticalMoveDirection { get; set; }
|
||||||
|
public int DamageValue { get; set; }
|
||||||
|
|
||||||
|
//internal members
|
||||||
|
Rigidbody2D rigidBody;
|
||||||
|
const float moveForce = 10f;
|
||||||
|
const float maxSpeed = 5f;
|
||||||
|
|
||||||
|
DamagerController damagerController;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
rigidBody = GetComponent<Rigidbody2D>();
|
||||||
|
|
||||||
|
damagerController = GetComponent<DamagerController>();
|
||||||
|
|
||||||
|
damagerController.PushOnTriggerEnter((Collider2D collider) => {
|
||||||
|
if (collider.gameObject.tag == "Player") {
|
||||||
|
collider.gameObject.GetComponent<PlayerController>().HealthValue -= DamageValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Destroy(gameObject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedUpdate() {
|
||||||
|
HandleMovement();
|
||||||
|
|
||||||
|
//handle grapphics
|
||||||
|
transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x) * HorizontalMoveDirection, transform.localScale.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleMovement() {
|
||||||
|
//move the entity in this direction, if not at max speed
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < maxSpeed) {
|
||||||
|
rigidBody.AddForce(Vector2.right * HorizontalMoveDirection * moveForce);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.y) < maxSpeed) {
|
||||||
|
rigidBody.AddForce(Vector2.up * VerticalMoveDirection * moveForce);
|
||||||
|
}
|
||||||
|
|
||||||
|
//slow the entity down when it's travelling too fast
|
||||||
|
if (Mathf.Abs (rigidBody.velocity.x) > maxSpeed) {
|
||||||
|
rigidBody.velocity = new Vector2 (Mathf.Sign (rigidBody.velocity.x) * maxSpeed, rigidBody.velocity.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mathf.Abs (rigidBody.velocity.y) > maxSpeed) {
|
||||||
|
rigidBody.velocity = new Vector2 (rigidBody.velocity.x, Mathf.Sign (rigidBody.velocity.y) * maxSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Creatures {
|
||||||
|
public interface ICreature {
|
||||||
|
//flags used to control other monsters
|
||||||
|
int HorizontalMoveDirection { get; set; }
|
||||||
|
int VerticalMoveDirection { get; set; }
|
||||||
|
|
||||||
|
//used by the combad system
|
||||||
|
int DamageValue { get; set; }
|
||||||
|
int HealthValue { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Creatures {
|
||||||
|
public class KuriboController : MonoBehaviour, ICreature {
|
||||||
|
//components
|
||||||
|
Rigidbody2D rigidBody;
|
||||||
|
|
||||||
|
//gameplay
|
||||||
|
const float moveForce = 10f;
|
||||||
|
const float maxSpeed = 2.5f;
|
||||||
|
|
||||||
|
public int HorizontalMoveDirection { get; set; }
|
||||||
|
public int VerticalMoveDirection { get; set; }
|
||||||
|
public int DamageValue { get; set; }
|
||||||
|
|
||||||
|
int _healthValue;
|
||||||
|
public int HealthValue {
|
||||||
|
get {
|
||||||
|
return _healthValue;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_healthValue = value;
|
||||||
|
if (_healthValue <= 0) {
|
||||||
|
Destroy(gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//internals
|
||||||
|
DamagerController damagerController;
|
||||||
|
|
||||||
|
void Awake() {
|
||||||
|
rigidBody = GetComponent<Rigidbody2D>();
|
||||||
|
|
||||||
|
HorizontalMoveDirection = -1;
|
||||||
|
VerticalMoveDirection = 0;
|
||||||
|
|
||||||
|
HealthValue = 1;
|
||||||
|
DamageValue = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
damagerController = GetComponentInChildren<DamagerController>();
|
||||||
|
|
||||||
|
damagerController.PushOnTriggerEnter((Collider2D collider) => {
|
||||||
|
if (collider.gameObject.tag == "Player") {
|
||||||
|
//deal damage to the player
|
||||||
|
collider.gameObject.GetComponent<PlayerController>().HealthValue -= DamageValue;
|
||||||
|
|
||||||
|
//NOTE: not every damager will deal damage
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedUpdate() {
|
||||||
|
HandleMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCollisionEnter2D(Collision2D collision) {
|
||||||
|
//handle bouncing on a monster
|
||||||
|
Vector2 normal = collision.GetContact(0).normal;
|
||||||
|
|
||||||
|
if (collision.gameObject.tag == "Monster") {
|
||||||
|
if (normal == Vector2.up) {
|
||||||
|
//bounce
|
||||||
|
rigidBody.AddForce(new Vector2(0f, 480f));
|
||||||
|
} else {
|
||||||
|
//turn around
|
||||||
|
if (SameSign(collision.gameObject.GetComponent<ICreature>().HorizontalMoveDirection, HorizontalMoveDirection) || collision.gameObject.GetComponent<ICreature>().HorizontalMoveDirection == 0) {
|
||||||
|
rigidBody.velocity = new Vector2(0f, rigidBody.velocity.y);
|
||||||
|
HorizontalMoveDirection = -HorizontalMoveDirection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//collision with the player (when the player is not bouncing)
|
||||||
|
if (collision.gameObject.tag == "Player" && normal != Vector2.down) {
|
||||||
|
//turn around
|
||||||
|
rigidBody.velocity = new Vector2(0f, rigidBody.velocity.y);
|
||||||
|
HorizontalMoveDirection = -HorizontalMoveDirection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleMovement() {
|
||||||
|
//turn around if stopped
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < 0.1f) {
|
||||||
|
StartCoroutine(SetDirectionIfNotMovingAfter(-HorizontalMoveDirection, 0.1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
//move the entity in this direction, if not at max speed
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < maxSpeed) {
|
||||||
|
rigidBody.AddForce(Vector2.right * HorizontalMoveDirection * moveForce);
|
||||||
|
}
|
||||||
|
|
||||||
|
//slow the entity down when it's travelling too fast
|
||||||
|
if (Mathf.Abs (rigidBody.velocity.x) > maxSpeed) {
|
||||||
|
rigidBody.velocity = new Vector2 (Mathf.Sign (rigidBody.velocity.x) * maxSpeed, rigidBody.velocity.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mathf.Abs (rigidBody.velocity.y) > maxSpeed) {
|
||||||
|
rigidBody.velocity = new Vector2 (rigidBody.velocity.x, Mathf.Sign (rigidBody.velocity.y) * maxSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//utilities
|
||||||
|
IEnumerator SetDirectionIfNotMovingAfter(int direction, float delay) {
|
||||||
|
yield return new WaitForSeconds(delay);
|
||||||
|
//turn around if stopped
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < 0.1f) {
|
||||||
|
HorizontalMoveDirection = direction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SameSign(float num1, float num2) {
|
||||||
|
if (num1 > 0 && num2 > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (num1 < 0 && num2 < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//if either is zero, return false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Creatures {
|
||||||
|
public class WolfController : MonoBehaviour, ICreature {
|
||||||
|
//components
|
||||||
|
SpriteRenderer spriteRenderer;
|
||||||
|
Rigidbody2D rigidBody;
|
||||||
|
|
||||||
|
//gameplay
|
||||||
|
const float moveForce = 10f;
|
||||||
|
const float walkSpeed = 2.5f;
|
||||||
|
const float runSpeed = 5f;
|
||||||
|
float maxSpeed;
|
||||||
|
|
||||||
|
int _horizontalMoveDirection;
|
||||||
|
public int HorizontalMoveDirection {
|
||||||
|
get {
|
||||||
|
return _horizontalMoveDirection;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_horizontalMoveDirection = value;
|
||||||
|
if (_horizontalMoveDirection >= 0) {
|
||||||
|
transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), Mathf.Abs(transform.localScale.y));
|
||||||
|
} else {
|
||||||
|
transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), Mathf.Abs(transform.localScale.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int VerticalMoveDirection { get; set; }
|
||||||
|
public int DamageValue { get; set; }
|
||||||
|
|
||||||
|
int _healthValue;
|
||||||
|
public int HealthValue {
|
||||||
|
get {
|
||||||
|
return _healthValue;
|
||||||
|
}
|
||||||
|
set { //TODO: flash red
|
||||||
|
_healthValue = value;
|
||||||
|
if (_healthValue <= 0) {
|
||||||
|
Destroy(gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//internals
|
||||||
|
DamagerController damagerController;
|
||||||
|
|
||||||
|
bool detectedPlayer = false;
|
||||||
|
float detectionDistance = 10f;
|
||||||
|
|
||||||
|
void Awake() {
|
||||||
|
spriteRenderer = GetComponent<SpriteRenderer>();
|
||||||
|
rigidBody = GetComponent<Rigidbody2D>();
|
||||||
|
|
||||||
|
HorizontalMoveDirection = 1;
|
||||||
|
VerticalMoveDirection = 0;
|
||||||
|
|
||||||
|
HealthValue = 1;
|
||||||
|
DamageValue = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
damagerController = GetComponentInChildren<DamagerController>();
|
||||||
|
|
||||||
|
damagerController.PushOnTriggerEnter((Collider2D collider) => {
|
||||||
|
if (collider.gameObject.tag == "Player") {
|
||||||
|
//deal damage to the player
|
||||||
|
collider.gameObject.GetComponent<PlayerController>().HealthValue -= DamageValue;
|
||||||
|
|
||||||
|
//flip direction after a bite
|
||||||
|
HorizontalMoveDirection = -HorizontalMoveDirection;
|
||||||
|
|
||||||
|
//NOTE: not every damager will deal damage
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
damagerController.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedUpdate() {
|
||||||
|
HandleDetection();
|
||||||
|
HandleMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCollisionEnter2D(Collision2D collision) {
|
||||||
|
//handle bouncing on a monster
|
||||||
|
Vector2 normal = collision.GetContact(0).normal;
|
||||||
|
|
||||||
|
if (collision.gameObject.tag == "Monster") {
|
||||||
|
if (normal == Vector2.up) {
|
||||||
|
//bounce
|
||||||
|
rigidBody.AddForce(new Vector2(0f, 480f));
|
||||||
|
} else {
|
||||||
|
//turn around
|
||||||
|
if (SameSign(collision.gameObject.GetComponent<ICreature>().HorizontalMoveDirection, HorizontalMoveDirection) || collision.gameObject.GetComponent<ICreature>().HorizontalMoveDirection == 0) {
|
||||||
|
rigidBody.velocity = new Vector2(0f, rigidBody.velocity.y);
|
||||||
|
HorizontalMoveDirection = -HorizontalMoveDirection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//collision with the player (when the player is not bouncing)
|
||||||
|
if (collision.gameObject.tag == "Player" && normal != Vector2.down) {
|
||||||
|
//turn around
|
||||||
|
rigidBody.velocity = new Vector2(0f, rigidBody.velocity.y);
|
||||||
|
HorizontalMoveDirection = -HorizontalMoveDirection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleDetection() {
|
||||||
|
detectedPlayer = Physics2D.Linecast(transform.position, transform.position + new Vector3(transform.localScale.x * detectionDistance, 0, 0), 1 << LayerMask.NameToLayer("Player"));
|
||||||
|
|
||||||
|
if (detectedPlayer) {
|
||||||
|
maxSpeed = runSpeed;
|
||||||
|
spriteRenderer.color = Color.red;
|
||||||
|
damagerController.gameObject.SetActive(true);
|
||||||
|
} else { //no see the play
|
||||||
|
maxSpeed = walkSpeed;
|
||||||
|
spriteRenderer.color = Color.white;
|
||||||
|
damagerController.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleMovement() {
|
||||||
|
//turn around if stopped
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < 0.1f) {
|
||||||
|
StartCoroutine(SetDirectionIfNotMovingAfter(-HorizontalMoveDirection, 0.1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
//move the entity in this direction, if not at max speed
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < maxSpeed) {
|
||||||
|
rigidBody.AddForce(Vector2.right * HorizontalMoveDirection * moveForce);
|
||||||
|
}
|
||||||
|
|
||||||
|
//slow the entity down when it's travelling too fast
|
||||||
|
if (Mathf.Abs (rigidBody.velocity.x) > maxSpeed) {
|
||||||
|
rigidBody.velocity = new Vector2 (Mathf.Sign (rigidBody.velocity.x) * maxSpeed, rigidBody.velocity.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mathf.Abs (rigidBody.velocity.y) > maxSpeed) {
|
||||||
|
rigidBody.velocity = new Vector2 (rigidBody.velocity.x, Mathf.Sign (rigidBody.velocity.y) * maxSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//utilities
|
||||||
|
IEnumerator SetDirectionIfNotMovingAfter(int direction, float delay) {
|
||||||
|
yield return new WaitForSeconds(delay);
|
||||||
|
//turn around if stopped
|
||||||
|
if (Mathf.Abs(rigidBody.velocity.x) < 0.1f) {
|
||||||
|
HorizontalMoveDirection = direction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDrawGizmos() {
|
||||||
|
Gizmos.color = Color.red;
|
||||||
|
Gizmos.DrawLine(transform.position, transform.position + new Vector3(transform.localScale.x * detectionDistance, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SameSign(float num1, float num2) {
|
||||||
|
if (num1 > 0 && num2 > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (num1 < 0 && num2 < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//if either is zero, return false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class DamagerController : MonoBehaviour {
|
||||||
|
public delegate void CallbackHandler(Collider2D collider);
|
||||||
|
|
||||||
|
List<CallbackHandler> onTriggerEnter = new List<CallbackHandler>();
|
||||||
|
List<CallbackHandler> onTriggerStay= new List<CallbackHandler>();
|
||||||
|
List<CallbackHandler> onTriggerExit = new List<CallbackHandler>();
|
||||||
|
|
||||||
|
//public access members
|
||||||
|
public void PushOnTriggerEnter(CallbackHandler callback) {
|
||||||
|
onTriggerEnter.Add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PushOnTriggerStay(CallbackHandler callback) {
|
||||||
|
onTriggerStay.Add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PushOnTriggerExit(CallbackHandler callback) {
|
||||||
|
onTriggerExit.Add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PurgeLists() {
|
||||||
|
onTriggerEnter.Clear();
|
||||||
|
onTriggerStay.Clear();
|
||||||
|
onTriggerExit.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//monobehaviour members
|
||||||
|
void OnTriggerEnter2D(Collider2D collider) {
|
||||||
|
foreach(CallbackHandler callback in onTriggerEnter) {
|
||||||
|
callback(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnTriggerStay2D(Collider2D collider) {
|
||||||
|
foreach(CallbackHandler callback in onTriggerStay) {
|
||||||
|
callback(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnTriggerExit2D(Collider2D collider) {
|
||||||
|
foreach(CallbackHandler callback in onTriggerExit) {
|
||||||
|
callback(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,715 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using SpriterDotNetUnity;
|
||||||
|
|
||||||
|
public class PlayerController : MonoBehaviour {
|
||||||
|
//internal components
|
||||||
|
GameObject spriteObject;
|
||||||
|
UnityAnimator animator;
|
||||||
|
Rigidbody2D rigidBody;
|
||||||
|
BoxCollider2D currentBoxCollider;
|
||||||
|
|
||||||
|
//constants
|
||||||
|
const float deadZone = 0.25f;
|
||||||
|
|
||||||
|
//gameplay
|
||||||
|
[Header("Movement Settings")]
|
||||||
|
public float moveForce = 10f;
|
||||||
|
public float jumpForce = 400;
|
||||||
|
public float maxSpeed = 3f;
|
||||||
|
public float fallSpeed = 8f;
|
||||||
|
public float dashMultiplier = 2f;
|
||||||
|
public float straightJumpVerticalMultiplier = 1.1f;
|
||||||
|
public float straightJumpHorizontalMultiplier = 0.5f;
|
||||||
|
// public float rollingJumpVerticalMultiplier = 1.0f;
|
||||||
|
// public float rollingJumpHorizontalMultiplier = 1.0f;
|
||||||
|
public float jumpMaxSpeedMultiplier = 1.1f;
|
||||||
|
public float wallJumpMaxSpeedMultiplier = 0.5f;
|
||||||
|
public float wallHuggedMultiplier = 0.5f;
|
||||||
|
|
||||||
|
//basic movement
|
||||||
|
float horizontalInput = 0f;
|
||||||
|
float verticalInput = 0f;
|
||||||
|
bool jumping = false;
|
||||||
|
bool grounded = false;
|
||||||
|
bool wallHugged = false;
|
||||||
|
bool wallJumping = false;
|
||||||
|
const float groundedProjection = 0.08f;
|
||||||
|
|
||||||
|
//dashing movement
|
||||||
|
float dashValue = 0f;
|
||||||
|
float dashTime = float.NegativeInfinity;
|
||||||
|
bool dashLatch = true;
|
||||||
|
|
||||||
|
//movement modifiers
|
||||||
|
float horizontalModifier = 1f;
|
||||||
|
float verticalModifier = 1f;
|
||||||
|
float dashModifier = 1f;
|
||||||
|
float maxSpeedModifier = 1f;
|
||||||
|
|
||||||
|
//combat
|
||||||
|
DamagerController[] damagerControllers;
|
||||||
|
HUDCanvas hud;
|
||||||
|
bool invulnerable = false;
|
||||||
|
|
||||||
|
public int DamageValue { get; set; }
|
||||||
|
public int HealthValue {
|
||||||
|
set {
|
||||||
|
//prevent damage while invulnerable
|
||||||
|
if (value < hud.FlameLevel && invulnerable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check death
|
||||||
|
if (value < 0) {
|
||||||
|
Debug.Log("YOU DIED");
|
||||||
|
}
|
||||||
|
|
||||||
|
//trigger hitstun if damage taken
|
||||||
|
if (value < hud.FlameLevel) {
|
||||||
|
StartCoroutine(TriggerHitStun(0.8f));
|
||||||
|
}
|
||||||
|
|
||||||
|
//set the graphics
|
||||||
|
hud.FlameLevel = value;
|
||||||
|
}
|
||||||
|
get {
|
||||||
|
return hud.FlameLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//graphical modifiers
|
||||||
|
float prevTimeScale;
|
||||||
|
float prevLocalScaleX;
|
||||||
|
|
||||||
|
//gameplay
|
||||||
|
float friction = 0f;
|
||||||
|
|
||||||
|
void Awake() {
|
||||||
|
rigidBody = GetComponent<Rigidbody2D>();
|
||||||
|
currentBoxCollider = GetComponent<BoxCollider2D>();
|
||||||
|
prevTimeScale = Time.timeScale; //BUGFIX: waking when unpaused
|
||||||
|
prevLocalScaleX = transform.localScale.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
//BUGFIX: Set the sprite sorting order
|
||||||
|
GetComponentsInChildren<SpriterDotNetBehaviour>()[0].SortingLayer = "Player";
|
||||||
|
|
||||||
|
//get the HUD
|
||||||
|
hud = Object.FindObjectOfType<HUDCanvas>();
|
||||||
|
|
||||||
|
DamageValue = 1;
|
||||||
|
HealthValue = 4;
|
||||||
|
|
||||||
|
//get and disable the damagers
|
||||||
|
damagerControllers = GetComponentsInChildren<DamagerController>();
|
||||||
|
foreach(DamagerController dmgr in damagerControllers) {
|
||||||
|
dmgr.gameObject.SetActive(false);
|
||||||
|
|
||||||
|
dmgr.PushOnTriggerEnter((Collider2D collider) => {
|
||||||
|
if (collider.gameObject.tag == "Monster" && collider.gameObject.GetComponent<Creatures.ICreature>().HealthValue > 0) {
|
||||||
|
collider.gameObject.GetComponent<Creatures.ICreature>().HealthValue -= DamageValue;
|
||||||
|
hud.SparkLevel++;
|
||||||
|
|
||||||
|
//bounce on attack
|
||||||
|
Vector2 normal = collider.bounds.ClosestPoint(transform.position) - transform.position;
|
||||||
|
normal.Normalize();
|
||||||
|
|
||||||
|
if (normal.y < 0f) {
|
||||||
|
jumping = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
if (Time.timeScale > 0f && Time.timeScale == prevTimeScale && HandleAnimation()) {
|
||||||
|
HandleInput();
|
||||||
|
}
|
||||||
|
prevTimeScale = Time.timeScale;
|
||||||
|
|
||||||
|
//Debug.LogFormat("{0} {1}", animator.CurrentAnimation.Name, currentBoxCollider.size.y);
|
||||||
|
|
||||||
|
//handle gameplay
|
||||||
|
if (friction >= 1f) {
|
||||||
|
hud.SparkLevel++;
|
||||||
|
friction -= 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animator.CurrentAnimation.Name != "Run" && animator.CurrentAnimation.Name != "Wall Slide") {
|
||||||
|
friction = 0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedUpdate() {
|
||||||
|
HandleMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCollisionEnter2D(Collision2D collision) {
|
||||||
|
//handle bouncing on a monster
|
||||||
|
Vector2 normal = collision.GetContact(0).normal;
|
||||||
|
|
||||||
|
if (collision.gameObject.tag == "Monster") {
|
||||||
|
if (normal == Vector2.up) {
|
||||||
|
//bounce
|
||||||
|
jumping = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleInput() {
|
||||||
|
//determine if on the ground (using coyote time)
|
||||||
|
bool trueGrounded;
|
||||||
|
trueGrounded = Physics2D.Linecast(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x), -groundedProjection, 0), 1 << LayerMask.NameToLayer("Ground"));
|
||||||
|
trueGrounded |= Physics2D.Linecast(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x + currentBoxCollider.size.x / 2.1f), -groundedProjection, 0), 1 << LayerMask.NameToLayer("Ground"));
|
||||||
|
trueGrounded |= Physics2D.Linecast(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x - currentBoxCollider.size.x / 2.1f), -groundedProjection, 0), 1 << LayerMask.NameToLayer("Ground"));
|
||||||
|
|
||||||
|
if (trueGrounded) {
|
||||||
|
grounded = true;
|
||||||
|
} else {
|
||||||
|
StartCoroutine(SetGroundedWithDelay(false, 0.1f)); //coyote physics: 100ms
|
||||||
|
}
|
||||||
|
|
||||||
|
//determine wall hugging
|
||||||
|
wallHugged = Physics2D.Linecast(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x + currentBoxCollider.size.x / 2 + groundedProjection), currentBoxCollider.size.y * 0.05f, 0), 1 << LayerMask.NameToLayer("Ground"));
|
||||||
|
wallHugged &= Physics2D.Linecast(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x + currentBoxCollider.size.x / 2 + groundedProjection), currentBoxCollider.size.y * 0.5f, 0), 1 << LayerMask.NameToLayer("Ground"));
|
||||||
|
wallHugged &= Physics2D.Linecast(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x + currentBoxCollider.size.x / 2 + groundedProjection), currentBoxCollider.size.y * 0.95f, 0), 1 << LayerMask.NameToLayer("Ground"));
|
||||||
|
|
||||||
|
//reset multipliers under regular conditions
|
||||||
|
if (trueGrounded && !jumping) {
|
||||||
|
horizontalModifier = 1f;
|
||||||
|
verticalModifier = 1f;
|
||||||
|
maxSpeedModifier = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get inputs
|
||||||
|
verticalInput = GamePad.GetAxis(CAxis.LY);
|
||||||
|
horizontalInput = GamePad.GetAxis(CAxis.LX);
|
||||||
|
|
||||||
|
//determine vertical input
|
||||||
|
if (Mathf.Abs(verticalInput) < deadZone) { //no input
|
||||||
|
verticalInput = 0f;
|
||||||
|
|
||||||
|
//handle stop crouching
|
||||||
|
if (animator.CurrentAnimation.Name == "Crouch") {
|
||||||
|
animator.Play("Crouch to Idle");
|
||||||
|
}
|
||||||
|
} else { //yes input
|
||||||
|
if (verticalInput < 0) { //looking up
|
||||||
|
if (grounded && animator.CurrentAnimation.Name == "Idle" && Mathf.Abs(horizontalInput) < deadZone) {
|
||||||
|
animator.Play("Idle to Lookup");
|
||||||
|
}
|
||||||
|
} else { //crouching down
|
||||||
|
//from rolling jump to crouch
|
||||||
|
if (grounded && animator.CurrentAnimation.Name == "Rolling Jump") {
|
||||||
|
animator.Play("Crouch");
|
||||||
|
}
|
||||||
|
else if (grounded && Mathf.Abs(rigidBody.velocity.y) > 0.0001f) { //explicitly don't check for animation here; "Straight Jump Landing" passes through here for some reason
|
||||||
|
animator.Play("Rolling Jump");
|
||||||
|
}
|
||||||
|
//if not already crouching
|
||||||
|
else if (grounded && animator.CurrentAnimation.Name != "Crouch" && animator.CurrentAnimation.Name != "Idle to Crouch") {
|
||||||
|
animator.Play("Idle to Crouch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//determine if walking
|
||||||
|
if (Mathf.Abs(horizontalInput) < deadZone) { //no input
|
||||||
|
//reset multipliers under regular conditions
|
||||||
|
if (grounded && !jumping) {
|
||||||
|
dashModifier = 1f;
|
||||||
|
if (animator.CurrentAnimation.Name == "Run") {
|
||||||
|
animator.Play("Walk");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dashLatch) {
|
||||||
|
//capture the time of last release for dashing
|
||||||
|
dashTime = Time.time;
|
||||||
|
dashLatch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//stop walking
|
||||||
|
horizontalInput = 0f;
|
||||||
|
if (animator.CurrentAnimation.Name == "Walk") {
|
||||||
|
//animator.Play("Walk to Idle"); //TODO: enable this
|
||||||
|
animator.Play("Idle"); //TODO: remove this (why?)
|
||||||
|
}
|
||||||
|
} else { //yes input
|
||||||
|
if (animator.CurrentAnimation.Name == "Crouch") {
|
||||||
|
//TODO: slides/rolls
|
||||||
|
|
||||||
|
horizontalInput = horizontalInput > 0 ? 0.0001f : -0.0001f; //TMP
|
||||||
|
} else if (animator.CurrentAnimation.Name == "Lookup") {
|
||||||
|
animator.Play("Lookup to Idle");
|
||||||
|
} else if (wallHugged && !grounded && (animator.CurrentAnimation.Name != "Brace on Wall" && animator.CurrentAnimation.Name != "Wall Slide" && animator.CurrentAnimation.Name != "Wall Kick")) {
|
||||||
|
animator.Play("Brace on Wall");
|
||||||
|
} else {
|
||||||
|
//check if dashing
|
||||||
|
if (Time.time - dashTime < 0.2f && SameSign(horizontalInput, dashValue) && grounded && !dashLatch) {
|
||||||
|
dashModifier = dashMultiplier;
|
||||||
|
horizontalInput = maxSpeed * dashModifier * (horizontalInput > 0 ? 1 : -1);
|
||||||
|
animator.Play("Run");
|
||||||
|
StartCoroutine(BuildingFriction("Run", 0.05f));
|
||||||
|
}
|
||||||
|
|
||||||
|
//capture the value for dashing
|
||||||
|
dashValue = horizontalInput;
|
||||||
|
|
||||||
|
//BUGFIX
|
||||||
|
dashLatch = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//BUGFIX: landing into a run
|
||||||
|
if (animator.CurrentAnimation.Name == "Idle" && dashModifier != 1f) {
|
||||||
|
animator.Play("Run");
|
||||||
|
StartCoroutine(BuildingFriction("Run", 0.05f));
|
||||||
|
}
|
||||||
|
|
||||||
|
//start walking
|
||||||
|
if (animator.CurrentAnimation.Name == "Idle") {
|
||||||
|
animator.Play("Idle to Walk");
|
||||||
|
}
|
||||||
|
|
||||||
|
//flip direction
|
||||||
|
if (Time.timeScale > 0f) {
|
||||||
|
prevLocalScaleX = transform.localScale.x;
|
||||||
|
transform.localScale = new Vector3(horizontalInput > 0 ? 1 : -1, 1, 1);
|
||||||
|
|
||||||
|
//play turning animations
|
||||||
|
if (prevLocalScaleX != transform.localScale.x) {
|
||||||
|
if (animator.CurrentAnimation.Name == "Idle" || animator.CurrentAnimation.Name == "Idle to Walk" || animator.CurrentAnimation.Name == "Walk" || animator.CurrentAnimation.Name == "Lookup to Idle") {
|
||||||
|
animator.Play("Ground Turn");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animator.CurrentAnimation.Name == "Straight Jump Rising" || animator.CurrentAnimation.Name == "Straight Jump Crest" || animator.CurrentAnimation.Name == "Straight Jump Falling") {
|
||||||
|
animator.Play("Straight Jump Turn");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animator.CurrentAnimation.Name == "Rolling Jump") {
|
||||||
|
animator.Play("Rolling Jump Turn");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//determine if jumping
|
||||||
|
if (GamePad.GetState().Pressed(CButton.A) && grounded) {
|
||||||
|
jumping = true;
|
||||||
|
|
||||||
|
maxSpeedModifier = jumpMaxSpeedMultiplier;
|
||||||
|
|
||||||
|
if (animator.CurrentAnimation.Name == "Crouch") {
|
||||||
|
animator.Play("Rolling Jump");
|
||||||
|
}
|
||||||
|
else if (Mathf.Abs(horizontalInput) < deadZone) {
|
||||||
|
animator.Play("Begin Straight Jump");
|
||||||
|
horizontalModifier = straightJumpHorizontalMultiplier;
|
||||||
|
verticalModifier = straightJumpVerticalMultiplier;
|
||||||
|
} else {
|
||||||
|
animator.Play("Begin Rolling Jump");
|
||||||
|
//horizontalModifier = rollingJumpHorizontalMultiplier;
|
||||||
|
//verticalModifier = rollingJumpVerticalMultiplier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GamePad.GetState().Pressed(CButton.A) && !grounded && wallHugged && (animator.CurrentAnimation.Name == "Brace on Wall" || animator.CurrentAnimation.Name == "Wall Slide")) {
|
||||||
|
wallJumping = true;
|
||||||
|
|
||||||
|
maxSpeedModifier = jumpMaxSpeedMultiplier;
|
||||||
|
|
||||||
|
animator.Play("Wall Kick");
|
||||||
|
}
|
||||||
|
|
||||||
|
//determine if attacking on the ground
|
||||||
|
if (GamePad.GetState().Pressed(CButton.B) && grounded) {
|
||||||
|
if (verticalInput < -deadZone) { //yes up input
|
||||||
|
if (animator.CurrentAnimation.Name == "Run") {
|
||||||
|
animator.Play("Grounded Upward Slash"); //TODO: replace with "Running Upward Slash"
|
||||||
|
} else {
|
||||||
|
animator.Play("Grounded Upward Slash");
|
||||||
|
}
|
||||||
|
StartCoroutine(EnableDamagerForPeriod(0, 0.3f));
|
||||||
|
} else { //no vertical input
|
||||||
|
if (animator.CurrentAnimation.Name == "Run") {
|
||||||
|
animator.Play("Grounded Forward Slash"); //TODO: replace with "Running Forward Slash"
|
||||||
|
} else {
|
||||||
|
animator.Play("Grounded Forward Slash");
|
||||||
|
}
|
||||||
|
StartCoroutine(EnableDamagerForPeriod(1, 0.3f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//determine if attacking in the air
|
||||||
|
if (GamePad.GetState().Pressed(CButton.B) && !grounded) {
|
||||||
|
if (verticalInput < -deadZone) { //yes up input
|
||||||
|
animator.Play("Airborn Upward Slash");
|
||||||
|
StartCoroutine(EnableDamagerForPeriod(0, 0.3f));
|
||||||
|
} else if (verticalInput > deadZone) { //yes down input
|
||||||
|
animator.Play("Airborn Downward Slash");
|
||||||
|
StartCoroutine(EnableDamagerForPeriod(2, 0.3f));
|
||||||
|
} else { //no vertical input
|
||||||
|
animator.Play("Airborn Forward Slash");
|
||||||
|
StartCoroutine(EnableDamagerForPeriod(1, 0.3f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//determine if releasing the attack button
|
||||||
|
if (GamePad.GetState().Released(CButton.B)) {
|
||||||
|
foreach (DamagerController dmgr in damagerControllers) {
|
||||||
|
dmgr.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//BUGFIX: prevent crouch-gliding and slash-gliding
|
||||||
|
if (grounded && (animator.CurrentAnimation.Name == "Crouch")) {
|
||||||
|
horizontalInput = 0f;
|
||||||
|
dashModifier = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//BUGFIX: falling animations after walking/running off a cliff
|
||||||
|
if (rigidBody.velocity.y < -0.0001f && (animator.CurrentAnimation.Name == "Walk" || animator.CurrentAnimation.Name == "Run")) {
|
||||||
|
animator.Play("Straight Jump Falling");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleMovement() {
|
||||||
|
//stop the player if input in that direction has been removed
|
||||||
|
if (horizontalInput * rigidBody.velocity.x <= 0 && grounded) {
|
||||||
|
rigidBody.velocity = new Vector2 (rigidBody.velocity.x * 0.85f, rigidBody.velocity.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//move in the inputted direction, if not at max speed
|
||||||
|
if (horizontalInput * rigidBody.velocity.x < maxSpeed * dashModifier * maxSpeedModifier) {
|
||||||
|
rigidBody.AddForce (Vector2.right * horizontalInput * moveForce * horizontalModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
//slow the player down when it's travelling too fast
|
||||||
|
if (Mathf.Abs (rigidBody.velocity.x) > maxSpeed * dashModifier * maxSpeedModifier) {
|
||||||
|
rigidBody.velocity = new Vector2 (Mathf.Sign (rigidBody.velocity.x) * maxSpeed * dashModifier * maxSpeedModifier, rigidBody.velocity.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rigidBody.velocity.y < -fallSpeed * (wallHugged ? wallHuggedMultiplier : 1f)) {
|
||||||
|
rigidBody.velocity = new Vector2 (rigidBody.velocity.x, Mathf.Sign (rigidBody.velocity.y) * fallSpeed * (wallHugged ? wallHuggedMultiplier : 1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
//jump up
|
||||||
|
if (jumping) {
|
||||||
|
rigidBody.velocity = new Vector2(rigidBody.velocity.x, 0f); //max v-jump speed
|
||||||
|
rigidBody.AddForce (new Vector2 (0f, jumpForce * verticalModifier));
|
||||||
|
jumping = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wallJumping) {
|
||||||
|
rigidBody.velocity = new Vector2(0f, 0f); //wall-jump from zero
|
||||||
|
rigidBody.AddForce (new Vector2 (-transform.localScale.x * maxSpeed * jumpForce, jumpForce * verticalModifier));
|
||||||
|
maxSpeedModifier = wallJumpMaxSpeedMultiplier;
|
||||||
|
wallJumping = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HandleAnimation() {
|
||||||
|
if (spriteObject == null) {
|
||||||
|
foreach (Transform child in transform) {
|
||||||
|
if (child.name == "Ember") {
|
||||||
|
spriteObject = child.gameObject;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animator == null && spriteObject != null) {
|
||||||
|
animator = spriteObject.GetComponent<SpriterDotNetBehaviour>().Animator;
|
||||||
|
animator.AnimationFinished += HandleAnimationTransitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
//determine statue state
|
||||||
|
if (!PauseManager.Instance.Paused && animator.CurrentAnimation.Name == "Statue" &&
|
||||||
|
(
|
||||||
|
//NOTE: carbon input really needs an "any key"
|
||||||
|
//any face button
|
||||||
|
GamePad.GetState().Pressed(CButton.A) || GamePad.GetState().Pressed(CButton.B) || GamePad.GetState().Pressed(CButton.X) || GamePad.GetState().Pressed(CButton.Y) || //only pressed this loop
|
||||||
|
//any axis
|
||||||
|
Mathf.Abs(GamePad.GetAxis(CAxis.LX)) >= deadZone || Mathf.Abs(GamePad.GetAxis(CAxis.LY)) >= deadZone || Mathf.Abs(GamePad.GetAxis(CAxis.RX)) >= deadZone || Mathf.Abs(GamePad.GetAxis(CAxis.RY)) >= deadZone
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
animator.Play("Statue to Idle");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animator.CurrentAnimation.Name == "Statue to Idle") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//switch from regular animations to transition animations
|
||||||
|
if (animator.CurrentAnimation.Name == "Straight Jump Rising" && rigidBody.velocity.y <= 0) {
|
||||||
|
animator.Play("Straight Jump Crest");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animator.CurrentAnimation.Name == "Straight Jump Falling" && rigidBody.velocity.y >= 0) {
|
||||||
|
animator.Play("Straight Jump Landing");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animator.CurrentAnimation.Name == "Rolling Jump" && grounded) {
|
||||||
|
animator.Play("Straight Jump Landing"); //deliberately reuse this
|
||||||
|
}
|
||||||
|
|
||||||
|
//start looking up
|
||||||
|
if (animator.CurrentAnimation.Name == "Idle" && verticalInput < 0 && Mathf.Abs(rigidBody.velocity.x) < 0.0001f) {
|
||||||
|
animator.Play("Idle to Lookup");
|
||||||
|
}
|
||||||
|
|
||||||
|
//stop looking up
|
||||||
|
if (animator.CurrentAnimation.Name == "Lookup" && verticalInput >= 0) {
|
||||||
|
animator.Play("Lookup to Idle");
|
||||||
|
}
|
||||||
|
|
||||||
|
//BUGFIX: bouncing off of a wall
|
||||||
|
if (!grounded && !wallHugged && animator.CurrentAnimation.Name == "Wall Slide") {
|
||||||
|
animator.Play("Rolling Jump");
|
||||||
|
}
|
||||||
|
|
||||||
|
//if ever simply falling (or attacking)
|
||||||
|
if (!grounded && !wallHugged && rigidBody.velocity.y < 0 && animator.CurrentAnimation.Name != "Straight Jump Crest" && animator.CurrentAnimation.Name != "Straight Jump Turn" && animator.CurrentAnimation.Name != "Rolling Jump Turn" && animator.CurrentAnimation.Name != "Rolling Jump" && animator.CurrentAnimation.Name != "Airborn Upward Slash" && animator.CurrentAnimation.Name != "Airborn Downward Slash" && animator.CurrentAnimation.Name != "Airborn Forward Slash") {
|
||||||
|
animator.Play("Straight Jump Falling");
|
||||||
|
}
|
||||||
|
|
||||||
|
//hit a wall
|
||||||
|
if (animator.CurrentAnimation.Name != "Brace on Wall" && animator.CurrentAnimation.Name != "Wall Slide" && animator.CurrentAnimation.Name != "Wall Kick" && wallHugged && !grounded) {
|
||||||
|
animator.Play("Brace on Wall");
|
||||||
|
}
|
||||||
|
|
||||||
|
//reach the bottom of a wall-slide (or hit the ground when turning)
|
||||||
|
if ((animator.CurrentAnimation.Name == "Brace on Wall" || animator.CurrentAnimation.Name == "Wall Slide" || animator.CurrentAnimation.Name == "Straight Jump Turn" || animator.CurrentAnimation.Name == "Rolling Jump Turn") && grounded) {
|
||||||
|
animator.Play("Straight Jump Landing");
|
||||||
|
}
|
||||||
|
|
||||||
|
//if bouncing
|
||||||
|
if (animator.CurrentAnimation.Name == "Straight Jump Landing" && !grounded && rigidBody.velocity.y > 0f) {
|
||||||
|
animator.Play("Begin Rolling Jump");
|
||||||
|
}
|
||||||
|
|
||||||
|
//handle bounding box
|
||||||
|
if (
|
||||||
|
animator.CurrentAnimation.Name == "Crouch" ||
|
||||||
|
animator.CurrentAnimation.Name == "Idle to Crouch" ||
|
||||||
|
animator.CurrentAnimation.Name == "Rolling Jump" ||
|
||||||
|
animator.CurrentAnimation.Name == "Begin Rolling Jump" ||
|
||||||
|
(rigidBody.velocity.y > 0 && animator.CurrentAnimation.Name == "Straight Jump Landing") ||
|
||||||
|
animator.CurrentAnimation.Name == "Brace on Wall" ||
|
||||||
|
animator.CurrentAnimation.Name == "Wall Slide" ||
|
||||||
|
animator.CurrentAnimation.Name == "Wall Kick"
|
||||||
|
) {
|
||||||
|
//half box
|
||||||
|
if (currentBoxCollider != GetComponents<BoxCollider2D>()[1]) {
|
||||||
|
currentBoxCollider.enabled = false;
|
||||||
|
currentBoxCollider = GetComponents<BoxCollider2D>()[1];
|
||||||
|
currentBoxCollider.enabled = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//full box
|
||||||
|
if (currentBoxCollider != GetComponents<BoxCollider2D>()[0]) {
|
||||||
|
currentBoxCollider.enabled = false;
|
||||||
|
currentBoxCollider = GetComponents<BoxCollider2D>()[0];
|
||||||
|
currentBoxCollider.enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//peek with the camera
|
||||||
|
CameraController camController = Object.FindObjectOfType<CameraController>();
|
||||||
|
if (camController.GetPeek() == Vector2.zero) {
|
||||||
|
if (animator.CurrentAnimation.Name == "Lookup") {
|
||||||
|
camController.SetPeek(new Vector2(0f, 4f));
|
||||||
|
}
|
||||||
|
if (animator.CurrentAnimation.Name == "Crouch") {
|
||||||
|
camController.SetPeek(new Vector2(0f, -4f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (camController.GetPeek() != Vector2.zero) {
|
||||||
|
if (animator.CurrentAnimation.Name != "Lookup" && animator.CurrentAnimation.Name != "Crouch") {
|
||||||
|
camController.ResetPeek();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//internal callbacks
|
||||||
|
void HandleAnimationTransitions(string name) {
|
||||||
|
//NOTE: This handles the end of transitional animations
|
||||||
|
switch(name) {
|
||||||
|
case "Statue to Idle":
|
||||||
|
animator.Play("Idle");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Idle to Walk":
|
||||||
|
animator.Play("Walk");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Walk to Idle":
|
||||||
|
animator.Play("Idle");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Begin Straight Jump":
|
||||||
|
animator.Play("Straight Jump Rising");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Straight Jump Crest":
|
||||||
|
animator.Play("Straight Jump Falling");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Straight Jump Landing":
|
||||||
|
animator.Play("Idle");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Begin Rolling Jump":
|
||||||
|
animator.Play("Rolling Jump");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Idle to Crouch":
|
||||||
|
animator.Play("Crouch");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Crouch to Idle":
|
||||||
|
animator.Play("Idle");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Idle to Lookup":
|
||||||
|
animator.Play("Lookup");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Lookup to Idle":
|
||||||
|
animator.Play("Idle");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Brace on Wall":
|
||||||
|
animator.Play("Wall Slide");
|
||||||
|
StartCoroutine(BuildingFriction("Wall Slide", 0.1f));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Wall Kick":
|
||||||
|
animator.Play("Rolling Jump");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Grounded Forward Slash":
|
||||||
|
animator.Play("Idle");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Grounded Upward Slash":
|
||||||
|
if (verticalInput < -deadZone && Mathf.Abs(rigidBody.velocity.x) < 0.0001f) {
|
||||||
|
animator.Play("Lookup");
|
||||||
|
} else {
|
||||||
|
if (dashModifier != 1f) {
|
||||||
|
animator.Play("Run");
|
||||||
|
StartCoroutine(BuildingFriction("Run", 0.05f));
|
||||||
|
} else {
|
||||||
|
animator.Play("Idle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Airborn Upward Slash":
|
||||||
|
case "Airborn Downward Slash":
|
||||||
|
case "Airborn Forward Slash":
|
||||||
|
if (rigidBody.velocity.y > 0f) {
|
||||||
|
animator.Play("Straight Jump Rising");
|
||||||
|
} else {
|
||||||
|
animator.Play("Straight Jump Falling");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Ground Turn":
|
||||||
|
animator.Play("Idle");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Straight Jump Turn":
|
||||||
|
if (rigidBody.velocity.y > 0f) {
|
||||||
|
animator.Play("Straight Jump Rising");
|
||||||
|
} else {
|
||||||
|
animator.Play("Straight Jump Falling");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Rolling Jump Turn":
|
||||||
|
animator.Play("Rolling Jump");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//utilities
|
||||||
|
void OnDrawGizmos() {
|
||||||
|
if (currentBoxCollider != null) {
|
||||||
|
Gizmos.color = Color.red;
|
||||||
|
Gizmos.DrawLine(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x), -groundedProjection, 0));
|
||||||
|
Gizmos.DrawLine(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x + currentBoxCollider.size.x / 2.1f), -groundedProjection, 0));
|
||||||
|
Gizmos.DrawLine(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x - currentBoxCollider.size.x / 2.1f), -groundedProjection, 0));
|
||||||
|
|
||||||
|
Gizmos.color = Color.red;
|
||||||
|
Gizmos.DrawLine(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x + currentBoxCollider.size.x / 2 + groundedProjection), currentBoxCollider.size.y * 0.05f, 0));
|
||||||
|
Gizmos.DrawLine(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x + currentBoxCollider.size.x / 2 + groundedProjection), currentBoxCollider.size.y * 0.5f, 0));
|
||||||
|
Gizmos.DrawLine(transform.position + new Vector3(currentBoxCollider.offset.x, currentBoxCollider.offset.y, 0), transform.position + new Vector3(transform.localScale.x * (currentBoxCollider.offset.x + currentBoxCollider.size.x / 2 + groundedProjection), currentBoxCollider.size.y * 0.95f, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SameSign(float num1, float num2) {
|
||||||
|
if (num1 > 0 && num2 > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (num1 < 0 && num2 < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//if either is zero, return false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator SetGroundedWithDelay(bool value, float delay) {
|
||||||
|
yield return new WaitForSeconds(delay);
|
||||||
|
grounded = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator EnableDamagerForPeriod(int index, float delay) {
|
||||||
|
damagerControllers[index].gameObject.SetActive(true);
|
||||||
|
yield return new WaitForSeconds(delay);
|
||||||
|
damagerControllers[index].gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator BuildingFriction(string animation, float increment) {
|
||||||
|
while (animator.CurrentAnimation.Name == animation) {
|
||||||
|
friction += increment;
|
||||||
|
yield return new WaitForSeconds(0.1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator TriggerHitStun(float delay) {
|
||||||
|
invulnerable = true;
|
||||||
|
StartCoroutine(TriggerHitStunGraphic(0.1f, delay - 0.1f));
|
||||||
|
yield return new WaitForSeconds(delay);
|
||||||
|
invulnerable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator TriggerHitStunGraphic(float redDelay, float opacityDelay) {
|
||||||
|
SpriteRenderer[] spriteRenderers = GetComponentsInChildren<SpriteRenderer>();
|
||||||
|
|
||||||
|
//flash red
|
||||||
|
foreach (var renderer in spriteRenderers) {
|
||||||
|
renderer.color = Color.red;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return new WaitForSeconds(redDelay);
|
||||||
|
|
||||||
|
foreach (var renderer in spriteRenderers) {
|
||||||
|
renderer.color = Color.white;
|
||||||
|
renderer.material.color = new Color(1f, 1f, 1f, 0.75f);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return new WaitForSeconds(opacityDelay);
|
||||||
|
|
||||||
|
foreach (var renderer in spriteRenderers) {
|
||||||
|
renderer.material.color = Color.white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class ProximitySpawner : MonoBehaviour {
|
||||||
|
//public access members
|
||||||
|
public GameObject prefab;
|
||||||
|
public string targetTag;
|
||||||
|
public float minDistance = 4f;
|
||||||
|
public float maxDistance = 10f;
|
||||||
|
public bool destroyIfTooFar = false;
|
||||||
|
|
||||||
|
//private members
|
||||||
|
Transform targetTransform;
|
||||||
|
GameObject spawnedObject;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
targetTransform = GameObject.FindWithTag(targetTag).transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
//get the distance
|
||||||
|
float distance = Vector3.Distance(transform.position, targetTransform.position);
|
||||||
|
|
||||||
|
//destroy if the player is too far away
|
||||||
|
if (destroyIfTooFar && distance > maxDistance) {
|
||||||
|
Destroy(spawnedObject);
|
||||||
|
return; //skip out on the next check
|
||||||
|
}
|
||||||
|
|
||||||
|
//check the distance, check the spawned object
|
||||||
|
if (distance > minDistance && distance < maxDistance && spawnedObject == null) {
|
||||||
|
spawnedObject = Instantiate(prefab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class TimedSpawner : MonoBehaviour {
|
||||||
|
//inspector access elements
|
||||||
|
public GameObject prefab;
|
||||||
|
public float spawnDelay = 10f;
|
||||||
|
public int maxSpawns = 3;
|
||||||
|
|
||||||
|
//private members
|
||||||
|
float lastSpawnTime = float.NegativeInfinity;
|
||||||
|
List<GameObject> spawnList = new List<GameObject>();
|
||||||
|
|
||||||
|
//TODO: maybe all spawners should shut off (and monsters become inactive) when the player is too far away.
|
||||||
|
void Update() {
|
||||||
|
//prune the list
|
||||||
|
spawnList.RemoveAll(spawn => spawn == null);
|
||||||
|
|
||||||
|
//spawn if enough time has passed
|
||||||
|
if (Time.time - lastSpawnTime > spawnDelay && spawnList.Count < maxSpawns) {
|
||||||
|
lastSpawnTime = Time.time;
|
||||||
|
|
||||||
|
spawnList.Add(Instantiate(prefab, transform.position, Quaternion.identity, transform));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Structures {
|
||||||
|
public class HazardController : MonoBehaviour {
|
||||||
|
//internals
|
||||||
|
int DamageValue { get; set; }
|
||||||
|
DamagerController damagerController;
|
||||||
|
|
||||||
|
void Awake() {
|
||||||
|
DamageValue = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
damagerController = GetComponent<DamagerController>();
|
||||||
|
|
||||||
|
damagerController.PushOnTriggerStay((Collider2D collider) => {
|
||||||
|
if (collider.gameObject.tag == "Player") {
|
||||||
|
//deal damage to the player
|
||||||
|
collider.gameObject.GetComponent<PlayerController>().HealthValue -= DamageValue;
|
||||||
|
|
||||||
|
//NOTE: not every damager will deal damage
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Structures {
|
||||||
|
public class Pedestal : MonoBehaviour {
|
||||||
|
public string name;
|
||||||
|
public SaveHandler SaveHandler { set; get; }
|
||||||
|
|
||||||
|
void OnCollisionEnter2D(Collision2D collision) {
|
||||||
|
if (collision.gameObject.tag == "Player") {
|
||||||
|
SaveFileManager.LoadedSaveSlot.currentLocation = name;
|
||||||
|
SaveHandler.saveMenuAvailable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnCollisionExit2D(Collision2D collision) {
|
||||||
|
if (collision.gameObject.tag == "Player") {
|
||||||
|
SaveHandler.saveMenuAvailable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[Serializable()]
|
||||||
|
public class ConfigurationManager {
|
||||||
|
//singleton members
|
||||||
|
private static ConfigurationManager singletonObject = null;
|
||||||
|
public static ConfigurationManager Instance {
|
||||||
|
get {
|
||||||
|
if (singletonObject == null) {
|
||||||
|
string fname = Path.Combine(Application.persistentDataPath, "configuration.json");
|
||||||
|
new ConfigurationManager(fname); //NOTE: singleton object assigned elsewhere
|
||||||
|
}
|
||||||
|
return singletonObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//serializable fields (these can be null, so handle that elsewhere)
|
||||||
|
public string textSpeed;
|
||||||
|
public float volume;
|
||||||
|
|
||||||
|
//private internal members
|
||||||
|
static bool initialized = false; //BUGFIX: stack overflow
|
||||||
|
static string dataPath;
|
||||||
|
|
||||||
|
//methods
|
||||||
|
private ConfigurationManager(string fname) {
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = true;
|
||||||
|
LoadData(fname);
|
||||||
|
dataPath = fname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CleanUp() {
|
||||||
|
SaveData(Instance, dataPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadData(string fname) {
|
||||||
|
if (!File.Exists(fname)) {
|
||||||
|
singletonObject = JsonUtility.FromJson<ConfigurationManager> ("{}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamReader streamReader = File.OpenText(fname);
|
||||||
|
string jsonString = streamReader.ReadToEnd();
|
||||||
|
streamReader.Close();
|
||||||
|
singletonObject = JsonUtility.FromJson<ConfigurationManager> (jsonString);
|
||||||
|
|
||||||
|
//reset statics
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveData(ConfigurationManager configMgr, string fname) {
|
||||||
|
string jsonString = JsonUtility.ToJson(configMgr);
|
||||||
|
StreamWriter streamWriter = File.CreateText(fname);
|
||||||
|
streamWriter.Write(jsonString);
|
||||||
|
streamWriter.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class PauseManager {
|
||||||
|
//singleton members
|
||||||
|
private static PauseManager singletonObject = null;
|
||||||
|
public static PauseManager Instance {
|
||||||
|
get {
|
||||||
|
if (singletonObject != null) {
|
||||||
|
return singletonObject;
|
||||||
|
} else {
|
||||||
|
return singletonObject = new PauseManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
singletonObject = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//paused controller
|
||||||
|
bool paused = false;
|
||||||
|
public bool Paused {
|
||||||
|
get {
|
||||||
|
return paused;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
paused = value;
|
||||||
|
TriggerLists();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void CallbackHandler();
|
||||||
|
|
||||||
|
List<CallbackHandler> onPausedList = new List<CallbackHandler>();
|
||||||
|
List<CallbackHandler> onResumeList = new List<CallbackHandler>();
|
||||||
|
|
||||||
|
private PauseManager() {}
|
||||||
|
|
||||||
|
public void PushOnPaused(CallbackHandler callback) {
|
||||||
|
onPausedList.Add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PushOnResume(CallbackHandler callback) {
|
||||||
|
onResumeList.Add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PurgeLists() {
|
||||||
|
onPausedList.Clear();
|
||||||
|
onResumeList.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriggerLists() {
|
||||||
|
if (Paused) {
|
||||||
|
foreach(CallbackHandler callback in onPausedList) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foreach(CallbackHandler callback in onResumeList) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class SaveFileManager {
|
||||||
|
//public structures
|
||||||
|
[Serializable()]
|
||||||
|
public class SaveSlot {
|
||||||
|
//serializable fields (these can be null, so handle that elsewhere)
|
||||||
|
public string currentLocation; //name of the pedestal
|
||||||
|
public float secondsPlaying;
|
||||||
|
public string awardImage; //TODO: award image
|
||||||
|
|
||||||
|
//abilities
|
||||||
|
public bool flameBody;
|
||||||
|
public bool chargeSwipe;
|
||||||
|
public bool wallSlide;
|
||||||
|
public bool flameProjectile;
|
||||||
|
public bool flameWings;
|
||||||
|
}
|
||||||
|
|
||||||
|
//singleton members
|
||||||
|
private static SaveFileManager singletonObject = null;
|
||||||
|
public static SaveFileManager Instance {
|
||||||
|
get {
|
||||||
|
if (singletonObject == null) {
|
||||||
|
singletonObject = new SaveFileManager();
|
||||||
|
}
|
||||||
|
return singletonObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//private internal members
|
||||||
|
//
|
||||||
|
|
||||||
|
private SaveFileManager() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//public members
|
||||||
|
public static string saveSlotFileName; //NOT part of the save structure; only one can be loaded into the game at a time
|
||||||
|
public static SaveSlot LoadedSaveSlot { get; set; }
|
||||||
|
|
||||||
|
//methods
|
||||||
|
public static SaveSlot LoadData(string fname) {
|
||||||
|
if (!File.Exists(fname)) {
|
||||||
|
return JsonUtility.FromJson<SaveSlot> ("{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamReader streamReader = File.OpenText(fname);
|
||||||
|
string jsonString = streamReader.ReadToEnd();
|
||||||
|
streamReader.Close();
|
||||||
|
|
||||||
|
return JsonUtility.FromJson<SaveSlot> (jsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SaveData(SaveSlot save, string fname) {
|
||||||
|
string jsonString = JsonUtility.ToJson(save);
|
||||||
|
|
||||||
|
StreamWriter streamWriter = File.CreateText(fname);
|
||||||
|
streamWriter.Write(jsonString);
|
||||||
|
streamWriter.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SaveSlot CreateBlankSaveSlot() {
|
||||||
|
SaveSlot saveSlot = new SaveSlot();
|
||||||
|
|
||||||
|
saveSlot.currentLocation = "Start";
|
||||||
|
saveSlot.secondsPlaying = 0f;
|
||||||
|
saveSlot.awardImage = "";
|
||||||
|
|
||||||
|
saveSlot.flameBody = false;
|
||||||
|
saveSlot.chargeSwipe = false;
|
||||||
|
saveSlot.wallSlide = false;
|
||||||
|
saveSlot.flameProjectile = false;
|
||||||
|
saveSlot.flameWings = false;
|
||||||
|
|
||||||
|
return saveSlot;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using SpriterDotNetUnity;
|
||||||
|
|
||||||
|
//DOCS: this is intended for Ember's foot step sounds
|
||||||
|
|
||||||
|
public class PlayerAudio : MonoBehaviour {
|
||||||
|
//public members
|
||||||
|
public AudioClip[] leftFootsteps;
|
||||||
|
public AudioClip[] rightFootsteps;
|
||||||
|
public AudioClip jumpSound;
|
||||||
|
public AudioClip landSound;
|
||||||
|
|
||||||
|
//internal members
|
||||||
|
GameObject spriteObject;
|
||||||
|
UnityAnimator animator;
|
||||||
|
AudioSource audioSource;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
audioSource = GetComponent<AudioSource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
//spriter object is handled as an animation
|
||||||
|
HandleAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is called once per frame
|
||||||
|
void HandleAnimation() {
|
||||||
|
if (spriteObject == null) {
|
||||||
|
foreach (Transform child in transform) {
|
||||||
|
if (child.name == "Ember") {
|
||||||
|
spriteObject = child.gameObject;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animator == null && spriteObject != null) {
|
||||||
|
animator = spriteObject.GetComponent<SpriterDotNetBehaviour>().Animator;
|
||||||
|
animator.EventTriggered += AudioTriggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioTriggers(string name) {
|
||||||
|
switch(name) {
|
||||||
|
case "S: footstep left":
|
||||||
|
audioSource.PlayOneShot(leftFootsteps[PickASlot(leftFootsteps.Length)]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "S: footstep right":
|
||||||
|
audioSource.PlayOneShot(rightFootsteps[PickASlot(rightFootsteps.Length)]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "S: jump":
|
||||||
|
audioSource.PlayOneShot(jumpSound);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "S: land":
|
||||||
|
audioSource.PlayOneShot(landSound);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int PickASlot(int length) {
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
if (Random.Range(0, 2) == 0) return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Startups {
|
||||||
|
public class Debugger : MonoBehaviour {
|
||||||
|
AudioController audioController;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
audioController = Object.FindObjectOfType(typeof(AudioController)) as AudioController;
|
||||||
|
|
||||||
|
audioController.Load("rockstar", "Audio/Music/EngineTest");
|
||||||
|
audioController.Load("forest_ambience", "Audio/Music/Forest_Ambience");
|
||||||
|
audioController.Load("forest_background", "Audio/Music/Forest_Background");
|
||||||
|
|
||||||
|
audioController.Play("rockstar", AudioController.Mode.JUMP, 5f, 15);
|
||||||
|
|
||||||
|
// StartCoroutine(DebugLoopMusic(10f));
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator DebugLoopMusic(float duration) {
|
||||||
|
for(;;) {
|
||||||
|
audioController.PauseFadeOutAll(3f, new List<string> {"forest_background"});
|
||||||
|
audioController.UnpauseFadeIn("forest_background", 3f, AudioController.Mode.LOOP);
|
||||||
|
yield return new WaitForSeconds(duration);
|
||||||
|
audioController.PauseFadeOutAll(3f, new List<string> {"forest_ambience"});
|
||||||
|
audioController.UnpauseFadeIn("forest_ambience", 3f, AudioController.Mode.LOOP);
|
||||||
|
yield return new WaitForSeconds(duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
//DOCS: http://wiki.unity3d.com/index.php/FramesPerSecond
|
||||||
|
|
||||||
|
namespace Startups {
|
||||||
|
public class FPSDisplay : MonoBehaviour {
|
||||||
|
float deltaTime = 0.0f;
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
deltaTime += (Time.unscaledDeltaTime - deltaTime) * 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnGUI() {
|
||||||
|
int w = Screen.width, h = Screen.height;
|
||||||
|
|
||||||
|
GUIStyle style = new GUIStyle();
|
||||||
|
|
||||||
|
Rect rect = new Rect(0, 0, w, h * 2 / 100);
|
||||||
|
style.alignment = TextAnchor.UpperLeft;
|
||||||
|
style.fontSize = h * 2 / 100;
|
||||||
|
style.normal.textColor = new Color (0.0f, 0.0f, 0.5f, 1.0f);
|
||||||
|
float msec = deltaTime * 1000.0f;
|
||||||
|
float fps = 1.0f / deltaTime;
|
||||||
|
string text = string.Format("{0:0.0} ms ({1:0.} fps)", msec, fps);
|
||||||
|
GUI.Label(rect, text, style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Startups {
|
||||||
|
public class PauseMenuHandler : MonoBehaviour {
|
||||||
|
public Canvas pauseMenuCanvas;
|
||||||
|
public Canvas optionsMenuCanvas;
|
||||||
|
public Canvas saveMenuCanvas;
|
||||||
|
|
||||||
|
PauseManager pauseManager;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
pauseManager = PauseManager.Instance;
|
||||||
|
pauseManager.Paused = false;
|
||||||
|
|
||||||
|
pauseManager.PushOnPaused(() => {
|
||||||
|
pauseMenuCanvas.gameObject.SetActive(true);
|
||||||
|
Time.timeScale = 0f;
|
||||||
|
});
|
||||||
|
|
||||||
|
pauseManager.PushOnResume(() => {
|
||||||
|
pauseMenuCanvas.gameObject.SetActive(false);
|
||||||
|
optionsMenuCanvas.gameObject.SetActive(false);
|
||||||
|
saveMenuCanvas.gameObject.SetActive(false);
|
||||||
|
Time.timeScale = 1f;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy() {
|
||||||
|
pauseManager.PurgeLists();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
if (GamePad.GetState().Pressed(CButton.Start)) {
|
||||||
|
pauseManager.Paused = !pauseManager.Paused;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class SaveHandler : MonoBehaviour {
|
||||||
|
public GameObject playerObject;
|
||||||
|
public Dictionary<string, Structures.Pedestal> pedestalDictionary = new Dictionary<string, Structures.Pedestal>();
|
||||||
|
|
||||||
|
public bool saveMenuAvailable = false;
|
||||||
|
|
||||||
|
public float startTime = 0f;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
//create the save file if it doesn't exist
|
||||||
|
if (SaveFileManager.LoadedSaveSlot == null) {
|
||||||
|
SaveFileManager.saveSlotFileName = Path.Combine(Application.persistentDataPath, DateTime.Now.ToString("yyyyMMddTHHmmss") + ".sav");
|
||||||
|
SaveFileManager.LoadedSaveSlot = SaveFileManager.CreateBlankSaveSlot();
|
||||||
|
|
||||||
|
// SaveFileManager.SaveData(SaveFileManager.LoadedSaveSlot, SaveFileManager.saveSlotFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//initialize the game world with the given save data
|
||||||
|
startTime = Time.time;
|
||||||
|
|
||||||
|
//convert the array into a quick-search dictionary
|
||||||
|
Structures.Pedestal[] pedestals = GameObject.FindObjectsOfType<Structures.Pedestal>();
|
||||||
|
foreach(Structures.Pedestal pedestal in pedestals) {
|
||||||
|
pedestal.SaveHandler = this;
|
||||||
|
pedestalDictionary[pedestal.name] = pedestal;
|
||||||
|
}
|
||||||
|
|
||||||
|
//place the player on their saved pedestal
|
||||||
|
playerObject.transform.position = pedestalDictionary[SaveFileManager.LoadedSaveSlot.currentLocation].gameObject.transform.position;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Startups {
|
||||||
|
public class ConfigHandler : MonoBehaviour {
|
||||||
|
void OnDestroy() {
|
||||||
|
ConfigurationManager.Instance.CleanUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
//Must include Spriter Namespace
|
||||||
|
using SpriterDotNetUnity;
|
||||||
|
|
||||||
|
enum animationMode
|
||||||
|
{
|
||||||
|
lookUp,
|
||||||
|
lookDown,
|
||||||
|
move,
|
||||||
|
straightJump,
|
||||||
|
rollingJump,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EmberAnimationCycle : MonoBehaviour
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Instead of putting the script on Spriter's automatically generated prefab, which will cause it to be unset every
|
||||||
|
* time Evan tweaks the damn animations, we put the control scripts on a seperate gameobject which becomes a parent
|
||||||
|
* of the Spriter prefab and take a reference to the Spriter object so we can manipulate it.
|
||||||
|
*/
|
||||||
|
public GameObject Ember;
|
||||||
|
|
||||||
|
// This is the actual thing we use to animate the character.
|
||||||
|
UnityAnimator anim;
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool slash = false;
|
||||||
|
animationMode mode = animationMode.lookUp;
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (Ember == null)
|
||||||
|
{
|
||||||
|
foreach (Transform child in transform)
|
||||||
|
{
|
||||||
|
if (child.name == "Ember") { Ember = child.gameObject; break;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anim == null)
|
||||||
|
{
|
||||||
|
anim = Ember.GetComponent<SpriterDotNetBehaviour>().Animator;
|
||||||
|
//This event is fired whenever an animation ends.
|
||||||
|
anim.AnimationFinished += animationTransitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.anyKeyDown)
|
||||||
|
{
|
||||||
|
//Advance the animation.
|
||||||
|
if (anim.CurrentAnimation.Name == "Statue") anim.Play("Statue to Idle");
|
||||||
|
else if (anim.CurrentAnimation.Name == "Idle")
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case animationMode.move:
|
||||||
|
anim.Play("Idle to Walk");
|
||||||
|
mode = animationMode.straightJump;
|
||||||
|
break;
|
||||||
|
case animationMode.straightJump:
|
||||||
|
anim.Play("Begin Straight Jump");
|
||||||
|
mode = animationMode.rollingJump;
|
||||||
|
break;
|
||||||
|
case animationMode.rollingJump:
|
||||||
|
anim.Play("Begin Rolling Jump");
|
||||||
|
mode = animationMode.lookUp;
|
||||||
|
break;
|
||||||
|
case animationMode.lookUp:
|
||||||
|
if (!slash)
|
||||||
|
{
|
||||||
|
anim.Play("Grounded Forward Slash");
|
||||||
|
slash = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slash = false;
|
||||||
|
anim.Play("Idle to Lookup");
|
||||||
|
mode = animationMode.lookDown;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case animationMode.lookDown:
|
||||||
|
anim.Play("Idle to Crouch");
|
||||||
|
mode = animationMode.move;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (anim.CurrentAnimation.Name == "Walk") anim.Play("Run");
|
||||||
|
else if (anim.CurrentAnimation.Name == "Run") anim.Play("Idle");
|
||||||
|
else if (anim.CurrentAnimation.Name == "Straight Jump Rising")
|
||||||
|
{
|
||||||
|
if (!slash)
|
||||||
|
{
|
||||||
|
anim.Play("Airborn Upward Slash");
|
||||||
|
slash = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
anim.Play("Straight Jump Crest");
|
||||||
|
slash = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (anim.CurrentAnimation.Name == "Straight Jump Falling"
|
||||||
|
|| anim.CurrentAnimation.Name == "Rolling Jump")
|
||||||
|
{
|
||||||
|
if (!slash)
|
||||||
|
{
|
||||||
|
if (anim.CurrentAnimation.Name == "Straight Jump Falling") anim.Play("Airborn Forward Slash");
|
||||||
|
else anim.Play("Airborn Downward Slash");
|
||||||
|
slash = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
anim.Play("Straight Jump Landing");
|
||||||
|
slash = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (anim.CurrentAnimation.Name == "Crouch") anim.Play("Crouch to Idle");
|
||||||
|
else if (anim.CurrentAnimation.Name == "Lookup")
|
||||||
|
{
|
||||||
|
if (!slash)
|
||||||
|
{
|
||||||
|
anim.Play("Grounded Upward Slash");
|
||||||
|
slash = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
anim.Play("Lookup to Idle");
|
||||||
|
slash = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void animationTransitions(string name)
|
||||||
|
{
|
||||||
|
//We check to see if it's one of our transition animations and if so advance to the animation
|
||||||
|
// we are transitioning to.
|
||||||
|
if (name == "Statue to Idle") anim.Play("Idle");
|
||||||
|
else if (name == "Idle to Walk") anim.Play("Walk");
|
||||||
|
else if (name == "Begin Straight Jump") anim.Play("Straight Jump Rising");
|
||||||
|
else if (name == "Straight Jump Crest") anim.Play("Straight Jump Falling");
|
||||||
|
else if (name == "Begin Rolling Jump") anim.Play("Rolling Jump");
|
||||||
|
else if (name == "Straight Jump Landing") anim.Play("Idle");
|
||||||
|
else if (name == "Idle to Crouch") anim.Play("Crouch");
|
||||||
|
else if (name == "Crouch to Idle") anim.Play("Idle");
|
||||||
|
else if (name == "Idle to Lookup") anim.Play("Lookup");
|
||||||
|
else if (name == "Lookup to Idle") anim.Play("Idle");
|
||||||
|
else if (name == "Grounded Forward Slash") anim.Play("Idle");
|
||||||
|
else if (name == "Grounded Upward Slash") anim.Play("Lookup");
|
||||||
|
else if (name == "Airborn Upward Slash") anim.Play("Straight Jump Rising");
|
||||||
|
else if (name == "Airborn Forward Slash") anim.Play("Straight Jump Falling");
|
||||||
|
else if (name == "Airborn Downward Slash") anim.Play("Rolling Jump");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using TMPro;
|
||||||
|
|
||||||
|
namespace DialogSystem {
|
||||||
|
public class DialogCanvas : MonoBehaviour {
|
||||||
|
//public access references
|
||||||
|
public Image dialogPanel;
|
||||||
|
public TextMeshProUGUI dialogText;
|
||||||
|
|
||||||
|
//internal variables
|
||||||
|
bool visible;
|
||||||
|
List<string> internalTextList;
|
||||||
|
|
||||||
|
//fine-tuning the interface
|
||||||
|
float speed = 0.25f;
|
||||||
|
float speedCharCount = 0;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
SetVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
if (!PauseManager.Instance.Paused && visible) {
|
||||||
|
HandleInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedUpdate() {
|
||||||
|
if (visible) {
|
||||||
|
ProcessSpeed();
|
||||||
|
ProcessText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetVisible(bool b) {
|
||||||
|
visible = b;
|
||||||
|
|
||||||
|
dialogPanel.gameObject.SetActive(visible);
|
||||||
|
dialogText.gameObject.SetActive(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetVisible() {
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetText(List<string> stringList, bool setVisible = true) {
|
||||||
|
internalTextList = stringList;
|
||||||
|
dialogText.text = "";
|
||||||
|
SetVisible(setVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleInput() {
|
||||||
|
if (GamePad.GetState().Pressed(CButton.A)) {
|
||||||
|
if (internalTextList[0].Length > speedCharCount) {
|
||||||
|
//skip the text scroll
|
||||||
|
speedCharCount = internalTextList[0].Length;
|
||||||
|
} else {
|
||||||
|
//skip to the next "page"
|
||||||
|
internalTextList.RemoveAt(0);
|
||||||
|
speedCharCount = 0;
|
||||||
|
|
||||||
|
//if there isn't another "page", go dormant
|
||||||
|
if (internalTextList.Count == 0) {
|
||||||
|
SetVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessSpeed() {
|
||||||
|
switch(ConfigurationManager.Instance.textSpeed) {
|
||||||
|
case "Fast":
|
||||||
|
speed = 1f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Normal":
|
||||||
|
speed = 0.25f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Slow":
|
||||||
|
speed = 0.1f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessText() {
|
||||||
|
//if the list of text has run out
|
||||||
|
if (internalTextList.Count == 0) {
|
||||||
|
SetVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetVisible(true);
|
||||||
|
|
||||||
|
//only show the first "speedCharCount" characters
|
||||||
|
string thisLine = internalTextList[0];
|
||||||
|
if (speedCharCount >= thisLine.Length) {
|
||||||
|
dialogText.text = thisLine;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
speedCharCount += speed;
|
||||||
|
thisLine = thisLine.Substring(0, (int)Mathf.Floor(speedCharCount));
|
||||||
|
|
||||||
|
dialogText.text = thisLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
public class HUDCanvas : MonoBehaviour {
|
||||||
|
//public access members
|
||||||
|
public Sprite[] sparkSprites;
|
||||||
|
public Sprite[] flameSprites;
|
||||||
|
|
||||||
|
//public properties
|
||||||
|
int _sparkLevel = 0;
|
||||||
|
public int SparkLevel {
|
||||||
|
get {
|
||||||
|
return _sparkLevel;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_sparkLevel = value;
|
||||||
|
if (_sparkLevel < 0) {
|
||||||
|
_sparkLevel = 0;
|
||||||
|
}
|
||||||
|
if (_sparkLevel > sparkSprites.Length * (flameSprites.Length - 1)) {
|
||||||
|
_sparkLevel = sparkSprites.Length * (flameSprites.Length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int FlameLevel {
|
||||||
|
get {
|
||||||
|
return _sparkLevel / sparkSprites.Length;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_sparkLevel = value * sparkSprites.Length + _sparkLevel % sparkSprites.Length;
|
||||||
|
while(_sparkLevel < 0) {
|
||||||
|
_sparkLevel += sparkSprites.Length;
|
||||||
|
}
|
||||||
|
while(_sparkLevel > sparkSprites.Length * (flameSprites.Length - 1)) {
|
||||||
|
_sparkLevel -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//internal members
|
||||||
|
Image[] childImages;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
childImages = GetComponentsInChildren<Image>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
HandleGraphics();
|
||||||
|
DebugHandleInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleGraphics() {
|
||||||
|
childImages[0].sprite = sparkSprites[SparkLevel % sparkSprites.Length];
|
||||||
|
childImages[1].sprite = flameSprites[SparkLevel / sparkSprites.Length];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugHandleInput() {
|
||||||
|
if (Input.GetKeyDown("1")) {
|
||||||
|
SparkLevel--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKeyDown("2")) {
|
||||||
|
SparkLevel++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKeyDown("3")) {
|
||||||
|
FlameLevel--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKeyDown("4")) {
|
||||||
|
FlameLevel++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class ConfirmDelete : MenuOption {
|
||||||
|
//public access members
|
||||||
|
public string fileName;
|
||||||
|
public GameObject loadCanvas;
|
||||||
|
public GameObject confirmationCanvas;
|
||||||
|
|
||||||
|
public override void Execute() {
|
||||||
|
File.Delete(fileName);
|
||||||
|
confirmationCanvas.SetActive(false);
|
||||||
|
loadCanvas.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Scroll(float x) {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class ConfirmLoad : MenuOption {
|
||||||
|
//public access members
|
||||||
|
public SaveFileManager.SaveSlot saveData;
|
||||||
|
public string fileName;
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
if (transform.childCount > 0) {
|
||||||
|
//BUGFIX: I don't know why this is disabled here
|
||||||
|
transform.GetChild(0).GetComponent<Image>().enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute() {
|
||||||
|
SaveFileManager.saveSlotFileName = fileName;
|
||||||
|
SaveFileManager.LoadedSaveSlot = saveData;
|
||||||
|
SceneManager.LoadScene("Gameplay");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Scroll(float x) {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class LoadCanvas : MonoBehaviour {
|
||||||
|
//public access members
|
||||||
|
public GameObject saveSlotPrefab;
|
||||||
|
public GameObject confirmationCanvas;
|
||||||
|
|
||||||
|
void OnEnable() {
|
||||||
|
//load the save objects
|
||||||
|
DirectoryInfo info = new DirectoryInfo(Application.persistentDataPath);
|
||||||
|
|
||||||
|
//create the load menu
|
||||||
|
foreach(var file in info.GetFiles("*.sav")) {
|
||||||
|
GameObject saveSlot = Instantiate(saveSlotPrefab) as GameObject;
|
||||||
|
saveSlot.transform.SetParent(transform); //BUGFIX: unity bug
|
||||||
|
saveSlot.GetComponent<SaveSlot>().SetSaveSlotInfo(SaveFileManager.LoadData(file.FullName));
|
||||||
|
|
||||||
|
saveSlot.GetComponent<SaveSlot>().fileName = file.FullName;
|
||||||
|
saveSlot.GetComponent<SaveSlot>().loadCanvas = transform.gameObject;
|
||||||
|
saveSlot.GetComponent<SaveSlot>().confirmationCanvas = confirmationCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Move the "back" option to the bottom
|
||||||
|
transform.GetChild(0).SetAsLastSibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisable() {
|
||||||
|
foreach (Transform child in transform) {
|
||||||
|
if (child.GetComponent<SaveSlot>() != null) {
|
||||||
|
GameObject.Destroy(child.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using TMPro;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class SaveSlot : MenuOption {
|
||||||
|
public string fileName;
|
||||||
|
public GameObject loadCanvas;
|
||||||
|
public GameObject confirmationCanvas;
|
||||||
|
|
||||||
|
//private access members
|
||||||
|
SaveFileManager.SaveSlot saveData;
|
||||||
|
|
||||||
|
public void SetSaveSlotInfo(SaveFileManager.SaveSlot saveSlot) {
|
||||||
|
TextMeshProUGUI[] texts = GetComponentsInChildren<TextMeshProUGUI>(true);
|
||||||
|
|
||||||
|
texts[0].text = saveSlot.currentLocation;
|
||||||
|
|
||||||
|
TimeSpan time = TimeSpan.FromSeconds(saveSlot.secondsPlaying);
|
||||||
|
texts[1].text = time.ToString(@"hh\:mm\:ss");
|
||||||
|
|
||||||
|
saveData = saveSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute() {
|
||||||
|
//show a confirmation canvas
|
||||||
|
confirmationCanvas.transform.GetChild(0).GetComponent<ConfirmLoad>().saveData = saveData;
|
||||||
|
confirmationCanvas.transform.GetChild(0).GetComponent<ConfirmLoad>().fileName = fileName;
|
||||||
|
confirmationCanvas.transform.GetChild(1).GetComponent<ConfirmDelete>().fileName = fileName;
|
||||||
|
|
||||||
|
//BUGFIX: move the cursor somewhere safe
|
||||||
|
transform.Find("Cursor").SetParent(confirmationCanvas.transform.GetChild(0));
|
||||||
|
|
||||||
|
//BUGFIX: wait a frame to show the confirmation page, to make sure the cursor is safe
|
||||||
|
StartCoroutine(DoStuffNextFrame());
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator DoStuffNextFrame() {
|
||||||
|
yield return null;
|
||||||
|
loadCanvas.SetActive(false);
|
||||||
|
confirmationCanvas.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Scroll(float x) {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
class Quit : MenuOption {
|
||||||
|
override public void Execute() {
|
||||||
|
Application.Quit();
|
||||||
|
Debug.Log("Quit called");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
class StartGame : MenuOption {
|
||||||
|
override public void Execute() {
|
||||||
|
SceneManager.LoadScene("Gameplay");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class MenuCanvas : MonoBehaviour {
|
||||||
|
//public access members
|
||||||
|
public Image cursorImage;
|
||||||
|
public bool floating = false;
|
||||||
|
|
||||||
|
//private members
|
||||||
|
MenuOption[] menuOptions = null;
|
||||||
|
|
||||||
|
//fine-tuned input
|
||||||
|
const float deadZone = 0.25f;
|
||||||
|
const float inputDelay = 0.5f;
|
||||||
|
const float scrollDelay = 0.1f;
|
||||||
|
float lastInputX = float.NegativeInfinity;
|
||||||
|
float lastInputY = float.NegativeInfinity;
|
||||||
|
|
||||||
|
void OnEnable() {
|
||||||
|
menuOptions = GetComponentsInChildren<MenuOption>();
|
||||||
|
|
||||||
|
//set up the cursor
|
||||||
|
menuOptions[0].hover = true;
|
||||||
|
RectTransform rt = cursorImage.GetComponent<RectTransform>();
|
||||||
|
rt.SetParent(menuOptions[0].transform);
|
||||||
|
rt.offsetMin = new Vector2(0, 0);
|
||||||
|
rt.offsetMax = new Vector2(0, 0);
|
||||||
|
|
||||||
|
HandleGraphics();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisable() {
|
||||||
|
//BUGFIX: reset this menu tree if closing the menu
|
||||||
|
foreach (Transform child in transform) {
|
||||||
|
child.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
//BUGFIX: remove all non-active elements
|
||||||
|
menuOptions = Array.FindAll(menuOptions, (MenuOption option) => option.gameObject.active);
|
||||||
|
|
||||||
|
HandleInput();
|
||||||
|
HandleGraphics();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleInput() {
|
||||||
|
//press a button
|
||||||
|
if (GamePad.GetState().Pressed(CButton.A)) {
|
||||||
|
foreach(MenuOption option in menuOptions) {
|
||||||
|
if (option.hover) {
|
||||||
|
option.Execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//scroll left or right
|
||||||
|
if (Mathf.Abs(GamePad.GetAxis(CAxis.LX)) >= deadZone && Time.unscaledTime - lastInputX > scrollDelay) {
|
||||||
|
lastInputX = Time.unscaledTime;
|
||||||
|
|
||||||
|
foreach(MenuOption option in menuOptions) {
|
||||||
|
if (option.hover) {
|
||||||
|
option.Scroll(GamePad.GetAxis(CAxis.LX));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//keyboard/gamepad scroll up
|
||||||
|
if (GamePad.GetAxis(CAxis.LY) < -deadZone && Time.unscaledTime - lastInputY > inputDelay) {
|
||||||
|
lastInputY = Time.unscaledTime;
|
||||||
|
|
||||||
|
//move the cursor one up
|
||||||
|
for (int i = 1; i < menuOptions.Length; i++) {
|
||||||
|
//find the current hovered item
|
||||||
|
if (menuOptions[i].hover) {
|
||||||
|
//move the hover up
|
||||||
|
menuOptions[i].hover = false;
|
||||||
|
menuOptions[i-1].hover = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//keyboard/gamepad scroll down
|
||||||
|
if (GamePad.GetAxis(CAxis.LY) > deadZone && Time.unscaledTime - lastInputY > inputDelay) {
|
||||||
|
lastInputY = Time.unscaledTime;
|
||||||
|
|
||||||
|
//move the cursor one down
|
||||||
|
for (int i = 0; i < menuOptions.Length - 1; i++) {
|
||||||
|
//find the current hovered item
|
||||||
|
if (menuOptions[i].hover) {
|
||||||
|
//move the hover down
|
||||||
|
menuOptions[i].hover = false;
|
||||||
|
menuOptions[i+1].hover = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//deadzone reset lastInputX
|
||||||
|
if (Mathf.Abs(GamePad.GetAxis(CAxis.LX)) < deadZone) {
|
||||||
|
lastInputX = float.NegativeInfinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
//deadzone reset lastInputY
|
||||||
|
if (Mathf.Abs(GamePad.GetAxis(CAxis.LY)) < deadZone) {
|
||||||
|
lastInputY = float.NegativeInfinity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleGraphics() {
|
||||||
|
bool hoverSet = false;
|
||||||
|
|
||||||
|
//update the graphics
|
||||||
|
foreach(MenuOption option in menuOptions) {
|
||||||
|
if (option.hover) {
|
||||||
|
if (hoverSet) {
|
||||||
|
option.hover = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RectTransform rt = cursorImage.GetComponent<RectTransform>();
|
||||||
|
rt.SetParent(option.transform);
|
||||||
|
rt.anchorMin = new Vector2(0, 0);
|
||||||
|
rt.anchorMax = new Vector2(1, 1);
|
||||||
|
rt.offsetMin = new Vector2(0, 0);
|
||||||
|
rt.offsetMax = new Vector2(0, 0);
|
||||||
|
hoverSet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (floating) {
|
||||||
|
float offset = cursorImage.transform.position.y - Screen.height / 2;
|
||||||
|
transform.position = new Vector2(transform.position.x, transform.position.y - offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class MenuOption : MonoBehaviour {
|
||||||
|
//if this option is being hovered over, logically
|
||||||
|
public bool hover = false;
|
||||||
|
|
||||||
|
public virtual void Execute() {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Scroll(float x) {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using TMPro;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class TextSpeed : MenuOption {
|
||||||
|
//component references
|
||||||
|
ConfigurationManager configManager;
|
||||||
|
TextMeshProUGUI text;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
configManager = ConfigurationManager.Instance;
|
||||||
|
text = GetComponent<TextMeshProUGUI>();
|
||||||
|
configManager.textSpeed = (configManager.textSpeed != null && configManager.textSpeed != "" ? configManager.textSpeed : "Normal");
|
||||||
|
text.text = configManager.textSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
override public void Execute() {
|
||||||
|
switch(configManager.textSpeed) {
|
||||||
|
case "Normal":
|
||||||
|
configManager.textSpeed = "Slow";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Slow":
|
||||||
|
configManager.textSpeed = "Fast";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Fast":
|
||||||
|
configManager.textSpeed = "Normal";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
text.text = configManager.textSpeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using TMPro;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class Volume : MenuOption {
|
||||||
|
//component references
|
||||||
|
ConfigurationManager configManager;
|
||||||
|
TextMeshProUGUI text;
|
||||||
|
|
||||||
|
void Start() {
|
||||||
|
configManager = ConfigurationManager.Instance;
|
||||||
|
text = GetComponent<TextMeshProUGUI>();
|
||||||
|
configManager.volume = (configManager.volume != null && configManager.volume != 0 ? configManager.volume : 100f);
|
||||||
|
text.text = configManager.volume.ToString();
|
||||||
|
|
||||||
|
UpdateMasterVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Execute() {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Scroll(float x) {
|
||||||
|
//DO NOTHING
|
||||||
|
configManager.volume += x;
|
||||||
|
|
||||||
|
configManager.volume = Mathf.Clamp(configManager.volume, 0f, 100f);
|
||||||
|
|
||||||
|
text.text = configManager.volume.ToString();
|
||||||
|
|
||||||
|
UpdateMasterVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateMasterVolume() {
|
||||||
|
AudioListener.volume = configManager.volume / 100f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class QuitToMainMenu : MenuOption {
|
||||||
|
public override void Execute() {
|
||||||
|
SceneManager.LoadScene("MainMenu");
|
||||||
|
PauseManager.Instance.Paused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class ReturnToGame : MenuOption {
|
||||||
|
public override void Execute() {
|
||||||
|
PauseManager.Instance.Paused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
using TMPro;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class Heading : MonoBehaviour {
|
||||||
|
void Start() {
|
||||||
|
TextMeshProUGUI text = GetComponent<TextMeshProUGUI>();
|
||||||
|
|
||||||
|
if (!File.Exists(SaveFileManager.saveSlotFileName)) {
|
||||||
|
text.text = "Save The Game?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class HideMeIf : MonoBehaviour {
|
||||||
|
public SaveHandler saveHandler;
|
||||||
|
|
||||||
|
void OnEnable() {
|
||||||
|
if (!saveHandler.saveMenuAvailable) {
|
||||||
|
gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
public class SaveGame : MenuOption {
|
||||||
|
public SaveHandler saveHandler;
|
||||||
|
|
||||||
|
public Canvas oldMenu;
|
||||||
|
public Canvas newMenu;
|
||||||
|
|
||||||
|
public override void Execute() {
|
||||||
|
//calculate playtime
|
||||||
|
SaveFileManager.LoadedSaveSlot.secondsPlaying += Time.time - saveHandler.startTime;
|
||||||
|
saveHandler.startTime = Time.time;
|
||||||
|
|
||||||
|
//save the game
|
||||||
|
SaveFileManager.SaveData(SaveFileManager.LoadedSaveSlot, SaveFileManager.saveSlotFileName);
|
||||||
|
oldMenu.gameObject.SetActive(false);
|
||||||
|
newMenu.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Scroll(float x) {
|
||||||
|
//DO NOTHING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace MenuSystem {
|
||||||
|
class SwitchMenus : MenuOption {
|
||||||
|
public Canvas oldMenu;
|
||||||
|
public Canvas newMenu;
|
||||||
|
|
||||||
|
override public void Execute() {
|
||||||
|
oldMenu.gameObject.SetActive(false);
|
||||||
|
newMenu.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 245 B |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 162 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 162 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 162 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 157 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 158 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 162 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 159 KiB |