블로그 이미지
내게 능력 주시는 자 안에서 내가 모든것을 할수 있느니라 - 빌립보서 4 : 13 - happydong

카테고리

Happydong (1363)
프로그래밍 (156)
MUSIC (16)
인물 (3)
Utility (10)
세미나 소식&내용 (22)
IT뉴스 (18)
운동 (830)
CAFE (10)
Life (282)
Total
Today
Yesterday



 자바(JAVA)를 처음 공부하면서 간단하게 만들어 본 스윙(Swing) 프로젝트이다. 

 역시 만들면서 배우는게 빠르기 때문에 몰 만들어 볼까 고민하다, 옛날에 실버라이트로 만들던 게임(?!)인 "같은그림 찾기" 게임을 만들어 보기로 결심하고 모르는 부분은 구글링하면서 만들어 보았다. 비록, 허접하지만 저와 같이 스터디를 시작한 분들에게 도움이 되길 바란다. 


1. 작동 모습


[그림 1 - 시작 화면]


[그림 2 - 게임 진행화면]



[영상 1 - 실행화면]


2. 프로젝트 구성



[그림 3 - 프로젝트 구성]


[그림 4 - 프로젝트 파일 설명]



※ 프로젝트 전체 소스 ↓↓


StudyPhotoGame.zip




Posted by happydong
, |



Get Microsoft Silverlight
Posted by happydong
, |



Silverlight게임 만들기 빨리 진행을 해서 끝내야 하는데제가 회사일 때문에 조금 바빠서리자꾸 늦어 지네요~^^;;아주 혹시나 제 글을 관심 있게 봐주시는 분들에게 죄송하다는 말을 드리고 싶네요~^^;;

그럼 지난 강좌를 이어가도록 하겠습니다. 지난번 시간에는 랜덤함수를 이용해서 이미지들을 생성해서 보여주는 것까지 코드를 짜보았습니다. 이번 시간에는 간단하게 Blend를 이용해서 여러 가지 Storyboard만들어 볼 것이며, 같은 그림을 클릭했을 때 이미지가 지워지도록 만들어 볼 것입니다. ~ 그럼 지난 시간까지 무리 없이 잘 따라오셨다면 Blend를 실행시키시고 해당 프로젝트를 열어주세요. 프로젝트가 다 열리셨다면 Photo.xaml파일을 클릭해서 열어 주세요~

사용자 삽입 이미지


위 그림과 같이 열리셨다면 Rectangle객체를 선택을 해서 전에 만들었던 Image객체 위 크기와 높이를 똑같이 합니다. (Left Top 0 이며, Rectangle객체는 img_back(Canvas객체)의 하위에 생성하지 않습니다.) 속성설정은 아래 그림과 같으며 혹시나 해서 코드소스를 같이 붙어 드립니다^^ 그리고 혹시 객체 색을 어떻게 지정하는지 궁금하신 분들은 [무한도전]Silverlight 메뉴바 만들기(3)를 참고 하세요~!

사용자 삽입 이미지

Photo.xaml 페이지

<Rectangle Width="96" Height="96" Stroke="#FF000000" x:Name="imghide" Opacity="1" RenderTransformOrigin="0.5,0.5" Cursor="Hand">

<Rectangle.RenderTransform>

<TransformGroup>

<ScaleTransform ScaleX="1" ScaleY="1"/>

<SkewTransform AngleX="0" AngleY="0"/>

<RotateTransform Angle="0"/>

<TranslateTransform X="0" Y="0"/>

</TransformGroup>

</Rectangle.RenderTransform>

<Rectangle.Fill>

<LinearGradientBrush EndPoint="0.505,0" StartPoint="0.5,0.979">

<GradientStop Color="#FF2A2A2A" Offset="0.019"/>

<GradientStop Color="#FF474646" Offset="0.538"/>

<GradientStop Color="#FF414141" Offset="0.486"/>

