문제

저는 iPhone을 더 잘 활용하기 위해 몇 가지 기본 앱/유틸리티/게임을 작업 중입니다.

현재 설정이 있습니다. CGRect 손가락이 움직이는 곳마다 움직입니다. 그러나 나는 그것을 원하지 않습니다 CGRect 밖으로 나가려고 bounds ~의 view.

원래 방법

- (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];
    }
}

문제

나는 다음을 포함하여 몇 가지 다른 방법을 시도했습니다. && 그리고 그것을 단 하나의 진술로 만듭니다.그만큼 boundaries 분명히 하드 코딩되어 있으며 수동으로 설정하는지는 잘 모르겠습니다. touchLocation 그것을 유지하는 가장 좋은 방법입니다 bounds.

내가 쉽게 할 수 있는데 이 모든 것이 나에게는 어리석은 것처럼 보인다. self.view.bounds 그리고 경계를 얻으십시오 CGRect.어떻게 활용하나요? bounds 이것을하기 위해?설정 외에 이런 일이 발생하지 않도록 하는 더 좋은 방법이 있습니까? touchLocation 수동으로?대신에 어떻게든 엄격한 제한을 둘 수 있나요?

어때요? switch 성명?그게 시도한 것보다 더 잘 작동할까요?if에스?


시도

아래에 게시된 @Brad Goss의 방법을 활용하려고 하는데 작동하지 않습니까?

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.뭐야?

왼쪽 하단 모서리:

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)

예상대로 최소값에서만 작동했습니다.나는 아직도 이 기능들이 어떤 역할을 하는지 매우 혼란스럽습니다.통찰력을 주시면 감사하겠습니다!


해결되었습니다!

고맙게도 우리의 긴 길이 가까워졌습니다.그래서 전혀 몰랐기 때문에 다음과 같습니다. MIN 그리고 MAX 하다.발생한 혼란으로 인해 처음에는 명확하지 않았습니다.

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);

삼.수학적 제약 조건을 적용합니다.

먼저, 우리는 MAX, 또는 우리의 한도에 따라 가능한 가장 낮은 값 중 가장 높은 값, minX, 그리고 startTouchLocation, 을 위한 X.화면 왼쪽의 한계를 계산합니다.결과는 다음과 같이 설정됩니다. currentTouchLocation.

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

둘째, 우리는 MIN, 또는 우리의 한도에 따라 가능한 가장 높은 값 중 가장 낮은 값, maxX, 그리고 currentTouchLocation, 을 위한 X.원래 터치 위치를 사용하지 않고 대신 결과 위치를 사용한다는 점에 유의하세요. MAX 방금 사용한 함수입니다.이 값은 화면 왼쪽에서 이미 확인되었으므로 오른쪽을 확인합니다.

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];
}

오늘은 배움에 좋은 날이었습니다.

도움이 되었습니까?

해결책

당신은 그것의 움직임을 제한하기 위해 그것의 슈퍼뷰의 경계를 사용하고 싶을 것입니다.

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];
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top