|
|
1.1 root 1: /*---------------------------------------------------------------------------*\
2: | BOUNCING BALL MODULE
3: |
4: | segment: _TEXT (DOS16)
5: | created: 19-Oct-90
6: | history: 19-Oct-90 <chriswil> created.
7: |
8: \*---------------------------------------------------------------------------*/
9:
10: #include <windows.h>
11: #include "gdidemo.h"
12: #include "bounce.h"
13:
14:
15: VOID XFormClear(PMYXFORM);
16: VOID XFormScale(PMYXFORM,int,int);
17: VOID XFormTrans(PMYXFORM,int,int);
18: VOID XFormPoint(PMYXFORM,LPPOINT);
19:
20:
21: /*---------------------------------------------------------------------------*\
22: | CREATE BOUNCE WINDOW PROCEDURE
23: |
24: | created: 20-May-91
25: | history: 20-May-91 <chriswil> created.
26: |
27: \*---------------------------------------------------------------------------*/
28: HWND FAR CreateBounceWindow(HWND hWndClient, int nItem)
29: {
30: HANDLE hInstance;
31: MDICREATESTRUCT mcs;
32:
33:
34: hInstance = GETINSTANCE(hWndClient);
35:
36: /*
37: ** Initialize the MDI create struct for creation of the
38: ** test window.
39: */
40: mcs.szClass = BOUNCECLASS;
41: mcs.szTitle = BOUNCETITLE;
42: mcs.hOwner = hInstance;
43: mcs.x = CW_USEDEFAULT;
44: mcs.y = CW_USEDEFAULT;
45: mcs.cx = CW_USEDEFAULT;
46: mcs.cy = CW_USEDEFAULT;
47: mcs.style = 0l;
48: mcs.lParam = (LONG)nItem;
49:
50: return((HWND)SendMessage(hWndClient,WM_MDICREATE,NULL,(LONG)(LPMDICREATESTRUCT)&mcs));
51: }
52:
53:
54: /*---------------------------------------------------------------------------*\
55: | BOUNCE WINDOW PROCEDURE
56: |
57: | created: 20-May-91
58: | history: 20-May-91 <chriswil> created.
59: |
60: \*---------------------------------------------------------------------------*/
61: LONG APIENTRY BounceProc(HWND hWnd, UINT wMsg, WPARAM wParam, LONG lParam)
62: {
63: switch(wMsg)
64: {
65: case WM_CREATE:
66: BounceCreateProc(hWnd);
67: break;
68:
69: case WM_MOVE:
70: BounceRefresh(hWnd);
71: break;
72:
73: case WM_COMMAND:
74: BounceCommandProc(hWnd,wParam,lParam);
75: break;
76:
77: case WM_TIMER:
78: BounceObjects(hWnd);
79: break;
80:
81: case WM_PAINT:
82: BouncePaintProc(hWnd);
83: break;
84:
85: case WM_DESTROY:
86: BounceDestroyProc(hWnd);
87: break;
88:
89:
90: default:
91: return(DefMDIChildProc(hWnd,wMsg,wParam,lParam));
92: }
93: return(0l);
94: }
95:
96:
97: /*---------------------------------------------------------------------------*\
98: | BOUNCE CREATE PROCEDURE
99: |
100: | created: 20-May-91
101: | history: 20-May-91 <chriswil> created.
102: |
103: \*---------------------------------------------------------------------------*/
104: BOOL BounceCreateProc(HWND hWnd)
105: {
106: PBOUNCEDATA pbd;
107:
108:
109: if(AllocWindowInfo(hWnd,sizeof(BOUNCEDATA)))
110: {
111: if(pbd = (PBOUNCEDATA)LockWindowInfo(hWnd))
112: {
113: pbd->hBall1 = ballCreate(hWnd,20,20,RGB(255,0,0));
114: pbd->hBall2 = ballCreate(hWnd,20,20,RGB(0,0,255));
115: pbd->hBall3 = ballCreate(hWnd,20,20,RGB(0,255,0));
116: pbd->hBall4 = ballCreate(hWnd,20,20,RGB(255,0,255));
117:
118: UnlockWindowInfo(hWnd);
119:
120: SetTimer(hWnd,1,50,NULL);
121: return(TRUE);
122: }
123: FreeWindowInfo(hWnd);
124: }
125: return(FALSE);
126: }
127:
128:
129: /*---------------------------------------------------------------------------*\
130: | BOUNCE COMMAND PROCEDURE
131: |
132: | created: 20-May-91
133: | history: 20-May-91 <chriswil> created.
134: |
135: \*---------------------------------------------------------------------------*/
136: BOOL BounceCommandProc(HWND hWnd, WPARAM wParam, LONG lParam)
137: {
138: hWnd = hWnd;
139: wParam = wParam;
140: lParam = lParam;
141:
142: return(TRUE);
143: }
144:
145:
146: /*---------------------------------------------------------------------------*\
147: | BOUNCE PAINT PROCEDURE
148: |
149: | created: 20-May-91
150: | history: 20-May-91 <chriswil> created.
151: |
152: \*---------------------------------------------------------------------------*/
153: VOID BouncePaintProc(HWND hWnd)
154: {
155: HDC hDC;
156: PAINTSTRUCT ps;
157:
158:
159: if(hDC = BeginPaint(hWnd,&ps))
160: EndPaint(hWnd,&ps);
161:
162: BounceRefresh(hWnd);
163:
164: return;
165: }
166:
167:
168: /*---------------------------------------------------------------------------*\
169: | BOUNCE DESTROY PROCEDURE
170: |
171: | created: 20-May-91
172: | history: 20-May-91 <chriswil> created.
173: |
174: \*---------------------------------------------------------------------------*/
175: VOID BounceDestroyProc(HWND hWnd)
176: {
177: PBOUNCEDATA pbd;
178:
179:
180: KillTimer(hWnd,1);
181: if(pbd = (PBOUNCEDATA)LockWindowInfo(hWnd))
182: {
183: ballDestroy(pbd->hBall1);
184: ballDestroy(pbd->hBall2);
185: ballDestroy(pbd->hBall3);
186: ballDestroy(pbd->hBall4);
187:
188: UnlockWindowInfo(hWnd);
189: }
190: FreeWindowInfo(hWnd);
191: return;
192: }
193:
194:
195: /*---------------------------------------------------------------------------*\
196: | BOUNCE REFRESH
197: |
198: | created: 20-May-91
199: | history: 20-May-91 <chriswil> created.
200: |
201: \*---------------------------------------------------------------------------*/
202: VOID BounceRefresh(HWND hWnd)
203: {
204: PBOUNCEDATA pbd;
205: RECT rect;
206: HDC hDC;
207: POINT pDimensions;
208: int xDirection,yDirection;
209:
210:
211: if(pbd = (PBOUNCEDATA)LockWindowInfo(hWnd))
212: {
213: if(hDC = GetDC(hWnd))
214: {
215: GetClientRect(hWnd,&rect);
216: FillRect(hDC,&rect,GETCLASSBRUSH(hWnd));
217:
218: xDirection = ((lRandom() % 5)+5);
219: yDirection = ((lRandom() % 5)+5);
220: ballSetPosition(pbd->hBall1,0,0);
221: ballSetDirection(pbd->hBall1,xDirection,yDirection);
222:
223:
224: ballGetDimensions(pbd->hBall2,&pDimensions);
225: ballSetPosition(pbd->hBall2,rect.right-pDimensions.x,0);
1.1.1.2 ! root 226: xDirection = -(((int)lRandom() % 5)+5);
1.1 root 227: yDirection = ((lRandom() % 5)+5);
228: ballSetDirection(pbd->hBall2,xDirection,yDirection);
229:
230:
231: ballGetDimensions(pbd->hBall3,&pDimensions);
232: ballSetPosition(pbd->hBall3,0,rect.bottom-pDimensions.y);
233: xDirection = ((lRandom() % 5)+5);
1.1.1.2 ! root 234: yDirection = -((int)(lRandom() % 5)+5);
1.1 root 235: ballSetDirection(pbd->hBall3,xDirection,yDirection);
236:
237:
238: ballGetDimensions(pbd->hBall4,&pDimensions);
239: ballSetPosition(pbd->hBall4,rect.right-pDimensions.x,rect.bottom-pDimensions.y);
1.1.1.2 ! root 240: xDirection = -((int)(lRandom() % 5)+5);
! 241: yDirection = -((int)(lRandom() % 5)+5);
1.1 root 242: ballSetDirection(pbd->hBall4,xDirection,yDirection);
243:
244:
245: ballBounce(pbd->hBall1);
246: ballBounce(pbd->hBall2);
247: ballBounce(pbd->hBall3);
248: ballBounce(pbd->hBall4);
249:
250: ReleaseDC(hWnd,hDC);
251: }
252: UnlockWindowInfo(hWnd);
253: }
254: return;
255: }
256:
257:
258:
259: VOID BounceObjects(HWND hWnd)
260: {
261: PBOUNCEDATA pbd;
262:
263:
264: if(pbd = (PBOUNCEDATA)LockWindowInfo(hWnd))
265: {
266: /*
267: ** Determine if the balls hit any of the edges of the display. If
268: ** they do, then these functions reset their position to something
269: ** more desireable and re-do their direction.
270: */
271: CheckEdgePosition(hWnd,pbd->hBall1);
272: CheckEdgePosition(hWnd,pbd->hBall2);
273: CheckEdgePosition(hWnd,pbd->hBall3);
274: CheckEdgePosition(hWnd,pbd->hBall4);
275:
276: ballBounce(pbd->hBall1);
277: ballBounce(pbd->hBall2);
278: ballBounce(pbd->hBall3);
279: ballBounce(pbd->hBall4);
280:
281:
282: UnlockWindowInfo(hWnd);
283: }
284: return;
285: }
286:
287:
288: VOID CheckEdgePosition(HWND hWnd, HANDLE hBall)
289: {
290: POINT pPos,pDir,pDim;
291: int xNewPos,yNewPos,xNewDir,yNewDir;
292: RECT rect;
293:
294:
295:
296: ballGetPosition(hBall,&pPos);
297: ballGetDirection(hBall,&pDir);
298: ballGetDimensions(hBall,&pDim);
299:
300: GetClientRect(hWnd,&rect);
301:
302:
303: /*
304: ** Check each edge of the client rectagle. If the ball goes past the
305: ** boundries, reset the position and give it a new direction.
306: */
307: xNewDir = pDir.x;
308: yNewDir = pDir.y;
309: xNewPos = pPos.x+pDir.x;
310: yNewPos = pPos.y+pDir.y;
311:
312: if(xNewPos < rect.left)
313: {
314: xNewDir = ((lRandom() % 5)+5);
315: ballSetPosition(hBall,rect.left,pPos.y);
316: }
317: if((xNewPos+pDim.x) > rect.right)
318: {
1.1.1.2 ! root 319: xNewDir = -(((int)lRandom() % 5)+5);
1.1 root 320: ballSetPosition(hBall,rect.right-pDim.x,pPos.y);
321: }
322: if(yNewPos < rect.top)
323: {
324: yNewDir = ((lRandom() % 5)+5);
325: ballSetPosition(hBall,pPos.x,rect.top);
326: }
327: if((yNewPos+pDim.y) > rect.bottom)
328: {
1.1.1.2 ! root 329: yNewDir = -(((int)lRandom() % 5)+5);
1.1 root 330: ballSetPosition(hBall,pPos.x,rect.bottom-pDim.y);
331: }
332: ballSetDirection(hBall,xNewDir,yNewDir);
333:
334: return;
335: }
336:
337:
338: /*---------------------------------------------------------------------------*\
339: | CLEAR XFORM
340: |
341: | created: 31-Oct-90
342: | history: 31-Oct-90 <chriswil> created.
343: |
344: \*---------------------------------------------------------------------------*/
345: VOID XFormClear(PMYXFORM pXForm)
346: {
347: int Row,Col;
348:
349:
350: for(Row=0; Row < 3; Row++)
351: for(Col=0; Col < 3; Col++)
352: if(Row == Col)
353: pXForm->xForm[Row][Col] = 1;
354: else
355: pXForm->xForm[Row][Col] = 0;
356: return;
357: }
358:
359:
360: /*---------------------------------------------------------------------------*\
361: | XFORM SCALE
362: |
363: | created: 31-Oct-90
364: | history: 31-Oct-90 <chriswil> created.
365: |
366: \*---------------------------------------------------------------------------*/
367: VOID XFormScale(PMYXFORM pXForm, int xScale, int yScale)
368: {
369: int idx;
370:
371:
372: for(idx=0; idx < 3; idx++)
373: {
374: pXForm->xForm[idx][0] = pXForm->xForm[idx][0] * xScale;
375: pXForm->xForm[idx][1] = pXForm->xForm[idx][1] * yScale;
376: }
377: return;
378: }
379:
380:
381:
382: /*---------------------------------------------------------------------------*\
383: |
384: | created: 31-Oct-90
385: | history: 31-Oct-90 <chriswil> created.
386: |
387: \*---------------------------------------------------------------------------*/
388: VOID XFormTrans(PMYXFORM pXForm, int xTrans, int yTrans)
389: {
390: pXForm->xForm[2][0] = pXForm->xForm[2][0] + xTrans;
391: pXForm->xForm[2][1] = pXForm->xForm[2][1] + yTrans;
392:
393: return;
394: }
395:
396:
397:
398: /*---------------------------------------------------------------------------*\
399: |
400: | created: 31-Oct-90
401: | history: 31-Oct-90 <chriswil> created.
402: |
403: \*---------------------------------------------------------------------------*/
404: VOID XFormPoint(PMYXFORM pXForm, LPPOINT pPoint)
405: {
406: int x,y;
407:
408:
409: x = (pXForm->xForm[0][0] * pPoint->x) + (pXForm->xForm[1][0] * pPoint->y) + pXForm->xForm[2][0];
410: y = (pXForm->xForm[0][1] * pPoint->x) + (pXForm->xForm[1][1] * pPoint->y) + pXForm->xForm[2][1];
411:
412: pPoint->x = x;
413: pPoint->y = y;
414:
415: return;
416: }
417:
418:
419: /*
420: ** -------------------------------
421: ** -------------------------------
422: ** -------------------------------
423: */
424:
425: HANDLE ballCreate(HWND hWnd, int nWidth, int nHeight, COLORREF crColor)
426: {
427: HANDLE hBall;
428: PBALLDATA pbd;
429:
430: if(hBall = LocalAlloc(LHND,sizeof(BALLDATA)))
431: {
432: if(pbd = (PBALLDATA)LocalLock(hBall))
433: {
434: pbd->hWnd = hWnd;
435: pbd->nWidth = nWidth;
436: pbd->nHeight = nHeight;
437: pbd->xDirection = 0;
438: pbd->yDirection = 0;
439: pbd->bNewPosition = FALSE;
440: pbd->xPosition = 0;
441: pbd->yPosition = 0;
442: pbd->crColor = crColor;
443: XFormClear(&pbd->xForm);
444:
445: LocalUnlock(hBall);
446: return(hBall);
447: }
448: LocalFree(hBall);
449: }
450: return(NULL);
451: }
452:
453:
454: BOOL ballDestroy(HANDLE hBall)
455: {
456: if(LocalFree(hBall))
457: return(FALSE);
458: return(TRUE);
459: }
460:
461:
462: VOID ballBounce(HANDLE hBall)
463: {
464: PBALLDATA pbd;
465: HDC hDC;
466: HBRUSH hBrush;
467: POINT pOrg,pExt;
468: HRGN hTmp,hOld,hNew;
469:
470:
471: if(pbd = (PBALLDATA)LocalLock(hBall))
472: {
473: /*
474: ** Create old ball object.
475: */
476: pOrg.x = 0;
477: pOrg.y = 0;
478: pExt.x = pbd->nWidth;
479: pExt.y = pbd->nHeight;
480: XFormPoint(&pbd->xForm,&pOrg);
481: XFormPoint(&pbd->xForm,&pExt);
482: hOld = CreateEllipticRgn(pOrg.x,pOrg.y,pExt.x,pExt.y);
483:
484:
485: /*
486: ** Create new ball object.
487: */
488: if(pbd->bNewPosition)
489: {
490: pbd->bNewPosition = FALSE;
491: XFormClear(&pbd->xForm);
492: XFormTrans(&pbd->xForm,pbd->xPosition,pbd->yPosition);
493: }
494: else
495: XFormTrans(&pbd->xForm,pbd->xDirection,pbd->yDirection);
496: pOrg.x = 0;
497: pOrg.y = 0;
498: pExt.x = pbd->nWidth;
499: pExt.y = pbd->nHeight;
500: XFormPoint(&pbd->xForm,&pOrg);
501: XFormPoint(&pbd->xForm,&pExt);
502: hNew = CreateEllipticRgn(pOrg.x,pOrg.y,pExt.x,pExt.y);
503:
504:
505:
506: if(hDC = GetDC(pbd->hWnd))
507: {
508: hTmp = CreateRectRgn(1,1,2,2);
509: CombineRgn(hTmp,hOld,hNew,RGN_DIFF);
510: FillRgn(hDC,hTmp,GETCLASSBRUSH(pbd->hWnd));
511:
512: hBrush = CreateSolidBrush(pbd->crColor);
513: FillRgn(hDC,hNew,hBrush);
514: DeleteObject(hBrush);
515:
516: ReleaseDC(pbd->hWnd,hDC);
517:
518: DeleteObject(hTmp);
519: }
520:
521: DeleteObject(hOld);
522: DeleteObject(hNew);
523:
524: LocalUnlock(hBall);
525: }
526: return;
527: }
528:
529:
530: BOOL ballGetDimensions(HANDLE hBall, LPPOINT pDimension)
531: {
532: PBALLDATA pbd;
533: BOOL bOK;
534:
535:
536: bOK = FALSE;
537: if(pbd = (PBALLDATA)LocalLock(hBall))
538: {
539: pDimension->x = pbd->nWidth;
540: pDimension->y = pbd->nHeight;
541:
542: bOK = TRUE;
543: LocalUnlock(hBall);
544: }
545: return(bOK);
546: }
547:
548:
549: BOOL ballSetDimensions(HANDLE hBall, int nWidth, int nHeight)
550: {
551: PBALLDATA pbd;
552: BOOL bOK;
553:
554:
555: bOK = FALSE;
556: if(pbd = (PBALLDATA)LocalLock(hBall))
557: {
558: pbd->nWidth = nWidth;
559: pbd->nHeight = nHeight;
560:
561: bOK = TRUE;
562: LocalUnlock(hBall);
563: }
564: return(bOK);
565: }
566:
567:
568: BOOL ballGetDirection(HANDLE hBall, LPPOINT pDirection)
569: {
570: PBALLDATA pbd;
571: BOOL bOK;
572:
573:
574: bOK = FALSE;
575: if(pbd = (PBALLDATA)LocalLock(hBall))
576: {
577: pDirection->x = pbd->xDirection;
578: pDirection->y = pbd->yDirection;
579:
580: bOK = TRUE;
581: LocalUnlock(hBall);
582: }
583: return(bOK);
584: }
585:
586:
587: BOOL ballSetDirection(HANDLE hBall, int xDirection, int yDirection)
588: {
589: PBALLDATA pbd;
590: BOOL bOK;
591:
592:
593: bOK = FALSE;
594: if(pbd = (PBALLDATA)LocalLock(hBall))
595: {
596: pbd->xDirection = xDirection;
597: pbd->yDirection = yDirection;
598:
599: bOK = TRUE;
600: LocalUnlock(hBall);
601: }
602: return(bOK);
603: }
604:
605:
606: BOOL ballGetPosition(HANDLE hBall, LPPOINT pPosition)
607: {
608: PBALLDATA pbd;
609: BOOL bOK;
610: POINT pOrg;
611:
612:
613: bOK = FALSE;
614: if(pbd = (PBALLDATA)LocalLock(hBall))
615: {
616: pOrg.x = 0;
617: pOrg.y = 0;
618: XFormPoint(&pbd->xForm,&pOrg);
619:
620: pPosition->x = pOrg.x;
621: pPosition->y = pOrg.y;
622:
623: bOK = TRUE;
624: LocalUnlock(hBall);
625: }
626: return(bOK);
627: }
628:
629:
630: BOOL ballSetPosition(HANDLE hBall, int x, int y)
631: {
632: PBALLDATA pbd;
633: BOOL bOK;
634:
635:
636: bOK = FALSE;
637: if(pbd = (PBALLDATA)LocalLock(hBall))
638: {
639: pbd->bNewPosition = TRUE;
640: pbd->xPosition = x;
641: pbd->yPosition = y;
642:
643: bOK = TRUE;
644: LocalUnlock(hBall);
645: }
646: return(bOK);
647: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.