Як зробити рух у Python

Як зробити рух у Python



Анімації з Matplotlib

Використовуємо бібліотеку matplotlib для створення цікавої анімації.

NOP::Nuances of Programming

Зображення імітації дощу виконано за допомогою бібліотеки Matplotlib, відомої як прабатько пакетів для візуалізації даних на python. Matplotlib імітує краплі дощу на поверхні шляхом анімування масштабу та непрозорості 50 точок графіка розкиду. У цій статті ми розглянемо анімації Matplotlib і кілька способів їх створення.

Огляд

Matplotlib – це одна з найвідоміших бібліотек Python із двовимірною (2D) графікою. Багато хто починає подорож у світ візуалізації даних з Matplotlib. З її допомогою можна з легкістю створювати графіки, гістограми, енергетичні спектри, стовпчасті діаграми, графіки похибок, графіки розкиду та багато іншого. Вона також інтегрується з такими бібліотеками, як Pandas та Seaborn для створення більш складних візуалізацій.

Деякі особливості matplotlib:

  • Вона розроблена подібно до MATLAB, тому перемикатися між ними досить просто.
  • Містить множину розширень для візуалізації.
  • Відтворює практично всі графіки (якщо докласти зусиль).
  • Існує більше десяти років, відповідно має велику базу користувачів.

Однак у деяких областях Matplotlib відстає від своїх потужних супротивників.

  • Matplotlib має досить багатослівний імперативний API.
  • Іноді трапляються слабкі за стилем стандартні параметри.
  • Слабка підтримка Інтернету та інтерактивних графів.
  • Часто гальмує за наявності великого обсягу складних даних.

Освіжити знання про базові функції допоможе шпаргалка по Matplotlib з Datacamp.

Анімації

Базовий клас animation у Matplotlib відповідає за анімацію. Він надає основу, навколо якої створюється функціональність анімації. Для цього є два основні інтерфейси:

FuncAnimation створює анімацію за допомогою повторення виклику функції func.

ArtistAnimation: анімація з використанням фіксованого набору об'єктів Artist.

FuncAnimation є зручнішим способом. У документації можна ознайомитись з обома способами докладніше. У цій статті ми будемо використовувати лише інструмент FuncAnimation.

Вимоги

  • Встановіть модулі, включаючи numpy та matplotlib
  • Встановіть ffmpeg або imagemagick для збереження анімації у форматі mp4 чи gif.

Тепер можна перейти до створення базової анімації у Jupyter Notebooks. Код доступний у репозиторії Github.

Базова анімація: синусоїдальна хвиля, що рухається

Створимо базову анімацію синусоїдальної хвилі, що рухається екраном, за допомогою FuncAnimation . Вихідний код для цієї анімації взятий з Інструкції з анімації в Matplotlib. Розглянемо вхідні дані, та був розберемо окремі фрагменти коду.

import numpy as np
from matplotlib import pyplot as plt
від matplotlib.animation import FuncAnimation
plt.style.use('seaborn-pastel')

fig = plt.figure()
ax = plt.axes(xlim=(0, 4), ylim=(-2, 2))
line, = ax.plot([], [], lw=3)

def init():
line.set_data([], [])
return line,
def animate(i):
x = np.linspace (0, 4, 1000)
y = np.sin(2 * np.pi * (x - 0.01 * i))
line.set_data(x, y)
return line,

anim = FuncAnimation(fig, animate, init_func=init,
frames=200, interval=20, blit=True)

anim.save('sine_wave.gif', writer='imagemagick')
  • У рядках 7-9 створюємо фігуру window з однією віссю. Потім створюємо порожній об'єкт line, єдиний об'єкт, який буде змінюватися в анімації. Об'єкт line буде заповнений даними пізніше.
  • У рядках 11–13 створюємо функцію init, яка здійснює анімацію. Функція init ініціалізує дані та встановлює межі осі.
  • У рядках 14–18 визначаємо функцію, яка приймає кількість кадрів (i) як параметр і створює синусоїдальну хвилю (або будь-яку іншу анімацію), яка виконує рухи залежно від значення i. Ця функція повертає кортеж змінених об'єктів графіка, який повідомляє фреймворк анімації, які частини графіка потрібно анімувати.
  • У рядку 20 створюємо об'єкт animation.Параметр blit гарантує, що буде перемальовано лише змінені частини графіка.

