├── LICENSE ├── README ├── boom.wav ├── game.mpy ├── game.py ├── main.py ├── pew.wav └── tiles.bmp /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Radomir Dopieralski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a game for the µGame game console, based on the classic Space Invaders 2 | arcade game. 3 | 4 | Note that because of memory requirements, you should copy the game.mpy and not 5 | the game.py file onto the device. This is a compiled version of the same 6 | program, and it takes less memory to load. 7 | 8 | Future version will probably be better optimized and will be able to run the 9 | uncompiled version directly, but for now there is this workaround. 10 | -------------------------------------------------------------------------------- /boom.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/python-ugame/vacuum-invaders/bcb9e68034e85eb7227a6716a923e4bf203d92f5/boom.wav -------------------------------------------------------------------------------- /game.mpy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/python-ugame/vacuum-invaders/bcb9e68034e85eb7227a6716a923e4bf203d92f5/game.mpy -------------------------------------------------------------------------------- /game.py: -------------------------------------------------------------------------------- 1 | import ugame 2 | import stage 3 | import random 4 | import time 5 | 6 | 7 | class Ship(stage.Sprite): 8 | def __init__(self): 9 | super().__init__(tiles, 4, 56, 102) 10 | self.dx = 0 11 | self.x = 56 12 | self.tick = 0 13 | self.dead = False 14 | 15 | def update(self): 16 | super().update() 17 | self.tick = not self.tick 18 | 19 | keys = ugame.buttons.get_pressed() 20 | self.set_frame(4, 0 if self.tick else 4) 21 | if keys & ugame.K_RIGHT: 22 | self.dx = min(self.dx + 1, 4) 23 | self.set_frame(5, 0) 24 | elif keys & ugame.K_LEFT: 25 | self.dx = max(self.dx - 1, -4) 26 | self.set_frame(5, 4) 27 | else: 28 | self.dx = self.dx // 2 29 | if keys & ugame.K_X: 30 | if missile.y <= -16: 31 | missile.move(self.x, self.y) 32 | sound.play(pew_sound) 33 | elif missile1.y <= 16: 34 | missile1.move(self.x, self.y) 35 | sound.play(pew_sound) 36 | elif missile2.y <= 16: 37 | missile2.move(self.x, self.y) 38 | sound.play(pew_sound) 39 | if keys & ugame.K_O: 40 | pause(" Pause...") 41 | self.x = max(min(self.x + self.dx, 112), 0) 42 | self.move(self.x, self.y) 43 | 44 | 45 | class Saucer(stage.Sprite): 46 | def __init__(self): 47 | super().__init__(tiles, 9, 0, 0) 48 | self.tick = 0 49 | self.dx = 4 50 | 51 | def update(self): 52 | super().update() 53 | self.tick = (self.tick + 1) % 6 54 | self.layer.frame(9, 0 if self.tick >= 3 else 4) 55 | if self.x >= 128 or self.x <= -16: 56 | self.dx = -self.dx 57 | self.move(self.x + self.dx, self.y) 58 | if abs(self.x - ship.x) < 4 and bomb.y >= 128: 59 | bomb.move(self.x, self.y) 60 | 61 | 62 | class Bomb(stage.Sprite): 63 | def __init__(self): 64 | super().__init__(tiles, 6, 0, 128) 65 | self.boom = 0 66 | 67 | def update(self): 68 | super().update() 69 | if self.y >= 128: 70 | return 71 | if self.boom: 72 | if self.boom == 1: 73 | sound.play(boom_sound) 74 | self.set_frame(12 + self.boom, 0) 75 | self.boom += 1 76 | if self.boom > 4: 77 | self.boom = 0 78 | ship.dead = True 79 | self.move(self.x, 128) 80 | return 81 | self.move(self.x, self.y + 8) 82 | self.set_frame(6, 0 if self.y % 16 else 4) 83 | if stage.collide(self.x + 4, self.y + 4, self.x + 12, self.y + 12, 84 | ship.x + 4, ship.y + 4, ship.x + 12, ship.y + 12): 85 | self.boom = 1 86 | 87 | 88 | class Missile(stage.Sprite): 89 | def __init__(self, power): 90 | super().__init__(tiles, 12, 0, -32) 91 | self.boom = 0 92 | self.power = power 93 | 94 | def update(self): 95 | super().update() 96 | if self.boom: 97 | if self.boom == 1: 98 | sound.play(boom_sound) 99 | self.set_frame(12 + self.boom) 100 | self.boom += 1 101 | if self.boom > 4: 102 | self.boom = 0 103 | self.kill() 104 | aliens.tile(self.ax, self.ay, 0) 105 | aliens.dirty = True 106 | return 107 | 108 | if self.y <= -32: 109 | return 110 | self.move(self.x, self.y - 8) 111 | self.set_frame(12 - self.power, 0 if self.y % 16 == 6 else 4) 112 | self.ax = (self.x + 8 - aliens.x) // 16 113 | self.ay = (self.y + 4 - aliens.y) // 16 114 | if aliens.tile(self.ax, self.ay) and (self.x + 10 - aliens.x) % 16 > 4: 115 | aliens.tile(self.ax, self.ay, 7) 116 | self.move(self.x, self.y - 4) 117 | self.boom = 1 118 | 119 | def kill(self): 120 | self.move(self.x, -32) 121 | self.set_frame(12 - self.power) 122 | 123 | 124 | class Aliens(stage.Grid): 125 | def __init__(self): 126 | super().__init__(tiles, 7, 3) 127 | for y in range(3): 128 | for x in range(7): 129 | self.tile(x, y, 8) 130 | self.tick = self.left = self.right = self.descend = 0 131 | self.dx = 2 132 | self.dirty = False 133 | 134 | def update(self): 135 | self.tick = (self.tick + 1) % 4 136 | self.layer.frame(0, 0 if self.tick >= 2 else 4) 137 | if self.tick in (0, 2): 138 | if self.x >= 14 + self.right or self.x <= 2 - self.left: 139 | self.y += 1 140 | self.descend += 1 141 | if self.descend >= 4: 142 | self.descend = 0 143 | self.dx = -self.dx 144 | self.x += self.dx 145 | else: 146 | self.x += self.dx 147 | self.move(self.x, self.y) 148 | 149 | def reform(self): 150 | self.left = 16 * 6 151 | self.right = 16 * 6 152 | for x in range(7): 153 | for y in range(3): 154 | if self.tile(x, y): 155 | self.left = min(16 * x, self.left) 156 | self.right = min(96 - 16 * x, self.right) 157 | self.dirty = False 158 | 159 | 160 | def pause(info): 161 | while ugame.buttons.get_pressed() & ugame.K_O: 162 | time.sleep(0.25) 163 | text.cursor(0, 0) 164 | text.text(info) 165 | game.render_block() 166 | while not ugame.buttons.get_pressed() & ugame.K_O: 167 | time.sleep(0.25) 168 | text.clear() 169 | game.render_block() 170 | while ugame.buttons.get_pressed() & ugame.K_O: 171 | time.sleep(0.25) 172 | 173 | 174 | tiles = stage.Bank.from_bmp16("tiles.bmp") 175 | while True: 176 | space = stage.Grid(tiles) 177 | aliens = Aliens() 178 | game = stage.Stage(ugame.display, 12) 179 | for y in range(8): 180 | for x in range(8): 181 | space.tile(x, y, 1) 182 | for i in range(8): 183 | space.tile(random.randint(0, 7), random.randint(0, 7), 184 | random.randint(2, 3)) 185 | aliens.move(8, 17) 186 | saucer = Saucer() 187 | bomb = Bomb() 188 | ship = Ship() 189 | missile = Missile(0) 190 | missile1 = Missile(1) 191 | missile2 = Missile(2) 192 | text = stage.Text(9, 1) 193 | text.move(28, 60) 194 | sprites = [saucer, bomb, ship, missile, missile1, missile2] 195 | game.layers = [text] + sprites + [aliens, space] 196 | game.render_block() 197 | pew_sound = open("pew.wav", 'rb') 198 | boom_sound = open("boom.wav", 'rb') 199 | sound = ugame.audio 200 | sound.mute(False) 201 | 202 | while aliens.left + aliens.right < 112 and aliens.y < 80 and not ship.dead: 203 | for sprite in sprites: 204 | sprite.update() 205 | aliens.update() 206 | game.render_sprites(sprites) 207 | game.render_block(aliens.x + aliens.left - 1, aliens.y - 1, 208 | aliens.x + 113 - aliens.right, aliens.y + 48) 209 | if aliens.dirty: 210 | aliens.reform() 211 | game.tick() 212 | 213 | if ship.dead or aliens.y >= 80: 214 | pause("Game Over") 215 | else: 216 | pause("You won!") 217 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import game 2 | -------------------------------------------------------------------------------- /pew.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/python-ugame/vacuum-invaders/bcb9e68034e85eb7227a6716a923e4bf203d92f5/pew.wav -------------------------------------------------------------------------------- /tiles.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/python-ugame/vacuum-invaders/bcb9e68034e85eb7227a6716a923e4bf203d92f5/tiles.bmp --------------------------------------------------------------------------------