今回はプログラミング言語の「Python」を使って作成しました。
インベーダーゲームです。敵の数と速度とHPを増やして難しくしました。
■ プログラム
import traceback try: import sys from random import randint import pygame from pygame.locals import Rect, QUIT, KEYDOWN, \ K_LEFT, K_RIGHT, K_SPACE #----------------------------------------------------------- # グローバル変数 #----------------------------------------------------------- # Pygame初期設定 pygame.init() pygame.key.set_repeat(5, 5) SURFACE = pygame.display.set_mode((600, 600)) FPSCLOCK = pygame.time.Clock() BLOCKS = [] #----------------------------------------------------------- # スーパークラス定義 #----------------------------------------------------------- class Drawable: """ 全ての描画オブジェクトのスーパークラス """ def __init__(self, rect, offset0, offset1): strip = pygame.image.load("strip.png") self.images = (pygame.Surface((24, 24), pygame.SRCALPHA), pygame.Surface((24, 24), pygame.SRCALPHA)) self.rect = rect self.count = 0 self.images[0].blit(strip, (0, 0), Rect(offset0, 0, 24, 24)) self.images[1].blit(strip, (0, 0), Rect(offset1, 0, 24, 24)) def move(self, diff_x, diff_y): """ オブジェクトを移動 """ self.count += 1 self.rect.move_ip(diff_x, diff_y) def draw(self): """ オブジェクトを描画 """ image = self.images[0] if self.count % 2 == 0 \ else self.images[1] SURFACE.blit(image, self.rect.topleft) #----------------------------------------------------------- # サブクラス定義 #----------------------------------------------------------- class Block: """ ブロックオブジェクト """ def __init__(self, col, rect): self.col = col self.rect = rect self.blockHP = 5 self.visibleFlag = True def draw(self): """ ブロックを描画する """ pygame.draw.rect(SURFACE, self.col, self.rect) class Ship(Drawable): """ 自機オブジェクト """ def __init__(self): super().__init__(Rect(300, 550, 24, 24), 192, 192) class Beam(Drawable): """ ビームオブジェクト """ def __init__(self): super().__init__(Rect(300, 0, 24, 24), 0, 24) class Bomb(Drawable): """ 爆弾オブジェクト """ def __init__(self): super().__init__(Rect(300, -50, 24, 24), 48, 72) self.time = randint(5, 220) class Alien(Drawable): """ エイリアンオブジェクト """ def __init__(self, rect, offset, score): super().__init__(rect, offset, offset+24) self.score = score self.HP = 3 self.visibleFlag = True #----------------------------------------------------------- # メインルーチン #----------------------------------------------------------- def main(): global BLOCKS sysfont = pygame.font.SysFont(None, 72) scorefont = pygame.font.SysFont(None, 36) message_clear = sysfont.render("!!CLEARED!!", True, (0, 255, 225)) message_over = sysfont.render("GAME OVER!!", True, (0, 255, 225)) message_rect = message_clear.get_rect() message_rect.center = (300, 300) game_over = False moving_left = True moving_down = False move_interval = 10 counter = 0 score = 0 aliens = [] bombs = [] #----------------------------------------------------------- # インスタンス生成 #----------------------------------------------------------- ship = Ship() beam = Beam() # ブロック生成 colors = [(255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0), (255, 0, 0)] for ypos, color in enumerate(colors): for xpos in range(0, 5): BLOCKS.append(Block(color, Rect(xpos * 100 + 70, ypos * 10 + 450, 60, 10))) # エイリアンの並びを初期化 for ypos in range(8): offset = 96 if ypos < 2 else 144 for xpos in range(10): rect = Rect(100+xpos*50, ypos*50 + 50, 24, 24) alien = Alien(rect, offset, (8-ypos)*10) aliens.append(alien) # 爆弾を設定 for _ in range(8): bombs.append(Bomb()) #---------------------------------------------------------------------------------- # ループ処理 #---------------------------------------------------------------------------------- while True: ship_move_x = 0 for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_LEFT: ship_move_x = -5 elif event.key == K_RIGHT: ship_move_x = +5 elif event.key == K_SPACE and beam.rect.bottom < 0: beam.rect.center = ship.rect.center if not game_over: counter += 1 #----------------------------------------------------------- # 移動処理 #----------------------------------------------------------- # 自機を移動 ship.move(ship_move_x, 0) # ビームを移動 beam.move(0, -10) # エイリアンを移動 area = aliens[0].rect.copy() for alien in aliens: area.union_ip(alien.rect) if counter % move_interval == 0: move_x = -5 if moving_left else 5 move_y = 0 if (area.left < 10 or area.right > 590) and \ not moving_down: moving_left = not moving_left move_x, move_y = 0, 24 move_interval = max(1, move_interval - 2) moving_down = True else: moving_down = False for alien in aliens: alien.move(move_x, move_y) if area.bottom > 550: game_over = True # 爆弾を移動 HitFlag = False # bombとblockの当たり判定用フラグ for bomb in bombs: if bomb.time < counter and bomb.rect.top < 0: enemy = aliens[randint(0, len(aliens) - 1)] bomb.rect.center = enemy.rect.center if bomb.rect.top > 0: bomb.move(0, 10) for x in BLOCKS: if x.rect.colliderect(bomb.rect): x.blockHP -= 1 HitFlag = True if x.blockHP < 1: x.visibleFlag = False BLOCKS = [x for x in BLOCKS if x.visibleFlag] #BLOCKS = [x for x in BLOCKS if not x.rect.colliderect(bomb.rect)] if bomb.rect.top > 600 or HitFlag == True: bomb.time += randint(50, 250) bomb.rect.top = -50 HitFlag = False if bomb.rect.colliderect(ship.rect): game_over = True #----------------------------------------------------------- # 衝突処理 #----------------------------------------------------------- # ビームがブロックと衝突 for x in BLOCKS: if x.rect.colliderect(beam.rect): x.blockHP -= 1 beam.rect.top = -50 if x.blockHP < 1: x.visibleFlag = False BLOCKS = [x for x in BLOCKS if x.visibleFlag] #BLOCKS = [x for x in BLOCKS if not x.rect.colliderect(beam.rect)] # ビームがエイリアンと衝突? tmp = [] for alien in aliens: # エイリアンとブロックが衝突 for block in BLOCKS: if alien.rect.colliderect(block.rect): BLOCKS = [x for x in BLOCKS if not x.rect.colliderect(block.rect)] if alien.rect.collidepoint(beam.rect.center): alien.HP -= 1 beam.rect.top = -50 if alien.HP < 1: score += alien.score if alien.HP > 0: tmp.append(alien) aliens = tmp if len(aliens) == 0: game_over = True #----------------------------------------------------------- # 描画処理 #----------------------------------------------------------- # 描画 SURFACE.fill((0, 0, 0)) for alien in aliens: alien.draw() ship.draw() beam.draw() for bomb in bombs: bomb.draw() for block in BLOCKS: block.draw() score_str = str(score).zfill(5) score_image = scorefont.render(score_str, True, (0, 255, 0)) SURFACE.blit(score_image, (500, 10)) if game_over: if len(aliens) == 0: SURFACE.blit(message_clear, message_rect.topleft) else: SURFACE.blit(message_over, message_rect.topleft) pygame.display.update() FPSCLOCK.tick(30) #----------------------------------------------------------- # エントリポイント #----------------------------------------------------------- if __name__ == '__main__': main() except Exception as e: # 文字列を取得する format_exec()メソッド print("エラー情報\n" + traceback.format_exc()) input() |
■ 参考書
「ゲームを作りながら楽しく学べるPythonプログラミング (Future Coders(NextPublishing))」
■ ゲーム用ライブラリ
「Pygame」
■ プログラミング言語