Це базовий підхід до створення анімації в Matplotlib. При внесенні невеликих змін до коду можна створити більш цікаві візуалізації. Розглянемо деякі з них.

Зростаюча спіраль

Створимо спіраль, що рухається, яка буде повільно розмотуватися, за допомогою класу animation в matplotlib. Код схожий на код графіка синусоїдальної хвилі, проте містить кілька змін.

import matplotlib.pyplot as plt  
import matplotlib.animation as animation
import numpy as np
plt.style.use('dark_background')

fig = plt.figure()
ax = plt.axes(xlim=(-50, 50), ylim=(-50, 50))
line, = ax.plot([], [], lw=2)

# initialization function
def init():
# creating an empty plot/frame
line.set_data([], [])
return line,

# lists to store x and y axis points
xdata, ydata = [], []

# animation function
def animate(i):
# t is a parameter
t = 0.1 * i

# x, y values ​​to be plotted
x = t*np.sin(t)
y = t*np.cos(t)

# appending new points to x, y axes points list
xdata.append(x)
ydata.append(y)
line.set_data(xdata, ydata)
return line,

# setting a title for the plot
plt.title('Creating a growing coil with matplotlib!')
# hiding the axis details
plt.axis('off')

# call the animator
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=500, interval=20, blit=True)

# save the animation as mp4 video file
anim.save('coil.gif',writer='imagemagick')

Графік оновлення в режимі реального часу

Графіки оновлення в режимі реального часу стануть у нагоді при побудові динамічних величин, таких як дані про запаси, дані сенсорів та інші залежні від часу дані. Створюємо базовий граф, який оновлюється автоматично з появою нових даних у системі. Створимо графік цін на акції компанії за місяць.

#importing libraries
import matplotlib.pyplot as plt
import matplotlib.animation as animation


fig = plt.figure()
#creating a subplot
ax1 = fig.add_subplot(1,1,1)

def animate(i):
data = open('stock.txt','r').read()
lines = data.split('\n')
xs = []
ys = []

for line in lines:
x, y = line.split(',') # Delimiter is comma
xs.append(float(x))
ys.append(float(y))


ax1.clear()
ax1.plot(xs, ys)

plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Live graph with matplotlib')


ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()

Відкрийте термінал та запустіть файл python. Отримуємо зображений нижче графік, який автоматично оновлюється таким чином:

Інтервал складає 1000 мілісекунд або одну секунду.

Анімація на 3D-графіці

Створення 3D-графіків досить поширене, проте, якщо анімувати кут огляду в цих графіках? Ідея полягає у зміні огляду камери та використанні кожного результуючого зображення для створення анімації. У Python Graph Gallery можна знайти розділ, присвячений цій темі.

Створіть папку volcano в одному каталозі із notebook. Усі зображення, які будуть використовуватися в анімації, зберігаються у цій папці.

# library
від mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

# Get the data (csv file is hosted on the web)
url = 'https://python-graph-gallery.com/wp-content/uploads/volcano.csv'
data = pd.read_csv(url)

# Transform it to a long format
df=data.unstack().reset_index()
df.columns=["X","Y","Z"]

# And transform the old column name in something numeric
df['X']=pd.Categorical(df['X'])
df['X']=df['X'].cat.codes

# We are going to do 20 plots, for 20 different angles
for angle in range(70,210,2):

# Make the plot
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_trisurf(df['Y'], df['X'], df['Z'], cmap=plt.cm.viridis, linewidth=0.2)

ax.view_init(30,angle)

filename='Volcano/Volcano_step'+str(angle)+'.png'
plt.savefig(filename, dpi=96)
plt.gca()

Цей фрагмент коду створить кілька файлів PNG у папці Volcano.Тепер використовуємо ImageMagick для створення анімації з цих зображень. Відкрийте термінал, перейдіть до папки Volcano та введіть наступну команду:

convert -delay 10 Volcano*.png animated_volcano.gif

Анімації з використанням модуля Celluloid

Celluloid - це модуль у Python, що спрощує процес створення анімації в matplotlib. Ця бібліотека створює фігуру matplotlib та Camera з неї. Потім вона використовує фігуру і робить знімок із камери після створення кожного кадру. Нарешті створюється анімація зі всіх захоплених кадрів.

