home *** CD-ROM | disk | FTP | other *** search
/ PDA Software Library / pdasoftwarelib.iso / PILOT / GAMES / NEKO / NEKO.ZIP / neko / src / neko.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-02  |  8.2 KB  |  400 lines

  1. /* neko.c */
  2.  
  3. #pragma pack(2)
  4.  
  5. #include <Pilot.h>
  6.  
  7. #include "neko.h"
  8.  
  9. /*
  10.  * constants
  11.  */
  12.  
  13. #define WINDOW_TOP 15
  14.  
  15. #define NEKO_WIDTH 32
  16. #define NEKO_HEIGHT 32
  17.  
  18. #define CURSOR_WIDTH 16
  19. #define CURSOR_HEIGHT 16
  20.  
  21. #define INTERVAL 12
  22. #define SLEEP_INTERVAL (INTERVAL * 4)
  23.  
  24. #define MOVE_DELTA 12
  25. #define NANAME_MOVE_DELTA 9
  26.  
  27. #define NEKO_STOP 0
  28. #define NEKO_JARE 1
  29. #define NEKO_KAKI 2
  30. #define NEKO_AKUBI 3
  31. #define NEKO_SLEEP 4
  32. #define NEKO_AWAKE 5
  33. #define NEKO_U_MOVE 6
  34. #define NEKO_D_MOVE 7
  35. #define NEKO_L_MOVE 8
  36. #define NEKO_R_MOVE 9
  37. #define NEKO_UL_MOVE 10
  38. #define NEKO_UR_MOVE 11
  39. #define NEKO_DL_MOVE 12
  40. #define NEKO_DR_MOVE 13
  41. #define NEKO_U_TOGI 14
  42. #define NEKO_D_TOGI 15
  43. #define NEKO_L_TOGI 16
  44. #define NEKO_R_TOGI 17
  45.  
  46. #define NEKO_STOP_TIME 4
  47. #define NEKO_JARE_TIME 10
  48. #define NEKO_KAKI_TIME 4
  49. #define NEKO_AKUBI_TIME 3
  50. #define NEKO_AWAKE_TIME 3
  51. #define NEKO_TOGI_TIME 10
  52.  
  53. #define CURSOR_OFF 0
  54. #define CURSOR_ON 1
  55. #define CURSOR_MOVED 2
  56.  
  57. /*
  58.  * macros
  59.  */
  60.  
  61. #define ABS(x) ((x) >= 0 ? (x) : -(x))
  62.  
  63. #define TRIM(x, min, max) \
  64.     if ((x) < (min)) { (x) = (min); } else if ((x) > (max)) { (x) = (max); }
  65.  
  66. /*
  67.  * global variables
  68.  */
  69.  
  70. static Int neko_state;
  71. static Int neko_animation;
  72. static Int neko_timer;
  73.  
  74. static Int neko_x;
  75. static Int neko_y;
  76.  
  77. static Int cursor_state;
  78.  
  79. static Int cursor_x;
  80. static Int cursor_y;
  81.  
  82. static Int cursor_bitmap;
  83. static Int next_cursor;
  84.  
  85. /*
  86.  * functions
  87.  */
  88.  
  89. static void DrawBitmap(Int x, Int y, Int id)
  90. {
  91.     VoidHand h;
  92.     VoidPtr p;
  93.  
  94.     h = DmGet1Resource('Tbmp', id);
  95.     if (h != NULL) {
  96.     p = MemHandleLock(h);
  97.     WinDrawBitmap((BitmapPtr) p, x, y);
  98.     MemHandleUnlock(h);
  99.     DmReleaseResource(h);
  100.     }
  101. }
  102.  
  103. static void DrawNeko()
  104. {
  105.     DrawBitmap(neko_x, neko_y, NEKO_BITMAPS + neko_state * 2 + neko_animation);
  106.     neko_animation = ! neko_animation;
  107.     ++neko_timer;
  108. }
  109.  
  110. static void EraseNeko()
  111. {
  112.     RectangleType r;
  113.     r.topLeft.x = neko_x;
  114.     r.topLeft.y = neko_y;
  115.     r.extent.x = NEKO_WIDTH;
  116.     r.extent.y = NEKO_HEIGHT;
  117.     WinEraseRectangle(&r, 0);
  118. }
  119.  
  120. static void DrawCursor()
  121. {
  122.     if (cursor_state != CURSOR_OFF) {
  123.     DrawBitmap(cursor_x - CURSOR_WIDTH / 2, cursor_y, cursor_bitmap);
  124.     }
  125. }
  126.  
  127. static void EraseCursor()
  128. {
  129.     if (cursor_state != CURSOR_OFF) {
  130.     RectangleType r;
  131.     r.topLeft.x = cursor_x - CURSOR_WIDTH / 2;
  132.     r.topLeft.y = cursor_y;
  133.     r.extent.x = CURSOR_WIDTH;
  134.     r.extent.y = CURSOR_HEIGHT;
  135.     WinEraseRectangle(&r, 0);
  136.     }
  137. }
  138.  
  139. static void SetNekoState(Int state)
  140. {
  141.     neko_state = state;
  142.     neko_animation = 0;
  143.     neko_timer = 0;
  144. }
  145.  
  146. static void SetCursorState(Int state, EventPtr event)
  147. {
  148.     cursor_state = state;
  149.     if (event != NULL) {
  150.     cursor_x = event->screenX;
  151.     cursor_y = event->screenY;
  152.     }
  153. }
  154.  
  155. static void NekoDirection()
  156. {
  157.     Int dx, dy, state;
  158.  
  159.     dx = (cursor_x - NEKO_WIDTH / 2) - neko_x;
  160.     dy = (cursor_y - NEKO_HEIGHT + CURSOR_HEIGHT / 2) - neko_y;
  161.     if (ABS(dx) * 5 < ABS(dy) * 2) {
  162.     state = NEKO_U_MOVE + (dy >= 0);
  163.     } else if (ABS(dx) * 2 > ABS(dy) * 5) {
  164.     state = NEKO_L_MOVE + (dx >= 0);
  165.     } else {
  166.     state = NEKO_UL_MOVE + (dy >= 0) * 2 + (dx > 0);
  167.     }
  168.     if (state != neko_state) {
  169.     SetNekoState(state);
  170.     }
  171. }
  172.  
  173. static Boolean CalcNekoXY()
  174. {
  175.     Int dx, dy, max;
  176.     Int prev_x, prev_y;
  177.  
  178.     dx = (cursor_x - NEKO_WIDTH / 2) - neko_x;
  179.     dy = (cursor_y - NEKO_HEIGHT + CURSOR_HEIGHT / 2) - neko_y;
  180.     if (ABS(dx) * 5 < ABS(dy) * 2) {
  181.     max = MOVE_DELTA;
  182.     } else if (ABS(dx) * 2 > ABS(dy) * 5) {
  183.     max = MOVE_DELTA;
  184.     } else {
  185.     max = NANAME_MOVE_DELTA;
  186.     }
  187.     if (ABS(dx) > max || ABS(dy) > max) {
  188.     if (ABS(dx) >= ABS(dy)) {
  189.         dy = dy * max / ABS(dx);
  190.         dx = (dx >= 0) ? max : -max;
  191.     } else {
  192.         dx = dx * max / ABS(dy);
  193.         dy = (dy >= 0) ? max : -max;
  194.     }
  195.     }
  196.  
  197.     prev_x = neko_x;
  198.     prev_y = neko_y;
  199.     neko_x += dx;
  200.     neko_y += dy;
  201.     TRIM(neko_x, 0, WINDOW_WIDTH - NEKO_WIDTH)
  202.     TRIM(neko_y, WINDOW_TOP, WINDOW_HEIGHT - NEKO_HEIGHT)
  203.  
  204.     return (neko_x != prev_x) || (neko_y != prev_y);
  205. }
  206.  
  207. static void NekoThinkMove()
  208. {
  209.     EraseNeko();
  210.  
  211.     if (cursor_state == CURSOR_MOVED) {
  212.     if (neko_state == NEKO_STOP
  213.      || neko_state == NEKO_JARE
  214.      || neko_state == NEKO_KAKI
  215.      || neko_state == NEKO_AKUBI
  216.      || neko_state == NEKO_SLEEP
  217.      || neko_state == NEKO_U_TOGI
  218.      || neko_state == NEKO_D_TOGI
  219.      || neko_state == NEKO_L_TOGI
  220.      || neko_state == NEKO_R_TOGI) {
  221.         SetNekoState(NEKO_AWAKE);
  222.         SetCursorState(CURSOR_ON, NULL);
  223.     }
  224.     }
  225.  
  226.     switch (neko_state) {
  227.     case NEKO_STOP:
  228.     if (neko_timer >= NEKO_STOP_TIME) {
  229.         if (cursor_x < CURSOR_WIDTH / 2) {
  230.         SetNekoState(NEKO_L_TOGI);
  231.         } else if (cursor_x > WINDOW_WIDTH - CURSOR_WIDTH / 2) {
  232.         SetNekoState(NEKO_R_TOGI);
  233.         } else if (cursor_y < WINDOW_TOP + CURSOR_HEIGHT / 2) {
  234.         SetNekoState(NEKO_U_TOGI);
  235.         } else if (cursor_y > WINDOW_HEIGHT - CURSOR_HEIGHT / 2) {
  236.         SetNekoState(NEKO_D_TOGI);
  237.         } else {
  238.         SetNekoState(NEKO_JARE);
  239.         }
  240.     }
  241.     break;
  242.  
  243.     case NEKO_JARE:
  244.     if (neko_timer >= NEKO_JARE_TIME) {
  245.         EraseCursor();
  246.         SetNekoState(NEKO_KAKI);
  247.         SetCursorState(CURSOR_OFF, NULL);
  248.     }
  249.     break;
  250.  
  251.     case NEKO_KAKI:
  252.     if (neko_timer >= NEKO_KAKI_TIME) {
  253.         SetNekoState(NEKO_AKUBI);
  254.     }
  255.     break;
  256.  
  257.     case NEKO_AKUBI:
  258.     if (neko_timer >= NEKO_AKUBI_TIME) {
  259.         SetNekoState(NEKO_SLEEP);
  260.     }
  261.     break;
  262.  
  263.     case NEKO_SLEEP:
  264.     break;
  265.  
  266.     case NEKO_AWAKE:
  267.     if (neko_timer >= NEKO_AWAKE_TIME) {
  268.         NekoDirection();
  269.     }
  270.     break;
  271.  
  272.     case NEKO_U_MOVE:
  273.     case NEKO_D_MOVE:
  274.     case NEKO_L_MOVE:
  275.     case NEKO_R_MOVE:
  276.     case NEKO_UL_MOVE:
  277.     case NEKO_UR_MOVE:
  278.     case NEKO_DL_MOVE:
  279.     case NEKO_DR_MOVE:
  280.     if (cursor_state == CURSOR_MOVED) {
  281.         NekoDirection();
  282.         SetCursorState(CURSOR_ON, NULL);
  283.     }
  284.     if (! CalcNekoXY()) {
  285.         SetNekoState(NEKO_STOP);
  286.     }
  287.     break;
  288.  
  289.     case NEKO_U_TOGI:
  290.     case NEKO_D_TOGI:
  291.     case NEKO_L_TOGI:
  292.     case NEKO_R_TOGI:
  293.     if (neko_timer >= NEKO_TOGI_TIME) {
  294.         EraseCursor();
  295.         SetNekoState(NEKO_KAKI);
  296.         SetCursorState(CURSOR_OFF, NULL);
  297.     }
  298.     break;
  299.     }
  300.  
  301.     DrawNeko();
  302.     DrawCursor();
  303. }
  304.  
  305. static void InitNeko()
  306. {
  307.     neko_x = (WINDOW_WIDTH - NEKO_WIDTH) / 2;
  308.     neko_y = (WINDOW_HEIGHT - NEKO_HEIGHT) / 2;
  309.     SetNekoState(NEKO_SLEEP);
  310.     SetCursorState(CURSOR_OFF, NULL);
  311.     next_cursor = MOUSE_CURSOR_ID;
  312.     DrawNeko();
  313. }
  314.  
  315. static Boolean HandleMainFormEvent(EventPtr event)
  316. {
  317.     switch (event->eType) {
  318.     case frmOpenEvent:
  319.     FrmDrawForm(FrmGetActiveForm());
  320.     InitNeko();
  321.         return true;
  322.  
  323.     case ctlSelectEvent:
  324.         if (event->data.ctlSelect.controlID == BIRD_CURSOR_ID
  325.          || event->data.ctlSelect.controlID == MOUSE_CURSOR_ID
  326.          || event->data.ctlSelect.controlID == FISH_CURSOR_ID) {
  327.         next_cursor = event->data.ctlSelect.controlID;
  328.         return true;
  329.     }
  330.         if (event->data.ctlSelect.controlID == ABOUT_BUTTON_ID) {
  331.         FormPtr frm;
  332.         frm = FrmInitForm(ABOUT_FORM_ID);
  333.         FrmDoDialog(frm);
  334.         FrmDeleteForm(frm);
  335.         return true;
  336.     }
  337.     break;
  338.  
  339.     case penDownEvent:
  340.     case penMoveEvent:
  341.     if (event->screenY >= WINDOW_TOP) {
  342.         EraseCursor();
  343.         SetCursorState(CURSOR_MOVED, event);
  344.         cursor_bitmap = next_cursor;
  345.         NekoThinkMove();
  346.         return true;
  347.     }
  348.     break;
  349.  
  350.     case nilEvent:
  351.     NekoThinkMove();
  352.     return true;
  353.  
  354.     default:
  355.     break;
  356.     }
  357.  
  358.     return false;
  359. }
  360.  
  361. static Boolean HandleAppEvent(EventPtr event)
  362. {
  363.     FormPtr form;
  364.  
  365.     if (event->eType == frmLoadEvent) {
  366.     form = FrmInitForm(event->data.frmLoad.formID);
  367.     FrmSetActiveForm(form);
  368.     if (event->data.frmLoad.formID == MAIN_FORM_ID) {
  369.         FrmSetEventHandler(form, HandleMainFormEvent);
  370.     }
  371.     return true;
  372.     }
  373.     return false;
  374. }
  375.  
  376. static void EventLoop()
  377. {
  378.     EventType event;
  379.     Word error;
  380.  
  381.     do {
  382.     EvtGetEvent(&event,
  383.         neko_state == NEKO_SLEEP ? SLEEP_INTERVAL : INTERVAL);
  384.     if (SysHandleEvent(&event) == false
  385.      && MenuHandleEvent(NULL, &event, &error) == false
  386.      && HandleAppEvent(&event) == false) {
  387.         FrmDispatchEvent(&event);
  388.     }
  389.     } while (event.eType != appStopEvent);
  390. }
  391.  
  392. DWord PilotMain(Word cmd, Ptr cmdPBP, Word launchFlags)
  393. {
  394.     if (cmd == sysAppLaunchCmdNormalLaunch) {
  395.     FrmGotoForm(MAIN_FORM_ID);
  396.     EventLoop();
  397.     }
  398.     return 0;
  399. }
  400.