Продолжаем начатое. Добавим в игру увеличение скорости если питон ест, и подсчет очков. Добавим переменные:
1
2
3
4
5
6
...
speed=500;# начальная скорость питона
increase_speed=10;# размер увеличения скорости при удачной еде
score=0;# набранные очки в результате игры
score_color=(100,100,50)# цвет очков
...
Интересный момент работы с таймером. По умолчанию time.time() отдает данные в секундах целые числа, и доли секунд в цифрах после запятой. Для того чтобы соответственно удобно считать миллисекунды, значения нужно умножать на 1000. Изменим код:
1
2
3
4
5
6
7
8
start_time=time.time()*1000
...
whilerunning:
if(time.time()*1000-start_time)>speed:
start_time=time.time()*1000
Draw_foods(screen)
Draw_python(screen)
...
А теперь изменим функцию Draw_python, добавив отрисовку количества очков, а так-же увеличение скорости и количества очков при поедании:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
globalscore,speed
..
forelement infoods:
if[element[0],element[1]]==head_coor:
del_tail=False
foods.remove(element)
speed=speed-increase_speed# увеличиваем скорость питона
score=score+element[0]# увеличиваем очки в зависимости от типа сожранного
Добавим еще штрих — сделаем реакцию на столкновение со стенами поля, а именно чтоб питон переходил на левый край при столкновении с правым и т.д.,
1
2
3
4
5
6
7
8
9
...if(head_coor[0]>size_x):
head_coor[0]=1;
if(head_coor[1]>size_y):
head_coor[1]=1;
if(head_coor[0]<0):
head_coor[0]=size_x;
if(head_coor[1]<0):
head_coor[1]=size_y;
...
Теперь не хватает последнего: проигрыша в случае столкновения головы с хвостом. Объявим глобальный цикл в котором будет крутится игра, в нём разместим цикл игры. При проигрыше выводим вопрос «Вы проиграли хотите еще (Y/N)» Если игрок выбирает Y, то из глобального цикла не выходим, иначе покидаем глобальный цикл.
В предыдущей части, мы научили питона двигаться. Теперь чуть усложним задачу: раскидаем по игровому полю еду, и в том случае если питон её съедает, то питон растёт. В результате получится что-то вроде:
Что делаем сначала? А сначала инициируем массив с едой, где будет храниться координаты еды, и её тип. В зависимости от типа еды, ёё цвет будет разным. Так-же определим массив с доступными цветами еды, и количество еды доступной на поле одномоментно:
.
1
2
3
4
foods=[]# массив координат с едой
max_foods=3# сколько еды может быть одновременно на поле
Далее напишем функцию, которая генерирует распределение еды на поле случайным образом. При генерации проверяется, совпадение координат с телом питона — нужно не допустить генерацию «внутри» питона. Сюда же поместим и отрисовку сгенерированной еды:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Генерируем и отрисовываем еду для питона
def Draw_foods(screen):
foriinrange(max_foods-len(foods)):# массив с едой всегда должен быть "полон"
whileTrue:# цикл генерации еды. Генерируем до тех пор пока сгенерированные координаты не устроят нас
x=random.randint(0,size_x)+1
y=random.randint(0,size_y)+1
food_type=random.randint(0,len(color_food)-1)
if[x,y]notinpython_body:
break;
foods.insert(0,[x,y,food_type])
print(f"Нагенерировали еды: {foods}, теперь её нарисуем");
Далее чуть изменим функцию отрисовки движения питона Draw_python. А именно добавим проверку совпадения координат головы питона с координатами еды. Если совпадение есть — то еду удаляем, а хвост удлиняем (т.е. фактически не удаляем при движении)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#проверяем: если голова совпадает с какойто едой, то еду удаляем, а жопу не удяляем
В рамках компании по попытке обучения одного товарища программированию начал писать классическую игру Питон. С правилами: питон двигается по полю, если он что-то ест, то растёт. Если натыкается на стену или на самого себя — игрок проигрывает.
В этой части обучающей статьи, мы научимся вырисовывать питона и управлять им с клавиатуры. Результатом будет что-то вроде:
Для отрисовки графики и получения событий нажатия клавиш будем использовать библиотеку pygame
Итак начнем. Сначала зададим настроечные переменные для игры, как то размер поля, цвета и т.п.:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# объявляем переменные
FPS=60
width_field=800# размер поля по ширине
height_field=600# размер поля по высоте
size_x=20# количество клеток по ширине
size_y=20# количество клеток по высоте
color_grid=(0,200,100)# цвет линий ячеек
fill_grid=(0,0,0)# цвет игровогого поля
color_python=(50,200,100)# цвет тела питона
step_x=round(width_field/size_x,0)# шаг клетки по ширине
step_y=round(height_field/size_y,0)# шаг клетки по высоте
python_body=[[round(size_x/2,0),round(size_y/2,0)],[round((size_x-2)/2,0),round(size_y/2,0)],[round((size_x-4)/2,0),round(size_y/2,0)]]# массив тела питона
moved_direction_x=0# текущее направление движения питона по оси x
moved_direction_y=0# текущее направление движения питона по оси y
Затем создадим окно с указанными размерами , закрасим его чёрным цветом, и нарисуем сетку:
Далее нам нужно создать бесконечный цикл, внутри которого будем ловить события нажатия стрелочек клавиатуры, и задавать вектор движения головы питона:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
running=True
whilerunning:
forevent inpygame.event.get():
ifevent.type==pygame.KEYDOWN:
ifevent.key==pygame.K_LEFT:
moved_direction_x=-1
moved_direction_y=0
ifevent.key==pygame.K_RIGHT:
moved_direction_x=1
moved_direction_y=0
ifevent.key==pygame.K_UP:
moved_direction_y=-1
moved_direction_x=0
ifevent.key==pygame.K_DOWN:
moved_direction_x=0
moved_direction_y=1
ifevent.type==pygame.QUIT:
running=False
pygame.display.flip()
pygame.display.update()
clock.tick(FPS)
pygame.quit()
print("нормально вышли")
Если мы сейчас в этот цикл вставим событие отрисовки самого питона, то он будет двигаться с дикой скоростью. Ограничим её одной клеткой в секунду, используя измерение времени. В начале цикла замерим время начала игры, и внутри цикла, если видим, что прошла секунда — отрисовываем питона, для этого чуть изменим код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
start_time=time.time()
running=True
whilerunning:
if(time.time()-start_time)>1:
start_time=time.time()
Draw_python(screen)
forevent inpygame.event.get():
ifevent.type==pygame.KEYDOWN:
ifevent.key==pygame.K_LEFT:
moved_direction_x=-1
moved_direction_y=0
ifevent.key==pygame.K_RIGHT:
moved_direction_x=1
moved_direction_y=0
ifevent.key==pygame.K_UP:
moved_direction_y=-1
moved_direction_x=0
ifevent.key==pygame.K_DOWN:
moved_direction_x=0
moved_direction_y=1
ifevent.type==pygame.QUIT:
running=False
pygame.display.flip()
pygame.display.update()
clock.tick(FPS)
pygame.quit()
print("нормально вышли")
Функции отрисовки питона (Draw_python) пока нет. Создадим её.. В начале функции посчитаем радиус кружка тела. Потом если вектор направления задан, то голову передвинем на вектор, а жопу питона удалим. Таким образом создадим видимость движения питона:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# рисуем питона
def Draw_python(screen):
radius=(round(step_x/2)-1)ifround(step_x/2)<round(step_y/2)else(round(step_y/2)-1)# выбираем радиус по ширине или высоте шага, смотря что меньше, чтоб вписаться в прямоугольник
ifmoved_direction_x!=0ormoved_direction_y!=0:
print(f"Пришли:{python_body}")
head_coor=python_body[0].copy()
head_coor[0]=head_coor[0]+moved_direction_x;
head_coor[1]=head_coor[1]+moved_direction_y;
print(f"-тело{python_body},голова: {head_coor}");
python_body.insert(0,head_coor)# передвигаю голову
В общем в рамках компании по попытке обучения одного товарища программированию, написал небольшую консольную игру, дабы с ним попробовать её воспроизвести.
Суть игры: компьютер загадывает случайную кнопку из списка и время за которое игрок должен успеть её нажать. Если игрок успевает нажать — ему добавляется балл.
Итак, для написания понадобится знать что такое циклы, массивы, случайные числа. Использовать будем модули keyboard, random и time
keyboard — для получения нажатий клавиш на клавиатуре
random — для получения случайных числел
time — для расчета времени реакции
Для начала определим одномерный массив, в котором перечислим доступные для выбора компьютером клавиши.
1
keys=["q","w","e","r","t","y"];
Далее создадим бесконечный цикл, внутри которого будем выбирать случайную клавишу для нажатия:
1
2
3
4
5
6
7
8
import keyboard
import random
import time
keys=["q","w","e","r","t","y"];
whileTrue:
key_to_press=keys[random.randint(0,len(keys)-1)]
print(f"-нажми кнопку {key_to_press}")
Что делает этот код? Бесконечно выводит в консоль сообщение о том, что нужно нажать случайно выбранную кнопку. Давайте теперь чуть переделаем код, чтобы случайно выбиралась не только клавиша которую нужноно нажать игроку, но и время за которое ему нужно её нажать:
1
2
3
4
5
6
7
8
9
10
import keyboard
import random
import time
keys=["q","w","e","r","t","y"];
whileTrue:
key_to_press=keys[random.randint(0,len(keys)-1)]
time_to_press=random.randint(1,3)
print(f"Нажми кнопку {key_to_press} за {time_to_press} секунды");
Что дальше? А дальше нам нужно объявить еще один цикл и ждать пока не истечет время отведенное для того чтобы игрок нажал кнопку. Для этого, перед началом цикла запомним время начала игры, и внутри цикла постоянно будем проверять, на сколько оно отличается от текущего времени:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import keyboard
import random
import time
keys=["q","w","e","r","t","y"];
whileTrue:
key_to_press=keys[random.randint(0,len(keys)-1)]
time_to_press=random.randint(1,3)# время в секундах ожидания реакции
print(f"Нажми кнопку {key_to_press} за {time_to_press} секунды");
start_time=time.time()# запоминаем время начала игры
whileTrue:
if(time.time()-start_time>time_to_press):# разница между текущее временем и временем начала игры больше чем time_to_press, то игрок не успел нажать кнопку
print("- ты проиграл, не успел нажать!")
break;
Теперь добавим чуточку интерактивности, а именно проверку, «а не нажата ли клавиша загаданная компьютером»:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import keyboard
import random
import time
keys=["q","w","e","r","t","y"];
whileTrue:
key_to_press=keys[random.randint(0,len(keys)-1)]
time_to_press=random.randint(1,3)# время в секундах ожидания реакции
print(f"Нажми кнопку {key_to_press} за {time_to_press} секунды");
start_time=time.time()# запоминаем время начала игры
whileTrue:
if(time.time()-start_time>time_to_press):# разница между текущее временем и временем начала игры больше чем time_to_press, то игрок не успел нажать кнопку
print("- ты проиграл, не успел нажать!")
break;
ifkeyboard.is_pressed(key_to_press):
print(f'-Ты выиграл!')
break
Ну и осталось чуток прилизать код, добавив возможность подсчета кто круче, компьютер или игрок:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import keyboard
import random
import time
# создадим массив с доступными клавишами
keys=["q","w","e","r","t","y"];
count_win_gamer=0
count_win_pc=0
whileTrue:
start_time=time.time()
key_to_press=keys[random.randint(0,len(keys)-1)]
time_to_press=random.randint(1,3)
print(f"Нажми кнопку {key_to_press} за {time_to_press} секунды");
win=False;
whileTrue:
if(time.time()-start_time>time_to_press):
print(f"- ты проиграл уже {count_win_pc} , не успел нажать! Общий счёт: {count_win_pc}/{count_win_gamer} (ты)")
count_win_pc=count_win_pc+1
break;
ifkeyboard.is_pressed(key_to_press):
count_win_gamer=count_win_gamer+1
print(f'-Ты выиграл уже {count_win_gamer} раз! Общий счёт: {count_win_pc}/{count_win_gamer} (ты)')