한이음 프로젝트로 앱 개발을 거의 마무리하고 사용자 테스트를 진행하고 있는데

오늘 회의에서 얘기한 결과, 폰트의 가독성에 대한 피드백이 많이 있어서 폰트를 수정했다.

 

나눔스퀘어체로 수정했는데 글자 자체는 깔끔하지만 줄간격이 너무 좁아서 빼곡한 느낌이 있었다.

 

 

앱에서 제공하는 진단테스트, 상담 채팅 기능에서는 한 화면에 많은 양의 텍스트가 보이는데

이렇게 글자가 빼곡하면 가독성이 저하된다고 판단해서 줄간격을 넓히는 방법을 찾아보았다.

 

방법은 android:lineSpacingExtra 속성을 사용하는 것이었다.

 

<TextView
...
android:lineSpacingExtra="5dp"
/>

 

이런 식으로 특정 TextView에 직접 속성을 지정해줘도 되고

나는 앱 전체 텍스트에 적용이 되도록 style.xml에 TextView의 스타일을 지정했다.

 

values > style.xml

  <style name="TextViewFontStyle" parent="@android:style/Widget.DeviceDefault.TextView">
      <item name="android:fontFamily">@font/custom_font_family</item>
      <item name="android:textSize">16sp</item>
      <item name="android:lineSpacingExtra">5sp</item>
  </style>

 

참고로 custom_font_family는 폰트자체 속성을 지정하기 위해 작성한 것으로, 코드는 다음과 같다.

 

font > custom_font.family.xml

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <font
        android:font="@font/nanumsquare"
        android:fontStyle="normal"
        android:fontWeight="500"
        app:font="@font/nanumsquare"
        app:fontStyle="normal"
        app:fontWeight="500"
        tools:ignore="ResourceCycle" />

</font-family>

 

font 폴더에 있는 나눔스퀘어 ttf를 지정했다.

 


 

 

줄간격 수정 전후를 비교해보았을 때 가독성이 훨씬 좋아졌다.

안드로이드 스튜디오 앱 개발 프로젝트를 진행하면서 다크모드는 생각도 못하고 있었는데

다크모드를 적용하고 앱을 실행하면 레이아웃의 많은 부분이 원치 않게 깨지는 현상을 발견했다.

 

res - values - themes 폴더에 일반/다크모드 전용 themes.xml 파일이 있어서

원하는 사람은 themes.xml (night) 파일을 수정하여 다크모드에 맞게 따로 디자인을 적용해도 좋을 것 같으나

나는 다크모드를 지원하지 않는 방법을 찾아보았다.

 

 

앱을 실행할 때 가장 먼저 실행되는 액티비티인 로딩 화면(스플래시 화면) java 파일 onCreate 메소드에

다음과 같이 코드를 작성했다.

public class ActivitySplash extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); //다크모드 지원 X
	//생략
    }
}

 

이렇게 작성하면 AppCompatActivity를 상속한 클래스는 다크모드를 킨 상태로 앱을 이용하더라도

다크모드 테마가 아닌 기본 테마가 적용이 된다.

 

하지만 일부 페이지는 위의 코드를 작성해도 다크모드가 적용되는 것을 발견했는데

AppCompatActivity가 아닌 Activity를 상속한 클래스들이었다.

따라서 해당 클래스들을 모두 AppCompatAcitivty를 상속하도록 수정했다.

 

이로써 다크모드 적용으로 인해 앱의 디자인이 원치 않게 깨지는 현상을 막을 수 있었다!

Dialogflow를 사이트 자체에서 세팅하는 것도 어려운 일이었는데

이것을 앱 화면에 띄우기 위해 Android Studio 내에서 코드를 짜는 것도 역시 어려운 일이었다.

관련 라이브러리가 무엇이 있는지도 모르고 어떤 메소드를 사용해야하고,

어떤 로직을 짜야하는지 너무 막막했기 때문이다.

 