Встановлення

pip install celluloid

Декілька прикладів використання модуля Celluloid.

Minimal

from matplotlib import pyplot as plt
from celluloid import Camera

fig = plt.figure()
camera = Camera(fig)
for i in range(10):
plt.plot([i] * 10)
camera.snap()
animation = camera.animate()
animation.save('celluloid_minimal.gif', writer = 'imagemagick')

Subplots

import numpy as np
from matplotlib import pyplot as plt
from celluloid import Camera

fig, axes = plt.subplots(2)
camera = Camera(fig)
t = np.linspace (0, 2 * np.pi, 128, endpoint = False)
for i in t:
axes[0].plot(t, np.sin(t + i), color='blue')
axes[1].plot(t, np.sin(t - i), color='blue')
camera.snap()

animation = camera.animate()
animation.save('celluloid_subplots.gif', writer = 'imagemagick')

Legends

import matplotlib
from matplotlib import pyplot as plt
from celluloid import Camera

fig = plt.figure()
camera = Camera(fig)
for i in range(20):
t = plt.plot (range (i, i + 5))
plt.legend(t, [f'line'])
camera.snap()
animation = camera.animate()
animation.save('celluloid_legends.gif', writer = 'imagemagick')

Висновок

За допомогою анімації можна наголосити на особливостях візуалізації, які важко передати за допомогою статичних діаграм. Однак не варто зловживати використанням візуалізацій. Кожну функцію візуалізації даних слід використовувати розумно для створення кращого ефекту.

Python-спільнота

Гра у логіці готова. Підкажіть, будь ласка,
як організувати повільний рух фішок?
Дякую!

