Я решил немного отступить от обзора моей игры WORLDSPACE и показать, как можно быстро написать простую и довольно популярную игру "морской бой".
Моя игра будет немного проще, но анимации побольше)). Пожалуй, начнем!
Любая программа на python начинается с импорта необходимых модулей. Нам понадобятся модули tkinter и из модуля PIL мы загрузим Image, ImageTk:
import tkinter as tk
from tkinter import*
from PIL import Image, ImageTk
tkinter - это графический интерфейс, в котором будет отображаться наша игра, а image и ImageTk из библиотеки PIL - загрузка и обработка картинок.
root = tk.Tk()
root.geometry("1000x546+2+10")
root.resizable(width=False, height=False)
root = tk.Tk() - создание главного окна нашей игры
root.geometry("1000x546+2+10") - геометрия главного окна (ширина, высота, координата х верхнего левого угла, координата у верхнего левого угла)
root.resizable(width=False, height=False) - запрет изменения размеров главного окна по ширине и высоте
frames = [PhotoImage(file='C:\\sea\\sea_011.gif', format = 'gif -index %i' %(i)) for i in range(20)] - создание списка методом генератора списков и заполнение этого списка кадрами из gif-анимации и присвоение переменной frames этого списка. Число (20) в цикле - это количество кадров, которое содержит gif-анимация.
Небольшое отступление. gif-анимацию можно скачать с интернета, а можно ее сделать самому. Я делал ее сам при помощи программы Sqirlz Water Reflections - наложение спецэффектов на воду.
Создаем холст для размещения будущей графики:
canvas1 = Canvas(root, width = 1000, height = 546) - root - родитель для холста, ширина холста 1000 пикселей, высота 546 пикселей
Упаковываем холст методом place в родительском окне:
canvas1.place(x = 0, y = 0) - упаковка place - абсолютные координаты в родительском окне (root) - указывается верхний левый угол.
Следующий код - загрузка кораблика (будущая мишень) в программу. Здесь загружаем два кораблика - для движения налево и направо.
im = Image.open("C:\\sea\\ships_10_001.png").convert('RGBA')
datas = im.getdata()
opacity_level = 0
newData = []
for item in datas:
if item[0] == 127 and item[1] == 127 and item[2] == 127:
newData.append((0, 0, 0, opacity_level))
else:
newData.append(item)
im.putdata(newData)
ship1 = ImageTk.PhotoImage(im)
fon = canvas1.create_image(0, 0, anchor = 'nw', image = frames[0])
ships = canvas1.create_image(600, 300, anchor = 'nw', image = ship1)
im = Image.open("C:\\sea\\ships_10_101.png").convert('RGBA')
datas = im.getdata()
opacity_level = 0
newData = []
for item in datas:
if item[0] == 127 and item[1] == 127 and item[2] == 127:
newData.append((0, 0, 0, opacity_level))
else:
newData.append(item)
im.putdata(newData)
ship2 = ImageTk.PhotoImage(im)
Изображение кораблика я взял с интернета и предварительно немного обработал в paint - убрал все, что не относится к кораблику окрасил в серый цвет(RGB палитра - 127,127,127). Каждый пиксель с этим цветом будет преобразован в прозрачный вот в этой строчке: newData.append((0, 0, 0, opacity_level)).
fon = canvas1.create_image(0, 0, anchor = 'nw', image = frames[0])
ships = canvas1.create_image(600, 300, anchor = 'nw', image = ship1)
Этими строчками размещаем наши картинки на холсте. fon - это первый кадр из gif-анимации (frames[0]), ships - кораблик. Для размещения картинок на холсте используются методы холста create_image. Числа - это координаты х, у места позиционирования картинок. anchor = 'nw' - это якорь для картинок - относительно какой стороны картинки будут отсчитываться координаты их размещение. В моем случае (nw) - северо-запад (верхний левый угол). image - какая картинка будет создана на холсте.
Следующий блок кода - функция анимации в нашей программе:
def update(ind, s, speed, fon, ships):
frame = frames[ind] - переменной передается кадр gif-анимации с индексом ind
ind += 1 - следующий кадр gif-анимации
if ind == 20: - если кадр gif-анимации последний
ind = 0 - обнуление индекса
canvas1.itemconfig(fon, image = frame) - изменение картинки gif-анимации на следующую
x = canvas1.coords(ships)[0] - текущая координата х кораблика
y = canvas1.coords(ships)[1] - текущая координата у кораблика
if s == 'l' and x > 10: - "l", "r" направление движение кораблика, если направление l и координата х больше 10 (правая сторона экрана)
x -= speed - изменение х на величину скорости кораблика (движение налево)
canvas1.itemconfig(ships, image = ship1) - если движение налево - картинка кораблика 1
else: - если достигли левой стороны экрана
s = 'r' - флаг направления меняется на противоположный
x += speed - движение направо
canvas1.itemconfig(ships, image = ship2)- если движение направо - картинка кораблика 2
if x < 12 or x > 908: - если достигнут правый или левый край экрана
speed += 0.02 - увеличение текущей скорости на 0,02
y += 1 - изменение координаты у (кораблик спустился на 1 пиксель вниз)
if s == 'r' and x < 910: - если флаг направления направо и координата х кораблика меньше 910
x += speed - движение направо
canvas1.itemconfig(ships, image = ship2) - картинка - кораблик 2
else: - иначе
s = 'l'- меняем флаг направления движения на противоположный
x -= speed - движение налево
canvas1.itemconfig(ships, image = ship1)
canvas1.coords(ships, x, y) - изменение текущих координат кораблика
root.after(25, update, ind, s, speed, fon, ships) - следующих "ход" для главного цикла программы: выполнить через 25мс, вызвать функцию update, вместе с этой функцией передаются параметры - текущий кадр gif-анимации (ind), флаг направлениядвижения кораблика (s), текущая скорость кораблика (speed), идентификаторы созданных картинок на холсте (fon, ships).
Вызов функции анимации:
update(0, 'l', 2, fon, ships)
Главный цикл, который запускает программу:
root.mainloop()
В следующей статье будет продолжение создания игры - анимация стрельбы по кораблику, анимация взрыва кораблика. А здесь можно посмотреть - что получилось на данном этапе.