//구글콘솔 광고 추가가
728x90
반응형
롤케이크 자르기 문제

 

내 코드
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
    public int solution(int[] topping) {
        int answer = 0;
        Stack<int> stack = new Stack<int>(topping);
        var dic = topping.GroupBy(x => x).ToDictionary(x=>x.Key,x=>x.Count());
        HashSet<int> hashSet = new HashSet<int>();
        while(stack.Count > 0)
        {
            int n = stack.Pop();
            hashSet.Add(n);
            if (dic[n] == 1)
                dic.Remove(n);
            else
                dic[n]--;
            if(dic.Count() == hashSet.Count)
                answer++;
        }
        return answer;
    }
}

 

728x90
반응형
728x90
반응형
의상 문제

 

 

내 코드
using System;
using System.Collections.Generic;
public class Solution {
    public int solution(string[,] clothes) {
        int answer = 1;
        Dictionary<string, int> dic = new Dictionary<string, int>();
        dic.Add(clothes[0, 1], 0);
        for (int i = 0; i < clothes.GetLength(0); i++)
        {
            if(dic.ContainsKey(clothes[i, 1]))
            {
                dic[clothes[i, 1]]++;
            }
            else
            {
                dic.Add(clothes[i, 1],1);
            }
        }
        foreach(string key in dic.Keys)
        {
            // *(한옷의 종류 수 +1(안입는 경우의 수))
            answer *= dic[key] + 1;
        }
        answer -= 1; // - 아무것도 안입는 경우의 수
        return answer;
    }
}
728x90
반응형
728x90
반응형

유니티에서 스프라이트를 가져와야 할 때 스프라이트 뒤에 배경 색이 있는 경우가 있다. 주로 한 가지 색깔로 되어 있는데 그냥 사용하기엔 번거롭기 때문에 투명으로 변경해 주는 게 편하다.

 

나의 경우 Aseprite 프로그램을 구매해둔게 있어서 거기서 간단하게 수정하는 방법을 기록해 두기로 했다.

예전엔 이 쉬운걸 몰라서 지우개로 한 땀 한 땀 지웠던 적도 있었는데 지금 생각해 보면 그 당시 시간이 많았던 걸까 싶다.


 

화면에 보이는 것 처럼 마젠타 색깔로 되어 있는 스프라이트를 봐보자. 

바로 옆에 있는 팔레트에는 해당 스프라이트에서 사용한 색깔들이 구성되어 있다. 우리는 여기에 투명색을 하나 더 추가해줄 것이다. 

 

색깔 선택하는 창에서 투명쪽으로 마우스를 가져다 대고 꾹 한번 누르면 

 

이렇게 바뀌는데 여기서 저 흰 느낌표가 들어가 있는 빨간색 ui를 클릭해서 팔레트에 추가해 준다.

 

마지막으로 위 순서대로 해주면 배경은 투명으로 바뀐다.

투명색깔을 팔레트에 추가해 주고 채우기 버튼을 클릭해서 배경으로 들어가 있는 마젠타 색 어디든 클릭해주면 배경이 투명으로 채워진다.

 

안지워진 마젠타색들이 거슬리지만 저부분은 사용할 필요 없는 부분이니까 작업해줄 필요가 없다. 혹시나 필요하다면 그냥 똑같이 클릭클릭해주면서 투명으로 채워주면 해결된다.

 

지금까지 아주 간단하지만 모르면 생각보다 뻘짓을 해야 되는 작업이었다. 

 

 

++ 만약 연두색 배경이 있는 스프라이트를 들고 왔는데 Aseprite에서 투명이라고 인식할 수 있다.

그럴 때는 아래쪽에 위치해 있는 Background 레이어를 복제해 준 다음 새 레이어를 하나 만들어 복제한 레이어와 합체해 주고 원래 있던 Background레이어를 지워주면 해결된다.

728x90
반응형
728x90
반응형

어제 써둔 pseudo 3d game 유니티 공부에 대해 저장해 두려고 글을 쓴다. 

일단 내가 만든 방법은 2d 배경 1장에 도로의 가운데 라인과, 장애물이 플레이어의 반대 방향(위에서 아래 방향)으로 이동하게 해서 플레이어는 가만히 있지만 이동하는 느낌을 만들어 봤다. 장애물 만드는 방법과 도로 라인 만드는 방법을 다르게 해 봤다. 사실 두 가지 다 각자 테스트 해보다가 각자 만들어졌지만 원리는 비슷할 것이다. 

 

 


1. 우선 게임에 필요한 스프라이트들을 구글에서 찾아서 들고온다.

 

나의 경우는 아래 스프라이트 사이트에서 많이 이용한다.

https://www.spriters-resource.com/

 

The Spriters Resource

This page does not work well in portrait mode on mobile. Please rotate your device.

www.spriters-resource.com

생각보다 많은 다양한 게임들의 스프라이트들을 다운로드할 수 있다. 만약 배경이 있다면 aseprite 프로그램을 사용해서 제거해 준다. 물론 코드로 뒷배경을 삭제시켜 주는 방법도 있다. 하지만 나는 이 프로그램을 돈 주고 샀기 때문에 뽕을 뽑아야 한다는 마음으로 작은 작업이라도 사용하는 편이다.

 

ai를 사용해서 나만의 배경을 만들어 볼까도 했지만 2시간 동안 하늘의 사이즈를 줄여주지 않는 ai에게 굴복하고 그만뒀다.(회원가입도 했는데... 하늘을 줄여주는 게 그렇게 싫었던 걸까. 그렇게 소량으로만 줄여주고 싶었던 것일까. 한글도 영어도 전부 먹히지 않았던 너란 ai. 배경 오브젝트들이 점점 한자들이 나오길래 중국인가 싶었지만 난 중국어는 못하는 걸.)

언덕도, 산도, 나무도, 하늘도 더이상 나의 계획대로 변경되지 않았던 나름 예뻤던 내가 요청한 배경. 도로 안에 가운데 라인도 빼달라고 빼달라고 그렇게 말했는데 완강했던 너의 모습. 잊지 못할 거야.

 

2. 유니티에서 몇 가지 작업을 해준다.

일단 우선적으로 2d project를 만들어 준다. 그리고 Obstacle Manager(장애물 관리 매니저) 오브젝트와, RoadLineManager(도로 라인 관리 매니저)를 만들어 준다. 프리팹들은 장애물 프리팹과, 라인 프리팹만 있으면 된다. UI Canvas를 만들어 주고 필요하다면 플레이어가 이동할 수 있는 버튼을 추가로 만들어 주면 된다. 나의 경우 버튼을 눌러 좌, 우로 이동할 수 있게 작업했다. 속도를 늘리는 버튼과 속도를 줄이는 버튼 또한 만들어 두었다.

 

 

 

3. 이제 스크립트를 짜보자.

 

우선 도로 라인이 내려오게 만들어 주는 RoadLineManager를 만들어 보자. 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

public class RoadLineManager : MonoBehaviour
{
    [Header("Line Spawn Settings")]
    public GameObject roadLinePrefab;
    public int poolSize = 10;
    public float spawnInterval = 1f;
    
    [Header("Line Position Settings")]
    public float startYPosition = 5.7f;
    public float startXPosition = 0.15f;
    public float endYPosition = -1f;
    public float fixedLineSpacing = 1.8f;
    
    [Header("Line Scale Settings")]
    public float startScaleX = 0.05f;
    public float startScaleY = 0.02f;
    public float endScaleX = 0.4f;
    public float endScaleY = 0.5f;
    
    [Header("Movement Settings")]
    public float initialMoveSpeed = 5f;
    public float currentMoveSpeed;
    public float maxMoveSpeed = 15f;
    public float accelerationRate = 2f;
    
    [Header("Line Settings")]
    public int maxVisibleLines = 6;

    private List<GameObject> linePool;
    private float[] linePositions;
    //private float[] spacings = new float[] { 1.0f, 1.2f, 1.5f, 1.8f, 2.2f, 2.7f };
    private float[] spacings = new float[] { 0.8f, 1.2f, 1.8f, 2.5f, 3.3f, 4.2f };
    private void Start()
    {
        linePool = new List<GameObject>();
        linePositions = new float[maxVisibleLines];
        InitializePool();
        currentMoveSpeed = initialMoveSpeed;
        UpdateLinePositions();
        SpawnInitialLines();
    }
    
