home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/wish
- ###############################
- #
- # Bubbles
- #
- set version 1.0.2a
- #
- # Copyright ulis, 2004
- #
- # Licence NOL
- #
- ###############################
-
- # ===========
- # package
- # ===========
-
- package require Tk
- catch { console hide }
-
- # ===========
- # images
- # ===========
-
- set images(8) \
- {
- 00 00 00 52 f7 00 00 00
- 00 52 bd c6 c6 c6 52 00
- 00 52 8c 94 94 94 8c 00
- 52 6b 84 8c 8c 8c 7b 63
- 52 84 b5 ce ce c6 a5 52
- 00 84 bd e7 e7 d6 a5 00
- 00 52 94 c6 ce b5 52 00
- 00 00 00 52 84 00 00 00
- }
- set images(16) \
- {
- 00 00 00 00 00 00 c0 c0 c0 c0 00 00 00 00 00 00
- 00 00 00 c0 c0 ef ff f7 f7 f7 ff a5 c0 00 00 00
- 00 00 a5 a2 e7 de de de de de de d6 ce a0 00 00
- 00 a0 a0 bd bd bd c6 c6 c6 c6 c6 bd bd a3 9a 00
- 00 92 9a a5 a5 a5 a5 ad ad a5 a5 a5 a5 ab 8a 00
- 00 92 90 94 9c 94 94 94 94 94 94 8c 8c 83 82 00
- 80 a2 8a 8b 84 84 84 8c 8c 8c 84 84 7b 63 8a 80
- 80 aa 6b 7b 84 8c 8c 8c 8c 8c 8c 84 7b 73 73 80
- 80 c3 73 8c 9c a5 ad ad ad ad ad a5 94 84 7b 80
- 80 c3 84 9c b5 c6 ce ce ce ce c6 bd a5 8c 73 80
- 00 aa 84 a5 c6 d6 de e7 e7 e7 d6 c6 ad 8c 73 00
- 00 94 84 a5 bd d6 e7 e7 e7 e7 d6 bd a5 84 8a 00
- 00 a0 8b 94 b5 ce de e7 e7 de ce b5 94 73 90 00
- 00 00 a0 73 94 b5 c6 ce ce c6 b5 94 73 ad 00 00
- 00 00 00 a0 9c 84 a5 ad ad a5 8c 73 90 00 00 00
- 00 00 00 00 00 00 80 80 80 80 00 00 00 00 00 00
- }
- set images(24) \
- {
- 00 00 00 00 00 00 00 00 00 7c 46 2e 2d 45 7b 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 73 56 71 8e 9a 9a 8e 70 55 73 00 00 00 00 00 00 00
- 00 00 00 00 00 90 43 8c db fc ff ff ff ff fb dc 8c 43 8f 00 00 00 00 00
- 00 00 00 00 6c 45 cc fa ee e8 e6 e6 e6 e7 e7 ee fa cd 45 6c 00 00 00 00
- 00 00 00 6f 3a c4 e0 d2 d5 d7 d8 d8 d8 d8 d7 d5 d2 e1 c3 39 70 00 00 00
- 00 00 96 2e 86 cc be c3 c4 c5 c5 c5 c6 c5 c5 c5 c4 bf cc 86 2e 96 00 00
- 00 00 41 47 95 b1 ae b1 b2 b3 b3 b4 b4 b3 b3 b2 b1 ae b1 94 47 41 00 00
- 00 81 3c 4f 88 9f 9d a0 a1 a2 a3 a4 a4 a3 a2 a1 a0 9d 9f 88 50 3d 82 00
- 00 55 4a 52 74 8f 8d 91 93 94 94 94 94 94 94 92 91 8e 8e 75 52 4b 4f 00
- 8e 4c 52 59 64 7e 83 86 88 8a 8a 8b 8b 8b 8a 89 87 84 7f 65 59 55 43 c1
- 63 4e 58 60 68 74 80 84 86 87 88 88 88 88 88 86 84 80 74 68 61 5a 49 8c
- 50 52 5e 68 73 7b 83 88 8c 8d 8e 8d 8d 8e 8e 8c 87 82 7a 72 68 5e 51 64
- 53 57 64 71 7f 8a 92 99 9e a0 a0 a0 a0 a0 a0 9d 98 91 87 7c 70 64 55 66
- 68 59 6a 7a 8a 98 a3 ad b2 b4 b5 b5 b5 b5 b4 b1 ab a0 93 86 77 69 53 8e
- 93 5e 6f 82 95 a7 b6 c0 c7 ca cb cc cc cb c9 c5 bd b0 a1 8f 7c 6c 53 c2
- 00 69 6e 87 9c b1 c1 ce d5 da dc dd dd dc d9 d3 c9 ba a7 94 7f 69 61 00
- 00 91 64 88 9d b2 c5 d4 dd e3 e6 e7 e7 e6 e2 d9 cd bb a7 91 7e 5d 8d 00
- 00 00 64 80 97 ad c1 d1 dc e3 e7 e8 e8 e5 e0 d5 c6 b4 9e 89 75 5d 00 00
- 00 00 a4 69 8f a4 b9 cb d8 e0 e5 e7 e6 e2 da cd bd aa 93 81 5e a1 00 00
- 00 00 00 8e 73 99 ad c0 ce d8 de e0 df da d1 c3 b1 9c 8a 66 88 00 00 00
- 00 00 00 00 90 76 99 ae bc c8 ce d1 d0 ca c0 b2 9f 8a 69 89 00 00 00 00
- 00 00 00 00 00 ab 7c 8b a3 b3 ba bd bc b6 ac 9a 80 72 a6 00 00 00 00 00
- 00 00 00 00 00 00 00 a0 89 8b 96 9b 9a 92 85 83 9d 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 c7 9d 86 85 9c c6 00 00 00 00 00 00 00 00 00
- }
- set images(32) \
- {
- 00 00 00 00 00 00 00 00 00 00 00 00 b0 79 52 41 41 52 79 b0 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 d8 8e 58 49 55 61 66 66 61 54 48 57 8e d8 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 84 3e 51 91 c9 e6 f1 f5 f5 f1 e6 c9 91 51 3e 83 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 c0 4c 45 a6 ed fe fc f7 f5 f4 f4 f5 f8 fc fe ed a6 45 4c c0 00 00 00 00 00 00
- 00 00 00 00 00 a4 3c 5c d5 f6 e9 e5 e7 e8 e8 e9 e9 e8 e8 e6 e5 e9 f6 d5 5c 3c a4 00 00 00 00 00
- 00 00 00 00 a4 3a 5c d0 e4 d7 db dc dd dd de de de dd de dd dd db d7 e4 d0 5c 3a a4 00 00 00 00
- 00 00 00 c0 45 4b a9 d8 ca d0 d0 d1 d1 d2 d2 d2 d2 d2 d2 d1 d1 d0 d0 cb d8 a9 4b 45 c1 00 00 00
- 00 00 00 53 48 6a c2 bf c2 c3 c4 c5 c5 c6 c7 c6 c6 c6 c6 c5 c5 c4 c3 c2 c0 c2 6b 48 53 00 00 00
- 00 00 87 45 50 80 b8 b2 b5 b6 b8 b9 ba ba ba bb bb bb ba ba b8 b8 b7 b5 b2 b8 7f 52 45 87 00 00
- 00 d7 4c 54 53 80 ab a6 aa ac ad af af af b0 b0 b0 b0 af af ae ad ac aa a7 ab 81 54 54 4d d8 00
- 00 92 44 59 58 78 9d 9c 9e a1 a3 a4 a4 a5 a6 a7 a6 a6 a5 a5 a4 a2 a1 9f 9c 9d 78 59 5a 44 93 00
- 00 68 4f 5c 5f 6c 90 94 96 99 9b 9c 9d 9d 9e 9e 9e 9e 9e 9e 9c 9b 99 97 94 91 6e 60 5d 50 64 00
- b0 56 57 5f 65 6a 7f 8e 8f 92 94 96 97 97 98 98 98 98 98 97 96 95 92 8f 8f 80 6b 66 60 59 4d b0
- 83 55 5b 63 6a 70 77 87 8c 90 92 94 95 96 96 96 96 95 96 96 94 93 90 8d 87 78 71 6a 64 5f 4b ba
- 65 57 5f 68 70 77 7d 83 8d 91 93 95 96 97 97 96 97 97 97 97 95 93 91 8c 83 7e 77 70 68 61 52 88
- 58 5a 64 6d 75 7e 86 8d 93 97 9a 9d 9e 9e 9f 9e 9e 9e 9e 9e 9d 9a 97 93 8c 85 7e 76 6d 64 58 6f
- 5a 5c 67 71 7c 86 90 98 9f a4 a7 a9 ab ab ab ab ab ac ab ab a9 a6 a2 9d 96 8e 85 7b 71 68 5a 70
- 6a 5e 6b 78 83 90 9a a4 ac b2 b6 b8 b9 ba ba bb ba bb ba b9 b8 b5 b0 a9 a1 97 8c 81 76 6b 59 89
- 87 61 6e 7c 8a 98 a4 b0 ba c1 c5 c7 c9 ca ca ca ca ca c9 c8 c6 c2 bd b6 ab 9f 93 86 79 6d 56 b9
- b2 66 6f 80 90 a0 ae bb c7 ce d2 d6 d7 d8 d8 d8 d9 d8 d7 d6 d3 d0 c9 c0 b5 a7 99 89 7b 6e 5b b0
- 00 77 6c 82 93 a4 b4 c2 d0 d8 dd e0 e2 e3 e4 e5 e5 e4 e2 e1 de d9 d2 c8 ba aa 9b 8a 7c 67 72 00
- 00 9b 65 83 94 a6 b7 c7 d5 de e4 e8 ea ec ec ec ec ec ea e8 e4 df d7 cb bc ab 9a 89 7b 60 9a 00
- 00 d8 6a 7e 91 a3 b4 c5 d4 e0 e6 eb ee f0 f0 f0 f0 f0 ee eb e7 e0 d6 c8 b8 a7 96 84 75 63 d8 00
- 00 00 97 6d 8c 9d af c0 cf dc e6 ec f0 f1 f2 f3 f3 f1 ee eb e5 dd d1 c1 b1 9f 8e 80 65 93 00 00
- 00 00 00 72 80 95 a7 b9 c9 d8 e3 eb f0 f1 f3 f3 f2 f1 ed e9 e2 d7 c9 b9 a8 96 87 74 6b 00 00 00
- 00 00 00 c8 72 8b 9d b0 c1 cf dc e5 ec ef f2 f2 f1 ef eb e4 da ce bf af 9e 8c 7d 67 c6 00 00 00
- 00 00 00 00 b0 71 8f a2 b3 c2 d0 da e2 e8 ea eb eb e7 e2 da cf c2 b2 a1 90 81 65 ac 00 00 00 00
- 00 00 00 00 00 b0 78 8e a4 b3 c1 cc d5 db df e0 df db d5 cc c1 b3 a3 94 7f 6d ad 00 00 00 00 00
- 00 00 00 00 00 00 c8 82 88 a0 b0 bb c4 cb d0 d1 d0 cd c5 bc b2 a3 93 7b 77 c5 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 a1 85 8e 9f ae b5 b9 bb ba b7 b1 a7 97 85 7d 9c 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 d8 ae 93 8c 92 9b 9d 9c 98 8f 88 8f aa d8 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 dc bb 98 8d 8c 97 bb dc 00 00 00 00 00 00 00 00 00 00 00 00
- }
- set images(40) \
- {
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ce 9e 7a 5c 52 52 5d 7a 9d ce 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 de a6 6e 4d 42 42 44 44 44 44 41 42 4d 6e a5 de 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 d9 89 49 34 4e 79 a0 ba c6 cc cc c6 b9 a0 79 4d 35 49 89 d9 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 9c 49 37 69 b4 e7 fd fe fe fe fe fe fe fe fe fd e7 b4 69 36 48 9c 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 6e 37 53 b0 f1 fd f5 f0 ee ee ef ef ef ef ef ee f0 f5 fd f1 af 53 37 6d 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 cb 57 3a 67 d5 f5 e8 e5 e7 e9 e8 e9 e9 ea e9 ea e9 e9 e8 e7 e5 e8 f6 d5 68 3b 57 cb 00 00 00 00 00 00
- 00 00 00 00 00 cd 4e 41 64 d5 e7 da df df df e0 e0 e0 e0 e1 e1 e0 e1 e0 df e0 df df da e7 d5 65 40 4e cd 00 00 00 00 00
- 00 00 00 00 00 56 45 54 be dc d0 d5 d6 d6 d6 d7 d7 d7 d7 d8 d8 d7 d7 d7 d6 d7 d5 d5 d5 d0 dc bd 54 45 56 00 00 00 00 00
- 00 00 00 00 6d 45 4b 88 d3 c6 ca cb cb cc cd cd cd cd cd cd cd ce cd ce cc ce cc cc cb ca c6 d3 87 4b 45 6c 00 00 00 00
- 00 00 00 97 3f 53 53 ad c1 bd c0 c1 c1 c3 c3 c4 c4 c5 c4 c5 c5 c5 c4 c4 c3 c4 c2 c1 c1 c0 bd c1 ad 54 53 3f 97 00 00 00
- 00 00 d8 4d 50 50 65 b1 b3 b4 b5 b7 b8 b9 ba ba bb bb bb bc bc bb bb bb ba b9 b9 b9 b7 b6 b5 b3 b2 66 51 50 4d d8 00 00
- 00 00 89 43 56 53 6b ab aa ab ad ae af b0 b1 b2 b2 b2 b3 b3 b3 b3 b3 b2 b2 b1 b1 af af ad ac aa ab 6b 53 57 45 89 00 00
- 00 d9 52 50 57 57 6a a0 a0 a2 a3 a5 a7 a8 a9 a9 aa aa ab ab aa aa aa aa a9 a9 a8 a7 a6 a4 a2 a0 9f 6a 57 57 50 52 db 00
- 00 a0 45 57 59 5c 66 92 99 9a 9b 9e 9f a1 a1 a1 a2 a3 a3 a3 a3 a3 a3 a3 a2 a1 a0 9f 9e 9d 9a 98 93 66 5d 5a 57 45 a3 00
- 00 75 4a 59 5c 62 64 82 93 92 96 97 99 9b 9b 9c 9c 9c 9d 9d 9d 9e 9d 9e 9d 9b 9a 99 98 96 92 94 83 65 62 5d 5b 4d 73 00
- ca 5c 52 5c 5f 64 68 74 8b 8e 90 91 93 95 96 97 97 98 98 99 99 98 98 97 97 97 96 93 92 90 8d 8c 74 69 65 60 5c 54 53 00
- 9a 55 56 5e 63 68 6e 71 7f 8b 8c 8f 91 93 94 95 96 96 96 96 97 96 96 96 95 94 94 92 90 8d 8b 7f 72 6e 69 63 5e 5a 49 d4
- 7c 54 5a 60 66 6c 72 77 7c 85 8d 8f 92 94 94 95 96 96 96 96 96 96 96 95 96 94 93 92 8f 8c 85 7c 78 73 6e 68 62 5d 4c ac
- 62 57 5d 64 6b 71 77 7d 82 87 8c 91 93 95 97 98 97 98 99 98 98 98 99 98 98 97 96 93 91 8d 86 82 7e 77 72 6c 64 5e 53 82
- 59 58 5f 68 6f 76 7d 83 89 8f 93 97 9a 9c 9e 9f 9f 9f 9f 9f 9e 9f a0 9e 9f 9e 9c 99 97 93 8e 88 83 7c 76 6f 68 61 56 73
- 5a 5a 62 6b 73 7b 83 8b 92 98 9d a1 a5 a7 a9 aa aa aa aa ab aa aa ab a9 aa a8 a6 a3 a0 9b 96 90 89 82 7b 73 6b 63 58 73
- 65 5c 65 6e 78 81 8a 93 9a a1 a8 ac b0 b2 b4 b5 b6 b5 b6 b6 b6 b6 b6 b5 b4 b3 b2 ae ab a5 9e 97 8f 87 7f 76 6d 65 58 82
- 80 5e 67 72 7c 87 91 9a a3 ab b3 b8 bd bf c0 c1 c2 c2 c3 c2 c2 c3 c2 c1 c1 bf bd ba b5 b0 a8 9f 96 8d 83 7a 70 68 54 ac
- 9d 61 68 75 80 8b 97 a1 ac b5 be c3 c7 ca cc cd ce ce ce ce ce cf ce cd cc ca c8 c4 bf b8 b0 a6 9c 92 86 7c 71 68 55 d2
- c8 6a 68 77 83 91 9c a8 b4 be c7 cd d1 d5 d7 d8 d9 d9 da da da d9 d9 d8 d7 d5 d2 ce c8 c0 b8 ad a1 95 89 7d 73 66 60 00
- 00 81 63 79 85 92 9f ad b9 c4 cf d5 d9 dc de e0 e2 e3 e3 e3 e3 e3 e2 e1 df dd da d5 cf c7 bb af a3 97 8a 7e 74 61 7c 00
- 00 a7 60 78 85 93 a2 af bc c8 d2 db e0 e4 e6 e8 e9 ea ea eb ea ea e9 e8 e6 e3 df db d3 cb be b1 a4 97 8a 7c 73 5b a7 00
- 00 d9 6b 75 83 92 a1 b0 bd c9 d4 de e3 e7 eb ed ee ee ef ee ee ee ed ec e9 e7 e2 dc d4 ca bd b0 a2 95 87 7a 6d 66 da 00
- 00 00 96 69 81 8e 9d ab ba c6 d2 dc e4 e9 ed ef f0 f1 f1 f0 f1 f0 f0 ee ea e7 e3 db d1 c5 b9 ab 9d 8f 81 78 61 93 00 00
- 00 00 d8 6c 7a 89 98 a7 b5 c3 cf d9 e3 e9 ec ef f0 f2 f3 f3 f2 f2 f0 ed ea e6 e0 d7 cc c0 b3 a5 97 8a 7d 70 66 d7 00 00
- 00 00 00 a1 69 85 91 a0 af bd c9 d5 df e6 ec ef f0 f3 f3 f3 f2 f1 f0 ec e9 e3 db d2 c6 b9 ac 9e 91 83 79 60 9d 00 00 00
- 00 00 00 00 87 76 8c 99 a8 b7 c3 cf da e3 e8 ee f0 f1 f3 f3 f2 f1 ef eb e7 e0 d6 cb bf b2 a4 96 89 7e 6a 81 00 00 00 00
- 00 00 00 00 00 7a 7c 90 9d ac bb c7 d2 db e2 e8 ec ef f0 f0 f0 ee eb e6 df d7 cd c2 b4 a9 9a 8c 82 6f 71 00 00 00 00 00
- 00 00 00 00 00 cf 74 7f 93 9f af bb c7 d0 d8 df e3 e7 e9 e9 e8 e6 e3 de d6 cd c2 b7 aa 9d 8e 84 73 6b cd 00 00 00 00 00
- 00 00 00 00 00 00 cd 7e 7f 95 a0 ad ba c5 cd d4 d9 dd de e0 df dc d8 d3 cb c3 b8 ab 9d 90 86 72 74 cb 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 8d 7c 93 a0 ab b6 c0 c7 cd d1 d3 d4 d3 d0 cc c6 bf b6 aa 9d 94 85 70 85 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 aa 80 88 99 a6 ae b6 bc c0 c3 c4 c3 c1 bd b6 af a6 9c 8f 7e 76 a6 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 d7 a0 86 89 95 a1 a8 ac ae af af ac a9 a3 9b 8f 81 7f 9c d6 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 db b7 98 89 8a 91 97 97 97 95 8e 87 86 95 b5 db 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 cd ad 92 8f 8e 91 ac cd 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- }
- set images(bg) \
- {
- #8ede8e
- #8bbb8b
- #81b181
- #8ccc8c
- #8bdb8b
- #8fcf8f
- #87c787
- #8bcb8b
- #8ddd8d
- #8cbc8c
- }
-
- # ===========
- # procs
- # ===========
-
- # -----------
- # create the bubble images
- # -----------
- proc CreateImages {} \
- {
- #puts "CreateImages"
- for {set d $::Size} {$d > 0} {incr d -8} \
- {
- # create images
- array unset datas
- for {set n 0} {$n < 8} {incr n} \
- { image create photo img$d-$n }
- # compute data
- set data $::images($d)
- set ndx -1
- for {set i 0} {$i < $d} {incr i} \
- {
- array unset rows
- set first 0
- set last 0
- for {set j 0} {$j < $d} {incr j} \
- {
- set c [lindex $data [incr ndx]]
- set cc [scan $c %x]
- set c2 [format %2.2x [expr {round($cc * 0.5)}]]
- set c3 [expr {round($cc * 1.25)}]
- if {$c3 > 255} { set c3 255 }
- set c3 [format %2.2x $c3]
- lappend rows(0) #${c}${c}${c} ; # white
- lappend rows(1) #${c}0000 ; # red
- lappend rows(2) #00${c}00 ; # green
- lappend rows(3) #${c}${c}00 ; # yellow
- lappend rows(4) #00${c}${c} ; # indigo
- lappend rows(5) #${c}00${c} ; # violet
- lappend rows(6) #${c}${c2}00 ; # orange
- lappend rows(7) #${c2}${c2}${c2}; # gray
- }
- for {set n 0} {$n < 8} {incr n} \
- { lappend datas($n) $rows($n) }
- }
- # put images data
- for {set n 0} {$n < 8} {incr n} \
- { img$d-$n put $datas($n) }
- # set transparency
- catch \
- {
- set ndx -1
- for {set i 0} {$i < $d} {incr i} \
- {
- for {set j 0} {$j < $d} {incr j} \
- {
- set c [lindex $data [incr ndx]]
- if {$c == 0} \
- {
- for {set n 0} {$n < 8} {incr n} \
- { img$d-$n transparency set $i $j 1 }
- }
- }
- }
- }
- }
- # create background
- image create photo imgbg -width 1000 -height 1000
- imgbg put $::images(bg) -to 0 0 1000 1000
- }
- # -----------
- # init the game dialog
- # -----------
- proc CreateDialog {} \
- {
- #puts "CreateDialog"
- # create background
- # create digits areas
- catch { destroy .f1}
- frame .f1
- canvas .f1.bg -width 1000 -height 1000 -bd 0 -highlightth 0
- .f1.bg create image 0 0 -anchor nw -image imgbg
- place .f1.bg -in .f1 -relx 0 -rely 0
- CreateDigitsCanvas $::StepDisplay
- CreateDigitsCanvas $::ScoreDisplay
- CreateDigitsCanvas $::GrandScoreDisplay
- CreateDigitsCanvas $::DelayDisplay
- button $::OptionsButton -width 10 -text Options -command Options -relief groove -padx 5 -pady 5
- grid $::StepDisplay \
- $::ScoreDisplay \
- $::GrandScoreDisplay \
- $::OptionsButton \
- -padx 10 -pady 5
- grid .f1 -row 0 -sticky ew
- # create game area
- CreateBubblesCanvas
- # center
- CenterDialog .
- }
- proc CreateDigitsCanvas {canvas} \
- {
- # create canvas
- set size $::CanvasSize($canvas)
- canvas $canvas -bg gray85 -relief sunken \
- -width [expr {$size * 20 + 10}] -height 32 \
- -bd 1 -highlightth 0 -selectborderwi 0
- # create digits
- set x 10
- set y 5
- for {set i 0} {$i < $size} {incr i} \
- {
- CreateDigit $canvas $i $x $y
- incr x 20
- }
- # init display
- SetNumber $canvas 0
- }
- proc CreateBubblesCanvas {} \
- {
- # create frame
- catch { destroy .f2}
- frame .f2
- canvas .f2.bg -width 1000 -height 1000 -bd 0 -highlightth 0
- .f2.bg create image 0 0 -anchor nw -image imgbg
- place .f2.bg -in .f2 -relx 0 -rely 0
- # create count down canvas
- canvas $::TimeDisplay -relief sunken \
- -width 21 -height $::Height \
- -bd 1 -highlightth 0 -selectborderwi 0
- $::TimeDisplay create rectangle 1 1 20 $::Height \
- -outline "" -fill green -tags used
- $::TimeDisplay create rectangle 1 1 20 0 \
- -outline "" -fill red -tags left
- # create game area
- canvas $::BubblesDisplay -bg gray75 -relief sunken \
- -width [expr {$::Width + 1}] -height $::Height \
- -bd 1 -highlightth 0 -selectborderwi 0
- $::BubblesDisplay config -scrollregion [list 0 0 $::Width $::Height]
- $::BubblesDisplay xview scroll 1 unit
- $::BubblesDisplay yview scroll 1 unit
- # create decoration
- for {set i 0} {$i < 64} {incr i} \
- {
- set x [expr {round(rand() * $::Width)}]
- set y [expr {round(rand() * $::Height)}]
- set d [expr {round(rand() * $::R)}]
- $::BubblesDisplay create oval \
- [expr {$x - $d}] \
- [expr {$y - $d}] \
- [expr {$x + $d}] \
- [expr {$y + $d}] -outline gray65 -width 2
- }
- # Click events
- bind $::BubblesDisplay <Button-1> { Fire %x %y }
- bind $::BubblesDisplay <Button-3> { Dump }
- # display all
- grid $::TimeDisplay $::BubblesDisplay -padx 5 -pady 10
- grid .f2 -row 1 -sticky ew
- update
- }
- # -----------
- # center dialog
- # -----------
- proc CenterDialog {w} \
- {
- # hide dialog
- wm geometry $w -2000-2000
- # compute sizes
- update
- set x [expr {([winfo screenwidth $w] - [winfo width $w]) / 2}]
- set y [expr {([winfo screenheight $w] - [winfo height $w]) / 2}]
- # place dialog
- wm geometry $w +$x+$y
- }
- # -----------
- # options dialog
- # -----------
- proc Options {} \
- {
- # stop count down
- set ::Halted 1
- # inhibite call to options
- $::OptionsButton config -state disabled
- # save parameters value
- set Level $::Level
- set Size $::Size
- set Speed $::Speed
- # create dialog
- if {[winfo exists .o]} { destroy .o }
- toplevel .o
- wm title .o "Bubbles, Options"
- # manage events
- bind .o <<Close>> \
- {
- catch \
- {
- set fn /root/.Bubbles1.Parameters
- set fp [open $fn w]
- puts $fp "set ::Level $::Level"
- puts $fp "set ::Size $::Size"
- puts $fp "set ::Speed $::Speed"
- close $fp
- }
- $::OptionsButton config -state normal
- destroy .o
- set ::Halted 0
- if {$::Status == "newgame"} { NewGame }
- }
- bind . <<Exit>> { exit }
- wm protocol .o WM_DELETE_WINDOW { event generate .o <<Close>> }
- bind .o <Escape> \
- {
- set ::Level $Level
- set ::Size $Size
- set ::Speed $Speed
- event generate .o <<Close>>
- }
- # create buttons area
- frame .o.f
- canvas .o.f.bg -width 1000 -height 1000 -bd 0 -highlightth 0
- .o.f.bg create image 0 0 -anchor nw -image imgbg
- place .o.f.bg -in .o.f -relx 0 -rely 0
- # create buttons
- foreach {w t c} \
- {
- 1 "Continue" { event generate .o <<Close>> }
- 2 "New Game" { set ::Status newgame; event generate .o <<Close>> }
- 3 "Quit Game" { event generate .o <<Close>>; event generate . <<Exit>> }
- 4 "Hall of Fame" { DisplayFame }
- } \
- { button .o.f.b$w -width 20 -text $t -command $c -relief groove }
- # create level area
- frame .o.f0 -relief groove -bd 2 -padx 25 -pady 5
- label .o.f0.lt -fg gray20 -font {-weight bold} -text "bubbles level"
- frame .o.f0.f
- # create buttons
- foreach w {0 1 2} v {novice expert master} t {novice expert master} \
- { radiobutton .o.f0.f.r$w -variable ::Level -value $v -text $t \
- -command { .o.f.b1 config -state disabled }
- }
- # create size area
- frame .o.f1 -relief groove -bd 2 -padx 25 -pady 5
- label .o.f1.lt -fg gray20 -font {-weight bold} -text "bubbles size"
- frame .o.f1.f
- # create buttons
- foreach w {0 1} v {40 24} t {big small} \
- { radiobutton .o.f1.f.r$w -variable ::Size -value $v -text $t \
- -command { .o.f.b1 config -state disabled }
- }
- # create speed area
- frame .o.f2 -relief groove -bd 2 -padx 25 -pady 5
- label .o.f2.lt -fg gray20 -font {-weight bold} -text "bubbles speed"
- frame .o.f2.f
- # create buttons
- foreach w {0 1 2} v {1 3 5} t {slow medium speed} \
- { radiobutton .o.f2.f.r$w -variable ::Speed -value $v -text $t }
- # display all
- grid .o.f -sticky ew
- foreach w {1 2 3 4} \
- { grid .o.f.b$w -padx 40 -pady 5 }
- foreach w {0 1 2} \
- { grid .o.f$w -padx 5 -pady 5 -sticky nsew }
- foreach w {0 1 2} \
- {
- pack .o.f$w.lt -anchor center
- pack .o.f$w.f
- }
- foreach {w1 s} {0 {r0 r1 r2} 1 {r0 r1} 2 {r0 r1 r2}} \
- { foreach w2 $s { pack .o.f$w1.f.$w2 -anchor w } }
- CenterDialog .o
- raise .o
- focus -force .o
- # disable Continue if New Game is mandatory
- if {$::Status == "newgame"} { .o.f.b1 config -state disabled }
- }
- # -----------
- # display hall of fame
- # -----------
- proc DisplayFame {{scores {}} {entry 0}} \
- {
- #puts "DisplayFame $scores"
- # get scores if needed
- if {$scores == {}} { set scores [ReadFame] }
- # create dialog
- if {[winfo exists .h]} { destroy .h }
- toplevel .h
- wm title .h "Bubbles, Hall of Fame"
- canvas .h.bg -width 1000 -height 1000 -bd 0 -highlightth 0
- .h.bg create image 0 0 -anchor nw -image imgbg
- place .h.bg -in .h -relx 0 -rely 0
- focus -force .h
- # manage events
- bind .h <<Close>> { destroy .h }
- bind .h <Escape> { event generate .h <<Close>> }
- # create frame title
- frame .h.ft
- canvas .h.ft.bg -width 1000 -height 1000 -bd 0 -highlightth 0
- .h.ft.bg create image 0 0 -anchor nw -image imgbg
- place .h.ft.bg -in .h.ft -relx 0 -rely 0
- # create user area
- label .h.ft.u -bd 1 -relief sunken -width 10 -font {-weight bold} \
- -bg gray90 -fg DarkOrange -text $::User
- # create level area
- label .h.ft.ll -bd 1 -relief sunken -width 6 -font {-weight bold} \
- -bg gray90 -fg DarkGreen -text $::Level
- # create score area
- label .h.ft.ls -bd 1 -relief sunken -width 8 -font {-weight bold} \
- -bg gray90 -fg red -text [format %7.7i $::GrandScore]
- grid .h.ft.u .h.ft.ll .h.ft.ls -padx 20 -pady 25 -sticky nw
- # create scores frame
- frame .h.fs -bd 0
- canvas .h.fs.bg -width 500 -height 1000 -bd 0 -highlightth 0
- .h.fs.bg create image 0 0 -anchor nw -image imgbg
- place .h.fs.bg -in .h.fs -relx 0 -rely 0
- set ::numScore -1
- set i 1
- foreach score $scores \
- {
- if {$score == ""} { break }
- # get info
- foreach {number level user} [split $score] break
- # create num area
- label .h.fs.ln$i -bd 1 -relief sunken -width 2 -font {-weight bold} \
- -bg gray90 -fg gray20 -text $i
- # create user area
- label .h.fs.u$i -bd 1 -relief sunken -width 10 -font {-weight bold} \
- -bg gray90 -fg DarkOrange -text $user
- if {$user == "" && $entry == -1} \
- {
- # create user entry
- set entry $i
- entry .h.fs.u$i.e -bd 0 -relief flat -width 10 -font {-weight bold} \
- -bg gray90 -fg DarkOrchid -textvariable ::User \
- -insertbackground DarkOrchid -insertwidth 4 -selectforeground DarkOrchid
- place .h.fs.u$i.e -in .h.fs.u$i -anchor center -relx 0.5 -rely 0.5
- focus -force .h.fs.u$i.e
- .h.fs.u$i.e selection range 0 end
- .h.fs.u$i.e icursor end
- }
- # create level area
- label .h.fs.ll$i -bd 1 -relief sunken -width 6 -font {-weight bold} \
- -bg gray90 -fg DarkGreen -text $level
- # create score area
- label .h.fs.ls$i -bd 1 -relief sunken -width 8 -font {-weight bold} \
- -bg gray90 -fg red -text [format %7.7i $number]
- # display row
- grid .h.fs.ln$i .h.fs.u$i .h.fs.ll$i .h.fs.ls$i -padx 10 -pady 5
- incr i
- }
- # place/display frames
- pack .h.ft -padx 20 -pady 20 -fill x
- pack .h.fs -padx 20 -pady 20 -fill x
- # create register button if needed
- if {$entry > 0} \
- {
- # add a Register button
- set ::numScore [incr entry -1]
- bind .h <<Register>> \
- {
- set score "$::GrandScore $::Level $::User"
- set ::Scores [lreplace $::Scores $::numScore $::numScore $score]
- WriteFame $::Scores
- DisplayFame $::Scores
- }
- bind .h <Return> { event generate .h <<Register>> }
- button .h.b -width 20 -text Register -relief groove \
- -command { event generate .h <<Register>> }
- pack .h.b -pady 10
- }
- # place dialog
- CenterDialog .h
- raise .h
- }
- # -----------
- # update hall of fame
- # -----------
- proc UpdateFame {} \
- {
- #puts "UpdateFame"
- # add new score
- set ::Scores [ReadFame]
- lappend ::Scores [list $::GrandScore $::Level]
- set ::Scores [lrange [lsort -dic -dec $::Scores] 0 9]
- # display new Hall of Fame
- DisplayFame $::Scores -1
- }
- # -----------
- # read the Hall of fame
- # -----------
- proc ReadFame {} \
- {
- #puts "ReadFame"
- # read file
- set scores ""
- catch \
- {
- set fn /root/.Bubbles1.HallOfFame
- set fp [open $fn]
- set scores [split [read $fp] \n]
- close $fp
- }
- # fill score if empty
- if {$scores == ""} \
- { for {set i 0} {$i < 10} {incr i} { lappend scores "0 expert anonymous" } }
- return $scores
- }
- # -----------
- # write the Hall of fame
- # -----------
- proc WriteFame {scores} \
- {
- #puts "WriteFame $scores"
- # write file
- catch \
- {
- set fn /root/.Bubbles1.HallOfFame
- set fp [open $fn w]
- puts -nonewline $fp [join $scores \n]
- close $fp
- }
- }
- # -----------
- # create the bubbles for the step
- # -----------
- proc CreateBubbles {} \
- {
- #puts "CreateBubbles"
- # create the slots
- CreateBubblesCanvas
- # create the first bubbles
- set y $::R
- set nrows [expr {int($::N * 0.9)}]
- set ncols $::N
- for {set i 0} {$i < $nrows} {incr i} \
- {
- if {$i % 2 == 0} { set x $::R; set j 0 } \
- else { set x $::Size; set j 1 }
- for {} {$j < $ncols} {incr j} \
- {
- set ndx [CreateBubble $x $y]
- UpdateBubble $ndx $x $y
- incr x $::Size
- }
- incr y $::DY
- }
- }
- # -----------
- # froze the bubbles
- # -----------
- proc FrozeBubbles {{delay ""}} \
- {
- if {$delay == ""} \
- {
- set delay 25
- after 1000 {catch { after cancel $::Froze }}
- }
- set bg [$::BubblesDisplay cget -bg]
- set bg [expr {$bg == "gray75" ? "gray65" : "gray75"}]
- $::BubblesDisplay config -bg $bg
- foreach ndx [array names ::Bubbles] \
- {
- foreach {- x y} $::Bubbles($ndx) break
- set dx [expr {(rand() > 0.5 ? 1 : -1) * int(rand() * 2)}]
- set dy [expr {(rand() > 0.5 ? 1 : -1) * int(rand() * 2)}]
- $::BubblesDisplay coords bubble$ndx [expr {$x + $dx}] [expr {$y + $dy}]
- }
- set ::Froze [after $delay FrozeBubbles $delay]
- }
- # -----------
- # create one digit
- # -----------
- proc CreateDigit {canvas ndx x y} \
- {
- #puts "CreateDigit $canvas $ndx $x $y"
- # create digit segments
- set y0 0
- set size 12
- set xs [expr {$x + $size}]
- set ys [expr {$y + $size}]
- foreach \
- { x1 y1 x2 y2 tag dy} \
- [list \
- $x $y $xs $y 0 0 \
- $x $y $x $ys 1 0 \
- $xs $y $xs $ys 2 $size \
- $x $y $xs $y 3 0 \
- $x $y $x $ys 4 0 \
- $xs $y $xs $ys 5 $size \
- $x $y $xs $y 6 0 \
- ] \
- {
- $canvas create line $x1 [expr {$y0 + $y1}] $x2 [expr {$y0 + $y2}] \
- -tags dgt$ndx-$tag -fill gray65 -width 3
- incr y0 $dy
- }
- }
- array set ::Segments \
- {
- "" {}
- 0 {0 1 2 4 5 6}
- 1 {2 5}
- 2 {0 2 3 4 6}
- 3 {0 2 3 5 6}
- 4 {1 2 3 5}
- 5 {0 1 3 5 6}
- 6 {0 1 3 4 5 6}
- 7 {0 2 5}
- 8 {0 1 2 3 4 5 6}
- 9 {0 1 2 3 5 6}
- }
- # -----------
- # display a digit
- # -----------
- proc SetDigit {canvas ndx digit {color red}} \
- {
- #puts "SetDigit $canvas $ndx $digit $color"
- # colorize each segment
- set segments $::Segments($digit)
- for {set i 0} {$i < 7} {incr i} \
- {
- if {[lsearch -exact $segments $i] == -1} \
- { set c gray65 } else { set c $color }
- $canvas itemconfig dgt$ndx-$i -fill $c
- }
- }
- # -----------
- # blink a score
- # -----------
- proc BlinkNumber {canvas value {color ""}} \
- {
- #puts "BlinkNumber $canvas $value $color"
- # alternate colors
- if {$color == ""} \
- {
- StopBlink
- set color red
- } \
- elseif {![info exists ::Blink]} { return }
- set color [expr {$color == "red" ? "gray65" : "red"}]
- # display the number
- SetNumber $canvas $value $color
- # repeat
- set ::Blink [after 500 [list BlinkNumber $canvas $value $color]]
- }
- # -----------
- # stop blinking a score
- # -----------
- proc StopBlink {} \
- {
- #puts "StopBlink"
- # stop
- if {[info exists ::Blink]} \
- {
- catch {after cancel $::Blink}
- unset ::Blink
- }
- }
- # -----------
- # display a score
- # -----------
- proc SetNumber {canvas value {color red}} \
- {
- #puts "SetNumber $canvas $value $color"
- # compute display size
- set size $::CanvasSize($canvas)
- # format value
- set value [format %*.*i $size $size $value]
- # display digits
- set i -1
- foreach digit [split $value {}] \
- { SetDigit $canvas [incr i] $digit $color }
- }
- # -----------
- # count down the time
- # -----------
- proc CountDown {{time ""}} \
- {
- #puts "CountDown $time"
- if {$time == ""} \
- {
- # init
- CancelCount
- set time $::StepTime
- set ::Status countdown
- for {set t $::Height} {$t > 0} {incr t -1} \
- {
- puts $::Status
- if {$::Status != "countdown"} { return }
- $::TimeDisplay coords left 1 1 20 $t; update
- after 10
- }
- }
- set ::CurrentTime $time
- set t [expr {round($::Height * ($::StepTime - $time) / double($::StepTime))}]
- $::TimeDisplay coords left 1 1 20 $t; update
- if {$time > 0} \
- {
- # count down
- if {$::Halted} { incr time }
- set ::CountDown [after 1000 [list CountDown [incr time -1]]]
- } \
- else \
- {
- # timed out
- set ::Status timeout
- EndOfStep
- }
- }
- # -----------
- # cancel a count down
- # -----------
- proc CancelCount {} \
- {
- #puts "CancelCount"
- if {[info exists ::CountDown]} \
- {
- after cancel $::CountDown
- unset ::CountDown
- }
- }
- # -----------
- # randomly pick a color
- # -----------
- proc PickColor {} \
- {
- #puts "PickColor"
- # pick a random color from permitted
- set n [expr {int(rand() * 0.999 * $::nbColors) + 1}]
- set color [lindex $::Colors $n]
- return $color
- }
- # -----------
- # the next bubble to engage
- # -----------
- proc PrepareBubble {} \
- {
- #puts "PrepareBubble"
- # prepare the next bubble
- CreateBubble $::R [expr {$::Height - $::R}]
- }
- # -----------
- # engage the prepared bubble
- # -----------
- proc EngageBubble {} \
- {
- #puts "EngageBubble"
- # catch in case of time out occured at the wrong time
- # and bubbles were destroyed
- catch \
- {
- # get the next bubble
- set ndx $::nbBubbles
- set x [expr {$::Width / 2}]
- set y [expr {$::Height - $::R}]
- $::BubblesDisplay coords bubble$ndx $x $y
- # update info
- set bubble $::Bubbles($ndx)
- set ::Bubbles($ndx) [lreplace $bubble 1 2 $x $y]
- # prepare the next bubble
- PrepareBubble
- set ::Bonus 1
- set ::StepValue 0
- }
- }
- # -----------
- # create a bubble
- # -----------
- proc CreateBubble {x y {ndx ""} {d ""} {color ""}} \
- {
- #puts "CreateBubble $x $y $ndx $d $color"
- if {$ndx == ""} \
- {
- # beginning
- # create an index & pick a color
- set ndx [incr ::nbBubbles]
- set color [PickColor]
- # create the bubble
- set d 8
- $::BubblesDisplay create image $x $y \
- -tags [list bubble bubble$ndx] \
- -image img$d-$color
- # register it
- set ::Bubbles($ndx) [list $color $x $y 0 0 0]
- # animate
- after 100 [list CreateBubble 0 0 $ndx $d $color]
- # return the index
- return $ndx
- } \
- elseif {[incr d 8] <= $::Size} \
- {
- # growing
- $::BubblesDisplay itemconfig bubble$ndx -image img$d-$color
- after 100 [list CreateBubble 0 0 $ndx $d $color]
- }
- }
- # -----------
- # destroy a bubble
- # -----------
- proc DestroyBubble {ndx {d ""} {color ""}} \
- {
- #puts "DestroyBubble $ndx $d $color"
- if {$d == ""} \
- {
- # beginning
- set d $::Size
- foreach {color x y row col} $::Bubbles($ndx) break
- #puts "DestroyBubble $ndx ($x:$y){$row:$col}"
- array unset ::Slots $row:$col
- array unset ::Bubbles $ndx
- }
- if {[incr d -8] == 0} \
- {
- # destroy
- $::BubblesDisplay delete bubble$ndx
- } \
- else \
- {
- # resize
- $::BubblesDisplay itemconfig bubble$ndx -image img$d-$color
- after 100 [list DestroyBubble $ndx $d $color]
- }
- }
- # -----------
- # change the bubble info
- # -----------
- proc UpdateBubble {ndx x y} \
- {
- #puts "UpdateBubble $ndx $x $y"
- # move to a bubble slot
- SetSlot $ndx $x $y
- # pick or create a group
- SetGroup $ndx
- }
- # -----------
- # join a color group to another
- # -----------
- proc UpdateGroup {group ngroup} \
- {
- #puts "UpdateGroup $group $ngroup"
- foreach ndx $::Groups($group) \
- {
- set bubble $::Bubbles($ndx)
- set ::Bubbles($ndx) [lreplace $bubble 5 5 $ngroup]
- lappend ::Groups($ngroup) $ndx
- }
- array unset ::Groups $group
- set ::Bonus [expr {$::Bonus * 4}]
- }
- # -----------
- # destroy a color group
- # -----------
- proc DestroyGroup {group} \
- {
- #puts "DestroyGroup $group"
- set n [llength $::Groups($group)]
- incr ::StepValue [expr {$n * $n * $n}]
- foreach ndx $::Groups($group) { DestroyBubble $ndx }
- array unset ::Groups $group
- }
- # -----------
- # compute the color group of a bubble
- # -----------
- proc SetGroup {ndx} \
- {
- #puts "SetGroup $ndx"
- foreach {color - - row col} $::Bubbles($ndx) break
- # check bubbles in the row
- foreach j [list [expr {$col - 1}] [expr {$col + 1}]] \
- {
- if {[info exists ::Slots($row:$j)]} \
- {
- set bubble $::Bubbles($::Slots($row:$j))
- if {$color == [lindex $bubble 0]} \
- {
- set g [lindex $bubble 5]
- if {![info exists group]} { set group $g } \
- elseif {$g != $group} { UpdateGroup $g $group }
- }
- }
- }
- # check in the contiguous rows
- set i1 [expr {$row - 1}]
- set i2 [expr {$row + 1}]
- if {$row % 2 == 0} \
- {
- # largest row
- set j0 [expr {$col - 1}]
- if {$j0 == -1} { incr j0 }
- set j1 $col
- if {$j1 == $::N - 1} { incr j1 -1 }
- } \
- else \
- {
- # smallest row
- set j0 $col
- set j1 [expr {$col + 1}]
- }
- foreach i [list $i1 $i2] \
- {
- foreach j [list $j0 $j1] \
- {
- if { "$i:$j" != "$row:$col" && [info exists ::Slots($i:$j)]} \
- {
- set bubble $::Bubbles($::Slots($i:$j))
- if {$color == [lindex $bubble 0]} \
- {
- set g [lindex $bubble 5]
- if {![info exists group]} { set group $g } \
- elseif {$g != $group} { UpdateGroup $g $group }
- }
- }
- }
- }
- if {![info exists group]} { set group [incr ::nbGroups] }
- lappend ::Groups($group) $ndx
- set bubble $::Bubbles($ndx)
- set ::Bubbles($ndx) [lreplace $bubble 5 5 $group]
- }
- # -----------
- # set the virtual slot of a bubble
- # -----------
- proc SetSlot {ndx x y} \
- {
- #puts "SetSlot $ndx $x $y"
- # compute the nearest slot
- set row [expr {round(($y - $::R) / $::DY)}]
- set offset [expr {$row % 2 == 0 ? 0 : 1}]
- set col [expr {round(($x - (1 + $offset) * $::R) / $::Size)}]
- if {$col < 0} { incr col }
- if {$col > $::N - 1 - $offset} { incr col -1 }
- # check if already filled
- if {[info exists ::Slots($row:$col)]} \
- {
- incr row
- incr col [expr {$row % 2}]
- if {$::dX < 0} { incr col }
- set offset [expr {$row % 2 == 0 ? $::Size : $::R}]
- }
- # update bubble info
- set y [expr {$row * $::DY + $::R}]
- set x [expr {$col * $::Size + (1 + $offset) * $::R}]
- $::BubblesDisplay coords bubble$ndx $x $y
- # update global info
- set ::Slots($row:$col) $ndx
- set bubble $::Bubbles($ndx)
- set ::Bubbles($ndx) [lreplace $bubble 1 4 $x $y $row $col]
- }
- # -----------
- # move the fired bubble
- # -----------
- proc Shot {time x0 y0} \
- {
- #puts "Shot $time $x0 $y0"
- if {$::Status != "shot"} { return }
- # catch in case of time out occured at the wrong time
- # and bubbles were destroyed
- catch \
- {
- # move a tic
- set x1 [expr {$x0 + $::Speed * $::dX}]
- set y1 [expr {$y0 + $::Speed * $::dY}]
- $::BubblesDisplay coords bubble$::Index $x1 $y1
- if {($x1 < $::R && $::dX < 0) || ($x1 > $::Width - $::R && $::dX > 0)} \
- {
- # bounce
- set ::Status bounce
- set xb [expr {$x1 - $::Speed * $::dX}]
- set yb [expr {$y1 + $::Speed * $::dY}]
- Fire $xb $yb
- } \
- elseif {$time < $::Speed} \
- {
- # end
- SetResult $x1 $y1
- } \
- else \
- {
- # collisions
- foreach ndx $::Collisions \
- {
- if {[info exists ::Bubbles($ndx)]} \
- {
- foreach {- xc yc} $::Bubbles($ndx) break
- if {($xc - $x1) * ($xc - $x1) + ($yc - $y1) * ($yc - $y1) <= $::Size * $::Size} \
- { SetResult $x1 $y1; return }
- }
- }
- # next tic
- after 1 [list Shot [incr time -$::Speed] $x1 $y1]
- }
- }
- }
- # -----------
- # fire the engaged bubble
- # -----------
- proc Fire {xm ym} \
- {
- #puts "Fire $xm $ym"
- # throw the bubble
- if {$::Status == "ready"} \
- {
- # shot
- set ::Shot 1
- set ::Index [expr {$::nbBubbles - 1}]
- foreach {color x0 y0} $::Bubbles($::Index) break
- } \
- elseif {$::Status == "bounce"} \
- {
- # bounce
- set color [lindex $::Bubbles($::Index) 0]
- foreach {x0 y0} [$::BubblesDisplay coords bubble$::Index] break
- } \
- else { return }
- # trajectory
- set dx [expr {$xm - $x0}]
- set dy [expr {$ym - $y0}]
- if {$xm == $x0} \
- {
- set a 0
- set b $xm
- set dc $::R
- } \
- else \
- {
- set a [expr {$dy / double($dx)}]
- set b [expr {(($xm * $y0) - ($x0 * $ym)) / ($xm - $x0)}]
- set dc [expr {abs($::R / sin(atan($a)))}]
- }
- # move
- set ::Collisions {}
- set y1 $::R
- if {$a == 0} { set x1 $xm } \
- else { set x1 [expr {($y1 - $b) / $a}] }
- # potential collisions
- set x $x0
- foreach slot [lsort -dic -dec [array names ::Slots]] \
- {
- # check for some collisions
- set ndx $::Slots($slot)
- if {[lsearch -exact $::Collisions $ndx] > -1} { continue }
- foreach {- xc yc} $::Bubbles($ndx) break
- if {$yc > $::Height - $::Size } { continue }
- if {$a != 0} { set x [expr {($yc - $b) / $a}] }
- set xl [expr {$x - 2 * $dc}]
- set xr [expr {$x + 2 * $dc}]
- if {$xc >= $xl && $xc <= $xr} { lappend ::Collisions $ndx }
- }
- if {$x1 < $::R} \
- {
- # left bounce
- set x1 $::R
- set y1 [expr {$a * $x1 + $b}]
- } \
- elseif {$x1 > $::Width - $::R} \
- {
- # right bounce
- set x1 [expr {$::Width - $::R}]
- set y1 [expr {$a * $x1 + $b}]
- }
- # shot the bubble
- set dx [expr {$x1 - $x0}]
- set dy [expr {$y1 - $y0}]
- set time [expr {int(sqrt(($dx * $dx) + ($dy * $dy)))}]
- if {$time == 0} { return }
- set ::dX [expr {$dx / double($time)}]
- set ::dY [expr {$dy / double($time)}]
- if {$::Status == "ready" || $::Status == "bounce"} \
- {
- set ::Status shot
- after 1 [list Shot $time $x0 $y0]
- }
- }
- # -----------
- # set the result of the shot
- # -----------
- proc SetResult {x y} \
- {
- #puts "SetResult $x $y"
- if {$::Status != "timeout"} \
- {
- # compute new color groups
- UpdateBubble $::Index $x $y
- update
- if {[lindex $::Bubbles($::Index) 2] >= $::Height - $::Size} \
- {
- # lost!
- set ::Status timeout
- } \
- else \
- {
- set group [lindex $::Bubbles($::Index) 5]
- if {[llength $::Groups($group)] > 2} \
- { DestroyGroup $group }
- array set colors {}
- foreach group [array names ::Groups] \
- {
- set color [lindex $::Bubbles([lindex $::Groups($group) 0]) 0]
- set colors($color) $color
- }
- set names [lsort -dic -uniq [array names colors]]
- set ::nbColors [llength $names]
- set ::Colors [concat 0 $names]
- }
- }
- if {$::Status == "timeout" || $::nbColors < 1} \
- {
- # end of step
- EndOfStep
- } \
- else \
- {
- # continue
- set ::Score [expr {$::Score + $::StepValue * $::Bonus}]
- SetNumber $::ScoreDisplay $::Score
- EngageBubble
- # ready to shot
- set ::Status ready
- }
- }
- # -----------
- # end of step
- # -----------
- proc EndOfStep {} \
- {
- #puts "EndOfStep"
- # end of step
- set ::Status endofstep
- CancelCount
- FrozeBubbles
- after 1000 {catch { after cancel $::Froze }}
- # next step
- set bonus 0
- switch $::Level \
- {
- master { set bonus 5000 }
- expert { set bonus 2000 }
- }
- incr ::Score [expr {$::CurrentTime * 10 + $bonus}]
- incr ::GrandScore $::Score
- set n 7
- if {$::Level == "novice"} { set n 6 }
- if {$::nbInitialColors < $n} \
- {
- # next step
- incr ::nbInitialColors
- SetNumber $::GrandScoreDisplay $::GrandScore
- after 1000 NextStep
- after 750
- foreach ndx [array names ::Bubbles] \
- { catch { DestroyBubble $ndx } }
- } \
- else \
- {
- # end of game
- set ::Status newgame
- BlinkNumber $::GrandScoreDisplay $::GrandScore
- DestroyBubble $::nbBubbles
- Options
- UpdateFame
- }
- }
- # -----------
- # prepare for the next step
- # -----------
- proc NextStep {} \
- {
- #puts "NextStep"
- # initialize
- set ::InitialColors [lrange [list 0 0 1 2 3 4 5 6 7] 0 $::nbInitialColors]
- set ::Colors $::InitialColors
- set ::nbColors $::nbInitialColors
- set ::nbBubbles 0
- set ::nbGroups 0
- set ::Score 0
- set ::Bonus 1
- set ::StepValue 0
- set ::Halted 0
- array unset ::Bubbles
- array unset ::Slots
- array unset ::Groups
-
- # update dialog
- StopBlink
- SetNumber $::GrandScoreDisplay 0
- # create bubbles
- CreateBubbles
- # prepare a bubble
- PrepareBubble
- # engage the bubble & fire!
- EngageBubble
- # display the step
- SetNumber $::StepDisplay [incr ::Step]
- # start the timer
- catch { after cancel $::Timer }
- CountDown
- # ready to shot
- set ::Status ready
- }
- # -----------
- # reset the game
- # -----------
- proc NewGame {} \
- {
- #puts "NewGame"
- # in case of
- CancelCount
- # globals
- set ::Status newgame
- set ::MasterWidth 16
- set ::ExpertWidth 13
- set ::NoviceWidth 10
- set ::MasterTime 300
- set ::ExpertTime 330
- set ::NoviceTime 360
- switch $::Level \
- {
- master { set ::N $::MasterWidth; set ::StepTime $::MasterTime }
- expert { set ::N $::ExpertWidth; set ::StepTime $::ExpertTime }
- default { set ::N $::NoviceWidth; set ::StepTime $::NoviceTime }
- }
- set ::DY [expr {int($::Size * 0.866)}]
- set ::R [expr {$::Size / 2}]
- set ::Width [expr {$::Size * $::N}]
- set ::Height [expr {int($::Width * 1.25)}]
- set n 4
- if {$::Level == "novice"} { set n 3 }
- set ::nbInitialColors $n
- set ::Score 0
- set ::GrandScore 0
- # create dialog
- set ::StepDisplay .f1.s
- set ::ScoreDisplay .f1.d
- set ::GrandScoreDisplay .f1.e
- set ::DelayDisplay .f1.f
- set ::OptionsButton .f1.b
- set ::TimeDisplay .f2.t
- set ::BubblesDisplay .f2.c
- array set ::CanvasSize \
- [list \
- $::StepDisplay 1 \
- $::ScoreDisplay 5 \
- $::GrandScoreDisplay 7 \
- $::DelayDisplay 3 \
- ]
- CreateDialog
- # first step
- set ::Step 0
- NextStep
- }
- # -----------
- # dump internal info
- # -----------
- proc Dump {} \
- {
- puts "internal\n--------"
- puts "step: [expr {3 - $::nbInitialColors}]"
- puts "time: $::CurrentTime/$::StepTime"
- puts "level: $::Level"
- puts "bubbles\n-------"
- foreach ndx [lsort -dic [array names ::Bubbles]] \
- { puts "$ndx: $::Bubbles($ndx)" }
- puts "slots\n-----"
- for {set row 0} {$row < 20} {incr row} \
- {
- set ndxs [array names ::Slots $row:*]
- if {[llength $ndxs] == 0} { continue }
- set line ""
- for {set col 0} {$col < $::N} {incr col} \
- {
- set ndx [array names ::Slots $row:$col]
- if {$ndx != ""} { append line "{$row:$col}$::Slots($row:$col) " }
- }
- if {$line != ""} { puts $line }
- }
- puts "groups\n------"
- foreach group [lsort -dic [array names ::Groups]] \
- {
- set ndxs $::Groups($group)
- set n [lindex $::Bubbles([lindex $ndxs 0]) 0]
- set color [lindex {gray red green yellow indigo violet} $n]
- puts "$group: $color $ndxs"
- }
- }
- # -----------
- # display error info
- # -----------
- proc bgerror {args} \
- {
- puts "\nbgerror:\n$args\n"
- set level [info level]
- for {set l $level} {$l < 1} {incr l -1} \
- { puts "$l:\t[info level $l]" }
- Dump
- }
-
- # ===========
- # start game
- # ===========
-
- # exit event
- wm protocol . WM_DELETE_WINDOW exit
- # title
- wm title . "Bubbles v $version, by ulis"
- # parameters
- #BK was 40...
- set ::Size 24
- set ::Speed 3
- set ::Level expert
- catch { source /root/.Bubbles1.Parameters }
- # global
- set ::User anonymous
- # create images
- CreateImages
- # initialize
- NewGame
-