using System.Collections; using System.Collections.Generic; using Photon.Pun; using UnityEngine; using UnityEngine.UIElements; public class SnakeController : MonoBehaviourPunCallbacks { public GameManager gameManager; public Vector2 startOffset = new Vector3(-10,-10); public float movingInterval = 0.2f; public Vector2 curDirection = Vector3.right; public List snakePieces = new List(); public List bends = new List(); public GameObject snakePiecePrefab; public int startingLength = 3; public Vector2 fieldSize= new Vector2(160,90); float moveTimer; public float topEdge => transform.position.y + fieldSize.y /2f; public float botEdge => transform.position.y - fieldSize.y /2f; public float leftEdge => transform.position.x - fieldSize.x /2f; public float rightEdge => transform.position.x + fieldSize.x /2f; void Start(){ snakePieces = new List(); for(int i=0; i < startingLength; i++){ Vector3 pos = ((Vector2)transform.position - startOffset)-(Vector2.right * i); GameObject newPiece = PhotonNetwork.Instantiate(snakePiecePrefab.name,pos, Quaternion.identity ); snakePieces.Add(newPiece.GetComponent()); } ButtonSet.OnUp +=OnUp; ButtonSet.OnDown +=OnDown; ButtonSet.OnLeft +=OnLeft; ButtonSet.OnRight+=OnRight; } private void OnDestroy() { ButtonSet.OnUp -=OnUp; ButtonSet.OnDown -=OnDown; ButtonSet.OnLeft -=OnLeft; ButtonSet.OnRight-=OnRight; } bool kickstarted = false; void Update() { CheckHead(); if(isDead){return;} Move(); ProcessInput(); } void ProcessInput(){ if(Input.GetKeyDown(KeyCode.RightArrow)){ OnRight(); }else if(Input.GetKeyDown(KeyCode.LeftArrow)){ OnLeft(); }else if(Input.GetKeyDown(KeyCode.UpArrow)){ OnUp(); }else if(Input.GetKeyDown(KeyCode.DownArrow)){ OnDown(); } } void OnRight(){ ChangeDir(Vector2.right); } void OnLeft(){ ChangeDir(-Vector2.right); } void OnUp(){ ChangeDir(Vector2.up); } void OnDown(){ ChangeDir(-Vector2.up); } public int Score; public void AddScore(int amount = 1){ Score+=amount; if(PhotonNetwork.LocalPlayer.CustomProperties.ContainsKey("score")){ PhotonNetwork.LocalPlayer.CustomProperties["score"]=Score; }else{ PhotonNetwork.LocalPlayer.CustomProperties.Add("score",Score); } PhotonNetwork.LocalPlayer.SetCustomProperties(PhotonNetwork.LocalPlayer.CustomProperties); } List moveInputQueue =new List(); void ChangeDir(Vector2 newDir){ if(curDirection == -newDir){ return; } moveInputQueue.Add(newDir); } bool queueNewPiece = false; void Move(){ if(moveTimer > 0){ moveTimer-=Time.deltaTime; }else{ moveTimer = movingInterval; if(moveInputQueue.Count >0){ Vector2 dir = Vector2.zero; if(curDirection.x != 0){ dir = new Vector2(-curDirection.x, moveInputQueue[0].y); }else{ dir = new Vector2(moveInputQueue[0].x, -curDirection.y); } curDirection = moveInputQueue[0]; moveInputQueue.RemoveAt(0); bends.Add(new BendData(){ position = snakePieces[0].transform.position, direction = dir }); } Vector2 curPosition = snakePieces[0].transform.position; Vector2 lastPosition = snakePieces[snakePieces.Count-1].transform.position; for(int i=snakePieces.Count-1; i>0; i--){ Vector3 dir = (snakePieces[i-1].transform.position - snakePieces[i].transform.position).normalized; snakePieces[i].direction = dir; snakePieces[i].isHead=false; snakePieces[i].transform.position = snakePieces[i-1].transform.position; snakePieces[i].transform.position = snakePieces[i].transform.position; BendData bendToRemove = null; foreach(BendData bend in bends){ if(bend.position == snakePieces[i].transform.position){ snakePieces[i].direction = bend.direction; if(i == snakePieces.Count-1){ bendToRemove = bend; } break; } } if(bendToRemove!=null){ bends.Remove(bendToRemove); } } if(queueNewPiece){ GameObject newPiece = PhotonNetwork.Instantiate(snakePiecePrefab.name,lastPosition, Quaternion.identity ); snakePieces.Add(newPiece.GetComponent()); AddScore(); queueNewPiece=false; } snakePieces[0].transform.position = curPosition + curDirection; snakePieces[0].direction = curDirection; snakePieces[0].isHead=true; if(snakePieces[0].transform.position.x > rightEdge){ snakePieces[0].transform.position= new Vector2(leftEdge,snakePieces[0].transform.position.y); }else if(snakePieces[0].transform.position.x topEdge){ snakePieces[0].transform.position = new Vector2(snakePieces[0].transform.position.x, botEdge); }else if(snakePieces[0].transform.position.y < botEdge){ snakePieces[0].transform.position = new Vector2(snakePieces[0].transform.position.x, topEdge); } } } bool isDead = false; void CheckHead(){ Collider2D[] obstacles = Physics2D.OverlapCircleAll(snakePieces[0].transform.position, 0.25f); foreach(Collider2D obstacle in obstacles){ if(obstacle.GetComponent()!=null){ if(obstacle.transform == snakePieces[0].transform){ }else{ Debug.Log($"Crashed into {obstacle.name}", gameObject); isDead = true; gameManager.OnGameOver(); } } if(obstacle.GetComponent()!=null){ queueNewPiece=true; gameManager.DestroyFruit(obstacle.transform.position); } } } private void OnDrawGizmos() { Gizmos.DrawWireCube(transform.position, new Vector3(fieldSize.x,fieldSize.y)); if(snakePieces.Count > 0){ Gizmos.DrawWireSphere(snakePieces[0].transform.position, 0.25f); } } } [System.Serializable] public class BendData{ public Vector3 position; public Vector2 direction; }