<GradientStop Color="#FF999999" Offset="0.923"/>

<GradientStop Color="#FF333333" Offset="0.269"/>

</LinearGradientBrush>

</Rectangle.Fill>

</Rectangle>


위 코드는 img_back(Canvas객체) 바로 아래에 넣으시면 되고,그렇게 생성이 될 것 입니다^^

 

이제는 몇가지 Storyboard를 만들어 보도록 하겠습니다. 이 부분은 그림으로 하나하나 캡쳐뜨는 것이 너무 많을 것 같아서 동영상으로 찍어 보았습니다. ^^;;처음 찍어보는 거라 좀 쓱쓰럽네요~^^그래도 혹시 Blend에 익숙하지 않은 분들에게 도움이 되셨으면 좋겠습니다~

참고로 마이크가 없는 관계로 말로 설명을 하지 못했습니다. 다소 보는데 불편하시더라고 이해해주세요~!^^;;;

 



두개의 StoryBoard를 말들었습니다. 하나는 Photobig이고, 하나는 Photosmall입니다.

각각의 행위는 아래와 같습니다.

  Photobig : 사용자가 클릭을 했을 때 객체가 커지면서 이미지가 보여지는 StoryBoard.

Photosmall : 같은 그림이 아닐경우 객체가 작아지면서 이미지가 보이지 않는 StoryBoard.

 

생성된 코드는 아래와 같습니다.

Photo.xaml 페이지

<Canvas.Resources>

<Storyboard x:Name="Photobig">

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="img_back" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1.25"/>

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="img_back" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1.25"/>

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imghide" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1.25"/>

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imghide" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1.25"/>

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imghide" Storyboard.TargetProperty="(UIElement.Opacity)">

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0"/>

</DoubleAnimationUsingKeyFrames>

</Storyboard>

<Storyboard x:Name="Photosmall">

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="img_back" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">

<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.25"/>

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imghide" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">

<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.25"/>

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="img_back" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">

<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.25"/>

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imghide" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">

<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.25"/>

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>

</DoubleAnimationUsingKeyFrames>

<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="imghide" Storyboard.TargetProperty="(UIElement.Opacity)">

<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>

<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>

</DoubleAnimationUsingKeyFrames>

</Storyboard>

</Canvas.Resources>

<!-- 전에 있던 코드에서 코드가 조금 추가 되었습니다. 유의하세요~! -->

<Canvas Width="96" Height="96" Canvas.Left="0" Canvas.Top="0" x:Name="img_back" RenderTransformOrigin="0.5,0.5">

<Canvas.RenderTransform>

<TransformGroup>

<ScaleTransform ScaleX="1" ScaleY="1"/>

<SkewTransform AngleX="0" AngleY="0"/>

<RotateTransform Angle="0"/>

<TranslateTransform X="0" Y="0"/>

</TransformGroup>

</Canvas.RenderTransform>

<Image Width="96" Height="96" Stretch="Fill" x:Name="image1">

</Image>

</Canvas>


이제 StoryBoard가 만들어 졌으니깐 같은 그림일 때 지워지고 같은 그림이 아니라면 다시 원래되로 돌아가는 소스코드를 짜보도록 하겠습니다. 먼저 Photo페이지의 cs코드부분 열어주시고, 아래 코드들를 입력 합니다.

(참고로 아래 코드들은 전에 작성했던 코드에 추가적으로 들어가는 코드이니 혼동없으시길 바랍니다)

 

Photo.xaml.cs 페이지 (전역변수 선언)

기존 코드 생략

// 클릭을 했는지 여부를 확인 하기위한

bool _Mousedown = false;

 

Photo.xaml.cs 페이지 (Property)

/// <summary>

/// 객체가 클릭 여부를 지정하거나 반환

/// </summary>

public bool MouseDown

{

            get { return _Mousedown; }

            set { _Mousedown = value; }

}

 