    private void InitializePool()
    {
        for (int i = 0; i < poolSize; i++)
        {
            GameObject line = Instantiate(roadLinePrefab);
            line.SetActive(false);
            linePool.Add(line);
        }
    }

    private void UpdateLinePositions()
    {
        linePositions[0] = startYPosition;
        
        for (int i = 1; i < maxVisibleLines; i++)
        {
            float spacing = fixedLineSpacing * spacings[i-1];
            linePositions[i] = linePositions[i-1] - spacing;
        }
    }
    
    private void SpawnInitialLines()
    {
        for (int i = 0; i < maxVisibleLines; i++)
        {
            SpawnLineAtPosition(linePositions[i]);
        }
    }

    private void SpawnLineAtPosition(float yPosition)
    {
        GameObject line = GetInactiveLine();
        if (line != null)
        {
            float t = (startYPosition - yPosition) / (startYPosition - endYPosition);
            t = Mathf.Clamp01(t);
            
            float scaleX = Mathf.Lerp(startScaleX, endScaleX, t);
            float scaleY = Mathf.Lerp(startScaleY, endScaleY, t);
            
            line.transform.position = new Vector3(startXPosition, yPosition, 0);
            line.transform.localScale = new Vector3(scaleX, scaleY, 1);
            line.SetActive(true);
        }
    }
    
    private void Update()
    {
        UpdateLines();
    }

    private void UpdateLines()
    {
        int visibleCount = 0;
        float highestY = float.MinValue;

        foreach (GameObject line in linePool)
        {

            if (line.activeInHierarchy)
            {
                Vector3 pos = line.transform.position;
                float t = (startYPosition - pos.y) / (startYPosition - endYPosition);
                t = Mathf.Clamp01(t);

                float scaleX = Mathf.Lerp(startScaleX, endScaleX, t);
                float scaleY = Mathf.Lerp(startScaleY, endScaleY, t);

                // 스케일이 클수록 더 빠르게 이동하도록 수정
                float speedMultiplier = scaleY / startScaleY;
                pos.y -= (currentMoveSpeed * speedMultiplier) * Time.deltaTime;

                line.transform.localScale = new Vector3(scaleX, scaleY, 1);
                line.transform.position = pos;

                if (pos.y < endYPosition)
                {
                    line.SetActive(false);
                }
                else
                {
                    highestY = Mathf.Max(highestY, pos.y);
                    visibleCount++;
                }
            }
        }

        if (visibleCount < maxVisibleLines)
        {
            if (highestY == float.MinValue)
            {
                SpawnLineAtPosition(startYPosition);
            }
            else
            {
                int currentIndex = visibleCount - 1;
                float spacing = fixedLineSpacing * spacings[currentIndex];
                float newYPos = highestY + spacing;
                
                if (newYPos <= startYPosition)
                {
                    SpawnLineAtPosition(newYPos);
                }
            }
        }
    }
    
    private GameObject GetInactiveLine()
    {
        return linePool.Find(line => !line.activeInHierarchy);
    }

    public void IncreaseSpeed()
    {
        currentMoveSpeed = Mathf.Min(currentMoveSpeed + accelerationRate, maxMoveSpeed);
    }
    
    public void DecreaseSpeed()
    {
        currentMoveSpeed = Mathf.Max(currentMoveSpeed - accelerationRate, initialMoveSpeed);
    }
    
    public void ResetSpeed()
    {
        currentMoveSpeed = initialMoveSpeed;
    }
}

 

이 코드를 짤 때 몇 가지 골머리 써야 됐었던 부분이 있었다.

그중 가장 큰 게 라인이 프리팹으로 활성화가 될 때 아래로 내려오는 느낌으로 원근감 있게 내려오려면 처음 적용해 줬던 간격을 계속 유지하면 안 되는 문제가 있었다. 이 부분을 수정하기 위해 나에겐 여러 번의 시도가 필요했다. 그래서 UpdateLines() 함수는 정말 쉴 새 없이 수정됐었다. 그리고 마침내 해결된 방법이 바로 위에 적어둔 스케일의 사이즈에 따라 빠르게 이동시키는 것. 이 부분이 사실 그렇게 어려운 부분은 아니었다. 처음부터 수치를 디버깅해서 확인해 봤으면 문제가 되지 않았을 것이다. 변경시켜 주던 수치값이 제대로 늘어나지 않는 오류를 모르고 도대체 왜 내가 원했던 데로 나오지 않는 거지 하다가 시간을 두배로 썼다. 잊지 말자 디버깅.

 

