티스토리 뷰
[1] RotationClock
<Window x:Class="_042_RotationClock.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:_042_RotationClock"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="400">
<Grid>
<Canvas x:Name="aClock" Width="300" Height="300">
<Rectangle Width="300" Height="300"
Stroke="LightSteelBlue"/>
<Ellipse Width="300" Height="300"
Stroke="LightSteelBlue"
StrokeThickness="2"/>
<Line X1="0" Y1="150" X2="300" Y2="150"
Stroke="LightBlue"/>
<Line X1="150" Y1="0" X2="150" Y2="300"
Stroke="LightBlue"/>
<!--시계바늘-->
<Line x:Name="secHand" Stroke="Red"
StrokeThickness="2"
StrokeEndLineCap="Round"/>
<Line x:Name="minHand" Stroke="Green"
StrokeThickness="4"
StrokeEndLineCap="Round"/>
<Line x:Name="hourHand" Stroke="Blue"
StrokeThickness="6"
StrokeEndLineCap="Round"/>
<!--배꼽-->
<Ellipse x:Name="center" Width="20"
Height="20" Margin="140"
Stroke="DarkOliveGreen"
StrokeThickness="2"
Fill="Chocolate"/>
</Canvas>
</Grid>
</Window>
xmal코드이다 앞의 WPFClock의 코드와 비슷하지만
Line객체를 매 번 선언해주었다.
배꼽도 만들어주었다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace _042_RotationClock
{
/// <summary>
/// MainWindow.xaml에 대한 상호 작용 논리
/// </summary>
public partial class MainWindow : Window
{
private double hourDeg;
private double minDeg;
private double secDeg;
public MainWindow()
{
InitializeComponent();
// 시계판
DrawFace();
// 시계바늘
MakeClockHands();
// 타이머
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = new TimeSpan(0, 0, 0, 0, 10); // 10밀리초
dt.Tick += Dt_Tick;
dt.Start();
}
private void MakeClockHands()
{
int W = 300;
int H = 300;
secHand.X1 = W / 2; // 시계 중심
secHand.Y1 = H / 2; // 시계 중심
secHand.X2 = H / 2;
secHand.Y2 = 20;
minHand.X1 = W / 2; // 시계 중심
minHand.Y1 = H / 2; // 시계 중심
minHand.X2 = H / 2;
minHand.Y2 = 40;
hourHand.X1 = W / 2; // 시계 중심
hourHand.Y1 = H / 2; // 시계 중심
hourHand.X2 = H / 2;
hourHand.Y2 = 60;
}
// 눈금을 가진 시계판
private void DrawFace()
{
Line[] marking = new Line[60];
int W = 300; // 시계크기
for(int i=0; i<60; i++)
{
marking[i] = new Line();
marking[i].Stroke = Brushes.LightSteelBlue;
marking[i].X1 = W / 2;
marking[i].Y1 = 2;
marking[i].X2 = W / 2;
if(i%5 == 0)
{
marking[i].Y2 = 20;
marking[i].StrokeThickness = 5;
}
else
{
marking[i].Y2 = 10;
marking[i].StrokeThickness = 2;
}
RotateTransform rt = new RotateTransform(6*i);
rt.CenterX = W / 2;
rt.CenterY = W / 2;
marking[i].RenderTransform = rt;
aClock.Children.Add(marking[i]);
}
}
private void Dt_Tick(object sender, EventArgs e)
{
int W = 300;
DateTime c = DateTime.Now;
int hour = c.Hour;
int min = c.Minute;
int sec = c.Second;
hourDeg = hour * 30 + min * 0.5;
minDeg = min * 6;
secDeg = sec * 6 + c.Millisecond * 0.006;
RotateTransform rtH = new RotateTransform(hourDeg);
rtH.CenterX = W / 2;
rtH.CenterY = W / 2;
hourHand.RenderTransform = rtH;
RotateTransform rtM = new RotateTransform(minDeg);
rtM.CenterX = W / 2;
rtM.CenterY = W / 2;
minHand.RenderTransform = rtM;
RotateTransform rtS = new RotateTransform(secDeg);
rtS.CenterX = W / 2;
rtS.CenterY = W / 2;
secHand.RenderTransform = rtS;
}
}
}
전체 cs코드이다.
private double hourDeg;
private double minDeg;
private double secDeg;
double값을 가진 시간,분,초의 각도를 지정해주었다.
// 시계판
DrawFace();
// 시계바늘
MakeClockHands();
// 타이머
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = new TimeSpan(0, 0, 0, 0, 10); // 10밀리초
dt.Tick += Dt_Tick;
dt.Start();
시계판을 그려주는 DrawFace함수와
침들을 띄워줄 MakeClockHands함수를 실행해주었다.
그 후 따로 함수를 사용하지 않고 timer의 값들을 설정해주었다.
타이머를 실행해주었다.
private void MakeClockHands()
{
int W = 300;
int H = 300;
secHand.X1 = W / 2; // 시계 중심
secHand.Y1 = H / 2; // 시계 중심
secHand.X2 = H / 2;
secHand.Y2 = 20;
minHand.X1 = W / 2; // 시계 중심
minHand.Y1 = H / 2; // 시계 중심
minHand.X2 = H / 2;
minHand.Y2 = 40;
hourHand.X1 = W / 2; // 시계 중심
hourHand.Y1 = H / 2; // 시계 중심
hourHand.X2 = H / 2;
hourHand.Y2 = 60;
}
시계판을 300 x 300으로 그릴 것이기 때문에
시침,분침,초침의 좌표들을 설정해준다.
private void DrawFace()
{
Line[] marking = new Line[60];
int W = 300; // 시계크기
for(int i=0; i<60; i++)
{
marking[i] = new Line();
marking[i].Stroke = Brushes.LightSteelBlue;
marking[i].X1 = W / 2;
marking[i].Y1 = 2;
marking[i].X2 = W / 2;
if(i%5 == 0)
{
marking[i].Y2 = 20;
marking[i].StrokeThickness = 5;
}
else
{
marking[i].Y2 = 10;
marking[i].StrokeThickness = 2;
}
RotateTransform rt = new RotateTransform(6*i);
rt.CenterX = W / 2;
rt.CenterY = W / 2;
marking[i].RenderTransform = rt;
aClock.Children.Add(marking[i]);
}
}
시계판을 그려줄 DrawFace함수를 작성한다.
시계에 분마다 막대기를 그려줄 것이다.
색상은 라이트블루로 X1과 Y1을 시계의 정중앙의 가장 윗부분으로 좌표를 잡아준다. (왼,위)좌표
그 후 X2,Y2를 사용해 오른쪽 아래의 좌표를 입력하여준다.
라인을 생성해주고 색상은 라이트스틸블루로
그리고 5분침마다 굵기와 길이를 길게 설정해준다.
그리고 WPF의 장점인 RotateTransForm 클래스의 rt를 선언하여
눈금 하나당 중심점을 기준으로 6도씩 회전하도록 설정하였다.
6도씩 돌아가면서 marking[i]가 전부 출력되게 되는 것이다.
이제 aClock의 children으로 add해준다.
private void Dt_Tick(object sender, EventArgs e)
{
int W = 300;
DateTime c = DateTime.Now;
int hour = c.Hour;
int min = c.Minute;
int sec = c.Second;
hourDeg = hour * 30 + min * 0.5;
minDeg = min * 6;
secDeg = sec * 6 + c.Millisecond * 0.006;
RotateTransform rtH = new RotateTransform(hourDeg);
rtH.CenterX = W / 2;
rtH.CenterY = W / 2;
hourHand.RenderTransform = rtH;
RotateTransform rtM = new RotateTransform(minDeg);
rtM.CenterX = W / 2;
rtM.CenterY = W / 2;
minHand.RenderTransform = rtM;
RotateTransform rtS = new RotateTransform(secDeg);
rtS.CenterX = W / 2;
rtS.CenterY = W / 2;
secHand.RenderTransform = rtS;
}
이제 Tick이벤트함수의 코드이다.
w를 시계의 크기인 300으로
c를 현재시간으로 설정해준다.
시분초를 설정해준 다음
받은 현재시간값으로 매 틱마다 각도를 계산해준다.
그 후 RotationTransForm class의 rth를 선언하여
나머지값들은 xaml에서 모두 선언되었으므로 변화할 때마다 Tick함수를 사용하여 값을 넘겨주기만 하면 된다.
xaml에서 따로 객체를 선언한 것이기 때문에 clear같은것을 해줄 필요는 없다.
[2]snakebite game
<Window x:Class="_043_SnakeBite.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:_043_SnakeBite"
mc:Ignorable="d"
Title="SnakeBite" Height="350" Width="525">
<Grid>
<Image Source="Images/Tulips.jpg"
Stretch="Fill"/>
<Button x:Name="btnPlay" Content="Play"
HorizontalAlignment="Left"
Margin="126,250,0,0"
VerticalAlignment="Top"
Height="38" Width="75"
Click="btnPlay_Click"/>
<Button x:Name="btnQuit" Content="Quit"
HorizontalAlignment="Left"
Margin="323,250,0,0"
VerticalAlignment="Top"
Height="38" Width="75"
Click="btnQuit_Click"/>
</Grid>
</Window>
snakebiteGame을 만들어보았다.
실행창의 xaml코드이다.
그리드를 만들어 이미지를 배경처럼 채워주었고
시작버튼과 종료버튼을 만들어주었다.
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
Game game= new Game();
game.Show();
}
private void btnQuit_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
추려온 cs코드이며 Game class game을 만들어주거나 종료하는 버튼이 있는 form이다.
이와같이 출려되게 된다.
<Window x:Class="_043_SnakeBite.Game"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:_043_SnakeBite"
mc:Ignorable="d"
Title="Game" Height="340" Width="420"
KeyDown="Window_KeyDown">
<Canvas x:Name="field"
Width="400" Height="300"
Background="LightSteelBlue">
<TextBlock x:Name="txtScore" Text="Eggs=0"
Canvas.Left="200" Margin="10"/>
<TextBlock x:Name="txtTime" Text=""
Canvas.Left="270" Margin="10"/>
</Canvas>
</Window>
게임이 진행되는 game form을 구성한 xaml이다.
canvas에 점수와 시간을 표시할 textblock을 두개 넣어주었다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace _043_SnakeBite
{
/// <summary>
/// Game.xaml에 대한 상호 작용 논리
/// </summary>
public partial class Game : Window
{
Random r = new Random();
Ellipse[] snake = new Ellipse[30];
Ellipse egg;
int W = 10; // 뱀과 알의 크기
int visibleCount = 5; // 눈에 보이는 뱀의 길이
public Game()
{
InitializeComponent();
InitEgg();
InitSnake();
}
private void InitSnake()
{
// 뱀의 머리 위치
int x = r.Next((int)(field.Width) / W); // 40
int y = r.Next((int)(field.Height) / W); // 30
for(int i = 0; i < 30; i++)
{
snake[i] = new Ellipse();
snake[i].Width = W;
snake[i].Height = W;
snake[i].Stroke = Brushes.Black;
if (i == 0) // 머리
snake[i].Fill = Brushes.Chocolate;
else if (i % 5 == 0)
snake[i].Fill = Brushes.Green;
else
snake[i].Fill = Brushes.Gold;
snake[i].Tag = new Point(x * W, (y + i) * W);
field.Children.Add(snake[i]);
Canvas.SetLeft(snake[i], x * W);
Canvas.SetTop(snake[i], (y + i) * W);
}
for (int i = visibleCount; i < 30; i++)
snake[i].Visibility = Visibility.Hidden;
}
private void InitEgg()
{
egg = new Ellipse();
egg.Width = W;
egg.Height = W;
egg.Stroke = Brushes.Black;
egg.Fill = Brushes.Red;
int x = r.Next((int)(field.Width) / W); // 40
int y = r.Next((int)(field.Height) / W); // 30
egg.Tag = new Point(x, y);
field.Children.Add(egg);
Canvas.SetLeft(egg, x * W);
Canvas.SetTop(egg, y * W);
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
}
}
}
game의 cs코드이다.
Random r = new Random();
Ellipse[] snake = new Ellipse[30];
Ellipse egg;
int W = 10; // 뱀과 알의 크기
int visibleCount = 5; // 눈에 보이는 뱀의 길이
전역변수로 Random class r을 선언해주고
타원배열 snake를 30칸 크기로 선언해준다.
타원 egg를 선언
뱀과 알의 크기로 사용할 w=10으로
눈에 보이는 뱀의 초기 길이는 5로 설정해주었다.
public Game()
{
InitializeComponent();
InitEgg();
InitSnake();
}
폼 실행 함수 안에는
InitEgg로 알을 생성하는 함수와
InitSnake로 뱀을 생성하는 함수만 있다.
private void InitSnake()
{
// 뱀의 머리 위치
int x = r.Next((int)(field.Width) / W); // 40
int y = r.Next((int)(field.Height) / W); // 30
for(int i = 0; i < 30; i++)
{
snake[i] = new Ellipse();
snake[i].Width = W;
snake[i].Height = W;
snake[i].Stroke = Brushes.Black;
if (i == 0) // 머리
snake[i].Fill = Brushes.Chocolate;
else if (i % 5 == 0)
snake[i].Fill = Brushes.Green;
else
snake[i].Fill = Brushes.Gold;
snake[i].Tag = new Point(x * W, (y + i) * W);
field.Children.Add(snake[i]);
Canvas.SetLeft(snake[i], x * W);
Canvas.SetTop(snake[i], (y + i) * W);
}
for (int i = visibleCount; i < 30; i++)
snake[i].Visibility = Visibility.Hidden;
}
먼저 뱀을 생성하는 함수이다.
뱀의 머리 위치를 전체 필드의 (x,y)/10으로 정해진 범위 내의 랜덤한값으로 받아준다.
다음 반복문을 30번 (뱀의 길이)만큼 돌려준다.
30개의 타원을 snake배열에 저장해주고 크기는 10 x 10으로 해준다.
색상은 블랙을 디폴트로 한다.
하지만 i==0이면 뱀의 머리이고 이 부분은 초콜렛 색으로 칠해준다.
아니라면 다섯마디마다 초록색으로 나머지는 금색으로 칠해준다.
snake[i]의 태그를 좌표의 규칙에 따라 선언해준다. (10칸씩 가야하므로 w를 곱해준 것)
그리고 children으로 field에 추가해준다.canvas에 snake[i]에 대한 좌상단좌표값을 넣어준다.(그림그릴때 쓸 것)
visiblecount를 제외한 나머지 부분은 hide로 가려준다.
초기 뱀의 길이는 =5이다
private void InitEgg()
{
egg = new Ellipse();
egg.Width = W;
egg.Height = W;
egg.Stroke = Brushes.Black;
egg.Fill = Brushes.Red;
int x = r.Next((int)(field.Width) / W); // 40
int y = r.Next((int)(field.Height) / W); // 30
egg.Tag = new Point(x, y);
field.Children.Add(egg);
Canvas.SetLeft(egg, x * W);
Canvas.SetTop(egg, y * W);
}
다음은 알의 생성 함수이다.
알도 마찬가지로 타원이며
뱀과 마디의 크기는 같다.
테두리는 검은색 속은 빨간색으로 만들어준다.
알이 나타날 수 있는 위치를 랜덤하게 정해주었다.
tag에 방금 받은 랜덤한 값을 붙여준다.
field의 children으로 추가해준다.
마찬가지로 canvas에 좌상단 좌표를 set해준다.
위와같이 나오게된다.
현재 이 후의 코드가 깃허브에 올라와있지 않습니다 수업시간에 짠 코드는 학교 컴퓨터에있어 확인이 안되는 상황입니다...
추후에 공부하여 추가하겠습니다.
감사합니다.
'VS-02분반수업' 카테고리의 다른 글
VP(22-06-10) (0) | 2022.06.18 |
---|---|
VP(22-06-08) (0) | 2022.06.09 |
VP(22-06-03) (0) | 2022.06.08 |
VP(22-06-02) (0) | 2022.06.08 |
VP(22-05-27) (0) | 2022.05.30 |