1 /*---------------------------------------------------------------------------*
2   Project:  NitroSDK - WM - demos - dataShare-Model
3   File:     ball.h
4 
5   Copyright 2007 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: ball.h,v $
14   Revision 1.1  2007/10/26 12:15:26  yosizaki
15   Initial upload.
16 
17   $NoKeywords: $
18  *---------------------------------------------------------------------------*/
19 
20 #ifndef BALL_H_
21 #define BALL_H_
22 
23 
24 #ifdef  __cplusplus
25 extern "C" {
26 #endif
27 
28 
29 /*===========================================================================*/
30 
31 #define BALL_PLAYER_MAX         16
32 #define BALL_RADIUS             4
33 #define BALL_FIELD_WIDTH        256
34 #define BALL_FIELD_HEIGHT       192
35 #define BALL_VELOCITY_ONE       10
36 #define BALL_VELOCITY_ACCEL     5
37 #define BALL_VELOCITY_DECREASE  1
38 #define BALL_VELOCITY_MAX       (BALL_VELOCITY_ONE * 6)
39 #define BALL_VELOCITY_BOOST     (BALL_VELOCITY_ONE * 3)
40 
41 #define BALL_BUTTON_A            0x0001 // A
42 #define BALL_BUTTON_B            0x0002 // B
43 #define BALL_BUTTON_SELECT       0x0004 // SELECT
44 #define BALL_BUTTON_START        0x0008 // START
45 #define BALL_BUTTON_KEY_RIGHT    0x0010 // RIGHT on the +Control Pad
46 #define BALL_BUTTON_KEY_LEFT     0x0020 // LEFT on the +Control Pad
47 #define BALL_BUTTON_KEY_UP       0x0040 // UP on the +Control Pad
48 #define BALL_BUTTON_KEY_DOWN     0x0080 // DOWN on the +Control Pad
49 #define BALL_BUTTON_R            0x0100 // R
50 #define BALL_BUTTON_L            0x0200 // L
51 #define BALL_BUTTON_X            0x0400 // X
52 #define BALL_BUTTON_Y            0x0800 // Y
53 
54 #ifndef SDK_INLINE
55 #define SDK_INLINE static inline
56 #endif
57 
58 /*===========================================================================*/
59 
60 typedef struct BallData
61 {
62     int     x;
63     int     y;
64     int     vx;
65     int     vy;
66     u16     plt;
67     u16     chr;
68 }
69 BallData;
70 
71 typedef struct SharedContext
72 {
73     BallData	ball[BALL_PLAYER_MAX];
74     u8          disabledPlt;    // The palette number when not connected
75     u8          connectedPlt;   // The palette number when connected
76     u8          ownPlt;         // The palette number used by the local host itself
77     u8          padding[1];
78 }
79 SharedContext;
80 
81 
82 /*===========================================================================*/
83 
84 static SharedContext shared[1];
85 
86 
87 /*===========================================================================*/
88 
InitBall(const char * chrArray,u8 disabledPlt,u8 connectedPlt,u8 ownPlt)89 SDK_INLINE void InitBall(const char *chrArray,
90                          u8 disabledPlt, u8 connectedPlt, u8 ownPlt)
91 {
92     int     i;
93     if (chrArray == 0)
94     {
95         chrArray = "0123456789ABCDEF";
96     }
97     for (i = 0; i < BALL_PLAYER_MAX; ++i)
98     {
99         shared->ball[i].x = (190 + (i % 4) * 5);
100         shared->ball[i].y = (40 + i * 8);
101         shared->ball[i].vx = 0;
102         shared->ball[i].vy = 0;
103         shared->ball[i].plt = disabledPlt;
104         shared->ball[i].chr = chrArray[i];
105     }
106     shared->disabledPlt = disabledPlt;
107     shared->connectedPlt = connectedPlt;
108     shared->ownPlt = ownPlt;
109 }
110 
InputBallKey(int aid,int key)111 SDK_INLINE void InputBallKey(int aid, int key)
112 {
113     if ((aid >= 0) && (aid < BALL_PLAYER_MAX))
114     {
115         if ((key & BALL_BUTTON_KEY_RIGHT) != 0)
116         {
117             if (shared->ball[aid].vx == 0)
118             {
119                 shared->ball[aid].vx += BALL_VELOCITY_BOOST;
120             }
121             else if (shared->ball[aid].vx < +BALL_VELOCITY_MAX)
122             {
123                 shared->ball[aid].vx += BALL_VELOCITY_ACCEL;
124             }
125         }
126         else if ((key & BALL_BUTTON_KEY_LEFT) != 0)
127         {
128             if (shared->ball[aid].vx == 0)
129             {
130                 shared->ball[aid].vx -= BALL_VELOCITY_BOOST;
131             }
132             else if (shared->ball[aid].vx > -BALL_VELOCITY_MAX)
133             {
134                 shared->ball[aid].vx -= BALL_VELOCITY_ACCEL;
135             }
136         }
137         if ((key & BALL_BUTTON_KEY_DOWN) != 0)
138         {
139             if (shared->ball[aid].vy == 0)
140             {
141                 shared->ball[aid].vy += BALL_VELOCITY_BOOST;
142             }
143             else if (shared->ball[aid].vy < +BALL_VELOCITY_MAX)
144             {
145                 shared->ball[aid].vy += BALL_VELOCITY_ACCEL;
146             }
147         }
148         if ((key & BALL_BUTTON_KEY_UP) != 0)
149         {
150             if (shared->ball[aid].vy == 0)
151             {
152                 shared->ball[aid].vy -= BALL_VELOCITY_BOOST;
153             }
154             else if (shared->ball[aid].vy > -BALL_VELOCITY_MAX)
155             {
156                 shared->ball[aid].vy -= BALL_VELOCITY_ACCEL;
157             }
158         }
159         shared->ball[aid].plt = shared->connectedPlt;
160     }
161 }
162 
UpdateBalls(u16 ownAID)163 SDK_INLINE void UpdateBalls(u16 ownAID)
164 {
165     int     i, j;
166     int     bound = 0;
167     if ((ownAID >= 0) && (ownAID < BALL_PLAYER_MAX))
168     {
169         shared->ball[ownAID].plt = shared->ownPlt;
170     }
171     // Acceleration/deceleration and outer wall collision detection
172     for (i = 0; i < BALL_PLAYER_MAX; ++i)
173     {
174         int     x = shared->ball[i].x;
175         int     y = shared->ball[i].y;
176         x += shared->ball[i].vx / BALL_VELOCITY_ONE;
177         y += shared->ball[i].vy / BALL_VELOCITY_ONE;
178         if ((x < 0) || (x > BALL_FIELD_WIDTH - BALL_RADIUS * 2))
179         {
180             shared->ball[i].vx *= -1;
181             bound |= (1 << i);
182         }
183         else if (shared->ball[i].vx != 0)
184         {
185             shared->ball[i].vx -= (shared->ball[i].vx > 0) ? +BALL_VELOCITY_DECREASE : -BALL_VELOCITY_DECREASE;
186         }
187         if ((y < 0) || (y > BALL_FIELD_HEIGHT - BALL_RADIUS * 2))
188         {
189             shared->ball[i].vy *= -1;
190             bound |= (1 << i);
191         }
192         else if (shared->ball[i].vy != 0)
193         {
194             shared->ball[i].vy -= (shared->ball[i].vy > 0) ? +BALL_VELOCITY_DECREASE : -BALL_VELOCITY_DECREASE;
195         }
196         if ((bound & (1 << i)) == 0)
197         {
198             shared->ball[i].x = x;
199             shared->ball[i].y = y;
200             for (j = 0; j < BALL_PLAYER_MAX; ++j)
201             {
202                 if (j != i)
203                 {
204                     int     dx = shared->ball[j].x - x;
205                     int     dy = shared->ball[j].y - y;
206                     if (dx * dx + dy * dy < (BALL_RADIUS * 2) * (BALL_RADIUS * 2))
207                     {
208                         BOOL    target_bound = ((bound & (1 << j)) != 0);
209                         int     vx1 = shared->ball[i].vx;
210                         int     vy1 = shared->ball[i].vy;
211                         int     vx2, vy2;
212                         if (!target_bound)
213                         {
214                             vx2 = shared->ball[j].vx;
215                             vy2 = shared->ball[j].vy;
216                         }
217                         else
218                         {
219                             vx2 = 0;
220                             vy2 = 0;
221                         }
222                         {
223                             int     dvx = vx2 - vx1;
224                             int     dvy = vy2 - vy1;
225                             int     dx2 = dx * dx;
226                             int     dy2 = dy * dy;
227                             int     mag2 = dx2 + dy2;
228                             int     crs = dx * dy;
229                             shared->ball[i].vx = ((vx1 * dy2 + vx2 * dx2) + dvy * crs) / mag2;
230                             shared->ball[i].vy = ((vy1 * dx2 + vy2 * dy2) + dvx * crs) / mag2;
231                             if (!target_bound)
232                             {
233                                 shared->ball[j].vx = ((vx1 * dx2 + vx2 * dy2) - dvy * crs) / mag2;
234                                 shared->ball[j].vy = ((vy1 * dx2 + vy2 * dy2) - dvx * crs) / mag2;
235                                 bound |= (1 << j);
236                             }
237                         }
238                         bound |= (1 << i);
239                         break;
240                     }
241                 }
242             }
243         }
244     }
245 }
246 
247 /*===========================================================================*/
248 
249 #ifdef  __cplusplus
250 }       /* extern "C" */
251 #endif
252 
253 #endif /* BALL_H_ */
254 
255 /*---------------------------------------------------------------------------*
256   End of file
257  *---------------------------------------------------------------------------*/
258