coordinate_ctrl.c

00001 /*
00002   座標系コマンド
00003   Satofumi KAMIMURA
00004   $Id$
00005 */
00006 #define C_RUNCTRL_SOURCE
00007 
00008 #include "coordinate_ctrl.h"
00009 #include "commandCtrl.h"
00010 #include "move_ctrl.h"
00011 #include <stdio.h>
00012 #include <math.h>
00013 
00014 enum { NO_OFFSET_DATA = -1 };
00015 
00016 
00017 #define CRD_EFFECT_CALL \
00018   if (crdEffectMode) { \
00019     int c_x, c_y, c_div16; \
00020     int crd_id, crd_x, crd_y, crd_div16; \
00021     run_getLastCommandPosition(&crd_id, &crd_x, &crd_y, &crd_div16); \
00022     run_getCoordinateOffset(&c_x,&c_y,&c_div16,GL,crd_id,crd_x,crd_y,crd_div16); \
00023     sendChangeCoordinateOffset(c_x, c_y, c_div16); \
00024   }
00025 
00026 
00027 static offsetInfo_t *CrdInfo = NULL;
00028 static int CrdInfoMax = 0;
00029 static int CrdInfoNext = 0;
00030 static int crdEffectMode = CRD_EFFECT_OFF;
00031 
00032 
00033 static void initOffsetInfo(offsetInfo_t *offset) {
00034   offset->parent_id = GL;
00035   offset->x = 0;
00036   offset->y = 0;
00037   offset->div16 = 0;
00038 }
00039 
00040 
00049 void _initCoordinateCtrl(offsetInfo_t *crdInfo, int num) {
00050   int i;
00051 
00052   CrdInfo = crdInfo;
00053   CrdInfoMax = num;
00054 
00055   for (i = 0; i < num; ++i) {
00056     CrdInfo[i].parent_id = NO_OFFSET_DATA;
00057   }
00058 
00059   // GL, FS の初期化
00060   initOffsetInfo(&CrdInfo[GL]);
00061   initOffsetInfo(&CrdInfo[FS]);
00062   CrdInfo[FS].parent_id = GL;
00063   CrdInfoNext = 2;
00064 }
00065 
00066 
00067 //static int getGLBodyPos(int *x, int *y, int *div16) {
00068 //return recvGetPosition(x, y, div16);
00069 //}
00070 
00071 
00082 int run_getBodyPos(int dest_id, int *x, int *y, int *div16) {
00083   int gl_x, gl_y;
00084   long gl_div16;
00085 
00086   int ret_value = recvGetPosition(&gl_x, &gl_y, &gl_div16);
00087   if (ret_value < 0) {
00088     return ret_value;
00089   }
00090   if (dest_id == FS) {
00091     run_updateParentOffset(dest_id, gl_x, gl_y, gl_div16);
00092     *x = 0;
00093     *y = 0;
00094     *div16 = 0;
00095 
00096   } else if (dest_id != GL) { // LC
00097     // 取得した GL の位置が、自座標系でどの位置にあるかを返す
00098     ret_value = run_getCoordinateOffset(x, y, div16, dest_id,
00099                                         GL, gl_x, gl_y, gl_div16);
00100   } else {
00101     *x = gl_x;
00102     *y = gl_y;
00103     *div16 = gl_div16;
00104   }
00105   return ret_value;
00106 }
00107 
00108 
00115 int run_createCoordinate(void) {
00116   int i;
00117   for (i = 0; i <= CrdInfoNext; ++i) {
00118     if (CrdInfo[i].parent_id == NO_OFFSET_DATA) {
00119       initOffsetInfo(&CrdInfo[i]);
00120       return i;
00121     }
00122   }
00123   return -1;
00124 }
00125 
00126 
00134 int run_deleteCoordinate(int crd_id) {
00135   CrdInfo[crd_id].parent_id = NO_OFFSET_DATA;
00136   return 0;
00137 }
00138 
00139 
00149 int run_getParentId(int crd_id) {
00150   return CrdInfo[crd_id].parent_id;
00151 }
00152 
00153 
00154 int run_getGLCoordinateOffset(int *offset_x, int *offset_y,
00155                               int *offset_div16,
00156                               int dest_id, int x, int y, int div16) {
00157   offsetInfo_t diff;
00158   int id;
00159 
00160   diff.x = x;
00161   diff.y = y;
00162   diff.div16 = div16;
00163 
00164   id = dest_id;
00165   while (id != GL) {
00166     int x_tmp = diff.x;
00167     int y_tmp = diff.y;
00168     double radian = 2.0 * M_PI * CrdInfo[id].div16 / 0x10000;
00169     diff.x = (int)(x_tmp * cos(radian) - y_tmp * sin(radian)) + CrdInfo[id].x;
00170     diff.y = (int)(x_tmp * sin(radian) + y_tmp * cos(radian)) + CrdInfo[id].y;
00171     diff.div16 += CrdInfo[dest_id].div16;
00172     id = CrdInfo[id].parent_id;
00173   }
00174 
00175   *offset_x = diff.x;
00176   *offset_y = diff.y;
00177   *offset_div16 = diff.div16 & 0xffff;
00178 
00179   return 0;
00180 }
00181 
00182 
00187 int run_getCoordinateOffset(int *offset_x, int *offset_y,
00188                         int *offset_div16, int base_id,
00189                         int target_id, int x, int y, int div16) {
00190   offsetInfo_t base_offset, this_offset;
00191   int x_diff, y_diff;
00192   double radian;
00193 
00194     // 一度 GL から見た座標系を取得し、相対的な位置を計算して返す
00195   if (base_id == GL) {
00196     return run_getGLCoordinateOffset(offset_x, offset_y, offset_div16,
00197                                  target_id, x, y, div16);
00198   }
00199   run_getCoordinateOffset(&base_offset.x, &base_offset.y, &base_offset.div16,
00200                           GL, base_id, 0, 0, 0);
00201   run_getCoordinateOffset(&this_offset.x, &this_offset.y, &this_offset.div16,
00202                           GL, target_id, x, y, div16);
00203 
00204   x_diff = this_offset.x - base_offset.x;
00205   y_diff = this_offset.y - base_offset.y;
00206   *offset_div16 = (this_offset.div16 - base_offset.div16) & 0xffff;
00207 
00208   // 回転処理
00209   radian = 2.0 * M_PI * *offset_div16 / 0x10000;
00210   *offset_x = (int)(x_diff * cos(radian) - y_diff * sin(radian));
00211   *offset_y = (int)(x_diff * sin(radian) + y_diff * cos(radian));
00212 
00213   return 0;
00214 
00215 #if 0
00216   int diff_x = x;
00217   int diff_y = y;
00218   int diff_div16 = div16;
00219   int crd_id = target_id;
00220 
00221   while (crd_id == GL) {
00222     int x_tmp = diff_x;
00223     int y_tmp = diff_y;
00224     double radian = 2.0 * M_PI * CrdInfo[crd_id].div16 / 65536;
00225 
00226     diff_x = (int)(x_tmp * cos(radian) - y_tmp * sin(radian));
00227     diff_y = (int)(x_tmp * sin(radian) + y_tmp * cos(radian));
00228     diff_x += CrdInfo[crd_id].x;
00229     diff_y += CrdInfo[crd_id].y;
00230     diff_div16 += CrdInfo[crd_id].div16;
00231 
00232     crd_id = CrdInfo[crd_id].parent_id;
00233   }
00234 
00235   *offset_x = diff_x;
00236   *offset_y = diff_y;
00237   *offset_div16 = diff_div16 & 0xffff;
00238   return 0;
00239 #endif
00240 }
00241 
00242 
00252 int run_updateParentOffset(int dest_id, int x, int y, int div16) {
00253   int ret_value;
00254 
00255   if (dest_id == GL) {
00256     ret_value = sendChangeCoordinateOffset(x, y, div16);
00257     if (ret_value < 0) {
00258       return ret_value;
00259     }
00260   } else {
00261     CrdInfo[dest_id].x = x;
00262     CrdInfo[dest_id].y = y;
00263     CrdInfo[dest_id].div16 = div16;
00264   }
00265 
00266   CRD_EFFECT_CALL;
00267 
00268   return 0;
00269 }
00270 
00271 
00272 
00286 int run_setCoordinateParent(int dest_id, int parent_id,
00287                         int x, int y, int div16) {
00288   int id;
00289   // GL, FS は座標系の張り替えを禁止
00290   if ((dest_id == GL) || (dest_id == FS)) {
00291     return -1;
00292   }
00293 
00294   // 自分自身の座標系上での張り替え
00295   if (dest_id == parent_id) {
00296     offsetInfo_t offset = CrdInfo[dest_id];
00297     double radian = 2.0 * M_PI * offset.div16 / 0x10000;
00298     offset.x += (int)(x * cos(radian) - y * sin(radian));
00299     offset.y += (int)(x * sin(radian) + y * cos(radian));
00300     offset.div16 += div16;
00301     /*
00302     int offset_x = CrdInfo[dest_id].x + x;
00303     int offset_y = CrdInfo[dest_id].y + y;
00304     int offset_div16 = CrdInfo[dest_id].div16 + div16;
00305     */
00306     return run_updateParentOffset(dest_id, offset.x, offset.y, offset.div16);
00307   }
00308 
00309   // 親を子に張り付けようとしたら、例外を投げる
00310   for (id = dest_id; dest_id != GL; dest_id = CrdInfo[dest_id].parent_id) {
00311     if (dest_id == parent_id) {
00312       return -1;
00313     }
00314   }
00315 
00316   CrdInfo[dest_id].parent_id = parent_id;
00317   CrdInfo[dest_id].x = x;
00318   CrdInfo[dest_id].y = y;
00319   CrdInfo[dest_id].div16 = div16;
00320 
00321   CRD_EFFECT_CALL;
00322 
00323   return 0;
00324 }
00325 
00326 
00337 int run_setCoordinateBody(int dest_id, int x, int y, int div16) {
00338   int pos_x, pos_y, pos_div16;
00339   int ret_value;
00340 
00341   if ((dest_id == GL) || (dest_id == FS)) {
00342     return -1;
00343   }
00344 
00345   ret_value = run_getBodyPos(dest_id, &pos_x, &pos_y, &pos_div16);
00346   if (ret_value < 0) {
00347     return ret_value;
00348   }
00349 
00350   return run_setCoordinateParent(dest_id, CrdInfo[dest_id].parent_id,
00351                                  pos_x, pos_y, pos_div16);
00352 }
00353 
00354 
00368 int run_adjustBodyPos(int x, int y, int div16) {
00369 
00370   CRD_EFFECT_CALL
00371 
00372   return -1;
00373 }
00374 
00375 
00382 int run_setCoordinateMode(int mode) {
00383   crdEffectMode = (mode == CRD_EFFECT_ON) ? CRD_EFFECT_ON : CRD_EFFECT_OFF;
00384   return 0;
00385 }
00386 

Generated on Mon Apr 13 22:52:04 2009 by  doxygen 1.5.7.1