首先蜜蜂祝大家狗年一帆風順,因年底比較空閒,自己琢磨了一個骰子游戲
github地址
專案使用了Cocoapods,又設定了忽略檔案,所以下載的時候請自行 pod install 一下
專案主要利用CATransform3DRotate改變view的perspective來實現骰子的3D旋轉功能,再進行隨機數來達到搖骰子的功能
因為使用了毛玻璃,所以在模擬器的情況下會崩潰,建議真機執行,或者將毛玻璃效果(全域性搜尋maoboli)遮蔽即可
先附上效果圖(使用liceape製作的gif,gif效果沒有實際的好):
實現思路
首先,一個骰子為一個View,分別set 6張圖片,然後分別設定對應的的CATransform3D
eg:
- (UIView *)view1
{
if (!_view1) {
_view1 = [[UIView alloc]init];
UIImageView *img = [[UIImageView alloc]init];
[img setImage:[UIImage imageNamed:@"one"]];
img.layer.allowsEdgeAntialiasing = true;
[_view1 addSubview:img];
[img mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.mas_equalTo(0.3);
make.bottom.right.mas_equalTo(-0.3);
}];
_view1.layer.borderWidth = 1;
_view1.layer.borderColor = [UIColor lightGrayColor].CGColor;
_view1.layer.cornerRadius = 3;
}
return _view1;
}
複製程式碼
[self addSubview:self.view1];
[self.view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.bottom.mas_equalTo(0);
}];
CATransform3D viewTrans = CATransform3DIdentity;
viewTrans = CATransform3DRotate(view2Trans, M_PI_2, 0, 1, 0);
viewTrans = CATransform3DTranslate(view2Trans, theWidth/2, 0, -theWidth/2);
self.view1.layer.transform = viewTrans;
複製程式碼
最重要的,記得吧骰子所在的view的M34屬性設定一下,才能看到3D效果
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/500.0;
self.layer.sublayerTransform = perspective;
複製程式碼
在controller初始化骰子所在的view(diceview)的時候,記得設定一下3d角度,便於觀察
CATransform3D perspective1 = CATransform3DIdentity;
perspective1.m34 = -1/500;
perspective1 = CATransform3DRotate(perspective1, -M_PI_4 + M_PI_2, 1, 0, 0);
perspective1 = CATransform3DRotate(perspective1, -M_PI_4, 0, 0, 1);
perspective1 = CATransform3DTranslate(perspective1, 0, 0, 25);
self.diceView.layer.sublayerTransform = perspective1;
複製程式碼
然後點選的時候,建立了一個timer,讓CATransform3DRotate改變,從而達到骰子3D翻轉的效果
- (void)timerAction
{
self.theNum += 0.35;
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/500.0;
perspective = CATransform3DRotate(perspective, self.theNum, 1, 0, 0);
perspective = CATransform3DRotate(perspective, self.theNum, 0, 1, 0);
perspective = CATransform3DRotate(perspective, self.theNum, 0, 0, 1);
perspective = CATransform3DTranslate(perspective, 0, 0, 25);
self.diceView.layer.sublayerTransform = perspective;
}
複製程式碼
再次點選的時候建立先停止之前的timer,然後做另外一個timer的Action,一開始腦子沒轉過來,總是想著讓骰子搖到特定的角度,後來思路一通,先是用隨機數隨機出一個數,然後再讓骰子做動畫聽到那個點數
- (void)timer2Action
{
self.Num1 = self.Num1 - 0.025;
if (self.Num1 > 0) {
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/500.0;
switch (self.onPoint) {
case 0:
{
// 1 的情況
perspective = CATransform3DRotate(perspective, -M_PI_4 + M_PI_2 - self.Num1, 1, 0, 0);
perspective = CATransform3DRotate(perspective, -self.Num1 , 0, 1, 0);
perspective = CATransform3DRotate(perspective, M_PI_4 + M_PI_2 * self.roundPoint -self.Num1, 0, 0, 1);
}
break;
case 1:
{
// 2 的情況
perspective = CATransform3DRotate(perspective, -M_PI_4 - self.Num1, 1, 0, 0);
perspective = CATransform3DRotate(perspective, -M_PI_4 + M_PI_2 * self.roundPoint - self.Num1, 0, 1, 0);
perspective = CATransform3DRotate(perspective, M_PI_2 - self.Num1, 0, 0, 1);
}
break;
case 2:
{
// 3 的情況
perspective = CATransform3DRotate(perspective, -M_PI_4 + M_PI_2 * 2 - self.Num1, 1, 0, 0);
perspective = CATransform3DRotate(perspective, -M_PI_4 - self.Num1 + M_PI_2 * self.roundPoint, 0, 1, 0);
perspective = CATransform3DRotate(perspective, - self.Num1, 0, 0, 1);
}
break;
case 3:
{
// 4 的情況
perspective = CATransform3DRotate(perspective, -M_PI_4 - self.Num1, 1, 0, 0);
perspective = CATransform3DRotate(perspective, -M_PI_4 - self.Num1 + M_PI_2 * self.roundPoint, 0, 1, 0);
perspective = CATransform3DRotate(perspective, - self.Num1, 0, 0, 1);
}
break;
case 4:
{
// 5 的情況
perspective = CATransform3DRotate(perspective, -M_PI_4 - self.Num1, 1, 0, 0);
perspective = CATransform3DRotate(perspective, -M_PI_4 + M_PI_2 * self.roundPoint - self.Num1, 0, 1, 0);
perspective = CATransform3DRotate(perspective, -M_PI_2 - self.Num1, 0, 0, 1);
}
break;
case 5:
{
// 6 的情況
perspective = CATransform3DRotate(perspective, -M_PI_4 - M_PI_2 - self.Num1, 1, 0, 0);
perspective = CATransform3DRotate(perspective, -self.Num1 , 0, 1, 0);
perspective = CATransform3DRotate(perspective, M_PI_4 + M_PI_2 * self.roundPoint -self.Num1, 0, 0, 1);
}
break;
default:
break;
}
perspective = CATransform3DTranslate(perspective, 0, 0, 25 );
self.diceView.layer.sublayerTransform = perspective;
}else{
[self.timer2 setFireDate:[NSDate distantFuture]];
self.thetag = 0;
}
}
複製程式碼
最後有多個骰子存在的情況下,加了動畫改進,讓5個骰子做旋轉動畫,一開始想到的是用貝塞爾曲線實現,後來嘗試
了一下利用CATransform3DRotate只改變Z的數值,發現這種方法也可行,然後再加上一個座標往center的動畫,效果出來就很炫酷了
- (void)timerAction
{
self.zTrans += M_PI_2*8/125;
self.theNum += 0.35;
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/500.0;
perspective = CATransform3DRotate(perspective, self.theNum, 1, 0, 0);
perspective = CATransform3DRotate(perspective, self.theNum, 0, 1, 0);
perspective = CATransform3DRotate(perspective, self.theNum, 0, 0, 1);
perspective = CATransform3DTranslate(perspective, 0, 0, 25);
self.diceView.layer.sublayerTransform = perspective;
self.diceView1.layer.sublayerTransform = perspective;
self.diceView2.layer.sublayerTransform = perspective;
self.diceView3.layer.sublayerTransform = perspective;
self.diceView4.layer.sublayerTransform = perspective;
CATransform3D perspective1 = CATransform3DIdentity;
perspective1 = CATransform3DRotate(perspective1, self.zTrans, 0, 0, 1);
self.layer.sublayerTransform = perspective1;
}
複製程式碼
參考資料
具體的知識點可以參考 《核心動畫高階技巧》
各路大神覺得不錯的賞顆star吧,萌新求罩~?