접속화면을 멋있게

2007.04.12 11:45

그리움 조회 수:165 추천:45

이니님 글 퍼옴


안녕하세요.



이번 강좌 에서는 접속 화면을 꾸며보겠습니다.

어떻게 화면을 바꿀건지 생각해 볼까요?



1. 안시를 이용한 멋있는 대기 화면 (?)
2. 접속시에 현재 게임중인 플레이어 리스트 표시

3. 현재 사용자 수 표시

4. 접속 화면에서 엔터 칠것인지 여부



이렇게 4개를 한번 구성해 보겠습니다. 저렇게 하면 멋있는 접속 대기 화면이

되겠죠?

우선, Io.C 를 참고 해야 합니다. 이 파일에 접속 대기 화면 함수가 포함되어
있습니다.
            
우선, 대기 화면을 멋있게 바꿔야 합니다.

..oooOOOooo...oooOOOooo...oooOOOooo...oooOOOooo...oooOOOooo...oooOOOooo..
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                       판타지아에 오신것을 환영 합니다
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

                               판 타 지 아 I

                             저) 첼린저 소프트
                   이니, 메샤, 푸른매, 쿠루, 용아, 유리병

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

   * 현재 사용자 (15/50) *

   이니, 사랑, 시니, 쿠루, 용아, 푸른매, 타이, 메샤, 유리병, 첼린저,
   판타지아, 마이크로, 카즈야, 동성, 하이.


이 화면은 판타지아 머드의 대기 화면입니다. LP 머드는 현재 인원을 쉽게
표시할수 있다고 합니다. 하지만, Mordor 에서는 이런 기능이 없죠. 하지만
간단히 응용해서 만들수 있습니다.

'누구' 명령어를 응용해서 만들면 되는데요, 한번 다음 루틴을 볼까요?

for(i=0; i    if(!Ply[i].ply) continue;
  if(Ply[i].ply->fd == -1) continue;
  print(fd, "%s, ", Ply[i].ply->name);
  }

자, 이렇게 하면 현재 사용중인 모든 사용자가 화면에 찍히게 됩니다. 하지만
너무 부족한게 많죠? 프로그래머는 사용자의 많은 경우를 생각하여야 합니다.
그래서 머리가 뿌개지는것이 프로그래머죠. ^^;

저렇게 하면 관리까지 찍힐텐데, 투명인 관리도 찍히면 안되겠죠? 우리는
관리 보강 루틴을 만들어야만 합니다. -_-+

for(i=0; i    if(!Ply[i].ply) continue;
  if(Ply[i].ply->fd == -1) continue;
  if(F_ISSET(Ply[i].ply, PDMINV)) continue; // 투명인 관리는 뛰어 넘음
  print(fd, "%s, ", Ply[i].ply->name);
}

continue가 무엇 일까요. for 문이나, while 문에서는 break, continue 문을
자주 보게 됩니다. 차이점을 알아볼까요.

break : 현재 루프를 끝냄
continue : 루프의 끝으로 이동

만약에, 위의 continue 대신 break 를 넣게되면, 저 조건에 맞지 않아서 break
문이 실행된다면, 뒤에 있는 사용자도 모두 넘어가 버리게 됩니다. 아시겠지요?

PDMINV는 플레이어 플래그 코드 입니다. On / Off 로 되어 있지요. 그러면
플레그 앞에 있는 F_ISSET 은 무엇일까요. 이것은 간단히 만들어 놓은
함수 입니다. (Mtype.H 참조) 플레그가 On 인지 Off 인지 알아내주는 함수이죠.
플레그에 관한 함수를 알아볼까요?
                              
F_SET : 플레그를 On
F_CLR : 플레그를 Off
F_ISSET : 플레그의 여부를 알아다줌

저 위의 비교문은 만약, PDMINV가 On 이면 넘어가라는 뜻이지요. 저렇게 하면
관리는 뛰어넘게 되겠죠.

하지만, 또 하나 생각할게 있습니다. 만약에 위처럼 표현을 한다면 이렇게
찍혀나올 겁니다.

..oooOOOooo...oooOOOooo...oooOOOooo...oooOOOooo...oooOOOooo...oooOOOooo..
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                       판타지아에 오신것을 환영 합니다
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    
                               판 타 지 아 I

                             저) 첼린저 소프트
                   이니, 메샤, 푸른매, 쿠루, 용아, 유리병

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

   * 현재 사용자 (15/50) *

   이니, 사랑, 시니, 쿠루, 용아, 푸른매, 타이, 메샤, 유리병, 첼린저, 판타지?
,
마이크로, 카즈야, 동성, 하이,


무엇이 잘못 되어 있는 걸까요. 2군데가 있습니다. 아이디가 한줄이 넘으면
줄이 정리되지 않고 바로 줄 맨 앞으로 넘어가 버리지요? 그리고, 맨 마지막은
마침표로 끝나야 하는데, 위처럼 코딩을 하니깐 콤마로 끝나네요.

그러면 어떻게 해결을 해야 할까요?