그런 와중에 발견한 한줄기의 빛...!!!!🌟

 

https://youtu.be/zVxDBBCdpfY

 

영상으로 방법도 순서대로 알려주었으며

더보기란에 해당 코드의 GitHub 주소도 나와있어 많은 참고가 되었다!!

 

adapter, helper, interface, model 등 사용하는 파일이 많아 헷갈릴 수 있으나

해당 코드의 작동 원리를 분석하게된 덕분에 각 구성요소의 역할들을 학습할 수 있었다.

  • Adapter 패턴 사용

 

1. RecyclerView 태그 추가

  • 원하는 화면 xml 파일에 다음과 같이 추가
<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" />

 

2. 데이터.java 생성

  • model 폴더
  • 변수, 생성자, Get/Set 함수 만들기 (우클릭 → Generate)

 

3. 데이터_item.xml 생성

  • 각 데이터별 카드 디자인
  • CardView를 활용함
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardBackgroundColor="#FFFFFF"
        app:cardCornerRadius="10dp"
        app:cardElevation="5dp"
        app:cardUseCompatPadding="true">

    </androidx.cardview.widget.CardView>

</LinearLayout>

 

4. 데이터Adapter.java 생성

  • extends RecyclerView.Adapter<데이터Adapter.ViewHolder>
  • public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType){}
  • public void onBindViewHolder(ViewHolder viewHolder, int position){}
  • public int getItemCount(){}
  • static class ViewHolder extends RecyclerView.ViewHolder{} 등등 추가
package org.techtown.recyclerview;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class 데이터Adapter extends RecyclerView.Adapter<데이터Adapter.ViewHolder> {
    ArrayList<데이터> items = new ArrayList<데이터>();

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
        View itemView = inflater.inflate(R.layout.person_item, viewGroup, false);

        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
        데이터 item = items.get(position);
        viewHolder.setItem(item);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder{
        TextView textView; //데이터_item.xml 내부의 요소

        public ViewHolder(View itemView){
            super(itemView);

            textView = itemView.findViewById(R.id.textView);
        }

        public void setItem(데이터 item){
            textView.setText(item.getName());
        }
    }

    public void addItem(데이터 item){
        items.add(item);
    }

    public void setItems(ArrayList<데이터> items){
        this.items = items;
    }

    public 데이터 getItem(int position){
        return items.get(position);
    }

    public void setItem(int position, 데이터 item){
        items.set(position, item);
    }
}

 

5. 원하는 화면(RecyclerView를 포함한 화면)과 관련된.java에 코드 추가

  • LayoutManager 이용해서 recyclerView 레이아웃 설정
  • Adapter 생성 후 addItem
  • RecyclerView에 Adapter을 이용해서 데이터 넘기기
RecyclerView recyclerView = findViewById(R.id.recyclerView);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        PersonAdapter adapter = new PersonAdapter();

        adapter.addItem(new 데이터("데이터1","데이터1속성"));
				adapter.addItem(new 데이터("데이터2","데이터2속성"));
				adapter.addItem(new 데이터("데이터3","데이터3속성"));
        recyclerView.setAdapter(adapter);

 

3학년 2학기 컴퓨터그래픽스 과목에서는 지금까지 배운 그래픽스 이론들을 활용하는

자유 주제의 텀프로젝트가 주어졌다.

개발 형태, 주제, 플랫폼 등 아무런 제한 없이 정말 자유롭게 진행하면 되는 프로젝트였고

나는 유니티3D를 이용한 게임을 개발해보았다.

프로젝트를 시작할 때 나는 유니티를 다뤄본 적이 없었고, 심지어 C#을 공부한 적도 없었다.

지금까지 C언어, 자바, 파이썬 등의 프로그래밍 언어를 배웠기 때문에 프로그래밍에 대한 지식은 있으니까

인터넷에 나온 강좌들을 찾아보면서 공부하는 동시에 개발을 해보기로 했다.

