4

私はiPhoneを使っていくつかの基本的なアプリ/ユーティリティ/ゲームに取り組んでおり、iPhoneをよりよく把握しています。

私は現在、指が動くところならどこでも動くという設定をしていますが、の外に出CGRectたくありません。CGRectboundsview

独自の方法

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    startLocation = [touch locationInView:self];
    if (startLocation.x < 33){
        touchLocation.x = 33;
            //NSLog(@"Touch At:%f, %f", touchLocation.x, touchLocation.y);
        [self setNeedsDisplay];
    }
    if (startLocation.x > 288){
        touchLocation.x = 288;
            //NSLog(@"Touch At:%f, %f", touchLocation.x, touchLocation.y);
        [self setNeedsDisplay];
    }
    if (startLocation.y < 84){
        touchLocation.y = 84;
            //NSLog(@"Touch At:%f, %f", touchLocation.x, touchLocation.y);
        [self setNeedsDisplay];
    }
    if (startLocation.y > 460){
        touchLocation.y = 460;
            //NSLog(@"Touch At:%f, %f", touchLocation.x, touchLocation.y);
        [self setNeedsDisplay];
    }
    else {
        touchLocation = startLocation;
        [self setNeedsDisplay];
    }
}

問題

私はこれのいくつかの異なる方法を試しました。これには、&&1つのステートメントを使用して作成することも含まれます。はboundaries明らかにハードコーディングされており、手動で設定するtouchLocationことがそれを維持するための最良の方法であるかどうかはわかりませんbounds

self.view.bounds私が簡単に境界を取得できるとき、これはすべて私にはばかげているように見えCGRectます。これを行うにはどうすればよいboundsですか?touchLocation手動で設定する以外に、それを防ぐためのより良い方法はありますか?代わりにどういうわけかそれに厳しい制限を設けることはできますか?

switchステートメントはどうですか?それは試みられたものよりもうまくいくでしょうifか?


試み

以下に掲載されている@BradGossの方法を利用しようとしていますが、機能していませんか?

Touch Started: (319.000000,350.000000)
Touch Result: (319.000000,350.000000)
Boundaries calculated: X:(0.000000,288.000000) Y(0.000000,328.000000)

タッチ開始は、実際の開始タッチです。タッチ結果は変更された結果である必要があります。

上記のログは、定義されたbounds、別名機能していないことを示しています。彼が書いたコードはまったく同じなので、再投稿するつもりはありません。


問題を試みる

私は問題を発見しました。これは上記と同じタイプの状況ですが、設定された個々の値をログに記録します。

Touch Started: (293.000000,341.000000)
min x:288.000000
max x:293.000000
min y:328.000000
max y:341.000000
Touch Result: (293.000000,341.000000)
Boundaries calculated: X:(0.000000,288.000000) Y(0.000000,328.000000)

私はそれを理解していません、私はそれを発見するとすぐにここにそれを投稿しました。そうでなければ、私はまったく更新するのを忘れてしまいます、追加してください。

私は戻って、考えられるそれぞれの状況で何が起こっているのかを正確に確認します。


間違い

別の問題が見つかりました。からを計算しますが、boundaries subtractsからは計算maximumsしないコードaddですminimums。これは、が画面から消えないようにするためのものでboundaryあるため、重要です。rect

maxX = b.origin.x + b.size.width/* - [box bounds].size.width */;
minX = b.origin.x/* + [box bounds].size.width */;
maxY = b.origin.y + b.size.height/* - [box bounds].size.height */;
minY = b.origin.y?/* + [box bounds].size.height */;

これを修正すると、元の問題に引き続き取り組むことができます。


間違い2

了解しました。別の問題を修正しました。y表示されているときに値を追加していました。私はそれをこの新しいコードに追加するのを忘れました/それについて言及します。コードは次のようになります。

maxX = b.origin.x + b.size.width/* - [box bounds].size.width */;
minX = b.origin.x/* + [box bounds].size.width */;
maxY = b.origin.y + b.size.height/* - [box bounds].size.height + 20*/;
minY = b.origin.y/* + [box bounds].size.height + 20*/;

表示される円のサイズはの内側な64px CGRectので20px、親指のすぐ上に円を表示するのに十分でした。これは修正されていますが、元の問題の解決にはまだ役立っていません。

左上隅:

Touch Started: (14.000000,20.000000)
min x:14.000000
max x:32.000000
min y:20.000000
max y:84.000000
Touch Result: (32.000000,84.000000)
Boundaries calculated: X:(32.000000,288.000000) Y(84.000000,276.000000)

MAX正常に動作しますが、なぜではなく正しい値が出てくるのか混乱していますMIN。ここで何かが混乱しています。

右上隅:

Touch Started: (303.000000,21.000000)
min x:288.000000
max x:303.000000
min y:21.000000
max y:84.000000
Touch Result: (303.000000,84.000000)
Boundaries calculated: X:(32.000000,288.000000) Y(84.000000,276.000000)

MAXの代わりに、画面の上部から外れるのを防いでいますMIN。上に示したように、私はまだ右から飛び立つことができます。

右下隅:

Touch Started: (317.000000,358.000000)
min x:288.000000
max x:317.000000
min y:276.000000
max y:358.000000
Touch Result: (317.000000,358.000000)
Boundaries calculated: X:(32.000000,288.000000) Y(84.000000,276.000000)

両方向で失敗しています。これで、実際の値はからMAX、最大値はから取得されMINます。WTF?

左下隅:

Touch Started: (8.000000,354.000000)
min x:8.000000
max x:32.000000
min y:276.000000
max y:354.000000
Touch Result: (32.000000,354.000000)
Boundaries calculated: X:(32.000000,288.000000) Y(84.000000,276.000000)