위 변수는 사용자가 한객체를 여러 번 클릭하는 행위를 방지하기 위해서 선언한 것 이며,

Property를 통해서 Page클래스에서 확인할수 있습니다.

 

Photo.xaml.cs 페이지

public Photo(Page page,Downloader down ,String URL)

{

    기존 코드 생략

    // 객체 클릭 이벤트 생성

this.MouseLeftButtonDown += new MouseEventHandler(Photo_MouseLeftButtonDown);

}

void Photo_MouseLeftButtonDown(object sender, MouseEventArgs e)

{

 // Page클래스의 SetPoint에 접근

_Page.SetPoint(this, _root);

}

 

SetPoint를 아래코드에서도 알수 있겠지만 접근제한자가 internal이여서 접근이 가능하며, 인자값으로 자신(Photo) _root(FrameworkElement)를 받고 있습니다. Page클래스 단에서 쉽게 Photo클래스를 컨트롤 하기 위해서 입니다.

 

Photo.xaml.cs 페이지 (Property)

/// <summary>

/// 객체의 이미지 URL값을 반환

/// </summary>

public string getUrl

{

get { return _URL; }

}


Property Page클래스에서 같은 그림인지 아닌지 확인 하기위해서 만든 것입니다. , 같은 그림인지 여부는 URL값으로 확인 할수 있습니다. 이제 대충 어떻게 해야하는지 감을 잡으신 분들분 계실 것 같군요~!^^이제 Page.xaml.cs페이지에서 코드를 짜보도록 하겠습니다. 먼전 변수 선선언부부터 하도록 하겠습니다 .

 

Page.xaml.cs 페이지 (전역변수 선언)

기존 코드 생략

 

// 사용자의 두번 클릭을 위한 전역 변수

int number = 0;

// 선택한 두개의 이미지 확인을 위한 Photo 배열

private Photo[] _ImgArray = new Photo[2];

// Photo FramworkElement 생성 각각의 StoryBoard 두개를 실행하기 위함.

private FrameworkElement[] _ROOT = new FrameworkElement[2];

 

보시기 편하게 주석으로 각각의 변수가 어떻게 쓰여질지 작성해 봤습니다.다음은 SetPoint부분의 코드를 작성해 보겠습니다.

 

Page.xaml.cs 페이지

internal void SetPoint(Photo photo, FrameworkElement root)

{

// 사용자가 막 클릭하는 걸 방지..딱 두번만 클릭관련 조건~!

if (number < 2)

{

// 스크린 Canvas에서 이미지 삭제

screen.Children.Remove(photo);

// 스크린 Canvas에 이미지 다시 추가

screen.Children.Add(photo);

 

//같은 그림들 두번 클릭하면 안됨. 그래서 해당 Photo에 마우스클릭을 했었는지 확인함.

if (!photo.MouseDown)

{

photo.MouseDown = true;

// Photo에 있는 StoryBoard를 생성하기.

Storyboard Photobig = root.FindName("Photobig") as Storyboard;

Photobig.Begin();

 

_ImgArray[number] = photo;

_ROOT[number] = root;

number++;

if (_ImgArray[1] != null)

{

// 두번째로 찍은 이미지이면 스토리보드 실행후 이벤트 발생함

Photobig.Completed += new EventHandler(Photobig_Completed);

}

}

}

}