프로젝트 이름은 "치킨런", 닭이 장애물을 피해 병아리를 모아 목표지점에 도달하는 게임이다.

프로젝트 개요 및 목표

개요

장애물을 피해서 목표 지점까지 도달하는 3D 러닝 게임을 제작함

목표

- Unity3D 환경에서 게임을 제작함

- 다양한 컴퓨터그래픽스 이론을 적용하여 프로젝트를 진행함

- 닭이 모든 병아리를 모아서 목표 지점에 도착하는 러닝 게임을 제작함

프로젝트 전체 시스템 구성도

유니티에서 오브젝트에 C# 스크립트를 연결시켜 게임을 개발했다.

먼저 오브젝트는 주요 오브젝트, 장애물 및 지형, 사용자 인터페이스, 그 외의 오브젝트로 나눌 수 있다.

주요 오브젝트는 플레이어의 캐릭터인 닭, 플레이어가 모아야하는 아이템 병아리,

플레이어 시점의 카메라, 게임의 전반적인 관리를 담당하는 게임 매니저가 있다.

맵에 있는 장애물을 간략하게 표현해보았다.

스크립트는 주요 오브젝트, 장애물 및 지형, 그 외에 관련된 스크립트가 있다.

프로젝트 내 주요 기능 설명

카메라가 캐릭터를 잡아주되, 캐릭터와 일정 거리를 유지하면서 이동할 수 있도록 오프셋을 설정한다.

플레이어는 3인칭 시점에서 게임을 플레이한다.

닭의 진로를 방해하는 장애물들은 반복적으로 좌우 또는 상하로 이동한다.

장애물과 닿았을 때, 맵 밖으로 떨어졌을 때 다시 시작 지점에 리스폰된다.

동적인 효과를 주기 위해 애니메이터,애니메이터 컨트롤러를 사용했다.

플레이어의 캐릭터인 닭은 플레이어의 조작에 따라 다른 액션을 취하고

병아리들은 제자리에서 3개의 행동을 반복한다.

프로젝트 설계 방법

이 게임은 PC에서 실행하는 게임이기 때문에 키보드의 방향키를 이용하여 이동하고, 스페이스바로 점프를 한다.

게임 시작과 동시에 타이머가 시작하고 필드에 있는 병아리를 모두 모은 후 목표 지점에 도달하면 게임이 끝난다.

프로젝트 수행 결과

 

 


프로젝트 후기

유니티를 처음 사용한 것 치고는 그래도 나름 게임 같은 결과물이 나왔다.

사실 맵을 완주하는 것은 한 번도 떨어지지 않고 직진하면 1분이 걸려서 굉장히 짧고 간단한 게임이라고 할 수 있다.

그런데 게임 제작을 완료하고 주변 사람들에게 한 번 플레이해보라고 게임 파일을 보내줬는데

10, 14트만에 성공한 친구들도 있었고 대체로 게임이 어렵다는 평을 들었다. 10분 이상 플레이했다고ㅎㅎ

현재 상태에서 개선할만한 점을 몇 가지 생각해보았다.

- 단순히 제자리에서 움직이는 장애물뿐만 아니라 플레이어 캐릭터를 따라오는 인공지능적인? 방해자를 만든다.

- 커브 구간을 추가하여 맵을 다채롭게 만든다. (카메라도 같이 회전)

- 이동 방향에 따라 닭이 바라보는 방향도 자연스럽게 만든다.

- PC뿐만 아니라 모바일 플랫폼에서도 플레이 가능하도록 앱 형식으로 만든다.

 

 

https://github.com/askges20/ChickenRun

 

askges20/ChickenRun

2020-2 컴퓨터그래픽스 프로젝트. Contribute to askges20/ChickenRun development by creating an account on GitHub.

github.com

⬆ 해당 프로젝트는 현재 가상 조이스틱을 이용하여 플레이할 수 있는 앱으로 수정하였으며 GitHub에 업로드되어있다.

+ Recent posts