Гузариш ба мундариҷа
Мавзӯи 6 аз 6

Сатҳ, камера ва платформер

Ин барои чӣ лозим аст

Вақте ки бозӣ дар як равзана ҷой мегирад, координатаҳои ҷаҳон ва экранро омехта кардан осон аст. Дар платформери калон қаҳрамон метавонад дар пиксели ҳазоруми сатҳ бошад ва дар наздикии маркази экран монад. Харита тамоми ҷаҳонро тасвир мекунад, камера бошад қисми намоёнро интихоб мекунад.

Дар ин мавзӯъ унсурҳои шиносро якҷоя ҷамъ мекунем: маълумоти харита ба спрайтҳо табдил меёбад, физика бозингарро ҳаракат медиҳад, камера аз паси ӯ меравад, интерфейс дар ҷояш мемонад. Платформаи ҳаракаткунанда саволи муҳимеро илова мекунад: объектҳои бо ҳам алоқамандро бо кадом тартиб нав кардан лозим?

Қадами 1. Харита — маълумот аст

Барои сатҳи хурд рӯйхати сатрҳо мувофиқ аст. Ҳар аломат катакро ифода мекунад: масалан, # — девор, o — ашё, P — ҷои оғоз, . — холигӣ. Аломатҳо худашон чизе намекашанд: боркунанда онҳоро мехонад ва объектҳои лозимиро месозад.

LEVEL = ["..o", "P#."]
print(len(LEVEL), max(len(line) for line in LEVEL))
for row, line in enumerate(LEVEL):
    print(row, line.count("#"), line.count("o"))

Натиҷа:

2 3
0 0 1
1 1 0

Дар ин ҷо ду сатр ва се сутун ҳаст. Агар сатрҳо дарозии гуногун дошта бошанд, бари харитаро дарозтарин муайян мекунад, баландиро бошад — шумораи сатрҳо. Катаки холӣ спрайт талаб намекунад: ин хотира ва шумораи санҷишҳоро сарфа мекунад.

Қадами 2. Аз катак ба мавқеи спрайт

Катак масоҳат дорад, спрайт — мавқеи марказ. Бинобар ин координатаи кунҷи катак барои гузоштани спрайт аз рӯи марказ мувофиқ нест. Ғайр аз ин, сатрҳои матн аз боло ба поён мераванд, y дар arcade бошад ба боло меафзояд.

Се қатори баландиашон 40-ро дида мебароем. Марказҳои онҳо аз боло ба поён дар баландиҳои 100, 60, 20 ҷойгиранд. Месанҷем, ки спрайтҳо кадом қитъаҳоро ишғол мекунанд:

import arcade
heights = [100, 60, 20]
for row, y in enumerate(heights):
    tile = arcade.SpriteSolidColor(40, 40, center_x=20, center_y=y)
    print(row, tile.bottom, tile.top)

Натиҷа:

0 80.0 120.0
1 40.0 80.0
2 0.0 40.0

Қаторҳо бе фосила пайваст мешаванд. Агар ашё аз катак хурдтар бошад, маркази он боз ҳам дар маркази катак мемонад. Вазифаи объектҳоро ҷудо кунед: деворҳо ба рӯйхати монеаҳо, ашё ба рӯйхати худ, оғоз ба ҷуфти координатаҳо меравад. Ин имкон медиҳад, ки физика танҳо деворҳоро ва ҷамъоварии ашё танҳо ашёро санҷад.

Қадами 3. Ҷаҳон ва экран

Ҳангоми миқёси оддӣ камера аз марказаш ба чап ва рост нисфи бари равзанаро нишон медиҳад. Мавқеъ дар экран аз мавқеъ дар ҷаҳон бо тарҳи маркази камера ва иловаи нисфи равзана ҳосил мешавад:

center, width = 700, 600
for world_x in (400, 700, 1000):
    screen_x = world_x - center + width // 2
    print(world_x, screen_x)

Натиҷа:

400 0
700 300
1000 600