予想通り、それは最小値に対してのみ機能しました。これらの関数が何をするのかについて、私はまだ非常に混乱しています。洞察をいただければ幸いです。


解決しました!

ありがたいことに、私たちの長い道のりは終わりに近づいています。それで、私には手がかりがなかったので、ここに何MINMAXしますか。混乱が起こったため、最初ははっきりしませんでした。

MAX(x,y) will output the larger of the two numbers
// MAX(13,37) = 37
MIN(x,y) will output the smallest of the two numbers
// MIN(13,37) = 13

したがって、これは、この状況でこれらの関数を正しく使用するために行う必要があることです。

1.XとYの最大値と最小値を計算します。

それぞれの最小値は次のように計算されます

view.origin + keepOnScreenRect.width  

それぞれの最大値は次のように計算されます

view.origin + view.size.height/width - keepOnScreenRect.height/width

指のオフセットを忘れないでください!
私が行ったことを実行していて、keepOnScreenRectをユーザーの指の少し上に配置している場合は、Yの最小値が画面/ビューの下部であるため、Yの最大値にオフセットを追加するだけです。で0より低くなることは物理的に不可能です。

なぜこれが行われるのか疑問に思っているのは、ユーザーが指で見ることができないためです。

2.タッチの場所を取得しますtouchesBegan:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    startTouchLocation = [touch locationInView:self];
    NSLog(@"Touch Started: (%f,%f)", startTouchLocation.x, startTouchLocation.y);

3.数学的な制約を適用します。

まず、の制限、、、およびMAXに従って、可能な限り低い値の両方の、または最大値を取得します。これにより、画面の左側の制限が計算されます。この結果はに設定されます。minXstartTouchLocationXcurrentTouchLocation

currentTouchLocation.x = MAX(minX, startTouchLocation.x);

次に、の制限、、、およびMINに従って、可能な限り高い値の両方の、または最小値を取得します。元のタッチの場所を使用しているのではなく、使用したばかりの関数の結果の場所を使用していることに注意してください。この値は画面の左側ですでにチェックされているので、右側をチェックします。maxXcurrentTouchLocationXMAX

currentTouchLocation.x = MIN(maxX, currentTouchLocation.x);

それは私たちのX範囲内にあることが保証されている場所を私たちに与えます。次に、で同じことを実行しYます。

currentTouchLocation.y = MAX(minY, startTouchLocation.y);
currentTouchLocation.y = MIN(maxY, currentTouchLocation.y);

これですべてが終了したので、ビューに再描画するように指示でき、素敵な小さな長方形が切り取られることを恐れなくなりました。

[self setNeedsDisplay];

完成品

/* Generates the limits based on the view's size, taking into account 
   the width/height of the rect being displayed in it. This should only
   be run once, unless the size of the view changes, in which case limits
   would have to be recalculated. The same goes for if you were to change
   the size of the displaying rect after calculation */

- (void)boundsCalculation {
    CGRect viewBounds = [self bounds];

        // calculate constraints
    maxX = viewBounds.origin.x + viewBounds.size.width - 32;
    minX = viewBounds.origin.x + 32;
    maxY = viewBounds.origin.y + viewBounds.size.height - 32;
    minY = viewBounds.origin.y + 84;
    NSLog(@"Boundaries calculated: X:(%f,%f) Y(%f,%f)", minX, maxX, minY, maxY);
}

/* Magic goodness that happens when the user touches the screen.
   Note that we don't calculate the bounds every time the user touches
   the screen, that would be silly. */

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    startTouchLocation = [touch locationInView:self];
    NSLog(@"Touch Started: (%f,%f)", startTouchLocation.x, startTouchLocation.y);

        // apply constraints
            // highest x value between the lowest allotted x value and touch
    currentTouchLocation.x = MAX(minX, startTouchLocation.x);
            // lowest x value between the highest allotted x value and touch
    currentTouchLocation.x = MIN(maxX, currentTouchLocation.x);
            // highest y value between the lowest allotted y value and touch
    currentTouchLocation.y = MAX(minY, startTouchLocation.y);
            // lowest y value between the highest allotted y value and touch
    currentTouchLocation.y = MIN(maxY, currentTouchLocation.y);
           // NSLog(@"Touch Result: (%f,%f)", currentTouchLocation.x, currentTouchLocation.y);

           // If you don't do this you won't see anything
    [self setNeedsDisplay];
}

今日は学ぶのに良い日でした。

4

1 に答える 1

2

あなたは間違いなくそのスーパービューの境界を使用してその動きを制限したいと思います。

setNeedsDisplayを頻繁に呼び出さないでください。メソッドの最後に一度呼び出します。不必要に再描画する可能性があります。

これを実現するには、次のようなものを使用します。

// define these variables where ever you'd like
static float maxX = 0.;
static float maxY = 0.;
static float minX = 0.;
static float minY = 0.;

- (void)setupView {
    CGRect b = [self bounds];

    // calculate constraints
    maxX = b.origin.x + b.size.width/* - [box bounds].size.width */;
    minX = b.origin.x;
    maxY = b.origin.y + b.size.height/* - [box bounds].size.height */;
    minY = b.origin.y;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    startLocation = [touch locationInView:self];

    // apply constraints
    touchLocation.x = MIN(maxX, startLocation.x);
    touchLocation.x = MAX(minX, startLocation.x);
    touchLocation.y = MIN(maxY, startLocation.y);
    touchLocation.y = MAX(minY, startLocation.y);

    [self setNeedsDisplay];
}
于 2009-12-17T17:41:03.347 に答える