for(i=0; i    if(!Ply[i].ply) continue;
  if(Ply[i].ply->fd == -1) continue;
  if(F_ISSET(Ply[i].ply, PDMINV)) continue;
  sprintf(strs, "%s, ", Ply[i].ply->name);
  strcat(str, strs);
  if (strlen(str) >= 65) {
     print(fd, str);
     print(fd, "\n ");
     str[0] = 0;
  }
}

이렇게 코딩을 해보았습니다. str 이라는 변수를 하나 만들고, 그곳에 문자열을
저장해서 찍는 방법을 구현해 보았지요. 하지만, 이것도 문제가 있군요. 바로
넘어간 줄이 짤린다는 거지요.


   *
현재 사용자 (15/50) *

   이니, 사랑, 시니, 쿠루, 용아, 푸른매, 타이, 메샤, 유리병, 첼린저, 판타지?
,


이렇게만 찍힐것 같군요. 나머지 사용자는 어디 간거지. -_-+
그러면 어떻게 해야 할까요? 맨 마지막에 나머지 str을 찍어주는 루틴을 만들면
될것 같군요. 하지만 만약에 str이 NULL이면 어떻게 하죠? 그러면 str이 존재
할때만 출력하게 루틴을 만들어 주면 되겠네요.

for(i=0; i    if(!Ply[i].ply) continue;
  if(Ply[i].ply->fd == -1) continue;
  if(F_ISSET(Ply[i].ply, PDMINV)) continue;
  n = 1;
  sprintf(strs, "%s, ", Ply[i].ply->name);
  strcat(str, strs);
  if (strlen(str) >= 65) {
     print(fd, str);
     print(fd, "\n ");
     str[0] = 0;
     n = 0;
  }
}

if (n == 1) print(fd, str);

여기서는, n 이라는 변수를 만들어서 str에 문자를 쓰면 n 을 1로 만들어
주었습니다. 한줄이 넘어가서 이미 찍으면 n 을 다시 청소해 주지요.
이렇게 변수를 이용하는 방법이 있고, strlen(str) > 0 이렇게 비교를 해서
찍어주는 방법도 있지요.

for(i=0; i    if(!Ply[i].ply) continue;
  if(Ply[i].ply->fd == -1) continue;
  if(F_ISSET(Ply[i].ply, PDMINV)) continue;
  sprintf(strs, "%s, ", Ply[i].ply->name);
  strcat(str, strs);
  if (strlen(str) >= 65) {
     print(fd, str);
     print(fd, "\n ");
     str[0] = 0;
  }
}

if (strlen(str) > 0) print(fd, str); // if (str[0] > 0) print(fd, str);

이런 식으로 간단히 해줄수도 있겠죠? 제가 쓰는 // 주석문은 Gcc 에서는
오류가 발생합니다. T.T 그대로 가져다가 컴파일 하시면 안되요.

자, 이런 방식으로 하면 다음과 같이 나올껍니다.


   * 현재 사용자 (15/50) *

   이니, 사랑, 시니, 쿠루, 용아, 푸른매, 타이, 메샤, 유리병, 첼린저,
   판타지아, 마이크로, 카즈야, 동성, 하이,


정말 잘 나오는군요. 마지막의 콤마는 어떻게 처리할까요. 또 현재 사용자의
사용자 숫자는 어떻게 처리 할까요?

현재 사용자의 숫자 처리 법을 한번 연구해 봅시다.

total = 0;
for(i=0; i    if(!Ply[i].ply) continue;
  if(Ply[i].ply->fd == -1) continue;
  if(F_ISSET(Ply[i].ply, PDMINV)) continue;
  total++;
}

이렇게 하면, 현재 사용자의 숫자를 알수 있겠네요. 물론 사용자 표시줄에
넣을수도 있겠지만, 다른 부분의 응용을 위하여 따로 떨어뜨려 놓았습니다.
저 소스는 맨 앞에 넣어야 합니다.

그러면, 현재 사용자를 알수 있을겁니다. 그러면 콤마를 처리하려면 어떻게
해야할까요. strs 에 문자를 넣어줄때, 현재 쓰는 횟수를 처리하여, 총 사용자와
숫자가 같으면 마침표를 넣어주고 아니면 콤마를 넣어주면 어떻까요?
  

total = 0;
for(i=0; i    if(!Ply[i].ply) continue;
  if(Ply[i].ply->fd == -1) continue;
  if(F_ISSET(Ply[i].ply, PDMINV)) continue;
  total++;
}

j = 0;
for(i=0; i    if(!Ply[i].ply) continue;
  if(Ply[i].ply->fd == -1) continue;
  if(F_ISSET(Ply[i].ply, PDMINV)) continue;
  j++;
  if (j == total) sprintf(strs, "%s.",
Ply[i].ply->name);
             else sprintf(strs, "%s, ", Ply[i].ply->name);
  strcat(str, strs);
  if (strlen(str) >= 65) {
     print(fd, str);
     print(fd, "\n ");
     str[0] = 0;
     n = 0;
  }
}

if (total == 0) print(fd, "없음.");
if (n == 1) print(fd, str);
      