Нуқтаи ҷаҳони 700 ба мобайни равзана афтод. Кӯчонидани камера center_x-и спрайтҳоро тағйир намедиҳад: тарзи намоиши онҳо тағйир меёбад. Бинобар ин барои ҳаракат додани тасвир ҳамаи деворҳо ва тангаҳоро бо даст кӯчонидан лозим нест.

Қадами 4. Ду камера дар arcade

Camera2D мавқеъ ва параметрҳои намоишро нигоҳ медорад. Онро баъд аз равзана сохтан лозим аст. Камераи ҷаҳон аз паси бозингар ҳаракат мекунад, камераи интерфейс беҳаракат мемонад. Контексти with camera.activate(): камераи интихобшударо муваққатан фаъол мекунад ва ҳангоми баромадан пешинаро барқарор мекунад.

import arcade
window = arcade.Window(600, 400, visible=False)
camera = arcade.Camera2D()
gui = arcade.Camera2D()
camera.position = (700, 200)
with camera.activate():
    print(tuple(camera.position))
with gui.activate():
    print(tuple(gui.position))
window.close()

Натиҷа:

(700, 200)
(300.0, 200.0)

Дар мисол равзана пинҳон аст, то танзимотро бе даври бозӣ санҷем. Дар on_draw аввал self.clear()-ро даъват мекунанд, баъд ҷаҳонро дар контексти камераи ҷаҳон мекашанд, баъд аз он — ҳисоб ва ҷонҳоро дар контексти gui. Агар ҳисобро якҷоя бо деворҳо кашем, ҳангоми ҳаракати тасвир он меравад.

Қадами 5. Фазои берун аз сатҳро нишон намедиҳем

Бигузор бари сатҳ 1800, бари равзана 600 бошад. Маркази камера бояд байни 300 ва 1500 монад, то майдони намоён аз канорҳо берун наравад. Функсияи clamp мавқеи дилхоҳро дар ин фосила нигоҳ медорад:

import arcade
for desired in (50, 600, 1700):
    print(arcade.math.clamp(desired, 300, 1500))

Натиҷа:

300
600
1500

Дар мобайн камера аз паси бозингар меравад, дар назди канорҳо меистад. Аз рӯи амуд мулоҳиза ҳамин гуна аст. Агар сатҳ аз рӯи як тир аз равзана хурдтар бошад, фосилаи иҷозатдодашуда дигар нест: аз рӯи ин тир маркази сатҳро интихоб мекунанд. Он гоҳ фазои холӣ ногузир аст, вале сатҳ симметрӣ ҷойгир мешавад. Андозаҳоро аз рӯи ду тир мустақилона санҷед: сатҳи васеъ метавонад паст бошад.

Қадами 6. Платформае, ки бозингарро мебарад

Платформаи ҳаракаткунанда аз девори оддӣ фарқ дорад: бозингари болояш истода бояд кӯчиши онро гирад. Дар модели худ аввал дар хотир нигоҳ медоранд, ки оё бозингар дар платформа истода буд, баъд платформаро мекӯчонанд ва мусофирро мебаранд. Санҷиш баъд аз кӯчиш аллакай мавқеи дигарро тасвир мекунад.

Дар PhysicsEnginePlatformer объектҳои беҳаракатро тавассути walls, ҳаракаткунандаҳоро бошад тавассути platforms медиҳанд. Барои ҳаракати худкор суръат ва сарҳадҳоро таъин мекунанд. Мисол бурдани уфуқиро бе кӯчонидани дастии бозингар нишон медиҳад:

import arcade
p = arcade.SpriteSolidColor(20, 20, center_x=50, center_y=50)
lift = arcade.SpriteSolidColor(100, 20, center_x=50, center_y=30)
lift.change_x = 2
lift.boundary_left, lift.boundary_right = 0, 200
platforms = arcade.SpriteList()
platforms.append(lift)
engine = arcade.PhysicsEnginePlatformer(p, platforms=platforms, gravity_constant=1)
for _ in range(3):
    engine.update()