버튼에 적용시켰던 speed up 버튼과 speed down 버튼에 사용할 함수도 여기 있는 IncreaseSpeed() 함수와 DecreaseSpeed() 함수를 연결해 주면 된다. 필요시 나머지 함수들도 연결시켜줘도 기능은 할 것이다. 

 

나의 경우는 변수들을 많이 만들어 최대한 유니티에서 배경을 바꿨을 때도 사용할 수 있게 작업했다. 지금 보이는 것과 같이 저 배경은 free이기 때문에 가져온 스프라이트지 그렇게 내 마음에 들지 않기 때문일지도 모른다. 도로의 시작과 끝을 잡아줄 위치 변수들과, 라인의 스케일을 관리해 줄 변수들, 라인과 라인 사이의 간격을 정할 변수로 되어있다. 그리고 화면에 나올 라인의 개수 변수가 있는데 이건 간격과 도로의 총길이에 따라 나오지 않을 수도 있다. 프리팹은 오브젝트 풀링을 사용해서 최적화해 두었다. 

 

 

 

장애물 매니저는 내일 다시 정리해 두겠다. 여기서는 역시나 오브젝트풀로 장애물을 관리하고, 도로의 좌, 우에 따라붙어서 원근감 있게 스케일이 커지도록 작업했다.

 

++ 나도 모르게 필요없는 파일인줄 알고 프로젝트 삭제시켜서 장애물 매니저는 그렇게 날라갔다...다시 작업해서 올리도록 하겠다.

728x90
반응형
728x90
반응형

며칠 전 공부했던 곳에서 봤던 단어 pseudo! 그때도 낯설었던 단어 슈도라는 단어를 이렇게 다시 만날 줄이야.

그때 공부했을 땐 슈도 코드에 대해서였지만 지금은 2d로 3d게임 환경을 만드는 것이다. 오래전 우리가 게임했을 때 대체로 많이 보였던 기법인데 대표적인 게임이 "Out Run" 게임이 있다. 이외에도 레이싱 게임에서는 종종 많이 발견됐었던 것 같다. 그때는 그게 3D인지 2D인지 알게 뭐였는가. 그저 게임하는 게 즐거웠을 뿐이었지. 

그렇게 즐거웠던 게임이 이제 단순히 "참 즐거웠던 게임이었지."란 과거형의 기억이 아닌 순간이 왔다. 새로 작업해 보기로 한 프로젝트 팀에서 딱 "Out Run"게임처럼 구현해 주길 바라는 말을 듣게 되었다.

 

사실 처음엔 뭐 얼마나 어렵겠어라는 생각이 전부였다. 못할 건 없지란 생각으로 일주일 동안 시도해 볼 시간을 얻어 Test를 해보기 전까지 정말 딱 그 생각이었다. 생각보다 구글에 "How do i make OutRun"라고 치는 순간 기가 막힌 정보들도 찾을 수 있어서 쉽게 접근할 수 있겠다 생각했었다. 

 

https://jakesgordon.com/writing/javascript-racer/

 

How to build a racing game

Personal Website for Jake Gordon

jakesgordon.com

https://jakesgordon.com/writing/javascript-racer-v1-straight/

 

How to build a racing game - straight roads

Personal Website for Jake Gordon

jakesgordon.com

 

정말 멋진 내용이다. 도로 기하학에서 약간 주춤거렸지만 생각보다 꽤 술술 재미있게 읽혔다. 

여기와 함께 Pseudo 3d game 부분도 필수로 읽어야 되는 내용이였다.

http://www.extentofthejam.com/pseudo/

 

Lou's Pseudo 3d Page

