Найти в Дзене
Python gamedev

Игра морской бой на языке программирования PYTHON (ч.1)

Я решил немного отступить от обзора моей игры 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\\

Я решил немного отступить от обзора моей игры 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()

В следующей статье будет продолжение создания игры - анимация стрельбы по кораблику, анимация взрыва кораблика. А здесь можно посмотреть - что получилось на данном этапе.