print(lift.center_x, p.center_x)

Натиҷа:

56 56

Ҳар ду объект шаш пиксел кӯчиданд. Барои ҳаракати амудӣ change_y, boundary_bottom, boundary_top истифода мешаванд. Нав кардани ҳамин платформаҳоро илова даъват накунед: муҳаррик онҳоро аллакай мекӯчонад. Дар масъалаи лифт модели соддакардашудаи худ истифода мешавад, тартиби қадамҳои он дар шарт дода шудааст.

Дар дохил чӣ тавр кор мекунад

Боркунии харита одатан як маротиба иҷро мешавад: хондани аломат, интихоби навъи объект, ҳисоби марказ, илова ба рӯйхати лозимӣ. Ҳар кадр ҳамаи спрайтҳоро аз нав сохтан лозим нест. Барои харитаҳои калон муҳаррири Tiled қабатҳо ва объектҳоро нигоҳ медорад, arcade.load_tilemap ва arcade.Scene.from_tilemap бошанд кӯмак мекунанд, ки файли харита ба саҳнаи бозӣ табдил ёбад. Барои боркунӣ файли мавҷудаи харита ва захираҳои он лозим аст.

Камера ба расмкашӣ табдилдиҳиро татбиқ мекунад; физика ва санҷишҳои тамос дар координатаҳои ҷаҳон кор карданро давом медиҳанд. Ин ба аксбардорӣ аз макет монанд аст: гардонидан ё кӯчонидани аппарати аксбардорӣ ҷойгиршавии хонаҳоро тағйир намедиҳад. Тафсилоти кори платформаҳои ҳаракаткунанда дар ҳуҷҷатҳои arcade тасвир шудаанд.

Хатоҳои маъмул

  1. y = row * size. Сатри болоӣ дар поён мемонад, координата бошад канори катакро ифода мекунад. Самти сатрҳо ва мавқеи марказро ба назар гиред.
  2. rows = len(line). Баландӣ аз дарозии сатри мушаххас вобаста мешавад. Шумораи қаторҳоро аз тамоми рӯйхати сатрҳо гиред.
  3. camera.position = player.position бе санҷиши андозаҳо. Дар назди канор фазои берун аз харита пайдо мешавад. Намоишро бо назардошти нисфи равзана маҳдуд кунед ва сатҳи хурдро алоҳида коркард кунед.
  4. Ҳисобро дар дохили camera.activate() мекашанд. Интерфейс якҷоя бо ҷаҳон меравад. Онро баъд аз ҷаҳон тавассути gui-и беҳаракат кашед.
  5. Лифти ҳаракаткунанда танҳо ба walls дода шудааст. Суръат таъин шудааст, вале ҳаракати худкор нест. Барои такягоҳҳои ҳаракаткунанда platforms ва як даъвати нав кардани муҳаррикро истифода баред.

Варақаи ёддошт

Чӣ Қоида
андозаҳои харита баландӣ аз рӯи шумораи сатрҳо, бар аз рӯи дарозтарин сатр
мавқеи катак сатрҳои болоиро ба y-ҳои калон гузаронидан, марказро истифода бурдан
гурӯҳҳои объектҳо деворҳо, ашё ва бозингар алоҳида нигоҳ дошта мешаванд
камераи ҷаҳон arcade.Camera2D(), camera.position
интихоби камера with camera.activate():
интерфейс камераи алоҳидаи беҳаракат, баъд аз ҷаҳон кашида мешавад
ҳудуди намоиш фосилаи марказ ба нисфи андозаи равзана баробар аст
сатҳи хурд аз рӯи тири мувофиқ дар марказ гузоштан
такягоҳҳои ҳаракаткунанда platforms, суръат ва boundary_*

Акнун платформер тамоми роҳро аз харита то кадр дорад: боркунӣ, ҳаракат, тамосҳо, камера ва интерфейс. Барои машқи мустақил ба бозии охирин хорҳои шинос ё душмани посбонро илова кунед ва ин тартиби навкуниро нигоҳ доред.