Lou's Pseudo 3d Page Pseudo 3d en español aqui! Gracias a Luis Peña! (C) 2013 Louis Gorenfeld, updated May 3, 2013 NEW: Important details on the segmented road system and some additional links NEW: An (optional) explanation of finding field-of-view for t

www.extentofthejam.com

 

읽으면서 드는 생각은 "생각보다 어렵겠는데"였다. 

 

위에 글을 읽어보고 하루 후에 유니티를 켜봤다가 그새를 잊은 건지 허튼짓을 했었던 순간이 있었다. 바로 2d 스프라이트들을 아래쪽에 쭉 깔아 두고 플레이어한테 다가오게 하면 안 되나 했다가 그렇게 되면 3d가 되는 거란 걸 인식하고 세상 똥멍청이인가 싶었었다.

누군가는 또 이 방법을 사용해서 작업을 했던 흔적을 발견했다. 완전히 똥멍청이 생각은 아니였던 걸로!

 

뭐 그래도 뭐든 시도는 좋은 거니까 라는 마인드로 다시 시도해 봤다. 그러다 세그먼트들 작업을 할 때 생각했다. 왜 2D환경에서 3d를 구현하고 싶은 걸까. 옛날이라면 어쩔 수 없었던 선택일지 몰라도 요즘 같은 현대 사회에 왜 3d로 만들면 한방에 해결이 되는 이 상황을 난 지금 왜 이렇게 집중하고 있을까였다.ㅎㅎ 이렇게 오늘도 난 성장했다.

 

그럼에도 불구하고 뭔가 슬슬 화면에 나오기 시작했을 때쯤 쾌감은 짜릿했다.

하지만 내 코드에서는 몇 가지 문제점들이 보였다. 속도가 붙을수록 세그먼트들의 간격이 생기는 상황. 뭔가 잘못 만든 게 분명했다. 작업하면서 스케일값도 중요했다. 일주일 동안 이 작업만 할 수 있는 스케줄은 아니었기에 다른 쉽게 가는 방법이 있을까 하고 생각하다가 도로에 있는 차선만 이동하는 것도 나쁘지 않겠다는 생각을 했다. 결과적으로는 나쁘지 않은 결괏값을 얻을 수 있었다. 위의 방식대로 하던 중 문제가 있었던 부분은 연속으로 나오는 부분에서 간격이 벌어지는 문제였다면 라인은 연속해서 나오지 않기에 그대로 작업을 해보았다. 

작업할 때 가장 중점적으로 생각한 부분이 멀리 있는 공간에서 화면 가까이로 오는 부분에서 느껴져야 할 원근감과 스케일 부분, 그리고 왼쪽 도로와 오른쪽 도로에서 오는 장애물의 경우 차선을 따라 각각의 끝에 자연스럽게 유지돼서 붙어 내려와야 하는 부분. 그리고 애증의 간격 부분. 

간격이 생각보다 어려웠던 게 차량 이동을 생각할 때 도로 위의 라인이 멀리서 가까이로 올수록 간격이 넓어져야 하는데 간격을 정해두고 스케일만 키웠던 게 문제였다. 그래서 접근한 부분이 스케일 값이 커질수록 position y의 값을 더 작아지게 해서 간격을 늘려볼까도 생각을 했는데 이렇게 구현해 보니 무슨 문제인지 전혀 원하는 방향대로 나오지 않길래 디버그를 해봤더니 알았다. 내가 원한 만큼의 수치가 계산에서 이루어지고 있지 않았다. 수치를 조절하는 부분을 다시 수정하고 봤더니 이젠 프리팹으로 만들어 둔 오브젝트가 시작 부분에서 종료되는 부분까지 나오는 거리가 문제가 돼서 활성화가 안 되는 버그를 보고 눈을 감았다. 이것저것 머릿속에서 한참 생각해 보다가(프리팹 순서를 정해서 활성화해 볼까, 리스크에 위치값을 저장시켜서 그 부분에 가면 위치를 두 배씩 늘려볼까, 등등 지금 생각해 보면 별의별 말도 안 되는 생각들이 있었다.) 속도 값을 늘려볼까 싶었는데 이게 생각보다 괜찮은 결괏값을 만들어 줬다. 그렇게 장애물과, 라인의 움직임을 구현시켜 두었더니 한결 마음이 편해졌다. 결과적으로 프리뷰느낌으로 보기에 나쁘지 않을 정도의 상태를 만들어 두고 생각해 봤는데 이 방법이 최선의 선택은 아닌 것 같다. 저 위의 내용을 토대로 다시 한번 작업해 봐야겠다.

 

