├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── html ├── README.md ├── checkers │ ├── .gitignore │ ├── images │ │ ├── black-queen.png │ │ ├── black.png │ │ ├── logo.png │ │ ├── red-queen.png │ │ └── red.png │ ├── index.html │ ├── main.js │ ├── package-lock.json │ └── package.json ├── colors │ ├── audio │ │ └── fairy.mp3 │ └── index.html ├── game-of-life │ └── index.html ├── guessing-game │ ├── boing.mp3 │ └── index.html ├── index.html ├── logo.png ├── morse-code │ ├── audios │ │ ├── 0.wav │ │ ├── 1.wav │ │ ├── 2.wav │ │ ├── 3.wav │ │ ├── 4.wav │ │ ├── 5.wav │ │ ├── 6.wav │ │ ├── 7.wav │ │ ├── 8.wav │ │ ├── 9.wav │ │ ├── A.wav │ │ ├── B.wav │ │ ├── C.wav │ │ ├── D.wav │ │ ├── E.wav │ │ ├── F.wav │ │ ├── G.wav │ │ ├── H.wav │ │ ├── I.wav │ │ ├── J.wav │ │ ├── K.wav │ │ ├── L.wav │ │ ├── M.wav │ │ ├── N.wav │ │ ├── O.wav │ │ ├── P.wav │ │ ├── Q.wav │ │ ├── R.wav │ │ ├── S.wav │ │ ├── T.wav │ │ ├── U.wav │ │ ├── V.wav │ │ ├── W.wav │ │ ├── X.wav │ │ ├── Y.wav │ │ ├── Z.wav │ │ ├── dah.wav │ │ ├── dih.wav │ │ └── space.wav │ └── index.html ├── racing │ ├── index.html │ └── tennis-ball.png ├── rps++ │ ├── data-capture │ │ ├── README.md │ │ ├── index.html │ │ ├── index.js │ │ └── python │ │ │ ├── README.md │ │ │ ├── data-adult.json │ │ │ ├── data-kid.json │ │ │ ├── model.ipynb │ │ │ └── models.json │ ├── index.html │ └── index.js ├── rps-game │ ├── audio │ │ ├── lose.mp3 │ │ ├── tie.mp3 │ │ └── win.mp3 │ ├── images │ │ ├── paper.png │ │ ├── rock.png │ │ ├── scissor.png │ │ └── start.png │ └── index.html ├── sign-language │ ├── images │ │ ├── a.png │ │ ├── b.png │ │ ├── c.png │ │ ├── d.png │ │ ├── e.png │ │ ├── f.png │ │ ├── g.png │ │ ├── h.png │ │ ├── i.png │ │ ├── j.png │ │ ├── k.png │ │ ├── l.png │ │ ├── m.png │ │ ├── n.png │ │ ├── o.png │ │ ├── p.png │ │ ├── q.png │ │ ├── r.png │ │ ├── s.png │ │ ├── t.png │ │ ├── u.png │ │ ├── v.png │ │ ├── w.png │ │ ├── x.png │ │ ├── y.png │ │ └── z.png │ └── index.html ├── slot-machine-game │ ├── boing.mp3 │ └── index.html ├── solar-system │ └── index.html └── tic-tac-toe │ ├── audio │ └── fairy.mp3 │ └── index.html ├── java └── greenfoot │ ├── .gitignore │ ├── README.md │ ├── bee-vs-bug │ ├── Bee.ctxt │ ├── Bee.java │ ├── Bug.ctxt │ ├── Bug.java │ ├── MyWorld.ctxt │ ├── MyWorld.java │ ├── README.TXT │ ├── images │ │ ├── bee.png │ │ ├── fingerprint.jpg │ │ └── ladybug_02.png │ ├── project.greenfoot │ └── sounds │ │ └── ahhh.wav │ ├── bump-babies │ ├── Baby.ctxt │ ├── Baby.java │ ├── Fish.ctxt │ ├── Fish.java │ ├── MyWorld.ctxt │ ├── MyWorld.java │ ├── README.TXT │ ├── images │ │ ├── baby2.png │ │ ├── bluerock.jpg │ │ └── fish3.png │ └── project.greenfoot │ └── race-car │ ├── GreenCar.ctxt │ ├── GreenCar.java │ ├── MyWorld.ctxt │ ├── MyWorld.java │ ├── README.TXT │ ├── RedCar.ctxt │ ├── RedCar.java │ ├── Score.ctxt │ ├── Score.java │ ├── images │ ├── car02-n.png │ └── car03-n.png │ └── project.greenfoot ├── logo.png └── python └── pygame ├── .gitignore ├── README.md ├── basic ├── audios │ └── fairy.wav ├── bouncing-balls.py ├── bouncing-image-with-sound.py ├── bouncing-images.py ├── char-animation.py ├── collison-detection.py ├── draw-circles.py ├── draw-shapes.py ├── draw-sprite.py ├── image-rotation.py ├── images │ ├── Satyr_01_Idle_000.png │ ├── Satyr_02_Idle_000.png │ ├── Satyr_03_Idle_000.png │ ├── ball.png │ ├── frame-1.png │ ├── frame-2.png │ ├── frame-3.png │ ├── frame-4.png │ ├── frame-5.png │ ├── frame-6.png │ ├── frame-7.png │ ├── frame-8.png │ └── logo.png ├── key-movement.py └── mouse-movement.py ├── space-battle ├── audio │ ├── bullet.wav │ ├── explosion.wav │ └── game.wav ├── game.py ├── images │ ├── bullet.png │ ├── rock.png │ ├── ship.png │ └── upgrade.png └── objects.py └── yappy-bird ├── game.py ├── images ├── frame-1.png ├── frame-2.png ├── frame-3.png ├── frame-4.png ├── frame-5.png ├── frame-6.png ├── frame-7.png └── frame-8.png └── objects.py /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: vangj 4 | patreon: vangj 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://oneoffcoder.com/ 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode/ 3 | .ipynb_checkpoints/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![One-Off Coder Logo](logo.png "One-Off Coder") 2 | 3 | # Lightning Projects 4 | 5 | These are a set of `Lightning Projects` that are meant to be friendly, fun, yet 6 | effective coding projects for children to learn and improve their coding skills. 7 | If you have any questions, please do not hesistate to contact us at 8 | info@oneoffcoder.com. 9 | 10 | * [HTML, CSS, JavaScript](html): Games based on HTML, CSS and JavaScript 11 | * [Java, Greenfoot](java/greenfoot): Games based on Java and Greenfoot 12 | * [Python, Pygame](python/pygame): Games based on Python and Pygame 13 | 14 | # Citation 15 | 16 | ``` 17 | @misc{lightning_projects_oneoffcoder_2020, 18 | title={Lightning Projects}, 19 | url={https://github.com/oneoffcoder/lightning-projects/}, 20 | journal={GitHub}, 21 | author={One-Off Coder}, 22 | year={2020}, 23 | month={Jun}} 24 | ``` 25 | 26 | # Copyright Stuff 27 | 28 | ``` 29 | Copyright 2020 One-Off Coder 30 | 31 | Licensed under the Apache License, Version 2.0 (the "License"); 32 | you may not use this file except in compliance with the License. 33 | You may obtain a copy of the License at 34 | 35 | http://www.apache.org/licenses/LICENSE-2.0 36 | 37 | Unless required by applicable law or agreed to in writing, software 38 | distributed under the License is distributed on an "AS IS" BASIS, 39 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 40 | See the License for the specific language governing permissions and 41 | limitations under the License. 42 | ``` 43 | 44 | 45 | # Contact 46 | 47 | One-Off Coder 48 | 49 | * [Website](https://www.oneoffcoder.com) 50 | * [Twitter](https://twitter.com/oneoffcoder) 51 | * [Facebook](https://www.facebook.com/oneoffcoder) 52 | * [YouTube](https://www.youtube.com/channel/UCCCv8Glpb2dq2mhUj5mcHCQ) -------------------------------------------------------------------------------- /html/README.md: -------------------------------------------------------------------------------- 1 | ![One-Off Coder Logo](../logo.png "One-Off Coder") 2 | 3 | # Project Description 4 | 5 | * [guessing-game](guessing-game): Have fun coding a game that asks users to guess which number the computer will generate. 6 | * [slot-machine-game](slot-machine-game): Learn about random number generators through coding a slot machine simulator. 7 | * [rps-game](rps-game): A challenging project to code the classic Rock, Paper, Scissor game. 8 | * [tic-tac-toe](tic-tack-toe): Classic tic tac toe. 9 | * [colors](colors): Colors! 10 | * [checkers](checkers): Classic checkers. 11 | * [solar-system](solar-system): A simulation of the planetary orbits in our solar system. 12 | * [game-of-life](game-of-life): Conway's Game of Life. 13 | * [morse-code](morse-code): Morse code. 14 | * [sign-language](sign-language): Learn sign language alphabets. 15 | * [rps++](rps++): Rock, Paper, Scissor re-invented with a double dose of artificial intelligence; hand pose recognition with deep learning and hand pose prediction with logistic regression. -------------------------------------------------------------------------------- /html/checkers/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | out/ -------------------------------------------------------------------------------- /html/checkers/images/black-queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/checkers/images/black-queen.png -------------------------------------------------------------------------------- /html/checkers/images/black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/checkers/images/black.png -------------------------------------------------------------------------------- /html/checkers/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/checkers/images/logo.png -------------------------------------------------------------------------------- /html/checkers/images/red-queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/checkers/images/red-queen.png -------------------------------------------------------------------------------- /html/checkers/images/red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/checkers/images/red.png -------------------------------------------------------------------------------- /html/checkers/main.js: -------------------------------------------------------------------------------- 1 | const { app, BrowserWindow } = require('electron') 2 | 3 | function createWindow () { 4 | // Create the browser window. 5 | const win = new BrowserWindow({ 6 | width: 1000, 7 | height: 1000, 8 | webPreferences: { 9 | nodeIntegration: true 10 | } 11 | }) 12 | 13 | // and load the index.html of the app. 14 | win.loadFile('index.html') 15 | } 16 | 17 | // This method will be called when Electron has finished 18 | // initialization and is ready to create browser windows. 19 | // Some APIs can only be used after this event occurs. 20 | app.whenReady().then(createWindow) 21 | 22 | // Quit when all windows are closed, except on macOS. There, it's common 23 | // for applications and their menu bar to stay active until the user quits 24 | // explicitly with Cmd + Q. 25 | app.on('window-all-closed', () => { 26 | if (process.platform !== 'darwin') { 27 | app.quit() 28 | } 29 | }) 30 | 31 | app.on('activate', () => { 32 | // On macOS it's common to re-create a window in the app when the 33 | // dock icon is clicked and there are no other windows open. 34 | if (BrowserWindow.getAllWindows().length === 0) { 35 | createWindow() 36 | } 37 | }) 38 | 39 | // In this file you can include the rest of your app's specific main process 40 | // code. You can also put them in separate files and require them here. -------------------------------------------------------------------------------- /html/checkers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "checkers", 3 | "version": "1.0.0", 4 | "description": "Checkers", 5 | "main": "main.js", 6 | "dependencies": { 7 | "electron-squirrel-startup": "^1.0.0" 8 | }, 9 | "devDependencies": { 10 | "@electron-forge/cli": "^6.0.0-beta.51", 11 | "@electron-forge/maker-deb": "^6.0.0-beta.51", 12 | "@electron-forge/maker-rpm": "^6.0.0-beta.51", 13 | "@electron-forge/maker-squirrel": "^6.0.0-beta.51", 14 | "@electron-forge/maker-zip": "^6.0.0-beta.51", 15 | "electron": "^9.0.4" 16 | }, 17 | "scripts": { 18 | "start": "electron-forge start", 19 | "package": "electron-forge package", 20 | "make": "electron-forge make" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/oneoffcoder/lightning-projects.git" 25 | }, 26 | "keywords": [ 27 | "html", 28 | "css", 29 | "javascript", 30 | "checkers", 31 | "games" 32 | ], 33 | "author": "One-Off Coder", 34 | "license": "Apache-2.0", 35 | "bugs": { 36 | "url": "https://github.com/oneoffcoder/lightning-projects/issues" 37 | }, 38 | "homepage": "https://github.com/oneoffcoder/lightning-projects#readme", 39 | "config": { 40 | "forge": { 41 | "packagerConfig": {}, 42 | "makers": [ 43 | { 44 | "name": "@electron-forge/maker-squirrel", 45 | "config": { 46 | "name": "checkers" 47 | } 48 | }, 49 | { 50 | "name": "@electron-forge/maker-zip", 51 | "platforms": [ 52 | "darwin", 53 | "linux" 54 | ] 55 | }, 56 | { 57 | "name": "@electron-forge/maker-deb", 58 | "config": {} 59 | }, 60 | { 61 | "name": "@electron-forge/maker-rpm", 62 | "config": {} 63 | } 64 | ] 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /html/colors/audio/fairy.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/colors/audio/fairy.mp3 -------------------------------------------------------------------------------- /html/colors/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Colors 10 | 12 | 44 | 45 | 46 | 47 |
48 |
49 |

Colors!

50 |

51 | Color generator 52 |

53 |
54 |

55 | Hit scramble to generate new colors 56 |

57 |

58 | 59 | Source Code 60 | 61 |

62 | 63 |
64 |
65 | 66 |
67 | 68 | 71 | 72 | 75 | 78 | 81 | 82 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /html/guessing-game/boing.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/guessing-game/boing.mp3 -------------------------------------------------------------------------------- /html/guessing-game/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Guessing Game 10 | 12 | 14 | 23 | 24 | 25 | 26 |
27 |
28 |

Guessing Game

29 |

30 | Are you able to guess which numbers the computer will generate? 31 |

32 |
33 |

34 | Try entering the numbers: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 35 |

36 |

37 | 38 | Source Code 39 | 40 |

41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | Guess 49 |
50 | 51 |
52 |
53 |
54 | 57 |
58 |
59 |
60 |
61 | 62 | 63 |
64 |
65 |
66 |
67 |
68 | 69 | 72 | 73 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Web Programming Demos 10 | 12 | 30 | 31 | 32 | 33 |
34 |
35 |

Web Programming Demos

36 |

37 | 38 | One-Off Coder 39 | 40 |

41 |

42 | "The best way to predict the future is to create it," President Abraham Lincoln. 43 |

44 |
45 |

46 | 47 | Source Code on GitHub 48 | 49 |

