著者| Li Qiujian
プロデュース| AIテクノロジーベースキャンプ(rgznai100)
「タンクバトル」は、1985年に日本のナムコゲームカンパニーがニンテンドーFCプラットフォームで立ち上げた多面的な飛行機射撃ゲームです。このゲームは、戦略的なオンラインカテゴリである戦車戦と基地の防衛をテーマにしています。同時に、FCプラットフォームでは珍しいレベルエディターを内蔵した数少ないゲームの1つでもあり、プレイヤーはいくつかの小道具を入手することで、独自のレベルを作成し、タンクとベースを強化できます。今日は、pythonを使用して、次の戦車戦の生産を復元します。
実験前の準備
まず、使用するPythonのバージョンは3.6.5です。使用するモジュールは次のとおりです。
魔神プログラム
その中で、ウィザードクラスは、弾丸プログラム、食べ物、家、レンガの壁、木やその他の障害物、タンクなどの主要な機能を呼び出すための基本的なプログラムフレームワークとして使用されます。具体的なプログラムのレイアウトは次のとおりです。
弾丸プログラムの中で、弾丸の位置、方向、画像の読み込み、弾丸の速度などの基本情報を含むbullet.pyプログラムを最初に確立する必要があります。具体的なコードは次のとおりです。
''' 弾丸'''classBullet(pygame.sprite.Sprite):
def __init__(self, bullet_image_paths, screensize, direction, position, border_len, is_stronger=False, speed=8,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.bullet_image_paths = bullet_image_paths
self.width, self.height = screensize
self.direction = direction
self.position = position
self.image = pygame.image.load(self.bullet_image_paths.get(direction))
self.rect = self.image.get_rect()
self.rect.center = position
# マップのエッジ幅
self.border_len = border_len
# それは強化された弾丸ですか(壊れた鉄の壁の強化版)
self.is_stronger = is_stronger
# 弾丸の速度
self.speed = speed
''' 弾丸を動かす,弾丸が範囲外になった場合,次にTrueを返します,それ以外の場合はFalse'''
def move(self):if self.direction =='up':
self.rect = self.rect.move(0,-self.speed)
elif self.direction =='down':
self.rect = self.rect.move(0, self.speed)
elif self.direction =='left':
self.rect = self.rect.move(-self.speed,0)
elif self.direction =='right':
self.rect = self.rect.move(self.speed,0)if(self.rect.top < self.border_len)or(self.rect.bottom > self.height)or(self.rect.left < self.border_len)or(self.rect.right > self.width):return True
return False
食品報酬カテゴリ、タンクが食品を食べるときの寿命を延ばすなどの基本的な報酬としてfood.pyを確立します。
''' 食物.報酬を得るために使用されます'''classFoods(pygame.sprite.Sprite):
def __init__(self, food_image_paths, screensize,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.name = random.choice(list(food_image_paths.keys()))
self.image = pygame.image.load(food_image_paths.get(self.name))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = random.randint(100, screensize[0]-100), random.randint(100, screensize[1]-100)
self.exist_time =1000
def update(self):
self.exist_time -=1return True if self.exist_time <0else False
タンクファミリの場合、home.pyを作成して、基本情報(生きているかどうか、画像の読み込み、場所のサイズなど)を保存します。
''' ベースキャンプ'''classHome(pygame.sprite.Sprite):
def __init__(self, position, imagepaths,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.imagepaths = imagepaths
self.image = pygame.image.load(self.imagepaths[0])
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
self.alive = True
''' 破壊されました'''
def setDead(self):
self.image = pygame.image.load(self.imagepaths[1])
self.alive = False
''' 画面に描く'''
def draw(self, screen):
screen.blit(self.image, self.rect)
レンガの壁などの障害物の場合は、メインの位置サイズでもあるscenes.pyのレイアウトを作成します。
''' れんが壁'''classBrick(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
''' 鉄の壁'''classIron(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
''' 氷'''classIce(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((24,24))for i inrange(2):for j inrange(2):
self.image.blit(pygame.image.load(imagepath),(12*i,12*j))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
''' 川'''classRiver(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((24,24))for i inrange(2):for j inrange(2):
self.image.blit(pygame.image.load(imagepath),(12*i,12*j))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
''' 木'''classTree(pygame.sprite.Sprite):
def __init__(self, position, imagepath,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((24,24))for i inrange(2):for j inrange(2):
self.image.blit(pygame.image.load(imagepath),(12*i,12*j))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = position
タンクの場合は、tanks.pyを作成して、タンクの数、初期位置などの情報を含めます。
''' プレイヤータンク'''classPlayerTank(pygame.sprite.Sprite):
def __init__(self, name, player_tank_image_paths, position, border_len, screensize, direction='up', bullet_image_paths=None, protected_mask_path=None, boom_image_path=None,**kwargs):
pygame.sprite.Sprite.__init__(self)
# プレーヤー1/プレーヤー2
self.name = name
# タンクピクチャーパス
self.player_tank_image_paths = player_tank_image_paths.get(name)
# マップのエッジ幅
self.border_len = border_len
# 画面サイズ
self.screensize = screensize
# タンクの初期方向
self.init_direction = direction
# 初期位置
self.init_position = position
# 弾丸の写真
self.bullet_image_paths = bullet_image_paths
# 保護カバーの画像パス
self.protected_mask = pygame.image.load(protected_mask_path)
self.protected_mask_flash_time =25
self.protected_mask_flash_count =0
self.protected_mask_pointer = False
# タンク爆発ビュー
self.boom_image = pygame.image.load(boom_image_path)
self.boom_last_time =5
self.booming_flag = False
self.boom_count =0
# タンク寿命の数
self.num_lifes =3
# リセット
self.reset()'''モバイル'''
def move(self, direction, scene_elems, player_tanks_group, enemy_tanks_group, home):
# 爆発時に動かない
if self.booming_flag:return
# 方向が一貫していない場合は、最初に方向を変更してください
if self.direction != direction:
self.setDirection(direction)
self.switch_count = self.switch_time
self.move_cache_count = self.move_cache_time
# モバイル(バッファを使用する)
self.move_cache_count +=1if self.move_cache_count < self.move_cache_time:return
self.move_cache_count =0if self.direction =='up':
speed =(0,-self.speed)
elif self.direction =='down':
speed =(0, self.speed)
elif self.direction =='left':
speed =(-self.speed,0)
elif self.direction =='right':
speed =(self.speed,0)
rect_ori = self.rect
self.rect = self.rect.move(speed)
# - - 出会いのシーン要素
for key, value in scene_elems.items():if key in['brick_group','iron_group','river_group']:if pygame.sprite.spritecollide(self, value, False, None):
self.rect = rect_ori
elif key in['ice_group']:if pygame.sprite.spritecollide(self, value, False, None):
self.rect = self.rect.move(speed)
# - - 他のプレイヤーの戦車に遭遇した
if pygame.sprite.spritecollide(self, player_tanks_group, False, None):
self.rect = rect_ori
# - - 敵の戦車に遭遇
if pygame.sprite.spritecollide(self, enemy_tanks_group, False, None):
self.rect = rect_ori
# - - プレイヤーベースキャンプに会う
if pygame.sprite.collide_rect(self, home):
self.rect = rect_ori
# - - 境界を打つ
if self.rect.left < self.border_len:
self.rect.left = self.border_len
elif self.rect.right > self.screensize[0]-self.border_len:
self.rect.right = self.screensize[0]- self.border_len
elif self.rect.top < self.border_len:
self.rect.top = self.border_len
elif self.rect.bottom > self.screensize[1]-self.border_len:
self.rect.bottom = self.screensize[1]- self.border_len
# タンクホイールモーションエフェクトの写真を切り替える
self.switch_count +=1if self.switch_count > self.switch_time:
self.switch_count =0
self.switch_pointer = not self.switch_pointer
self.image = self.tank_direction_image.subsurface((48*int(self.switch_pointer),0),(48,48))
ゲームインターフェース設定
ゲームインターフェイス設定には、開始インターフェイス設定、終了インターフェイス設定、およびレベル切り替えインターフェイス設定が含まれます。
ゲーム開始インターフェースには、プレーヤー数の選択と写真と音楽のロードが含まれます。
''' ゲーム開始インターフェース'''
def gameStartInterface(screen, cfg):
background_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('background'))
color_white =(255,255,255)
color_red =(255,0,0)
font = pygame.font.Font(cfg.FONTPATH, cfg.WIDTH//12)
logo_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('logo'))
logo_img = pygame.transform.scale(logo_img,(446,70))
logo_rect = logo_img.get_rect()
logo_rect.centerx, logo_rect.centery = cfg.WIDTH/2, cfg.HEIGHT//4
tank_cursor = pygame.image.load(cfg.PLAYER_TANK_IMAGE_PATHS.get('player1')[0]).convert_alpha().subsurface((0,144),(48,48))
tank_rect = tank_cursor.get_rect()
# プレイヤー選択数
player_render_white = font.render('1 PLAYER', True, color_white)
player_render_red = font.render('1 PLAYER', True, color_red)
player_rect = player_render_white.get_rect()
player_rect.left, player_rect.top = cfg.WIDTH/2.8, cfg.HEIGHT/2.5
players_render_white = font.render('2 PLAYERS', True, color_white)
players_render_red = font.render('2 PLAYERS', True, color_red)
players_rect = players_render_white.get_rect()
players_rect.left, players_rect.top = cfg.WIDTH/2.8, cfg.HEIGHT/2
# ゲームのヒント
game_tip = font.render('press <Enter> to start', True, color_white)
game_tip_rect = game_tip.get_rect()
game_tip_rect.centerx, game_tip_rect.top = cfg.WIDTH/2, cfg.HEIGHT/1.4
game_tip_flash_time =25
game_tip_flash_count =0
game_tip_show_flag = True
# メインループ
clock = pygame.time.Clock()
is_dual_mode = False
while True:for event in pygame.event.get():if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RETURN:return is_dual_mode
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_w or event.key == pygame.K_s:
is_dual_mode = not is_dual_mode
screen.blit(background_img,(0,0))
screen.blit(logo_img, logo_rect)
game_tip_flash_count +=1if game_tip_flash_count > game_tip_flash_time:
game_tip_show_flag = not game_tip_show_flag
game_tip_flash_count =0if game_tip_show_flag:
screen.blit(game_tip, game_tip_rect)if not is_dual_mode:
tank_rect.right, tank_rect.top = player_rect.left-10, player_rect.top
screen.blit(tank_cursor, tank_rect)
screen.blit(player_render_red, player_rect)
screen.blit(players_render_white, players_rect)else:
tank_rect.right, tank_rect.top = players_rect.left-10, players_rect.top
screen.blit(tank_cursor, tank_rect)
screen.blit(player_render_white, player_rect)
screen.blit(players_render_red, players_rect)
pygame.display.update()
clock.tick(60)
ゲーム終了インターフェースには、ゲームの勝利と失敗の判断、およびゲームを終了するか設定を再開するかが含まれます。
''' ゲームオーバーインターフェース'''
def gameEndIterface(screen, cfg, is_win=True):
background_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('background'))
color_white =(255,255,255)
color_red =(255,0,0)
font = pygame.font.Font(cfg.FONTPATH, cfg.WIDTH//12)
# ゲーム失敗グラフ
gameover_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('gameover'))
gameover_img = pygame.transform.scale(gameover_img,(150,75))
gameover_img_rect = gameover_img.get_rect()
gameover_img_rect.midtop = cfg.WIDTH/2, cfg.HEIGHT/8
gameover_flash_time =25
gameover_flash_count =0
gameover_show_flag = True
# ゲームに勝つためのヒント
if is_win:
font_render = font.render('Congratulations, You win!', True, color_white)else:
font_render = font.render('Sorry, You fail!', True, color_white)
font_rect = font_render.get_rect()
font_rect.centerx, font_rect.centery = cfg.WIDTH/2, cfg.HEIGHT/3
# オプトアウトまたは再起動に使用されます
tank_cursor = pygame.image.load(cfg.PLAYER_TANK_IMAGE_PATHS.get('player1')[0]).convert_alpha().subsurface((0,144),(48,48))
tank_rect = tank_cursor.get_rect()
restart_render_white = font.render('RESTART', True, color_white)
restart_render_red = font.render('RESTART', True, color_red)
restart_rect = restart_render_white.get_rect()
restart_rect.left, restart_rect.top = cfg.WIDTH/2.4, cfg.HEIGHT/2
quit_render_white = font.render('QUIT', True, color_white)
quit_render_red = font.render('QUIT', True, color_red)
quit_rect = quit_render_white.get_rect()
quit_rect.left, quit_rect.top = cfg.WIDTH/2.4, cfg.HEIGHT/1.6
is_quit_game = False
# メインループ
clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RETURN:return is_quit_game
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_w or event.key == pygame.K_s:
is_quit_game = not is_quit_game
screen.blit(background_img,(0,0))
gameover_flash_count +=1if gameover_flash_count > gameover_flash_time:
gameover_show_flag = not gameover_show_flag
gameover_flash_count =0if gameover_show_flag:
screen.blit(gameover_img, gameover_img_rect)
screen.blit(font_render, font_rect)if not is_quit_game:
tank_rect.right, tank_rect.top = restart_rect.left-10, restart_rect.top
screen.blit(tank_cursor, tank_rect)
screen.blit(restart_render_red, restart_rect)
screen.blit(quit_render_white, quit_rect)else:
tank_rect.right, tank_rect.top = quit_rect.left-10, quit_rect.top
screen.blit(tank_cursor, tank_rect)
screen.blit(restart_render_white, restart_rect)
screen.blit(quit_render_red, quit_rect)
pygame.display.update()
clock.tick(60)
ゲームインターフェイススイッチは、主に進行状況バーによって読み込まれます。
''' レベル切り替えインターフェース'''
def switchLevelIterface(screen, cfg, level_next=1):
background_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('background'))
color_white =(255,255,255)
color_gray =(192,192,192)
font = pygame.font.Font(cfg.FONTPATH, cfg.WIDTH//20)
logo_img = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('logo'))
logo_img = pygame.transform.scale(logo_img,(446,70))
logo_rect = logo_img.get_rect()
logo_rect.centerx, logo_rect.centery = cfg.WIDTH/2, cfg.HEIGHT//4
# ゲームの読み込みのヒント
font_render = font.render('Loading game data, You will enter Level-%s'% level_next, True, color_white)
font_rect = font_render.get_rect()
font_rect.centerx, font_rect.centery = cfg.WIDTH/2, cfg.HEIGHT/2
# ゲームの読み込みの進行状況バー
gamebar = pygame.image.load(cfg.OTHER_IMAGE_PATHS.get('gamebar')).convert_alpha()
gamebar_rect = gamebar.get_rect()
gamebar_rect.centerx, gamebar_rect.centery = cfg.WIDTH/2, cfg.HEIGHT/1.4
tank_cursor = pygame.image.load(cfg.PLAYER_TANK_IMAGE_PATHS.get('player1')[0]).convert_alpha().subsurface((0,144),(48,48))
tank_rect = tank_cursor.get_rect()
tank_rect.left = gamebar_rect.left
tank_rect.centery = gamebar_rect.centery
# 読み込み時間
load_time_left = gamebar_rect.right - tank_rect.right +8
# メインループ
clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == pygame.QUIT:
pygame.quit()
sys.exit()if load_time_left <=0:return
screen.blit(background_img,(0,0))
screen.blit(logo_img, logo_rect)
screen.blit(font_render, font_rect)
screen.blit(gamebar, gamebar_rect)
screen.blit(tank_cursor, tank_rect)
pygame.draw.rect(screen, color_gray,(gamebar_rect.left+8, gamebar_rect.top+8, tank_rect.left-gamebar_rect.left-8, tank_rect.bottom-gamebar_rect.top-16))
tank_rect.left +=1
load_time_left -=1
pygame.display.update()
clock.tick(60)
完全なコード:
抽出コード:09bl
著者:Qiuキー
***CSDNブログの専門家、CSDNマスタークラスの作成者。中国鉱業技術大学の修士号、開発におけるタッパップコンペティションアワードなど。 ***
Recommended Posts