くまちゃんのiOS/Androidゲームプログラミング

マイペースでゲームつくってます。

横画面のときのタッチ座標問題

わかった!わかったあああ!!
いや、なにがって、40超えたオッサンがちょっとした数学の問題が解けずに土曜の夜中にうんうんうなっとったわけですわ。
なんやゆうたら、アイホンの画面ありまっしゃろ、あれ、フツーは縦で使いますやん?そうするとでんな、X座標Y座標は左上が(0,0)ですわ。まあ、フツーですわな、これが。それがやな、これ、横画面にしたい思てやってみたら、そらもう難儀なことになりまんねん。なにが難儀て、画像や文字を表示する座標は横画面にしてもやっぱり左上が(0,0)なのはごっつ助かるんやけど、なんと画面のどこをタッチしたかを感知する座標はもとのままやっちゅーことやねん。なに?言うてることがよーわからん?つまりやな、横画面にすると、表示のための座標は左上が(0,0)やけども、タッチの座標は左上が(0,480)になるわけや。これ、2つの座標軸を同時に扱わなあかんっちゅーややこいことになりよんねん。何のためかて?それはな、画面に表示されたキャラクターをタッチしたかどうかを判定するためやねん。2つの座標軸で合致したかどうかやで?そんなん習てないわ。そやな、X軸とY軸の対応がてれこになるのはすぐ気づいたで。そっからや。x1=0のときy2=480,x1=480のときy2=0や。これを変換させる数式を見いださなあかんねん。これが悩んだわ。2時間ぐらい。こういう時はGoogle先生も頼れまへんな。うだうだしだして、もうあきらめて寝よか、いうときに閃いたがな。気づいたら意外と簡単なもんやけどな、自力で解けたときはそらうれしいもんやで。こういう経験が血となり肉となるんや。え?わては役所のもんやけどな。ぐだぐだ言うとらんと、さくっと答え書くわ。
(y2-480)*(-1)
要は、480ひいてからマイナス1かけたらええねん。このマイナスっちゅーのがミソやな。あー、わかったらうれし。
そやそや、これには実はまだオチがあんねん。
これ、よー考えたらホームボタンが左にきてる、つまり右周りに90度回転させた時にだけ、通用する式やで...
ホームボタンが右に来る場合もあるやん?そうすると左上は(320,0)や...
もー考えるのいやんなるやろ... もう遅いさかいに、寝るわ...

-----

...式、展開したら、ただ単に480-y2だけでいいやん、っていうのは後のハナシやで...;

-----

+90度と-90度の回転変換…

-----

そーですわ、回転変換ですわ。実はこれ問題が2段構えで、回転変換した後に並行移動せなあかん、ちゅうのが気づかんかったんですわ...。しかもその並行移動が+90度の時はX軸に-480、-90度の時はY軸に-320という...; 回転変換の一般式x2=x1cos@-y1sin@, y2=x1sin@+y1cos@の後に条件判断で並行移動差分加える、っちゅーのが一般解ですな!

-----

補足すると、実は画面は@=0, π/2, π, 3/2πの4パターンしか遷移しないので一般解まで求める必要はなく、さらにそれら角度のsin, cosの値は-1, 0, 1しか取らないのでCPUの計算コスト削減のためには、結果的には上記の通りベタで-1かける、とかでいいやんかいさ、と。まあさらに式を展開しておくほうがより計算コスト削減になりますけど、そこまですると、この思考経過がすべて吹っ飛んでしまって本質見えなくなるので;

-----

ああ!ぐわ〜、今気づいたけどこれ、並行移動の差分はiPhone4s以前の画面サイズやん...; iPhone5は縦568や...

だから、変数でbounds.size.heightとwidthを保存してその変数で調整するべし。

ホームボタンの右左で調整するのは今はめんどいので、左だけに固定して以下ソース。

// タッチパネル操作

-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {

    lastPoint = [[touches anyObject] locationInView:self.superview];

}

 

-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {

    // タッチした座標を取得

    CGPoint p=[[touches anyObject] locationInView:self.superview];

    

    // X座標の移動量を算出。直前のラストポイントと今タッチした座標の差をみている。

    int h = [[UIScreen mainScreen] bounds].size.height;

    for (int i=0; i<N; i++) {

        if ( *1**2+*3 {

            d[i].vx=lastPoint.y-p.y;

            d[i].vy=p.x-lastPoint.x;

        }

    }

    

    lastPoint = p;

}

 

-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {

}

 

-(void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {

    [self touchesEnded:touches withEvent:event];

}

-----

Appleはん、もうこれ以上、画面サイズ変更するのかんにんしてぇぇぇ;

*1:d[i].x+20)-(p.y-h)*(-1

*2:d[i].x+20)-(p.y-h)*(-1

*3:d[i].y+20)-p.x)*((d[i].y+20)-p.x) < (40+40)*(20+20