위 코드는 주석을 통해서도 대충 이해하실수 있을 것이라고 생각이 됩니다. 조금 이상하게 보일 부분이 이미지를 삭제하고 추가하는 부분일텐데요. 이 부분은 왜 이렇게 했냐면
사용자 정의 컨트롤이 for문을 돌면서 동적으로 생성이 되다 보니깐 먼저 생성된 것들은 제일 마지막에 생성된 객체의 밑에 있게됩니다. 만약 사용자가 제일 밑에 있는 객체을 클릭했다고 했을 때 그 객체의 StoryBoard는 어떻게 되겠습니까? 상상이 가시나요~^^ 제일 위에 있는 객체에 겹치게 되어서 제일 위에 있는 객체 위로 못올라 오게 됩니다. 그럼 클릭한 객체의 zindex값을 조정해 주면 되지 않을까 생각하시는 분이 있을까 생각이 됩니다. 저 또한 그렇게 생각을 했으니깐요.그래서  사용자 정의 컨트롤의 최상위 Canvas zindex값을 조정해 봤는데 안되더군요~^^;; 나름 고민과 좌절을 겪고 있던중 문득 생각이 난 것이 새로 추가하면 위로 가지 않을까 싶어서 삭제후 다시 추가를 했던 것 입니다~^^;;그러니 내가 원하던데로 움직이니정말 좋았습니다.ㅋㅋ 음..다음 조건들은 주석에서도 설명하고 있듯이 사용자가 객체 클릭횟수를 조절하기 위함이고요, 그 다음은 한 객체를 두번 클릭을 방지하기 위한 조건입니다. 한 객체를 두번 클릭하면 StoryBoard가 두번 일어나겠지요~!그럼 안되잖아요~! 클릭하면 _ImgArray배열 변수에 값을 지정하게 되고 두번째 값까지 들어가게 되면 생성한 StoryBoard의 이벤트(Completed:StoryBoard가 끝나면 일어나는 이벤트)를 생성합니다~! 이벤트 내용 코드는 아래와 같습니다~

 

Page.xaml.cs 페이지

void Photobig_Completed(object sender, EventArgs e)

{

//이미지 URL이 같다면 지워버리게 함.

if (_ImgArray[0].getUrl == _ImgArray[1].getUrl)

{

for (int i = 0; i < 2; i++)

{

//스크린 Canvas에서 제거

screen.Children.Remove(_ImgArray[i]);

number = 0;

}

}

else

{

for (int i = 0; i < 2; i++)

{

// Photo에 있는 StoryBoard를 생성하기.

Storyboard Photosmall = _ROOT[i].FindName("Photosmall") as Storyboard;

Photosmall.Begin();

// 그림이 같이 않을 경우 StoryBoard가 실행이 다 끝난 다음에 클릭할수 있도록 하기 //위한 이벤트처리.

Photosmall.Completed += new EventHandler(Photosmall_Completed);

//마우스 관련 다시 false로 돌림

_ImgArray[i].MouseDown = false;

}

}

//배열은 null 값으로 재지정함.

for (int k = 0; k < 2; k++)

{

_ImgArray[k] = null;

_ROOT[k] = null;

}

}

// Photosmall StoryBoard 이벤트부분

void Photosmall_Completed(object sender, EventArgs e) { number = 0; }

 

위 코드가 바로 같은 그림인 경우 객체를 삭제하는 코드 부분입니다.URL값으로 확인을 해서 같은 그림이라면 삭제가 이루어 지고요, 같은 그림이 아니라면 Photosmall StoryBoard를 생성해서 실행하게 됩니다.StoryBoard가 실행이 끝나면 다시 클릭할수 있도록 number변수를 초기화 해줍니다.

그리고 _ImgArray배열과 _ROOT배열의 값을 null로 초기화 해줍니다~ 이렇게 해야 다음에 다시 확인할수 있을 테니깐요~^^ 아래 동영상은 잘 작동이 되는 모습을 찍어본 것 입니다.



 

~이제 어느정도 게임 처럼 작동하고 있군요~^^ 이제부터는 간단한 조건과 스토리보드만 추가하면 게임이 완성이 됩니다~^^ 한번 잘 생각해 보시고 직접 미리만들어 보는 것도 괜찮을 것 같네요~ 여기까지 따라오느라 수고 많으셨습니다~^^ 혹시 제 내용중에 부족한 부분이 있거나 궁금하신 부분이 있다면 언제든지 말씀해 주세요~^^
 
Posted by happydong
, |