Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/refupanker/the_2d_ski_game

the 2D Ski Game with unity csharp
https://github.com/refupanker/the_2d_ski_game

Last synced: about 2 months ago
JSON representation

the 2D Ski Game with unity csharp

Awesome Lists containing this project

README

        

# Ski Game
_[by 27-45 / LostMoon Games]_

Gameplay
Documentation

Gameplay


Menu : Start



Menu : Settings



Menu : Level Completed



Menu : Game Over



In Game : First Step



In Game : Landing after jump



In Game : Checkpoints


Back to top

Documentation

- [Player](#player)
- [Ground Checker](#groundchecker)
- [Hearts Controller](#heartscontroller)
- [Panoramic Background](#panorama)
- [Checkpoints System](#checkpoints)
- [Random ground generating](#groundgenerater)


Player


Movement


uses rigidbody and adds force to move player smoothly

if (Input.GetKey(KeyCode.D)){
rb.AddForce(this.transform.right * moveSpeed);}

Back & Front Flip



if (Input.GetKey(KeyCode.S)){
//backflip
transform.Rotate(Vector3.forward * rotationForce * Time.deltaTime);
flipTime += 1;
}
if (Input.GetKey(KeyCode.W)){
//front flip
transform.Rotate(-Vector3.forward * rotationForce * Time.deltaTime);
flipTime += 1;}

Camera Scale


uses GroundChecker
throws laser and calculates player distance to ground
and changes field of view ;

calcFov.orthographicSize = Mathf.Lerp(calcFov.orthographicSize,
Mathf.Clamp(gc.distanceToGround, 5f, MaxCameraFov),
Time.deltaTime * 5f);


Align Camera


Camera follows user as smoothly

transform.position = Vector3.Lerp(transform.position,
new Vector3(target.position.x + CenterDistance,
target.position.y, transform.position.z),
smoothDelay);

Align player to ground


uses GroundChecker

transform.rotation = Quaternion.Lerp(transform.rotation,
Quaternion.FromToRotation(Vector3.up * Time.deltaTime, gc.rotater.normal),
3f * Time.deltaTime);


Head Controller


with unity api,we can detect collisions between objects.

we added CircleCollider to player 's head and used "OnCollisionEnter2D" method to detect collisions

playerHead might collide with player's body so we must check the collided object is ground layer

public bool hit { get; set; } // notify other objects
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.layer == LayerMask.NameToLayer("ground"))// check the layer is "ground"
{
hit = true;
}
}

Dash Controller


the speed boost for player , uses "E" key to activate dash for limited seconds
coroutines used for refill dash bar

if (CanDash)
{
StartCoroutine("UseDash");
CanDash = false;
for (int i = 0; i < 100; i++)
{
rb.AddForce(player.right * dashPower);
}
StartCoroutine("CountDown");
}
Back to top


Timer


How it works


the basic timer,increases time value(miliseconds) and converts to normal time for user interface

IEnumerator timerCounter()
{
if (player.CanMove)
{
time += 1;
label.text = GetAsUiTimeFormat();
}
yield return new WaitForSeconds(0.01f);
StartCoroutine(timerCounter());
}
public string GetAsUiTimeFormat(){
return FillZero((time / (60 * 60)) % 60) + ":" +
FillZero((time / (60)) % 60) + ":" +
FillZero(time % 100);
}
private string FillZero(int num){
return num < 10 ? "0" + num : num + "";
}
Back to top


Ground Checker


How it works


throws an laser from specified point to distance then returns objects by layer

displays distance as meter


RaycastHit2D hit = Physics2D.Raycast(
transform.position, // raycast start point
Vector2.down, // the direction
Mathf.Infinity, // max distance
layer); // layer (in this case : "ground")

Back to top


Hearths Controller


How it works


gets heart objects from user interface

in every start,refreshes hearts

responsible with GameOver Screen

plays animations and sounds for gameover screen

Player uses hearthsController

public void RemoveHeart()
{
if (getActiveHearts() <= 0)
{
player.CanMove = false;
gameOverScreen.SetActive(true);
}
else
{
hitSfx.Stop();
hitSfx.Play();
Animation anim = getNextActiveHeart().GetComponent();
anim.Play();
StartCoroutine(
waitToanimate(anim, () =>
{
getNextActiveHeart().gameObject.SetActive(false);
}));
}
}
Back to top


Panorama


How it works


panoramic view that adds more depth to game

made with 3 layer,moves with opposite velocity of player

the parent object holds instances of layers in horizontal direction

layers moves by distance scale to player

according to this formule : PlayerVelocity/DistanceScale

uses Player to get player speed

foreach (Transform item in this.transform)
{
item.Translate(-(velocity.velocity.x * Time.deltaTime / layerDistance), 0, 0);
}

Back to top


Checkpoints Controller


How it works


requires : instance of UI Checkpoint and InGame Checkpoints(Array)

uses start and end point to calculate total distance

calculates every ingame checkpoint object's distance to finish line

then converts to UI values

foreach (var item in CheckPoints)
{
float InWorldPercent = 100 * Vector2.Distance(item.transform.position, StartPoint.position) / finishDistance;
Transform NewUiCheckPoint = Instantiate(UiCheckpointInstance, UiCheckpointHolder);
float inUiPointX = UiDistanceSlider.rect.width * (InWorldPercent / 100);
NewUiCheckPoint.localPosition = new Vector2(inUiPointX, UiCheckpointInstance.position.y);
}

Back to top


Ground Generater


How it works


gets variables : width (points count) , points distance , points curve

and converts to path for sprite renderer

then sprite renderer fills the shape that created with points

public void ReStart(bool recheckpoint = false)
{
// clear previous objects
ssc = this.GetComponent();
ssc.spline.Clear();
foreach (Transform item in CheckpointsHolder)
{
Destroy(item.gameObject);
}

UiController.CheckPoints.Clear();

// add flat starting position for better landing
ssc.spline.InsertPointAt(0, Vector3.zero);
ssc.spline.InsertPointAt(1, new Vector3(HorizontalDistance, 0, 0));
AddCheckpoint(HorizontalDistance / 2, 0);

float l = HorizontalDistance * 2;
float minY = ssc.spline.GetPosition(0).y;
for (int i = 2; i <= Width; i++)
{
// calculate new Y point with previous Y point
float preY = ssc.spline.GetPosition(i - 1).y;
float t = Random.Range(preY - VerticalDistance, preY + VerticalDistance);
minY = (t < minY) ? t : minY;
ssc.spline.InsertPointAt(i, new Vector2(l, t));
l += HorizontalDistance;
if (i % perDistance == 0)
{
AddCheckpoint(ssc.spline.GetPosition(i).x, ssc.spline.GetPosition(i).y);
}
}

// turn back to first point with fill
Vector2 firstpoint = ssc.spline.GetPosition(0);
Vector2 lastpoint = ssc.spline.GetPosition(ssc.spline.GetPointCount() - 1);
ssc.spline.InsertPointAt(ssc.spline.GetPointCount(), new Vector2(lastpoint.x, minY - GroundFillDistance));
ssc.spline.InsertPointAt(0, new Vector2(firstpoint.x, minY - GroundFillDistance));
ssc.spline.InsertPointAt(ssc.spline.GetPointCount() - 1, new Vector2(finishLine.position.x - transform.position.x, finishLine.position.y - transform.position.y));
ssc.spline.InsertPointAt(ssc.spline.GetPointCount() - 1, new Vector2(finishLine.position.x - transform.position.x - HorizontalDistance * 2, finishLine.position.y - transform.position.y));

// adds curve between to points for better hill view
for (int i = 0; i < ssc.spline.GetPointCount(); i++)
{
ssc.spline.SetTangentMode(i, ShapeTangentMode.Continuous);
ssc.spline.SetLeftTangent(i, new Vector3(-PointCurve, 0, 0));
ssc.spline.SetRightTangent(i, new Vector3(PointCurve, 0, 0));
}

// update user interface checkpoints
if (recheckpoint)
{
UiController.ReplaceCheckpoints();
}
}
Back to top