Ҷозиба ва ҷаҳишҳо
Ин барои чӣ лозим аст
Платформерро аз рӯи ҳаракат мешиносанд: қаҳрамон боло мепарад, суст мешавад, меафтад ва дар платформа меистад. Агар танҳо координатаро тағйир диҳем, ҷаҳиш ба сафар дар лифт монанд мешавад. Барои ҳосил кардани камон суръат-ро тағйир додан лозим аст, мавқеъро бошад бо суръат.
Дар arcade модели соддаро худатон навиштан ё PhysicsEnginePlatformer-ро истифода бурдан мумкин аст. Таҳлили қадамҳои хурд кӯмак мекунад фаҳмед, ки чаро қаҳрамон аз фарш мегузарад, дар девор мечаспад ё аз канор ҷаҳида намерасад.
Қадами 1. Мавқеъ, суръат ва ҷозиба
Мавқеъ — объект дар куҷост. Суръат — дар як қадам чӣ қадар мекӯчад. Ҷозиба — тағйири суръат ба поён. Дар arcade тири y ба боло нигаронида шудааст, бинобар ин ҷозибаро тарҳ мекунанд. Дар ин мавзӯъ суръатҳо бо пиксел дар як кадр дода шудаанд, на дар як сония.
y, vy = 60, 6
for frame in range(1, 5):
vy -= 2
y += vy
print(frame, y, vy)
Натиҷа:
1 64 4
2 66 2
3 66 0
4 64 -2
Аввал объект боло меравад, баъд суръат сифр мешавад, баъд манфӣ. Суръати сифр дар нуқтаи болоӣ маънои онро надорад, ки объект дар замин истодааст. Ҷаҳиш бо суръати амудии мусбат сар мешавад; ҷозиба ҳангоми боло рафтан ҳам амал мекунад.
Тартиб дар ин ҷо ошкоро интихоб шудааст: аввал суръатро, баъд мавқеъро тағйир додан. Агар ин амалҳоро ҷой иваз кунед, координатаҳо аллакай дар кадри аввал дигар мешаванд. Ба ҳисобҳо бо воҳидҳои «дар кадр» бе тағйир додани тамоми модел delta_time илова накунед.
Қадами 2. Ҳадди суръати афтидан
Бе маҳдудият суръати манфӣ аз рӯи модул бепоён меафзуд. Суръати ниҳоӣ тезтарин қадами иҷозатдодашударо ба поён муайян мекунад. Азбаски афтидан манфӣ аст, маҳдудият аз поён тавассути max иҷро мешавад:
vy = -7
for _ in range(3):
vy = max(vy - 2, -10)
print(vy)
Натиҷа:
-9
-10
-10
-10 аз -9 хурдтар аст, вале маънои афтидани тезтарро дорад. Маҳдуд кардани қадам хавфи гузаштан аз платформаро байни ду санҷиш кам мекунад. Он ҳимояро ҳангоми ҳар гуна ғафсии платформа ва ҳар гуна суръат кафолат намедиҳад: барои ҳолатҳои мураккаб қадамҳои иловагӣ ё санҷиши тамоми роҳи ҳаракат лозим аст.
Қадами 3. Фуруд ва тарафҳои спрайт
Фаршро бо баландии сатҳи он муайян мекунанд. Дар он бояд поёни бозингар истад, на маркази ӯ. Таъини bottom худаш марказро аз нав ҳисоб мекунад:
import arcade
p = arcade.SpriteSolidColor(20, 20, center_x=50, center_y=35)
print(p.bottom)
p.bottom = 30
print(p.center_y, p.bottom)
Натиҷа:
25.0
40.0 30.0
Андоза 20 × 20 монд, марказ бошад панҷ пиксел боло рафт. Ҳангоми фуруди воқеӣ суръати амудиро низ сифр мекунанд, вагарна дар қадами навбатӣ бозингар бо суръати ҷамъшуда боз афтиданӣ мешавад. Задани сар ба шифт истоданро дар назди тарафи поёнии шифт талаб мекунад.
Барои девор ҳамин геометрия амал мекунад: ҳангоми ҳаракат ба рост монеа аз бозингар рост аст, ҳангоми ҳаракат ба чап — чап. Самт муайян мекунад, ки кадом тарафҳоро мувофиқ кардан лозим. Бекор кардани оддии тамоми қадам фосила мегузорад, агар то девор аз дарозии қадам камтар пиксел монда бошад.
Қадами 4. Тирҳоро ҷудо мекунем ва муҳаррикро истифода мебарем
Аввал объектро аз рӯи x мекӯчонанд ва буришҳои уфуқиро ислоҳ мекунанд. Баъд аз рӯи y мекӯчонанд ва амудиҳоро ислоҳ мекунанд. Ҳамин тавр маълум аст, ки кадом қадам буришро ба вуҷуд овард. Агар якбора ҳар ду координатаро тағйир диҳем, дар кунҷ фаҳмидан душвор аст, ки бозингарро ба паҳлӯ ё ба боло тела додан лозим.
PhysicsEnginePlatformer-и тайёр ҳаракат ва бархӯрдҳоро ба ӯҳда мегирад. walls — рӯйхати деворҳои беҳаракат, gravity_constant — бузургии ҷозиба дар як қадам. Барои санҷиши ҳисобҳо равзана ҳатмӣ нест:
import arcade
p = arcade.SpriteSolidColor(20, 20, center_x=50, center_y=50)
walls = arcade.SpriteList()
floor = arcade.SpriteSolidColor(200, 20, center_x=50, center_y=10)
walls.append(floor)
engine = arcade.PhysicsEnginePlatformer(p, walls=walls, gravity_constant=1)
for _ in range(12):
engine.update()
print(round(p.bottom), p.change_y, engine.can_jump())
Натиҷа:
20 0.0 True
Бозингар дар сатҳи болоии фарш монд. can_jump() имконияти ҷаҳишро аз рӯи қоидаҳои муҳаррик месанҷад; баробарии change_y == 0 онро иваз намекунад. Дар бозӣ engine.update()-ро дар on_update даъват мекунанд, on_draw бошад танҳо ҳолати ҳосилшударо мекашад. Ҳамин бозингарро боз тавассути p.update() ҳаракат надиҳед: вагарна дар як кадр қадами дуюм ҳосил мешавад.
Қадами 5. Coyote time ва буфери ҷаҳиш
Coyote time барои ҷаҳиш баъд аз рафтан аз канор якчанд кадр медиҳад. Буфери ҷаҳиш (jump buffer) пахши ба наздикӣ рӯйдодаро дар хотир нигоҳ медорад: агар бозингар қариб фуруд омада бошад, фармон гум намешавад. Якумӣ ба тамоси ба наздикӣ рӯйдода бо такягоҳ вобаста аст, дуюмӣ — ба фармони ба наздикӣ додашуда.
Синни ҳодисаро бо ҳисобкунак нигоҳ доштан қулай аст. Сифр маънои «ҳозир рух медиҳад», адади мусбат — чанд кадр гузашт. Танҳо ҳисобкунаки вақтро баъд аз рафтан аз замин нишон медиҳем:
air = 0
for on_ground in (True, False, False, True):
air = 0 if on_ground else air + 1
print(air)
Натиҷа:
0
1
2
0
Барои пахш ҳисобкунаки алоҳида лозим аст. Ҳар ду равзанаи вақтро баъд аз нав кардани ҳисобкунакҳо санҷед ва бодиққат хонед, ки сарҳади охирин дохил аст ё не. Баъд аз ҷаҳиши муваффақ ҳодисаҳои истифодашударо хомӯш кардан лозим: як пахш набояд якчанд ҷаҳиш диҳад. Дар масъалаҳо ин мантиқи алоҳида бар болои ҳисобкунакҳои аллакай навшуда аст, на имконияти дарунсохти can_jump().
Дар дохил чӣ тавр кор мекунад
Модел ҳолатро байни кадрҳо нигоҳ медорад: координатаҳо, суръатҳо, ҳисобкунакҳо. Ҳар қадам ҳолати пешинаро мегирад ва ҳолати навро ҳосил мекунад. Ин ба ҷадвале монанд аст, ки сатри навбатӣ аз рӯи сатри пешина ҳисоб карда мешавад; фаромӯш кардани сифр кардан ё тартиби нодуруст ба ҳамаи сатрҳои минбаъда таъсир мерасонад.
Санҷиши бархӯрд танҳо буришро ошкор мекунад. Муҳаррики физикӣ илова бар ин мавқеъ ва суръатро ислоҳ мекунад. Расмкашӣ баъдтар рух медиҳад ва ҳолати аллакай ҳисобшударо нишон медиҳад, бинобар ин физикаро дар дохили on_draw ислоҳ кардан лозим нест.
Хатоҳои маъмул
vy += GRAVITY. Дар arcade объект ба боло суръат мегирад. Барои кашиш ба поён ҷозибаи мусбатро тарҳ кунед.min(vy, -MAX_FALL). Қариб ҳар суръати хурд фавран ниҳоӣ ё ҳатто хурдтар мешавад. Сарҳади поёнироmaxмуайян мекунад.p.center_y = FLOOR. Нисфи поёнии спрайт зери фарш мемонад.bottom-ро бо фарш мувофиқ кунед ва ҳаракати амудиро боздоред.- Ҷаҳиш ҳангоми
change_y == 0. Ҷаҳиш дар нуқтаи болоии траектория иҷозат дода мешавад. Мавҷудияти такягоҳро санҷед ёengine.can_jump()-ро истифода баред. - Як пахшро бисёр кадрҳо истифода мебаранд. Ҷаҳиши такрорӣ дар ҳаво ҳосил мешавад. Баъд аз кор кардан ҳодисаҳои истифодашударо хомӯш кунед ва пахши навро интизор шавед.
Варақаи ёддошт
| Мафҳум | Чиро дар хотир доштан |
|---|---|
| ҷозиба | суръатро тағйир медиҳад, на бевосита координатаро |
| ҷаҳиш | change_y-и мусбат |
| ҳадди афтидан | сарҳади поёнии суръати манфӣ |
| фуруд | поёнро бо такягоҳ мувофиқ кардан, суръати амудиро сифр кардан |
| деворҳо | ҳаракат ва ислоҳ алоҳида аз рӯи ҳар тир |
| физикаи тайёр | arcade.PhysicsEnginePlatformer, engine.update() |
| такягоҳ барои ҷаҳиш | engine.can_jump() |
| coyote time | синни охирин тамос бо замин |
| буфери ҷаҳиш | синни охирин пахше, ки ҳанӯз истифода нашудааст |