50 | 51 |
52 |
53 | 54 | 59 | 60 |
61 | 102 |
103 | 104 |
105 | 126 | 127 | 130 | 133 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /html/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/logo.png -------------------------------------------------------------------------------- /html/morse-code/audios/0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/0.wav -------------------------------------------------------------------------------- /html/morse-code/audios/1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/1.wav -------------------------------------------------------------------------------- /html/morse-code/audios/2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/2.wav -------------------------------------------------------------------------------- /html/morse-code/audios/3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/3.wav -------------------------------------------------------------------------------- /html/morse-code/audios/4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/4.wav -------------------------------------------------------------------------------- /html/morse-code/audios/5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/5.wav -------------------------------------------------------------------------------- /html/morse-code/audios/6.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/6.wav -------------------------------------------------------------------------------- /html/morse-code/audios/7.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/7.wav -------------------------------------------------------------------------------- /html/morse-code/audios/8.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/8.wav -------------------------------------------------------------------------------- /html/morse-code/audios/9.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/9.wav -------------------------------------------------------------------------------- /html/morse-code/audios/A.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/A.wav -------------------------------------------------------------------------------- /html/morse-code/audios/B.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/B.wav -------------------------------------------------------------------------------- /html/morse-code/audios/C.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/C.wav -------------------------------------------------------------------------------- /html/morse-code/audios/D.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/D.wav -------------------------------------------------------------------------------- /html/morse-code/audios/E.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/E.wav -------------------------------------------------------------------------------- /html/morse-code/audios/F.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/F.wav -------------------------------------------------------------------------------- /html/morse-code/audios/G.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/G.wav -------------------------------------------------------------------------------- /html/morse-code/audios/H.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/H.wav -------------------------------------------------------------------------------- /html/morse-code/audios/I.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/I.wav -------------------------------------------------------------------------------- /html/morse-code/audios/J.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/J.wav -------------------------------------------------------------------------------- /html/morse-code/audios/K.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/K.wav -------------------------------------------------------------------------------- /html/morse-code/audios/L.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/L.wav -------------------------------------------------------------------------------- /html/morse-code/audios/M.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/M.wav -------------------------------------------------------------------------------- /html/morse-code/audios/N.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/N.wav -------------------------------------------------------------------------------- /html/morse-code/audios/O.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/O.wav -------------------------------------------------------------------------------- /html/morse-code/audios/P.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/P.wav -------------------------------------------------------------------------------- /html/morse-code/audios/Q.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/Q.wav -------------------------------------------------------------------------------- /html/morse-code/audios/R.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/R.wav -------------------------------------------------------------------------------- /html/morse-code/audios/S.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/S.wav -------------------------------------------------------------------------------- /html/morse-code/audios/T.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/T.wav -------------------------------------------------------------------------------- /html/morse-code/audios/U.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/U.wav -------------------------------------------------------------------------------- /html/morse-code/audios/V.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/V.wav -------------------------------------------------------------------------------- /html/morse-code/audios/W.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/W.wav -------------------------------------------------------------------------------- /html/morse-code/audios/X.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/X.wav -------------------------------------------------------------------------------- /html/morse-code/audios/Y.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/Y.wav -------------------------------------------------------------------------------- /html/morse-code/audios/Z.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/Z.wav -------------------------------------------------------------------------------- /html/morse-code/audios/dah.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/dah.wav -------------------------------------------------------------------------------- /html/morse-code/audios/dih.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/dih.wav -------------------------------------------------------------------------------- /html/morse-code/audios/space.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/morse-code/audios/space.wav -------------------------------------------------------------------------------- /html/racing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Racing 5 | 7 | 19 | 20 | 21 | 22 | 23 |
24 |
26 | tennis ball progress bar 27 |
28 | 29 | 32 | 35 | 38 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /html/racing/tennis-ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/racing/tennis-ball.png -------------------------------------------------------------------------------- /html/rps++/data-capture/README.md: -------------------------------------------------------------------------------- 1 | # Info 2 | 3 | Use this application to acquire training data for learning rock, paper, scissor and shoot hand poses. 4 | The [Python](python) code is a [Jupyter](https://jupyter.org/) notebook that uses the training data to learn a logistic 5 | regression model to make predictions about the meaning of the hand poses. -------------------------------------------------------------------------------- /html/rps++/data-capture/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Display Webcam Stream 8 | 9 | 19 | 20 | 21 | 22 | 23 |
24 |
25 | 26 | 35 |
36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /html/rps++/data-capture/index.js: -------------------------------------------------------------------------------- 1 | let videoWidth, videoHeight, 2 | scatterGLHasInitialized = false, scatterGL, fingerLookupIndices = { 3 | thumb: [0, 1, 2, 3, 4], 4 | indexFinger: [0, 5, 6, 7, 8], 5 | middleFinger: [0, 9, 10, 11, 12], 6 | ringFinger: [0, 13, 14, 15, 16], 7 | pinky: [0, 17, 18, 19, 20] 8 | }; 9 | let model; 10 | const VIDEO_WIDTH = 640; 11 | const VIDEO_HEIGHT = 500; 12 | const mobile = false; 13 | let lastSymbol = undefined; 14 | let symbol = undefined; 15 | const data = { 16 | 'rock': [], 17 | 'paper': [], 18 | 'scissor': [], 19 | 'shoot': [] 20 | } 21 | 22 | function drawKeypoints(ctx, keypoints) { 23 | function drawPoint(ctx, y, x, r) { 24 | ctx.beginPath(); 25 | ctx.arc(x, y, r, 0, 2 * Math.PI); 26 | ctx.fill(); 27 | } 28 | 29 | function drawPath(ctx, points, closePath) { 30 | const region = new Path2D(); 31 | region.moveTo(points[0][0], points[0][1]); 32 | for (let i = 1; i < points.length; i++) { 33 | const point = points[i]; 34 | region.lineTo(point[0], point[1]); 35 | } 36 | 37 | if (closePath) { 38 | region.closePath(); 39 | } 40 | ctx.stroke(region); 41 | } 42 | 43 | const keypointsArray = keypoints; 44 | 45 | for (let i = 0; i < keypointsArray.length; i++) { 46 | const y = keypointsArray[i][0]; 47 | const x = keypointsArray[i][1]; 48 | drawPoint(ctx, x - 2, y - 2, 3); 49 | } 50 | 51 | const fingers = Object.keys(fingerLookupIndices); 52 | for (let i = 0; i < fingers.length; i++) { 53 | const finger = fingers[i]; 54 | const points = fingerLookupIndices[finger].map(idx => keypoints[idx]); 55 | drawPath(ctx, points, false); 56 | } 57 | } 58 | 59 | async function setupCamera() { 60 | if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { 61 | throw new Error( 62 | 'Browser API navigator.mediaDevices.getUserMedia not available'); 63 | } 64 | 65 | const video = document.getElementById('video'); 66 | const stream = await navigator.mediaDevices.getUserMedia({ 67 | 'audio': false, 68 | 'video': { 69 | facingMode: 'user', 70 | width: mobile ? undefined : VIDEO_WIDTH, 71 | height: mobile ? undefined : VIDEO_HEIGHT 72 | }, 73 | }); 74 | video.srcObject = stream; 75 | 76 | return new Promise((resolve) => { 77 | video.onloadedmetadata = () => { 78 | resolve(video); 79 | }; 80 | }); 81 | } 82 | 83 | async function loadVideo() { 84 | const video = await setupCamera(); 85 | video.play(); 86 | return video; 87 | } 88 | 89 | const main = 90 | async () => { 91 | model = await handpose.load(); 92 | let video; 93 | 94 | try { 95 | video = await loadVideo(); 96 | } catch (e) { 97 | let info = document.getElementById('info'); 98 | info.textContent = e.message; 99 | info.style.display = 'block'; 100 | throw e; 101 | } 102 | 103 | landmarksRealTime(video); 104 | } 105 | 106 | const landmarksRealTime = async (video) => { 107 | videoWidth = video.videoWidth; 108 | videoHeight = video.videoHeight; 109 | 110 | const canvas = document.getElementById('output'); 111 | 112 | canvas.width = videoWidth; 113 | canvas.height = videoHeight; 114 | 115 | const ctx = canvas.getContext('2d'); 116 | 117 | ctx.clearRect(0, 0, videoWidth, videoHeight); 118 | ctx.strokeStyle = 'red'; 119 | ctx.fillStyle = 'red'; 120 | 121 | ctx.translate(canvas.width, 0); 122 | ctx.scale(-1, 1); 123 | 124 | // These anchor points allow the hand pointcloud to resize according to its 125 | // position in the input. 126 | const ANCHOR_POINTS = [ 127 | [0, 0, 0], [0, -VIDEO_HEIGHT, 0], [-VIDEO_WIDTH, 0, 0], 128 | [-VIDEO_WIDTH, -VIDEO_HEIGHT, 0] 129 | ]; 130 | 131 | async function frameLandmarks() { 132 | ctx.drawImage( 133 | video, 0, 0, videoWidth, videoHeight, 0, 0, canvas.width, 134 | canvas.height); 135 | const predictions = await model.estimateHands(video); 136 | if (predictions.length > 0) { 137 | const result = predictions[0].landmarks; 138 | const annots = predictions[0].annotations; 139 | 140 | if (symbol) { 141 | const d = captureData(annots); 142 | data[symbol].push(d); 143 | 144 | console.log(d); 145 | uncapture(); 146 | } 147 | 148 | drawKeypoints(ctx, result, annots); 149 | } 150 | requestAnimationFrame(frameLandmarks); 151 | }; 152 | 153 | frameLandmarks(); 154 | }; 155 | 156 | function captureData(annots) { 157 | function getPoints(k, prefix, data) { 158 | for (let i = 0; i < annots[k].length; i++) { 159 | const colPrefix = `${prefix}${i}`; 160 | const suf = ['x', 'y', 'z']; 161 | const arr = annots[k][i]; 162 | for (let j = 0; j < arr.length; j++) { 163 | const col = `${colPrefix}${suf[j]}`; 164 | const val = arr[j]; 165 | data[col] = val; 166 | } 167 | } 168 | } 169 | 170 | const data = {}; 171 | getPoints('indexFinger', 'index', data); 172 | getPoints('middleFinger', 'middle', data); 173 | getPoints('ringFinger', 'ring', data); 174 | getPoints('pinky', 'pinky', data); 175 | getPoints('thumb', 'thumb', data); 176 | getPoints('palmBase', 'palm', data) 177 | return data; 178 | } 179 | 180 | function capture(s) { 181 | symbol = s; 182 | } 183 | 184 | function uncapture() { 185 | lastSymbol = symbol; 186 | symbol = undefined; 187 | } 188 | 189 | function undo() { 190 | data[lastSymbol].pop(); 191 | } 192 | 193 | function download() { 194 | function getMsPastEpoch() { 195 | const now = new Date() 196 | const ms = now.getTime() 197 | return ms; 198 | } 199 | 200 | const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data)); 201 | const a = document.getElementById('dlAnchor'); 202 | a.setAttribute('href', dataStr); 203 | a.setAttribute('download', `data-${getMsPastEpoch()}.json`); 204 | a.click(); 205 | } 206 | 207 | navigator.getUserMedia = navigator.getUserMedia || 208 | navigator.webkitGetUserMedia || navigator.mozGetUserMedia; 209 | 210 | tf.setBackend('webgl').then(() => main()); 211 | -------------------------------------------------------------------------------- /html/rps++/data-capture/python/README.md: -------------------------------------------------------------------------------- 1 | # Info 2 | 3 | [model.ipynb](model.ipynb) uses a Logistic regression model to learn the patterns 4 | of rock, paper, scissor and shoot hand poses. The input data are [data-adult.json](data-adult.json) and [data-kid.json](data-kid.json), which are predefined hand poses captured 5 | from an adult and child. The output is [models.json](models.json) which is a JSON 6 | file of the parameters of the predictive models for the hand poses. -------------------------------------------------------------------------------- /html/rps++/data-capture/python/models.json: -------------------------------------------------------------------------------- 1 | { 2 | "rock": { 3 | "intercept": 0.00016663445532947161, 4 | "coefs": [ 5 | 0.004493594066278487, 6 | -0.0181734867175551, 7 | 0.005816454286539876, 8 | 0.007395881203186832, 9 | -0.021052713127063166, 10 | -0.01500798715307004, 11 | 0.004911851710132168, 12 | 0.01592353320779108, 13 | -0.020577159228584666, 14 | -0.0011558048197663723, 15 | 0.0412232920550652, 16 | -0.010656181936082443, 17 | -0.003855122627525821, 18 | -0.014773240760272222, 19 | 0.007374035871422153, 20 | 0.0024225614798120804, 21 | -0.009702062079755555, 22 | -0.014249427590112267, 23 | -0.0003057471332293967, 24 | 0.039026941393299465, 25 | -0.01541200884855696, 26 | -0.012065863356455556, 27 | 0.06281924690685216, 28 | -0.0014091253058344682, 29 | -0.01037020844725474, 30 | -0.013303465539355274, 31 | 0.006422522757763716, 32 | 9.113270214539499e-05, 33 | -0.016522594930717473, 34 | -0.0076775055261058805, 35 | 0.005339043404761528, 36 | 0.00037986560511112685, 37 | -0.004796379758956194, 38 | -0.0013055819655805173, 39 | 0.00036789860342919357, 40 | 0.0060919296953114216, 41 | -0.016697270688938552, 42 | -0.012629480479088316, 43 | 0.005103006990909591, 44 | -0.0057108164913697215, 45 | -0.01781500837990077, 46 | -0.002764011794977438, 47 | 0.000993638686474716, 48 | -0.006822513530989345, 49 | 0.002355145862881284, 50 | -0.004494793169187664, 51 | -0.004395227676391269, 52 | 0.013420881218017792, 53 | 0.01696347056031915, 54 | 0.005574588046618272, 55 | -0.006677588763661525, 56 | 0.019614195257619278, 57 | -0.009642013148219714, 58 | -0.008204249974550038, 59 | 0.006696780136807361, 60 | -0.02058544268438159, 61 | -0.009153931317764789, 62 | -0.016746868102120522, 63 | -0.01361350016233158, 64 | -0.009211409400370168, 65 | 0.008726930655722803, 66 | 0.01289767965992764, 67 | -1.900009082527232e-06 68 | ] 69 | }, 70 | "paper": { 71 | "intercept": 5.835654613844104e-05, 72 | "coefs": [ 73 | -0.009139454197085665, 74 | 0.008565854879610004, 75 | -0.009220224313312328, 76 | -0.0061087763642032845, 77 | 0.020272390829743737, 78 | -0.003113458455537707, 79 | -0.0010165469320500434, 80 | 0.0153752347350819, 81 | -0.005444796133333202, 82 | 0.004895262228446878, 83 | 0.0150373670809992, 84 | -0.011385191741365612, 85 | 0.002277442850461132, 86 | 0.013999083467625375, 87 | -0.008377951690502696, 88 | 0.0002909320432572904, 89 | 0.021338669154711803, 90 | 0.0075584635430500785, 91 | -0.0028628258163235086, 92 | 0.019912440133490538, 93 | 0.0092146553243537, 94 | -0.004982543788312038, 95 | 0.02047433676724552, 96 | 0.009105113657712478, 97 | 0.01612396792331375, 98 | 0.017502672063936586, 99 | -0.008879149875499452, 100 | 0.0034397324261617, 101 | 0.02993888816065672, 102 | 0.01002364254607002, 103 | -0.0192768672707338, 104 | -0.028357666778241034, 105 | 0.00908904965885131, 106 | -0.03745124838371773, 107 | -0.08011167692339737, 108 | 0.004034240150638302, 109 | 0.0357015518471651, 110 | 0.01882968995998238, 111 | -0.012186470212627228, 112 | 0.007317792487834422, 113 | 0.024292966056803138, 114 | 0.002029382963444806, 115 | -0.029642505831290692, 116 | -0.01992560501590033, 117 | 0.00026012646555537405, 118 | -0.06269194140352884, 119 | -0.0697427236285067, 120 | -0.002148014770746275, 121 | 0.004291594768267101, 122 | -0.019145512232655405, 123 | -0.007843496625722585, 124 | -0.0023416961603515613, 125 | -0.007879927891031702, 126 | -0.012084825739039223, 127 | 0.021840304252015195, 128 | 0.009127455787217301, 129 | -0.016890576048913638, 130 | 0.06518071828045109, 131 | 0.020193290271455274, 132 | -0.02236403004439325, 133 | 0.018623261216544076, 134 | -0.023804949855688966, 135 | 6.967241066564688e-07 136 | ] 137 | }, 138 | "scissor": { 139 | "intercept": 0.0004732872275962553, 140 | "coefs": [ 141 | -0.0022927351464847407, 142 | -0.008291005042016403, 143 | 0.013063651569532497, 144 | 0.008306041163775686, 145 | -0.0168495062459517, 146 | 0.015355057324314591, 147 | 0.016632688833974545, 148 | -0.02721764285188774, 149 | 0.019764708150699563, 150 | 0.025465050630419154, 151 | -0.03201631053989809, 152 | 0.025126840770415684, 153 | -0.002140330433519718, 154 | -0.015510554983485615, 155 | 0.00592426548203055, 156 | -0.007788995147753785, 157 | -0.03278973394550188, 158 | 0.014790324595070884, 159 | -0.006494150432250139, 160 | -0.0390125559824367, 161 | 0.023216987984591, 162 | -0.009516242488853837, 163 | -0.042355379867691056, 164 | 0.030910460382777526, 165 | -0.0002314933915167194, 166 | -0.013151950865890716, 167 | -0.0019424587176279974, 168 | 0.020818211668454926, 169 | -0.0037853385338370085, 170 | -0.00845190221605843, 171 | 0.016618268048852573, 172 | 0.019939316896806752, 173 | -0.0014599576811318647, 174 | -0.0015251292134849778, 175 | 0.03635174397354812, 176 | 0.0065296516414917365, 177 | 0.014765491710761568, 178 | -0.011932269808963412, 179 | -0.007788393562453929, 180 | 0.041753228684391124, 181 | 0.007682776739393862, 182 | -0.01463858388201525, 183 | 0.044816020016839854, 184 | 0.029092915818816435, 185 | -0.008374711352544906, 186 | 0.03583325046722424, 187 | 0.050148594157042044, 188 | -0.0019546879721942245, 189 | -0.016808812679485002, 190 | 0.010747326111204476, 191 | 0.006990860564231347, 192 | -0.024584566230194588, 193 | 0.017862421854510074, 194 | 0.0024082511288380476, 195 | -0.05018490922331198, 196 | 0.02574793067828618, 197 | -0.004993774913726719, 198 | -0.0947939127729616, 199 | 0.02119667381109406, 200 | -0.007245178629343176, 201 | -0.013542072920946235, 202 | 0.020731893133612605, 203 | -1.8836892663767876e-07 204 | ] 205 | }, 206 | "shoot": { 207 | "intercept": -0.0006982782290691921, 208 | "coefs": [ 209 | 0.006938595276950665, 210 | 0.01789863687963746, 211 | -0.009659881542736722, 212 | -0.009593146003105917, 213 | 0.01762982854302785, 214 | 0.002766388284322471, 215 | -0.020527993612413968, 216 | -0.00408112509116473, 217 | 0.006257247211252607, 218 | -0.02920450803946343, 219 | -0.02424434859629662, 220 | -0.0030854670929253607, 221 | 0.003718010210293204, 222 | 0.0162847122758126, 223 | -0.004920349662920951, 224 | 0.005075501624398148, 225 | 0.021153126870311477, 226 | -0.008099360547971076, 227 | 0.009662723381514434, 228 | -0.019926825544509613, 229 | -0.017019634460342235, 230 | 0.026564649633328347, 231 | -0.04093820380650239, 232 | -0.03860644873460304, 233 | -0.005522266084787265, 234 | 0.008952744340975578, 235 | 0.004399085835395952, 236 | -0.024349076796996005, 237 | -0.009630954696388897, 238 | 0.006105765196142563, 239 | -0.0026804441831190435, 240 | 0.008038484276033462, 241 | -0.002832712218712842, 242 | 0.040281959562536676, 243 | 0.04339203434612915, 244 | -0.016655821487390313, 245 | -0.03376977286919372, 246 | 0.005732060327706987, 247 | 0.01487185678420943, 248 | -0.04336020468104305, 249 | -0.014160734416633292, 250 | 0.015373212713596218, 251 | -0.01616715287221629, 252 | -0.002344797272268752, 253 | 0.005759439024160596, 254 | 0.03135348410528389, 255 | 0.02398935714751267, 256 | -0.009318178475024568, 257 | -0.004446252649437305, 258 | 0.002823598074363506, 259 | 0.007530224825156777, 260 | 0.007312067132532629, 261 | -0.00034048081567744545, 262 | 0.017880824584760594, 263 | 0.02164782483405883, 264 | -0.0142899437814946, 265 | 0.031038282280424583, 266 | 0.04636006259415263, 267 | -0.02777646392056524, 268 | 0.03882061807413296, 269 | -0.013808118951585874, 270 | -0.009824622938341668, 271 | 1.3916539025098639e-06 272 | ] 273 | } 274 | } -------------------------------------------------------------------------------- /html/rps++/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | Rock, Paper, Scissor++ 15 | 68 | 69 | 70 | 71 |
72 |
73 |

Rock Paper Scissor++

74 |

75 | Use your right hand to play Rock Paper Scissor (RPS)! 76 |

77 |
78 |

79 | Using artificial intelligence (deep learning) to recognize your hand pose to play RPS 80 |

81 |

82 | 83 | Source Code 84 | 85 |

86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | 98 | 108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | 117 | 119 | 121 | 122 |
123 |
124 |
Your Score
125 |

126 | 0 127 |
128 | 129 |

130 |
ready ...
131 |
132 |
133 |
134 |
135 |
136 |
137 | 139 | 141 | 142 |
143 |
144 |
CPU Score
145 |

146 | 0 147 |
148 | 149 |

150 |
ready ...
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 | 160 | 163 | 166 | 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /html/rps-game/audio/lose.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/rps-game/audio/lose.mp3 -------------------------------------------------------------------------------- /html/rps-game/audio/tie.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/rps-game/audio/tie.mp3 -------------------------------------------------------------------------------- /html/rps-game/audio/win.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/rps-game/audio/win.mp3 -------------------------------------------------------------------------------- /html/rps-game/images/paper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/rps-game/images/paper.png -------------------------------------------------------------------------------- /html/rps-game/images/rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/rps-game/images/rock.png -------------------------------------------------------------------------------- /html/rps-game/images/scissor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/rps-game/images/scissor.png -------------------------------------------------------------------------------- /html/rps-game/images/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/rps-game/images/start.png -------------------------------------------------------------------------------- /html/rps-game/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Rock, Paper, Scissor! 11 | 12 | 14 | 59 | 60 | 61 | 62 | 63 |
64 |
65 |

Rock, Paper, Scissor Shoot!

66 |

67 | Play against the computer 68 |

69 |
70 |

71 | You will have 15 seconds to make a decision, or the computer wins by default 72 |

73 |

74 | 75 | Source Code 76 | 77 |

78 |
79 |
80 | 81 | 82 | 83 | 86 | 89 | 90 | 91 | 96 | 101 | 102 | 103 | 112 | 115 | 116 | 117 |
84 | Player Score: 85 | 87 | Computer Score: 88 |
92 |
93 | 94 |
95 |
97 |
98 | 99 |
100 |
104 | 106 | 108 | 110 | 111 | 113 |
114 |
118 | 119 | 122 | 125 | 128 | 129 | 132 | 135 | 138 | 139 | 293 | 294 | 295 | -------------------------------------------------------------------------------- /html/sign-language/images/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/a.png -------------------------------------------------------------------------------- /html/sign-language/images/b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/b.png -------------------------------------------------------------------------------- /html/sign-language/images/c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/c.png -------------------------------------------------------------------------------- /html/sign-language/images/d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/d.png -------------------------------------------------------------------------------- /html/sign-language/images/e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/e.png -------------------------------------------------------------------------------- /html/sign-language/images/f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/f.png -------------------------------------------------------------------------------- /html/sign-language/images/g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/g.png -------------------------------------------------------------------------------- /html/sign-language/images/h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/h.png -------------------------------------------------------------------------------- /html/sign-language/images/i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/i.png -------------------------------------------------------------------------------- /html/sign-language/images/j.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/j.png -------------------------------------------------------------------------------- /html/sign-language/images/k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/k.png -------------------------------------------------------------------------------- /html/sign-language/images/l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/l.png -------------------------------------------------------------------------------- /html/sign-language/images/m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/m.png -------------------------------------------------------------------------------- /html/sign-language/images/n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/n.png -------------------------------------------------------------------------------- /html/sign-language/images/o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/o.png -------------------------------------------------------------------------------- /html/sign-language/images/p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/p.png -------------------------------------------------------------------------------- /html/sign-language/images/q.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/q.png -------------------------------------------------------------------------------- /html/sign-language/images/r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/r.png -------------------------------------------------------------------------------- /html/sign-language/images/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/s.png -------------------------------------------------------------------------------- /html/sign-language/images/t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/t.png -------------------------------------------------------------------------------- /html/sign-language/images/u.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/u.png -------------------------------------------------------------------------------- /html/sign-language/images/v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/v.png -------------------------------------------------------------------------------- /html/sign-language/images/w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/w.png -------------------------------------------------------------------------------- /html/sign-language/images/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/x.png -------------------------------------------------------------------------------- /html/sign-language/images/y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/y.png -------------------------------------------------------------------------------- /html/sign-language/images/z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/sign-language/images/z.png -------------------------------------------------------------------------------- /html/slot-machine-game/boing.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/slot-machine-game/boing.mp3 -------------------------------------------------------------------------------- /html/slot-machine-game/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Slot Machine! 10 | 12 | 13 | 46 | 47 | 48 | 49 |
50 |
51 |

Play Slot!

52 |

53 | Slot machine simulator 54 |

55 |

56 | 57 | Source Code 58 | 59 |

60 |
61 |

62 | Hit lever button to start 63 |

64 |
65 |
66 |
67 | 68 |
69 | 70 | 71 | 72 | 75 | 78 | 81 | 82 | 83 |
73 | - 74 | 76 | - 77 | 79 | - 80 |
84 |
85 | You Won! 86 |
87 | 90 | 91 | 94 | 97 | 100 | 101 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /html/solar-system/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Solar System 10 | 61 | 62 | 63 | 64 | 65 |
66 |

Solar System

67 |
68 |
69 | 70 | 71 | 72 | Sun 73 | 74 | 75 | 76 | 77 | Mercury 78 | 79 | 80 | 81 | Venus 82 | 83 | 84 | 85 | earth 86 | 87 | 88 | 89 | Mars 90 | 91 | 92 | 93 | Jupiter 94 | 95 | 96 | 97 | Saturn 98 | 99 | 100 | 101 | Uranus 102 | 103 | 104 | 105 | Neptune 106 | 107 | 108 | 109 | Pluto 110 | 111 | 112 | 113 | 115 | 116 | 117 | 119 | 120 | 121 | 123 | 124 | 125 | 127 | 128 | 129 | 131 | 132 | 133 | 135 | 136 | 137 | 139 | 140 | 141 | 143 | 144 | 145 | 147 | 148 | 149 |
150 | 291 | 292 | 293 | -------------------------------------------------------------------------------- /html/tic-tac-toe/audio/fairy.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/html/tic-tac-toe/audio/fairy.mp3 -------------------------------------------------------------------------------- /html/tic-tac-toe/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Tic-Tac-Toe 10 | 12 | 44 | 45 | 46 | 47 |
48 |
49 |

Tic-Tac-Toe!

50 |

51 | Classic Tic-Tac-Toe game; play against the computer 52 |

53 |

54 | 55 | Source Code 56 | 57 |

58 |
59 |

60 | Hit restart at any time to start over 61 |

62 | 63 |
64 |
65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 |
   
   
   
84 |
85 | 86 | 87 | 90 | 91 | 263 | 264 | 265 | -------------------------------------------------------------------------------- /java/greenfoot/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | doc/ -------------------------------------------------------------------------------- /java/greenfoot/README.md: -------------------------------------------------------------------------------- 1 | ![One-Off Coder Logo](../logo.png "One-Off Coder") 2 | 3 | # Projects 4 | 5 | * [bump-babies](bump-babies): fish eating baby snacks 6 | * [bee-vs-bug](bee-vs-bug): get away from the ladybug 7 | * [race-car](race-car): avoid oncoming traffic -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/Bee.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=Bee 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ Bee\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params= 5 | comment1.target=void\ act() 6 | comment1.text=\n\ Act\ -\ do\ whatever\ the\ Bee\ wants\ to\ do.\ This\ method\ is\ called\ whenever\n\ the\ 'Act'\ or\ 'Run'\ button\ gets\ pressed\ in\ the\ environment.\n 7 | numComments=2 8 | -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/Bee.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | 3 | /** 4 | * Write a description of class Bee here. 5 | * 6 | * @author (your name) 7 | * @version (a version number or a date) 8 | */ 9 | public class Bee extends Actor 10 | { 11 | static int x, y; 12 | /** 13 | * Act - do whatever the Bee wants to do. This method is called whenever 14 | * the 'Act' or 'Run' button gets pressed in the environment. 15 | */ 16 | public void act() 17 | { 18 | // Add your action code here. 19 | if (Greenfoot.isKeyDown("w") || Greenfoot.isKeyDown("up")) { 20 | setRotation(-90); 21 | move(5); 22 | } else if (Greenfoot.isKeyDown("s") || Greenfoot.isKeyDown("down")) { 23 | setRotation(90); 24 | move(5); 25 | } else if (Greenfoot.isKeyDown("a") || Greenfoot.isKeyDown("left")) { 26 | setRotation(180); 27 | move(5); 28 | } else if (Greenfoot.isKeyDown("d") || Greenfoot.isKeyDown("right")) { 29 | setRotation(0); 30 | move(5); 31 | } 32 | this.x = getX(); 33 | this.y = getY(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/Bug.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=Bug 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ Bug\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params= 5 | comment1.target=void\ act() 6 | comment1.text=\n\ Act\ -\ do\ whatever\ the\ Bug\ wants\ to\ do.\ This\ method\ is\ called\ whenever\n\ the\ 'Act'\ or\ 'Run'\ button\ gets\ pressed\ in\ the\ environment.\n 7 | comment2.params= 8 | comment2.target=void\ movement() 9 | numComments=3 10 | -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/Bug.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | 3 | /** 4 | * Write a description of class Bug here. 5 | * 6 | * @author (your name) 7 | * @version (a version number or a date) 8 | */ 9 | public class Bug extends Actor 10 | { 11 | GreenfootSound sound = new GreenfootSound("ahhh.wav"); 12 | /** 13 | * Act - do whatever the Bug wants to do. This method is called whenever 14 | * the 'Act' or 'Run' button gets pressed in the environment. 15 | */ 16 | public void act() 17 | { 18 | // Add your action code here. 19 | movement(); 20 | if (isTouching(Bee.class)) { 21 | sound.play(); 22 | removeTouching(Bee.class); 23 | Greenfoot.stop(); 24 | } 25 | } 26 | 27 | public void movement() { 28 | int dx = 2; 29 | int dy = 2; 30 | 31 | if (getX() < Bee.x) { 32 | setRotation(0); 33 | move((int)(Math.random() * dx) + 1); 34 | } else if (getX() > Bee.x) { 35 | setRotation(180); 36 | move((int)(Math.random() * dx) + 1); 37 | } 38 | if (getY() < Bee.y) { 39 | setRotation(90); 40 | move((int)(Math.random() * dy) + 1); 41 | } else if (getY() > Bee.y) { 42 | setRotation(270); 43 | move((int)(Math.random() * dy) + 1); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/MyWorld.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=MyWorld 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ MyWorld\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params= 5 | comment1.target=MyWorld() 6 | comment1.text=\n\ Constructor\ for\ objects\ of\ class\ MyWorld.\n\ \n 7 | comment2.params= 8 | comment2.target=void\ prepare() 9 | comment2.text=\n\ Prepare\ the\ world\ for\ the\ start\ of\ the\ program.\n\ That\ is\:\ create\ the\ initial\ objects\ and\ add\ them\ to\ the\ world.\n 10 | numComments=3 11 | -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/MyWorld.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | 3 | /** 4 | * Write a description of class MyWorld here. 5 | * 6 | * @author (your name) 7 | * @version (a version number or a date) 8 | */ 9 | public class MyWorld extends World 10 | { 11 | Bee bee; 12 | Bug bug; 13 | /** 14 | * Constructor for objects of class MyWorld. 15 | * 16 | */ 17 | public MyWorld() 18 | { 19 | // Create a new world with 600x400 cells with a cell size of 1x1 pixels. 20 | super(600, 400, 1); 21 | bee = new Bee(); 22 | bug = new Bug(); 23 | 24 | addObject(bee, 15, 15); 25 | addObject(bug, getWidth() / 2, getHeight() / 2); 26 | prepare(); 27 | } 28 | 29 | /** 30 | * Prepare the world for the start of the program. 31 | * That is: create the initial objects and add them to the world. 32 | */ 33 | private void prepare() 34 | { 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/README.TXT: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | This is the project README file. Here, you should describe your project. 3 | Tell the reader (someone who does not know anything about this project) 4 | all he/she needs to know. The comments should usually include at least: 5 | ------------------------------------------------------------------------ 6 | 7 | PROJECT TITLE: 8 | PURPOSE OF PROJECT: 9 | VERSION or DATE: 10 | HOW TO START THIS PROJECT: 11 | AUTHORS: 12 | USER INSTRUCTIONS: 13 | -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/images/bee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/java/greenfoot/bee-vs-bug/images/bee.png -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/images/fingerprint.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/java/greenfoot/bee-vs-bug/images/fingerprint.jpg -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/images/ladybug_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/java/greenfoot/bee-vs-bug/images/ladybug_02.png -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/project.greenfoot: -------------------------------------------------------------------------------- 1 | #Greenfoot project file 2 | class.Bee.image=bee.png 3 | class.Bug.image=ladybug_02.png 4 | class.MyWorld.image=fingerprint.jpg 5 | dependency1.from=MyWorld 6 | dependency1.to=Bee 7 | dependency1.type=UsesDependency 8 | dependency2.from=MyWorld 9 | dependency2.to=Bug 10 | dependency2.type=UsesDependency 11 | dependency3.from=Bug 12 | dependency3.to=Bee 13 | dependency3.type=UsesDependency 14 | editor.fx.0.height=0 15 | editor.fx.0.width=0 16 | editor.fx.0.x=0 17 | editor.fx.0.y=0 18 | height=878 19 | package.numDependencies=3 20 | package.numTargets=3 21 | project.charset=UTF-8 22 | publish.hasSource=false 23 | publish.locked=true 24 | publish.longDesc= 25 | publish.shortDesc= 26 | publish.tags= 27 | publish.title= 28 | publish.url= 29 | readme.height=58 30 | readme.name=@README 31 | readme.width=47 32 | readme.x=10 33 | readme.y=10 34 | simulation.speed=50 35 | target1.height=50 36 | target1.name=Bee 37 | target1.showInterface=false 38 | target1.type=ClassTarget 39 | target1.width=80 40 | target1.x=0 41 | target1.y=0 42 | target2.height=50 43 | target2.name=Bug 44 | target2.showInterface=false 45 | target2.type=ClassTarget 46 | target2.width=80 47 | target2.x=0 48 | target2.y=0 49 | target3.height=50 50 | target3.name=MyWorld 51 | target3.showInterface=false 52 | target3.type=ClassTarget 53 | target3.width=80 54 | target3.x=0 55 | target3.y=0 56 | version=3.0.0 57 | width=1064 58 | world.lastInstantiated=MyWorld 59 | xPosition=1169 60 | yPosition=441 61 | -------------------------------------------------------------------------------- /java/greenfoot/bee-vs-bug/sounds/ahhh.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/java/greenfoot/bee-vs-bug/sounds/ahhh.wav -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/Baby.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=Baby 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ Baby\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params=id\ x\ y 5 | comment1.target=Baby(int,\ int,\ int) 6 | comment2.params= 7 | comment2.target=int\ getId() 8 | comment3.params= 9 | comment3.target=int\ getX() 10 | comment4.params= 11 | comment4.target=int\ getY() 12 | comment5.params= 13 | comment5.target=void\ act() 14 | comment5.text=\n\ Act\ -\ do\ whatever\ the\ Baby\ wants\ to\ do.\ This\ method\ is\ called\ whenever\n\ the\ 'Act'\ or\ 'Run'\ button\ gets\ pressed\ in\ the\ environment.\n 15 | numComments=6 16 | -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/Baby.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | import java.util.Random; 3 | 4 | /** 5 | * Write a description of class Baby here. 6 | * 7 | * @author (your name) 8 | * @version (a version number or a date) 9 | */ 10 | public class Baby extends Actor 11 | { 12 | private static final Random _rand = new Random(37L); 13 | private int id; 14 | private int x; 15 | private int y; 16 | private int xDelta; 17 | private int yDelta; 18 | 19 | public Baby(int id, int x, int y) { 20 | this.id = id; 21 | this.x = x; 22 | this.y = y; 23 | this.xDelta = _rand.nextDouble() < 0.5d ? -1 : 1; 24 | this.yDelta = _rand.nextDouble() < 0.5d ? -1 : 1; 25 | } 26 | 27 | public int getId() { return id; } 28 | public int getX() { return x; } 29 | public int getY() { return y; } 30 | /** 31 | * Act - do whatever the Baby wants to do. This method is called whenever 32 | * the 'Act' or 'Run' button gets pressed in the environment. 33 | */ 34 | public void act() { 35 | x = x + xDelta; 36 | y = y + yDelta; 37 | 38 | setLocation(x, y); 39 | 40 | if (x == 0 || x == getWorld().getWidth()) { 41 | xDelta = xDelta * -1; 42 | } 43 | if (y == 0 || y == getWorld().getHeight()) { 44 | yDelta = yDelta * -1; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/Fish.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=Fish 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ Fish\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params= 5 | comment1.target=void\ act() 6 | comment1.text=\n\ Act\ -\ do\ whatever\ the\ Fish\ wants\ to\ do.\ This\ method\ is\ called\ whenever\n\ the\ 'Act'\ or\ 'Run'\ button\ gets\ pressed\ in\ the\ environment.\n 7 | comment2.params= 8 | comment2.target=void\ babyHitDetection() 9 | numComments=3 10 | -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/Fish.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | 3 | /** 4 | * Write a description of class Fish here. 5 | * 6 | * @author (your name) 7 | * @version (a version number or a date) 8 | */ 9 | public class Fish extends Actor 10 | { 11 | /** 12 | * Act - do whatever the Fish wants to do. This method is called whenever 13 | * the 'Act' or 'Run' button gets pressed in the environment. 14 | */ 15 | public void act() 16 | { 17 | try { 18 | MouseInfo mouseInfo = Greenfoot.getMouseInfo(); 19 | if (null != mouseInfo) { 20 | setLocation(mouseInfo.getX(), mouseInfo.getY()); 21 | } 22 | } catch (Exception e) { 23 | // swallow exception 24 | } 25 | 26 | babyHitDetection(); 27 | } 28 | 29 | public void babyHitDetection() { 30 | Actor actor = getOneIntersectingObject(Baby.class); 31 | if (actor != null) { 32 | Baby baby = (Baby) actor; 33 | ((MyWorld)getWorld()).remove(actor); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/MyWorld.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=MyWorld 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ MyWorld\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params= 5 | comment1.target=MyWorld() 6 | comment1.text=\n\ Constructor\ for\ objects\ of\ class\ MyWorld.\n\ \n 7 | comment2.params= 8 | comment2.target=Baby\ nextBaby() 9 | comment3.params=actor 10 | comment3.target=void\ remove(greenfoot.Actor) 11 | numComments=4 12 | -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/MyWorld.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | import java.util.List; 3 | import java.util.ArrayList; 4 | import java.util.Random; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | 7 | /** 8 | * Write a description of class MyWorld here. 9 | * 10 | * @author (your name) 11 | * @version (a version number or a date) 12 | */ 13 | public class MyWorld extends World 14 | { 15 | private static final Random _rand = new Random(37L); 16 | private static final AtomicInteger _babyCounter = new AtomicInteger(0); 17 | 18 | Fish fish; 19 | List babies; 20 | final int numBabies = 20; 21 | /** 22 | * Constructor for objects of class MyWorld. 23 | * 24 | */ 25 | public MyWorld() 26 | { 27 | // Create a new world with 600x400 cells with a cell size of 1x1 pixels. 28 | super(600, 400, 1); 29 | 30 | fish = new Fish(); 31 | addObject(fish, getWidth() / 2, getHeight() / 2); 32 | 33 | babies = new ArrayList(); 34 | for (int i = 0; i < numBabies; i++) { 35 | Baby baby = nextBaby(); 36 | babies.add(baby); 37 | addObject(baby, baby.getX(), baby.getY()); 38 | } 39 | 40 | } 41 | 42 | private Baby nextBaby() { 43 | int x = _rand.nextInt(getWidth()); 44 | int y = _rand.nextInt(getHeight()); 45 | Baby baby = new Baby(_babyCounter.getAndIncrement(), x, y); 46 | System.out.println(baby.getId()); 47 | return baby; 48 | } 49 | 50 | public void remove(Actor actor) { 51 | babies.remove(actor); 52 | removeObject(actor); 53 | 54 | int threshold = _rand.nextInt(100) + 1; 55 | if (babies.size() <= threshold) { 56 | int numToAdd = _rand.nextInt(5) + 1; 57 | for (int i = 0; i < numToAdd; i++) { 58 | Baby baby = nextBaby(); 59 | babies.add(baby); 60 | addObject(baby, baby.getX(), baby.getY()); 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/README.TXT: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | This is the project README file. Here, you should describe your project. 3 | Tell the reader (someone who does not know anything about this project) 4 | all he/she needs to know. The comments should usually include at least: 5 | ------------------------------------------------------------------------ 6 | 7 | PROJECT TITLE: 8 | PURPOSE OF PROJECT: 9 | VERSION or DATE: 10 | HOW TO START THIS PROJECT: 11 | AUTHORS: 12 | USER INSTRUCTIONS: 13 | -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/images/baby2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/java/greenfoot/bump-babies/images/baby2.png -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/images/bluerock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/java/greenfoot/bump-babies/images/bluerock.jpg -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/images/fish3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/java/greenfoot/bump-babies/images/fish3.png -------------------------------------------------------------------------------- /java/greenfoot/bump-babies/project.greenfoot: -------------------------------------------------------------------------------- 1 | #Greenfoot project file 2 | class.Baby.image=baby2.png 3 | class.Fish.image=fish3.png 4 | class.MyWorld.image=bluerock.jpg 5 | dependency1.from=MyWorld 6 | dependency1.to=Fish 7 | dependency1.type=UsesDependency 8 | dependency2.from=MyWorld 9 | dependency2.to=Baby 10 | dependency2.type=UsesDependency 11 | dependency3.from=Fish 12 | dependency3.to=Baby 13 | dependency3.type=UsesDependency 14 | dependency4.from=Fish 15 | dependency4.to=MyWorld 16 | dependency4.type=UsesDependency 17 | editor.fx.0.height=0 18 | editor.fx.0.width=0 19 | editor.fx.0.x=0 20 | editor.fx.0.y=0 21 | height=847 22 | package.numDependencies=4 23 | package.numTargets=3 24 | project.charset=UTF-8 25 | publish.hasSource=false 26 | publish.locked=true 27 | publish.longDesc= 28 | publish.shortDesc= 29 | publish.tags= 30 | publish.title= 31 | publish.url= 32 | readme.height=58 33 | readme.name=@README 34 | readme.width=47 35 | readme.x=10 36 | readme.y=10 37 | simulation.speed=58 38 | target1.height=50 39 | target1.name=Baby 40 | target1.showInterface=false 41 | target1.type=ClassTarget 42 | target1.width=80 43 | target1.x=0 44 | target1.y=0 45 | target2.height=50 46 | target2.name=Fish 47 | target2.showInterface=false 48 | target2.type=ClassTarget 49 | target2.width=80 50 | target2.x=0 51 | target2.y=0 52 | target3.height=50 53 | target3.name=MyWorld 54 | target3.showInterface=false 55 | target3.type=ClassTarget 56 | target3.width=80 57 | target3.x=0 58 | target3.y=0 59 | version=3.0.0 60 | width=1142 61 | world.lastInstantiated=MyWorld 62 | xPosition=1385 63 | yPosition=610 64 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/GreenCar.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=GreenCar 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ GreenCar\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params=world 5 | comment1.target=GreenCar(greenfoot.World) 6 | comment2.params= 7 | comment2.target=void\ act() 8 | comment2.text=\n\ Act\ -\ do\ whatever\ the\ GreenCar\ wants\ to\ do.\ This\ method\ is\ called\ whenever\n\ the\ 'Act'\ or\ 'Run'\ button\ gets\ pressed\ in\ the\ environment.\n 9 | comment3.params= 10 | comment3.target=void\ checkCollision() 11 | comment4.params= 12 | comment4.target=int\ getX() 13 | comment5.params= 14 | comment5.target=int\ getY() 15 | numComments=6 16 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/GreenCar.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | 3 | /** 4 | * Write a description of class GreenCar here. 5 | * 6 | * @author (your name) 7 | * @version (a version number or a date) 8 | */ 9 | public class GreenCar extends Actor 10 | { 11 | private int x; 12 | private int y; 13 | 14 | public GreenCar(World world) { 15 | int wWidth = world.getWidth(); 16 | int wHeight = world.getHeight(); 17 | int iWidth = getImage().getWidth(); 18 | int iHeight = getImage().getHeight(); 19 | 20 | x = (wWidth / 2) - (iWidth / 2); 21 | y = wHeight - (iHeight / 2); 22 | } 23 | /** 24 | * Act - do whatever the GreenCar wants to do. This method is called whenever 25 | * the 'Act' or 'Run' button gets pressed in the environment. 26 | */ 27 | public void act() 28 | { 29 | if (Greenfoot.isKeyDown("left")) { 30 | x = x - 1; 31 | } else if (Greenfoot.isKeyDown("right")) { 32 | x = x + 1; 33 | } else if (Greenfoot.isKeyDown("up")) { 34 | y = y - 1; 35 | } else if (Greenfoot.isKeyDown("down")) { 36 | y = y + 1; 37 | } 38 | setLocation(x, y); 39 | checkCollision(); 40 | } 41 | 42 | public void checkCollision() { 43 | RedCar redCar = (RedCar) getOneIntersectingObject(RedCar.class); 44 | if (null != redCar) { 45 | Greenfoot.stop(); 46 | } 47 | } 48 | 49 | public int getX() { return x; } 50 | public int getY() { return y; } 51 | } 52 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/MyWorld.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=MyWorld 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ MyWorld\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params= 5 | comment1.target=MyWorld() 6 | comment1.text=\n\ Constructor\ for\ objects\ of\ class\ MyWorld.\n\ \n 7 | comment2.params= 8 | comment2.target=void\ act() 9 | comment3.params= 10 | comment3.target=void\ addRedCar() 11 | comment4.params=redCar 12 | comment4.target=void\ removeRedCar(RedCar) 13 | comment5.params= 14 | comment5.target=long\ getScore() 15 | comment6.params= 16 | comment6.target=int\ getLevel() 17 | comment7.params= 18 | comment7.target=int\ getRandomXPosition() 19 | comment8.params= 20 | comment8.target=java.util.List\ getXPositions() 21 | numComments=9 22 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/MyWorld.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | import java.util.List; 3 | import java.util.ArrayList; 4 | import java.util.Random; 5 | 6 | /** 7 | * Write a description of class MyWorld here. 8 | * 9 | * @author (your name) 10 | * @version (a version number or a date) 11 | */ 12 | public class MyWorld extends World 13 | { 14 | private static final Random _rand = new Random(37L); 15 | GreenCar greenCar; 16 | List redCars; 17 | List xPositions; 18 | List xHistory; 19 | long numRedCarsAdded = 0L; 20 | int maxRedCars = 5; 21 | /** 22 | * Constructor for objects of class MyWorld. 23 | * 24 | */ 25 | public MyWorld() 26 | { 27 | // Create a new world with 600x400 cells with a cell size of 1x1 pixels. 28 | super(600, 600, 1); 29 | Greenfoot.setSpeed(65); 30 | 31 | xHistory = new ArrayList<>(); 32 | xPositions = getXPositions(); 33 | 34 | greenCar = new GreenCar(this); 35 | redCars = new ArrayList<>(); 36 | 37 | addObject(greenCar, greenCar.getX(), greenCar.getY()); 38 | addObject(new Score(this), 85, 10); 39 | addRedCar(); 40 | } 41 | 42 | public void act() { 43 | super.act(); 44 | if (redCars.size() < maxRedCars) { 45 | double p = _rand.nextDouble(); 46 | double t = (numRedCarsAdded < 5) ? 0.995d : 0.99d; 47 | if (p > t) { 48 | addRedCar(); 49 | } 50 | } 51 | } 52 | 53 | private void addRedCar() { 54 | RedCar redCar = new RedCar(getRandomXPosition()); 55 | redCars.add(redCar); 56 | addObject(redCar, redCar.getX(), redCar.getY()); 57 | numRedCarsAdded += 1L; 58 | if (numRedCarsAdded % 50 == 0) { 59 | maxRedCars += 1; 60 | } 61 | } 62 | 63 | public void removeRedCar(RedCar redCar) { 64 | redCars.remove(redCar); 65 | removeObject(redCar); 66 | } 67 | 68 | public long getScore() { return numRedCarsAdded; } 69 | 70 | public int getLevel() { return maxRedCars - 5 + 1; } 71 | 72 | private int getRandomXPosition() { 73 | int numPositions = xPositions.size(); 74 | int index = -1; 75 | while (true) { 76 | index = _rand.nextInt(numPositions); 77 | 78 | if (!xHistory.contains(index)) { 79 | xHistory.add(index); 80 | break; 81 | } 82 | } 83 | 84 | if (xHistory.size() > 5) { 85 | xHistory.remove(0); 86 | } 87 | 88 | return xPositions.get(index); 89 | } 90 | 91 | private List getXPositions() { 92 | int carWidth = (new RedCar()).getWidth(); 93 | int gameWidth = getWidth(); 94 | List positions = new ArrayList<>(); 95 | for (int i = 5; i < gameWidth; i += carWidth) { 96 | positions.add(i); 97 | } 98 | return positions; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/README.TXT: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | This is the project README file. Here, you should describe your project. 3 | Tell the reader (someone who does not know anything about this project) 4 | all he/she needs to know. The comments should usually include at least: 5 | ------------------------------------------------------------------------ 6 | 7 | PROJECT TITLE: 8 | PURPOSE OF PROJECT: 9 | VERSION or DATE: 10 | HOW TO START THIS PROJECT: 11 | AUTHORS: 12 | USER INSTRUCTIONS: 13 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/RedCar.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=RedCar 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ RedCar\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params= 5 | comment1.target=RedCar() 6 | comment2.params=x 7 | comment2.target=RedCar(int) 8 | comment3.params=world 9 | comment3.target=RedCar(greenfoot.World) 10 | comment4.params= 11 | comment4.target=void\ act() 12 | comment4.text=\n\ Act\ -\ do\ whatever\ the\ RedCar\ wants\ to\ do.\ This\ method\ is\ called\ whenever\n\ the\ 'Act'\ or\ 'Run'\ button\ gets\ pressed\ in\ the\ environment.\n 13 | comment5.params= 14 | comment5.target=int\ getX() 15 | comment6.params= 16 | comment6.target=int\ getY() 17 | comment7.params= 18 | comment7.target=int\ getWidth() 19 | comment8.params= 20 | comment8.target=int\ getHeight() 21 | numComments=9 22 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/RedCar.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | import java.util.Random; 3 | 4 | /** 5 | * Write a description of class RedCar here. 6 | * 7 | * @author (your name) 8 | * @version (a version number or a date) 9 | */ 10 | public class RedCar extends Actor 11 | { 12 | private static final Random _rand = new Random(37L); 13 | 14 | private int x; 15 | private int y; 16 | 17 | public RedCar() { 18 | x = 0; 19 | y = 0; 20 | } 21 | 22 | public RedCar(int x) { 23 | this.x = x; 24 | this.y = getImage().getHeight() / 2; 25 | } 26 | 27 | public RedCar(World world) { 28 | int wWidth = world.getWidth(); 29 | int wHeight = world.getHeight(); 30 | int iHeight = getImage().getHeight(); 31 | 32 | x = _rand.nextInt(wWidth); 33 | y = iHeight / 2; 34 | } 35 | /** 36 | * Act - do whatever the RedCar wants to do. This method is called whenever 37 | * the 'Act' or 'Run' button gets pressed in the environment. 38 | */ 39 | public void act() 40 | { 41 | y = y + 1; 42 | setLocation(x, y); 43 | if (isAtEdge()) { 44 | ((MyWorld)getWorld()).removeRedCar(this); 45 | } 46 | } 47 | 48 | public int getX() { return x; } 49 | public int getY() { return y; } 50 | public int getWidth() { return getImage().getWidth(); } 51 | public int getHeight() { return getImage().getHeight(); } 52 | } 53 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/Score.ctxt: -------------------------------------------------------------------------------- 1 | #BlueJ class context 2 | comment0.target=Score 3 | comment0.text=\n\ Write\ a\ description\ of\ class\ Score\ here.\n\ \n\ @author\ (your\ name)\ \n\ @version\ (a\ version\ number\ or\ a\ date)\n 4 | comment1.params=world 5 | comment1.target=Score(MyWorld) 6 | comment2.params= 7 | comment2.target=void\ act() 8 | comment2.text=\n\ Act\ -\ do\ whatever\ the\ Score\ wants\ to\ do.\ This\ method\ is\ called\ whenever\n\ the\ 'Act'\ or\ 'Run'\ button\ gets\ pressed\ in\ the\ environment.\n 9 | numComments=3 10 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/Score.java: -------------------------------------------------------------------------------- 1 | import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) 2 | 3 | /** 4 | * Write a description of class Score here. 5 | * 6 | * @author (your name) 7 | * @version (a version number or a date) 8 | */ 9 | public class Score extends Actor 10 | { 11 | private MyWorld world; 12 | 13 | public Score(MyWorld world) { 14 | this.world = world; 15 | } 16 | 17 | /** 18 | * Act - do whatever the Score wants to do. This method is called whenever 19 | * the 'Act' or 'Run' button gets pressed in the environment. 20 | */ 21 | public void act() 22 | { 23 | String s = "Level " + world.getLevel() + ", Score: " + world.getScore(); 24 | GreenfootImage img = new GreenfootImage(s, 24, Color.GREEN, Color.BLACK); 25 | setImage(img); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /java/greenfoot/race-car/images/car02-n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/java/greenfoot/race-car/images/car02-n.png -------------------------------------------------------------------------------- /java/greenfoot/race-car/images/car03-n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/java/greenfoot/race-car/images/car03-n.png -------------------------------------------------------------------------------- /java/greenfoot/race-car/project.greenfoot: -------------------------------------------------------------------------------- 1 | #Greenfoot project file 2 | class.GreenCar.image=car03-n.png 3 | class.RedCar.image=car02-n.png 4 | dependency1.from=MyWorld 5 | dependency1.to=GreenCar 6 | dependency1.type=UsesDependency 7 | dependency2.from=MyWorld 8 | dependency2.to=RedCar 9 | dependency2.type=UsesDependency 10 | dependency3.from=MyWorld 11 | dependency3.to=Score 12 | dependency3.type=UsesDependency 13 | dependency4.from=Score 14 | dependency4.to=MyWorld 15 | dependency4.type=UsesDependency 16 | dependency5.from=GreenCar 17 | dependency5.to=RedCar 18 | dependency5.type=UsesDependency 19 | dependency6.from=RedCar 20 | dependency6.to=MyWorld 21 | dependency6.type=UsesDependency 22 | editor.fx.0.height=737 23 | editor.fx.0.width=800 24 | editor.fx.0.x=1520 25 | editor.fx.0.y=492 26 | height=785 27 | package.numDependencies=6 28 | package.numTargets=4 29 | project.charset=UTF-8 30 | publish.hasSource=false 31 | publish.locked=true 32 | publish.longDesc= 33 | publish.shortDesc= 34 | publish.tags= 35 | publish.title= 36 | publish.url= 37 | readme.height=58 38 | readme.name=@README 39 | readme.width=47 40 | readme.x=10 41 | readme.y=10 42 | simulation.speed=50 43 | target1.height=50 44 | target1.name=Score 45 | target1.showInterface=false 46 | target1.type=ClassTarget 47 | target1.width=80 48 | target1.x=0 49 | target1.y=0 50 | target2.height=50 51 | target2.name=GreenCar 52 | target2.showInterface=false 53 | target2.type=ClassTarget 54 | target2.width=80 55 | target2.x=0 56 | target2.y=0 57 | target3.height=50 58 | target3.name=RedCar 59 | target3.showInterface=false 60 | target3.type=ClassTarget 61 | target3.width=80 62 | target3.x=0 63 | target3.y=0 64 | target4.height=50 65 | target4.name=MyWorld 66 | target4.showInterface=false 67 | target4.type=ClassTarget 68 | target4.width=80 69 | target4.x=0 70 | target4.y=0 71 | version=3.0.0 72 | width=837 73 | world.lastInstantiated=MyWorld 74 | xPosition=1670 75 | yPosition=469 76 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/logo.png -------------------------------------------------------------------------------- /python/pygame/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.pyc -------------------------------------------------------------------------------- /python/pygame/README.md: -------------------------------------------------------------------------------- 1 | ![One-Off Coder Logo](../logo.png "One-Off Coder") 2 | 3 | # Pygame 4 | 5 | Tutorials in [Pygame](https://www.pygame.org). The API documentation is [available](https://www.pygame.org/docs/). 6 | 7 | Images 8 | 9 | * [Open Game Art](https://opengameart.org/) 10 | * [craftpix](https://craftpix.net/) 11 | 12 | Audio 13 | 14 | * [zapsplat](https://www.zapsplat.com/) 15 | 16 | # Basic 17 | 18 | * [Circles](basic/draw-circles.py): learn how to draw circles 19 | * [Shapes](basic/draw-shapes.py): learn how to draw shapes 20 | * [Sprite](basic/draw-sprite.py): learn how to draw sprites 21 | * [Bouncing Balls](basic/bouncing-balls.py): learn how to animate balls bouncing around 22 | * [Bouncing Images](basic/bouncing-image.py): learn how to animate images 23 | * [Image Rotation](basic/image-rotation.py): learn how to rotate an image 24 | * [Sound](basic/bouncing-image-with-sound.py): learn how to play sound 25 | * [Key Events](basic/key-movement.py): learn how to listen for key events 26 | * [Mouse Movement](basic/mouse-movement.py): learn how to move a sprite with the mouse 27 | * [Collision](basic/collection-detection.py): learn how to detect collision 28 | * [Sprite Animation](basic/char-animation.py): learn how to animate a sprite 29 | 30 | # Games 31 | 32 | * [Space Battle](space-battle): learn how to create a space battle program 33 | * [Yappy Bird](yappy-bird): a Flappy-Bird clone -------------------------------------------------------------------------------- /python/pygame/basic/audios/fairy.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/audios/fairy.wav -------------------------------------------------------------------------------- /python/pygame/basic/bouncing-balls.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import sys 4 | 5 | import pygame 6 | from pygame.locals import * 7 | 8 | 9 | class Ball(object): 10 | def __init__(self, color, position, radius): 11 | self.color = color 12 | self.position = position 13 | self.radius = radius 14 | self.dx = 1 if random.random() < 0.5 else -1 15 | self.dy = 1 if random.random() < 0.5 else 1 16 | 17 | def draw(self, surface): 18 | pygame.draw.circle(surface, self.color, self.position, self.radius) 19 | 20 | def update(self, width, height): 21 | x, y = self.position 22 | x_changed, y_changed = False, False 23 | 24 | if x + self.radius >= width: 25 | self.dx = -1 26 | x_changed = True 27 | elif x <= 0: 28 | self.dx = 1 29 | x_changed = True 30 | 31 | if y + self.radius >= height: 32 | self.dy = -1 33 | y_changed = True 34 | elif y <= 0: 35 | self.dy = 1 36 | y_changed = True 37 | 38 | x, y = x + 1 * self.dx, y + 1 * self.dy 39 | self.position = x, y 40 | 41 | if x_changed or y_changed: 42 | self.color = Ball.get_rand_color() 43 | 44 | @staticmethod 45 | def get_rand_color(min_value=0, max_value=255): 46 | r = random.randint(min_value, max_value) 47 | g = random.randint(min_value, max_value) 48 | b = random.randint(min_value, max_value) 49 | a = random.randint(min_value, max_value) 50 | return r, g, b, a 51 | 52 | @staticmethod 53 | def get_rand_position(width, height): 54 | x = random.randint(0, width) 55 | y = random.randint(0, height) 56 | return x, y 57 | 58 | @staticmethod 59 | def get_rand_radius(min_value=10, max_value=30): 60 | r = random.randint(min_value, max_value) 61 | return r 62 | 63 | @staticmethod 64 | def rand(width, height): 65 | color = Ball.get_rand_color() 66 | position = Ball.get_rand_position(width, height) 67 | radius = Ball.get_rand_radius() 68 | return Ball(color, position, radius) 69 | 70 | 71 | def start(): 72 | pygame.init() 73 | 74 | FPS = 30 75 | width = 400 76 | height = 400 77 | DISPLAYSURF = pygame.display.set_mode((width, height)) 78 | pygame.display.set_caption('Bouncing Balls') 79 | fps_clock = pygame.time.Clock() 80 | 81 | balls = [Ball.rand(width, height) for _ in range(10)] 82 | 83 | while True: 84 | for event in pygame.event.get(): 85 | if event.type == QUIT: 86 | pygame.quit() 87 | sys.exit() 88 | 89 | DISPLAYSURF.fill((0, 0, 0, 0)) 90 | 91 | for ball in balls: 92 | ball.draw(DISPLAYSURF) 93 | ball.update(width, height) 94 | 95 | pygame.display.update() 96 | fps_clock.tick(FPS) 97 | 98 | 99 | if __name__ == '__main__': 100 | os.environ['SDL_VIDEO_CENTERED'] = '1' 101 | start() 102 | -------------------------------------------------------------------------------- /python/pygame/basic/bouncing-image-with-sound.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import sys 4 | 5 | import pygame 6 | from pygame.locals import * 7 | 8 | 9 | class Image(object): 10 | def __init__(self, fpath, apath, position, scale=1.0): 11 | img = pygame.image.load(fpath) 12 | w, h = img.get_rect().size[0], img.get_rect().size[1] 13 | w, h = int(w * scale), int(h * scale) 14 | img = pygame.transform.scale(img, (w, h)) 15 | 16 | self.image = img 17 | self.audio = pygame.mixer.Sound(apath) 18 | self.position = position 19 | self.dx = 1 if random.random() < 0.5 else -1 20 | self.dy = 1 if random.random() < 0.5 else 1 21 | 22 | def draw(self, surface): 23 | surface.blit(self.image, self.position) 24 | 25 | def update(self, width, height): 26 | x, y = self.position 27 | 28 | if x + self.image.get_rect().size[0] >= width: 29 | self.dx = -1 30 | elif x <= 0: 31 | self.dx = 1 32 | 33 | if y + self.image.get_rect().size[1] >= height: 34 | self.dy = -1 35 | elif y <= 0: 36 | self.dy = 1 37 | 38 | x, y = x + 1 * self.dx, y + 1 * self.dy 39 | self.position = x, y 40 | 41 | def hit_edge(self, width, height): 42 | x, y = self.position 43 | 44 | if x + self.image.get_rect().size[0] >= width: 45 | return True 46 | elif x <= 0: 47 | return True 48 | 49 | if y + self.image.get_rect().size[1] >= height: 50 | return True 51 | elif y <= 0: 52 | return True 53 | 54 | return False 55 | 56 | def play(self): 57 | self.audio.play() 58 | 59 | @staticmethod 60 | def get_rand_color(min_value=0, max_value=255): 61 | r = random.randint(min_value, max_value) 62 | g = random.randint(min_value, max_value) 63 | b = random.randint(min_value, max_value) 64 | a = random.randint(min_value, max_value) 65 | return r, g, b, a 66 | 67 | @staticmethod 68 | def get_rand_position(width, height): 69 | x = random.randint(0, width) 70 | y = random.randint(0, height) 71 | return x, y 72 | 73 | @staticmethod 74 | def get_rand_radius(min_value=10, max_value=30): 75 | r = random.randint(min_value, max_value) 76 | return r 77 | 78 | @staticmethod 79 | def rand(fpath, apath, width, height, scale=0.25): 80 | position = Image.get_rand_position(width, height) 81 | return Image(fpath, apath, position, scale=scale) 82 | 83 | 84 | def start(): 85 | pygame.init() 86 | 87 | FPS = 30 88 | width = 400 89 | height = 400 90 | DISPLAYSURF = pygame.display.set_mode((width, height)) 91 | pygame.display.set_caption('Bouncing Image with Sound') 92 | fps_clock = pygame.time.Clock() 93 | 94 | images = [Image.rand('./images/logo.png', './audios/fairy.wav', width, height, scale=0.5) for _ in range(1)] 95 | 96 | while True: 97 | for event in pygame.event.get(): 98 | if event.type == QUIT: 99 | pygame.quit() 100 | sys.exit() 101 | 102 | DISPLAYSURF.fill((0, 0, 0, 0)) 103 | 104 | for image in images: 105 | image.draw(DISPLAYSURF) 106 | image.update(width, height) 107 | 108 | if image.hit_edge(width, height): 109 | image.play() 110 | 111 | pygame.display.update() 112 | fps_clock.tick(FPS) 113 | 114 | 115 | if __name__ == '__main__': 116 | os.environ['SDL_VIDEO_CENTERED'] = '1' 117 | start() 118 | -------------------------------------------------------------------------------- /python/pygame/basic/bouncing-images.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import sys 4 | 5 | import pygame 6 | from pygame.locals import * 7 | 8 | 9 | class Image(object): 10 | def __init__(self, fpath, position, scale=1.0): 11 | img = pygame.image.load(fpath) 12 | w, h = img.get_rect().size[0], img.get_rect().size[1] 13 | w, h = int(w * scale), int(h * scale) 14 | img = pygame.transform.scale(img, (w, h)) 15 | 16 | self.image = img 17 | self.position = position 18 | self.dx = 1 if random.random() < 0.5 else -1 19 | self.dy = 1 if random.random() < 0.5 else 1 20 | 21 | def draw(self, surface): 22 | surface.blit(self.image, self.position) 23 | 24 | def update(self, width, height): 25 | x, y = self.position 26 | 27 | if x + self.image.get_rect().size[0] >= width: 28 | self.dx = -1 29 | elif x <= 0: 30 | self.dx = 1 31 | 32 | if y + self.image.get_rect().size[1] >= height: 33 | self.dy = -1 34 | elif y <= 0: 35 | self.dy = 1 36 | 37 | x, y = x + 1 * self.dx, y + 1 * self.dy 38 | self.position = x, y 39 | 40 | @staticmethod 41 | def get_rand_color(min_value=0, max_value=255): 42 | r = random.randint(min_value, max_value) 43 | g = random.randint(min_value, max_value) 44 | b = random.randint(min_value, max_value) 45 | a = random.randint(min_value, max_value) 46 | return r, g, b, a 47 | 48 | @staticmethod 49 | def get_rand_position(width, height): 50 | x = random.randint(0, width) 51 | y = random.randint(0, height) 52 | return x, y 53 | 54 | @staticmethod 55 | def get_rand_radius(min_value=10, max_value=30): 56 | r = random.randint(min_value, max_value) 57 | return r 58 | 59 | @staticmethod 60 | def rand(fpath, width, height, scale=0.25): 61 | position = Image.get_rand_position(width, height) 62 | return Image(fpath, position, scale=scale) 63 | 64 | 65 | def start(): 66 | pygame.init() 67 | 68 | FPS = 30 69 | width = 400 70 | height = 400 71 | DISPLAYSURF = pygame.display.set_mode((width, height)) 72 | pygame.display.set_caption('Bouncing Images') 73 | fps_clock = pygame.time.Clock() 74 | 75 | images = [Image.rand('./images/ball.png', width, height) for _ in range(10)] 76 | 77 | while True: 78 | for event in pygame.event.get(): 79 | if event.type == QUIT: 80 | pygame.quit() 81 | sys.exit() 82 | 83 | DISPLAYSURF.fill((0, 0, 0, 0)) 84 | 85 | for image in images: 86 | image.draw(DISPLAYSURF) 87 | image.update(width, height) 88 | 89 | pygame.display.update() 90 | fps_clock.tick(FPS) 91 | 92 | 93 | if __name__ == '__main__': 94 | os.environ['SDL_VIDEO_CENTERED'] = '1' 95 | start() 96 | -------------------------------------------------------------------------------- /python/pygame/basic/char-animation.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import pygame 5 | from pygame.locals import * 6 | 7 | 8 | class Bird(pygame.sprite.Sprite): 9 | def __init__(self, position, scale=0.5): 10 | pygame.sprite.Sprite.__init__(self) 11 | 12 | paths = [f'./images/frame-{i + 1}.png' for i in range(8)] 13 | imgs = [pygame.image.load(p) for p in paths] 14 | rect = imgs[0].get_rect() 15 | 16 | w, h = rect.size[0], rect.size[1] 17 | w, h = int(w * scale), int(h * scale) 18 | 19 | self.imgs = [pygame.transform.scale(img, (w, h)) for img in imgs] 20 | self.rect = self.imgs[0].get_rect() 21 | self.rect.center = position[0] - w / 2.0, position[1] - h / 2.0 22 | self.index = 0 23 | 24 | def draw(self, surface): 25 | surface.blit(self.imgs[self.index], self.rect.center) 26 | self.index += 1 27 | if self.index >= len(self.imgs): 28 | self.index = 0 29 | 30 | 31 | def start(): 32 | pygame.init() 33 | 34 | FPS = 30 35 | width = 400 36 | height = 400 37 | DISPLAYSURF = pygame.display.set_mode((width, height)) 38 | DISPLAYSURF.fill((255, 255, 255)) 39 | pygame.display.set_caption('Key Events') 40 | fps_clock = pygame.time.Clock() 41 | 42 | bird = Bird((200, 200), 0.10) 43 | 44 | while True: 45 | for event in pygame.event.get(): 46 | if event.type == QUIT: 47 | pygame.quit() 48 | sys.exit() 49 | 50 | DISPLAYSURF.fill((255, 255, 255, 0)) 51 | 52 | bird.draw(DISPLAYSURF) 53 | 54 | pygame.display.update() 55 | fps_clock.tick(FPS) 56 | 57 | 58 | if __name__ == '__main__': 59 | os.environ['SDL_VIDEO_CENTERED'] = '1' 60 | start() 61 | -------------------------------------------------------------------------------- /python/pygame/basic/collison-detection.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import sys 4 | 5 | import pygame 6 | from pygame.locals import * 7 | 8 | 9 | class Satyr(pygame.sprite.Sprite): 10 | def __init__(self, position, ipath, scale=0.5): 11 | pygame.sprite.Sprite.__init__(self) 12 | 13 | img = pygame.image.load(ipath) 14 | rect = img.get_rect(center=position) 15 | w, h = rect.size[0], rect.size[1] 16 | w, h = int(w * scale), int(h * scale) 17 | img = pygame.transform.scale(img, (w, h)) 18 | 19 | rect = img.get_rect(center=position) 20 | 21 | self.image = img 22 | self.rect = rect 23 | self.rect.center = position 24 | 25 | def draw(self, surface, position): 26 | self.rect.center = position 27 | surface.blit(self.image, position) 28 | 29 | 30 | class Image(pygame.sprite.Sprite): 31 | def __init__(self, position, ipath, scale=1.0): 32 | pygame.sprite.Sprite.__init__(self) 33 | 34 | img = pygame.image.load(ipath) 35 | w, h = img.get_rect().size[0], img.get_rect().size[1] 36 | w, h = int(w * scale), int(h * scale) 37 | img = pygame.transform.scale(img, (w, h)) 38 | 39 | rect = img.get_rect(center=position) 40 | 41 | self.image = img 42 | self.rect = rect 43 | self.rect.center = position 44 | self.dx = 1 if random.random() < 0.5 else -1 45 | self.dy = 1 if random.random() < 0.5 else 1 46 | 47 | def draw(self, surface): 48 | surface.blit(self.image, self.rect.center) 49 | 50 | def update(self, width, height): 51 | x, y = self.rect.center 52 | 53 | if x + self.image.get_rect().size[0] >= width: 54 | self.dx = -1 55 | elif x <= 0: 56 | self.dx = 1 57 | 58 | if y + self.image.get_rect().size[1] >= height: 59 | self.dy = -1 60 | elif y <= 0: 61 | self.dy = 1 62 | 63 | x, y = x + 1 * self.dx, y + 1 * self.dy 64 | self.rect.center = x, y 65 | 66 | 67 | def start(): 68 | pygame.init() 69 | 70 | FPS = 30 71 | width = 400 72 | height = 400 73 | DISPLAYSURF = pygame.display.set_mode((width, height)) 74 | DISPLAYSURF.fill((255, 255, 255)) 75 | pygame.display.set_caption('Key Events') 76 | fps_clock = pygame.time.Clock() 77 | 78 | satyr = Satyr((200, 200), './images/Satyr_01_Idle_000.png', scale=0.25) 79 | 80 | ball = Image((random.randint(0, width), random.randint(0, height)), './images/ball.png', scale=0.25) 81 | ball_group = pygame.sprite.Group() 82 | ball_group.add(ball) 83 | 84 | while True: 85 | for event in pygame.event.get(): 86 | if event.type == QUIT: 87 | pygame.quit() 88 | sys.exit() 89 | 90 | DISPLAYSURF.fill((255, 255, 255, 0)) 91 | 92 | if pygame.sprite.spritecollide(satyr, ball_group, False): 93 | print(f'collided {ball.rect.center}') 94 | 95 | satyr.draw(DISPLAYSURF, pygame.mouse.get_pos()) 96 | ball.draw(DISPLAYSURF) 97 | ball.update(width, height) 98 | 99 | pygame.display.update() 100 | fps_clock.tick(FPS) 101 | 102 | 103 | if __name__ == '__main__': 104 | os.environ['SDL_VIDEO_CENTERED'] = '1' 105 | start() 106 | -------------------------------------------------------------------------------- /python/pygame/basic/draw-circles.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import sys 4 | 5 | import pygame 6 | from pygame.locals import * 7 | 8 | 9 | def get_rand_color(min_value=0, max_value=255): 10 | r = random.randint(min_value, max_value) 11 | g = random.randint(min_value, max_value) 12 | b = random.randint(min_value, max_value) 13 | a = random.randint(min_value, max_value) 14 | return r, g, b, a 15 | 16 | 17 | def get_rand_position(width, height): 18 | x = random.randint(0, width) 19 | y = random.randint(0, height) 20 | return x, y 21 | 22 | 23 | def get_rand_radius(min_value=10, max_value=30): 24 | r = random.randint(min_value, max_value) 25 | return r 26 | 27 | 28 | def start(): 29 | pygame.init() 30 | 31 | FPS = 30 32 | width = 400 33 | height = 400 34 | 35 | DISPLAYSURF = pygame.display.set_mode((width, height)) 36 | pygame.display.set_caption('Circles') 37 | fps_clock = pygame.time.Clock() 38 | 39 | iters = 0 40 | while True: 41 | for event in pygame.event.get(): 42 | if event.type == QUIT: 43 | pygame.quit() 44 | sys.exit() 45 | 46 | if iters % 100 == 0: 47 | DISPLAYSURF.fill((0, 0, 0, 0)) 48 | iters = 0 49 | 50 | pygame.draw.circle(DISPLAYSURF, get_rand_color(), get_rand_position(width, height), get_rand_radius()) 51 | 52 | pygame.display.update() 53 | fps_clock.tick(FPS) 54 | 55 | iters += 1 56 | 57 | 58 | if __name__ == '__main__': 59 | os.environ['SDL_VIDEO_CENTERED'] = '1' 60 | start() 61 | -------------------------------------------------------------------------------- /python/pygame/basic/draw-shapes.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import sys 4 | 5 | import pygame 6 | from pygame.locals import * 7 | 8 | 9 | class Shape(object): 10 | def __init__(self, color): 11 | self.color = color 12 | 13 | def draw(self, surface): 14 | raise NotImplementedError('Not implemented') 15 | 16 | @staticmethod 17 | def get_rand_color(min_value=0, max_value=255): 18 | r = random.randint(min_value, max_value) 19 | g = random.randint(min_value, max_value) 20 | b = random.randint(min_value, max_value) 21 | a = random.randint(min_value, max_value) 22 | return r, g, b, a 23 | 24 | @staticmethod 25 | def get_rand_position(width, height): 26 | x = random.randint(0, width) 27 | y = random.randint(0, height) 28 | return x, y 29 | 30 | 31 | class Line(Shape): 32 | def __init__(self, color, start, stop, width): 33 | super().__init__(color) 34 | self.start = start 35 | self.stop = stop 36 | self.width = width 37 | 38 | def draw(self, surface): 39 | pygame.draw.line(surface, self.color, self.start, self.stop, self.width) 40 | 41 | @staticmethod 42 | def get_rand_width(min_value=1, max_value=5): 43 | return random.randint(min_value, max_value) 44 | 45 | @staticmethod 46 | def rand(width, height): 47 | color = Shape.get_rand_color() 48 | start = Shape.get_rand_position(width, height) 49 | stop = Shape.get_rand_position(width, height) 50 | width = Line.get_rand_width() 51 | return Line(color, start, stop, width) 52 | 53 | 54 | class Circle(Shape): 55 | def __init__(self, color, position, radius): 56 | super().__init__(color) 57 | self.position = position 58 | self.radius = radius 59 | 60 | def draw(self, surface): 61 | pygame.draw.circle(surface, self.color, self.position, self.radius) 62 | 63 | @staticmethod 64 | def get_rand_radius(min_value=10, max_value=30): 65 | r = random.randint(min_value, max_value) 66 | return r 67 | 68 | @staticmethod 69 | def rand(width, height): 70 | color = Shape.get_rand_color() 71 | position = Shape.get_rand_position(width, height) 72 | radius = Circle.get_rand_radius() 73 | return Circle(color, position, radius) 74 | 75 | 76 | class Rectangle(Shape): 77 | def __init__(self, color, position, dimension): 78 | super().__init__(color) 79 | self.position = position 80 | self.dimension = dimension 81 | 82 | def draw(self, surface): 83 | pygame.draw.rect(surface, self.color, (self.position, self.dimension)) 84 | 85 | @staticmethod 86 | def get_rand_dimension(min_value=10, max_value=50): 87 | width = random.randint(min_value, max_value) 88 | height = random.randint(min_value, max_value) 89 | return width, height 90 | 91 | @staticmethod 92 | def rand(width, height): 93 | color = Shape.get_rand_color() 94 | position = Shape.get_rand_position(width, height) 95 | dimension = Rectangle.get_rand_dimension() 96 | return Rectangle(color, position, dimension) 97 | 98 | 99 | def start(): 100 | pygame.init() 101 | 102 | FPS = 30 103 | width = 400 104 | height = 400 105 | 106 | DISPLAYSURF = pygame.display.set_mode((width, height)) 107 | pygame.display.set_caption('Shapes') 108 | fps_clock = pygame.time.Clock() 109 | 110 | iters = 0 111 | while True: 112 | for event in pygame.event.get(): 113 | if event.type == QUIT: 114 | pygame.quit() 115 | sys.exit() 116 | 117 | if iters % 100 == 0: 118 | DISPLAYSURF.fill((0, 0, 0, 0)) 119 | iters = 0 120 | 121 | probability = random.random() 122 | if probability < 0.33: 123 | shape = Circle.rand(width, height) 124 | elif probability < 0.66: 125 | shape = Line.rand(width, height) 126 | else: 127 | shape = Rectangle.rand(width, height) 128 | 129 | shape.draw(DISPLAYSURF) 130 | 131 | pygame.display.update() 132 | fps_clock.tick(FPS) 133 | 134 | iters += 1 135 | 136 | 137 | if __name__ == '__main__': 138 | os.environ['SDL_VIDEO_CENTERED'] = '1' 139 | start() 140 | -------------------------------------------------------------------------------- /python/pygame/basic/draw-sprite.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import pygame 5 | from pygame.locals import * 6 | 7 | 8 | class Satyr(pygame.sprite.Sprite): 9 | def __init__(self, position, scale=0.5): 10 | pygame.sprite.Sprite.__init__(self) 11 | 12 | img = pygame.image.load('./images/Satyr_01_Idle_000.png') 13 | rect = img.get_rect(center=position) 14 | w, h = rect.size[0], rect.size[1] 15 | w, h = int(w * scale), int(h * scale) 16 | img = pygame.transform.scale(img, (w, h)) 17 | 18 | rect = img.get_rect(center=position) 19 | x = position[0] - int(rect.size[0] / 2.0) 20 | y = position[1] - int(rect.size[1] / 2.0) 21 | 22 | self.image = img 23 | self.rect = rect 24 | self.position = x, y 25 | 26 | def draw(self, surface): 27 | surface.blit(self.image, self.position) 28 | 29 | 30 | def start(): 31 | pygame.init() 32 | 33 | FPS = 30 34 | width = 400 35 | height = 400 36 | DISPLAYSURF = pygame.display.set_mode((width, height)) 37 | DISPLAYSURF.fill((255, 255, 255)) 38 | pygame.display.set_caption('Key Events') 39 | fps_clock = pygame.time.Clock() 40 | 41 | satyr = Satyr((200, 200), 0.25) 42 | 43 | while True: 44 | for event in pygame.event.get(): 45 | if event.type == QUIT: 46 | pygame.quit() 47 | sys.exit() 48 | 49 | DISPLAYSURF.fill((255, 255, 255, 0)) 50 | 51 | satyr.draw(DISPLAYSURF) 52 | 53 | pygame.display.update() 54 | fps_clock.tick(FPS) 55 | 56 | 57 | if __name__ == '__main__': 58 | os.environ['SDL_VIDEO_CENTERED'] = '1' 59 | start() 60 | -------------------------------------------------------------------------------- /python/pygame/basic/image-rotation.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import sys 4 | 5 | import pygame 6 | from pygame.locals import * 7 | 8 | 9 | class Image(object): 10 | def __init__(self, fpath, position, scale=1.0): 11 | img = pygame.image.load(fpath) 12 | w, h = img.get_rect().size[0], img.get_rect().size[1] 13 | w, h = int(w * scale), int(h * scale) 14 | img = pygame.transform.scale(img, (w, h)) 15 | 16 | self.image = img 17 | self.position = position 18 | self.dx = 1 if random.random() < 0.5 else -1 19 | self.dy = 1 if random.random() < 0.5 else 1 20 | self.drot = 1 if random.random() < 0.5 else -1 21 | self.rotation = 0 22 | 23 | def draw(self, surface): 24 | image = pygame.transform.rotate(self.image, self.rotation) 25 | surface.blit(image, self.position) 26 | 27 | def update(self, width, height): 28 | x, y = self.position 29 | x_changed, y_changed = False, False 30 | 31 | if x + self.image.get_rect().size[0] >= width: 32 | self.dx = -1 33 | x_changed = True 34 | elif x <= 0: 35 | self.dx = 1 36 | x_changed = True 37 | 38 | if y + self.image.get_rect().size[1] >= height: 39 | self.dy = -1 40 | y_changed = True 41 | elif y <= 0: 42 | self.dy = 1 43 | y_changed = True 44 | 45 | x, y = x + 1 * self.dx, y + 1 * self.dy 46 | self.position = x, y 47 | 48 | if x_changed or y_changed: 49 | self.drot *= -1 50 | self.rotation += 10 * self.drot 51 | else: 52 | self.rotation += 5 * self.drot 53 | 54 | @staticmethod 55 | def get_rand_color(min_value=0, max_value=255): 56 | r = random.randint(min_value, max_value) 57 | g = random.randint(min_value, max_value) 58 | b = random.randint(min_value, max_value) 59 | a = random.randint(min_value, max_value) 60 | return r, g, b, a 61 | 62 | @staticmethod 63 | def get_rand_position(width, height): 64 | x = random.randint(0, width) 65 | y = random.randint(0, height) 66 | return x, y 67 | 68 | @staticmethod 69 | def get_rand_radius(min_value=10, max_value=30): 70 | r = random.randint(min_value, max_value) 71 | return r 72 | 73 | @staticmethod 74 | def rand(fpath, width, height, scale=0.25): 75 | position = Image.get_rand_position(width, height) 76 | return Image(fpath, position, scale=scale) 77 | 78 | 79 | def start(): 80 | pygame.init() 81 | 82 | FPS = 30 83 | width = 400 84 | height = 400 85 | DISPLAYSURF = pygame.display.set_mode((width, height)) 86 | pygame.display.set_caption('Rotating Image') 87 | fps_clock = pygame.time.Clock() 88 | 89 | image = Image.rand('./images/ball.png', width, height) 90 | 91 | while True: 92 | for event in pygame.event.get(): 93 | if event.type == QUIT: 94 | pygame.quit() 95 | sys.exit() 96 | 97 | DISPLAYSURF.fill((0, 0, 0, 0)) 98 | 99 | image.draw(DISPLAYSURF) 100 | image.update(width, height) 101 | 102 | pygame.display.update() 103 | fps_clock.tick(FPS) 104 | 105 | 106 | if __name__ == '__main__': 107 | os.environ['SDL_VIDEO_CENTERED'] = '1' 108 | start() 109 | -------------------------------------------------------------------------------- /python/pygame/basic/images/Satyr_01_Idle_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/Satyr_01_Idle_000.png -------------------------------------------------------------------------------- /python/pygame/basic/images/Satyr_02_Idle_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/Satyr_02_Idle_000.png -------------------------------------------------------------------------------- /python/pygame/basic/images/Satyr_03_Idle_000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/Satyr_03_Idle_000.png -------------------------------------------------------------------------------- /python/pygame/basic/images/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/ball.png -------------------------------------------------------------------------------- /python/pygame/basic/images/frame-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/frame-1.png -------------------------------------------------------------------------------- /python/pygame/basic/images/frame-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/frame-2.png -------------------------------------------------------------------------------- /python/pygame/basic/images/frame-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/frame-3.png -------------------------------------------------------------------------------- /python/pygame/basic/images/frame-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/frame-4.png -------------------------------------------------------------------------------- /python/pygame/basic/images/frame-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/frame-5.png -------------------------------------------------------------------------------- /python/pygame/basic/images/frame-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/frame-6.png -------------------------------------------------------------------------------- /python/pygame/basic/images/frame-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/frame-7.png -------------------------------------------------------------------------------- /python/pygame/basic/images/frame-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/frame-8.png -------------------------------------------------------------------------------- /python/pygame/basic/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/basic/images/logo.png -------------------------------------------------------------------------------- /python/pygame/basic/key-movement.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import sys 4 | 5 | import pygame 6 | from pygame.locals import * 7 | 8 | 9 | class Image(object): 10 | def __init__(self, fpath, position, scale=1.0): 11 | img = pygame.image.load(fpath) 12 | w, h = img.get_rect(center=position).size[0], img.get_rect(center=position).size[1] 13 | w, h = int(w * scale), int(h * scale) 14 | img = pygame.transform.scale(img, (w, h)) 15 | 16 | x = position[0] - int(img.get_rect(center=position).size[0] / 2.0) 17 | y = position[1] - int(img.get_rect(center=position).size[1] / 2.0) 18 | 19 | self.image = img 20 | self.position = x, y 21 | 22 | def draw(self, surface): 23 | surface.blit(self.image, self.position) 24 | 25 | def update(self, width, height, event): 26 | x, y = self.position 27 | rect = self.image.get_rect(center=self.position) 28 | img_width = rect.size[0] 29 | img_height = rect.size[1] 30 | 31 | if event.key in (K_LEFT, K_a): 32 | if x > 0: 33 | x -= 10 34 | elif event.key in (K_RIGHT, K_d): 35 | if x + img_width < width: 36 | x += 10 37 | 38 | if event.key in (K_UP, K_w): 39 | if y > 0: 40 | y -= 10 41 | elif event.key in (K_DOWN, K_s): 42 | if y + img_height < height: 43 | y += 10 44 | 45 | self.position = x, y 46 | 47 | @staticmethod 48 | def get_rand_color(min_value=0, max_value=255): 49 | r = random.randint(min_value, max_value) 50 | g = random.randint(min_value, max_value) 51 | b = random.randint(min_value, max_value) 52 | a = random.randint(min_value, max_value) 53 | return r, g, b, a 54 | 55 | @staticmethod 56 | def get_rand_position(width, height): 57 | x = random.randint(0, width) 58 | y = random.randint(0, height) 59 | return x, y 60 | 61 | @staticmethod 62 | def get_rand_radius(min_value=10, max_value=30): 63 | r = random.randint(min_value, max_value) 64 | return r 65 | 66 | @staticmethod 67 | def rand(fpath, width, height, scale=0.25): 68 | position = Image.get_rand_position(width, height) 69 | return Image(fpath, position, scale=scale) 70 | 71 | 72 | def start(): 73 | pygame.init() 74 | 75 | FPS = 30 76 | width = 400 77 | height = 400 78 | DISPLAYSURF = pygame.display.set_mode((width, height)) 79 | DISPLAYSURF.fill((255, 255, 255)) 80 | pygame.display.set_caption('Key Events') 81 | fps_clock = pygame.time.Clock() 82 | 83 | satyr = Image('./images/Satyr_01_Idle_000.png', (200, 200), 0.25) 84 | 85 | while True: 86 | for event in pygame.event.get(): 87 | if event.type == QUIT: 88 | pygame.quit() 89 | sys.exit() 90 | elif event.type == KEYUP: 91 | satyr.update(width, height, event) 92 | 93 | DISPLAYSURF.fill((255, 255, 255, 0)) 94 | 95 | satyr.draw(DISPLAYSURF) 96 | 97 | pygame.display.update() 98 | fps_clock.tick(FPS) 99 | 100 | 101 | if __name__ == '__main__': 102 | os.environ['SDL_VIDEO_CENTERED'] = '1' 103 | start() 104 | -------------------------------------------------------------------------------- /python/pygame/basic/mouse-movement.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import pygame 5 | from pygame.locals import * 6 | 7 | 8 | class Satyr(pygame.sprite.Sprite): 9 | def __init__(self, position, scale=0.5): 10 | pygame.sprite.Sprite.__init__(self) 11 | 12 | img = pygame.image.load('./images/Satyr_01_Idle_000.png') 13 | rect = img.get_rect(center=position) 14 | w, h = rect.size[0], rect.size[1] 15 | w, h = int(w * scale), int(h * scale) 16 | img = pygame.transform.scale(img, (w, h)) 17 | 18 | rect = img.get_rect(center=position) 19 | x = position[0] - int(rect.size[0] / 2.0) 20 | y = position[1] - int(rect.size[1] / 2.0) 21 | 22 | self.image = img 23 | self.rect = rect 24 | self.position = x, y 25 | 26 | def draw(self, surface, position): 27 | self.position = position[0] - self.rect.width / 2, position[1] - self.rect.height / 2 28 | surface.blit(self.image, self.position) 29 | 30 | 31 | def start(): 32 | pygame.init() 33 | 34 | FPS = 30 35 | width = 400 36 | height = 400 37 | DISPLAYSURF = pygame.display.set_mode((width, height)) 38 | DISPLAYSURF.fill((255, 255, 255)) 39 | pygame.display.set_caption('Key Events') 40 | fps_clock = pygame.time.Clock() 41 | 42 | satyr = Satyr((200, 200), 0.25) 43 | 44 | while True: 45 | for event in pygame.event.get(): 46 | if event.type == QUIT: 47 | pygame.quit() 48 | sys.exit() 49 | 50 | DISPLAYSURF.fill((255, 255, 255, 0)) 51 | 52 | satyr.draw(DISPLAYSURF, pygame.mouse.get_pos()) 53 | 54 | pygame.display.update() 55 | fps_clock.tick(FPS) 56 | 57 | 58 | if __name__ == '__main__': 59 | os.environ['SDL_VIDEO_CENTERED'] = '1' 60 | start() 61 | -------------------------------------------------------------------------------- /python/pygame/space-battle/audio/bullet.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/space-battle/audio/bullet.wav -------------------------------------------------------------------------------- /python/pygame/space-battle/audio/explosion.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/space-battle/audio/explosion.wav -------------------------------------------------------------------------------- /python/pygame/space-battle/audio/game.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/space-battle/audio/game.wav -------------------------------------------------------------------------------- /python/pygame/space-battle/game.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | import os 3 | import sys 4 | 5 | import pygame 6 | from pygame.constants import KEYUP, QUIT, K_SPACE, K_q, K_c 7 | 8 | from objects import Ship, Bullet, RockGenerator, GameInfo, GameOverMessage, AudioEffects 9 | 10 | 11 | def get_remaining_objects(bullets, rocks, bullet_group, rock_group): 12 | collisions = pygame.sprite.groupcollide(bullet_group, rock_group, True, True) 13 | n_collisions = len(collisions) 14 | if n_collisions > 0: 15 | collided_bullets = set([b.uuid for b in collisions.keys()]) 16 | bullets = [b for b in bullets if b.uuid not in collided_bullets] 17 | 18 | collided_rocks = set([r.uuid for r in itertools.chain(*collisions.values())]) 19 | rocks = [r for r in rocks if r.uuid not in collided_rocks] 20 | return bullets, rocks, n_collisions 21 | 22 | 23 | def get_remaining_rocks(ship, rocks, rock_group): 24 | collisions = pygame.sprite.spritecollide(ship, rock_group, True) 25 | n_collisions = len(collisions) 26 | if n_collisions > 0: 27 | collided_rocks = set([r.uuid for r in collisions]) 28 | rocks = [r for r in rocks if r.uuid not in collided_rocks] 29 | return rocks, -n_collisions 30 | 31 | 32 | def get_params(): 33 | width = 500 34 | height = 400 35 | 36 | DISPLAYSURF = pygame.display.set_mode((width, height)) 37 | DISPLAYSURF.fill((255, 255, 255)) 38 | 39 | score = 0 40 | lives = 1 41 | 42 | return { 43 | 'FPS': 30, 44 | 'width': width, 45 | 'height': height, 46 | 'DISPLAYSURF': DISPLAYSURF, 47 | 'fps_clock': pygame.time.Clock(), 48 | 'score': score, 49 | 'lives': lives, 50 | 'bullets': [], 51 | 'rocks': [], 52 | 'bullet_group': pygame.sprite.Group(), 53 | 'rock_group': pygame.sprite.Group(), 54 | 'ship': Ship((width / 2, height - 50), 0.5), 55 | 'rock_generator': RockGenerator(width, height), 56 | 'game_info': GameInfo(score, lives), 57 | 'audio': AudioEffects() 58 | } 59 | 60 | 61 | def quit_game(): 62 | pygame.quit() 63 | sys.exit() 64 | 65 | 66 | def start_game(**params): 67 | width, height = params['width'], params['height'] 68 | ship = params['ship'] 69 | score, lives = params['score'], params['lives'] 70 | bullets, rocks = params['bullets'], params['rocks'] 71 | bullet_group, rock_group = params['bullet_group'], params['rock_group'] 72 | rock_generator = params['rock_generator'] 73 | game_info = params['game_info'] 74 | DISPLAYSURF = params['DISPLAYSURF'] 75 | fps_clock, FPS = params['fps_clock'], params['FPS'] 76 | audio = params['audio'] 77 | 78 | while True: 79 | kwargs = { 80 | 'width': width, 81 | 'height': height, 82 | 'keys': pygame.key.get_pressed(), 83 | 'position': ship.get_center(), 84 | 'score': score, 85 | 'lives': lives 86 | } 87 | 88 | for event in pygame.event.get(): 89 | if event.type == QUIT: 90 | quit_game() 91 | elif event.type == KEYUP and event.key == K_SPACE: 92 | bullet = Bullet.instance(**kwargs) 93 | bullet_group.add(bullet) 94 | bullets.append(bullet) 95 | audio.play('bullet') 96 | 97 | if rock_generator.should_generate(): 98 | rock = rock_generator.next() 99 | rocks.append(rock) 100 | rock_group.add(rock) 101 | 102 | DISPLAYSURF.fill((255, 255, 255, 0)) 103 | 104 | game_info.draw(DISPLAYSURF, **kwargs) 105 | ship.draw(DISPLAYSURF, **kwargs) 106 | 107 | for bullet in bullets: 108 | bullet.draw(DISPLAYSURF, **kwargs) 109 | 110 | for rock in rocks: 111 | rock.draw(DISPLAYSURF, **kwargs) 112 | 113 | bullets, rocks, points = get_remaining_objects(bullets, rocks, bullet_group, rock_group) 114 | score += points 115 | for _ in range(points): 116 | audio.play('explosion') 117 | 118 | rocks, hits = get_remaining_rocks(ship, rocks, rock_group) 119 | lives += hits 120 | 121 | pygame.display.update() 122 | fps_clock.tick(FPS) 123 | 124 | if lives <= 0: 125 | break 126 | 127 | return score, lives 128 | 129 | 130 | def show_game_over(**params): 131 | DISPLAYSURF = params['DISPLAYSURF'] 132 | fps_clock, FPS = params['fps_clock'], params['FPS'] 133 | width, height = params['width'], params['height'] 134 | score, lives = params['score'], params['lives'] 135 | 136 | message = GameOverMessage(width, height, score, lives) 137 | do_continue = False 138 | 139 | while True: 140 | for event in pygame.event.get(): 141 | if event.type == QUIT: 142 | quit_game() 143 | elif event.type == KEYUP: 144 | if event.key == K_q: 145 | quit_game() 146 | elif event.key == K_c: 147 | print('continue') 148 | do_continue = True 149 | break 150 | 151 | if do_continue: 152 | break 153 | 154 | DISPLAYSURF.fill((255, 255, 255, 0)) 155 | 156 | message.draw(DISPLAYSURF) 157 | 158 | pygame.display.update() 159 | fps_clock.tick(FPS) 160 | 161 | return do_continue 162 | 163 | 164 | def start(): 165 | pygame.init() 166 | pygame.display.set_caption('Space Battle') 167 | 168 | pygame.mixer.init() 169 | pygame.mixer.music.load('./audio/game.wav') 170 | pygame.mixer.music.play(loops=-1) 171 | 172 | while True: 173 | params = get_params() 174 | params['score'], params['lives'] = start_game(**params) 175 | 176 | do_continue = show_game_over(**params) 177 | if not do_continue: 178 | break 179 | 180 | pygame.mixer.music.stop() 181 | quit_game() 182 | 183 | 184 | if __name__ == '__main__': 185 | os.environ['SDL_VIDEO_CENTERED'] = '1' 186 | start() 187 | -------------------------------------------------------------------------------- /python/pygame/space-battle/images/bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/space-battle/images/bullet.png -------------------------------------------------------------------------------- /python/pygame/space-battle/images/rock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/space-battle/images/rock.png -------------------------------------------------------------------------------- /python/pygame/space-battle/images/ship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/space-battle/images/ship.png -------------------------------------------------------------------------------- /python/pygame/space-battle/images/upgrade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/space-battle/images/upgrade.png -------------------------------------------------------------------------------- /python/pygame/space-battle/objects.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | import uuid 4 | 5 | import pygame 6 | from pygame.constants import K_LEFT, K_a, K_RIGHT, K_d 7 | 8 | 9 | class BaseObject(pygame.sprite.Sprite): 10 | def __init__(self, ipath, position, scale=0.5): 11 | pygame.sprite.Sprite.__init__(self) 12 | 13 | self.uuid = str(uuid.uuid4()) 14 | self.image = BaseObject.__scale__(ipath, position, scale) 15 | self.rect = self.image.get_rect(center=position) 16 | 17 | def get_center(self): 18 | return self.rect.center 19 | 20 | def draw(self, surface, **kwargs): 21 | raise NotImplementedError('Not yet implemented') 22 | 23 | @staticmethod 24 | def __scale__(ipath, position, scale): 25 | img = pygame.image.load(ipath) 26 | rect = img.get_rect(center=position) 27 | w, h = rect.size[0], rect.size[1] 28 | w, h = int(w * scale), int(h * scale) 29 | return pygame.transform.scale(img, (w, h)) 30 | 31 | 32 | class Bullet(BaseObject): 33 | def __init__(self, position, scale=1.0): 34 | BaseObject.__init__(self, './images/bullet.png', position, scale) 35 | 36 | def draw(self, surface, **kwargs): 37 | x, y = self.rect.center 38 | self.rect.center = x, y - 5 39 | 40 | surface.blit(self.image, self.rect.center) 41 | 42 | if y <= 0: 43 | self.kill() 44 | 45 | @staticmethod 46 | def instance(**kwargs): 47 | return Bullet(kwargs['position']) 48 | 49 | 50 | class Rock(BaseObject): 51 | def __init__(self, position, scale=1.0): 52 | BaseObject.__init__(self, './images/rock.png', position, scale) 53 | 54 | def draw(self, surface, **kwargs): 55 | x, y = self.rect.center 56 | self.rect.center = x, y + 1 57 | 58 | surface.blit(self.image, self.rect.center) 59 | 60 | if y >= kwargs['height']: 61 | self.kill() 62 | 63 | 64 | class Ship(BaseObject): 65 | def __init__(self, position, scale=1.0): 66 | BaseObject.__init__(self, './images/ship.png', position, scale) 67 | 68 | def draw(self, surface, **kwargs): 69 | width, height = kwargs['width'], kwargs['height'] 70 | x, y = self.rect.center 71 | w, h = self.rect.size 72 | 73 | if 'keys' in kwargs: 74 | keys = kwargs['keys'] 75 | if keys[K_LEFT] or keys[K_a]: 76 | if x - w / 2.0 >= 0: 77 | x -= 4 78 | elif keys[K_RIGHT] or keys[K_d]: 79 | if x + w / 2.0 <= width: 80 | x += 4 81 | 82 | self.rect.center = x, y 83 | 84 | surface.blit(self.image, self.rect.center) 85 | 86 | 87 | class RockGenerator(object): 88 | def __init__(self, width, height): 89 | rock = Rock((width / 2.0, height / 2.0)) 90 | w, h = rock.rect.size 91 | self.x_pos = [x for x in range(0, width, w)] 92 | self.prev_x = None 93 | self.start_time = None 94 | 95 | def should_generate(self): 96 | if self.start_time is None: 97 | self.start_time = time.time() 98 | return True 99 | 100 | stop_time = time.time() 101 | diff = int(stop_time - self.start_time) 102 | if diff >= 2: 103 | self.start_time = stop_time 104 | return True 105 | return False 106 | 107 | def next(self): 108 | while True: 109 | curr_x = random.choice(self.x_pos) 110 | if curr_x != self.prev_x: 111 | self.prev_x = curr_x 112 | return Rock((curr_x, 20)) 113 | 114 | 115 | class GameInfo(object): 116 | def __init__(self, score, lives): 117 | self.font = pygame.font.Font('freesansbold.ttf', 20) 118 | self.color = (0, 0, 0) 119 | self.position = 10, 10 120 | self.score = score 121 | self.lives = lives 122 | 123 | def __get_drawing_objects__(self): 124 | text_surface = self.font.render(f'Score: {self.score}, Lives: {self.lives}', True, self.color) 125 | rect = text_surface.get_rect() 126 | rect.x, rect.y = 10, 10 127 | 128 | return text_surface, rect 129 | 130 | def draw(self, surface, **kwargs): 131 | self.score = kwargs['score'] 132 | self.lives = kwargs['lives'] 133 | 134 | text_surface, rect = self.__get_drawing_objects__() 135 | surface.blit(text_surface, rect) 136 | 137 | 138 | class GameOverMessage(object): 139 | def __init__(self, width, height, score, lives): 140 | self.game_over_font = pygame.font.Font('freesansbold.ttf', 30) 141 | self.game_info_font = pygame.font.Font('freesansbold.ttf', 20) 142 | self.game_action_font = pygame.font.Font('freesansbold.ttf', 20) 143 | 144 | self.game_over_color = (255, 0, 0) 145 | self.game_info_color = (0, 0, 0) 146 | self.game_action_color = (0, 0, 0) 147 | 148 | self.center = width / 2.0, height / 2.0 149 | self.score = score 150 | self.lives = lives 151 | 152 | def __get_game_over__(self): 153 | text = 'Game Over' 154 | text_surface = self.game_over_font.render(text, True, self.game_over_color) 155 | rect = text_surface.get_rect() 156 | rect.center = self.center 157 | 158 | return text_surface, rect 159 | 160 | def __get_game_info__(self): 161 | text = f'Score: {self.score}, Lives: {self.lives}' 162 | text_surface = self.game_info_font.render(text, True, self.game_info_color) 163 | rect = text_surface.get_rect() 164 | rect.center = self.center[0], self.center[1] + 30 165 | 166 | return text_surface, rect 167 | 168 | def __get_game_action__(self): 169 | text = 'Hit "q" to quit. Hit "c" to continue.' 170 | text_surface = self.game_action_font.render(text, True, self.game_action_color) 171 | rect = text_surface.get_rect() 172 | rect.center = self.center[0], self.center[1] + 60 173 | 174 | return text_surface, rect 175 | 176 | def draw(self, surface): 177 | text_surface, rect = self.__get_game_over__() 178 | surface.blit(text_surface, rect) 179 | 180 | text_surface, rect = self.__get_game_info__() 181 | surface.blit(text_surface, rect) 182 | 183 | text_surface, rect = self.__get_game_action__() 184 | surface.blit(text_surface, rect) 185 | 186 | 187 | class AudioEffects(object): 188 | def __init__(self): 189 | self.effects = { 190 | 'bullet': pygame.mixer.Sound('./audio/bullet.wav'), 191 | 'explosion': pygame.mixer.Sound('./audio/explosion.wav') 192 | } 193 | 194 | def play(self, effect): 195 | if effect in self.effects: 196 | self.effects[effect].play() 197 | -------------------------------------------------------------------------------- /python/pygame/yappy-bird/game.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import pygame 5 | from pygame.constants import QUIT, K_SPACE 6 | 7 | from objects import Bird, Pipe, PipeGenerator 8 | 9 | 10 | def quit_game(): 11 | pygame.quit() 12 | sys.exit() 13 | 14 | 15 | def get_params(): 16 | width = 900 17 | height = 600 18 | 19 | DISPLAYSURF = pygame.display.set_mode((width, height)) 20 | DISPLAYSURF.fill((255, 255, 255)) 21 | 22 | score = 0 23 | 24 | return { 25 | 'FPS': 30, 26 | 'width': width, 27 | 'height': height, 28 | 'DISPLAYSURF': DISPLAYSURF, 29 | 'fps_clock': pygame.time.Clock(), 30 | 'score': score, 31 | 'pipes': [], 32 | 'pipe_group': pygame.sprite.Group(), 33 | 'bird': Bird((width / 10.0, height / 2.0)) 34 | } 35 | 36 | 37 | def start_game(**params): 38 | width, height = params['width'], params['height'] 39 | bird = params['bird'] 40 | score = params['score'] 41 | pipes = params['pipes'] 42 | pipe_group = params['pipe_group'] 43 | DISPLAYSURF = params['DISPLAYSURF'] 44 | fps_clock, FPS = params['fps_clock'], params['FPS'] 45 | 46 | started = False 47 | pipe_gen = PipeGenerator() 48 | 49 | while True: 50 | if not started: 51 | started = pygame.key.get_pressed()[K_SPACE] 52 | 53 | kwargs = { 54 | 'width': width, 55 | 'height': height, 56 | 'keys': pygame.key.get_pressed(), 57 | 'score': score, 58 | 'started': started 59 | } 60 | 61 | for event in pygame.event.get(): 62 | if event.type == QUIT: 63 | quit_game() 64 | 65 | DISPLAYSURF.fill((255, 255, 255, 0)) 66 | 67 | if pipe_gen.should_generate() and started: 68 | t_pipe, b_pipe = pipe_gen.next(**kwargs) 69 | pipes.extend([t_pipe, b_pipe]) 70 | pipe_group.add(t_pipe) 71 | pipe_group.add(b_pipe) 72 | 73 | bird.draw(DISPLAYSURF, **kwargs) 74 | 75 | for pipe in pipes: 76 | pipe.draw(DISPLAYSURF, **kwargs) 77 | 78 | pygame.display.update() 79 | fps_clock.tick(FPS) 80 | 81 | collisions = pygame.sprite.spritecollide(bird, pipes, False) 82 | n_collisions = len(collisions) 83 | if n_collisions > 0: 84 | break 85 | 86 | 87 | def start(): 88 | pygame.init() 89 | pygame.display.set_caption('Yappy Bird') 90 | 91 | params = get_params() 92 | start_game(**params) 93 | 94 | 95 | if __name__ == '__main__': 96 | os.environ['SDL_VIDEO_CENTERED'] = '1' 97 | start() 98 | 99 | -------------------------------------------------------------------------------- /python/pygame/yappy-bird/images/frame-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/yappy-bird/images/frame-1.png -------------------------------------------------------------------------------- /python/pygame/yappy-bird/images/frame-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/yappy-bird/images/frame-2.png -------------------------------------------------------------------------------- /python/pygame/yappy-bird/images/frame-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/yappy-bird/images/frame-3.png -------------------------------------------------------------------------------- /python/pygame/yappy-bird/images/frame-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/yappy-bird/images/frame-4.png -------------------------------------------------------------------------------- /python/pygame/yappy-bird/images/frame-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/yappy-bird/images/frame-5.png -------------------------------------------------------------------------------- /python/pygame/yappy-bird/images/frame-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/yappy-bird/images/frame-6.png -------------------------------------------------------------------------------- /python/pygame/yappy-bird/images/frame-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/yappy-bird/images/frame-7.png -------------------------------------------------------------------------------- /python/pygame/yappy-bird/images/frame-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneoffcoder/lightning-projects/a0df97648b3c2146f21acd9aa41f2116a94a282d/python/pygame/yappy-bird/images/frame-8.png -------------------------------------------------------------------------------- /python/pygame/yappy-bird/objects.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | import uuid 4 | 5 | import pygame 6 | from pygame.constants import K_SPACE 7 | 8 | 9 | class Bird(pygame.sprite.Sprite): 10 | def __init__(self, position, scale=0.1): 11 | pygame.sprite.Sprite.__init__(self) 12 | 13 | paths = [f'./images/frame-{i + 1}.png' for i in range(8)] 14 | imgs = [pygame.image.load(p) for p in paths] 15 | rect = imgs[0].get_rect() 16 | 17 | w, h = rect.size[0], rect.size[1] 18 | w, h = int(w * scale), int(h * scale) 19 | 20 | self.uuid = str(uuid.uuid4()) 21 | self.width, self.height = w, h 22 | self.imgs = [pygame.transform.scale(img, (w, h)) for img in imgs] 23 | self.rect = self.imgs[0].get_rect() 24 | self.rect.center = position[0] - w / 2.0, position[1] - h / 2.0 25 | self.index = 0 26 | self.is_killed = False 27 | 28 | def draw(self, surface, **kwargs): 29 | if self.is_killed: 30 | return 31 | 32 | if kwargs['started']: 33 | if 'keys' in kwargs and kwargs['keys'][K_SPACE]: 34 | dy = -10 35 | else: 36 | dy = 10 37 | else: 38 | dy = 0 39 | 40 | x, y = self.rect.center[0], self.rect.center[1] + dy 41 | y = max(0, y) 42 | y = min(kwargs['height'] - self.height, y) 43 | 44 | self.rect.center = x, y 45 | 46 | surface.blit(self.imgs[self.index], self.rect.center) 47 | self.index += 1 48 | if self.index >= len(self.imgs): 49 | self.index = 0 50 | 51 | if y >= kwargs['height'] - self.height: 52 | self.is_killed = True 53 | self.kill() 54 | 55 | 56 | class Pipe(pygame.sprite.Sprite): 57 | def __init__(self, position, width, height): 58 | pygame.sprite.Sprite.__init__(self) 59 | 60 | self.uuid = str(uuid.uuid4()) 61 | self.color = (10, 200, 10, 1) 62 | self.position = position 63 | self.dimension = width, height 64 | self.rect = (self.position, self.dimension) 65 | self.is_killed = False 66 | 67 | def draw(self, surface, **kwargs): 68 | if self.is_killed: 69 | return 70 | 71 | pygame.draw.rect(surface, self.color, (self.position, self.dimension)) 72 | self.position = self.position[0] - 5, self.position[1] 73 | self.rect = (self.position, self.dimension) 74 | 75 | if self.position[0] <= 0: 76 | self.is_killed = True 77 | self.kill() 78 | 79 | def __repr__(self): 80 | return f'pipe: pos={self.position} | dim={self.dimension}' 81 | 82 | 83 | class PipeGenerator(object): 84 | def __init__(self, pipe_width=70, tb_spacing=200): 85 | self.pipe_width = pipe_width 86 | self.tb_spacing = tb_spacing 87 | self.start_time = None 88 | 89 | def should_generate(self): 90 | if self.start_time is None: 91 | self.start_time = time.time() 92 | return True 93 | 94 | stop_time = time.time() 95 | diff = int(stop_time - self.start_time) 96 | if diff >= 2: 97 | self.start_time = stop_time 98 | return True 99 | return False 100 | 101 | def next(self, **kwargs): 102 | width, height = kwargs['width'], kwargs['height'] 103 | 104 | top_height = random.randint(int(height * 0.25), int(height * 0.50)) 105 | bot_height = height - (top_height + self.tb_spacing) 106 | 107 | top_x, top_y = width, 0 108 | bot_x, bot_y = width, top_height + self.tb_spacing 109 | 110 | top_pipe = Pipe((top_x, top_y), self.pipe_width, top_height) 111 | bot_pipe = Pipe((bot_x, bot_y), self.pipe_width, bot_height) 112 | 113 | return top_pipe, bot_pipe 114 | --------------------------------------------------------------------------------