Лекция · 5.5

Кейіпкерді басқару

Кейіпкер өзі жүреді, доп өзі секіреді — жақсы, бірақ ОЙЫНШЫ қайда? Ойынның мәні — басқаруда: көрсеткіні бассаң — жүреді, SPACE — секіреді, тінтуірмен шертсең — атады. Бүгін пернетақта мен тінтуірді ойынға қосамыз. Ең қызығы: «басу» мен «ұстап тұрудың» айырмашылығын білесің — Марио неге SPACE-ті ұстап тұрғанда бір-ақ рет секіреді, ал жүгіргенде көрсеткіні ұстап тұру жеткілікті?

Басқарудың екі тәсілі
Анықтама
Оқиға арқылы (KEYDOWN) — перне басылған СӘТТЕ бір рет іске қосылады. Күй арқылы (get_pressed) — перне ұсталып тұрған ӘР КАДРДА орындалады.
СалыстыруKEYDOWNget_pressed
Қашан іске қосыладыБасылған сәтте бір ретҰсталып тұрғанда әр кадрда
Лайық әрекеттерСекіру, ату, паузаЖүру, ұшу
Қайда жазыладыОқиғалар циклінің ішіндеОйын циклінде, оқиғалардан кейін
🔔
Аналогия: KEYDOWN — есік қоңырауы: бассаң — БІР рет шылдырлайды, ұстап тұрсаң да қайталанбайды. get_pressed — су краны: ашық тұрғанда су АҒА БЕРЕДІ. Секіру — қоңырау, жүру — кран.
KEYDOWN оқиғасы
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_SPACE:
            print('Секіру!')
        if event.key == pygame.K_ESCAPE:
            running = False

Логика екі қабатты: алдымен оқиға түрі (event.type == KEYDOWN — «қандай да бір перне басылды»), сосын нақты перне (event.key == K_SPACE — «дәл SPACE»). Перне константалары:

КонстантаПерне
K_LEFT, K_RIGHT, K_UP, K_DOWNКөрсеткілер
K_a ... K_zӘріптер (WASD жүру үшін)
K_SPACEБос орын
K_ESCAPEEsc
K_RETURNEnter
get_pressed күйі
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
    x -= speed
if keys[pygame.K_RIGHT]:
    x += speed
if keys[pygame.K_UP]:
    y -= speed
if keys[pygame.K_DOWN]:
    y += speed
Анықтама
pygame.key.get_pressed() — БАРЛЫҚ перненің күйін (басулы/басулы емес) қайтарады. keys[K_LEFT] — True болса, перне дәл қазір ұсталып тұр.

Байқа: төрт БӨЛЕК if (elif емес!) — сондықтан LEFT пен UP-ты бірге бассаң, кейіпкер диагональмен жүреді. get_pressed ойын циклінде, оқиғалар циклінен КЕЙІН, әр кадрда шақырылады.

⚠️
Жиі қате: жүруді KEYDOWN-мен жасау — кейіпкер бір басылымға бір-ақ қадам жасап, «кекештеніп» жүреді. Жүру — get_pressed! Керісінше, секіруді get_pressed-пен жасасаң — SPACE ұсталып тұрғанда кейіпкер әр кадрда қайта-қайта секіре береді.
⚠️
Есте сақта: pygame.key.get_pressed() тәсілі толық түрде тек кейбір оқулықтарда (мыс. Атамұра) түсіндіріледі — «Алматыкітап» оқулығында ұзақ қозғалыс негізінен KEYDOWN арқылы беріледі. Емтихан/ҰБТ тапсырмасында қай оқулық негіз болғанын ескер.

Шекара тексеруін if-тің ІШІНДЕ де жасауға болады — қозғалыс пен шекара бір қадамда тексеріледі:

keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > 0:
    x -= speed
if keys[pygame.K_RIGHT] and x < 800 - width:
    x += speed
if keys[pygame.K_UP] and y > 0:
    y -= speed
if keys[pygame.K_DOWN] and y < 600 - height:
    y += speed

Мұнда шекара шарты (x > 0, x < 800 - width) тікелей перне шартымен «and» арқылы қосылған: перне басулы ЖӘНЕ шекараға жетпеген болса ғана — қозғалыс болады. Нәтиже бірдей, бірақ код қысқарақ.

Тінтуірмен басқару
Анықтама
MOUSEBUTTONDOWN — тінтуір шертілді деген оқиға; event.pos — шертілген нүкте (x; y). pygame.mouse.get_pos() — курсордың ағымдағы координатасы.
for event in pygame.event.get():
    if event.type == pygame.MOUSEBUTTONDOWN:
        x, y = event.pos       # шертілген жерге
        print('Шертілді:', x, y)

Осы екі құралмен «нысанаға ату» ойынын жасауға болады: нысана суреті кездейсоқ жерде тұрады, ойыншы шертеді, шерту координатасы нысана тіктөртбұрышының ішінде ме — тексереміз (келесі сабақтағы соқтығысу!).

Шекара шектеуі

Басқарылатын кейіпкер экраннан шығып кетпеуі тиіс. Серпілуден айырмасы: кейіпкер шекарада жай ТОҚТАЙДЫ (доп сияқты секірмейді).

# Қозғалыстан КЕЙІН шектеу
if x < 0:
    x = 0
if x > 750:      # 800 - кейіпкер ені 50
    x = 750

Логика: координата шекарадан асып кетсе — оны шекара мәніне қайтарамыз. Кейіпкер «қабырғаға тірелген» болып көрінеді. Төрт шекараға да (жоғары/төмен/сол/оң) осылай жасалады.

Есеп
Берілді: автокөлік x=20, y=40 нүктесінде, жылдамдығы x_speed=10. SPACE басулы тұрғанда автокөлік қозғалады, қабырғаға тірелгенде — кері бағытта («серпіліп») қозғала бастайды.
if event.key == pygame.K_SPACE:
    pygame.time.delay(50)
    pygame.draw.rect(screen, [255,255,255], [x, y, 180, 120], 0)
    x = x + x_speed
    if x > screen.get_width() - 170 or x < 0:
        x_speed = -x_speed
    screen.blit(avto, [x, y])
    pygame.display.flip()

Айырмасы шекара-тоқтаудан: мұнда координата шектен шықпайды, тек жылдамдықтың таңбасы ауысады (x_speed = -x_speed) — сондықтан кейіпкер тоқтамай, керісінше бағытта жүре береді. Бұл — доптың серпілуімен бірдей идея, тек пернемен басқарылады.

🎯 ҰБТ байланысы
Басқару логикасы — шартты операторлардың қолданбасы.
1
if пен elif айырмасы: бөлек if-тер қатар орындалады (диагональ қозғалыс).
2
Кірістірілген шарттар: event.type → event.key — екі деңгейлі тексеру.
3
Оқиғалық программалау ұғымы — заманауи интерфейстердің негізі.
Сабақ қорытындысы
  • Екі тәсіл: KEYDOWN — бір басылым (секіру, ату); get_pressed — ұстап тұру (жүру).
  • KEYDOWN — оқиғалар циклінде: event.type → event.key → әрекет.
  • get_pressed — ойын циклінде әр кадрда; бөлек if-тер диагональ қозғалыс береді.
  • Тінтуір: MOUSEBUTTONDOWN + event.pos — шертілген нүкте.
  • Шекара: if x < 0: x = 0 — кейіпкер экранда қалады.