코육대 링크 : https://hanghaeplus-coyukdae.oopy.io/#1b467c7185e94a3295dc4a72a05ea3b2
항해 플러스: 제1회 코육대
이번 추석, 굳어버린 코딩 근육을 깨울 코딩 육상 대회가 왔다!
hanghaeplus-coyukdae.oopy.io
이번 추석 연휴 당시, 뭘 해볼까하고 여러 가지 찾아보다가 항해플러스에서 개최하는 코딩 육상 대회에 대해 알게 되었다.
연휴 때 계속 놀기보단 뭐라도 남기는 좋을 것 같아 가벼운 마음으로 참가해보기로 했다!
참가 부문은 총알 피하기로 결정했다!
개발 엔진으로는 유니티를 사용하기로 하였고, 이번 토이 프로젝트의 목표를 크게 세 가지로 잡았다!
1. '총알피하기' 에 충실한 싱글플레이 모드 구현
2. SQLite와 연동해 로컬 저장소를 만들어 랭킹시스템 구현
3. Photon Pun2 에셋을 이용해 멀티플레이 모드 구현
올해 초 개인적으로 SQLite와 Pun2를 이용해 간단한 토이 프로젝트를 진행한 적이 있었다.
이번 교육대를 계기로 총알 피하기를 제작하면서 공부한 내용을 다시 상기시킬 수 있어 매우 좋았다!
1. 총알피하기 싱글플레이 모드 구현
싱글플레이 모드는 라이프를 3개로 하였고, 3초마다 총알이 플레이어를 향해 날아오는 방식으로 만들었다.
아래 코드는 플레이어의 움직임을 구현한 SailMove.cs 파일이다.
싱글플레이 모드에서는 플레이어(1p)에 위 코드를 부착해 사용자의 입력을 Update()에서 처리하였다.
또한 OnTriggerEnter2D()를 이용해서 플레이어가 총알에 닿았을 때 UI 처리와 무적 시간(3초)를 부여하였다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SailMove : MonoBehaviour
{
Rigidbody2D RB;
SpriteRenderer SR;
public UImanager_SinglePlay UImanager;
public Animator Animator;
public int PlayerSpeed = 3;
public bool Isinvincibility = false;
public bool CoolerOn = false;
void Start()
{
RB = GetComponent<Rigidbody2D>();
SR = GetComponent<SpriteRenderer>();
}
void Update()
{
if (!UImanager.GameOver)
{
playerMove();
UseBooster();
}
}
public void playerMove()
{
float axis_width = Input.GetAxisRaw("Horizontal");
float axis_length = Input.GetAxisRaw("Vertical");
if (axis_width != 0)
{
SR.flipX = axis_width == 1;
}
RB.velocity = new Vector2(PlayerSpeed * axis_width, PlayerSpeed * axis_length);
}
public void UseBooster()
{
if (Input.GetKey(KeyCode.Space) && !CoolerOn)
{
UImanager.slider.value -= Time.deltaTime * 2;
PlayerSpeed = 5;
if (UImanager.slider.value < 0.1f) CoolerOn = true;
}
else
{
UImanager.slider.value += Time.deltaTime;
PlayerSpeed = 3;
if (UImanager.slider.value >= 4.9) CoolerOn = false;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Obstacle" && !Isinvincibility)
{
UImanager.DropHeart();
StartCoroutine(invincibilityTime());
}
}
IEnumerator invincibilityTime()
{
Animator.SetBool("IsHitted", true);
Isinvincibility = true;
yield return new WaitForSeconds(2);
Animator.SetBool("IsHitted", false);
Isinvincibility = false;
}
IEnumerator CoolTime()
{
yield return new WaitForSeconds(1f);
}
}
2. SQLite와 연동해 로컬 저장소를 만들어 랭킹시스템 구현
아래 코드는 로컬 환경에서 사용자의 점수(버틴 시간)을 기록하는 SQlite.cs 파일의 일부이다.
SQlite와 연동하여 Query문을 유니티 내부 스크립트에서 입력할 수 있게 하였다!
public void RecordRanking()
{
// 점수를 넣어야 하는데, 등록 이름이 없다면 등록하지 않고 반려시킨다.
if(UserName_inputField.text.Length == 0)
{
return;
}
// 점수 등록과정. InsertQueryDataBase() 함수를 이용해 등록 닉네임과 점수를 등록한다.
// 버틴 초의 합계가 점수가 된다.
try
{
int playerScore = 0;
if (UImanager_Single != null) playerScore = ((int)UImanager_Single.Time_sec) + 60 * UImanager_Single.Time_min;
else if(UImanager_Multi != null) playerScore = ((int)UImanager_Multi.Time_sec) + 60 * UImanager_Multi.Time_min;
InsertQueryDataBase("insert into user_Ranking(ID,SCORE) values(\"" + UserName_inputField.text + "\",\"" + playerScore + "\")");
DataBaseClose();
Debug.Log("랭킹 등록 완료.");
}
catch (SqliteExecutionException e)
{
print(e);
return;
}
}
3. Photon Pun2 에셋을 이용해 멀티플레이 모드 구현
멀티플레이 모드는 1대 1로 오래 버티는 사람이 승자가되는 형식으로 만들었다.
아래 코드는 멀티플레이 모드에서 총알을 발사하는 BulletDispensor.cs 코드이다.
총알 발사대는 게임 내부에 총 8개를 만들었으며, Pun2의 RPC 개념을 이용해 두 사용자 간 총알이 스폰되고 발사되는 식의 동기화를 처리하였다. 이 때 총알이 목표로 하는 표적은 Unity의 Random.range() 함수를 사용해 두 플레이어 중 하나에게 총알이 향하도록 만들었다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using System.Reflection;
using UnityEditor;
public class BulletDispensor_MultiPlay : MonoBehaviourPun
{
public GameObject bullet_prefab;
public GameObject Player_1;
public GameObject Player_2;
public PhotonView PV;
public float FireDelay = 3f;
public float CurTime = 0;
public int ShotPower = 3;
public bool StartSpawn = false;
private void Start()
{
PV = GetComponent<PhotonView>();
PV.RPC("FindSail", RpcTarget.All);
}
// 1초 간격으로 총알 발사
void Update()
{
if(StartSpawn)
{
CurTime += Time.deltaTime;
if (CurTime > FireDelay)
{
PV.RPC("BulletDispenseRPC", RpcTarget.All);
}
}
}
[PunRPC]
public void BulletDispenseRPC()
{
GameObject bullet = PhotonNetwork.Instantiate("bullet_prefab", this.transform.position, this.transform.rotation);
int RN = Random.Range(0, 2);
GameObject targetPlayer;
if (RN == 1) targetPlayer = Player_1;
else targetPlayer = Player_2;
Vector2 direction = (targetPlayer.transform.position - this.transform.position).normalized;
bullet.GetComponent<Rigidbody2D>().velocity = direction * ShotPower;
CurTime = 0;
}
[PunRPC]
public void FindSail()
{
Player_1 = GameObject.Find("1p_Sail(Clone)");
Player_2 = GameObject.Find("2p_Sail(Clone)");
StartSpawn = true;
}
}
다만 동기화의 처리가 살짝 미흡한 부분이 있어서 총알의 위치가 미세하게 틀리는 오류가 있었지만 그럭저럭 완성했다!
게임을 실제로 다운로드 받을 수 있는 구글 드라이브 링크다!
코육대 평가 기간이 끝나면 다시 내릴 예정이다.
https://drive.google.com/file/d/17LcO465HNMknYEEj_k3x2SxnZphgL3M7/view?usp=sharing
DudgeSail.zip
drive.google.com
게임 조작법에 관해서는 깃허브 레포지토리에 따로 올려놓았다! 게임을 시작하기 전 아래 링크에 접속해
readme 파일을 읽어보길 바란다.
https://github.com/belfly1111/DudgeSail
GitHub - belfly1111/DudgeSail: 2023 항해플러스 제 1회 교육대 참가작 입니다.
2023 항해플러스 제 1회 교육대 참가작 입니다. Contribute to belfly1111/DudgeSail development by creating an account on GitHub.
github.com
이번 추석연휴 동안 시간을 의미 없게 보내기 보다는 코육대에 참가하는게 훨씬 좋은 선택이었다!
과거에 진행했었던 토이프로젝트 내용을 다시 상기시킬 수 있었던 좋은 기회였고 내년에도 코육대를 한다면 부족한 점을 더 보완해서 참가하고 싶다!
'자유게시판' 카테고리의 다른 글
[IMS 스터디] 게임 서버 스터디 <2주차> (0) | 2024.02.02 |
---|---|
[IMS 스터디] 게임 서버 스터디 <1주차> (1) | 2024.01.26 |