adsense4


[iPhone][MonoTouch] 6번째 예제: ReactionTime (후편) iPhone

[iPhone][MonoTouch] 6번째 예제: ReactionTime (전편)에 이어서 계속 합니다.

앞의 글에서는 인터페이스빌더를 이용하여 화면 디자인을 하는 것에 대해서 설명했습니다. 이번에는 어플리케이션의 실행 로직을 만들어 보겠습니다.

MainView.cs파일은 메인뷰로서 정의된 UIView클래스입니다. 상위 컨트롤은 MainViewController.cs입니다. 기본적인 로직 작업은 MainView클래스 또는 MainViewController에서 이루어집니다. 이번 작업은 MainView클래스에서 이루어집니다.

필요한 라이브러리의 추가는 C#의 using을 사용합니다. 코드 추천기능이 충실히 되어 있어 그림처럼 편하게 작업 하실 수 있습니다.
iPhone SDK의 클래스들은 MonoTouch네임스페이스에 대부분 모여있습니다. MonoTouch.UIKit은 UI관련 대부분의 클래스를 정의 하고 있습니다.

어플리케이션을 처음 실행 시에 게임 시작을 알려주기 위해 AlertView를 사용하겠습니다. UIAlertView의 생성시 버튼 클릭의 이벤트를 처리하기 위해 UIAlertViewDelegate클래스가 필요합니다. "ClickedAlert"이름으로 UIAlertViewDelegate클래스를 정의합니다.
클래스 선언시 상속에 대한 부모 클래스 선택도 그림처럼 개발툴에서 지원해 줍니다. 추가된 클래스에 필요한 이벤트 메소드를 추가 합니다.
다른 클래스에도 적용되는 것입니다만, 각 클래스에서 제공하는 메소드를 재정의 하기 위해서 override 키워드를 사용합니다. 그림은 override를 입력한 후 현재 클래스에서 재정의 가능한 메소드 리스트가 제공되는 화면입니다. AlertView의 이벤트 처리를 위해 "Dismissed(UIAlertView, int)"를 정의 하겠습니다. 전체 클래스 소스는 다음과 같습니다.
namespace ReactionTime
{
public class ClickedAlert : UIAlertViewDelegate
{
MainView _mv; .....①
public ClickedAlert(MainView view)
{
_mv = view;
}

public override void Dismissed (UIAlertView alertView, int buttonIndex) ..... ②
{
_mv.Dismissed(alertView, buttonIndex); ...... ③
}

}
①은 메인뷰를 참조하기 위해 정의합니다.
②는 AlertView의 버튼(이번 예제에선 버튼이 한개뿐입니다.)을 클릭 했을 때 처리하는 이벤트 메소드입니다. 해당 델리게이트를 호출하는 AlertView가 첫번째 파라미터로 전달됩니다. 클릭된 버튼의 인덱스 번호가 buttonIndex로 전달됩니다.
③은 메인뷰의 함수를 호출하는 코드입니다.

코드를 보며 설명합니다. ClickedAlert 클래스에 대한 설명은 앞에서 했습니다.
using MonoTouch.UIKit;
using System.Drawing;
using MonoTouch.Foundation;
using System;

namespace ReactionTime
{
public class ClickedAlert : UIAlertViewDelegate
{
MainView _mv;
public ClickedAlert(MainView view)
{
_mv = view;
}

public override void Dismissed (UIAlertView alertView, int buttonIndex)
{
_mv.Dismissed(alertView, buttonIndex);
}

}

public partial class MainView : UIView
{
int greenLightOn = 0; .... ①
DateTime startDate; .... ②

public MainView (IntPtr handle) : base(handle)
{
}

public override void Draw (RectangleF rect)
{
//Drawing code
}

public override void AwakeFromNib () .... ③
{
base.AwakeFromNib ();
UIAlertView alert = new UIAlertView("Reaction Time: 준비"
, "녹색 등이 켜진 후 가능한 빨리 발바닥 패달을 터치해 주세요."
, new ClickedAlert(this) .... ④
, "Play"
, null);

alert.Show();
}


public void Dismissed(UIAlertView alertView, int buttonIndex) .... ⑤
{
stopLight.Image = UIImage.FromFile("yellowLightSmall.png"); .... ⑥
greenLightOn = 0;

NSTimer.CreateScheduledTimer(TimeSpan.FromSeconds(2.0f), onYellowLightTimer); .... ⑦
}

public void onYellowLightTimer()
{
Console.WriteLine("onYellowLightTimer");
stopLight.Image = UIImage.FromFile("redLightSmall.png"); .... ⑥

Random rand = new Random(); .... ⑧
int delay = (rand.Next() % 7) + 1;
Console.WriteLine(" delay = {0}", delay);

NSTimer.CreateScheduledTimer(TimeSpan.FromSeconds(3.0f+delay), onRedLightTimer); .... ⑦
}

public void onRedLightTimer()
{
Console.WriteLine("onRedLightTimer");
stopLight.Image = UIImage.FromFile("greenLightSmall.png"); .... ⑥

greenLightOn = 1;
startDate = DateTime.Now;
}

partial void gasPedalPressed (UIButton sender) .... ⑨
{
TimeSpan period = DateTime.Now.Subtract(startDate); .... ⑩
double noSeconds = (double)(period.TotalMilliseconds);

String reactionTime = String.Format(" 반응 시간은 {0:0.} milliseconds. 더 빨리 눌러 보셔~", noSeconds);

if(greenLightOn == 0) reactionTime = "녹색 등이 켜질 때까지 기다리기! 성격이 급하긴...";

UIAlertView alert = new UIAlertView("ReactionTime"
, reactionTime
, new ClickedAlert(this)
, "OK", null);
alert.Show();
}

}
}
① 녹색등이 켜진 상태인지를 검사하기 위한 변수를 선언합니다.

② 패달을 클릭할 때까지의 반응 시간을 측정하기 위해 사용되는 변수를 선언합니다.

③ "AwakeFromNib"함수를 정의 합니다. 이 함수는 xib를 읽어 정의된 객체들의 인스턴스 변수들의 생성이 완료되었을 때 호출되는 함수입니다. 따라서 처음 실행 되었을 때 필요한 작업은 이곳에서 하면 됩니다.

④ UIAlertView를 생성해서 표시하는 코드입니다.
UIAlertView alert = new UIAlertView("Reaction Time: 준비"
, "녹색 등이 켜진 후 가능한 빨리 발바닥 패달을 터치해 주세요."
, new ClickedAlert(this)
, "Play"
, null);

alert.Show();
생성시에 필요한 파라미터를 지정하는 방법이 5가지가 있는데 그 중에 다음을 사용하여 정의합니다.
파라미터는 순서대로 타이틀, 내용, 델리게이트, 버튼의 타이틀, 추가 버튼 정의 입니다. 추가 버튼은 없으므로 null을 전달합니다. 화면에 표시는 alert.Show();를 호출합니다. 버튼 클릭에 대한 처리는 ClickedAlert 델리게이트 클래스에서 처리됩니다.

⑤ Dismissed함수는 ClickedAlert함수에서 호출됩니다.

⑥ stopLight는 인터페이스빌더를 통해 신호등 이미지를 지정한 UIImageView입니다. 프로그래 적으로 내부의 UIImage의 내용을 지정해 줌으로서 변경이 가능합니다. 각각 3개의 신호등 이미지를 지정해서 변경합니다. 이미지 파일에서 UIImage객체를 생성하는 방법은 UIImage.FromFile(이미지파일이름)을 사용하면 됩니다.
UIImage image = UIImage.FromFile("이미지파일이름"); 
이미지를 다룰때 자주 사용됩니다. 잘 기억해 두세요.

⑦ 타이머를 선언 하는 코드입니다. 타이머를 생성하는 함수는 크게 3가지가 있습니다.
NSTimer NSTimer.CreateRepeatingScheduledTimer(); // 일반적으로 반복되는 타이머의 경우 사용됩니다. 지정된 시간 간격으로 호출됩니다.
NSTimer NSTimer.CreateRepeatingTimer(); // 반복되는 타이머 선언입니다.
NSTimer NSTimer.CreateScheduledTimer(); // 단발성 타이머의 경우 사용됩니다. 지정된 시간 후에 호출됩니다.
예제에서는 세번째 CreateScheduledTimer를 사용합니다. 파라미터 지정은 두가지 방법이 있습니다. 한가지는 XCode와 같이 지정하는 방법입니다. 타이머에 데이터를 전달하거나 하는 추가 정보가 있을 때 사용할 수 있습니다. 두번째는 간략화 된 방법입니다. 필요한 시간과 호출된 함수를 정의 해 주면 됩니다.
코드에서 보듯이 시간 지정도 C#의 TimeSpan클래스를 사용하여 지정하며, 호출되는 함수는 간단히 멤버 함수를 지정해 주는 것으로 끝납니다.  시간은 TimeSpan의 함수들 중에 초단위로 지정하는 경우 TimeSpan.FromSeconds(초)를 사용합니다.

⑧ MonoTouch에서 임의의 수를 생성하는 경우에 Random클래스를 이용합니다. 사용하는 방법은 다음 코드처럼 사용합니다.
Random rand = new Random();
int a = rand.Next();
rand.Next()를 호출하면 1~ 정수 최대값 범위에서 임의의 수를 반환합니다. 실수를 원하는 경우는 다른 함수를 사용하시면 됩니다. 예제에서는 이렇게 얻은 수를 1~7사이의 수로 변환한 후 타이머의 시작 시간 정의에 사용합니다. 코드에서 보면 최대 4초~10초 사이의 간격으로 움직이게 됩니다.

⑨ 인터페이스빌더에서 정의한 Action의 이벤트를 정의한 함수 입니다. partial타입으로 정의되어 있기 때문에 편집기에서 partial을 입력하면 자동으로 현재 정의 가능한 Action의 리스트를 보여줍니다. 간단히 선택하는 것으로 수정 가능한 상태가 됩니다.
선택 후의 코드는 다음과 같습니다.
		partial void gasPedalPressed (UIButton sender)
{

}
파라미터는 연결된 이벤트의 종류에 따라 자동으로 정의됩니다. 이번엔 UIButton입니다.

⑩ 날짜나 시간을 계산하는데 MonoTouch에서 제공하는(정확히는 C#의 라이브러리) DateTime과 TimeSpan을 사용하면 편하게 계산할 수 있습니다. 녹색등이 켜진 상태에 측정된 시간은 startDate 변수에 저장합니다. 그 후 페달 버튼을 눌렀을 경우의 시간(DateTime.Now)에서 startDate시간을 뺀 것이 반응 시간이 되는 것입니다.
TimeSpan period = DateTime.Now.Subtract(startDate);
이렇게 얻는 시간을 원하는 단위로 변환하여 표시하면 되는 것입니다. 결과를 표시 하기 위해서 UIAlertView를 사용하고 있습니다.

전체적으로 코드가 실행되는 흐름은 다음과 같습니다.
                        AwakeFromNib
                        ↓
                        Dismissed                : UIAlertView의 버튼 클릭시 호출, Timer정의(onYellowLightTimer)
                        ↓
                        onYellowLightTimer  : 이미지를 빨간등으로 변경, Timer정의(onRegLightTimer)
                        ↓
                        onRedLightTimer     : 이미지를 녹색등으로 변경, 최종 반응시간 측정을 위한 시간 저장, 사용자 반응 기다림
                        ↓
                        gasPedalPressed     : 페달 버튼을 클릭 했을 때 호출, 시간 계산하여 반응시간을 UIAlertView로 알림.
                        ↓
                        Dismissed                : 반복
                        ...

무한 반복되는 어플리케이션입니다. 나름 시간을 줄이기 위해 노력하면 재미있습니다.

FlipsideView.xib은 간단히 어플리케이션에 대한 정보를 제공하는 역할 이외에 하지 않습니다. 인터페이스빌더를 실행시켜 디자인 할 화면은 다음과 같습니다.
간단히 Title을 "Reaction Time"으로 변경하는 것으로 끝내겠습니다. 수정 후에 저장하고 인터페이스빌더를 종료합니다.

모든 작업이 끝났으면 컴파일하여 실행시켜 봅니다.
현재 예제에는 한가지 문제가 있습니다. 동작 중에 "info Button"을 클릭하면 FlipsideView가 표시 되지만, 타이머는 계속 동작을 합니다. 그 부분을 해결하면 간단한 게임으로서 충분한 역할을 할 수 있을 것이라 생각합니다.

여섯번째 예제는 이것으로 마칩니다.

샘플 소스 : ReactionTime.zip





 

통계 위젯 (화이트)

67
50
400459

160x600스크래퍼

네이버Analysis