UIButtonに体力を持たせて撃破してみた

どうもです。
記事投稿が三日坊主にならないよう頑張ります。


今日の題
#UIButtonに体力を持たせて撃破してみた

![giphy-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415441/cbbc6faa-1326-b48d-52b8-d16bd9e99a4c.gif)

まあコードですが黒魔術を使って体力を付与しているだけです。

```objective_c:UIView+HitPoints.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN

@interface UIView (HitPoints)
@property (getter=getHitPoints) double hitPoints;
@property (getter=getMaxPoints) double maxPoints;
- (double)getHitPoints;
- (void)setHitPoints:(double)hitPoints;
- (void)setMaxPoints:(double)maxPoints;
- (double)getMaxPoints;
-(BOOL)isDead;
@end

NS_ASSUME_NONNULL_END
```

```objective_c:UIView+HitPoints.m
#import "UIView+HitPoints.h"
#include <objc/runtime.h>


@implementation UIView (getHitPoints)
- (double)getHitPoints
{
    return [objc_getAssociatedObject(self, @"hitPoints") doubleValue];
}
- (void)setHitPoints:(double)hitPoints
{
    objc_setAssociatedObject(self, @"hitPoints", [NSNumber numberWithLongLong:hitPoints], OBJC_ASSOCIATION_ASSIGN);
}
- (void)setMaxPoints:(double)maxPoints
{
    objc_setAssociatedObject(self, @"maxPoints", [NSNumber numberWithLongLong:maxPoints], OBJC_ASSOCIATION_ASSIGN);
    //ヒットポイントにも入れる
    [self setHitPoints:maxPoints];
}
- (double)getMaxPoints
{
    return [objc_getAssociatedObject(self, @"maxPoints") doubleValue];
}
//ヒットポイントが０を下回っていればYESを返却します。
-(BOOL)isDead{
    return ([objc_getAssociatedObject(self, @"hitPoints") doubleValue] <= 0);
}
@end
```
このようにViewにhitPointsプロパティをつけることによってアクセスできるようになっています。
![スクリーンショット 2019-11-27 0.28.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415441/b09eebc7-005c-e2b9-02ee-911532eb452e.png)


```objective_c:damageViewController.h
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface damageViewController : UIViewController

@end

NS_ASSUME_NONNULL_END
```


あとは体力、ボタン座標を元に色々計算するわけです。

```objective_c:damageViewController.m
#import "damageViewController.h"
#import "UIView+HitPoints.h"
#include <objc/runtime.h>

@interface damageViewController ()
@property (weak, nonatomic) IBOutlet UIButton *enemyButton;
@property (nonatomic) UIView *hitPointsView;
@end

@implementation damageViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.enemyButton.maxPoints = 1500;
}

- (IBAction)eventButton:(id)sender {
    [self showDamageView:sender];
    [self showDamageNumber:sender];
}

/*
 引数として渡されたオブジェクトにダメージを表示します
 */
-(void)showDamageNumber:(UIView *)enemyView{
    UILabel *damageLabel = [UILabel new];
    damageLabel.frame = enemyView.frame;
    damageLabel.frame = CGRectOffset(damageLabel.frame,enemyView.frame.size.width - enemyView.frame.size.width/10,0);
    damageLabel.text = [self damageCalculator:enemyView];
    
    if([self getDeviceBatteryState]){
        damageLabel.textColor = [UIColor blueColor];
    }else{
        damageLabel.textColor = [UIColor redColor];
    }
    [self.view addSubview:damageLabel];
    [self moveDamageLabel:damageLabel];
    
    //対象のビュー撃破時に通ります
    if([enemyView isDead]){
        [enemyView removeFromSuperview];
        [self.hitPointsView removeFromSuperview];
    }
}

/*
 ダメージを出力します
 */
-(NSString *)damageCalculator:(UIView *)enemyView{
    int damageInt = (int)arc4random_uniform(100);
    if([self getDeviceBatteryState])damageInt *= 5;
    enemyView.hitPoints -= damageInt;
    return [NSString stringWithFormat:@"-%d", damageInt];
}

/*
 damageLabelをアニメーションさせ完了時に破棄します
 */
-(void)moveDamageLabel:(UILabel *)damageLabel{
    [UIView animateWithDuration:1.0f animations:^{
        damageLabel.frame = CGRectOffset(damageLabel.frame, 0, -100.0);
        damageLabel.alpha = 0.0f;
    } completion:^(BOOL finished) {
        [damageLabel removeFromSuperview];
    }];
}

/*
 引数として渡されたオブジェクトの残体力を表示します
 */
-(void)showDamageView:(UIView *)enemyView{
    [self.hitPointsView removeFromSuperview];
    self.hitPointsView = [UIView new];
    self.hitPointsView.frame = [self getCGRectFrame:enemyView];
    self.hitPointsView.frame = CGRectOffset(self.hitPointsView.frame, 0, -enemyView.frame.size.height/2);
    self.hitPointsView.backgroundColor = [UIColor redColor];
    [self.view addSubview:self.hitPointsView];
}

/**
 対象ビューの体力rectを返却します
 */
-(CGRect)getCGRectFrame:(UIView*)view{
    double i = (view.hitPoints/view.maxPoints);
    return CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width * i, 5);
}

/**
 充電中の場合YESを返却します
 */
-(BOOL)getDeviceBatteryState{
    [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES];
    UIDeviceBatteryState batteryState = [UIDevice currentDevice].batteryState;
    if(batteryState == UIDeviceBatteryStateCharging)return YES;
    else return NO;
}
```


#小ネタ
なんと！！！！！！！！！！充電中だと攻撃力が５倍になります！！！！！！！！！
![giphy−2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415441/578c41df-9954-71d2-45ea-79d6377f3727.gif)

どうしてもこのボタンに勝てねーとか、
圧倒的な力でボタンを粉砕したい時には充電状態で挑んでください。

では良いボタン撃破ライフを。