SCM Repository
Annotation of /sml/trunk/src/eXene/examples/bounce/ball.sml
Parent Directory
|
Revision Log
Revision 2 - (view) (download)
1 : | monnier | 2 | (* ball.sml |
2 : | * | ||
3 : | * COPYRIGHT (c) 1990,1991 by John H. Reppy. See COPYRIGHT file for details. | ||
4 : | *) | ||
5 : | |||
6 : | structure Ball = | ||
7 : | struct | ||
8 : | |||
9 : | datatype ball_msg | ||
10 : | = KILL of Geometry.point | ||
11 : | | REDRAW of (int * Geometry.size) | ||
12 : | | KILL_ALL | ||
13 : | |||
14 : | val updatesPerSec = 10 | ||
15 : | |||
16 : | local | ||
17 : | structure MChan = Multicast | ||
18 : | open Geometry BounceDM | ||
19 : | |||
20 : | (* clip a point to keep a ball in the window. If we hit a wall, then | ||
21 : | * we adjust the vector. The clipped point should be computed | ||
22 : | * to lie on the vector, but for now we assume small vectors | ||
23 : | * and just truncate the coordinates. *) | ||
24 : | fun clip (ballRadius, SIZE{wid, ht}) = let | ||
25 : | val maxX = wid - ballRadius and maxY = ht - ballRadius | ||
26 : | fun clipCoord (coord : int, delta, minCoord, maxCoord) = | ||
27 : | if (coord <= minCoord) | ||
28 : | then (minCoord, ~delta) | ||
29 : | else if (coord >= maxCoord) | ||
30 : | then (maxCoord, ~delta) | ||
31 : | else (coord, delta) | ||
32 : | fun clip' (PT{x=x0, y=y0}, PT{x=dx0, y=dy0}) = let | ||
33 : | val (x1, dx1) = clipCoord(x0+dx0, dx0, ballRadius, maxX) | ||
34 : | val (y1, dy1) = clipCoord(y0+dy0, dy0, ballRadius, maxY) | ||
35 : | in | ||
36 : | (PT{x=x1, y=y1}, PT{x=dx1, y=dy1}) | ||
37 : | end | ||
38 : | in | ||
39 : | clip' | ||
40 : | end | ||
41 : | |||
42 : | fun mkIconFn win = let | ||
43 : | val ballIcons = | ||
44 : | map (EXeneBase.createTileFromImage (EXeneWin.screenOfWin win)) | ||
45 : | Heads.headDataList | ||
46 : | val n = List.length ballIcons | ||
47 : | val ch = CML.channel() | ||
48 : | fun loop i = if (i = n) | ||
49 : | then loop 0 | ||
50 : | else (CML.send(ch, List.nth(ballIcons, i)); loop(i+1)) | ||
51 : | in | ||
52 : | XDebug.xspawn("newIcon", fn () => loop 0); | ||
53 : | (fn () => CML.recv ch) | ||
54 : | end | ||
55 : | |||
56 : | val delayEvt = | ||
57 : | CML.timeOutEvt(Time.fromMicroseconds(1000000 div updatesPerSec)) | ||
58 : | in | ||
59 : | |||
60 : | fun mkBallFn (win, mchan, drawCh) = let | ||
61 : | val newIcon = mkIconFn win | ||
62 : | fun newBall (seqn, pos, vec, sz) = let | ||
63 : | val ballIcon = newIcon() | ||
64 : | val ballRadius = let | ||
65 : | val {sz=SIZE{wid, ...}, ...} = EXeneBase.geomOfTile ballIcon | ||
66 : | in | ||
67 : | wid div 2 | ||
68 : | end | ||
69 : | val offset = PT{x=ballRadius, y=ballRadius} | ||
70 : | fun drawBall (n, pos) = | ||
71 : | CML.send(drawCh, DrawBall(n, ballIcon, subPt(pos, offset))) | ||
72 : | fun moveBall (n, oldPos, newPos) = ( | ||
73 : | drawBall(n, oldPos); drawBall(n, newPos)) | ||
74 : | val clipFn = clip (ballRadius, sz) | ||
75 : | fun ball (inEvt, pos, vec, clipFn) = let | ||
76 : | fun loop (seqn, pos, vec, clipFn) = CML.select [ | ||
77 : | CML.wrap(delayEvt, fn () => let | ||
78 : | val (newPos, newVec) = clipFn(pos, vec) | ||
79 : | in | ||
80 : | if (pos <> newPos) | ||
81 : | then moveBall(seqn, pos, newPos) | ||
82 : | else (); | ||
83 : | loop(seqn, newPos, newVec, clipFn) | ||
84 : | end), | ||
85 : | CML.wrap(inEvt, | ||
86 : | fn (KILL(PT{x, y})) => let | ||
87 : | val deathZone = RECT{ | ||
88 : | x = x-ballRadius, y = y-ballRadius, | ||
89 : | wid = 2*ballRadius, ht = 2*ballRadius} | ||
90 : | in | ||
91 : | if within(pos, deathZone) | ||
92 : | then drawBall(seqn, pos) | ||
93 : | else loop(seqn, pos, vec, clipFn) | ||
94 : | end | ||
95 : | | (REDRAW(seqn', newSz)) => let | ||
96 : | val clipFn = clip (ballRadius, newSz) | ||
97 : | val (newPos, _) = clipFn(pos, PT{x=0, y=0}) | ||
98 : | in | ||
99 : | drawBall(seqn', pos); | ||
100 : | loop (seqn', newPos, vec, clipFn) | ||
101 : | end | ||
102 : | | KILL_ALL => drawBall(seqn, pos)) | ||
103 : | ] | ||
104 : | in | ||
105 : | drawBall (seqn, pos); | ||
106 : | loop (seqn, pos, vec, clipFn) | ||
107 : | end | ||
108 : | in | ||
109 : | XDebug.xspawn ( | ||
110 : | "Ball", | ||
111 : | fn () => | ||
112 : | ball(MChan.recvEvt(MChan.port mchan), pos, vec, clipFn)); | ||
113 : | () | ||
114 : | end | ||
115 : | in | ||
116 : | newBall | ||
117 : | end | ||
118 : | |||
119 : | end (* local *) | ||
120 : | end (* Ball *) |
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |