Бархӯрдҳо ва тангаҳо
Ин барои чӣ лозим аст
Бозӣ вақте зинда мешавад, ки объектҳо бо ҳам таъсир мерасонанд: бозингар тангаҳо ҷамъ мекунад, ба хорҳо мерасад, ба сари душман меҷаҳад. Ҳамаи инҳо — бархӯрди спрайтҳоянд. arcade онҳоро ҳатто дар байни садҳо объект зуд ёфта метавонад.
Вале ёфтани бархӯрд — нисфи кор аст. Санҷиш ҳар кадр, 60 маротиба дар сония мегузарад ва агар ғамхорӣ накунем, як танга 60 маротиба хол медиҳад, як хор бошад дар як сония ҳамаи ҷонҳоро мегирад. Дар ин мавзӯъ функсияҳои бархӯрд, майдонҳои худии спрайтҳо, қоидаи «як ҳодиса — як маротиба», таймери осебнопазирӣ ва фаҳмидани он ки зарба аз куҷо омадро мебинем.
Қадами 1. Ду спрайт
arcade.check_for_collision(a, b) True бармегардонад, агар спрайтҳо ба ҳамдигар дароянд, ва False, агар не.
import arcade
a = arcade.SpriteSolidColor(10, 10, center_x=5, center_y=5) # x аз 0 то 10
b = arcade.SpriteSolidColor(10, 10, center_x=12, center_y=5) # x аз 7 то 17
c = arcade.SpriteSolidColor(10, 10, center_x=40, center_y=5)
print(arcade.check_for_collision(a, b), arcade.check_for_collision(a, c))
Натиҷа:
True False
Агар спрайтҳо танҳо бо канорҳо расанд (канори рости яке маҳз дар канори чапи дигарӣ), ин ҳанӯз бархӯрд нест: онҳо масоҳати умумӣ надоранд.
Қадами 2. Спрайт ва рӯйхат
Аксар вақт спрайтро якбора бо ҳамаи тангаҳо, душманон ё деворҳо санҷидан лозим аст. arcade.check_for_collision_with_list(sprite, sprite_list) рӯйхати спрайтҳои расидаро бармегардонад:
import arcade
player = arcade.SpriteSolidColor(20, 20, center_x=50, center_y=50)
stones = arcade.SpriteList()
for x in (45, 60, 300):
stones.append(arcade.SpriteSolidColor(10, 10, center_x=x, center_y=50))
hits = arcade.check_for_collision_with_list(player, stones)
print(len(hits), [s.center_x for s in hits])
Натиҷа:
2 [45, 60]
Рӯйхати холӣ дар if дурӯғ ҳисоб мешавад, бинобар ин санҷиши «оё ба чизе расидем» кӯтоҳ навишта мешавад: if hits:. Натиҷаро бошад фавран бо даври for гузаштан қулай аст — ҳар спрайти расидаро алоҳида коркард кардан.
Ёфтани спрайтҳои зери курсори муш ба arcade.get_sprites_at_point((x, y), sprite_list) кӯмак мекунад:
import arcade
cards = arcade.SpriteList()
cards.append(arcade.SpriteSolidColor(50, 80, center_x=100, center_y=100))
cards.append(arcade.SpriteSolidColor(50, 80, center_x=300, center_y=100))
print(len(arcade.get_sprites_at_point((110, 120), cards)))
print(len(arcade.get_sprites_at_point((200, 100), cards)))
Натиҷа:
1
0
Қадами 3. Майдонҳои худии спрайт
Спрайт — объекти оддии Python аст ва ба он ҳар гуна майдон илова кардан мумкин аст: арзиши танга, саломатии душман, навъи бонус.
import arcade
gem = arcade.SpriteCircle(8, arcade.color.RUBY)
gem.value = 25
gem.kind = "лаъл"
print(gem.kind, gem.value)
Натиҷа:
лаъл 25
Функсияи хурди «фабрика» сохтан қулай аст, ки спрайтро месозад ва фавран майдонҳояшро пур мекунад, — ҳамин тавр дар бозӣ тангаҳои гуногун метавонанд арзиши гуногун дошта бошанд.
Қадами 4. Як ҳодиса — як маротиба
Санҷиши бархӯрдҳо ҳар кадр мегузарад. Агар бозингар болои танга истода бошад ва танга ба ҳеҷ куҷо нарафта бошад, дар кадри навбатӣ бархӯрд боз ёфт мешавад. Бубинем, ки агар ҳеҷ чизро хориҷ накунем, дар 5 кадр чанд хол «ҷамъ мешавад»:
import arcade
player = arcade.SpriteSolidColor(20, 20, center_x=0, center_y=0)
gems = arcade.SpriteList()
gems.append(arcade.SpriteSolidColor(10, 10, center_x=0, center_y=0))
score = 0
for frame in range(5):
score += 10 * len(arcade.check_for_collision_with_list(player, gems))
print(score, len(gems))
Натиҷа:
50 1
Як танга ба ҷои 10 хол 50 хол овард. Қоида: ҳама чизе, ки бояд як маротиба кор кунад, фавран «хомӯш» кардан лозим — ашёи ҷамъшударо хориҷ кардан (remove_from_sprite_lists() аз мавзӯи гузашта), фишангеро, ки кор кард, ба ҳолати дигар гузаронидан, баъд аз зарба — осебнопазириро фаъол кардан.
Қадами 5. Таймери осебнопазирӣ
Бо зарар ҳам ҳамин гуна аст: бозингар ба хор расид — ва то даме ки дур нарафтааст, ҳар кадр як ҷон гирифта мешавад. Бинобар ин баъд аз зарба таймер фаъол мекунанд: якчанд кадр бозингар осебнопазир аст (ва одатан милт-милт мекунад).
Таймер — танҳо шумораи кадрҳост, ки ҳар кадр то сифр кам мешавад:
timer = 0
log = []
for frame in range(6):
if timer > 0:
timer -= 1
if frame == 1: # дар кадри 1 чизе рух дод
timer = 3
log.append(timer)
print(log)
Натиҷа:
[0, 3, 2, 1, 0, 0]
То даме ки таймер аз сифр калон аст, амали «хатарнок» иҷро намешавад. Вақте ки он ба сифр расид — боз мумкин аст. Ҳангоми 60 кадр дар сония таймери 60 — ин як сония аст.
Агар ҳолати бозӣ дар луғат (state = {"lives": 3, "timer": 0}) нигоҳ дошта шавад, функсия метавонад онро дар ҷояш тағйир диҳад ва бозӣ тағйиротро мебинад.
Қадами 6. Зарба аз куҷо омад
Дар платформерҳо ҷаҳиш ба сари душман душманро мағлуб мекунад, бархӯрд аз паҳлӯ бошад ҷонро мегирад. Онҳоро чӣ тавр фарқ кардан мумкин? Ду аломат лозим аст:
- бозингар меафтад, на парвоз мекунад: суръати амудии ӯ
change_yманфӣ аст (дар arcade боло — плюс); - бозингар аз душман болотар аст: канори поёнии ӯ ҷое болои миёнаи душман аст.
Ба ададҳо барои ду мавқеи бозингар нигоҳ кунем:
import arcade
enemy = arcade.SpriteSolidColor(30, 30, center_x=100, center_y=100)
high = arcade.SpriteSolidColor(30, 30, center_x=100, center_y=125)
side = arcade.SpriteSolidColor(30, 30, center_x=120, center_y=100)
print(enemy.center_y, high.bottom, side.bottom)
Натиҷа:
100 110.0 85.0
Бозингари болои душман бо канори поёни худ дар баландии 110 меистад — аз маркази душман (100) болотар. Бозингари паҳлӯ — дар 85, аз марказ поёнтар. Бо муқоисаи чунин ададҳо (ва аломати суръат) бозӣ ҳал мекунад, ки расидан бо чӣ анҷом ёфт. Ба ҳолати «маҳз дар сатҳи марказ» диққат диҳед — бояд ҳал кард, ки он ба кадом натиҷа тааллуқ дорад, ва муқоисаро мувофиқан навишт.
Дар дохил чӣ тавр кор мекунад
Ҳар спрайт ҳитбокс дорад — бисёркунҷае, ки аз рӯи он бархӯрдҳо ҳисоб карда мешаванд (дар спрайти росткунҷа ин росткунҷаи худи он аст). Аввал arcade санҷиши тез ва тахминиро аз рӯи росткунҷаҳои иҳотакунанда мекунад ва танҳо агар онҳо бурида шаванд — санҷиши дақиқро. Барои check_for_collision_with_list arcade метавонад хеши фазоӣ-ро истифода барад: майдонро ба катакҳо тақсим мекунад ва танҳо спрайтҳои катакҳои ҳамсояро месанҷад. Бинобар ин бархӯрд бо садҳо танга зуд ҳисоб карда мешавад.
Хатоҳои маъмул
1. Ашёи ҷамъшуда хориҷ карда намешавад. То даме ки бозингар болои танга истодааст, хол меафзояд. Ашёе, ки як маротиба кор мекунад, фавран хориҷ карда мешавад.
2. Ашёро ҳисоб мекунанд, на арзиши онро. score += 1 ба ҷои score += coin.value — тангаҳои қиммат мисли арзон арзиш доранд.
3. break дар даври расидаҳо. Дар як кадр танҳо ашёи аввал коркард мешавад, боқимонда — аз кадри навбатӣ ё ҳеҷ гоҳ.
4. Зарар бе санҷиши таймер. Ҷонҳо дар ҳар кадри расидан мераванд. Зарар — танҳо вақте ки таймер сифр аст; баъд аз зарар таймерро боз фаъол мекунанд.
5. Ҷаҳиш аз боло бе санҷиши суръат. Агар ба change_y нигоҳ накунед, бозингаре, ки зери душман ҷаҳид, низ ӯро «мағлуб мекунад».
Варақаи ёддошт
| Чӣ | Код |
|---|---|
| ду спрайт | arcade.check_for_collision(a, b) → True / False |
| спрайт ва рӯйхат | hits = arcade.check_for_collision_with_list(s, lst) → рӯйхат |
| ба чизе расид | if hits: |
| спрайтҳо дар нуқта | arcade.get_sprites_at_point((x, y), lst) |
| майдони худӣ | coin.value = 5 |
| хориҷ кардани ҷамъшуда | coin.remove_from_sprite_lists() |
| таймер | if timer > 0: timer -= 1; амал танҳо вақте ки timer == 0 |
| оё спрайт меафтад | s.change_y < 0 |
| расидан бо канорҳо | бархӯрд нест |