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