Ҳаракат ва гардишҳо
Чаро вақтро бояд ба ҳисоб гирифт
Ҳаракат пайдарпайии тағйироти хурди мавқеъ аст. Агар дар ҳар кадр як миқдор ҷамъ кунем, дар компютери тез объект ҳам тезтар меравад. Аз ин рӯ суръатро бо воҳидҳо дар як сония дода, дарозии қадамро аз давомнокии кадр ҳисоб мекунанд. Ин ба бозигар, посбон ва бурҷи гардишкунанда лозим аст.
Кадр ва update()
Кадр як гузариши даври бозӣ аст. Ursina дар ҳар кадр update()-ро мехонад; дар зерсинфи Entity update(self)-ро муайян кардан мумкин аст. time.dt вақти байни кадрҳоро бо сония нигоҳ медорад. Дар ин мисол давомнокиҳоро худамон медиҳем, то натиҷа аз компютер вобаста набошад.
from ursina import Entity
player = Entity()
speed = 4
for dt in (0.1, 0.15, 0.25):
player.x += speed * dt
print(f"{player.x:.2f}")
Натиҷа:
0.40
1.00
2.00
Дар маҷмӯъ ним сония гузашт, бинобар ин объект ду воҳид рафт. Дар update()-и воқеӣ ба ҷойи dt аз time.dt истифода мешавад. dt-ро ду бор зарб накунед: суръат зарби вақт аллакай масофа медиҳад.
Нигоҳ доштан ва пахш кардан
held_keys["d"] нишон медиҳад, ки тугма нигоҳ дошта шудааст ё не: 1 ё 0. Фарқи тугмаҳои муқобил самт медиҳад: рост 1, чап −1, ҳар ду ё ҳеҷ кадом 0. Барои роҳравии пайваста ин фарқро дар update() мехонанд.
for right, left in ((1, 0), (0, 1), (1, 1), (0, 0)):
print(right - left)
Натиҷа:
1
-1
0
0
Барои амали якдафъаина input(key) хизмат мекунад: масалан, key == "space" ҷаҳишро оғоз мекунад ва "a up" раҳо кардани тугмаро мефаҳмонад. Дар он соҳа номи input дигар функсияи дохилии хондани сатр нест; бинобар ин коркарди равзана дар масъалаҳо дар блоки main ҷойгир аст.
Вектор: самт ва дарозӣ
Vec3 аз се ҷузъ иборат аст. Фарқи ду мавқеъ векторро аз якум ба дуюм медиҳад. length() дарозиро чен мекунад; normalized() самтро нигоҳ дошта, дарозиро ба 1 баробар мекунад. Ҳамин тавр «ба куҷо» аз «чӣ қадар» ҷудо мешавад.
from ursina import Vec3
offset = Vec3(0, 3, 4)
print(offset.length())
direction = offset.normalized()
print(direction)
print(direction * 2)
Натиҷа:
5.0
LVector3f(0, 0.6, 0.8)
LVector3f(0, 1.2, 1.6)
Бе нормализатсия offset * speed маънои онро дорад, ки ҳадафи дур нисбат ба наздик қавитар мекашад. Агар объект аллакай дар ҳадаф бошад, самт лозим нест: масофаи сифриро алоҳида коркард кунед. Барои аз ҳадаф нагузаштан пеш аз ҳаракат масофаи боқимондаро бо қадами иҷозатшуда муқоиса кунед; алгоритми пурраро дар масъала месозед.
Гардиш дар гирди меҳвари амудӣ
rotation_y кунҷи атрофи меҳвари y бо дараҷаҳо аст. Баъди як гардиши пурра самт такрор мешавад. Бақияи тақсим ба 360 кунҷро ба [0, 360) меорад. Барои гардиш ин шкаларо давра ҳисобидан лозим аст, на хати рост.
for angle in (-25, 365, 740):
print(angle % 360)
current, target = 340, 15
print(target - current)
print((target - current + 180) % 360 - 180)
Натиҷа:
335
5
20
-325
35
Сатри охир фарқи кӯтоҳро дар [−180, 180) медиҳад. Аломат тараф ва қимати мутлақ кунҷи боқимондаро муайян мекунад. Дар 180° формула самти манфиро интихоб мекунад; дар масъалаҳо ин қисми шарт аст. Суръати гардиш бо дараҷа дар сония чен мешавад, пас қадами кадр angular_speed * time.dt аст.
Масир ва масофаи боқимонда
Посбон ҳолат дорад: мавқеи ҷорӣ ва рақами нуқтаи навбатӣ. Пас аз расидан ба нуқта индекс иваз мешавад. Амали % бе ҳолати алоҳида барои нуқтаи охирин ба аввали рӯйхат бармегардонад.
points = [0, 1, 2]
i = 1
for _ in range(5):
print(i)
i = (i + 1) % len(points)
Натиҷа:
1
2
0
1
2
Агар дар кадр 7 воҳид рафтан лозим бошаду то нуқта 2 воҳид монда бошад, баъди расидан боз 5 мемонад. Ин бақия метавонад аз чанд порча гузарад. Аз ин рӯ дар update() баъзан давраи хурд лозим аст: он масофаи кадри ҷориро сарф мекунад ва кадри дигарро интизор намешавад. Нуқтаҳои ҳамсояи яксон диққати алоҳида мехоҳанд: порчаи сифрӣ масофаро сарф намекунад.
Хатоҳои маъмул ва ислоҳи онҳо
- player.x += speed бе time.dt суръатро аз FPS вобаста мекунад. Суръатро ба давомнокии кадр зарб кунед.
- player.position += offset * step қадамро бо дурии ҳадаф калон мекунад. Самти воҳидиро истифода бурда, расиданро алоҳида санҷед.
- target - current барои 340° ва 15° қимати −325° медиҳад: гардиш дароз мешавад. Фарқро ба [−180, 180) оред.
- i += 1 бе бозгашт ба аввал баъди нуқтаи охир IndexError медиҳад. Бақияи тақсим ба дарозии масирро истифода баред.
- dist = 0 ҳангоми ҳар расидан масофаи боқимондаро гум мекунад. Аввал ҳисоб кунед, ки чӣ қадар масофа воқеан сарф шуд.
Ёддошт
- update() дар ҳар кадр, input(key) барои рӯйдод ва held_keys барои ҳолати тугмаҳо аст.
- Қадам = суръат × time.dt.
- target - pos вектор ба ҳадаф аст; length() дарозӣ ва normalized() самти воҳидиро медиҳад.
- rotation_y бо дараҷаҳо аст; angle % 360 кунҷро ба давраи пурра меорад.
- Фарқи кӯтоҳ: (target - current + 180) % 360 - 180.
- Масир мавқеъ, нуқтаи навбатӣ ва масофаи сарфнашударо нигоҳ медорад.