Merge lp:~ken-vandine/dropping-letters/toolbar into lp:dropping-letters
- toolbar
- Merge into trunk
Proposed by
Ken VanDine
Status: | Merged |
---|---|
Approved by: | Alan Pope πΊπ§π± π¦ |
Approved revision: | 29 |
Merged at revision: | 24 |
Proposed branch: | lp:~ken-vandine/dropping-letters/toolbar |
Merge into: | lp:dropping-letters |
Diff against target: |
1291 lines (+608/-602) 5 files modified
debian/changelog (+11/-1) debian/control (+2/-2) debian/install (+2/-1) dropping-letters.qml (+592/-597) dropping-letters.qmlproject (+1/-1) |
To merge this branch: | bzr merge lp:~ken-vandine/dropping-letters/toolbar |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alan Pope πΊπ§π± π¦ (community) | Approve | ||
Review via email: mp+162706@code.launchpad.net |
Commit message
* Use a toolbar for volume and new game instead of the small items on the
bottombar
* Add HUD support
Description of the change
* Use a toolbar for volume and new game instead of the small items on the
bottombar
* Add HUD support
To post a comment you must log in.
- 28. By Ken VanDine
-
Use a toolbar for volume and new game instead of the small items on the
bottombar - 29. By Ken VanDine
-
added New game to HUD
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' | |||
2 | --- debian/changelog 2013-05-01 05:01:59 +0000 | |||
3 | +++ debian/changelog 2013-05-07 05:11:28 +0000 | |||
4 | @@ -1,4 +1,14 @@ | |||
6 | 1 | dropping-letters (0.1) UNRELEASED; urgency=low | 1 | dropping-letters (0.1.1) UNRELEASED; urgency=low |
7 | 2 | |||
8 | 3 | * Use a toolbar for volume and new game instead of the small items on the | ||
9 | 4 | bottombar | ||
10 | 5 | * Add HUD support | ||
11 | 6 | * debian/control | ||
12 | 7 | - depend on qtdeclarative5-hud1.0 | ||
13 | 8 | |||
14 | 9 | -- Ken VanDine <ken.vandine@canonical.com> Wed, 01 May 2013 18:00:42 -0700 | ||
15 | 10 | |||
16 | 11 | dropping-letters (0.1) raring; urgency=low | ||
17 | 2 | 12 | ||
18 | 3 | * Initial Release. | 13 | * Initial Release. |
19 | 4 | 14 | ||
20 | 5 | 15 | ||
21 | === modified file 'debian/control' | |||
22 | --- debian/control 2013-05-01 05:01:59 +0000 | |||
23 | +++ debian/control 2013-05-07 05:11:28 +0000 | |||
24 | @@ -5,11 +5,11 @@ | |||
25 | 5 | Build-Depends: debhelper (>= 9.0.0) | 5 | Build-Depends: debhelper (>= 9.0.0) |
26 | 6 | Standards-Version: 3.9.4 | 6 | Standards-Version: 3.9.4 |
27 | 7 | Homepage: http://launchpad.net/dropping-letters | 7 | Homepage: http://launchpad.net/dropping-letters |
29 | 8 | Vcs-Bzr: https://code.launchpad.net/~sil/dropping-letters | 8 | Vcs-Bzr: https://code.launchpad.net/~dropping-letters-devs/dropping-letters/trunk |
30 | 9 | 9 | ||
31 | 10 | Package: dropping-letters | 10 | Package: dropping-letters |
32 | 11 | Architecture: all | 11 | Architecture: all |
34 | 12 | Depends: ${misc:Depends},qtdeclarative5-localstorage-plugin,qtdeclarative5-particles-plugin,qtdeclarative5-qtmultimedia-plugin,qtdeclarative5-qtquick2-plugin,qtdeclarative5-ubuntu-ui-toolkit-plugin|qt-components-ubuntu,qtdeclarative5-window-plugin,qtdeclarative5-xmllistmodel-plugin,qmlscene | 12 | Depends: ${misc:Depends},qtdeclarative5-hud1.0,qtdeclarative5-localstorage-plugin,qtdeclarative5-particles-plugin,qtdeclarative5-qtmultimedia-plugin,qtdeclarative5-qtquick2-plugin,qtdeclarative5-ubuntu-ui-toolkit-plugin|qt-components-ubuntu,qtdeclarative5-window-plugin,qtdeclarative5-xmllistmodel-plugin,qmlscene |
35 | 13 | Description: Dropping Letters game | 13 | Description: Dropping Letters game |
36 | 14 | Build up words from falling letters to score | 14 | Build up words from falling letters to score |
37 | 15 | points. Don't let the letters build up to the | 15 | points. Don't let the letters build up to the |
38 | 16 | 16 | ||
39 | === modified file 'debian/install' | |||
40 | --- debian/install 2013-05-01 05:01:59 +0000 | |||
41 | +++ debian/install 2013-05-07 05:11:28 +0000 | |||
42 | @@ -1,5 +1,6 @@ | |||
44 | 1 | dropping-letters-ubuntu.qml /usr/share/dropping-letters | 1 | dropping-letters.qml /usr/share/dropping-letters |
45 | 2 | volume-sprite.png /usr/share/dropping-letters | 2 | volume-sprite.png /usr/share/dropping-letters |
46 | 3 | new.png /usr/share/dropping-letters | ||
47 | 3 | test_load_binarydict.js /usr/share/dropping-letters | 4 | test_load_binarydict.js /usr/share/dropping-letters |
48 | 4 | 80921__justinbw__buttonchime02up.ogg /usr/share/dropping-letters | 5 | 80921__justinbw__buttonchime02up.ogg /usr/share/dropping-letters |
49 | 5 | audio-volume-high.svg /usr/share/dropping-letters | 6 | audio-volume-high.svg /usr/share/dropping-letters |
50 | 6 | 7 | ||
51 | === renamed file 'dropping-letters-ubuntu.qml' => 'dropping-letters.qml' | |||
52 | --- dropping-letters-ubuntu.qml 2013-05-01 06:10:15 +0000 | |||
53 | +++ dropping-letters.qml 2013-05-07 05:11:28 +0000 | |||
54 | @@ -5,6 +5,7 @@ | |||
55 | 5 | import QtQuick.LocalStorage 2.0 | 5 | import QtQuick.LocalStorage 2.0 |
56 | 6 | import Ubuntu.Components 0.1 | 6 | import Ubuntu.Components 0.1 |
57 | 7 | import Ubuntu.Components.Popups 0.1 | 7 | import Ubuntu.Components.Popups 0.1 |
58 | 8 | import Ubuntu.HUD 1.0 as HUD | ||
59 | 8 | 9 | ||
60 | 9 | MainView { | 10 | MainView { |
61 | 10 | id: mainView | 11 | id: mainView |
62 | @@ -12,617 +13,598 @@ | |||
63 | 12 | width: units.gu(45) // 48 * 7 + 2 * 7 + 2 | 13 | width: units.gu(45) // 48 * 7 + 2 * 7 + 2 |
64 | 13 | height: units.gu(65) // 48 * 10 + 2 * 10 + 50 | 14 | height: units.gu(65) // 48 * 10 + 2 * 10 + 50 |
65 | 14 | 15 | ||
575 | 15 | Flipable { | 16 | |
576 | 16 | id: flipable | 17 | function resetGame () { |
577 | 17 | property bool flipped: false | 18 | lm.clear(); |
578 | 18 | property variant db: null | 19 | for (var i=0; i<7; i++) { |
579 | 19 | anchors.fill: parent | 20 | lm.append({'letters': [] }); |
580 | 20 | 21 | } | |
581 | 21 | transform: Rotation { | 22 | accum.text = ""; |
582 | 22 | id: rotation | 23 | droptimer.tickCount = 0; |
583 | 23 | origin.x: flipable.width/2 | 24 | flipable.flipped = true; |
584 | 24 | origin.y: flipable.height/2 | 25 | } |
585 | 25 | axis.x: 0; axis.y: 1; axis.z: 0 // set axis.y to 1 to rotate around y-axis | 26 | |
586 | 26 | angle: 0 // the default angle | 27 | Page { |
587 | 27 | } | 28 | tools: ToolbarActions { |
588 | 28 | property int minChromeHeight: 50 | 29 | Action { |
589 | 29 | 30 | text: i18n.tr("Volume") | |
590 | 30 | Component.onCompleted: { | 31 | iconSource: (volume.audible ? "audio-volume-high-symbolic.svg" : "audio-volume-muted-symbolic.svg") |
591 | 31 | var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000); | 32 | onTriggered: { |
592 | 32 | db.transaction(function(tx) { | 33 | volume.audible = !volume.audible; |
593 | 33 | // Create the database if it doesn't already exist | 34 | } |
594 | 34 | tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(score INT, time TEXT)'); | 35 | } |
595 | 35 | var res = tx.executeSql('SELECT score from Scores order by score DESC LIMIT 1'); | 36 | Action { |
596 | 36 | if (res.rows.length === 0) { | 37 | text: i18n.tr("New game") |
597 | 37 | bestscore.updateScore(0); | 38 | iconSource: ("new.png") |
598 | 38 | } else { | 39 | onTriggered: { |
599 | 39 | bestscore.updateScore(res.rows.item(0).score); | 40 | resetGame(); |
600 | 40 | } | 41 | } |
601 | 41 | }); | 42 | } |
602 | 42 | } | 43 | } |
603 | 43 | 44 | ||
604 | 44 | states: [ | 45 | Item { |
605 | 45 | State { | 46 | id: volume |
606 | 46 | name: "back" | 47 | property int frame: 0 |
607 | 47 | PropertyChanges { target: rotation; angle: 180 } | 48 | property bool reverse: false |
608 | 48 | when: flipable.flipped | 49 | property bool audible: true |
609 | 49 | }, | 50 | } |
610 | 50 | State { | 51 | |
611 | 51 | name: "front" | 52 | Flipable { |
612 | 52 | when: !flipable.flipped | 53 | id: flipable |
613 | 53 | } | 54 | property bool flipped: false |
614 | 54 | ] | 55 | property variant db: null |
615 | 55 | 56 | anchors.fill: parent | |
616 | 56 | transitions: [ | 57 | |
617 | 57 | Transition { | 58 | transform: Rotation { |
618 | 58 | NumberAnimation { target: rotation; property: "angle"; duration: 200 } | 59 | id: rotation |
619 | 59 | } | 60 | origin.x: flipable.width/2 |
620 | 60 | ] | 61 | origin.y: flipable.height/2 |
621 | 61 | 62 | axis.x: 0; axis.y: 1; axis.z: 0 // set axis.y to 1 to rotate around y-axis | |
622 | 62 | front: Rectangle { | 63 | angle: 0 // the default angle |
623 | 63 | id: entry | 64 | } |
624 | 64 | color: "#efefea" | 65 | property int minChromeHeight: 50 |
625 | 65 | width: flipable.width // 48 * 7 + 2 * 7 + 2 | 66 | |
626 | 66 | height: flipable.height // 48 * 10 + 2 * 10 + 50 | 67 | Component.onCompleted: { |
627 | 67 | 68 | var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000); | |
628 | 68 | Column { | 69 | db.transaction(function(tx) { |
629 | 69 | id: logo | 70 | // Create the database if it doesn't already exist |
630 | 70 | anchors.centerIn: parent | 71 | tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(score INT, time TEXT)'); |
631 | 71 | //spacing: units.dp(2) // 2 | 72 | var res = tx.executeSql('SELECT score from Scores order by score DESC LIMIT 1'); |
632 | 72 | Repeater { | 73 | if (res.rows.length === 0) { |
633 | 73 | id: titleRowRepeater | 74 | bestscore.updateScore(0); |
634 | 74 | model: ["DROP", "PING", "LETT", "ERS "] | 75 | } else { |
635 | 75 | Row { | 76 | bestscore.updateScore(res.rows.item(0).score); |
636 | 76 | id: titleRow | 77 | } |
637 | 77 | //spacing: units.dp(2) // 2 | 78 | }); |
638 | 78 | property int lineIndex: index | 79 | } |
639 | 79 | property string modelString: modelData | 80 | |
640 | 80 | Repeater { | 81 | states: [ |
641 | 81 | id: titleColRepeater | 82 | State { |
642 | 82 | model: modelData.split("") | 83 | name: "back" |
643 | 83 | Rectangle { | 84 | PropertyChanges { target: rotation; angle: 180 } |
644 | 84 | id: titleletter | 85 | when: flipable.flipped |
645 | 85 | width: Math.max(flipable.width * 0.4, flipable.height * 0.4) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing | 86 | }, |
646 | 86 | height: Math.max(flipable.width * 0.4, flipable.height * 0.4) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing | 87 | State { |
647 | 87 | color: Qt.hsla(210/360, 0.84, 0.25 + ((4-parent.lineIndex) * 0.05) + ((4-index) * 0.05)); | 88 | name: "front" |
648 | 88 | //radius: "medium" | 89 | when: !flipable.flipped |
649 | 89 | Label { | 90 | } |
650 | 90 | text: modelData | 91 | ] |
651 | 91 | anchors.centerIn: parent | 92 | |
652 | 92 | fontSize: "x-large" | 93 | transitions: [ |
653 | 93 | font.bold: true | 94 | Transition { |
654 | 94 | color: "#ffffff" | 95 | NumberAnimation { target: rotation; property: "angle"; duration: 200 } |
655 | 95 | } | 96 | } |
656 | 96 | states: [ | 97 | ] |
657 | 97 | State { name: "showing"; when: flipable.state == "front" | 98 | |
658 | 98 | PropertyChanges { target: titleletter; y: 0 } | 99 | front: Rectangle { |
659 | 99 | }, | 100 | id: entry |
151 | 100 | State { name: "notshowing"; when: flipable.state != "front" | ||
152 | 101 | PropertyChanges { target: titleletter; y: -units.gu(300) } | ||
153 | 102 | } | ||
154 | 103 | ] | ||
155 | 104 | Behavior on y { | ||
156 | 105 | SequentialAnimation { | ||
157 | 106 | PauseAnimation { | ||
158 | 107 | duration: (35 * parent.modelString.length * (4-parent.lineIndex)) + ( | ||
159 | 108 | 35 * index) } | ||
160 | 109 | NumberAnimation { easing.type: Easing.OutQuart } | ||
161 | 110 | } | ||
162 | 111 | } | ||
163 | 112 | } | ||
164 | 113 | } | ||
165 | 114 | } | ||
166 | 115 | } | ||
167 | 116 | } | ||
168 | 117 | Label { | ||
169 | 118 | id: playbutton | ||
170 | 119 | text: "play" | ||
171 | 120 | anchors.top: logo.bottom | ||
172 | 121 | anchors.topMargin: units.gu(2) | ||
173 | 122 | anchors.horizontalCenter: logo.horizontalCenter | ||
174 | 123 | fontSize: "x-large" | ||
175 | 124 | color: "#222222" | ||
176 | 125 | } | ||
177 | 126 | Label { | ||
178 | 127 | id: bestscore | ||
179 | 128 | property int bestsofar: 0 | ||
180 | 129 | text: "..." | ||
181 | 130 | anchors.top: playbutton.bottom | ||
182 | 131 | anchors.topMargin: units.gu(2) | ||
183 | 132 | anchors.horizontalCenter: logo.horizontalCenter | ||
184 | 133 | fontSize: "large" | ||
185 | 134 | color: "#222222" | ||
186 | 135 | function updateScore(score) { | ||
187 | 136 | if (score >= bestscore.bestsofar) { | ||
188 | 137 | bestscore.text = "Best score: " + score; | ||
189 | 138 | bestscore.bestsofar = score; | ||
190 | 139 | } | ||
191 | 140 | } | ||
192 | 141 | } | ||
193 | 142 | MouseArea { | ||
194 | 143 | anchors.fill: parent | ||
195 | 144 | enabled: !flipable.flipped | ||
196 | 145 | onClicked: { | ||
197 | 146 | lm.clear(); | ||
198 | 147 | for (var i=0; i<7; i++) { | ||
199 | 148 | lm.append({'letters': [] }); | ||
200 | 149 | } | ||
201 | 150 | accum.text = ""; | ||
202 | 151 | droptimer.tickCount = 0; | ||
203 | 152 | flipable.flipped = true | ||
204 | 153 | } | ||
205 | 154 | } | ||
206 | 155 | |||
207 | 156 | Rectangle { | ||
208 | 157 | id: helpbutton | ||
209 | 158 | width: units.gu(5) | ||
210 | 159 | height: units.gu(5) | ||
211 | 160 | radius: units.gu(1) | ||
212 | 161 | Label { | ||
213 | 162 | text: "?" | ||
214 | 163 | anchors.centerIn: parent | ||
215 | 164 | } | ||
216 | 165 | anchors.top: parent.top | ||
217 | 166 | anchors.right: parent.right | ||
218 | 167 | anchors.margins: units.gu(2) | ||
219 | 168 | MouseArea { | ||
220 | 169 | anchors.fill: parent | ||
221 | 170 | onClicked: { | ||
222 | 171 | PopupUtils.open(helppop, helpbutton) | ||
223 | 172 | } | ||
224 | 173 | } | ||
225 | 174 | } | ||
226 | 175 | Component { | ||
227 | 176 | id: helppop | ||
228 | 177 | Popover { | ||
229 | 178 | id: helpsheet | ||
230 | 179 | Rectangle { | ||
231 | 180 | anchors.top: parent.top | ||
232 | 181 | anchors.left: parent.left | ||
233 | 182 | anchors.right: parent.right | ||
234 | 183 | height: units.gu(15) | ||
235 | 184 | border.color: "#ddd" | ||
236 | 185 | radius: 2 | ||
237 | 186 | Label { | ||
238 | 187 | anchors.fill: parent | ||
239 | 188 | anchors.margins: units.gu(1) | ||
240 | 189 | text: "game by <a href='http://twitter.com/sil'>@sil</a><br>music: <a href='http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1200076'>Easy Lemon</a> from Kevin McCloud (incompetech.com)<br>sounds: freesound from <a href='http://www.freesound.org/people/kantouth/sounds/106727/'>kantouth</a> / <a href='http://www.freesound.org/people/tictacshutup/sounds/407/'>tictacshutup</a> / <a href='http://www.freesound.org/people/dj-chronos/sounds/45137/'>dj-chronos</a> / <a href='http://www.freesound.org/people/justinbw/sounds/80921/'>justinbw</a>" | ||
241 | 190 | wrapMode: Text.WordWrap | ||
242 | 191 | textFormat: Text.StyledText | ||
243 | 192 | onLinkActivated: Qt.openUrlExternally(link) | ||
244 | 193 | } | ||
245 | 194 | } | ||
246 | 195 | } | ||
247 | 196 | } | ||
248 | 197 | |||
249 | 198 | } | ||
250 | 199 | |||
251 | 200 | back: Rectangle { | ||
252 | 201 | id: main | ||
253 | 202 | color: "#58585A" | ||
254 | 203 | width: flipable.width // 48 * 7 + 2 * 7 + 2 | ||
255 | 204 | height: flipable.height // 48 * 10 + 2 * 10 + 50 | ||
256 | 205 | property var selectedItems: [] | ||
257 | 206 | /* | ||
258 | 207 | obtained with: | ||
259 | 208 | import re; fp=open('/usr/share/dict/words'); | ||
260 | 209 | shorts=[re.sub('[^a-zA-Z]','',x.lower().strip()) for x in fp if len(x)<7]; | ||
261 | 210 | from collections import Counter; c=Counter(''.join(shorts)); least=c.most_common()[-1][1]; | ||
262 | 211 | print dict([(x.upper(),c[x]/least) for x in c]) | ||
263 | 212 | */ | ||
264 | 213 | property variant letterFreqs: { | ||
265 | 214 | 'A': 66, 'C': 22, 'B': 19, 'E': 72, 'D': 28, 'G': 18, 'F': 12, 'I': 41, 'H': 20, | ||
266 | 215 | 'K': 14, 'J': 4, 'M': 22, 'L': 40, 'O': 48, 'N': 35, 'Q': 1, 'P': 22, 'S': 75, | ||
267 | 216 | 'R': 43, 'U': 26, 'T': 37, 'W': 13, 'V': 7, 'Y': 19, 'X': 3, 'Z': 4 | ||
268 | 217 | } | ||
269 | 218 | property variant letterScores: { | ||
270 | 219 | "A":1,"B":3,"C":3,"D":2,"E":1,"F":4,"G":2,"H":4,"I":1,"J":8,"K":5,"L":1, | ||
271 | 220 | "M":3,"N":1,"O":1,"P":3,"Q":10,"R":1,"S":1,"T":1,"U":1,"V":4,"W":4,"X":8, | ||
272 | 221 | "Y":4,"Z":10 | ||
273 | 222 | } | ||
274 | 223 | property int score: 0 | ||
275 | 224 | |||
276 | 225 | function getRandomWeightedLetter() { | ||
277 | 226 | // could work out sumOfWeights once, but this is easier to understand | ||
278 | 227 | var sumOfWeights = 0; | ||
279 | 228 | for (var k in main.letterFreqs) { sumOfWeights += main.letterFreqs[k]; } | ||
280 | 229 | var selection = Math.floor(Math.random() * sumOfWeights); | ||
281 | 230 | for (var k in main.letterFreqs) { | ||
282 | 231 | if (selection < main.letterFreqs[k]) return k; | ||
283 | 232 | selection -= main.letterFreqs[k]; | ||
284 | 233 | } | ||
285 | 234 | } | ||
286 | 235 | |||
287 | 236 | Audio { | ||
288 | 237 | id: music | ||
289 | 238 | source: "Easy_Lemon_60_second.ogg" | ||
290 | 239 | autoPlay: true | ||
291 | 240 | onStopped: music.play() | ||
292 | 241 | muted: !volume.audible | ||
293 | 242 | } | ||
294 | 243 | |||
295 | 244 | Audio { | ||
296 | 245 | id: click | ||
297 | 246 | source: "407__tictacshutup__click-1-off-click.ogg" | ||
298 | 247 | autoLoad: true | ||
299 | 248 | muted: !volume.audible | ||
300 | 249 | } | ||
301 | 250 | |||
302 | 251 | Audio { | ||
303 | 252 | id: success | ||
304 | 253 | source: "80921__justinbw__buttonchime02up.ogg" | ||
305 | 254 | autoLoad: true | ||
306 | 255 | muted: !volume.audible | ||
307 | 256 | } | ||
308 | 257 | |||
309 | 258 | Audio { | ||
310 | 259 | id: failure | ||
311 | 260 | source: "106727__kantouth__cartoon-bing-low.ogg" | ||
312 | 261 | autoLoad: true | ||
313 | 262 | muted: !volume.audible | ||
314 | 263 | } | ||
315 | 264 | |||
316 | 265 | Audio { | ||
317 | 266 | id: gameover | ||
318 | 267 | source: "45137__dj-chronos__dark-church-bell.ogg" | ||
319 | 268 | autoLoad: true | ||
320 | 269 | onStopped: { | ||
321 | 270 | flipable.flipped = false | ||
322 | 271 | } | ||
323 | 272 | muted: !volume.audible | ||
324 | 273 | } | ||
325 | 274 | |||
326 | 275 | Rectangle { | ||
327 | 276 | id: bottombar | ||
328 | 277 | anchors.bottom: main.bottom | ||
329 | 278 | anchors.left: main.left | ||
330 | 279 | anchors.right: main.right | ||
331 | 280 | height: (main.height - (game.squaresize * 10 + 11)) / 2 | ||
332 | 281 | z: 2 | ||
333 | 282 | color: Qt.hsla(210/360, 0.84, 0.2) | ||
334 | 283 | |||
335 | 284 | Rectangle { | ||
336 | 285 | id: mainscore | ||
337 | 286 | anchors.right: quitgame.left | ||
338 | 287 | anchors.top: bottombar.top | ||
339 | 288 | anchors.bottom: bottombar.bottom | ||
340 | 289 | anchors.left: volume.right | ||
341 | 290 | z: 2 | ||
342 | 291 | color: Qt.rgba(0,0,0,0) | ||
343 | 292 | Label { | ||
344 | 293 | anchors.centerIn: parent | ||
345 | 294 | fontSize: "x-large" | ||
346 | 295 | text: "" + main.score | ||
347 | 296 | color: "white" | ||
348 | 297 | } | ||
349 | 298 | } | ||
350 | 299 | |||
351 | 300 | Rectangle { | ||
352 | 301 | id: quitgame | ||
353 | 302 | width: bottombar.height | ||
354 | 303 | height: bottombar.height | ||
355 | 304 | color: Qt.rgba(0,0,0,0) | ||
356 | 305 | anchors.right: bottombar.right | ||
357 | 306 | anchors.top: bottombar.top | ||
358 | 307 | z: 3 | ||
359 | 308 | |||
360 | 309 | Label { | ||
361 | 310 | anchors.centerIn: parent | ||
362 | 311 | text: "\u00d7" | ||
363 | 312 | fontSize: "x-large" | ||
364 | 313 | color: "white" | ||
365 | 314 | MouseArea { | ||
366 | 315 | anchors.fill: parent | ||
367 | 316 | onClicked: { | ||
368 | 317 | flipable.flipped = false; | ||
369 | 318 | } | ||
370 | 319 | } | ||
371 | 320 | } | ||
372 | 321 | } | ||
373 | 322 | |||
374 | 323 | Rectangle { | ||
375 | 324 | id: volume | ||
376 | 325 | width: bottombar.height | ||
377 | 326 | height: bottombar.height + 1 | ||
378 | 327 | color: Qt.rgba(0,0,0,0) | ||
379 | 328 | anchors.left: bottombar.left | ||
380 | 329 | anchors.bottom: bottombar.bottom | ||
381 | 330 | z: 3 | ||
382 | 331 | clip: true | ||
383 | 332 | property int frame: 0 | ||
384 | 333 | property bool reverse: false | ||
385 | 334 | property bool audible: true | ||
386 | 335 | Image { | ||
387 | 336 | id: image | ||
388 | 337 | sourceSize.width: parent.height * 0.8 | ||
389 | 338 | sourceSize.height: parent.height * 0.8 | ||
390 | 339 | anchors.centerIn: parent | ||
391 | 340 | source: volume.audible ? "audio-volume-high-symbolic.svg" : "audio-volume-muted-symbolic.svg"; | ||
392 | 341 | } | ||
393 | 342 | MouseArea { | ||
394 | 343 | anchors.fill: parent | ||
395 | 344 | onClicked: { | ||
396 | 345 | volume.audible = !volume.audible | ||
397 | 346 | } | ||
398 | 347 | } | ||
399 | 348 | } | ||
400 | 349 | } | ||
401 | 350 | |||
402 | 351 | Rectangle { | ||
403 | 352 | id: topbar | ||
404 | 353 | color: "blue" | ||
405 | 354 | anchors.top: main.top | ||
406 | 355 | anchors.left: main.left | ||
407 | 356 | anchors.right: main.right | ||
408 | 357 | height: (main.height - (game.squaresize * 10 + 11)) / 2 | ||
409 | 358 | z: 2 | ||
410 | 359 | |||
411 | 360 | Rectangle { | ||
412 | 361 | anchors.fill: topbar | ||
413 | 362 | z: 2 | ||
414 | 363 | color: accum.text == "" ? "#efefea" : (accum.isValid ? Qt.hsla(124/360, 0.83, 0.45) : Qt.hsla(0, 0.83, 0.65)) | ||
415 | 364 | id: suggestedWordContainer | ||
416 | 365 | Label { | ||
417 | 366 | id: accum | ||
418 | 367 | anchors.centerIn: parent | ||
419 | 368 | text: "" | ||
420 | 369 | color: "white" | ||
421 | 370 | fontSize: "x-large" | ||
422 | 371 | font.bold: true | ||
423 | 372 | property bool isValid: false | ||
424 | 373 | function findBinaryWord( word ) { | ||
425 | 374 | var bd = Wordlist.wordlist; | ||
426 | 375 | var l = word.length; | ||
427 | 376 | // Don't search if there's nothing to look through | ||
428 | 377 | if ( !bd[l] ) { | ||
429 | 378 | return false; | ||
430 | 379 | } | ||
431 | 380 | // Get the number of words in the dictionary bin | ||
432 | 381 | var words = bd[l].length / l, | ||
433 | 382 | // The low point from where we're starting the binary search | ||
434 | 383 | low = 0, | ||
435 | 384 | // The max high point | ||
436 | 385 | high = words - 1, | ||
437 | 386 | // And the precise middle of the search | ||
438 | 387 | mid = Math.floor( words / 2 ); | ||
439 | 388 | // We continue to look until we reach a final word | ||
440 | 389 | while ( high >= low ) { | ||
441 | 390 | // Grab the word at our current position | ||
442 | 391 | var found = bd[l].substr( l * mid, l ); | ||
443 | 392 | // If we've found the word, stop now | ||
444 | 393 | if ( word === found ) { | ||
445 | 394 | return true; | ||
446 | 395 | } | ||
447 | 396 | // Otherwise, compare | ||
448 | 397 | // If we're too high, move lower | ||
449 | 398 | if ( word < found ) { | ||
450 | 399 | high = mid - 1; | ||
451 | 400 | // If we're too low, go higher | ||
452 | 401 | } else { | ||
453 | 402 | low = mid + 1; | ||
454 | 403 | } | ||
455 | 404 | // And find the new search point | ||
456 | 405 | mid = Math.floor( (low + high) / 2 ); | ||
457 | 406 | } | ||
458 | 407 | // Nothing was found | ||
459 | 408 | return false; | ||
460 | 409 | } | ||
461 | 410 | onTextChanged: { | ||
462 | 411 | accum.isValid = findBinaryWord(accum.text); | ||
463 | 412 | } | ||
464 | 413 | } | ||
465 | 414 | function processSuggestedWord() { | ||
466 | 415 | if (accum.isValid) { | ||
467 | 416 | success.play(); | ||
468 | 417 | var thisscore = 0, wordlength = accum.text.length; | ||
469 | 418 | accum.text = ""; | ||
470 | 419 | |||
471 | 420 | // tell the boxes to destroy themselves | ||
472 | 421 | main.selectedItems.forEach(function(b) { | ||
473 | 422 | thisscore += main.letterScores[b.containedLetter]; | ||
474 | 423 | b.state = "dead"; | ||
475 | 424 | }) | ||
476 | 425 | main.selectedItems = []; | ||
477 | 426 | main.score += thisscore * wordlength; | ||
478 | 427 | scoredisplay.text = "" + (thisscore * wordlength); | ||
479 | 428 | showscoredisplay.start(); | ||
480 | 429 | } else { | ||
481 | 430 | failure.play(); | ||
482 | 431 | accum.text = ""; | ||
483 | 432 | main.selectedItems.forEach(function(b) { b.selected = false; }) | ||
484 | 433 | main.selectedItems = []; | ||
485 | 434 | } | ||
486 | 435 | } | ||
487 | 436 | focus: true | ||
488 | 437 | Keys.onReturnPressed: { | ||
489 | 438 | suggestedWordContainer.processSuggestedWord(); | ||
490 | 439 | } | ||
491 | 440 | MouseArea { | ||
492 | 441 | anchors.fill: parent | ||
493 | 442 | onClicked: { suggestedWordContainer.processSuggestedWord(); } | ||
494 | 443 | } | ||
495 | 444 | } | ||
496 | 445 | |||
497 | 446 | |||
498 | 447 | } | ||
499 | 448 | |||
500 | 449 | Label { | ||
501 | 450 | id: scoredisplay | ||
502 | 451 | anchors.centerIn: parent | ||
503 | 452 | z: 3 | ||
504 | 453 | fontSize: "x-large" | ||
505 | 454 | text: "200" | ||
506 | 455 | color: "red" | ||
507 | 456 | opacity: 0 | ||
508 | 457 | } | ||
509 | 458 | |||
510 | 459 | ParallelAnimation { | ||
511 | 460 | id: showscoredisplay | ||
512 | 461 | NumberAnimation { | ||
513 | 462 | property: "scale" | ||
514 | 463 | from: 0.1 | ||
515 | 464 | to: 8.0 | ||
516 | 465 | duration: 400 | ||
517 | 466 | target: scoredisplay | ||
518 | 467 | } | ||
519 | 468 | SequentialAnimation { | ||
520 | 469 | NumberAnimation { | ||
521 | 470 | property: "opacity" | ||
522 | 471 | from: 0 | ||
523 | 472 | to: 1.0 | ||
524 | 473 | duration: 20 | ||
525 | 474 | target: scoredisplay | ||
526 | 475 | } | ||
527 | 476 | NumberAnimation { | ||
528 | 477 | property: "opacity" | ||
529 | 478 | from: 1.0 | ||
530 | 479 | to: 0 | ||
531 | 480 | duration: 380 | ||
532 | 481 | target: scoredisplay | ||
533 | 482 | } | ||
534 | 483 | } | ||
535 | 484 | } | ||
536 | 485 | |||
537 | 486 | |||
538 | 487 | Timer { | ||
539 | 488 | id: droptimer | ||
540 | 489 | repeat: true | ||
541 | 490 | running: flipable.flipped | ||
542 | 491 | interval: 2000 | ||
543 | 492 | property int tickCount: 0 | ||
544 | 493 | triggeredOnStart: true | ||
545 | 494 | onTriggered: { | ||
546 | 495 | tickCount += 5 | ||
547 | 496 | droptimer.interval = 2000 - tickCount | ||
548 | 497 | var idx = Math.round(Math.random() * (lm.count - 1)); | ||
549 | 498 | lm.get(idx).letters.append({ letter: main.getRandomWeightedLetter() }); | ||
550 | 499 | if (lm.get(idx).letters.count >= 10) { | ||
551 | 500 | droptimer.stop(); | ||
552 | 501 | gameover.play(); | ||
553 | 502 | var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000); | ||
554 | 503 | db.transaction(function(tx) { | ||
555 | 504 | tx.executeSql("insert into Scores values (?,?)", [main.score, 0]); | ||
556 | 505 | bestscore.updateScore(main.score); | ||
557 | 506 | }); | ||
558 | 507 | } | ||
559 | 508 | } | ||
560 | 509 | } | ||
561 | 510 | |||
562 | 511 | ListModel { | ||
563 | 512 | id: lm | ||
564 | 513 | } | ||
565 | 514 | |||
566 | 515 | |||
567 | 516 | Rectangle { | ||
568 | 517 | id: game | ||
569 | 518 | property int squaresize: Math.min((flipable.width) / 7, (flipable.height - (flipable.minChromeHeight * 2)) / 10) | ||
570 | 519 | anchors.top: topbar.bottom | ||
571 | 520 | anchors.bottom: bottombar.top | ||
572 | 521 | anchors.left: main.left | ||
573 | 522 | anchors.right: main.right | ||
574 | 523 | scale: -1 | ||
660 | 524 | color: "#efefea" | 101 | color: "#efefea" |
666 | 525 | Row { | 102 | width: flipable.width // 48 * 7 + 2 * 7 + 2 |
667 | 526 | anchors.horizontalCenter: game.horizontalCenter | 103 | height: flipable.height // 48 * 10 + 2 * 10 + 50 |
668 | 527 | anchors.top: game.top | 104 | |
669 | 528 | anchors.topMargin: 1 | 105 | Column { |
670 | 529 | //spacing: 1 | 106 | id: logo |
671 | 107 | anchors.centerIn: parent | ||
672 | 108 | //spacing: units.dp(2) // 2 | ||
673 | 530 | Repeater { | 109 | Repeater { |
686 | 531 | model: lm | 110 | id: titleRowRepeater |
687 | 532 | Column { | 111 | model: ["DROP", "PING", "LETT", "ERS "] |
688 | 533 | //spacing: 1 | 112 | Row { |
689 | 534 | property int idx: index | 113 | id: titleRow |
690 | 535 | width: game.squaresize | 114 | //spacing: units.dp(2) // 2 |
691 | 536 | height: game.height | 115 | property int lineIndex: index |
692 | 537 | add: Transition { | 116 | property string modelString: modelData |
681 | 538 | NumberAnimation { properties: "y"; easing.type: Easing.OutBounce; duration: 1000 } | ||
682 | 539 | } | ||
683 | 540 | move: Transition { | ||
684 | 541 | NumberAnimation { properties: "y"; easing.type: Easing.OutBounce } | ||
685 | 542 | } | ||
693 | 543 | Repeater { | 117 | Repeater { |
695 | 544 | model: letters | 118 | id: titleColRepeater |
696 | 119 | model: modelData.split("") | ||
697 | 545 | Rectangle { | 120 | Rectangle { |
713 | 546 | id: box | 121 | id: titleletter |
714 | 547 | property bool selected: false | 122 | width: Math.max(flipable.width * 0.4, flipable.height * 0.4) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing |
715 | 548 | property int idx: index | 123 | height: Math.max(flipable.width * 0.4, flipable.height * 0.4) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing |
716 | 549 | property string containedLetter: letter | 124 | color: Qt.hsla(210/360, 0.84, 0.25 + ((4-parent.lineIndex) * 0.05) + ((4-index) * 0.05)); |
702 | 550 | color: { | ||
703 | 551 | if (lm.get(parent.idx).letters.count >= 10) { | ||
704 | 552 | return "red"; | ||
705 | 553 | } else if (!selected) { | ||
706 | 554 | return Qt.hsla(210/360, 0.84, 0.25 + (idx * 0.05)); | ||
707 | 555 | } else if (accum.isValid) { | ||
708 | 556 | return Qt.hsla(124/360, 0.83, 0.45); // "#93cc98"; | ||
709 | 557 | } else { | ||
710 | 558 | return Qt.hsla(0, 0.83, 0.65); // "#cc9598" | ||
711 | 559 | } | ||
712 | 560 | } | ||
717 | 561 | //radius: "medium" | 125 | //radius: "medium" |
718 | 562 | scale: -1 | ||
719 | 563 | width: game.squaresize | ||
720 | 564 | height: game.squaresize | ||
721 | 565 | y: game.height + game.squaresize | ||
722 | 566 | z: 5 | ||
723 | 567 | Label { | 126 | Label { |
724 | 127 | text: modelData | ||
725 | 568 | anchors.centerIn: parent | 128 | anchors.centerIn: parent |
728 | 569 | text: letter | 129 | fontSize: "x-large" |
727 | 570 | fontSize: "large" | ||
729 | 571 | font.bold: true | 130 | font.bold: true |
730 | 572 | color: "#ffffff" | 131 | color: "#ffffff" |
731 | 573 | } | 132 | } |
740 | 574 | MouseArea { | 133 | states: [ |
741 | 575 | anchors.fill: parent | 134 | State { name: "showing"; when: flipable.state == "front" |
742 | 576 | onClicked: { | 135 | PropertyChanges { target: titleletter; y: 0 } |
743 | 577 | if (!box.selected) { | 136 | }, |
744 | 578 | box.selected = true; | 137 | State { name: "notshowing"; when: flipable.state != "front" |
745 | 579 | accum.text += letter; | 138 | PropertyChanges { target: titleletter; y: -units.gu(300) } |
746 | 580 | click.play(); | 139 | } |
747 | 581 | main.selectedItems[main.selectedItems.length] = box; | 140 | ] |
748 | 141 | Behavior on y { | ||
749 | 142 | SequentialAnimation { | ||
750 | 143 | PauseAnimation { | ||
751 | 144 | duration: (35 * parent.modelString.length * (4-parent.lineIndex)) + ( | ||
752 | 145 | 35 * index) } | ||
753 | 146 | NumberAnimation { easing.type: Easing.OutQuart } | ||
754 | 147 | } | ||
755 | 148 | } | ||
756 | 149 | } | ||
757 | 150 | } | ||
758 | 151 | } | ||
759 | 152 | } | ||
760 | 153 | } | ||
761 | 154 | Label { | ||
762 | 155 | id: playbutton | ||
763 | 156 | text: i18n.tr("Play") | ||
764 | 157 | anchors.top: logo.bottom | ||
765 | 158 | anchors.topMargin: units.gu(2) | ||
766 | 159 | anchors.horizontalCenter: logo.horizontalCenter | ||
767 | 160 | fontSize: "x-large" | ||
768 | 161 | color: "#222222" | ||
769 | 162 | MouseArea { | ||
770 | 163 | anchors.fill: parent | ||
771 | 164 | enabled: !flipable.flipped | ||
772 | 165 | onClicked: { | ||
773 | 166 | resetGame(); | ||
774 | 167 | } | ||
775 | 168 | } | ||
776 | 169 | } | ||
777 | 170 | Label { | ||
778 | 171 | id: bestscore | ||
779 | 172 | property int bestsofar: 0 | ||
780 | 173 | text: "..." | ||
781 | 174 | anchors.top: playbutton.bottom | ||
782 | 175 | anchors.topMargin: units.gu(2) | ||
783 | 176 | anchors.horizontalCenter: logo.horizontalCenter | ||
784 | 177 | fontSize: "large" | ||
785 | 178 | color: "#222222" | ||
786 | 179 | function updateScore(score) { | ||
787 | 180 | if (score >= bestscore.bestsofar) { | ||
788 | 181 | bestscore.text = "Best score: " + score; | ||
789 | 182 | bestscore.bestsofar = score; | ||
790 | 183 | } | ||
791 | 184 | } | ||
792 | 185 | } | ||
793 | 186 | |||
794 | 187 | Rectangle { | ||
795 | 188 | id: helpbutton | ||
796 | 189 | width: units.gu(5) | ||
797 | 190 | height: units.gu(5) | ||
798 | 191 | radius: units.gu(1) | ||
799 | 192 | Label { | ||
800 | 193 | text: "?" | ||
801 | 194 | anchors.centerIn: parent | ||
802 | 195 | } | ||
803 | 196 | anchors.top: parent.top | ||
804 | 197 | anchors.right: parent.right | ||
805 | 198 | anchors.margins: units.gu(2) | ||
806 | 199 | MouseArea { | ||
807 | 200 | anchors.fill: parent | ||
808 | 201 | onClicked: { | ||
809 | 202 | PopupUtils.open(helppop, helpbutton) | ||
810 | 203 | } | ||
811 | 204 | } | ||
812 | 205 | } | ||
813 | 206 | Component { | ||
814 | 207 | id: helppop | ||
815 | 208 | Popover { | ||
816 | 209 | id: helpsheet | ||
817 | 210 | Rectangle { | ||
818 | 211 | anchors.top: parent.top | ||
819 | 212 | anchors.left: parent.left | ||
820 | 213 | anchors.right: parent.right | ||
821 | 214 | height: units.gu(15) | ||
822 | 215 | border.color: "#ddd" | ||
823 | 216 | radius: 2 | ||
824 | 217 | Label { | ||
825 | 218 | anchors.fill: parent | ||
826 | 219 | anchors.margins: units.gu(1) | ||
827 | 220 | text: "game by <a href='http://twitter.com/sil'>@sil</a><br>music: <a href='http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1200076'>Easy Lemon</a> from Kevin McCloud (incompetech.com)<br>sounds: freesound from <a href='http://www.freesound.org/people/kantouth/sounds/106727/'>kantouth</a> / <a href='http://www.freesound.org/people/tictacshutup/sounds/407/'>tictacshutup</a> / <a href='http://www.freesound.org/people/dj-chronos/sounds/45137/'>dj-chronos</a> / <a href='http://www.freesound.org/people/justinbw/sounds/80921/'>justinbw</a>" | ||
828 | 221 | wrapMode: Text.WordWrap | ||
829 | 222 | textFormat: Text.StyledText | ||
830 | 223 | onLinkActivated: Qt.openUrlExternally(link) | ||
831 | 224 | } | ||
832 | 225 | } | ||
833 | 226 | } | ||
834 | 227 | } | ||
835 | 228 | |||
836 | 229 | } | ||
837 | 230 | |||
838 | 231 | back: Rectangle { | ||
839 | 232 | id: main | ||
840 | 233 | color: "#58585A" | ||
841 | 234 | width: flipable.width // 48 * 7 + 2 * 7 + 2 | ||
842 | 235 | height: flipable.height // 48 * 10 + 2 * 10 + 50 | ||
843 | 236 | property var selectedItems: [] | ||
844 | 237 | /* | ||
845 | 238 | obtained with: | ||
846 | 239 | import re; fp=open('/usr/share/dict/words'); | ||
847 | 240 | shorts=[re.sub('[^a-zA-Z]','',x.lower().strip()) for x in fp if len(x)<7]; | ||
848 | 241 | from collections import Counter; c=Counter(''.join(shorts)); least=c.most_common()[-1][1]; | ||
849 | 242 | print dict([(x.upper(),c[x]/least) for x in c]) | ||
850 | 243 | */ | ||
851 | 244 | property variant letterFreqs: { | ||
852 | 245 | 'A': 66, 'C': 22, 'B': 19, 'E': 72, 'D': 28, 'G': 18, 'F': 12, 'I': 41, 'H': 20, | ||
853 | 246 | 'K': 14, 'J': 4, 'M': 22, 'L': 40, 'O': 48, 'N': 35, 'Q': 1, 'P': 22, 'S': 75, | ||
854 | 247 | 'R': 43, 'U': 26, 'T': 37, 'W': 13, 'V': 7, 'Y': 19, 'X': 3, 'Z': 4 | ||
855 | 248 | } | ||
856 | 249 | property variant letterScores: { | ||
857 | 250 | "A":1,"B":3,"C":3,"D":2,"E":1,"F":4,"G":2,"H":4,"I":1,"J":8,"K":5,"L":1, | ||
858 | 251 | "M":3,"N":1,"O":1,"P":3,"Q":10,"R":1,"S":1,"T":1,"U":1,"V":4,"W":4,"X":8, | ||
859 | 252 | "Y":4,"Z":10 | ||
860 | 253 | } | ||
861 | 254 | property int score: 0 | ||
862 | 255 | |||
863 | 256 | function getRandomWeightedLetter() { | ||
864 | 257 | // could work out sumOfWeights once, but this is easier to understand | ||
865 | 258 | var sumOfWeights = 0; | ||
866 | 259 | for (var k in main.letterFreqs) { sumOfWeights += main.letterFreqs[k]; } | ||
867 | 260 | var selection = Math.floor(Math.random() * sumOfWeights); | ||
868 | 261 | for (var k in main.letterFreqs) { | ||
869 | 262 | if (selection < main.letterFreqs[k]) return k; | ||
870 | 263 | selection -= main.letterFreqs[k]; | ||
871 | 264 | } | ||
872 | 265 | } | ||
873 | 266 | |||
874 | 267 | Audio { | ||
875 | 268 | id: music | ||
876 | 269 | source: "Easy_Lemon_60_second.ogg" | ||
877 | 270 | autoPlay: true | ||
878 | 271 | onStopped: music.play() | ||
879 | 272 | muted: !volume.audible | ||
880 | 273 | } | ||
881 | 274 | |||
882 | 275 | Audio { | ||
883 | 276 | id: click | ||
884 | 277 | source: "407__tictacshutup__click-1-off-click.ogg" | ||
885 | 278 | autoLoad: true | ||
886 | 279 | muted: !volume.audible | ||
887 | 280 | } | ||
888 | 281 | |||
889 | 282 | Audio { | ||
890 | 283 | id: success | ||
891 | 284 | source: "80921__justinbw__buttonchime02up.ogg" | ||
892 | 285 | autoLoad: true | ||
893 | 286 | muted: !volume.audible | ||
894 | 287 | } | ||
895 | 288 | |||
896 | 289 | Audio { | ||
897 | 290 | id: failure | ||
898 | 291 | source: "106727__kantouth__cartoon-bing-low.ogg" | ||
899 | 292 | autoLoad: true | ||
900 | 293 | muted: !volume.audible | ||
901 | 294 | } | ||
902 | 295 | |||
903 | 296 | Audio { | ||
904 | 297 | id: gameover | ||
905 | 298 | source: "45137__dj-chronos__dark-church-bell.ogg" | ||
906 | 299 | autoLoad: true | ||
907 | 300 | onStopped: { | ||
908 | 301 | flipable.flipped = false | ||
909 | 302 | } | ||
910 | 303 | muted: !volume.audible | ||
911 | 304 | } | ||
912 | 305 | |||
913 | 306 | Rectangle { | ||
914 | 307 | id: bottombar | ||
915 | 308 | anchors.bottom: main.bottom | ||
916 | 309 | anchors.left: main.left | ||
917 | 310 | anchors.right: main.right | ||
918 | 311 | height: (main.height - (game.squaresize * 10 + 11)) / 2 | ||
919 | 312 | z: 2 | ||
920 | 313 | color: Qt.hsla(210/360, 0.84, 0.2) | ||
921 | 314 | |||
922 | 315 | Rectangle { | ||
923 | 316 | id: mainscore | ||
924 | 317 | anchors { | ||
925 | 318 | centerIn: bottombar | ||
926 | 319 | bottom: bottombar.bottom | ||
927 | 320 | } | ||
928 | 321 | z: 2 | ||
929 | 322 | color: Qt.rgba(0,0,0,0) | ||
930 | 323 | Label { | ||
931 | 324 | anchors.centerIn: parent | ||
932 | 325 | fontSize: "x-large" | ||
933 | 326 | text: "" + main.score | ||
934 | 327 | color: "white" | ||
935 | 328 | } | ||
936 | 329 | } | ||
937 | 330 | } | ||
938 | 331 | |||
939 | 332 | Rectangle { | ||
940 | 333 | id: topbar | ||
941 | 334 | color: "blue" | ||
942 | 335 | anchors.top: main.top | ||
943 | 336 | anchors.left: main.left | ||
944 | 337 | anchors.right: main.right | ||
945 | 338 | height: (main.height - (game.squaresize * 10 + 11)) / 2 | ||
946 | 339 | z: 2 | ||
947 | 340 | |||
948 | 341 | Rectangle { | ||
949 | 342 | anchors.fill: topbar | ||
950 | 343 | z: 2 | ||
951 | 344 | color: accum.text == "" ? "#efefea" : (accum.isValid ? Qt.hsla(124/360, 0.83, 0.45) : Qt.hsla(0, 0.83, 0.65)) | ||
952 | 345 | id: suggestedWordContainer | ||
953 | 346 | Label { | ||
954 | 347 | id: accum | ||
955 | 348 | anchors.centerIn: parent | ||
956 | 349 | text: "" | ||
957 | 350 | color: "white" | ||
958 | 351 | fontSize: "x-large" | ||
959 | 352 | font.bold: true | ||
960 | 353 | property bool isValid: false | ||
961 | 354 | function findBinaryWord( word ) { | ||
962 | 355 | var bd = Wordlist.wordlist; | ||
963 | 356 | var l = word.length; | ||
964 | 357 | // Don't search if there's nothing to look through | ||
965 | 358 | if ( !bd[l] ) { | ||
966 | 359 | return false; | ||
967 | 360 | } | ||
968 | 361 | // Get the number of words in the dictionary bin | ||
969 | 362 | var words = bd[l].length / l, | ||
970 | 363 | // The low point from where we're starting the binary search | ||
971 | 364 | low = 0, | ||
972 | 365 | // The max high point | ||
973 | 366 | high = words - 1, | ||
974 | 367 | // And the precise middle of the search | ||
975 | 368 | mid = Math.floor( words / 2 ); | ||
976 | 369 | // We continue to look until we reach a final word | ||
977 | 370 | while ( high >= low ) { | ||
978 | 371 | // Grab the word at our current position | ||
979 | 372 | var found = bd[l].substr( l * mid, l ); | ||
980 | 373 | // If we've found the word, stop now | ||
981 | 374 | if ( word === found ) { | ||
982 | 375 | return true; | ||
983 | 376 | } | ||
984 | 377 | // Otherwise, compare | ||
985 | 378 | // If we're too high, move lower | ||
986 | 379 | if ( word < found ) { | ||
987 | 380 | high = mid - 1; | ||
988 | 381 | // If we're too low, go higher | ||
989 | 382 | } else { | ||
990 | 383 | low = mid + 1; | ||
991 | 384 | } | ||
992 | 385 | // And find the new search point | ||
993 | 386 | mid = Math.floor( (low + high) / 2 ); | ||
994 | 387 | } | ||
995 | 388 | // Nothing was found | ||
996 | 389 | return false; | ||
997 | 390 | } | ||
998 | 391 | onTextChanged: { | ||
999 | 392 | accum.isValid = findBinaryWord(accum.text); | ||
1000 | 393 | } | ||
1001 | 394 | } | ||
1002 | 395 | function processSuggestedWord() { | ||
1003 | 396 | if (accum.isValid) { | ||
1004 | 397 | success.play(); | ||
1005 | 398 | var thisscore = 0, wordlength = accum.text.length; | ||
1006 | 399 | accum.text = ""; | ||
1007 | 400 | |||
1008 | 401 | // tell the boxes to destroy themselves | ||
1009 | 402 | main.selectedItems.forEach(function(b) { | ||
1010 | 403 | thisscore += main.letterScores[b.containedLetter]; | ||
1011 | 404 | b.state = "dead"; | ||
1012 | 405 | }) | ||
1013 | 406 | main.selectedItems = []; | ||
1014 | 407 | main.score += thisscore * wordlength; | ||
1015 | 408 | scoredisplay.text = "" + (thisscore * wordlength); | ||
1016 | 409 | showscoredisplay.start(); | ||
1017 | 410 | } else { | ||
1018 | 411 | failure.play(); | ||
1019 | 412 | accum.text = ""; | ||
1020 | 413 | main.selectedItems.forEach(function(b) { b.selected = false; }) | ||
1021 | 414 | main.selectedItems = []; | ||
1022 | 415 | } | ||
1023 | 416 | } | ||
1024 | 417 | focus: true | ||
1025 | 418 | Keys.onReturnPressed: { | ||
1026 | 419 | suggestedWordContainer.processSuggestedWord(); | ||
1027 | 420 | } | ||
1028 | 421 | MouseArea { | ||
1029 | 422 | anchors.fill: parent | ||
1030 | 423 | onClicked: { suggestedWordContainer.processSuggestedWord(); } | ||
1031 | 424 | } | ||
1032 | 425 | } | ||
1033 | 426 | |||
1034 | 427 | |||
1035 | 428 | } | ||
1036 | 429 | |||
1037 | 430 | Label { | ||
1038 | 431 | id: scoredisplay | ||
1039 | 432 | anchors.centerIn: parent | ||
1040 | 433 | z: 3 | ||
1041 | 434 | fontSize: "x-large" | ||
1042 | 435 | text: "200" | ||
1043 | 436 | color: "red" | ||
1044 | 437 | opacity: 0 | ||
1045 | 438 | } | ||
1046 | 439 | |||
1047 | 440 | ParallelAnimation { | ||
1048 | 441 | id: showscoredisplay | ||
1049 | 442 | NumberAnimation { | ||
1050 | 443 | property: "scale" | ||
1051 | 444 | from: 0.1 | ||
1052 | 445 | to: 8.0 | ||
1053 | 446 | duration: 400 | ||
1054 | 447 | target: scoredisplay | ||
1055 | 448 | } | ||
1056 | 449 | SequentialAnimation { | ||
1057 | 450 | NumberAnimation { | ||
1058 | 451 | property: "opacity" | ||
1059 | 452 | from: 0 | ||
1060 | 453 | to: 1.0 | ||
1061 | 454 | duration: 20 | ||
1062 | 455 | target: scoredisplay | ||
1063 | 456 | } | ||
1064 | 457 | NumberAnimation { | ||
1065 | 458 | property: "opacity" | ||
1066 | 459 | from: 1.0 | ||
1067 | 460 | to: 0 | ||
1068 | 461 | duration: 380 | ||
1069 | 462 | target: scoredisplay | ||
1070 | 463 | } | ||
1071 | 464 | } | ||
1072 | 465 | } | ||
1073 | 466 | |||
1074 | 467 | |||
1075 | 468 | Timer { | ||
1076 | 469 | id: droptimer | ||
1077 | 470 | repeat: true | ||
1078 | 471 | running: flipable.flipped | ||
1079 | 472 | interval: 2000 | ||
1080 | 473 | property int tickCount: 0 | ||
1081 | 474 | triggeredOnStart: true | ||
1082 | 475 | onTriggered: { | ||
1083 | 476 | tickCount += 5 | ||
1084 | 477 | droptimer.interval = 2000 - tickCount | ||
1085 | 478 | var idx = Math.round(Math.random() * (lm.count - 1)); | ||
1086 | 479 | lm.get(idx).letters.append({ letter: main.getRandomWeightedLetter() }); | ||
1087 | 480 | if (lm.get(idx).letters.count >= 10) { | ||
1088 | 481 | droptimer.stop(); | ||
1089 | 482 | gameover.play(); | ||
1090 | 483 | var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000); | ||
1091 | 484 | db.transaction(function(tx) { | ||
1092 | 485 | tx.executeSql("insert into Scores values (?,?)", [main.score, 0]); | ||
1093 | 486 | bestscore.updateScore(main.score); | ||
1094 | 487 | }); | ||
1095 | 488 | } | ||
1096 | 489 | } | ||
1097 | 490 | } | ||
1098 | 491 | |||
1099 | 492 | ListModel { | ||
1100 | 493 | id: lm | ||
1101 | 494 | } | ||
1102 | 495 | |||
1103 | 496 | |||
1104 | 497 | Rectangle { | ||
1105 | 498 | id: game | ||
1106 | 499 | property int squaresize: Math.min((flipable.width) / 7, (flipable.height - (flipable.minChromeHeight * 2)) / 10) | ||
1107 | 500 | anchors.top: topbar.bottom | ||
1108 | 501 | anchors.bottom: bottombar.top | ||
1109 | 502 | anchors.left: main.left | ||
1110 | 503 | anchors.right: main.right | ||
1111 | 504 | scale: -1 | ||
1112 | 505 | color: "#efefea" | ||
1113 | 506 | Row { | ||
1114 | 507 | anchors.horizontalCenter: game.horizontalCenter | ||
1115 | 508 | anchors.top: game.top | ||
1116 | 509 | anchors.topMargin: 1 | ||
1117 | 510 | //spacing: 1 | ||
1118 | 511 | Repeater { | ||
1119 | 512 | model: lm | ||
1120 | 513 | Column { | ||
1121 | 514 | //spacing: 1 | ||
1122 | 515 | property int idx: index | ||
1123 | 516 | width: game.squaresize | ||
1124 | 517 | height: game.height | ||
1125 | 518 | add: Transition { | ||
1126 | 519 | NumberAnimation { properties: "y"; easing.type: Easing.OutBounce; duration: 1000 } | ||
1127 | 520 | } | ||
1128 | 521 | move: Transition { | ||
1129 | 522 | NumberAnimation { properties: "y"; easing.type: Easing.OutBounce } | ||
1130 | 523 | } | ||
1131 | 524 | Repeater { | ||
1132 | 525 | model: letters | ||
1133 | 526 | Rectangle { | ||
1134 | 527 | id: box | ||
1135 | 528 | property bool selected: false | ||
1136 | 529 | property int idx: index | ||
1137 | 530 | property string containedLetter: letter | ||
1138 | 531 | color: { | ||
1139 | 532 | if (lm.get(parent.idx).letters.count >= 10) { | ||
1140 | 533 | return "red"; | ||
1141 | 534 | } else if (!selected) { | ||
1142 | 535 | return Qt.hsla(210/360, 0.84, 0.25 + (idx * 0.05)); | ||
1143 | 536 | } else if (accum.isValid) { | ||
1144 | 537 | return Qt.hsla(124/360, 0.83, 0.45); // "#93cc98"; | ||
1145 | 582 | } else { | 538 | } else { |
1150 | 583 | if (box === main.selectedItems[main.selectedItems.length - 1]) { | 539 | return Qt.hsla(0, 0.83, 0.65); // "#cc9598" |
1151 | 584 | main.selectedItems.pop(main.selectedItems.length - 1); | 540 | } |
1152 | 585 | box.selected = false; | 541 | } |
1153 | 586 | accum.text = accum.text.substr(0, accum.text.length - 1); | 542 | //radius: "medium" |
1154 | 543 | scale: -1 | ||
1155 | 544 | width: game.squaresize | ||
1156 | 545 | height: game.squaresize | ||
1157 | 546 | y: game.height + game.squaresize | ||
1158 | 547 | z: 5 | ||
1159 | 548 | Label { | ||
1160 | 549 | anchors.centerIn: parent | ||
1161 | 550 | text: letter | ||
1162 | 551 | fontSize: "large" | ||
1163 | 552 | font.bold: true | ||
1164 | 553 | color: "#ffffff" | ||
1165 | 554 | } | ||
1166 | 555 | MouseArea { | ||
1167 | 556 | anchors.fill: parent | ||
1168 | 557 | onClicked: { | ||
1169 | 558 | if (!box.selected) { | ||
1170 | 559 | box.selected = true; | ||
1171 | 560 | accum.text += letter; | ||
1172 | 561 | click.play(); | ||
1173 | 562 | main.selectedItems[main.selectedItems.length] = box; | ||
1174 | 563 | } else { | ||
1175 | 564 | if (box === main.selectedItems[main.selectedItems.length - 1]) { | ||
1176 | 565 | main.selectedItems.pop(main.selectedItems.length - 1); | ||
1177 | 566 | box.selected = false; | ||
1178 | 567 | accum.text = accum.text.substr(0, accum.text.length - 1); | ||
1179 | 568 | } | ||
1180 | 587 | } | 569 | } |
1181 | 588 | } | 570 | } |
1182 | 589 | } | 571 | } |
1219 | 590 | } | 572 | Behavior on opacity { |
1220 | 591 | Behavior on opacity { | 573 | SequentialAnimation { |
1221 | 592 | SequentialAnimation { | 574 | ScriptAction { script: pulseEmitter.burst(1000); } |
1222 | 593 | ScriptAction { script: pulseEmitter.burst(1000); } | 575 | NumberAnimation { properties:"opacity"; duration: 500 } |
1223 | 594 | NumberAnimation { properties:"opacity"; duration: 500 } | 576 | ScriptAction { script: lm.get(box.parent.idx).letters.remove(box.idx); } |
1224 | 595 | ScriptAction { script: lm.get(box.parent.idx).letters.remove(box.idx); } | 577 | } |
1225 | 596 | } | 578 | } |
1226 | 597 | } | 579 | states: [ |
1227 | 598 | states: [ | 580 | State { name: "alive" }, |
1228 | 599 | State { name: "alive" }, | 581 | State { |
1229 | 600 | State { | 582 | name: "dead" |
1230 | 601 | name: "dead" | 583 | PropertyChanges { target: box; opacity: 0 } |
1231 | 602 | PropertyChanges { target: box; opacity: 0 } | 584 | } |
1232 | 603 | } | 585 | ] |
1233 | 604 | ] | 586 | ParticleSystem { |
1234 | 605 | ParticleSystem { | 587 | id: particles |
1235 | 606 | id: particles | 588 | width: flipable.width / 2 |
1236 | 607 | width: flipable.width / 2 | 589 | height: flipable.width / 2 |
1237 | 608 | height: flipable.width / 2 | 590 | anchors.centerIn: parent |
1238 | 609 | anchors.centerIn: parent | 591 | clip: false |
1239 | 610 | clip: false | 592 | ImageParticle { |
1240 | 611 | ImageParticle { | 593 | source: "redStar.png" |
1241 | 612 | source: "redStar.png" | 594 | alpha: 0 |
1242 | 613 | alpha: 0 | 595 | colorVariation: 0.6 |
1243 | 614 | colorVariation: 0.6 | 596 | } |
1244 | 615 | } | 597 | Emitter { |
1245 | 616 | Emitter { | 598 | id: pulseEmitter |
1246 | 617 | id: pulseEmitter | 599 | x: parent.width/2 |
1247 | 618 | x: parent.width/2 | 600 | y: parent.height/2 |
1248 | 619 | y: parent.height/2 | 601 | emitRate: 2000 |
1249 | 620 | emitRate: 2000 | 602 | lifeSpan: 500 |
1250 | 621 | lifeSpan: 500 | 603 | enabled: false |
1251 | 622 | enabled: false | 604 | velocity: AngleDirection { magnitude: 256; angleVariation: 360; magnitudeVariation: 200; } |
1252 | 623 | velocity: AngleDirection { magnitude: 256; angleVariation: 360; magnitudeVariation: 200; } | 605 | size: parent.width / 8 |
1253 | 624 | size: parent.width / 8 | 606 | sizeVariation: 8 |
1254 | 625 | sizeVariation: 8 | 607 | } |
1255 | 626 | } | 608 | } |
1256 | 627 | } | 609 | } |
1257 | 628 | } | 610 | } |
1258 | @@ -633,4 +615,17 @@ | |||
1259 | 633 | } | 615 | } |
1260 | 634 | } | 616 | } |
1261 | 635 | } | 617 | } |
1262 | 618 | HUD.HUD { | ||
1263 | 619 | applicationIdentifier: "dropping-letters" | ||
1264 | 620 | HUD.Context { | ||
1265 | 621 | HUD.QuitAction { | ||
1266 | 622 | onTriggered: Qt.quit() | ||
1267 | 623 | } | ||
1268 | 624 | HUD.Action { | ||
1269 | 625 | label: i18n.tr("New game") | ||
1270 | 626 | keywords: "Reset;Start;New" | ||
1271 | 627 | onTriggered: resetGame() | ||
1272 | 628 | } | ||
1273 | 629 | } | ||
1274 | 630 | } | ||
1275 | 636 | } | 631 | } |
1276 | 637 | 632 | ||
1277 | === modified file 'dropping-letters.qmlproject' | |||
1278 | --- dropping-letters.qmlproject 2013-05-01 05:13:52 +0000 | |||
1279 | +++ dropping-letters.qmlproject 2013-05-07 05:11:28 +0000 | |||
1280 | @@ -3,7 +3,7 @@ | |||
1281 | 3 | import QmlProject 1.1 | 3 | import QmlProject 1.1 |
1282 | 4 | 4 | ||
1283 | 5 | Project { | 5 | Project { |
1285 | 6 | mainFile: "dropping-letters-ubuntu.qml" | 6 | mainFile: "dropping-letters.qml" |
1286 | 7 | 7 | ||
1287 | 8 | /* Include .qml, .js, and image files from current directory and subdirectories */ | 8 | /* Include .qml, .js, and image files from current directory and subdirectories */ |
1288 | 9 | QmlFiles { | 9 | QmlFiles { |
1289 | 10 | 10 | ||
1290 | === added file 'new.png' | |||
1291 | 11 | Binary files new.png 1970-01-01 00:00:00 +0000 and new.png 2013-05-07 05:11:28 +0000 differ | 11 | Binary files new.png 1970-01-01 00:00:00 +0000 and new.png 2013-05-07 05:11:28 +0000 differ |
Looks good.