사실 이제 더 이상 이런 부분의 코드 작업을 안 할 줄 알았는데 막상 해보니까 너무 재미있었다. 아무래도 이쪽 길로 가지 않는다 해도 취미로라도 계속해서 관심을 유지해야겠다.

 

 


밑에는 도로 기하학 찾아봤다가 흥미로우면서 경악했던 구글 화면.

728x90
반응형
728x90
반응형
테스트 케이스 추가
Parameters Return
queue1(int[ ]) queue2(int[ ])
[2, 3, 2] [1, 1, 1] 1
[1, 1, 1, 1, 1, 1, 1, 1, 1, 10] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] -1

 

두 큐 합 같게 만들기 문제

 

내 코드
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution {
    public int solution(int[] queue1, int[] queue2) {
        int answer = 0;
        Queue<int> q1 = new Queue<int>();
        Queue<int> q2 = new Queue<int>();
        long sum1 = 0;
        long sum2 = 0;

        foreach(int n in queue1)
        {
            q1.Enqueue(n);
            sum1 += n;
        }
        foreach(int n in queue2)
        {
            q2.Enqueue(n);
            sum2 += n;
        }
        //평균값 구할때 배열.Sum()으로 계산하니까 런타임 걸렸어. 알아둬라
        //long average = (queue1.Sum() + queue2.Sum()) /2;        
        long average = (sum1 + sum2) / 2;
        
        if((sum1 + sum2) % 2 !=0) return -1;
        
        int maxLength = (queue1.Length + queue2.Length)*2;
        while(answer < maxLength)
        {
            if(average == sum1) return answer;
            
            if(average > sum1)
            {
                int dequeueNum = q2.Dequeue();
                q1.Enqueue(dequeueNum);
                sum1 += dequeueNum;
                answer ++;
            }
            else
            {
                int dequeueNum = q1.Dequeue();
                q2.Enqueue(dequeueNum);
                sum1 -= dequeueNum;
                answer ++;
            }
        }
        return -1;
    }
}

 

728x90
반응형
728x90
반응형
성격 유형 검사하기 문제

 

내 코드
using System;
using System.Text;
using System.Collections.Generic;

public class Solution {
    public string solution(string[] survey, int[] choices) {
        string answer = "";
        StringBuilder answerSB = new StringBuilder();
        Dictionary<char,int> surveyDic = new Dictionary<char,int>()
        {
            { 'R', 0 },
            { 'T', 0 },
            { 'C', 0 },
            { 'F', 0 },
            { 'J', 0 },
            { 'M', 0 },
            { 'A', 0 },
            { 'N', 0 },
        };
     
        char[] c = new char[2];
        for (int i = 0; i < survey.Length; i++)
        {
            c = survey[i].ToCharArray();

            if (choices[i] > 4)
            {
                surveyDic[c[1]] += choices[i] - 4;
            }
            else if (choices[i] < 4)
            {
                surveyDic[c[0]] += 4 - choices[i];
            }
        }
        answerSB.Append(surveyDic['R'] >= surveyDic['T'] ? "R" : "T");
        answerSB.Append(surveyDic['C'] >= surveyDic['F'] ? "C" : "F");
        answerSB.Append(surveyDic['J'] >= surveyDic['M'] ? "J" : "M");
        answerSB.Append(surveyDic['A'] >= surveyDic['N'] ? "A" : "N");
        answer = answerSB.ToString();
        return answer;
    }
}
728x90
반응형
728x90
반응형

벌써 11월이 되었다. 이제 올해가 가기 전까지 단 두 달만을 남겨둔 상황이다.
나는 과연 올해에 어떤 삶을 살았는가.
최선을 다해 바쁘게 살았을 까.
결과적으로 나는 그렇지 못했던 것 같다.
바쁘게 살지 않았다 해서 여유를 가지고 나를 위해 살았나 생각해 봐도 나는 이도저도 선택하지 못한 한 해였던 것 같다.

차라리 완벽하게 편안한 쉼을 선택한 것도 아니라는 부분이 아쉽다. 왜 그랬을 까.

나이가 먹을수록 1년의 단위가 참 빠르게 지나가는 것 같다.
체감 상 거의 버스 정류장 지나가듯 한 달, 두 달 그렇게 지나가는 기분이 든다.
그 사이에 내가 하고 싶은 것들에 대해 잠시라도 눈을 떼면 이미 손에서는 멀어져 원래 내려야 할 정류장이 아닌 그다음 정류장으로 가고 있는 상황이다. 처음엔 그 상황이 당황스러웠는데, 이제는 더 늦기 전에 그다음 정류장에서라도 내려야 된다는 것을 알게 된 것 같다.

친구 관계도 그렇다. 나도 모르게 멀어져 버린 내 친구들이 올해도 존재한다. 어렸을 때는 친구를 사귀는 게 참 쉬웠던 것 같은데 이제는 친구를 잃는 것 역시 참 쉬워진 것 같다.

모두가 같은 생각을 할 수 없듯이 모두가 다른 마음을 가지고 세상을 바라보기에, 그 사이에서 오는 아쉬움을 알아차리지 못했던 것이 어쩌면 이유가 되는 것 같다. 
어렸을 땐 같은 시간 속에서 다른 생각과 다른 행동을 할 수 있다는 현실이 새롭고 흥미롭게 다가왔는데 어느 정도 성장한 지금의 상태로 보면 흥미롭게만 생각할 수 없는 것 같다. 아마도 나 또한 변해버린 시각으로 세상을 보는 것일 뿐이겠지.

 

나는 생각하는 것을 좋아한다. 과거에도 그랬고 지금도 그렇고 앞으로도 그럴 것이다.

생각이 쌓이고 그 쌓인 생각 위로 또 다른 생각이 쌓이는 것이 나는 참 좋았다. 더 깊은 생각을 할 수 있다는 것이 아마도 나이가 들면서 얻을 수 있는 큰 장점이라 생각했었다. 간과했었다. 생각에는 좋은 감정들만 있는 것이 아니라는 사실을.

어렸을 때는 기쁨의 기준치가 낮았던 것 같다. 풀밭을 걸어가도 신이 났고, 모든 게 궁금했고, 그래서 모든 시간들이 추억이 되었다.

하지만 커가면서 기쁨이라는 건 생각보다 쉽게 만날 수 있는 존재가 아니었다. 오히려 기쁨보단 슬픔이라는 감정에 대해 더 알아가는 시간이 되었던 것 같다. 그래서 더 모든 것에 무뎌진 감정을 갖게 되었다. 맞다. 나는 어쩌면 지금까지는 알지 못했던 슬픔에 대해 배워가고 있는 것 같다. 감정은 다양하기에 이 시간이 지나면 나는 또 다른 감정에 대해 배우고 있을 것이다. 그렇게 나는 인간이라는 기준치에 맞는 감정들을 가지게 될 테니 지금의 이 생각도, 익숙해지자.

아! 그래도 자격증을 두 개나 땄다. 새로운 환경에서 경험도 해보았다. 잘 되지 않은 결과라 할지라도 꽤 여러 곳에 발을 넣어보기도 했다. 그럼에도 올해의 나에게 부족하다 생각하는 계기가 되었던 이유는 아마도 세상 모두가 나보다 더 바쁘게 열심히 살고 있다는 것을 알았을 때인 것 같다. 하지만 이미 지나간 시간들은 돌아오지 않는다. 나는 오늘, 내일을 더 열심히 생각하고 살아가기로 했다. 나에게 주어진 시간들이 어느 정도 일지 몰라도 열심히 살고 싶다. 오늘 같이 또 후회되는 시간을 갖지 않기 위해서라도. 내년엔 더욱 발전한 나를 만나길 바라고 바란다. 힘내보자!

 

 

 

 

그대가 자신의 별을 따라가는 한, 영광스러운 항구에 실패 없이 도달할 수 있으리라. - 단테의 신곡.

 

728x90
반응형

+ Recent posts