# імпорт бібліотек
import
pygame
import
random
import
os
# введення констант
WIDTH
=
700
HEIGHT
=
700
FPS
=
60
WHITE
=
(255,
255,
255)
BLACK
=
(0,
0,
0)
RED
=
(255,
0,
0)
GREEN
=
(0,
255,
0)
BLUE
=
(0,
0,
255)
YELLOW
=
(255,
255,
0)
KOORD
=
((30,
665),
(108,
653),
(177,
647),
(251,
648),
(322,
642),
(390,
641),
(462,
648),
(528,
653),
(601,
659),
(674,
656),
(669,
584),
(602,
583),
(527,
577),
(460,
569),
(392,
573),
(322,
571),
(249,
577),
(179,
576),
(108,
573),
(33,
582),
(33,
509),
(111,
510),
(181,
508),
(253,
505),
(322,
503),
(389,
501),
(462,
505),
(531,
503),
(603,
515),
(671,
515),
(669,
439),
(600,
444),
(522,
436),
(460,
434),
(386,
435),
(318,
435),
(246,
442),
(178,
440),
(103,
437),
(37,
440),
(32,
374),
(107,
372),
(178,
373),
(245,
371),
(320,
370),
(387,
371),
(468,
372),
(527,
367),
(603,
370),
(670,
369),
(669,
296),
(598,
296),
(531,
302),
(466,
306),
(385,
304),
(318,
304),
(247,
305),
(180,
302),
(106,
305),
(31,
306),
(35,
235),
(108,
234),
(178,
234),
(249,
234),
(319,
233),
(388,
234),
(454,
236),
(524,
237),
(602,
234),
(666,
233),
(663,
166),
(593,
171),
(523,
169),
(454,
166),
(385,
167),
(315,
166),
(244,
167),
(181,
167),
(109,
168),
(38,
165),
(35,
100),
(112,
103),
(180,
106),
(252,
101),
(320,
99),
(389,
98),
(457,
96),
(523,
97),
(587,
101),
(665,
98),
(662,
33),
(586,
32),
(522,
32),
(454,
33),
(379,
31),
(315,
34),
(247,
36),
(175,
36),
(107,
38),
(41,
38))
# створення гри та вікна
pygame.init()
screen
=
pygame.display.set_mode((WIDTH,
HEIGHT))
pygame.display.set_caption("Змії та сходи")
clock
=
pygame.time.Clock()
font_name
=
pygame.font.match_font('arial')
game_folder
=
os.path.dirname(__file__)
# завантаження ігрової графіки
background
=
pygame.image.load(os.path.join(game_folder,
'pole.png')).convert()
background_rect
=
background.get_rect()
def
draw_text(surf,
text,
size,
x,
y):
"""пише текст у циклі гри"""
font
=
pygame.font.Font(font_name,
size)
text_surface
=
font.render(text,
True,
BLACK,
WHITE)
text_rect
=
text_surface.get_rect()
text_rect.midtop
=
(x,
y)
surf.blit(text_surface,
text_rect)
def
key(param):
"""Відпрацювання натискання на пробіл"""
resp
=
False
keys
=
pygame.key.get_pressed()
if
keys[param]:
resp
=
True
return
resp
def
open_game():
"Початкова заставка гри""
draw_text(screen,
"ЗМІЇ І СХОДИ",
64,
WIDTH
/
2,
HEIGHT
/
4)
draw_text(screen,
"Гра з кубиком",
64,
WIDTH
/
2,
HEIGHT
/
2)
draw_text(screen,
"Натисніть кнопку s",
64,
WIDTH
/
2,
HEIGHT
*
3
/
4)
if
key(pygame.K_s):
Loop.flag_begin
=
False
Loop.flag_gamer_turn
=
True
def
victor():
"Заставка перемога і вихід на початок"
draw_text(screen,
"Переміг <> гравець!".format(Loop.flag_vinner),
64,
WIDTH
/
2,
HEIGHT
/
4)
draw_text(screen,
"Натисніть кнопку f",
44,
WIDTH
/
2,
HEIGHT
/
2)
if
key(pygame.K_f):
player.index
=
0
player1.index
=
0
player.rect.center
=
KOORD[player.index]
player1.rect.center
=
KOORD[player1.index]
Loop.flag_begin
=
True
Loop.flag_gamer_turn
=
False
Loop.flag_vipalo
=
False
Loop.flag_hod
=
False
Loop.flag_victor
=
False
def
sdvig():
x,
y
=
KOORD[player.index]
x
+=
10
player.rect.center
=
x,
y
class
Player(pygame.sprite.Sprite):
"Основний клас для гравців"
def
__init__(self,
color,
name):
pygame.sprite.Sprite.__init__(self)
self.name
=
name
self.image
=
pygame.Surface((20,
20))
self.image.fill(color)
self.rect
=
self.image.get_rect()
self.index
=
0
self.rect.center
=
KOORD[self.index]
def
brosok(self):
"Гравець кидає кубик"
draw_text(screen,
"<> гравець кидає кубик".format(self.name),
44,
WIDTH
/
2,
HEIGHT
/
4)
draw_text(screen,
"Натисніть кнопку d",
44,
WIDTH
/
2,
HEIGHT
/
2)
if
key(pygame.K_d):
self.kubik
=
random.randint(1,
6)
#self.kubik = int(input("input"))
Loop.flag_gamer_turn
=
False
Loop.flag_vipalo
=
True
def
vipalo(self):
Заставка випала на кубику.
draw_text(screen,
"Випадає <>".format(self.kubik),
64,
WIDTH
/
2,
HEIGHT
/
4)
draw_text(screen,
"Натисніть кнопку c",
44,
WIDTH
/
2,
HEIGHT
/
2)
if
key(pygame.K_c):
Loop.flag_vipalo
=
False
Loop.flag_hod
=
True
def
hod(self):
"Рух фішки"
def
foo(x,
y,
x1,
y1):
#### delete #### nonlocal x, x1, y, y1
if
x!=x1
or
y!=y1:
if
x!=x1:
if
xx1:
x
+=
1
elif
x>x1:
x
-=
1
if
y!=y1:
if
yy1:
y
+=
1
elif
y>y1:
y
-=
1
#print("self.rect.center x=<> y<>".format(x, y))
self.rect.center
=
x,
y
foo(x,
y,
x1,
y1)
def
foo1(kort,
delta):
for
self.index
in
kort:
print("self.index = ",self.index)
x,
y
=
KOORD[self.index]
x1,
y1
=
KOORD[self.index
+
delta]
foo(x,
y,
x1,
y1)
self.index
+=
delta
if
self.kubik:
if
self.index==98:
Loop.flag_vinner
=
self.name
Loop.flag_hod
=
False
Loop.flag_victor
=
True
print("<> kub <> index <>".format(self.name,
self.kubik,
self.index))
x,
y
=
KOORD[self.index]
x1,
y1
=
KOORD[self.index
+
1]
foo(x,
y,
x1,
y1)
self.index
+=
1
self.kubik
-=
1
elif
self.index==4:
self.index
=
14
self.rect.center
=
KOORD[self.index]
elif
self.index==8:
foo1((8,
7,
6),
-1)
elif
self.index==9:
foo1((9,
10,
29),
1)
elif
self.index==17:
foo1((17,
1,
2),
1)
elif
self.index==23:
foo1((23,
37,
40),
1)
elif
self.index==32:
foo1((32,
47,
52,
67,
72,
86),
1)
elif
self.index==33:
foo1((33,
27,
12),
1)
elif
self.index==39:
foo1((39,
20,
21),
1)
elif
self.index==40:
foo1((40,
59,
60,
78),
1)
elif
self.index==50:
foo1((50,
49),
-1)
elif
self.index==56:
foo1((56,
64,
73),
1)
elif
self.index==61:
foo1((61,
57,
43,
44,
34,
25,
23),
1)
elif
self.index==83:
self.index
=
95
self.rect.center
=
KOORD[self.index]
elif
self.index==89:
self.index
=
91
self.rect.center
=
KOORD[self.index]
elif
self.index==93:
foo1((93,
86,
73,
66,
65,
54),
1)
elif
self.index==97:
foo1((97,
82,
77),
1)
else:
print("Stop on",
self.index)
self.turner()
Loop.flag_hod
=
False
Loop.flag_gamer_turn
=
True
def
turner(self):
""Перехід ходу""
if
Loop.flag_turn==1:
Loop.flag_turn
=
2
else:
Loop.flag_turn
=
1
class
Loop:
"Тут будемо зберігати прапори циклу гри"""
flag_begin
=
True
flag_gamer_turn
=
False
flag_vipalo
=
False
flag_hod
=
False
flag_turn
=
1
flag_victor
=
False
flag_vinner
=
None
player
=
Player(GREEN,
"Перший")
player1
=
Player(RED,
"Другий")
all_sprites
=
pygame.sprite.Group()
all_sprites.add(player,
player1)
цикл гри
running
=
True
while
running:
швидкість циклу
clock.tick(FPS)
контроль виходу хрестиком
for
event
in
pygame.event.get():
if
event.type
==
pygame.QUIT:
running
=
False
# Рендеринг
screen.blit(background,
background_rect)
all_sprites.draw(screen)
# Початкова заставка
if
Loop.flag_begin:
open_game()
# заставка кидок гравця
if
Loop.flag_gamer_turn:
if
Loop.flag_turn==1:
player.brosok()
else:
player1.brosok()
# заставка випала
if
Loop.flag_vipalo:
if
Loop.flag_turn==1:
player.vipalo()
else:
player1.vipalo()
# хід гравця
if
Loop.flag_hod:
if
Loop.flag_turn==1:
player.hod()
else:
player1.hod()
# Зсув фішок в одній клітці
if
player.index==player1.index:
sdvig()
# заставка перемога
if
Loop.flag_victor:
victor()
# Переворот екрану
pygame.display.flip()
вихід з гри
pygame.quit()

Схожі статті

  • Як і з чого зробити підлогу в підвалі 7 варіантів матеріалів - Статті про будівництво ремонт
  • Що потрібно щоб зробити ставку
  • Що потрібно зробити щоб продати акції
  • Як з автогенератора зробити вітрогенератор
  • Що можна зробити із пакетів від молока
  • Що зробити щоб не було запаху перегару
  • Як зробити документ горизонтальним
  • Що можна зробити замість ЕЕГ
  • Недавні статті

  • Чому взуття скрипить при ходьбі
  • Коли день народження у стрічці
  • Чи можна кішці їсти сіль
  • Варіанти планування ділянки 15 соток прямокутної форми
  • Що означає півмісяця знак
  • Рейсмусовий верстат для чого
  • У якому віці парують свиней
  • У чому полягає принцип нарахування та у яких випадках він застосовується