こんにちは友人! 今日はようやくマリオの戦いを終えます。 こことここから始めて ください 。 ただし、レベルエディタの形式で自転車を発明するのではなく、既製の強力なツールを使用します 。 紳士(同志)のソースラーとタービッツに感謝している知り合いのために
なぜそう
これにはいくつかの理由があります。
- 便利なレベルエディターを5分で書くことはできません。この時間を費やしてゲーム自体を完成させることをお勧めします
- 外観の異なるブロックタイプをゲームに追加する簡単な方法
- タイルマップエディターは2Dゲームの汎用ツールです。一度処理すると、さまざまな言語や技術で記述されたさまざまなゲームのレベルを生成するスキルが得られます
ヒーローにトラブルや障害を作成します
タイルマップエディターの操作については、たとえばこちらをご覧ください 。
ゲーム専用のレベルを作成する主なポイントについて説明します。
マップは少なくとも5つのレイヤーで構成されています。
- バックグラウンド-背景
- プラットフォーム -実行できるブロック
- DieBlocks-主人公に触れるブロックが即死を引き起こす
- モンスター -オブジェクトのレイヤー、ここに私たちのモンスター、そして王女とヒーロー自身
- テレポート-オブジェクトの層、そのため-名前で明確
背景
ここでは、何でも何でも描画できます。このレイヤーのタイルは、おそらくゲームの審美的な外観を除いて、ヒーローやゲームプロセスに影響を与えません。
実行するブロック
このレイヤーには、ゲームのPlatformクラスのオブジェクトを作成するタイルがあります
致命的なブロック
すべてのタイルは、外観(スパイクまたはレンガの壁)に関係なく、ゲーム内でBlockDieクラスのオブジェクトを作成します
モンスター
これはオブジェクトのレイヤーです。つまり、ゲーム内でタイルを表示せず、追加する各オブジェクトにはいくつかのプロパティが必要です。
コンストラクターの形式が次のモンスタークラスオブジェクト
class Monster(sprite.Sprite): def __init__(self, x, y, left, up, maxLengthLeft,maxLengthUp):
left 、 maxLeft 、 up 、 maxUp-手動で入力されたプロパティ 、およびx 、 y-オブジェクトの場所によって送信されたプロパティなどを必ず持ってください。
キャラクターオブジェクトの名前はPlayerでなければなりません
プリンセスオブジェクトはプリンセスという名前にする必要があります
レイヤータイプ:
テレポーター
このレイヤーのオブジェクトには、ヒーローの移動の最終目的地であるgoXとgoYのプロパティが必要です。
レイヤー:
最終的な座標を知る方法は?
簡単! ヒーローをテレポートさせたい場所にマウスカーソルを移動し、左下からその場所の座標を確認します
ゲームカード
上記で作成したマップを開くために、ゲームのメインファイルを変更しましょう。
開始するには、 ここから必要なライブラリをダウンロードして、ゲームソースフォルダーに入れます。
そしてそれらをインポートする
import tmxreader # tmx import helperspygame # tmx pygame
次に、 loadLevel()プロシージャをクリアし、書き換えます。
負荷レベル
def loadLevel(name): global playerX, playerY # , global total_level_height, total_level_width global sprite_layers # world_map = tmxreader.TileMapParser().parse_decode('%s/%s.tmx' % (FILE_DIR, name)) # resources = helperspygame.ResourceLoaderPygame() # resources.load(world_map) # pygame sprite_layers = helperspygame.get_layers_from_map(resources) # # 0 - , 1- , 2 - # 3 - , 4 - platforms_layer = sprite_layers[1] dieBlocks_layer = sprite_layers[2] for row in range(0, platforms_layer.num_tiles_x): # for col in range(0, platforms_layer.num_tiles_y): if platforms_layer.content2D[col][row] is not None: pf = Platform(row * PLATFORM_WIDTH, col * PLATFORM_WIDTH)# Platform platforms.append(pf) if dieBlocks_layer.content2D[col][row] is not None: bd = BlockDie(row * PLATFORM_WIDTH, col * PLATFORM_WIDTH) platforms.append(bd) teleports_layer = sprite_layers[4] for teleport in teleports_layer.objects: try: # goX = int(teleport.properties["goX"]) * PLATFORM_WIDTH goY = int (teleport.properties["goY"]) * PLATFORM_HEIGHT x = teleport.x y = teleport.y - PLATFORM_HEIGHT tp = BlockTeleport(x, y, goX, goY) entities.add(tp) platforms.append(tp) animatedEntities.add(tp) except: # , print(u" ") monsters_layer = sprite_layers[3] for monster in monsters_layer.objects: try: x = monster.x y = monster.y if monster.name == "Player": playerX = x playerY = y - PLATFORM_HEIGHT elif monster.name == "Princess": pr = Princess(x, y - PLATFORM_HEIGHT) platforms.append(pr) entities.add(pr) animatedEntities.add(pr) else: up = int(monster.properties["up"]) maxUp = int(monster.properties["maxUp"]) left = int(monster.properties["left"]) maxLeft = int(monster.properties["maxLeft"]) mn = Monster(x, y - PLATFORM_HEIGHT, left, up, maxLeft, maxUp) entities.add(mn) platforms.append(mn) monsters.add(mn) except: print(u" ") total_level_width = platforms_layer.num_tiles_x * PLATFORM_WIDTH # total_level_height = platforms_layer.num_tiles_y * PLATFORM_HEIGHT #
ここで何が見えますか?
まず、プロシージャは、レベルマップの読み込みに使用される入力パラメーターnameを受け入れるようになりました。 これは、レベル間の移行を行うために行われました。
次に、マップの読み込みと変換が行われます。マップで配列を解析するのと同じ原理で、タイルでレイヤーを解析します。 PlatformおよびBlockDieクラスの作成されたオブジェクトはエンティティグループに収まらないことに注意してください。つまり、これらのオブジェクトは表示されません。 それらは存在しますが、表示されません。 代わりに、マップレイヤーのタイルを表示します。
続ける
それでは、 メインの手順を実行しましょう
マップレイヤーのレンダラーを追加する
renderer = helperspygame.RendererPygame() #
目的-以下を参照
呼び出しをloadLevelに変更します
for lvl in range(1,4): loadLevel("map_%s" % lvl)
さらに、すべてのコードはこのループ内にあります
画面に画像を表示するためのブロックで、ビジュアライザーの作業を追加します
for sprite_layer in sprite_layers: # if not sprite_layer.is_object_group: # renderer.render_layer(screen, sprite_layer) # *** center_offset = camera.reverse(CENTER_OF_SCREEN) # renderer.set_camera_position_and_size(center_offset[0], center_offset[1], \ WIN_WIDTH, WIN_HEIGHT, "center")
レンダラーは画像を画面の中央、カメラの移動フォーカス内に表示するため、 Cameraクラスにプロシージャを追加する必要があることに注意してください
カメラ
class Camera(object): def __init__(self, camera_func, width, height): self.camera_func = camera_func self.state = Rect(0, 0, width, height) def apply(self, target): return target.rect.move(self.state.topleft) def update(self, target): self.state = self.camera_func(self.state, target.rect) def reverse(self, pos):# return pos[0] - self.state.left, pos[1] - self.state.top
loadlevelプロシージャに転送されたものを削除し、少し新しいものを追加して、次のビューを取得します。
メイン
def main(): pygame.init() # PyGame, screen = pygame.display.set_mode(DISPLAY) # pygame.display.set_caption("Super Mario Boy") # bg = Surface((WIN_WIDTH, WIN_HEIGHT)) # # renderer = helperspygame.RendererPygame() # for lvl in range(1,4): loadLevel("levels/map_%s" % lvl) bg.fill(Color(BACKGROUND_COLOR)) # left = right = False # - up = False running = False try: hero = Player(playerX, playerY) # (x,y) entities.add(hero) except: print (u" , -") hero = Player(65, 65) entities.add(hero) timer = pygame.time.Clock() camera = Camera(camera_configure, total_level_width, total_level_height) while not hero.winner: # timer.tick(60) for e in pygame.event.get(): # if e.type == QUIT: raise SystemExit, "QUIT" if e.type == KEYDOWN and e.key == K_UP: up = True if e.type == KEYDOWN and e.key == K_LEFT: left = True if e.type == KEYDOWN and e.key == K_RIGHT: right = True if e.type == KEYDOWN and e.key == K_LSHIFT: running = True if e.type == KEYUP and e.key == K_UP: up = False if e.type == KEYUP and e.key == K_RIGHT: right = False if e.type == KEYUP and e.key == K_LEFT: left = False if e.type == KEYUP and e.key == K_LSHIFT: running = False for sprite_layer in sprite_layers: # if not sprite_layer.is_object_group: # renderer.render_layer(screen, sprite_layer) # for e in entities: screen.blit(e.image, camera.apply(e)) animatedEntities.update() # a monsters.update(platforms) # camera.update(hero) # center_offset = camera.reverse(CENTER_OF_SCREEN) renderer.set_camera_position_and_size(center_offset[0], center_offset[1], \ WIN_WIDTH, WIN_HEIGHT, "center") hero.update(left, right, up, running, platforms) # pygame.display.update() # screen.blit(bg, (0, 0)) # for sprite_layer in sprite_layers: if not sprite_layer.is_object_group: renderer.render_layer(screen, sprite_layer) # for e in entities: screen.blit(e.image, camera.apply(e)) # font=pygame.font.Font(None,38) text=font.render(("Thank you MarioBoy! but our princess is in another level!"), 1,(255,255,255))# screen.blit(text, (10,100)) pygame.display.update() time.wait(10000) # 10 -
何がそんなに面白いの?
この記事と記事の前の部分で調べたものに加えて、ヒーローがプリンセスに触れたときに発生するイベントがあります。 この時点で、失敗に関するメッセージを表示し、それを読んで次の反復に進み、次のレベルをロードする時間を与えます。
以上です。 そのため、簡単かつ迅速に、ゲームを作り直して、 TMXファイルからレベルをロードしました 。
githubのソース