자, 이렇게 하면 이렇게 완벽히 출력이 되
겠네요. 인원수가 없을때 "없음."도
표시해주게 하였고요. ^^:


   * 현재 사용자 (15/50) *

   이니, 사랑, 시니, 쿠루, 용아, 푸른매, 타이, 메샤, 유리병, 첼린저,
   판타지아, 마이크로, 카즈야, 동성, 하이.


Mordor 가 지원하는 변수도 몇몇 있습니다. (Numplayers 등) 하지만 알수없는
버그 집합 Mordor 보다는 우리가 직접 제작 하여 쓰는것이 더 현명할것 같습
니다. ^^;
      
자, 그러면 이제 대기 화면에서 엔터를 치는것을 알아볼까요. Mordor 를 보면
엔터를 입력 받는 곳을 전혀 볼수가 없습니다. 이것은 한글판 무한대전에만
있는 건데요. 이것이 때로는 불편할때가 있습니다. 이걸 고쳐 볼까요.

output_buf();
RETURN(fd, login, -1);

한글판 무한대전의 접속 대기화면 함수의 맨 끝부분 입니다. Command1.C의
login 으로 넘겨주는 건데요, -1 을 넘겨주어 엔터를 입력받게 하는거죠.

여기서 간단히 엔터를 입력 안받고 아이디를 입력받게 고칠수 있습니다.
다음과 같이 해볼까요?

print(fd, "당신의 아이디를 입력해 주십시오 : ");
output_buf();
RETURN(fd, login, 1);

이렇게 하면, login 의 아이디 판단 부분으로 바로 뛰어 넘어서 엔터를 입력
받는 부분을 뛰어 넘게 됩니다.

그러면 대충 설명이 끝났네요. 전체 소스를 볼까요?
Io.C 입니다.

/************************************************************************/
/* init_connect */
/************************************************************************/

/* This function sets up the player using the fd'th input socket. */

void init_connect(fd)
int fd;
{
   int i, total = 0, j = 0, n = 0;
    /* Total 은 현재 사용자, J 는 현재 처리하는 사용자 번호, N 은 str이
       비어 있는지의 여부 */
   char str[255], strs[255];
    /* 임시 문자 변수 */

   str[0] = 0; /* 초기화 */
   for(i=0; i     if(!Ply[i].ply) continue;
   if(Ply[i].ply->fd == -1) continue;
   if(F_ISSET(Ply[i].ply, PDMINV)) continue; /* 투명이면 뛰어 넘음 */
   total++; }
        
   print(fd, "\n←[40m←[0;37m..oooOOOooo...oooOOOooo...oooOOOooo...oooOOOooo...oooOOOooo...oooOOOooo..");
   print(fd, "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
   print(fd, "\n ←[1;37m판타지아←0;37m에 오신것을 환영합니다. ");

   print(fd, "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
   print(fd, "\n");
   print(fd, "\n ←[1;37m판 아 ←[1;33mI0;37m");
   print(fd, "\n");
   print(fd, "\n 저) ←[1;32m첼저 소프트←[0;37m");
   print(fd, "\n 이니, 메샤, 푸른매, 쿠, 용아, 유리병");
   print(fd, "\n");
   print(fd, "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=
-=-=-=-=-=");
   print(fd, "\n");
   print(fd, "\n * 현재 사용자 (%02d/50) *", total);
    /* 현재 사용자를 (00/50) 이런 형식으로 표현. %02d! */
   print(fd, "\n ");

   if (total != 0) {
   j = 0;
   for(i=0; i      if(!Ply[i].ply) continue;
    if(Ply[i].ply->fd == -1) continue;
    if(F_ISSET(Ply[i].ply, PDMINV)) continue;
    j++;
    n = 1;
    if (j == total) sprintf(strs, "%s.", Ply[i].ply->name);
           else sprintf(strs, "%s, ", Ply[i].ply->name);
     /* 현재 마지막 사용자를 처리하고 있으면 마침표를 찍고 아니면 콤마를! */
    strcat(str, strs);
    if (strlen(str) >= 65) { /* 1줄 (65열)이 넘으면 다음줄로 넘김 */
     print(fd, str);
     print(fd, "\n ");
     str[0] = 0;
     n = 0;
    }
   }
   }

   if (total == 0) print(fd, "없음."); /* 사용자가 없으면.. */
   if (n == 1) print(fd, str); /* str이 비어 있지 않으면 */

   print(fd, "\n ");
   print(fd, "\n [Enter]를 누르십시
?

");
   print(fd, "\n ");
   print(fd, "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");

   Ply[fd].io->intrpt |= 2;
   Numplayers++; /* Mordor의 최대 사용자 수 */
                                                                        

   Ply[fd].io->ltime = time(0); /* 로긴 시각 */
   output_buf();
   RETURN(fd, login, -1); /* 엔터를 치게 넘김 */

}

이 소스를 Io.C 에 붙여서 사용하심도 좋을것 같습니다. 하지만 그대로 옮겨서
쓰기보다는 자기만의 머드를 만드는게 중요하겠죠.


홈지기 "그륨"


XE Login