Compare commits
No commits in common. "main" and "main" have entirely different histories.
|
@ -1,3 +0,0 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.11 (Pygame_Project_FINAL)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
|
@ -1,6 +0,0 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.11" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (Pygame_Project_FINAL)" project-jdk-type="Python SDK" />
|
||||
</project>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Pygame_Project.iml" filepath="$PROJECT_DIR$/.idea/Pygame_Project.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
421
01.03.24
|
@ -1,421 +0,0 @@
|
|||
import pygame
|
||||
import random
|
||||
import math
|
||||
|
||||
# Определение констант
|
||||
SCREEN_WIDTH = 1920
|
||||
SCREEN_HEIGHT = 1080
|
||||
PLAYER_WIDTH = 100
|
||||
PLAYER_HEIGHT = 150
|
||||
LOH_WIDTH = 300
|
||||
LOH_HEIGHT = 250
|
||||
BULLET_SIZE = 20
|
||||
FPS = 60
|
||||
BULLET_SPEED = 6
|
||||
TANK_SPEED = 2
|
||||
BOT_SPEED = 2
|
||||
FIRE_DELAY = 1000 # Задержка между выстрелами в миллисекундах
|
||||
WHITE = (255, 255, 255)
|
||||
BLACK = (0, 0, 0)
|
||||
|
||||
# Инициализация Pygame
|
||||
pygame.init()
|
||||
|
||||
# Создание игрового окна
|
||||
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags=pygame.FULLSCREEN)
|
||||
pygame.display.set_caption("Танчики")
|
||||
|
||||
# Загрузка изображений
|
||||
background_image = pygame.transform.scale(pygame.image.load("travka_pol.jpeg"), (960, 540))
|
||||
stena = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (100, 100))
|
||||
stenki = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (200, 200))
|
||||
tank_image = pygame.transform.scale(pygame.image.load("ntank-removebg-preview.png"), (PLAYER_WIDTH, PLAYER_HEIGHT))
|
||||
loh_image = pygame.transform.scale(pygame.image.load("loh.png"), (LOH_WIDTH, LOH_HEIGHT))
|
||||
bullet_image = pygame.transform.scale(pygame.image.load("bullet.png"), (BULLET_SIZE, BULLET_SIZE))
|
||||
|
||||
menu_background = pygame.transform.scale(pygame.image.load("menu_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
|
||||
|
||||
# Определение класса танка
|
||||
class Tank(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = tank_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = -90 # Поворот на 90 градусов против часовой стрелки
|
||||
self.TANK_SPEED = 2
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.boosted = False # Флаг, показывающий, активирован ли ускоритель
|
||||
self.boost_multiplier = 2 # Множитель скорости ускорения
|
||||
|
||||
def update(self):
|
||||
keys = pygame.key.get_pressed()
|
||||
if keys[pygame.K_w]:
|
||||
self.move_forward()
|
||||
mouse_pos = pygame.mouse.get_pos()
|
||||
self.angle = math.degrees(math.atan2(mouse_pos[1] - self.rect.centery, mouse_pos[0] - self.rect.centerx)) + 90
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
if keys[pygame.K_x]:
|
||||
if not self.boosted:
|
||||
self.TANK_SPEED *= self.boost_multiplier
|
||||
self.boosted = True
|
||||
else:
|
||||
if self.boosted:
|
||||
self.TANK_SPEED /= self.boost_multiplier
|
||||
self.boosted = False
|
||||
|
||||
def move_forward(self):
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += self.TANK_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += self.TANK_SPEED * math.sin(angle_rad)
|
||||
|
||||
def shoot(self):
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_fire_time > FIRE_DELAY: # Проверка задержки между выстрелами
|
||||
# Коррекция угла вылета пули, чтобы она вылетала из дула танка
|
||||
offset_angle = -90 # Угол смещения для вылета пули из дула
|
||||
corrected_angle = self.angle + offset_angle
|
||||
|
||||
# Вычисляем координаты дула танка
|
||||
offset_x = 70 * math.cos(math.radians(corrected_angle))
|
||||
offset_y = 70 * math.sin(math.radians(corrected_angle))
|
||||
bullet = PlayerBullet(self.rect.centerx + offset_x, self.rect.centery + offset_y, self.angle + 270)
|
||||
all_sprites.add(bullet)
|
||||
bullets.add(bullet)
|
||||
self.last_fire_time = current_time # Обновление времени последнего выстрела
|
||||
|
||||
|
||||
# Определение класса снаряда игрока
|
||||
class PlayerBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
# Определение класса снаряда бота
|
||||
class BotBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
# Определение класса для бота
|
||||
class Bot(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = loh_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = random.randint(0, 360) # Случайный начальный угол поворота
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.rotate_delay = random.randint(100, 500) # Начальная задержка перед поворотом
|
||||
self.rotate_timer = 0
|
||||
|
||||
def update(self):
|
||||
self.move_random()
|
||||
self.rotate_random()
|
||||
self.check_bounds()
|
||||
#self.shoot_random()
|
||||
|
||||
def move_random(self):
|
||||
# Движение вперёд в направлении текущего угла поворота
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += BOT_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += BOT_SPEED * math.sin(angle_rad)
|
||||
|
||||
def rotate_random(self):
|
||||
# Случайный поворот бота
|
||||
self.rotate_timer += 1
|
||||
if self.rotate_timer >= self.rotate_delay:
|
||||
self.angle += random.randint(-10, 10) # Случайный поворот
|
||||
self.rotate_delay = random.randint(100, 500) # Новая случайная задержка перед поворотом
|
||||
self.rotate_timer = 0
|
||||
|
||||
def check_bounds(self):
|
||||
# Проверка выхода за границы экрана
|
||||
if self.rect.left < 0:
|
||||
self.rect.left = 0
|
||||
elif self.rect.right > SCREEN_WIDTH:
|
||||
self.rect.right = SCREEN_WIDTH
|
||||
if self.rect.top < 0:
|
||||
self.rect.top = 0
|
||||
elif self.rect.bottom > SCREEN_HEIGHT:
|
||||
self.rect.bottom = SCREEN_HEIGHT
|
||||
|
||||
#def shoot_random(self):
|
||||
# Выстрел в направлении дула
|
||||
#current_time = pygame.time.get_ticks()
|
||||
#if current_time - self.last_fire_time > random.randint(1000, 5000):
|
||||
#bullet = BotBullet(self.rect.centerx, self.rect.centery, self.angle + 90) # Стрельба в направлении дула
|
||||
#all_sprites.add(bullet)
|
||||
#bullets.add(bullet)
|
||||
#self.last_fire_time = current_time
|
||||
|
||||
|
||||
|
||||
class Wall(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, image):
|
||||
super().__init__()
|
||||
self.image = image
|
||||
self.rect = self.image.get_rect(topleft=(x, y))
|
||||
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
walls = pygame.sprite.Group() # Группа для всех стен
|
||||
|
||||
|
||||
# Создание стен
|
||||
wall_positions = [
|
||||
(360, 40), (460, 730), (460, 830), (460, 930),
|
||||
(960, 40), (960, 140), (960, 240),
|
||||
(660, 240),
|
||||
(960, 440), (960, 540), (960, 640), (960, 740),
|
||||
(1260, 740), (1360, 740), (1460, 740), (1560, 740), (1660, 740),
|
||||
(360, 240), (360, 340), (360, 440),
|
||||
(0, 540), (60, 540), (260, 540), (360, 540), (460, 540),
|
||||
(560, 540), (660, 540), (760, 540), (860, 540),
|
||||
(1160, 240), (1260, 240), (1360, 240), (1460, 240), (1460, 340),
|
||||
(1760, 340), (1860, 340)
|
||||
]
|
||||
|
||||
for pos in wall_positions:
|
||||
wall = Wall(*pos, stena)
|
||||
all_sprites.add(wall)
|
||||
walls.add(wall)
|
||||
|
||||
# Создание стен "stenki"
|
||||
wall_stenki_positions = [
|
||||
(-150, 0), (-150, 200), (-150, 400), (-150, 600), (-150, 800), (-150, 1000),
|
||||
(0, -150), (200, -150), (400, -150), (600, -150), (800, -150), (1000, -150),
|
||||
(1200, -150), (1400, -150), (1600, -150), (1800, -150), (1870, 0), (1870, 200),
|
||||
(1870, 400), (1870, 600), (1870, 800), (1870, 1000), (0, 1030), (200, 1030),
|
||||
(400, 1030), (600, 1030), (800, 1030), (1000, 1030), (1200, 1030), (1400, 1030),
|
||||
(1600, 1030), (1800, 1030)
|
||||
]
|
||||
|
||||
for pos in wall_stenki_positions:
|
||||
wall_stenki = Wall(*pos, stenki)
|
||||
all_sprites.add(wall_stenki)
|
||||
walls.add(wall_stenki)
|
||||
|
||||
|
||||
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
|
||||
# Создание игрока
|
||||
player = Tank(SCREEN_WIDTH // 8, SCREEN_HEIGHT // 7)
|
||||
all_sprites.add(player)
|
||||
tanks.add(player)
|
||||
|
||||
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
def draw_menu():
|
||||
screen.blit(menu_background, (0, 0))
|
||||
# Рисуем текст меню
|
||||
font = pygame.font.Font(None, 50)
|
||||
text = font.render("Start", True, WHITE)
|
||||
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 50))
|
||||
screen.blit(text, text_rect)
|
||||
|
||||
# Рисуем кнопку "Выйти"
|
||||
quit_text = font.render("Quit", True, WHITE)
|
||||
quit_rect = quit_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 50))
|
||||
screen.blit(quit_text, quit_rect)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
return quit_rect # Возвращаем прямоугольник для кнопки "Выйти"
|
||||
|
||||
|
||||
def respawn_bot():
|
||||
# Создание нового экземпляра бота
|
||||
new_bot = Bot(random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
|
||||
all_sprites.add(new_bot)
|
||||
tanks.add(new_bot)
|
||||
|
||||
|
||||
# Главный цикл программы
|
||||
menu_active = True
|
||||
while menu_active:
|
||||
quit_rect = draw_menu()
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # Левая кнопка мыши
|
||||
if quit_rect.collidepoint(event.pos):
|
||||
pygame.quit()
|
||||
quit()
|
||||
else:
|
||||
menu_active = False # Нажата кнопка "Старт"
|
||||
|
||||
|
||||
|
||||
# Основной игровой цикл
|
||||
clock = pygame.time.Clock()
|
||||
running = True
|
||||
|
||||
|
||||
while running:
|
||||
player_bullets = []
|
||||
bot_bullets = []
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: # Обработка левой кнопки мыши
|
||||
player.shoot()
|
||||
|
||||
# Обновление всех спрайтов
|
||||
all_sprites.update()
|
||||
|
||||
# Проверка столкновений пуль с танками
|
||||
for bullet in bullets:
|
||||
if isinstance(bullet, PlayerBullet):
|
||||
tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
|
||||
if tank_hit and isinstance(tank_hit, Bot):
|
||||
tank_hit.kill() # Удаляем бота, если попал игрок
|
||||
bullet.kill() # Удаляем пулю
|
||||
elif isinstance(bullet, BotBullet):
|
||||
tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
|
||||
if tank_hit and isinstance(tank_hit, Tank):
|
||||
tank_hit.kill() # Удаляем игрока, если попал бот
|
||||
bullet.kill() # Удаляем пулю
|
||||
if tank_hit and isinstance(tank_hit, Bot):
|
||||
tank_hit.kill() # Удаляем бота, если попал игрок
|
||||
bullet.kill() # Удаляем пулю
|
||||
respawn_bot() # Пересоздаем бота в случайном месте карты
|
||||
|
||||
bullet.update()
|
||||
|
||||
# Отрисовка фона
|
||||
for i in range(2):
|
||||
for j in range(2):
|
||||
screen.blit(background_image, (i * 960, j * 540))
|
||||
|
||||
all_sprites.draw(screen)
|
||||
screen.blit(stena, (360, 40))
|
||||
|
||||
screen.blit(stena, (460, 730))
|
||||
screen.blit(stena, (460, 830))
|
||||
screen.blit(stena, (460, 930))
|
||||
|
||||
screen.blit(stena, (960, 40))
|
||||
screen.blit(stena, (960, 140))
|
||||
screen.blit(stena, (960, 240))
|
||||
|
||||
screen.blit(stena, (660, 240))
|
||||
|
||||
screen.blit(stena, (960, 440))
|
||||
screen.blit(stena, (960, 540))
|
||||
screen.blit(stena, (960, 640))
|
||||
screen.blit(stena, (960, 740))
|
||||
|
||||
screen.blit(stena, (1260, 740))
|
||||
screen.blit(stena, (1360, 740))
|
||||
screen.blit(stena, (1460, 740))
|
||||
screen.blit(stena, (1560, 740))
|
||||
screen.blit(stena, (1660, 740))
|
||||
|
||||
screen.blit(stena, (360, 240))
|
||||
screen.blit(stena, (360, 340))
|
||||
screen.blit(stena, (360, 440))
|
||||
|
||||
screen.blit(stena, (0, 540))
|
||||
screen.blit(stena, (60, 540))
|
||||
screen.blit(stena, (260, 540))
|
||||
screen.blit(stena, (360, 540))
|
||||
screen.blit(stena, (460, 540))
|
||||
screen.blit(stena, (560, 540))
|
||||
screen.blit(stena, (660, 540))
|
||||
screen.blit(stena, (760, 540))
|
||||
screen.blit(stena, (860, 540))
|
||||
|
||||
screen.blit(stena, (1160, 240))
|
||||
screen.blit(stena, (1260, 240))
|
||||
screen.blit(stena, (1360, 240))
|
||||
screen.blit(stena, (1460, 240))
|
||||
screen.blit(stena, (1460, 340))
|
||||
screen.blit(stena, (1760, 340))
|
||||
screen.blit(stena, (1860, 340))
|
||||
|
||||
screen.blit(stenki, (-150, 0))
|
||||
screen.blit(stenki, (-150, 200))
|
||||
screen.blit(stenki, (-150, 400))
|
||||
screen.blit(stenki, (-150, 600))
|
||||
screen.blit(stenki, (-150, 800))
|
||||
screen.blit(stenki, (-150, 1000))
|
||||
screen.blit(stenki, (0, -150))
|
||||
screen.blit(stenki, (200, -150))
|
||||
screen.blit(stenki, (400, -150))
|
||||
screen.blit(stenki, (600, -150))
|
||||
screen.blit(stenki, (800, -150))
|
||||
screen.blit(stenki, (1000, -150))
|
||||
screen.blit(stenki, (1200, -150))
|
||||
screen.blit(stenki, (1400, -150))
|
||||
screen.blit(stenki, (1600, -150))
|
||||
screen.blit(stenki, (1800, -150))
|
||||
screen.blit(stenki, (1870, 0))
|
||||
screen.blit(stenki, (1870, 200))
|
||||
screen.blit(stenki, (1870, 400))
|
||||
screen.blit(stenki, (1870, 600))
|
||||
screen.blit(stenki, (1870, 800))
|
||||
screen.blit(stenki, (1870, 1000))
|
||||
screen.blit(stenki, (0, 1030))
|
||||
screen.blit(stenki, (200, 1030))
|
||||
screen.blit(stenki, (400, 1030))
|
||||
screen.blit(stenki, (600, 1030))
|
||||
screen.blit(stenki, (800, 1030))
|
||||
screen.blit(stenki, (1000, 1030))
|
||||
screen.blit(stenki, (1200, 1030))
|
||||
screen.blit(stenki, (1400, 1030))
|
||||
screen.blit(stenki, (1600, 1030))
|
||||
screen.blit(stenki, (1800, 1030))
|
||||
|
||||
pygame.display.flip()
|
||||
clock.tick(FPS)
|
||||
|
||||
# Завершение работы Pygame
|
||||
pygame.quit()
|
||||
|
||||
# token: 8f195a885b18a96da6577884cc731f850f33a9e2
|
|
@ -0,0 +1,9 @@
|
|||
EXCEPTION NOTICE
|
||||
|
||||
1. As a special exception, the copyright holders of this library give permission for additional uses of the text contained in this release of the library as licenced under the wxWindows Library Licence, applying either version 3.1 of the Licence, or (at your option) any later version of the Licence as published by the copyright holders of version 3.1 of the Licence document.
|
||||
|
||||
2. The exception is that you may use, copy, link, modify and distribute under your own terms, binary object code versions of works based on the Library.
|
||||
|
||||
3. If you copy code from files distributed under the terms of the GNU General Public Licence or the GNU Library General Public Licence into a copy of this library, as this licence permits, the exception does not apply to the code that you add in this way. To avoid misleading anyone as to the status of such modified files, you must delete this exception notice from such code and/or adjust the licensing conditions notice accordingly.
|
||||
|
||||
4. If you write modifications of your own for this library, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, you must delete the exception notice from such code and/or adjust the licensing conditions notice accordingly.
|
|
@ -0,0 +1,3 @@
|
|||
# Pygame_Project
|
||||
|
||||
projekt igra 1, bla bla bla, tanckiki 2d
|
549
Tanki imbovie
|
@ -1,549 +0,0 @@
|
|||
import pygame
|
||||
import random
|
||||
import math
|
||||
|
||||
|
||||
# Определение констант
|
||||
SCREEN_WIDTH = 1920
|
||||
SCREEN_HEIGHT = 1080
|
||||
PLAYER_WIDTH = 100
|
||||
PLAYER_HEIGHT = 150
|
||||
LOH_WIDTH = 200
|
||||
LOH_HEIGHT = 150
|
||||
BULLET_SIZE = 20
|
||||
FPS = 60
|
||||
BULLET_SPEED = 6
|
||||
TANK_SPEED = 2
|
||||
BOT_SPEED = 2
|
||||
FIRE_DELAY = 1000 # Задержка между выстрелами в миллисекундах
|
||||
WHITE = (255, 255, 255)
|
||||
BLACK = (0, 0, 0)
|
||||
score = 0
|
||||
# Инициализация Pygame
|
||||
pygame.init()
|
||||
|
||||
# Создание игрового окна
|
||||
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags=pygame.FULLSCREEN)
|
||||
pygame.display.set_caption("Танчики")
|
||||
|
||||
# Загрузка и воспроизведение музыки
|
||||
pygame.mixer.music.load('music.mp3')
|
||||
pygame.mixer.music.play(-1) # Параметр -1 означает зацикливание музыки
|
||||
shot_sound = pygame.mixer.Sound('shot.wav')
|
||||
meme_sound = pygame.mixer.Sound("meme_sound.wav")
|
||||
explosion_sound = pygame.mixer.Sound("explosion_sound.wav")
|
||||
meme_sound = pygame.mixer.Sound("meme_sound.wav")
|
||||
stoneexplosion_sound = pygame.mixer.Sound("stoneexplosion_sound.wav")
|
||||
|
||||
# Загрузка изображений
|
||||
background_image = pygame.transform.scale(pygame.image.load("travka_pol.jpeg"), (960, 540))
|
||||
stena = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (100, 100))
|
||||
stenki = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (200, 200))
|
||||
tank_image = pygame.transform.scale(pygame.image.load("ntank-removebg-preview.png"), (PLAYER_WIDTH, PLAYER_HEIGHT))
|
||||
loh_image = pygame.transform.scale(pygame.image.load("loh.png"), (LOH_WIDTH, LOH_HEIGHT))
|
||||
bullet_image = pygame.transform.scale(pygame.image.load("bullet.png"), (BULLET_SIZE, BULLET_SIZE))
|
||||
explosion_images = [pygame.image.load(f"explosion_{i}.png") for i in range(1, 48)]
|
||||
stoneexplosion_images = [pygame.image.load(f"stoneexplosion_{i}.png") for i in range(1, 6)]
|
||||
|
||||
menu_background = pygame.transform.scale(pygame.image.load("menu_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
|
||||
|
||||
class Explosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.image = explosion_images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == 6:
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = explosion_images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Добавление класса для анимации удара о каменную стену
|
||||
class StoneExplosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.images = stoneexplosion_images
|
||||
self.image = self.images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
stoneexplosion_sound.play() # Воспроизведение звука удара о стену
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Определение класса танка
|
||||
class Tank(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = tank_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = -90 # Поворот на 90 градусов против часовой стрелки
|
||||
self.TANK_SPEED = 2
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.boosted = False # Флаг, показывающий, активирован ли ускоритель
|
||||
self.boost_multiplier = 2 # Множитель скорости ускорения
|
||||
|
||||
def update(self):
|
||||
keys = pygame.key.get_pressed()
|
||||
if keys[pygame.K_w]:
|
||||
self.move_forward()
|
||||
mouse_pos = pygame.mouse.get_pos()
|
||||
self.angle = math.degrees(math.atan2(mouse_pos[1] - self.rect.centery, mouse_pos[0] - self.rect.centerx)) + 90
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
if keys[pygame.K_x]:
|
||||
if not self.boosted:
|
||||
self.TANK_SPEED *= self.boost_multiplier
|
||||
self.boosted = True
|
||||
else:
|
||||
if self.boosted:
|
||||
self.TANK_SPEED /= self.boost_multiplier
|
||||
self.boosted = False
|
||||
|
||||
def move_forward(self):
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += self.TANK_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += self.TANK_SPEED * math.sin(angle_rad)
|
||||
|
||||
def shoot(self):
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_fire_time > FIRE_DELAY: # Проверка задержки между выстрелами
|
||||
shot_sound.play() # Воспроизведение звука выстрела
|
||||
# Коррекция угла вылета пули, чтобы она вылетала из дула танка
|
||||
offset_angle = -90 # Угол смещения для вылета пули из дула
|
||||
corrected_angle = self.angle + offset_angle
|
||||
|
||||
# Вычисляем координаты дула танка
|
||||
offset_x = 70 * math.cos(math.radians(corrected_angle))
|
||||
offset_y = 70 * math.sin(math.radians(corrected_angle))
|
||||
bullet = PlayerBullet(self.rect.centerx + offset_x, self.rect.centery + offset_y, self.angle + 270)
|
||||
all_sprites.add(bullet)
|
||||
bullets.add(bullet)
|
||||
self.last_fire_time = current_time # Обновление времени последнего выстрела
|
||||
|
||||
# Проверяем столкновение пули с каменными стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука столкновения с каменной стеной
|
||||
explosion = StoneExplosion(bullet.rect.centerx, bullet.rect.centery) # Создание анимации удара о стену
|
||||
all_sprites.add(explosion) # Добавление анимации удара о стену в группу спрайтов
|
||||
bullet.kill() # Удаление пули
|
||||
|
||||
class PlayerBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса снаряда бота
|
||||
class BotBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса для бота
|
||||
class Bot(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = loh_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = 0 # Угол поворота бота
|
||||
self.speed = BOT_SPEED # Скорость бота
|
||||
|
||||
def update(self):
|
||||
# Находим координаты игрока
|
||||
player_x, player_y = player.rect.center
|
||||
|
||||
# Вычисляем угол к игроку
|
||||
dx = player_x - self.rect.centerx
|
||||
dy = player_y - self.rect.centery
|
||||
self.angle = math.degrees(math.atan2(dy, dx)) + 90
|
||||
|
||||
# Поворачиваем изображение бота
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
# Двигаем бота в направлении игрока
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += self.speed * math.cos(angle_rad)
|
||||
self.rect.y += self.speed * math.sin(angle_rad)
|
||||
|
||||
# Проверяем, не выходит ли бот за границы экрана
|
||||
self.check_bounds()
|
||||
|
||||
def check_bounds(self):
|
||||
# Проверка выхода за границы экрана
|
||||
if self.rect.left < 0:
|
||||
self.rect.left = 0
|
||||
elif self.rect.right > SCREEN_WIDTH:
|
||||
self.rect.right = SCREEN_WIDTH
|
||||
if self.rect.top < 0:
|
||||
self.rect.top = 0
|
||||
elif self.rect.bottom > SCREEN_HEIGHT:
|
||||
self.rect.bottom = SCREEN_HEIGHT
|
||||
|
||||
def shoot_random(self):
|
||||
# Vыстрел в направлении дула
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_fire_time > random.randint(1000, 5000):
|
||||
bullet = BotBullet(self.rect.centerx, self.rect.centery, self.angle + 90) # Стрельба в направлении дула
|
||||
all_sprites.add(bullet)
|
||||
bullets.add(bullet)
|
||||
self.last_fire_time = current_time
|
||||
|
||||
|
||||
class Wall(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, image):
|
||||
super().__init__()
|
||||
self.image = image
|
||||
self.rect = self.image.get_rect(topleft=(x, y))
|
||||
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
walls = pygame.sprite.Group() # Группа для всех стен
|
||||
|
||||
# Создание стен
|
||||
wall_positions = [
|
||||
(360, 40), (460, 730), (460, 830), (460, 930),
|
||||
(960, 40), (960, 140), (960, 240),
|
||||
(660, 240),
|
||||
(960, 440), (960, 540), (960, 640), (960, 740),
|
||||
(1260, 740), (1360, 740), (1460, 740), (1560, 740), (1660, 740),
|
||||
(360, 240), (360, 340), (360, 440),
|
||||
(0, 540), (60, 540), (260, 540), (360, 540), (460, 540),
|
||||
(560, 540), (660, 540), (760, 540), (860, 540),
|
||||
(1160, 240), (1260, 240), (1360, 240), (1460, 240), (1460, 340),
|
||||
(1760, 340), (1860, 340)
|
||||
]
|
||||
|
||||
for pos in wall_positions:
|
||||
wall = Wall(*pos, stena)
|
||||
all_sprites.add(wall)
|
||||
walls.add(wall)
|
||||
|
||||
# Создание стен "stenki"
|
||||
wall_stenki_positions = [
|
||||
(-150, 0), (-150, 200), (-150, 400), (-150, 600), (-150, 800), (-150, 1000),
|
||||
(0, -150), (200, -150), (400, -150), (600, -150), (800, -150), (1000, -150),
|
||||
(1200, -150), (1400, -150), (1600, -150), (1800, -150), (1870, 0), (1870, 200),
|
||||
(1870, 400), (1870, 600), (1870, 800), (1870, 1000), (0, 1030), (200, 1030),
|
||||
(400, 1030), (600, 1030), (800, 1030), (1000, 1030), (1200, 1030), (1400, 1030),
|
||||
(1600, 1030), (1800, 1030)
|
||||
]
|
||||
|
||||
for pos in wall_stenki_positions:
|
||||
wall_stenki = Wall(*pos, stenki)
|
||||
all_sprites.add(wall_stenki)
|
||||
walls.add(wall_stenki)
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
|
||||
# Создание игрока
|
||||
player = Tank(SCREEN_WIDTH // 8, SCREEN_HEIGHT // 7)
|
||||
all_sprites.add(player)
|
||||
tanks.add(player)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
|
||||
def draw_menu():
|
||||
screen.blit(menu_background, (0, 0))
|
||||
font = pygame.font.Font(None, 50)
|
||||
|
||||
# Рисуем кнопку "Старт"
|
||||
start_text = font.render("Start", True, WHITE)
|
||||
start_rect = start_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 100))
|
||||
screen.blit(start_text, start_rect)
|
||||
|
||||
# Рисуем кнопку "Настройки"
|
||||
settings_text = font.render("Settings", True, WHITE)
|
||||
settings_rect = settings_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
|
||||
screen.blit(settings_text, settings_rect)
|
||||
|
||||
# Рисуем кнопку "Выйти"
|
||||
quit_text = font.render("Quit", True, WHITE)
|
||||
quit_rect = quit_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 100))
|
||||
screen.blit(quit_text, quit_rect)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
return start_rect, settings_rect, quit_rect
|
||||
|
||||
|
||||
def respawn_bot():
|
||||
# Создание нового экземпляра бота
|
||||
new_bot = Bot(random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
|
||||
all_sprites.add(new_bot)
|
||||
tanks.add(new_bot)
|
||||
|
||||
|
||||
last_meme_time = 0
|
||||
meme_delay = 2000 # Задержка в миллисекундах (2 секунды)
|
||||
|
||||
def draw_settings_menu():
|
||||
settings_background = pygame.transform.scale(pygame.image.load("settings_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
screen.blit(settings_background, (0, 0))
|
||||
font = pygame.font.Font(None, 50)
|
||||
|
||||
# Рисуем кнопку "Выйти" в правом верхнем углу
|
||||
quit_text = font.render("Quit", True, WHITE)
|
||||
quit_rect = quit_text.get_rect(topright=(SCREEN_WIDTH - 20, 20))
|
||||
screen.blit(quit_text, quit_rect)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
return quit_rect
|
||||
|
||||
last_meme_time = 0
|
||||
meme_delay = 2000 # Задержка в миллисекундах (2 секунды)
|
||||
|
||||
# Главный цикл программы
|
||||
menu_active = True
|
||||
settings_active = False # Флаг, показывающий, активно ли меню настроек
|
||||
while menu_active:
|
||||
if not settings_active:
|
||||
start_rect, settings_rect, quit_rect = draw_menu()
|
||||
else:
|
||||
quit_rect = draw_settings_menu()
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # Левая кнопка мыши
|
||||
if not settings_active:
|
||||
if start_rect.collidepoint(event.pos):
|
||||
menu_active = False # Нажата кнопка "Старт"
|
||||
elif settings_rect.collidepoint(event.pos):
|
||||
settings_active = True # Нажата кнопка "Настройки"
|
||||
elif quit_rect.collidepoint(event.pos):
|
||||
pygame.quit()
|
||||
quit()
|
||||
else:
|
||||
if quit_rect.collidepoint(event.pos):
|
||||
settings_active = False
|
||||
|
||||
# Основной игровой цикл
|
||||
clock = pygame.time.Clock()
|
||||
running = True
|
||||
paused = False # Track pause state
|
||||
|
||||
while running:
|
||||
|
||||
current_time = pygame.time.get_ticks()
|
||||
|
||||
# Handle events
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
|
||||
# Handle left mouse button click
|
||||
if not paused:
|
||||
player.shoot()
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_k:
|
||||
if current_time - last_meme_time > meme_delay: # Проверка задержки
|
||||
meme_sound.play()
|
||||
last_meme_time = current_time # Обновление времени последнего воспроизведения звука
|
||||
elif event.key == pygame.K_ESCAPE:
|
||||
# Toggle pause state when escape key is pressed
|
||||
paused = not paused
|
||||
|
||||
if not paused: # If not paused, update game state
|
||||
# Update sprites
|
||||
all_sprites.update()
|
||||
|
||||
# Проверка столкновений пуль с танками
|
||||
for bullet in bullets:
|
||||
if isinstance(bullet, PlayerBullet):
|
||||
tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
|
||||
if tank_hit and isinstance(tank_hit, Bot):
|
||||
explosion_sound.play() # Воспроизведение звука взрыва
|
||||
explosion = Explosion(tank_hit.rect.centerx, tank_hit.rect.centery) # Создание взрыва
|
||||
all_sprites.add(explosion) # Добавление взрыва в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю
|
||||
tank_hit.kill() # Удаляем бота
|
||||
respawn_bot() # Создаем нового бота
|
||||
score += 1
|
||||
|
||||
elif isinstance(bullet, BotBullet):
|
||||
# Проверяем столкновение пули бота с стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука взрыва камня
|
||||
explosion = Explosion(bullet.rect.centerx, bullet.rect.centery) # Создание взрыва камня
|
||||
all_sprites.add(explosion) # Добавление взрыва камня в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю бота
|
||||
|
||||
# Отрисовка фона
|
||||
for i in range(2):
|
||||
for j in range(2):
|
||||
screen.blit(background_image, (i * 960, j * 540))
|
||||
|
||||
all_sprites.draw(screen)
|
||||
screen.blit(stena, (360, 40))
|
||||
|
||||
screen.blit(stena, (460, 730))
|
||||
screen.blit(stena, (460, 830))
|
||||
screen.blit(stena, (460, 930))
|
||||
|
||||
screen.blit(stena, (960, 40))
|
||||
screen.blit(stena, (960, 140))
|
||||
screen.blit(stena, (960, 240))
|
||||
|
||||
screen.blit(stena, (660, 240))
|
||||
|
||||
screen.blit(stena, (960, 440))
|
||||
screen.blit(stena, (960, 540))
|
||||
screen.blit(stena, (960, 640))
|
||||
screen.blit(stena, (960, 740))
|
||||
|
||||
screen.blit(stena, (1260, 740))
|
||||
screen.blit(stena, (1360, 740))
|
||||
screen.blit(stena, (1460, 740))
|
||||
screen.blit(stena, (1560, 740))
|
||||
screen.blit(stena, (1660, 740))
|
||||
|
||||
screen.blit(stena, (360, 240))
|
||||
screen.blit(stena, (360, 340))
|
||||
screen.blit(stena, (360, 440))
|
||||
|
||||
screen.blit(stena, (0, 540))
|
||||
screen.blit(stena, (60, 540))
|
||||
screen.blit(stena, (260, 540))
|
||||
screen.blit(stena, (360, 540))
|
||||
screen.blit(stena, (460, 540))
|
||||
screen.blit(stena, (560, 540))
|
||||
screen.blit(stena, (660, 540))
|
||||
screen.blit(stena, (760, 540))
|
||||
screen.blit(stena, (860, 540))
|
||||
|
||||
screen.blit(stena, (1160, 240))
|
||||
screen.blit(stena, (1260, 240))
|
||||
screen.blit(stena, (1360, 240))
|
||||
screen.blit(stena, (1460, 240))
|
||||
screen.blit(stena, (1460, 340))
|
||||
screen.blit(stena, (1760, 340))
|
||||
screen.blit(stena, (1860, 340))
|
||||
|
||||
screen.blit(stenki, (-150, 0))
|
||||
screen.blit(stenki, (-150, 200))
|
||||
screen.blit(stenki, (-150, 400))
|
||||
screen.blit(stenki, (-150, 600))
|
||||
screen.blit(stenki, (-150, 800))
|
||||
screen.blit(stenki, (-150, 1000))
|
||||
screen.blit(stenki, (0, -150))
|
||||
screen.blit(stenki, (200, -150))
|
||||
screen.blit(stenki, (400, -150))
|
||||
screen.blit(stenki, (600, -150))
|
||||
screen.blit(stenki, (800, -150))
|
||||
screen.blit(stenki, (1000, -150))
|
||||
screen.blit(stenki, (1200, -150))
|
||||
screen.blit(stenki, (1400, -150))
|
||||
screen.blit(stenki, (1600, -150))
|
||||
screen.blit(stenki, (1800, -150))
|
||||
screen.blit(stenki, (1870, 0))
|
||||
screen.blit(stenki, (1870, 200))
|
||||
screen.blit(stenki, (1870, 400))
|
||||
screen.blit(stenki, (1870, 600))
|
||||
screen.blit(stenki, (1870, 800))
|
||||
screen.blit(stenki, (1870, 1000))
|
||||
screen.blit(stenki, (0, 1030))
|
||||
screen.blit(stenki, (200, 1030))
|
||||
screen.blit(stenki, (400, 1030))
|
||||
screen.blit(stenki, (600, 1030))
|
||||
screen.blit(stenki, (800, 1030))
|
||||
screen.blit(stenki, (1000, 1030))
|
||||
screen.blit(stenki, (1200, 1030))
|
||||
screen.blit(stenki, (1400, 1030))
|
||||
screen.blit(stenki, (1600, 1030))
|
||||
screen.blit(stenki, (1800, 1030))
|
||||
|
||||
font = pygame.font.Font(None, 36)
|
||||
score_text = font.render(f'Score: {score}', True, WHITE)
|
||||
screen.blit(score_text, (10, 10))
|
||||
score_rect = score_text.get_rect(topleft=(10, 10))
|
||||
pygame.draw.rect(screen, (0, 255, 0), (
|
||||
score_rect.topleft, (score_rect.width, score_rect.height))) # Draw a green rectangle behind the score
|
||||
screen.blit(score_text, score_rect.topleft)
|
||||
pygame.display.flip()
|
||||
clock.tick(FPS)
|
||||
|
||||
# Завершение работы Pygame
|
||||
pygame.quit()
|
182
about.html
|
@ -1,182 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>About Tanki 2D</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link rel="icon" href="https://cdn.discordapp.com/attachments/856238529502511144/1234217742689767424/free-icon-tank-942355.png?ex=662fee58&is=662e9cd8&hm=82b93f0803c76e54589ff9766815979b37ed52b2ac7ac88a05cd081040a33492&">
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #000; /* Черный цвет фона */
|
||||
color: #fff; /* Белый цвет текста */
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
margin-top: 80px; /* Отступ для контента под фиксированной шапкой */
|
||||
overflow-y: auto; /* Включаем вертикальную прокрутку */
|
||||
}
|
||||
|
||||
nav {
|
||||
position: fixed; /* Фиксированная позиция */
|
||||
top: 0; /* Расположение шапки вверху */
|
||||
left: 0; /* Расположение шапки слева */
|
||||
width: 100%; /* Занимает всю ширину экрана */
|
||||
background-color: #333;
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
z-index: 999; /* Чтобы шапка была выше других элементов */
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 100px; /* Устанавливаем ширину логотипа */
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
nav ul li a:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px #748623;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
margin-top: 80px;
|
||||
position: relative;
|
||||
background-color: #222; /* Серый фон */
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #748623;
|
||||
text-align: center; /* Add this line */
|
||||
}
|
||||
|
||||
|
||||
p {
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
margin-top: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.images-container {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.image {
|
||||
width: 45%;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px #748623;
|
||||
}
|
||||
|
||||
/* Стили для области оценки */
|
||||
#ratings {
|
||||
padding-top: 50px; /* Добавляем отступ сверху, чтобы область оценки была выше */
|
||||
text-align: center; /* Центрируем содержимое */
|
||||
}
|
||||
|
||||
#ratings input {
|
||||
width: 50px; /* Устанавливаем ширину поля ввода */
|
||||
margin: 10px; /* Добавляем отступы между элементами */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<div class="logo" onclick="location.href='/'">
|
||||
<img src="https://cdn.discordapp.com/attachments/704651653873139803/1233880220004519986/Screenshot_2024-04-27_233856-removebg-preview.png?ex=662eb400&is=662d6280&hm=518bf12af052c5268492e81d64f8957eea1d6163b3c8fe28c3e8a69758169263&" alt="Tanki Logo">
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/game">Game</a></li>
|
||||
<li><a href="/support">Support</a></li>
|
||||
<li><a href="/updates">Updates</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<h1>About Tanki 2D</h1>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p>Welcome to the world of Tanks 2D, an exciting single-player game in which you take command of a formidable tank and set out to conquer enemy territory.</p>
|
||||
<p>Embark on an epic single-player campaign filled with exciting missions and challenges.</p>
|
||||
<p>Customize your tank with a wide range of weapons, armor and upgrades to enhance your combat capabilities. Engage in adrenaline-pumping battles against enemy forces and bosses, using strategic tactics and your tank's unique abilities to overcome obstacles and emerge victorious.</p>
|
||||
<p>With addictive gameplay and stunning graphics, Tanki 2D offers an immersive gaming experience that will keep you hooked for hours. Get ready to go on an epic journey and become the best commander in Tanki 2D!</p>
|
||||
<div class="images-container">
|
||||
<img class="image" src="https://cdn.discordapp.com/attachments/856238529502511144/1234087135787618377/image.png?ex=662f74b5&is=662e2335&hm=ce9367095cc02d2236475fe2c7b6f8f958fe3e8b6547d727fce3e76126cfeb8a&" alt="Left Image">
|
||||
<img class="image" src="https://cdn.discordapp.com/attachments/856238529502511144/1234087242314813500/image.png?ex=662f74ce&is=662e234e&hm=5a7c75a04a0959a718b2a401bf74026a3f204e25639106d886d0dcb4759bfebf&" alt="Right Image">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Область для оценки -->
|
||||
<div id="ratings" class="container" style="margin-top: 1000px;"> <!-- Установите высоту в px в зависимости от контента выше -->
|
||||
<h2>Rate Our Website and Game</h2>
|
||||
<p>Please rate our website and game from 1 to 5 stars:</p>
|
||||
<div>
|
||||
<label for="websiteRating">Website:</label>
|
||||
<input type="number" id="websiteRating" name="websiteRating" min="1" max="5">
|
||||
</div>
|
||||
<div>
|
||||
<label for="gameRating">Game:</label>
|
||||
<input type="number" id="gameRating" name="gameRating" min="1" max="5">
|
||||
</div>
|
||||
<button onclick="submitRatings()">Submit Ratings</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Функция для отправки оценок
|
||||
function submitRatings() {
|
||||
var websiteRating = document.getElementById("websiteRating").value;
|
||||
var gameRating = document.getElementById("gameRating").value;
|
||||
|
||||
alert("Thank you for your ratings! \nFrom: Arsenij, Artem and Roman. :) \nWebsite: " + websiteRating + " stars\nGame: " + gameRating + " stars");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
27
app.py
|
@ -1,27 +0,0 @@
|
|||
from flask import Flask, render_template
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/index")
|
||||
@app.route("/")
|
||||
def index():
|
||||
return render_template('index.html')
|
||||
|
||||
@app.route("/about")
|
||||
def about():
|
||||
return render_template('about.html')
|
||||
|
||||
@app.route("/game")
|
||||
def game():
|
||||
return render_template('game.html')
|
||||
|
||||
@app.route("/support")
|
||||
def support():
|
||||
return render_template('support.html')
|
||||
|
||||
@app.route("/updates")
|
||||
def updates():
|
||||
return render_template('updates.html')
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
631
bla.py
|
@ -1,631 +0,0 @@
|
|||
import pygame
|
||||
import random
|
||||
import math
|
||||
|
||||
from main import current_time
|
||||
|
||||
# Определение констант
|
||||
SCREEN_WIDTH = 1920
|
||||
SCREEN_HEIGHT = 1080
|
||||
PLAYER_WIDTH = 90
|
||||
PLAYER_HEIGHT = 135
|
||||
LOH_WIDTH = 150
|
||||
LOH_HEIGHT = 100
|
||||
BULLET_SIZE = 20
|
||||
FPS = 60
|
||||
BULLET_SPEED = 6
|
||||
TANK_SPEED = 2
|
||||
BOT_SPEED = 2
|
||||
FIRE_DELAY = 1000 # Задержка между выстрелами в миллисекундах
|
||||
WHITE = (255, 255, 255)
|
||||
BLACK = (0, 0, 0)
|
||||
score = 0
|
||||
# Инициализация Pygame
|
||||
pygame.init()
|
||||
|
||||
# Создание игрового окна
|
||||
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags=pygame.FULLSCREEN)
|
||||
pygame.display.set_caption("Танчики")
|
||||
|
||||
|
||||
# Загрузка и воспроизведение музыки
|
||||
pygame.mixer.music.load('music.mp3')
|
||||
pygame.mixer.music.play(-1) # Параметр -1 означает зацикливание музыки
|
||||
shot_sound = pygame.mixer.Sound('shot.wav')
|
||||
meme_sound = pygame.mixer.Sound("meme_sound.wav")
|
||||
explosion_sound = pygame.mixer.Sound("explosion_sound.wav")
|
||||
stoneexplosion_sound = pygame.mixer.Sound("stoneexplosion_sound.wav")
|
||||
|
||||
# Загрузка изображений
|
||||
background_image = pygame.transform.scale(pygame.image.load("travka_pol.jpeg"), (960, 540))
|
||||
stena = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (100, 100))
|
||||
stenki = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (200, 200))
|
||||
tank_image = pygame.transform.scale(pygame.image.load("ntank-removebg-preview.png"), (PLAYER_WIDTH, PLAYER_HEIGHT))
|
||||
loh_image = pygame.transform.scale(pygame.image.load("loh.png"), (LOH_WIDTH, LOH_HEIGHT))
|
||||
bullet_image = pygame.transform.scale(pygame.image.load("bullet.png"), (BULLET_SIZE, BULLET_SIZE))
|
||||
explosion_images = [pygame.image.load(f"explosion_{i}.png") for i in range(1, 48)]
|
||||
stoneexplosion_images = [pygame.image.load(f"stoneexplosion_{i}.png") for i in range(1, 6)]
|
||||
menu_background = pygame.transform.scale(pygame.image.load("menu_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
|
||||
cursor = pygame.image.load("cursor.png")
|
||||
pygame.mouse.set_visible(False)
|
||||
|
||||
cursor_offset_x = cursor.get_width() // 2
|
||||
cursor_offset_y = cursor.get_height() // 2
|
||||
|
||||
paused_menu_active = False
|
||||
|
||||
class Explosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.image = explosion_images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == 6:
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = explosion_images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Добавление класса для анимации удара о каменную стену
|
||||
class StoneExplosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.images = stoneexplosion_images
|
||||
self.image = self.images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
stoneexplosion_sound.play() # Воспроизведение звука удара о стену
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Определение класса танка
|
||||
class Tank(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = tank_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = -90 # Поворот на 90 градусов против часовой стрелки
|
||||
self.TANK_SPEED = 2
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.boosted = False # Флаг, показывающий, активирован ли ускоритель
|
||||
self.boost_multiplier = 2 # Множитель скорости ускорения
|
||||
|
||||
def update(self):
|
||||
keys = pygame.key.get_pressed()
|
||||
if keys[pygame.K_w]:
|
||||
self.move_forward()
|
||||
mouse_pos = pygame.mouse.get_pos()
|
||||
self.angle = math.degrees(math.atan2(mouse_pos[1] - self.rect.centery, mouse_pos[0] - self.rect.centerx)) + 90
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
if keys[pygame.K_x]:
|
||||
if not self.boosted:
|
||||
self.TANK_SPEED *= self.boost_multiplier
|
||||
self.boosted = True
|
||||
else:
|
||||
if self.boosted:
|
||||
self.TANK_SPEED /= self.boost_multiplier
|
||||
self.boosted = False
|
||||
|
||||
def move_forward(self):
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += self.TANK_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += self.TANK_SPEED * math.sin(angle_rad)
|
||||
|
||||
def shoot(self):
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_fire_time > FIRE_DELAY: # Проверка задержки между выстрелами
|
||||
shot_sound.play() # Воспроизведение звука выстрела
|
||||
# Коррекция угла вылета пули, чтобы она вылетала из дула танка
|
||||
offset_angle = -90 # Угол смещения для вылета пули из дула
|
||||
corrected_angle = self.angle + offset_angle
|
||||
|
||||
# Вычисляем координаты дула танка
|
||||
offset_x = 70 * math.cos(math.radians(corrected_angle))
|
||||
offset_y = 70 * math.sin(math.radians(corrected_angle))
|
||||
bullet = PlayerBullet(self.rect.centerx + offset_x, self.rect.centery + offset_y, self.angle + 270)
|
||||
all_sprites.add(bullet)
|
||||
bullets.add(bullet)
|
||||
self.last_fire_time = current_time # Обновление времени последнего выстрела
|
||||
|
||||
# Проверяем столкновение пули с каменными стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука столкновения с каменной стеной
|
||||
explosion = StoneExplosion(bullet.rect.centerx, bullet.rect.centery) # Создание анимации удара о стену
|
||||
all_sprites.add(explosion) # Добавление анимации удара о стену в группу спрайтов
|
||||
bullet.kill() # Удаление пули
|
||||
|
||||
class PlayerBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса снаряда бота
|
||||
class BotBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса для бота
|
||||
class Bot(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = loh_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = 0 # Угол поворота бота
|
||||
self.speed = BOT_SPEED # Скорость бота
|
||||
|
||||
def update(self):
|
||||
# Находим координаты игрока
|
||||
player_x, player_y = player.rect.center
|
||||
|
||||
# Вычисляем угол к игроку
|
||||
dx = player_x - self.rect.centerx
|
||||
dy = player_y - self.rect.centery
|
||||
self.angle = math.degrees(math.atan2(dy, dx)) + 90
|
||||
|
||||
# Поворачиваем изображение бота
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
# Двигаем бота в направлении игрока
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += self.speed * math.cos(angle_rad)
|
||||
self.rect.y += self.speed * math.sin(angle_rad)
|
||||
|
||||
# Проверяем, не выходит ли бот за границы экрана
|
||||
self.check_bounds()
|
||||
|
||||
# Проверяем столкновения с другими ботами
|
||||
self.check_bot_collisions()
|
||||
|
||||
def check_bounds(self):
|
||||
# Проверка выхода за границы экрана
|
||||
if self.rect.left < 0:
|
||||
self.rect.left = 0
|
||||
elif self.rect.right > SCREEN_WIDTH:
|
||||
self.rect.right = SCREEN_WIDTH
|
||||
if self.rect.top < 0:
|
||||
self.rect.top = 0
|
||||
elif self.rect.bottom > SCREEN_HEIGHT:
|
||||
self.rect.bottom = SCREEN_HEIGHT
|
||||
|
||||
def check_bot_collisions(self):
|
||||
# Проверяем столкновения с другими ботами
|
||||
for bot in tanks:
|
||||
if bot != self:
|
||||
# Проверяем расстояние между ботами
|
||||
distance = math.sqrt(
|
||||
(self.rect.centerx - bot.rect.centerx) ** 2 + (self.rect.centery - bot.rect.centery) ** 2)
|
||||
min_distance = 100 # Минимальное допустимое расстояние между ботами
|
||||
if distance < min_distance:
|
||||
# Если боты слишком близко, переместим текущий бот подальше от другого бота
|
||||
dx = self.rect.centerx - bot.rect.centerx
|
||||
dy = self.rect.centery - bot.rect.centery
|
||||
self.rect.x += dx / distance * min_distance / 2
|
||||
self.rect.y += dy / distance * min_distance / 2
|
||||
|
||||
|
||||
|
||||
class Wall(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, image):
|
||||
super().__init__()
|
||||
self.image = image
|
||||
self.rect = self.image.get_rect(topleft=(x, y))
|
||||
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
walls = pygame.sprite.Group() # Группа для всех стен
|
||||
|
||||
# Создание стен
|
||||
wall_positions = [
|
||||
(360, 40), (460, 730), (460, 830), (460, 930),
|
||||
(960, 40), (960, 140), (960, 240),
|
||||
(660, 240),
|
||||
(960, 440), (960, 540), (960, 640), (960, 740),
|
||||
(1260, 740), (1360, 740), (1460, 740), (1560, 740), (1660, 740),
|
||||
(360, 240), (360, 340), (360, 440),
|
||||
(0, 540), (60, 540), (260, 540), (360, 540), (460, 540),
|
||||
(560, 540), (660, 540), (760, 540), (860, 540),
|
||||
(1160, 240), (1260, 240), (1360, 240), (1460, 240), (1460, 340),
|
||||
(1760, 340), (1860, 340)
|
||||
]
|
||||
|
||||
for pos in wall_positions:
|
||||
wall = Wall(*pos, stena)
|
||||
all_sprites.add(wall)
|
||||
walls.add(wall)
|
||||
|
||||
# Создание стен "stenki"
|
||||
wall_stenki_positions = [
|
||||
(-150, 0), (-150, 200), (-150, 400), (-150, 600), (-150, 800), (-150, 1000),
|
||||
(0, -150), (200, -150), (400, -150), (600, -150), (800, -150), (1000, -150),
|
||||
(1200, -150), (1400, -150), (1600, -150), (1800, -150), (1870, 0), (1870, 200),
|
||||
(1870, 400), (1870, 600), (1870, 800), (1870, 1000), (0, 1030), (200, 1030),
|
||||
(400, 1030), (600, 1030), (800, 1030), (1000, 1030), (1200, 1030), (1400, 1030),
|
||||
(1600, 1030), (1800, 1030)
|
||||
]
|
||||
|
||||
for pos in wall_stenki_positions:
|
||||
wall_stenki = Wall(*pos, stenki)
|
||||
all_sprites.add(wall_stenki)
|
||||
walls.add(wall_stenki)
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
|
||||
# Создание игрока
|
||||
player = Tank(SCREEN_WIDTH // 8, SCREEN_HEIGHT // 7)
|
||||
all_sprites.add(player)
|
||||
tanks.add(player)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
|
||||
def draw_menu():
|
||||
screen.blit(menu_background, (0, 0))
|
||||
font = pygame.font.Font(None, 50)
|
||||
|
||||
# Рисуем кнопку "Старт"
|
||||
start_text = font.render("Start", True, WHITE)
|
||||
start_rect = start_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 100))
|
||||
screen.blit(start_text, start_rect)
|
||||
|
||||
# Рисуем кнопку "Настройки"
|
||||
settings_text = font.render("Settings", True, WHITE)
|
||||
settings_rect = settings_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
|
||||
screen.blit(settings_text, settings_rect)
|
||||
|
||||
# Рисуем кнопку "Выйти"
|
||||
quit_text = font.render("Quit", True, WHITE)
|
||||
quit_rect = quit_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 100))
|
||||
screen.blit(quit_text, quit_rect)
|
||||
|
||||
x, y = pygame.mouse.get_pos()
|
||||
screen.blit(cursor, (x - cursor_offset_x, y - cursor_offset_y))
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
return start_rect, settings_rect, quit_rect
|
||||
|
||||
|
||||
def respawn_bot():
|
||||
# Создание нового экземпляра бота
|
||||
new_bot = Bot(random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
|
||||
all_sprites.add(new_bot)
|
||||
tanks.add(new_bot)
|
||||
|
||||
|
||||
last_meme_time = 0
|
||||
meme_delay = 2000 # Задержка в миллисекундах (2 секунды)
|
||||
|
||||
def draw_settings_menu():
|
||||
settings_background = pygame.transform.scale(pygame.image.load("settings_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
screen.blit(settings_background, (0, 0))
|
||||
font = pygame.font.Font(None, 50)
|
||||
|
||||
# Рисуем кнопку "Выйти" в правом верхнем углу
|
||||
quit_text = font.render("Quit", True, WHITE)
|
||||
quit_rect = quit_text.get_rect(topright=(SCREEN_WIDTH - 20, 20))
|
||||
screen.blit(quit_text, quit_rect)
|
||||
|
||||
# Рисуем кнопку для управления музыкой
|
||||
if pygame.mixer.music.get_busy():
|
||||
music_text = font.render("Music On", True, WHITE)
|
||||
else:
|
||||
music_text = font.render("Music Off", True, WHITE)
|
||||
music_rect = music_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 100))
|
||||
screen.blit(music_text, music_rect)
|
||||
|
||||
x, y = pygame.mouse.get_pos()
|
||||
screen.blit(cursor, (x - cursor_offset_x, y - cursor_offset_y))
|
||||
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
return quit_rect, music_rect
|
||||
|
||||
|
||||
|
||||
# Главный цикл программы
|
||||
menu_active = True
|
||||
settings_active = False # Флаг, показывающий, активно ли меню настроек
|
||||
|
||||
while menu_active:
|
||||
if not settings_active:
|
||||
start_rect, settings_rect, quit_rect = draw_menu()
|
||||
else:
|
||||
quit_rect, music_rect = draw_settings_menu()
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # Левая кнопка мыши
|
||||
if not settings_active:
|
||||
if start_rect.collidepoint(event.pos):
|
||||
menu_active = False # Нажата кнопка "Старт"
|
||||
elif settings_rect.collidepoint(event.pos):
|
||||
settings_active = True # Нажата кнопка "Настройки"
|
||||
elif quit_rect.collidepoint(event.pos):
|
||||
pygame.quit()
|
||||
quit()
|
||||
else:
|
||||
if quit_rect.collidepoint(event.pos):
|
||||
settings_active = False
|
||||
elif music_rect.collidepoint(event.pos):
|
||||
if pygame.mixer.music.get_busy():
|
||||
pygame.mixer.music.stop() # Выключение музыки
|
||||
else:
|
||||
pygame.mixer.music.play(-1) # Включение музыки
|
||||
|
||||
|
||||
# Основной игровой цикл
|
||||
clock = pygame.time.Clock()
|
||||
running = True
|
||||
paused = False # Track pause state
|
||||
while running:
|
||||
|
||||
if menu_active: # If in menu, return to menu loop
|
||||
while menu_active:
|
||||
start_rect, settings_rect, quit_rect = draw_menu()
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # Left mouse button
|
||||
if start_rect.collidepoint(event.pos):
|
||||
menu_active = False # Start button clicked
|
||||
elif settings_rect.collidepoint(event.pos):
|
||||
settings_active = True # Settings button clicked
|
||||
menu_active = False # Return to menu loop
|
||||
elif quit_rect.collidepoint(event.pos):
|
||||
pygame.quit()
|
||||
quit()
|
||||
pygame.display.flip() # Update the display
|
||||
clock.tick(FPS) #
|
||||
# Handle events
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
|
||||
# Handle left mouse button click
|
||||
if not paused:
|
||||
player.shoot()
|
||||
elif event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_k:
|
||||
# Handle 'k' key press for meme sound
|
||||
if current_time - last_meme_time > meme_delay:
|
||||
meme_sound.play()
|
||||
last_meme_time = current_time
|
||||
elif event.key == pygame.K_ESCAPE:
|
||||
# Toggle pause state when escape key is pressed
|
||||
paused = not paused
|
||||
elif event.key == pygame.K_SPACE:
|
||||
# Return to menu when space key is pressed
|
||||
menu_active = True
|
||||
settings_active = False # Reset settings_active when returning to menu
|
||||
|
||||
|
||||
if settings_active: # If in settings, return to settings loop
|
||||
while settings_active:
|
||||
quit_rect, music_rect = draw_settings_menu()
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # Left mouse button
|
||||
if quit_rect.collidepoint(event.pos):
|
||||
menu_active = True # Set menu_active to True to return to menu
|
||||
settings_active = False # Quit button clicked
|
||||
draw_menu() # Redraw the menu to prevent flickering
|
||||
elif music_rect.collidepoint(event.pos):
|
||||
if pygame.mixer.music.get_busy():
|
||||
pygame.mixer.music.stop() # Turn off music
|
||||
else:
|
||||
pygame.mixer.music.play(-1) # Turn on music
|
||||
pygame.display.flip() # Update the display
|
||||
clock.tick(FPS) # Limit the frame rate
|
||||
|
||||
|
||||
elif not paused: # If not in menu and not paused, update game state
|
||||
# Update sprites
|
||||
all_sprites.update()
|
||||
|
||||
|
||||
|
||||
# Проверка столкновений пуль с танками
|
||||
for bullet in bullets:
|
||||
if isinstance(bullet, PlayerBullet):
|
||||
tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
|
||||
if tank_hit and isinstance(tank_hit, Bot):
|
||||
explosion_sound.play() # Воспроизведение звука взрыва
|
||||
explosion = Explosion(tank_hit.rect.centerx, tank_hit.rect.centery) # Создание взрыва
|
||||
all_sprites.add(explosion) # Добавление взрыва в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю
|
||||
tank_hit.kill() # Удаляем бота
|
||||
respawn_bot() # Создаем нового бота
|
||||
score += 1
|
||||
|
||||
elif isinstance(bullet, BotBullet):
|
||||
# Проверяем столкновение пули бота с стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука взрыва камня
|
||||
explosion = Explosion(bullet.rect.centerx, bullet.rect.centery) # Создание взрыва камня
|
||||
all_sprites.add(explosion) # Добавление взрыва камня в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю бота
|
||||
|
||||
# Отрисовка фона
|
||||
for i in range(2):
|
||||
for j in range(2):
|
||||
screen.blit(background_image, (i * 960, j * 540))
|
||||
|
||||
all_sprites.draw(screen)
|
||||
screen.blit(stena, (360, 40))
|
||||
|
||||
screen.blit(stena, (460, 730))
|
||||
screen.blit(stena, (460, 830))
|
||||
screen.blit(stena, (460, 930))
|
||||
|
||||
screen.blit(stena, (960, 40))
|
||||
screen.blit(stena, (960, 140))
|
||||
screen.blit(stena, (960, 240))
|
||||
|
||||
screen.blit(stena, (660, 240))
|
||||
|
||||
screen.blit(stena, (960, 440))
|
||||
screen.blit(stena, (960, 540))
|
||||
screen.blit(stena, (960, 640))
|
||||
screen.blit(stena, (960, 740))
|
||||
|
||||
screen.blit(stena, (1260, 740))
|
||||
screen.blit(stena, (1360, 740))
|
||||
screen.blit(stena, (1460, 740))
|
||||
screen.blit(stena, (1560, 740))
|
||||
screen.blit(stena, (1660, 740))
|
||||
|
||||
screen.blit(stena, (360, 240))
|
||||
screen.blit(stena, (360, 340))
|
||||
screen.blit(stena, (360, 440))
|
||||
|
||||
screen.blit(stena, (0, 540))
|
||||
screen.blit(stena, (60, 540))
|
||||
screen.blit(stena, (260, 540))
|
||||
screen.blit(stena, (360, 540))
|
||||
screen.blit(stena, (460, 540))
|
||||
screen.blit(stena, (560, 540))
|
||||
screen.blit(stena, (660, 540))
|
||||
screen.blit(stena, (760, 540))
|
||||
screen.blit(stena, (860, 540))
|
||||
|
||||
screen.blit(stena, (1160, 240))
|
||||
screen.blit(stena, (1260, 240))
|
||||
screen.blit(stena, (1360, 240))
|
||||
screen.blit(stena, (1460, 240))
|
||||
screen.blit(stena, (1460, 340))
|
||||
screen.blit(stena, (1760, 340))
|
||||
screen.blit(stena, (1860, 340))
|
||||
|
||||
screen.blit(stenki, (-150, 0))
|
||||
screen.blit(stenki, (-150, 200))
|
||||
screen.blit(stenki, (-150, 400))
|
||||
screen.blit(stenki, (-150, 600))
|
||||
screen.blit(stenki, (-150, 800))
|
||||
screen.blit(stenki, (-150, 1000))
|
||||
screen.blit(stenki, (0, -150))
|
||||
screen.blit(stenki, (200, -150))
|
||||
screen.blit(stenki, (400, -150))
|
||||
screen.blit(stenki, (600, -150))
|
||||
screen.blit(stenki, (800, -150))
|
||||
screen.blit(stenki, (1000, -150))
|
||||
screen.blit(stenki, (1200, -150))
|
||||
screen.blit(stenki, (1400, -150))
|
||||
screen.blit(stenki, (1600, -150))
|
||||
screen.blit(stenki, (1800, -150))
|
||||
screen.blit(stenki, (1870, 0))
|
||||
screen.blit(stenki, (1870, 200))
|
||||
screen.blit(stenki, (1870, 400))
|
||||
screen.blit(stenki, (1870, 600))
|
||||
screen.blit(stenki, (1870, 800))
|
||||
screen.blit(stenki, (1870, 1000))
|
||||
screen.blit(stenki, (0, 1030))
|
||||
screen.blit(stenki, (200, 1030))
|
||||
screen.blit(stenki, (400, 1030))
|
||||
screen.blit(stenki, (600, 1030))
|
||||
screen.blit(stenki, (800, 1030))
|
||||
screen.blit(stenki, (1000, 1030))
|
||||
screen.blit(stenki, (1200, 1030))
|
||||
screen.blit(stenki, (1400, 1030))
|
||||
screen.blit(stenki, (1600, 1030))
|
||||
screen.blit(stenki, (1800, 1030))
|
||||
|
||||
font = pygame.font.Font(None, 36)
|
||||
score_text = font.render(f'Score: {score}', True, WHITE)
|
||||
screen.blit(score_text, (10, 10))
|
||||
score_rect = score_text.get_rect(topleft=(10, 10))
|
||||
pygame.draw.rect(screen, (0, 255, 0), (
|
||||
score_rect.topleft, (score_rect.width, score_rect.height))) # Draw a green rectangle behind the score
|
||||
screen.blit(score_text, score_rect.topleft)
|
||||
|
||||
x, y = pygame.mouse.get_pos()
|
||||
screen.blit(cursor, (x - cursor_offset_x, y - cursor_offset_y))
|
||||
|
||||
pygame.display.flip()
|
||||
clock.tick(FPS)
|
||||
|
||||
# Завершение работы Pygame
|
||||
pygame.quit()
|
BIN
bullet.png
Before Width: | Height: | Size: 40 KiB |
BIN
cursor.png
Before Width: | Height: | Size: 2.6 KiB |
BIN
explosion_1.png
Before Width: | Height: | Size: 16 KiB |
BIN
explosion_10.png
Before Width: | Height: | Size: 53 KiB |
BIN
explosion_11.png
Before Width: | Height: | Size: 76 KiB |
BIN
explosion_12.png
Before Width: | Height: | Size: 61 KiB |
BIN
explosion_13.png
Before Width: | Height: | Size: 64 KiB |
BIN
explosion_14.png
Before Width: | Height: | Size: 68 KiB |
BIN
explosion_15.png
Before Width: | Height: | Size: 70 KiB |
BIN
explosion_16.png
Before Width: | Height: | Size: 71 KiB |
BIN
explosion_17.png
Before Width: | Height: | Size: 72 KiB |
BIN
explosion_18.png
Before Width: | Height: | Size: 75 KiB |
BIN
explosion_19.png
Before Width: | Height: | Size: 75 KiB |
BIN
explosion_2.png
Before Width: | Height: | Size: 24 KiB |
BIN
explosion_20.png
Before Width: | Height: | Size: 78 KiB |
BIN
explosion_21.png
Before Width: | Height: | Size: 81 KiB |
BIN
explosion_22.png
Before Width: | Height: | Size: 87 KiB |
BIN
explosion_23.png
Before Width: | Height: | Size: 84 KiB |
BIN
explosion_24.png
Before Width: | Height: | Size: 96 KiB |
BIN
explosion_25.png
Before Width: | Height: | Size: 93 KiB |
BIN
explosion_26.png
Before Width: | Height: | Size: 89 KiB |
BIN
explosion_27.png
Before Width: | Height: | Size: 100 KiB |
BIN
explosion_28.png
Before Width: | Height: | Size: 94 KiB |
BIN
explosion_29.png
Before Width: | Height: | Size: 97 KiB |
BIN
explosion_3.png
Before Width: | Height: | Size: 32 KiB |
BIN
explosion_30.png
Before Width: | Height: | Size: 91 KiB |
BIN
explosion_31.png
Before Width: | Height: | Size: 102 KiB |
BIN
explosion_32.png
Before Width: | Height: | Size: 97 KiB |
BIN
explosion_33.png
Before Width: | Height: | Size: 102 KiB |
BIN
explosion_34.png
Before Width: | Height: | Size: 96 KiB |
BIN
explosion_35.png
Before Width: | Height: | Size: 96 KiB |
BIN
explosion_36.png
Before Width: | Height: | Size: 98 KiB |
BIN
explosion_37.png
Before Width: | Height: | Size: 95 KiB |
BIN
explosion_38.png
Before Width: | Height: | Size: 93 KiB |
BIN
explosion_39.png
Before Width: | Height: | Size: 80 KiB |
BIN
explosion_4.png
Before Width: | Height: | Size: 36 KiB |
BIN
explosion_40.png
Before Width: | Height: | Size: 74 KiB |
BIN
explosion_41.png
Before Width: | Height: | Size: 79 KiB |
BIN
explosion_42.png
Before Width: | Height: | Size: 74 KiB |
BIN
explosion_43.png
Before Width: | Height: | Size: 58 KiB |
BIN
explosion_44.png
Before Width: | Height: | Size: 60 KiB |
BIN
explosion_45.png
Before Width: | Height: | Size: 39 KiB |
BIN
explosion_46.png
Before Width: | Height: | Size: 26 KiB |
BIN
explosion_47.png
Before Width: | Height: | Size: 14 KiB |
BIN
explosion_5.png
Before Width: | Height: | Size: 40 KiB |
BIN
explosion_6.png
Before Width: | Height: | Size: 41 KiB |
BIN
explosion_7.png
Before Width: | Height: | Size: 43 KiB |
BIN
explosion_8.png
Before Width: | Height: | Size: 49 KiB |
BIN
explosion_9.png
Before Width: | Height: | Size: 49 KiB |
172
game.html
|
@ -1,172 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Game - Tanks 2D</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link rel="icon" href="https://cdn.discordapp.com/attachments/856238529502511144/1234217742689767424/free-icon-tank-942355.png?ex=662fee58&is=662e9cd8&hm=82b93f0803c76e54589ff9766815979b37ed52b2ac7ac88a05cd081040a33492&">
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #000; /* Черный цвет фона */
|
||||
color: #fff; /* Белый цвет текста */
|
||||
}
|
||||
|
||||
nav {
|
||||
position: fixed; /* Фиксированная позиция */
|
||||
top: 0; /* Расположение шапки вверху */
|
||||
left: 0; /* Расположение шапки слева */
|
||||
width: 100%; /* Занимает всю ширину экрана */
|
||||
background-color: #333;
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
z-index: 999; /* Чтобы шапка была выше других элементов */
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 100px; /* Устанавливаем ширину логотипа */
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
nav ul li a:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
background-color: #222; /* Цвет фона контейнера */
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px #748623; /* Тень контейнера */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #748623; /* Цвет заголовка */
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.advertisement {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.advertisement img {
|
||||
max-width: 100%;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(255, 255, 255, 0.1); /* Тень изображения */
|
||||
}
|
||||
|
||||
/* Стили для области оценки */
|
||||
#ratings {
|
||||
padding-top: 50px; /* Добавляем отступ сверху, чтобы область оценки была выше */
|
||||
padding-bottom: 50px; /* Добавляем отступ снизу */
|
||||
text-align: center; /* Центрируем содержимое */
|
||||
}
|
||||
|
||||
#ratings input {
|
||||
width: 50px; /* Устанавливаем ширину поля ввода */
|
||||
margin: 10px; /* Добавляем отступы между элементами */
|
||||
}
|
||||
|
||||
/* Стили для QR-кода */
|
||||
#qr-code {
|
||||
width: 150px; /* Задаем ширину */
|
||||
height: 150px; /* Задаем высоту */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<div class="logo">
|
||||
<a href="/"><img src="https://cdn.discordapp.com/attachments/704651653873139803/1233880220004519986/Screenshot_2024-04-27_233856-removebg-preview.png?ex=662eb400&is=662d6280&hm=518bf12af052c5268492e81d64f8957eea1d6163b3c8fe28c3e8a69758169263&" alt="Tanki Logo"></a>
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/game">Game</a></li>
|
||||
<li><a href="/support">Support</a></li>
|
||||
<li><a href="/updates">Updates</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<h1>Tanks 2D</h1>
|
||||
<img src="https://cdn.discordapp.com/attachments/856238529502511144/1234090991045312543/image.png?ex=662f784c&is=662e26cc&hm=065a8314fa2f80d3f78d86beccbd81b4c1471065feba35a0dd0342d43376cfc7&" alt="Tanks 2D Screenshot">
|
||||
|
||||
<p>
|
||||
Tanks 2D is a fast-paced game where you control a tank and fight other tanks in harsh environments.
|
||||
The game features one unique tank, unique weapons and challenging obstacles.
|
||||
As you progress, the number of enemies in the location increases each time.
|
||||
</p>
|
||||
|
||||
<h2>Key Features</h2>
|
||||
<p>
|
||||
- Fast-paced 2D tank battles<br>
|
||||
- Unique weapon<br>
|
||||
- Carefully designed map<br>
|
||||
- Detailed graphics<br>
|
||||
- Beautiful special effects of explosions<br>
|
||||
</p>
|
||||
|
||||
<h2>Difficulties during development</h2>
|
||||
<p>
|
||||
If you want to see the difficulties on the way of creating Tanks 2D, <a href="https://crimson-coletta-46.tiiny.site" target="_blank"> click here</a>.
|
||||
</p>
|
||||
<p><img id="qr-code" src="https://cdn.discordapp.com/attachments/711235658319921268/1234144155463057408/QRCode.png?ex=662fa9cf&is=662e584f&hm=469e1f53dc4872746d91f8bb84db6d2da0b47d7dda6b37745341179a20df19ab&" alt="QR Code"><br>QR Code</p>
|
||||
</div>
|
||||
|
||||
<!-- Область для оценки -->
|
||||
<div id="ratings" class="container" style="margin-top: 1000px;"> <!-- Установите высоту в px в зависимости от контента выше -->
|
||||
<h2>Rate Our Website and Game</h2>
|
||||
<p>Please rate our website and game from 1 to 5 stars:</p>
|
||||
<div>
|
||||
<label for="websiteRating">Website:</label>
|
||||
<input type="number" id="websiteRating" name="websiteRating" min="1" max="5">
|
||||
</div>
|
||||
<div>
|
||||
<label for="gameRating">Game:</label>
|
||||
<input type="number" id="gameRating" name="gameRating" min="1" max="5">
|
||||
</div>
|
||||
<button onclick="submitRatings()">Submit Ratings</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Функция для отправки оценок
|
||||
function submitRatings() {
|
||||
var websiteRating = document.getElementById("websiteRating").value;
|
||||
var gameRating = document.getElementById("gameRating").value;
|
||||
|
||||
// Здесь можно добавить код для отправки оценок на сервер или их обработки
|
||||
|
||||
alert("Thank you for your ratings! \nFrom: Arsenij, Artem and Roman. :) \nWebsite: " + websiteRating + " stars\nGame: " + gameRating + " stars");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
183
index.html
|
@ -1,183 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Welcome to Tanki 2D!</title>
|
||||
<link rel="icon" href="https://cdn.discordapp.com/attachments/856238529502511144/1234217742689767424/free-icon-tank-942355.png?ex=662fee58&is=662e9cd8&hm=82b93f0803c76e54589ff9766815979b37ed52b2ac7ac88a05cd081040a33492&"> <!-- Путь к вашему значку -->
|
||||
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #000; /* Черный цвет фона */
|
||||
color: #fff; /* Белый цвет текста */
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
margin-top: 80px; /* Отступ для контента под фиксированной шапкой */
|
||||
overflow-y: auto; /* Включаем вертикальную прокрутку */
|
||||
}
|
||||
|
||||
nav {
|
||||
position: fixed; /* Фиксированная позиция */
|
||||
top: 0; /* Расположение шапки вверху */
|
||||
left: 0; /* Расположение шапки слева */
|
||||
width: 100%; /* Занимает всю ширину экрана */
|
||||
background-color: #333;
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
z-index: 999; /* Чтобы шапка была выше других элементов */
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 100px; /* Устанавливаем ширину логотипа */
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
nav ul li a:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
background-color: #222; /* Цвет фона контейнера */
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px #748623; /* Тень контейнера */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #748623; /* Цвет заголовка */
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
background-color: #748623; /* Цвет кнопки */
|
||||
color: #fff; /* Цвет текста на кнопке */
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #748623; /* Изменение цвета кнопки при наведении */
|
||||
}
|
||||
|
||||
.advertisement {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.advertisement img {
|
||||
max-width: 100%;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(255, 255, 255, 0.1); /* Тень изображения */
|
||||
}
|
||||
|
||||
.footer {
|
||||
background-color: #888; /* Серый цвет фона нижнего раздела */
|
||||
padding: 20px;
|
||||
margin-top: 50px; /* Отступ сверху */
|
||||
}
|
||||
|
||||
.footer h2 {
|
||||
color: #fff; /* Белый цвет текста */
|
||||
margin: 0; /* Убираем внешние отступы */
|
||||
}
|
||||
|
||||
/* Стили для области оценки */
|
||||
#ratings {
|
||||
margin-top: 50px; /* Добавляем отступ сверху */
|
||||
text-align: center; /* Центрируем содержимое */
|
||||
}
|
||||
|
||||
#ratings input {
|
||||
width: 50px; /* Устанавливаем ширину поля ввода */
|
||||
margin: 10px; /* Добавляем отступы между элементами */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<div class="logo">
|
||||
<a href="/"><img src="https://cdn.discordapp.com/attachments/704651653873139803/1233880220004519986/Screenshot_2024-04-27_233856-removebg-preview.png?ex=662eb400&is=662d6280&hm=518bf12af052c5268492e81d64f8957eea1d6163b3c8fe28c3e8a69758169263&" alt="Tanki Logo"></a>
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/game">Game</a></li>
|
||||
<li><a href="/support">Support</a></li>
|
||||
<li><a href="/updates">Updates</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="wrapper">
|
||||
<div class="container">
|
||||
<h1>Welcome to Tanki 2D!</h1>
|
||||
<p>Experience the thrill of tank battles like never before. Join our community of players and dominate the battlefield!</p>
|
||||
<p>Get started now:</p>
|
||||
<a href="/about" class="btn">Learn More</a>
|
||||
|
||||
<!-- Advertisement Section -->
|
||||
<div class="advertisement">
|
||||
<h2>Check out our latest game: Tanks 2D</h2>
|
||||
<p>Engage in fast-paced 2D tank battles with stunning graphics and intense gameplay!</p>
|
||||
<img src="https://cdn.discordapp.com/attachments/856238529502511144/1234090991045312543/image.png?ex=662f784c&is=662e26cc&hm=065a8314fa2f80d3f78d86beccbd81b4c1471065feba35a0dd0342d43376cfc7&" alt="Tanks 2D Advertisement">
|
||||
</div>
|
||||
</div>
|
||||
<!-- Область для оценки -->
|
||||
<div id="ratings" class="container" style="margin-top: 1000px;"> <!-- Установите высоту в px в зависимости от контента выше -->
|
||||
<h2>Rate Our Website and Game</h2>
|
||||
<p>Please rate our website and game from 1 to 5 stars:</p>
|
||||
<div>
|
||||
<label for="websiteRating">Website:</label>
|
||||
<input type="number" id="websiteRating" name="websiteRating" min="1" max="5">
|
||||
</div>
|
||||
<div>
|
||||
<label for="gameRating">Game:</label>
|
||||
<input type="number" id="gameRating" name="gameRating" min="1" max="5">
|
||||
</div>
|
||||
<button onclick="submitRatings()">Submit Ratings</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Функция для отправки оценок
|
||||
function submitRatings() {
|
||||
var websiteRating = document.getElementById("websiteRating").value;
|
||||
var gameRating = document.getElementById("gameRating").value;
|
||||
|
||||
// Здесь можно добавить код для отправки оценок на сервер или их обработки
|
||||
|
||||
alert("Thank you for your ratings! \nFrom: Arsenij, Artem and Roman. :) \nWebsite: " + websiteRating + " stars\nGame: " + gameRating + " stars");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
515
main.py
|
@ -1,515 +0,0 @@
|
|||
import pygame
|
||||
import random
|
||||
import math
|
||||
|
||||
# Определение констант
|
||||
SCREEN_WIDTH = 1920
|
||||
SCREEN_HEIGHT = 1080
|
||||
PLAYER_WIDTH = 100
|
||||
PLAYER_HEIGHT = 150
|
||||
LOH_WIDTH = 300
|
||||
LOH_HEIGHT = 250
|
||||
BULLET_SIZE = 20
|
||||
FPS = 60
|
||||
BULLET_SPEED = 6
|
||||
TANK_SPEED = 2
|
||||
BOT_SPEED = 2
|
||||
FIRE_DELAY = 1000 # Задержка между выстрелами в миллисекундах
|
||||
WHITE = (255, 255, 255)
|
||||
BLACK = (0, 0, 0)
|
||||
|
||||
#Определение переменных
|
||||
score = 0
|
||||
|
||||
# Инициализация Pygame
|
||||
pygame.init()
|
||||
|
||||
# Создание игрового окна
|
||||
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags=pygame.FULLSCREEN)
|
||||
pygame.display.set_caption("Танчики")
|
||||
|
||||
# Загрузка и воспроизведение музыки
|
||||
pygame.mixer.music.load('music.mp3')
|
||||
pygame.mixer.music.play(-1) # Параметр -1 означает зацикливание музыки
|
||||
shot_sound = pygame.mixer.Sound('shot.wav')
|
||||
meme_sound = pygame.mixer.Sound("meme_sound.wav")
|
||||
explosion_sound = pygame.mixer.Sound("explosion_sound.wav")
|
||||
stoneexplosion_sound = pygame.mixer.Sound("stoneexplosion_sound.wav")
|
||||
|
||||
# Загрузка изображений
|
||||
background_image = pygame.transform.scale(pygame.image.load("travka_pol.jpeg"), (960, 540))
|
||||
stena = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (100, 100))
|
||||
stenki = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (200, 200))
|
||||
tank_image = pygame.transform.scale(pygame.image.load("ntank-removebg-preview.png"), (PLAYER_WIDTH, PLAYER_HEIGHT))
|
||||
loh_image = pygame.transform.scale(pygame.image.load("loh.png"), (LOH_WIDTH, LOH_HEIGHT))
|
||||
bullet_image = pygame.transform.scale(pygame.image.load("bullet.png"), (BULLET_SIZE, BULLET_SIZE))
|
||||
explosion_images = [pygame.image.load(f"explosion_{i}.png") for i in range(1, 48)]
|
||||
stoneexplosion_images = [pygame.image.load(f"stoneexplosion_{i}.png") for i in range(1, 6)]
|
||||
|
||||
menu_background = pygame.transform.scale(pygame.image.load("menu_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
|
||||
|
||||
class Explosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.image = explosion_images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == 6:
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = explosion_images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Добавление класса для анимации удара о каменную стену
|
||||
class StoneExplosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.images = stoneexplosion_images
|
||||
self.image = self.images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
stoneexplosion_sound.play() # Воспроизведение звука удара о стену
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Определение класса танка
|
||||
class Tank(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = tank_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = -90 # Поворот на 90 градусов против часовой стрелки
|
||||
self.TANK_SPEED = 2
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.boosted = False # Флаг, показывающий, активирован ли ускоритель
|
||||
self.boost_multiplier = 2 # Множитель скорости ускорения
|
||||
|
||||
def update(self):
|
||||
keys = pygame.key.get_pressed()
|
||||
if keys[pygame.K_w]:
|
||||
self.move_forward()
|
||||
mouse_pos = pygame.mouse.get_pos()
|
||||
self.angle = math.degrees(math.atan2(mouse_pos[1] - self.rect.centery, mouse_pos[0] - self.rect.centerx)) + 90
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
if keys[pygame.K_x]:
|
||||
if not self.boosted:
|
||||
self.TANK_SPEED *= self.boost_multiplier
|
||||
self.boosted = True
|
||||
else:
|
||||
if self.boosted:
|
||||
self.TANK_SPEED /= self.boost_multiplier
|
||||
self.boosted = False
|
||||
|
||||
def move_forward(self):
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += self.TANK_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += self.TANK_SPEED * math.sin(angle_rad)
|
||||
|
||||
def shoot(self):
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_fire_time > FIRE_DELAY: # Проверка задержки между выстрелами
|
||||
shot_sound.play() # Воспроизведение звука выстрела
|
||||
# Коррекция угла вылета пули, чтобы она вылетала из дула танка
|
||||
offset_angle = -90 # Угол смещения для вылета пули из дула
|
||||
corrected_angle = self.angle + offset_angle
|
||||
|
||||
# Вычисляем координаты дула танка
|
||||
offset_x = 70 * math.cos(math.radians(corrected_angle))
|
||||
offset_y = 70 * math.sin(math.radians(corrected_angle))
|
||||
bullet = PlayerBullet(self.rect.centerx + offset_x, self.rect.centery + offset_y, self.angle + 270)
|
||||
all_sprites.add(bullet)
|
||||
bullets.add(bullet)
|
||||
self.last_fire_time = current_time # Обновление времени последнего выстрела
|
||||
|
||||
# Проверяем столкновение пули с каменными стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука столкновения с каменной стеной
|
||||
explosion = StoneExplosion(bullet.rect.centerx, bullet.rect.centery) # Создание анимации удара о стену
|
||||
all_sprites.add(explosion) # Добавление анимации удара о стену в группу спрайтов
|
||||
bullet.kill() # Удаление пули
|
||||
|
||||
|
||||
class PlayerBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса снаряда бота
|
||||
class BotBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса для бота
|
||||
class Bot(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = loh_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = random.randint(0, 360) # Случайный начальный угол поворота
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.rotate_delay = random.randint(100, 500) # Начальная задержка перед поворотом
|
||||
self.rotate_timer = 0
|
||||
|
||||
def update(self):
|
||||
self.move_random()
|
||||
self.rotate_random()
|
||||
self.check_bounds()
|
||||
# self.shoot_random()
|
||||
|
||||
def move_random(self):
|
||||
# Движение вперёд в направлении текущего угла поворота
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += BOT_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += BOT_SPEED * math.sin(angle_rad)
|
||||
|
||||
def rotate_random(self):
|
||||
# Случайный поворот бота
|
||||
self.rotate_timer += 1
|
||||
if self.rotate_timer >= self.rotate_delay:
|
||||
self.angle += random.randint(-10, 10) # Случайный поворот
|
||||
self.rotate_delay = random.randint(100, 500) # Новая случайная задержка перед поворотом
|
||||
self.rotate_timer = 0
|
||||
|
||||
def check_bounds(self):
|
||||
# Проверка выхода за границы экрана
|
||||
if self.rect.left < 0:
|
||||
self.rect.left = 0
|
||||
elif self.rect.right > SCREEN_WIDTH:
|
||||
self.rect.right = SCREEN_WIDTH
|
||||
if self.rect.top < 0:
|
||||
self.rect.top = 0
|
||||
elif self.rect.bottom > SCREEN_HEIGHT:
|
||||
self.rect.bottom = SCREEN_HEIGHT
|
||||
|
||||
# def shoot_random(self):
|
||||
# Выстрел в направлении дула
|
||||
# current_time = pygame.time.get_ticks()
|
||||
# if current_time - self.last_fire_time > random.randint(1000, 5000):
|
||||
# bullet = BotBullet(self.rect.centerx, self.rect.centery, self.angle + 90) # Стрельба в направлении дула
|
||||
# all_sprites.add(bullet)
|
||||
# bullets.add(bullet)
|
||||
# self.last_fire_time = current_time
|
||||
|
||||
|
||||
class Wall(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, image):
|
||||
super().__init__()
|
||||
self.image = image
|
||||
self.rect = self.image.get_rect(topleft=(x, y))
|
||||
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
walls = pygame.sprite.Group() # Группа для всех стен
|
||||
|
||||
# Создание стен
|
||||
wall_positions = [
|
||||
(360, 40), (460, 730), (460, 830), (460, 930),
|
||||
(960, 40), (960, 140), (960, 240),
|
||||
(660, 240),
|
||||
(960, 440), (960, 540), (960, 640), (960, 740),
|
||||
(1260, 740), (1360, 740), (1460, 740), (1560, 740), (1660, 740),
|
||||
(360, 240), (360, 340), (360, 440),
|
||||
(0, 540), (60, 540), (260, 540), (360, 540), (460, 540),
|
||||
(560, 540), (660, 540), (760, 540), (860, 540),
|
||||
(1160, 240), (1260, 240), (1360, 240), (1460, 240), (1460, 340),
|
||||
(1760, 340), (1860, 340)
|
||||
]
|
||||
|
||||
for pos in wall_positions:
|
||||
wall = Wall(*pos, stena)
|
||||
all_sprites.add(wall)
|
||||
walls.add(wall)
|
||||
|
||||
# Создание стен "stenki"
|
||||
wall_stenki_positions = [
|
||||
(-150, 0), (-150, 200), (-150, 400), (-150, 600), (-150, 800), (-150, 1000),
|
||||
(0, -150), (200, -150), (400, -150), (600, -150), (800, -150), (1000, -150),
|
||||
(1200, -150), (1400, -150), (1600, -150), (1800, -150), (1870, 0), (1870, 200),
|
||||
(1870, 400), (1870, 600), (1870, 800), (1870, 1000), (0, 1030), (200, 1030),
|
||||
(400, 1030), (600, 1030), (800, 1030), (1000, 1030), (1200, 1030), (1400, 1030),
|
||||
(1600, 1030), (1800, 1030)
|
||||
]
|
||||
|
||||
for pos in wall_stenki_positions:
|
||||
wall_stenki = Wall(*pos, stenki)
|
||||
all_sprites.add(wall_stenki)
|
||||
walls.add(wall_stenki)
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
|
||||
# Создание игрока
|
||||
player = Tank(SCREEN_WIDTH // 8, SCREEN_HEIGHT // 7)
|
||||
all_sprites.add(player)
|
||||
tanks.add(player)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
|
||||
def draw_menu():
|
||||
screen.blit(menu_background, (0, 0))
|
||||
# Рисуем текст меню
|
||||
font = pygame.font.Font(None, 50)
|
||||
text = font.render("Start", True, WHITE)
|
||||
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 50))
|
||||
screen.blit(text, text_rect)
|
||||
|
||||
# Рисуем кнопку "Выйти"
|
||||
quit_text = font.render("Quit", True, WHITE)
|
||||
quit_rect = quit_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 50))
|
||||
screen.blit(quit_text, quit_rect)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
return quit_rect # Возвращаем прямоугольник для кнопки "Выйти"
|
||||
|
||||
|
||||
def respawn_bot():
|
||||
# Создание нового экземпляра бота
|
||||
new_bot = Bot(random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
|
||||
all_sprites.add(new_bot)
|
||||
tanks.add(new_bot)
|
||||
|
||||
|
||||
last_meme_time = 0
|
||||
meme_delay = 2000 # Задержка в миллисекундах (2 секунды)
|
||||
|
||||
# Главный цикл программы
|
||||
menu_active = True
|
||||
while menu_active:
|
||||
quit_rect = draw_menu()
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # Левая кнопка мыши
|
||||
if quit_rect.collidepoint(event.pos):
|
||||
pygame.quit()
|
||||
quit()
|
||||
else:
|
||||
menu_active = False # Нажата кнопка "Старт"
|
||||
|
||||
# Основной игровой цикл
|
||||
clock = pygame.time.Clock()
|
||||
running = True
|
||||
|
||||
while running:
|
||||
player_bullets = []
|
||||
bot_bullets = []
|
||||
|
||||
current_time = pygame.time.get_ticks()
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: # Обработка левой кнопки мыши
|
||||
player.shoot()
|
||||
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_k:
|
||||
if current_time - last_meme_time > meme_delay: # Проверка задержки
|
||||
meme_sound.play()
|
||||
last_meme_time = current_time # Обновление времени последнего воспроизведения звука
|
||||
|
||||
# Обновление всех спрайтов
|
||||
all_sprites.update()
|
||||
|
||||
# Проверка столкновений пуль с танками
|
||||
for bullet in bullets:
|
||||
if isinstance(bullet, PlayerBullet):
|
||||
tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
|
||||
if tank_hit and isinstance(tank_hit, Bot):
|
||||
explosion_sound.play() # Воспроизведение звука взрыва
|
||||
explosion = Explosion(tank_hit.rect.centerx, tank_hit.rect.centery) # Создание взрыва
|
||||
all_sprites.add(explosion) # Добавление взрыва в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю
|
||||
tank_hit.kill() # Удаляем бота
|
||||
respawn_bot() # Создаем нового бота
|
||||
score += 1
|
||||
|
||||
elif isinstance(bullet, BotBullet):
|
||||
# Проверяем столкновение пули бота с стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука взрыва камня
|
||||
explosion = Explosion(bullet.rect.centerx, bullet.rect.centery) # Создание взрыва камня
|
||||
all_sprites.add(explosion) # Добавление взрыва камня в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю бота
|
||||
|
||||
|
||||
# Отрисовка фона
|
||||
for i in range(2):
|
||||
for j in range(2):
|
||||
screen.blit(background_image, (i * 960, j * 540))
|
||||
|
||||
all_sprites.draw(screen)
|
||||
screen.blit(stena, (360, 40))
|
||||
|
||||
screen.blit(stena, (460, 730))
|
||||
screen.blit(stena, (460, 830))
|
||||
screen.blit(stena, (460, 930))
|
||||
|
||||
screen.blit(stena, (960, 40))
|
||||
screen.blit(stena, (960, 140))
|
||||
screen.blit(stena, (960, 240))
|
||||
|
||||
screen.blit(stena, (660, 240))
|
||||
|
||||
screen.blit(stena, (960, 440))
|
||||
screen.blit(stena, (960, 540))
|
||||
screen.blit(stena, (960, 640))
|
||||
screen.blit(stena, (960, 740))
|
||||
|
||||
screen.blit(stena, (1260, 740))
|
||||
screen.blit(stena, (1360, 740))
|
||||
screen.blit(stena, (1460, 740))
|
||||
screen.blit(stena, (1560, 740))
|
||||
screen.blit(stena, (1660, 740))
|
||||
|
||||
screen.blit(stena, (360, 240))
|
||||
screen.blit(stena, (360, 340))
|
||||
screen.blit(stena, (360, 440))
|
||||
|
||||
screen.blit(stena, (0, 540))
|
||||
screen.blit(stena, (60, 540))
|
||||
screen.blit(stena, (260, 540))
|
||||
screen.blit(stena, (360, 540))
|
||||
screen.blit(stena, (460, 540))
|
||||
screen.blit(stena, (560, 540))
|
||||
screen.blit(stena, (660, 540))
|
||||
screen.blit(stena, (760, 540))
|
||||
screen.blit(stena, (860, 540))
|
||||
|
||||
screen.blit(stena, (1160, 240))
|
||||
screen.blit(stena, (1260, 240))
|
||||
screen.blit(stena, (1360, 240))
|
||||
screen.blit(stena, (1460, 240))
|
||||
screen.blit(stena, (1460, 340))
|
||||
screen.blit(stena, (1760, 340))
|
||||
screen.blit(stena, (1860, 340))
|
||||
|
||||
screen.blit(stenki, (-150, 0))
|
||||
screen.blit(stenki, (-150, 200))
|
||||
screen.blit(stenki, (-150, 400))
|
||||
screen.blit(stenki, (-150, 600))
|
||||
screen.blit(stenki, (-150, 800))
|
||||
screen.blit(stenki, (-150, 1000))
|
||||
screen.blit(stenki, (0, -150))
|
||||
screen.blit(stenki, (200, -150))
|
||||
screen.blit(stenki, (400, -150))
|
||||
screen.blit(stenki, (600, -150))
|
||||
screen.blit(stenki, (800, -150))
|
||||
screen.blit(stenki, (1000, -150))
|
||||
screen.blit(stenki, (1200, -150))
|
||||
screen.blit(stenki, (1400, -150))
|
||||
screen.blit(stenki, (1600, -150))
|
||||
screen.blit(stenki, (1800, -150))
|
||||
screen.blit(stenki, (1870, 0))
|
||||
screen.blit(stenki, (1870, 200))
|
||||
screen.blit(stenki, (1870, 400))
|
||||
screen.blit(stenki, (1870, 600))
|
||||
screen.blit(stenki, (1870, 800))
|
||||
screen.blit(stenki, (1870, 1000))
|
||||
screen.blit(stenki, (0, 1030))
|
||||
screen.blit(stenki, (200, 1030))
|
||||
screen.blit(stenki, (400, 1030))
|
||||
screen.blit(stenki, (600, 1030))
|
||||
screen.blit(stenki, (800, 1030))
|
||||
screen.blit(stenki, (1000, 1030))
|
||||
screen.blit(stenki, (1200, 1030))
|
||||
screen.blit(stenki, (1400, 1030))
|
||||
screen.blit(stenki, (1600, 1030))
|
||||
screen.blit(stenki, (1800, 1030))
|
||||
|
||||
|
||||
|
||||
font = pygame.font.Font(None, 36)
|
||||
score_text = font.render(f'Score: {score}', True, WHITE)
|
||||
screen.blit(score_text, (10, 10))
|
||||
score_rect = score_text.get_rect(topleft=(10, 10))
|
||||
pygame.draw.rect(screen, (0, 255, 0), (score_rect.topleft, (score_rect.width, score_rect.height))) # Draw a green rectangle behind the score
|
||||
screen.blit(score_text, score_rect.topleft)
|
||||
pygame.display.flip()
|
||||
clock.tick(FPS)
|
||||
|
||||
# Завершение работы Pygame
|
||||
pygame.quit()
|
BIN
meme_sound.wav
Before Width: | Height: | Size: 344 KiB |
Before Width: | Height: | Size: 42 KiB |
351
pochti
|
@ -1,351 +0,0 @@
|
|||
import pygame
|
||||
import random
|
||||
import math
|
||||
|
||||
# Определение констант
|
||||
SCREEN_WIDTH = 1920
|
||||
SCREEN_HEIGHT = 1080
|
||||
PLAYER_SIZE = 150
|
||||
BULLET_SIZE = 20
|
||||
FPS = 60
|
||||
BULLET_SPEED = 6
|
||||
TANK_SPEED = 2
|
||||
BOT_SPEED = 2
|
||||
FIRE_DELAY = 500 # Задержка между выстрелами в миллисекундах
|
||||
WHITE = (255, 255, 255)
|
||||
BLACK = (0, 0, 0)
|
||||
|
||||
# Инициализация Pygame
|
||||
pygame.init()
|
||||
|
||||
# Создание игрового окна
|
||||
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags=pygame.FULLSCREEN)
|
||||
pygame.display.set_caption("Танчики")
|
||||
|
||||
# Загрузка изображений
|
||||
background_image = pygame.transform.scale(pygame.image.load("travka_pol.jpeg"), (960, 540))
|
||||
stena = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (100, 100))
|
||||
stenki = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (200, 200))
|
||||
tank_image = pygame.transform.scale(pygame.image.load("ntank-removebg-preview.png"), (PLAYER_SIZE, PLAYER_SIZE))
|
||||
bullet_image = pygame.transform.scale(pygame.image.load("bullet.png"), (BULLET_SIZE, BULLET_SIZE))
|
||||
|
||||
|
||||
# Определение класса танка
|
||||
class Tank(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = tank_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = -90 # Поворот на 90 градусов против часовой стрелки
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
|
||||
def update(self):
|
||||
keys = pygame.key.get_pressed()
|
||||
if keys[pygame.K_w]:
|
||||
self.move_forward()
|
||||
mouse_pos = pygame.mouse.get_pos()
|
||||
self.angle = math.degrees(math.atan2(mouse_pos[1] - self.rect.centery, mouse_pos[0] - self.rect.centerx)) + 90
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
def move_forward(self):
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += TANK_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += TANK_SPEED * math.sin(angle_rad)
|
||||
|
||||
def shoot(self):
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_fire_time > FIRE_DELAY: # Проверка задержки между выстрелами
|
||||
# Коррекция угла вылета пули, чтобы она вылетала из дула танка
|
||||
offset_angle = -90 # Угол смещения для вылета пули из дула
|
||||
corrected_angle = self.angle + offset_angle
|
||||
|
||||
# Вычисляем координаты дула танка
|
||||
offset_x = 70 * math.cos(math.radians(corrected_angle))
|
||||
offset_y = 70 * math.sin(math.radians(corrected_angle))
|
||||
bullet = PlayerBullet(self.rect.centerx + offset_x, self.rect.centery + offset_y, self.angle + 270)
|
||||
all_sprites.add(bullet)
|
||||
bullets.add(bullet)
|
||||
self.last_fire_time = current_time # Обновление времени последнего выстрела
|
||||
|
||||
|
||||
# Определение класса снаряда игрока
|
||||
class PlayerBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
# Определение класса снаряда бота
|
||||
class BotBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
# Определение класса для бота
|
||||
class Bot(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = tank_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = random.randint(0, 360) # Случайный начальный угол поворота
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.rotate_delay = random.randint(100, 500) # Начальная задержка перед поворотом
|
||||
self.rotate_timer = 0
|
||||
|
||||
def update(self):
|
||||
self.move_random()
|
||||
self.rotate_random()
|
||||
self.check_bounds()
|
||||
#self.shoot_random()
|
||||
|
||||
def move_random(self):
|
||||
# Движение вперёд в направлении текущего угла поворота
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += BOT_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += BOT_SPEED * math.sin(angle_rad)
|
||||
|
||||
def rotate_random(self):
|
||||
# Случайный поворот бота
|
||||
self.rotate_timer += 1
|
||||
if self.rotate_timer >= self.rotate_delay:
|
||||
self.angle += random.randint(-10, 10) # Случайный поворот
|
||||
self.rotate_delay = random.randint(100, 500) # Новая случайная задержка перед поворотом
|
||||
self.rotate_timer = 0
|
||||
|
||||
def check_bounds(self):
|
||||
# Проверка выхода за границы экрана
|
||||
if self.rect.left < 0:
|
||||
self.rect.left = 0
|
||||
elif self.rect.right > SCREEN_WIDTH:
|
||||
self.rect.right = SCREEN_WIDTH
|
||||
if self.rect.top < 0:
|
||||
self.rect.top = 0
|
||||
elif self.rect.bottom > SCREEN_HEIGHT:
|
||||
self.rect.bottom = SCREEN_HEIGHT
|
||||
|
||||
#def shoot_random(self):
|
||||
# Выстрел в направлении дула
|
||||
#current_time = pygame.time.get_ticks()
|
||||
#if current_time - self.last_fire_time > random.randint(1000, 5000):
|
||||
#bullet = BotBullet(self.rect.centerx, self.rect.centery, self.angle + 90) # Стрельба в направлении дула
|
||||
#all_sprites.add(bullet)
|
||||
#bullets.add(bullet)
|
||||
#self.last_fire_time = current_time
|
||||
|
||||
|
||||
|
||||
class Wall(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, image):
|
||||
super().__init__()
|
||||
self.image = image
|
||||
self.rect = self.image.get_rect(topleft=(x, y))
|
||||
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
walls = pygame.sprite.Group() # Группа для всех стен
|
||||
|
||||
# Создание игрока
|
||||
player = Tank(SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(player)
|
||||
tanks.add(player)
|
||||
|
||||
# Создание стен
|
||||
wall_positions = [
|
||||
(360, 40), (460, 730), (460, 830), (460, 930),
|
||||
(960, 40), (960, 140), (960, 240),
|
||||
(660, 240),
|
||||
(960, 440), (960, 540), (960, 640), (960, 740),
|
||||
(1260, 740), (1360, 740), (1460, 740), (1560, 740), (1660, 740),
|
||||
(360, 240), (360, 340), (360, 440),
|
||||
(0, 540), (60, 540), (260, 540), (360, 540), (460, 540),
|
||||
(560, 540), (660, 540), (760, 540), (860, 540),
|
||||
(1160, 240), (1260, 240), (1360, 240), (1460, 240), (1460, 340),
|
||||
(1760, 340), (1860, 340)
|
||||
]
|
||||
|
||||
for pos in wall_positions:
|
||||
wall = Wall(*pos, stena)
|
||||
all_sprites.add(wall)
|
||||
walls.add(wall)
|
||||
|
||||
# Создание стен "stenki"
|
||||
wall_stenki_positions = [
|
||||
(-150, 0), (-150, 200), (-150, 400), (-150, 600), (-150, 800), (-150, 1000),
|
||||
(0, -150), (200, -150), (400, -150), (600, -150), (800, -150), (1000, -150),
|
||||
(1200, -150), (1400, -150), (1600, -150), (1800, -150), (1870, 0), (1870, 200),
|
||||
(1870, 400), (1870, 600), (1870, 800), (1870, 1000), (0, 1030), (200, 1030),
|
||||
(400, 1030), (600, 1030), (800, 1030), (1000, 1030), (1200, 1030), (1400, 1030),
|
||||
(1600, 1030), (1800, 1030)
|
||||
]
|
||||
|
||||
for pos in wall_stenki_positions:
|
||||
wall_stenki = Wall(*pos, stenki)
|
||||
all_sprites.add(wall_stenki)
|
||||
walls.add(wall_stenki)
|
||||
|
||||
|
||||
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
|
||||
# Создание игрока
|
||||
player = Tank(SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(player)
|
||||
tanks.add(player)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
# Основной игровой цикл
|
||||
clock = pygame.time.Clock()
|
||||
running = True
|
||||
|
||||
while running:
|
||||
player_bullets = []
|
||||
bot_bullets = []
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: # Обработка левой кнопки мыши
|
||||
player.shoot()
|
||||
|
||||
# Обновление всех спрайтов
|
||||
all_sprites.update()
|
||||
|
||||
# Проверка столкновений пуль с танками
|
||||
for bullet in bullets:
|
||||
if isinstance(bullet, PlayerBullet):
|
||||
tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
|
||||
if tank_hit and isinstance(tank_hit, Bot):
|
||||
tank_hit.kill() # Удаляем бота, если попал игрок
|
||||
bullet.kill() # Удаляем пулю
|
||||
elif isinstance(bullet, BotBullet):
|
||||
tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
|
||||
if tank_hit and isinstance(tank_hit, Tank):
|
||||
tank_hit.kill() # Удаляем игрока, если попал бот
|
||||
bullet.kill() # Удаляем пулю
|
||||
bullet.update()
|
||||
|
||||
# Отрисовка фона
|
||||
for i in range(2):
|
||||
for j in range(2):
|
||||
screen.blit(background_image, (i * 960, j * 540))
|
||||
|
||||
all_sprites.draw(screen)
|
||||
screen.blit(stena, (360, 40))
|
||||
|
||||
screen.blit(stena, (460, 730))
|
||||
screen.blit(stena, (460, 830))
|
||||
screen.blit(stena, (460, 930))
|
||||
|
||||
screen.blit(stena, (960, 40))
|
||||
screen.blit(stena, (960, 140))
|
||||
screen.blit(stena, (960, 240))
|
||||
|
||||
screen.blit(stena, (660, 240))
|
||||
|
||||
screen.blit(stena, (960, 440))
|
||||
screen.blit(stena, (960, 540))
|
||||
screen.blit(stena, (960, 640))
|
||||
screen.blit(stena, (960, 740))
|
||||
|
||||
screen.blit(stena, (1260, 740))
|
||||
screen.blit(stena, (1360, 740))
|
||||
screen.blit(stena, (1460, 740))
|
||||
screen.blit(stena, (1560, 740))
|
||||
screen.blit(stena, (1660, 740))
|
||||
|
||||
screen.blit(stena, (360, 240))
|
||||
screen.blit(stena, (360, 340))
|
||||
screen.blit(stena, (360, 440))
|
||||
|
||||
screen.blit(stena, (0, 540))
|
||||
screen.blit(stena, (60, 540))
|
||||
screen.blit(stena, (260, 540))
|
||||
screen.blit(stena, (360, 540))
|
||||
screen.blit(stena, (460, 540))
|
||||
screen.blit(stena, (560, 540))
|
||||
screen.blit(stena, (660, 540))
|
||||
screen.blit(stena, (760, 540))
|
||||
screen.blit(stena, (860, 540))
|
||||
|
||||
screen.blit(stena, (1160, 240))
|
||||
screen.blit(stena, (1260, 240))
|
||||
screen.blit(stena, (1360, 240))
|
||||
screen.blit(stena, (1460, 240))
|
||||
screen.blit(stena, (1460, 340))
|
||||
screen.blit(stena, (1760, 340))
|
||||
screen.blit(stena, (1860, 340))
|
||||
|
||||
screen.blit(stenki, (-150, 0))
|
||||
screen.blit(stenki, (-150, 200))
|
||||
screen.blit(stenki, (-150, 400))
|
||||
screen.blit(stenki, (-150, 600))
|
||||
screen.blit(stenki, (-150, 800))
|
||||
screen.blit(stenki, (-150, 1000))
|
||||
screen.blit(stenki, (0, -150))
|
||||
screen.blit(stenki, (200, -150))
|
||||
screen.blit(stenki, (400, -150))
|
||||
screen.blit(stenki, (600, -150))
|
||||
screen.blit(stenki, (800, -150))
|
||||
screen.blit(stenki, (1000, -150))
|
||||
screen.blit(stenki, (1200, -150))
|
||||
screen.blit(stenki, (1400, -150))
|
||||
screen.blit(stenki, (1600, -150))
|
||||
screen.blit(stenki, (1800, -150))
|
||||
screen.blit(stenki, (1870, 0))
|
||||
screen.blit(stenki, (1870, 200))
|
||||
screen.blit(stenki, (1870, 400))
|
||||
screen.blit(stenki, (1870, 600))
|
||||
screen.blit(stenki, (1870, 800))
|
||||
screen.blit(stenki, (1870, 1000))
|
||||
screen.blit(stenki, (0, 1030))
|
||||
screen.blit(stenki, (200, 1030))
|
||||
screen.blit(stenki, (400, 1030))
|
||||
screen.blit(stenki, (600, 1030))
|
||||
screen.blit(stenki, (800, 1030))
|
||||
screen.blit(stenki, (1000, 1030))
|
||||
screen.blit(stenki, (1200, 1030))
|
||||
screen.blit(stenki, (1400, 1030))
|
||||
screen.blit(stenki, (1600, 1030))
|
||||
screen.blit(stenki, (1800, 1030))
|
||||
|
||||
pygame.display.flip()
|
||||
clock.tick(FPS)
|
||||
|
||||
# Завершение работы Pygame
|
||||
pygame.quit()
|
||||
|
||||
# token: 8f195a885b18a96da6577884cc731f850f33a9e2
|
|
@ -1 +0,0 @@
|
|||
oipyuiop
|
515
score
|
@ -1,515 +0,0 @@
|
|||
import pygame
|
||||
import random
|
||||
import math
|
||||
|
||||
# Определение констант
|
||||
SCREEN_WIDTH = 1920
|
||||
SCREEN_HEIGHT = 1080
|
||||
PLAYER_WIDTH = 100
|
||||
PLAYER_HEIGHT = 150
|
||||
LOH_WIDTH = 300
|
||||
LOH_HEIGHT = 250
|
||||
BULLET_SIZE = 20
|
||||
FPS = 60
|
||||
BULLET_SPEED = 6
|
||||
TANK_SPEED = 2
|
||||
BOT_SPEED = 2
|
||||
FIRE_DELAY = 1000 # Задержка между выстрелами в миллисекундах
|
||||
WHITE = (255, 255, 255)
|
||||
BLACK = (0, 0, 0)
|
||||
|
||||
#Определение переменных
|
||||
score = 0
|
||||
|
||||
# Инициализация Pygame
|
||||
pygame.init()
|
||||
|
||||
# Создание игрового окна
|
||||
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags=pygame.FULLSCREEN)
|
||||
pygame.display.set_caption("Танчики")
|
||||
|
||||
# Загрузка и воспроизведение музыки
|
||||
pygame.mixer.music.load('music.mp3')
|
||||
pygame.mixer.music.play(-1) # Параметр -1 означает зацикливание музыки
|
||||
shot_sound = pygame.mixer.Sound('shot.wav')
|
||||
meme_sound = pygame.mixer.Sound("meme_sound.wav")
|
||||
explosion_sound = pygame.mixer.Sound("explosion_sound.wav")
|
||||
stoneexplosion_sound = pygame.mixer.Sound("stoneexplosion_sound.wav")
|
||||
|
||||
# Загрузка изображений
|
||||
background_image = pygame.transform.scale(pygame.image.load("travka_pol.jpeg"), (960, 540))
|
||||
stena = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (100, 100))
|
||||
stenki = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (200, 200))
|
||||
tank_image = pygame.transform.scale(pygame.image.load("ntank-removebg-preview.png"), (PLAYER_WIDTH, PLAYER_HEIGHT))
|
||||
loh_image = pygame.transform.scale(pygame.image.load("loh.png"), (LOH_WIDTH, LOH_HEIGHT))
|
||||
bullet_image = pygame.transform.scale(pygame.image.load("bullet.png"), (BULLET_SIZE, BULLET_SIZE))
|
||||
explosion_images = [pygame.image.load(f"explosion_{i}.png") for i in range(1, 48)]
|
||||
stoneexplosion_images = [pygame.image.load(f"stoneexplosion_{i}.png") for i in range(1, 6)]
|
||||
|
||||
menu_background = pygame.transform.scale(pygame.image.load("menu_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
|
||||
|
||||
class Explosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.image = explosion_images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == 6:
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = explosion_images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Добавление класса для анимации удара о каменную стену
|
||||
class StoneExplosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.images = stoneexplosion_images
|
||||
self.image = self.images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
stoneexplosion_sound.play() # Воспроизведение звука удара о стену
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Определение класса танка
|
||||
class Tank(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = tank_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = -90 # Поворот на 90 градусов против часовой стрелки
|
||||
self.TANK_SPEED = 2
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.boosted = False # Флаг, показывающий, активирован ли ускоритель
|
||||
self.boost_multiplier = 2 # Множитель скорости ускорения
|
||||
|
||||
def update(self):
|
||||
keys = pygame.key.get_pressed()
|
||||
if keys[pygame.K_w]:
|
||||
self.move_forward()
|
||||
mouse_pos = pygame.mouse.get_pos()
|
||||
self.angle = math.degrees(math.atan2(mouse_pos[1] - self.rect.centery, mouse_pos[0] - self.rect.centerx)) + 90
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
if keys[pygame.K_x]:
|
||||
if not self.boosted:
|
||||
self.TANK_SPEED *= self.boost_multiplier
|
||||
self.boosted = True
|
||||
else:
|
||||
if self.boosted:
|
||||
self.TANK_SPEED /= self.boost_multiplier
|
||||
self.boosted = False
|
||||
|
||||
def move_forward(self):
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += self.TANK_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += self.TANK_SPEED * math.sin(angle_rad)
|
||||
|
||||
def shoot(self):
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_fire_time > FIRE_DELAY: # Проверка задержки между выстрелами
|
||||
shot_sound.play() # Воспроизведение звука выстрела
|
||||
# Коррекция угла вылета пули, чтобы она вылетала из дула танка
|
||||
offset_angle = -90 # Угол смещения для вылета пули из дула
|
||||
corrected_angle = self.angle + offset_angle
|
||||
|
||||
# Вычисляем координаты дула танка
|
||||
offset_x = 70 * math.cos(math.radians(corrected_angle))
|
||||
offset_y = 70 * math.sin(math.radians(corrected_angle))
|
||||
bullet = PlayerBullet(self.rect.centerx + offset_x, self.rect.centery + offset_y, self.angle + 270)
|
||||
all_sprites.add(bullet)
|
||||
bullets.add(bullet)
|
||||
self.last_fire_time = current_time # Обновление времени последнего выстрела
|
||||
|
||||
# Проверяем столкновение пули с каменными стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука столкновения с каменной стеной
|
||||
explosion = StoneExplosion(bullet.rect.centerx, bullet.rect.centery) # Создание анимации удара о стену
|
||||
all_sprites.add(explosion) # Добавление анимации удара о стену в группу спрайтов
|
||||
bullet.kill() # Удаление пули
|
||||
|
||||
|
||||
class PlayerBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса снаряда бота
|
||||
class BotBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса для бота
|
||||
class Bot(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = loh_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = random.randint(0, 360) # Случайный начальный угол поворота
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.rotate_delay = random.randint(100, 500) # Начальная задержка перед поворотом
|
||||
self.rotate_timer = 0
|
||||
|
||||
def update(self):
|
||||
self.move_random()
|
||||
self.rotate_random()
|
||||
self.check_bounds()
|
||||
# self.shoot_random()
|
||||
|
||||
def move_random(self):
|
||||
# Движение вперёд в направлении текущего угла поворота
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += BOT_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += BOT_SPEED * math.sin(angle_rad)
|
||||
|
||||
def rotate_random(self):
|
||||
# Случайный поворот бота
|
||||
self.rotate_timer += 1
|
||||
if self.rotate_timer >= self.rotate_delay:
|
||||
self.angle += random.randint(-10, 10) # Случайный поворот
|
||||
self.rotate_delay = random.randint(100, 500) # Новая случайная задержка перед поворотом
|
||||
self.rotate_timer = 0
|
||||
|
||||
def check_bounds(self):
|
||||
# Проверка выхода за границы экрана
|
||||
if self.rect.left < 0:
|
||||
self.rect.left = 0
|
||||
elif self.rect.right > SCREEN_WIDTH:
|
||||
self.rect.right = SCREEN_WIDTH
|
||||
if self.rect.top < 0:
|
||||
self.rect.top = 0
|
||||
elif self.rect.bottom > SCREEN_HEIGHT:
|
||||
self.rect.bottom = SCREEN_HEIGHT
|
||||
|
||||
# def shoot_random(self):
|
||||
# Выстрел в направлении дула
|
||||
# current_time = pygame.time.get_ticks()
|
||||
# if current_time - self.last_fire_time > random.randint(1000, 5000):
|
||||
# bullet = BotBullet(self.rect.centerx, self.rect.centery, self.angle + 90) # Стрельба в направлении дула
|
||||
# all_sprites.add(bullet)
|
||||
# bullets.add(bullet)
|
||||
# self.last_fire_time = current_time
|
||||
|
||||
|
||||
class Wall(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, image):
|
||||
super().__init__()
|
||||
self.image = image
|
||||
self.rect = self.image.get_rect(topleft=(x, y))
|
||||
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
walls = pygame.sprite.Group() # Группа для всех стен
|
||||
|
||||
# Создание стен
|
||||
wall_positions = [
|
||||
(360, 40), (460, 730), (460, 830), (460, 930),
|
||||
(960, 40), (960, 140), (960, 240),
|
||||
(660, 240),
|
||||
(960, 440), (960, 540), (960, 640), (960, 740),
|
||||
(1260, 740), (1360, 740), (1460, 740), (1560, 740), (1660, 740),
|
||||
(360, 240), (360, 340), (360, 440),
|
||||
(0, 540), (60, 540), (260, 540), (360, 540), (460, 540),
|
||||
(560, 540), (660, 540), (760, 540), (860, 540),
|
||||
(1160, 240), (1260, 240), (1360, 240), (1460, 240), (1460, 340),
|
||||
(1760, 340), (1860, 340)
|
||||
]
|
||||
|
||||
for pos in wall_positions:
|
||||
wall = Wall(*pos, stena)
|
||||
all_sprites.add(wall)
|
||||
walls.add(wall)
|
||||
|
||||
# Создание стен "stenki"
|
||||
wall_stenki_positions = [
|
||||
(-150, 0), (-150, 200), (-150, 400), (-150, 600), (-150, 800), (-150, 1000),
|
||||
(0, -150), (200, -150), (400, -150), (600, -150), (800, -150), (1000, -150),
|
||||
(1200, -150), (1400, -150), (1600, -150), (1800, -150), (1870, 0), (1870, 200),
|
||||
(1870, 400), (1870, 600), (1870, 800), (1870, 1000), (0, 1030), (200, 1030),
|
||||
(400, 1030), (600, 1030), (800, 1030), (1000, 1030), (1200, 1030), (1400, 1030),
|
||||
(1600, 1030), (1800, 1030)
|
||||
]
|
||||
|
||||
for pos in wall_stenki_positions:
|
||||
wall_stenki = Wall(*pos, stenki)
|
||||
all_sprites.add(wall_stenki)
|
||||
walls.add(wall_stenki)
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
|
||||
# Создание игрока
|
||||
player = Tank(SCREEN_WIDTH // 8, SCREEN_HEIGHT // 7)
|
||||
all_sprites.add(player)
|
||||
tanks.add(player)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
|
||||
def draw_menu():
|
||||
screen.blit(menu_background, (0, 0))
|
||||
# Рисуем текст меню
|
||||
font = pygame.font.Font(None, 50)
|
||||
text = font.render("Start", True, WHITE)
|
||||
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 50))
|
||||
screen.blit(text, text_rect)
|
||||
|
||||
# Рисуем кнопку "Выйти"
|
||||
quit_text = font.render("Quit", True, WHITE)
|
||||
quit_rect = quit_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 50))
|
||||
screen.blit(quit_text, quit_rect)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
return quit_rect # Возвращаем прямоугольник для кнопки "Выйти"
|
||||
|
||||
|
||||
def respawn_bot():
|
||||
# Создание нового экземпляра бота
|
||||
new_bot = Bot(random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
|
||||
all_sprites.add(new_bot)
|
||||
tanks.add(new_bot)
|
||||
|
||||
|
||||
last_meme_time = 0
|
||||
meme_delay = 2000 # Задержка в миллисекундах (2 секунды)
|
||||
|
||||
# Главный цикл программы
|
||||
menu_active = True
|
||||
while menu_active:
|
||||
quit_rect = draw_menu()
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # Левая кнопка мыши
|
||||
if quit_rect.collidepoint(event.pos):
|
||||
pygame.quit()
|
||||
quit()
|
||||
else:
|
||||
menu_active = False # Нажата кнопка "Старт"
|
||||
|
||||
# Основной игровой цикл
|
||||
clock = pygame.time.Clock()
|
||||
running = True
|
||||
|
||||
while running:
|
||||
player_bullets = []
|
||||
bot_bullets = []
|
||||
|
||||
current_time = pygame.time.get_ticks()
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: # Обработка левой кнопки мыши
|
||||
player.shoot()
|
||||
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_k:
|
||||
if current_time - last_meme_time > meme_delay: # Проверка задержки
|
||||
meme_sound.play()
|
||||
last_meme_time = current_time # Обновление времени последнего воспроизведения звука
|
||||
|
||||
# Обновление всех спрайтов
|
||||
all_sprites.update()
|
||||
|
||||
# Проверка столкновений пуль с танками
|
||||
for bullet in bullets:
|
||||
if isinstance(bullet, PlayerBullet):
|
||||
tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
|
||||
if tank_hit and isinstance(tank_hit, Bot):
|
||||
explosion_sound.play() # Воспроизведение звука взрыва
|
||||
explosion = Explosion(tank_hit.rect.centerx, tank_hit.rect.centery) # Создание взрыва
|
||||
all_sprites.add(explosion) # Добавление взрыва в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю
|
||||
tank_hit.kill() # Удаляем бота
|
||||
respawn_bot() # Создаем нового бота
|
||||
score += 1
|
||||
|
||||
elif isinstance(bullet, BotBullet):
|
||||
# Проверяем столкновение пули бота с стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука взрыва камня
|
||||
explosion = Explosion(bullet.rect.centerx, bullet.rect.centery) # Создание взрыва камня
|
||||
all_sprites.add(explosion) # Добавление взрыва камня в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю бота
|
||||
|
||||
|
||||
# Отрисовка фона
|
||||
for i in range(2):
|
||||
for j in range(2):
|
||||
screen.blit(background_image, (i * 960, j * 540))
|
||||
|
||||
all_sprites.draw(screen)
|
||||
screen.blit(stena, (360, 40))
|
||||
|
||||
screen.blit(stena, (460, 730))
|
||||
screen.blit(stena, (460, 830))
|
||||
screen.blit(stena, (460, 930))
|
||||
|
||||
screen.blit(stena, (960, 40))
|
||||
screen.blit(stena, (960, 140))
|
||||
screen.blit(stena, (960, 240))
|
||||
|
||||
screen.blit(stena, (660, 240))
|
||||
|
||||
screen.blit(stena, (960, 440))
|
||||
screen.blit(stena, (960, 540))
|
||||
screen.blit(stena, (960, 640))
|
||||
screen.blit(stena, (960, 740))
|
||||
|
||||
screen.blit(stena, (1260, 740))
|
||||
screen.blit(stena, (1360, 740))
|
||||
screen.blit(stena, (1460, 740))
|
||||
screen.blit(stena, (1560, 740))
|
||||
screen.blit(stena, (1660, 740))
|
||||
|
||||
screen.blit(stena, (360, 240))
|
||||
screen.blit(stena, (360, 340))
|
||||
screen.blit(stena, (360, 440))
|
||||
|
||||
screen.blit(stena, (0, 540))
|
||||
screen.blit(stena, (60, 540))
|
||||
screen.blit(stena, (260, 540))
|
||||
screen.blit(stena, (360, 540))
|
||||
screen.blit(stena, (460, 540))
|
||||
screen.blit(stena, (560, 540))
|
||||
screen.blit(stena, (660, 540))
|
||||
screen.blit(stena, (760, 540))
|
||||
screen.blit(stena, (860, 540))
|
||||
|
||||
screen.blit(stena, (1160, 240))
|
||||
screen.blit(stena, (1260, 240))
|
||||
screen.blit(stena, (1360, 240))
|
||||
screen.blit(stena, (1460, 240))
|
||||
screen.blit(stena, (1460, 340))
|
||||
screen.blit(stena, (1760, 340))
|
||||
screen.blit(stena, (1860, 340))
|
||||
|
||||
screen.blit(stenki, (-150, 0))
|
||||
screen.blit(stenki, (-150, 200))
|
||||
screen.blit(stenki, (-150, 400))
|
||||
screen.blit(stenki, (-150, 600))
|
||||
screen.blit(stenki, (-150, 800))
|
||||
screen.blit(stenki, (-150, 1000))
|
||||
screen.blit(stenki, (0, -150))
|
||||
screen.blit(stenki, (200, -150))
|
||||
screen.blit(stenki, (400, -150))
|
||||
screen.blit(stenki, (600, -150))
|
||||
screen.blit(stenki, (800, -150))
|
||||
screen.blit(stenki, (1000, -150))
|
||||
screen.blit(stenki, (1200, -150))
|
||||
screen.blit(stenki, (1400, -150))
|
||||
screen.blit(stenki, (1600, -150))
|
||||
screen.blit(stenki, (1800, -150))
|
||||
screen.blit(stenki, (1870, 0))
|
||||
screen.blit(stenki, (1870, 200))
|
||||
screen.blit(stenki, (1870, 400))
|
||||
screen.blit(stenki, (1870, 600))
|
||||
screen.blit(stenki, (1870, 800))
|
||||
screen.blit(stenki, (1870, 1000))
|
||||
screen.blit(stenki, (0, 1030))
|
||||
screen.blit(stenki, (200, 1030))
|
||||
screen.blit(stenki, (400, 1030))
|
||||
screen.blit(stenki, (600, 1030))
|
||||
screen.blit(stenki, (800, 1030))
|
||||
screen.blit(stenki, (1000, 1030))
|
||||
screen.blit(stenki, (1200, 1030))
|
||||
screen.blit(stenki, (1400, 1030))
|
||||
screen.blit(stenki, (1600, 1030))
|
||||
screen.blit(stenki, (1800, 1030))
|
||||
|
||||
|
||||
|
||||
font = pygame.font.Font(None, 36)
|
||||
score_text = font.render(f'Score: {score}', True, WHITE)
|
||||
screen.blit(score_text, (10, 10))
|
||||
score_rect = score_text.get_rect(topleft=(10, 10))
|
||||
pygame.draw.rect(screen, (0, 255, 0), (score_rect.topleft, (score_rect.width, score_rect.height))) # Draw a green rectangle behind the score
|
||||
screen.blit(score_text, score_rect.topleft)
|
||||
pygame.display.flip()
|
||||
clock.tick(FPS)
|
||||
|
||||
# Завершение работы Pygame
|
||||
pygame.quit()
|
Before Width: | Height: | Size: 2.3 MiB |
BIN
stena.jpeg
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 7.3 KiB |
155
support.html
|
@ -1,155 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>About Tanki</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link rel="icon" href="https://cdn.discordapp.com/attachments/856238529502511144/1234217742689767424/free-icon-tank-942355.png?ex=662fee58&is=662e9cd8&hm=82b93f0803c76e54589ff9766815979b37ed52b2ac7ac88a05cd081040a33492&">
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #000000; /* Черный цвет фона */
|
||||
color: #fff; /* Белый цвет текста */
|
||||
}
|
||||
|
||||
nav {
|
||||
position: fixed; /* Фиксированная позиция */
|
||||
top: 0; /* Расположение шапки вверху */
|
||||
left: 0; /* Расположение шапки слева */
|
||||
width: 100%; /* Занимает всю ширину экрана */
|
||||
background-color: #333;
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
z-index: 999; /* Чтобы шапка была выше других элементов */
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 100px; /* Устанавливаем ширину логотипа */
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
nav ul li a:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px #748623;
|
||||
background-color: #222;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
margin-top: 80px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #748623;
|
||||
text-align: center; /* Центрирование текста */
|
||||
}
|
||||
|
||||
p {
|
||||
color: #fff;
|
||||
text-align: center; /* Центрирование текста */
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.email {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Стили для области оценки */
|
||||
#ratings {
|
||||
padding-top: 50px; /* Добавляем отступ сверху, чтобы область оценки была выше */
|
||||
text-align: center; /* Центрируем содержимое */
|
||||
}
|
||||
|
||||
#ratings input {
|
||||
width: 50px; /* Устанавливаем ширину поля ввода */
|
||||
margin: 10px; /* Добавляем отступы между элементами */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<div class="logo" onclick="location.href='/'">
|
||||
<img src="https://cdn.discordapp.com/attachments/704651653873139803/1233880220004519986/Screenshot_2024-04-27_233856-removebg-preview.png?ex=662eb400&is=662d6280&hm=518bf12af052c5268492e81d64f8957eea1d6163b3c8fe28c3e8a69758169263&" alt="Tanki Logo">
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/game">Game</a></li>
|
||||
<li><a href="/support">Support</a></li>
|
||||
<li><a href="/updates">Updates</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<h1>Encountered any unexpected problems?</h1>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p>If you have any questions or problems, please contact our support team by email:</p>
|
||||
<p class="email">supporttanki@gmail.com</p>
|
||||
<form id="supportForm">
|
||||
<textarea id="problemDescription" placeholder="Or you can describe your problem here..." rows="4" cols="50"></textarea>
|
||||
<br>
|
||||
<button type="submit">Send</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Область для оценки -->
|
||||
<div id="ratings" class="container" style="margin-top: 1000px;"> <!-- Установите высоту в px в зависимости от контента выше -->
|
||||
<h2>Rate Our Website and Game</h2>
|
||||
<p>Please rate our website and game from 1 to 5 stars:</p>
|
||||
<div>
|
||||
<label for="websiteRating">Website:</label>
|
||||
<input type="number" id="websiteRating" name="websiteRating" min="1" max="5">
|
||||
</div>
|
||||
<div>
|
||||
<label for="gameRating">Game:</label>
|
||||
<input type="number" id="gameRating" name="gameRating" min="1" max="5">
|
||||
</div>
|
||||
<button onclick="submitRatings()">Submit Ratings</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Функция для отправки оценок
|
||||
function submitRatings() {
|
||||
var websiteRating = document.getElementById("websiteRating").value;
|
||||
var gameRating = document.getElementById("gameRating").value;
|
||||
|
||||
// Здесь можно добавить код для отправки оценок на сервер или их обработки
|
||||
|
||||
alert("Thank you for your ratings! \nFrom: Arsenij, Artem and Roman. :) \nWebsite: " + websiteRating + " stars\nGame: " + gameRating + " stars");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
BIN
travka_pol.jpeg
Before Width: | Height: | Size: 18 KiB |
192
updates.html
|
@ -1,192 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Game Updates</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link rel="icon" href="https://cdn.discordapp.com/attachments/856238529502511144/1234217742689767424/free-icon-tank-942355.png?ex=662fee58&is=662e9cd8&hm=82b93f0803c76e54589ff9766815979b37ed52b2ac7ac88a05cd081040a33492&">
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #000; /* Black background color */
|
||||
color: #fff; /* White text color */
|
||||
}
|
||||
|
||||
nav {
|
||||
position: fixed; /* Fixed position */
|
||||
top: 0; /* Position at the top */
|
||||
left: 0; /* Position at the left */
|
||||
width: 100%; /* Takes the full width */
|
||||
background-color: #333;
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
z-index: 999; /* Ensures the navbar is above other elements */
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 100px; /* Set the width of the logo */
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
nav ul li a:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
background-color: #222; /* Background color of the container */
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px #748623; /* Shadow around the container */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #748623; /* Header color */
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Styles for updates */
|
||||
.update {
|
||||
margin-bottom: 30px; /* Space between updates */
|
||||
}
|
||||
|
||||
.update h2 {
|
||||
color: #f0c911; /* Update header color */
|
||||
margin-bottom: 10px; /* Space below the update header */
|
||||
}
|
||||
|
||||
.update p {
|
||||
color: #fff; /* Text color for updates */
|
||||
line-height: 1.6; /* Line spacing */
|
||||
}
|
||||
|
||||
.note {
|
||||
border: 1px solid gray; /* Gray border */
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: #333; /* Background color */
|
||||
color: #f0c911; /* Text color */
|
||||
font-weight: bold; /* Bold font */
|
||||
margin-top: 20px; /* Space at the top */
|
||||
}
|
||||
|
||||
/* Styles for the rating area */
|
||||
#ratings {
|
||||
margin-top: 50px; /* Space at the top */
|
||||
text-align: center; /* Center-align content */
|
||||
}
|
||||
|
||||
#ratings input {
|
||||
width: 50px; /* Width of input fields */
|
||||
margin: 10px; /* Space between elements */
|
||||
}
|
||||
|
||||
/* Styles for scroll link */
|
||||
#scrollToRatings {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
#scrollToRatings a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#scrollToRatings a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<div class="logo" onclick="location.href='/'">
|
||||
<img src="https://cdn.discordapp.com/attachments/704651653873139803/1233880220004519986/Screenshot_2024-04-27_233856-removebg-preview.png?ex=662eb400&is=662d6280&hm=518bf12af052c5268492e81d64f8957eea1d6163b3c8fe28c3e8a69758169263&" alt="Tanki Logo">
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="/about">About</a></li>
|
||||
<li><a href="/game">Game</a></li>
|
||||
<li><a href="/support">Support</a></li>
|
||||
<li><a href="/updates">Updates</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<h1>Game Updates</h1>
|
||||
<div class="update">
|
||||
<h2>Update 1.0</h2>
|
||||
<p>In this update, graphics, game performance, and customization options have been improved. Bugs have also been fixed as reported by players. Get ready for intense battles in new, exciting conditions!</p>
|
||||
</div>
|
||||
<div class="update">
|
||||
<h2>Update 1.1</h2>
|
||||
<p>In this update, we improved the walls to prevent players from driving through them. Enjoy smoother gameplay and greater stability!</p>
|
||||
</div>
|
||||
<div class="update">
|
||||
<h2>Update 1.2</h2>
|
||||
<p>In this update, we almost doubled the game map and made it more detailed. Now we are on Steam as a free game! Enjoy smoother gameplay and greater stability!</p>
|
||||
</div>
|
||||
|
||||
<!-- Added text in a gray box -->
|
||||
<div class="note">
|
||||
If you want updates to appear more often, support the developers!!!
|
||||
<br><br> <!-- Double line break to create space -->
|
||||
ROMANS KOSOGOROVS
|
||||
<br>
|
||||
LV39HABA0551051381379
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Area for ratings -->
|
||||
<div id="ratings" class="container" style="margin-top: 1000px;">
|
||||
<h2>Rate Our Website and Game</h2>
|
||||
<p>Please rate our website from 1 to 5 stars:</p>
|
||||
<div>
|
||||
<label for="websiteRating">Website:</label>
|
||||
<input type="number" id="websiteRating" name="websiteRating" min="1" max="5">
|
||||
</div>
|
||||
<div>
|
||||
<label for="gameRating">Game:</label>
|
||||
<input type="number" id="gameRating" name="gameRating" min="1" max="5">
|
||||
</div>
|
||||
<button onclick="submitRatings()">Submit Ratings</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function submitRatings() {
|
||||
var websiteRating = document.getElementById("websiteRating").value;
|
||||
var gameRating = document.getElementById("gameRating").value;
|
||||
|
||||
alert("Thank you for your ratings!\nWebsite: " + websiteRating + " stars\nGame: " + gameRating + " stars");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,578 +0,0 @@
|
|||
import pygame
|
||||
import random
|
||||
import math
|
||||
|
||||
# Определение констант
|
||||
SCREEN_WIDTH = 1920
|
||||
SCREEN_HEIGHT = 1080
|
||||
PLAYER_WIDTH = 90
|
||||
PLAYER_HEIGHT = 135
|
||||
LOH_WIDTH = 150
|
||||
LOH_HEIGHT = 100
|
||||
BULLET_SIZE = 20
|
||||
FPS = 60
|
||||
BULLET_SPEED = 6
|
||||
TANK_SPEED = 2
|
||||
BOT_SPEED = 2
|
||||
FIRE_DELAY = 1000 # Задержка между выстрелами в миллисекундах
|
||||
WHITE = (255, 255, 255)
|
||||
BLACK = (0, 0, 0)
|
||||
score = 0
|
||||
# Инициализация Pygame
|
||||
pygame.init()
|
||||
|
||||
# Создание игрового окна
|
||||
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags=pygame.FULLSCREEN)
|
||||
pygame.display.set_caption("Танчики")
|
||||
|
||||
|
||||
# Загрузка и воспроизведение музыки
|
||||
pygame.mixer.music.load('music.mp3')
|
||||
pygame.mixer.music.play(-1) # Параметр -1 означает зацикливание музыки
|
||||
shot_sound = pygame.mixer.Sound('shot.wav')
|
||||
meme_sound = pygame.mixer.Sound("meme_sound.wav")
|
||||
explosion_sound = pygame.mixer.Sound("explosion_sound.wav")
|
||||
stoneexplosion_sound = pygame.mixer.Sound("stoneexplosion_sound.wav")
|
||||
|
||||
# Загрузка изображений
|
||||
background_image = pygame.transform.scale(pygame.image.load("travka_pol.jpeg"), (960, 540))
|
||||
stena = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (100, 100))
|
||||
stenki = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (200, 200))
|
||||
tank_image = pygame.transform.scale(pygame.image.load("ntank-removebg-preview.png"), (PLAYER_WIDTH, PLAYER_HEIGHT))
|
||||
loh_image = pygame.transform.scale(pygame.image.load("loh.png"), (LOH_WIDTH, LOH_HEIGHT))
|
||||
bullet_image = pygame.transform.scale(pygame.image.load("bullet.png"), (BULLET_SIZE, BULLET_SIZE))
|
||||
explosion_images = [pygame.image.load(f"explosion_{i}.png") for i in range(1, 48)]
|
||||
stoneexplosion_images = [pygame.image.load(f"stoneexplosion_{i}.png") for i in range(1, 6)]
|
||||
menu_background = pygame.transform.scale(pygame.image.load("menu_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
|
||||
current_time = pygame.time.get_ticks()
|
||||
|
||||
last_meme_time = 0
|
||||
meme_delay = 2000 # Задержка в миллисекундах (2 секунды)
|
||||
|
||||
class Explosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.image = explosion_images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == 6:
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = explosion_images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Добавление класса для анимации удара о каменную стену
|
||||
class StoneExplosion(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.images = stoneexplosion_images
|
||||
self.image = self.images[0]
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.frame = 0
|
||||
self.last_update = pygame.time.get_ticks()
|
||||
self.frame_rate = 50
|
||||
stoneexplosion_sound.play() # Воспроизведение звука удара о стену
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
|
||||
def update(self):
|
||||
now = pygame.time.get_ticks()
|
||||
if now - self.last_update > self.frame_rate:
|
||||
self.last_update = now
|
||||
self.frame += 1
|
||||
if self.frame == len(self.images):
|
||||
self.kill()
|
||||
else:
|
||||
center = self.rect.center
|
||||
self.image = self.images[self.frame]
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.center = center
|
||||
|
||||
# Определение класса танка
|
||||
class Tank(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = tank_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = -90 # Поворот на 90 градусов против часовой стрелки
|
||||
self.TANK_SPEED = 2
|
||||
self.last_fire_time = pygame.time.get_ticks() # Время последнего выстрела
|
||||
self.boosted = False # Флаг, показывающий, активирован ли ускоритель
|
||||
self.boost_multiplier = 2 # Множитель скорости ускорения
|
||||
|
||||
def update(self):
|
||||
keys = pygame.key.get_pressed()
|
||||
if keys[pygame.K_w]:
|
||||
self.move_forward()
|
||||
mouse_pos = pygame.mouse.get_pos()
|
||||
self.angle = math.degrees(math.atan2(mouse_pos[1] - self.rect.centery, mouse_pos[0] - self.rect.centerx)) + 90
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
if keys[pygame.K_x]:
|
||||
if not self.boosted:
|
||||
self.TANK_SPEED *= self.boost_multiplier
|
||||
self.boosted = True
|
||||
else:
|
||||
if self.boosted:
|
||||
self.TANK_SPEED /= self.boost_multiplier
|
||||
self.boosted = False
|
||||
|
||||
def move_forward(self):
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += self.TANK_SPEED * math.cos(angle_rad)
|
||||
self.rect.y += self.TANK_SPEED * math.sin(angle_rad)
|
||||
|
||||
def shoot(self):
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_fire_time > FIRE_DELAY: # Проверка задержки между выстрелами
|
||||
shot_sound.play() # Воспроизведение звука выстрела
|
||||
# Коррекция угла вылета пули, чтобы она вылетала из дула танка
|
||||
offset_angle = -90 # Угол смещения для вылета пули из дула
|
||||
corrected_angle = self.angle + offset_angle
|
||||
|
||||
# Вычисляем координаты дула танка
|
||||
offset_x = 70 * math.cos(math.radians(corrected_angle))
|
||||
offset_y = 70 * math.sin(math.radians(corrected_angle))
|
||||
bullet = PlayerBullet(self.rect.centerx + offset_x, self.rect.centery + offset_y, self.angle + 270)
|
||||
all_sprites.add(bullet)
|
||||
bullets.add(bullet)
|
||||
self.last_fire_time = current_time # Обновление времени последнего выстрела
|
||||
|
||||
# Проверяем столкновение пули с каменными стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука столкновения с каменной стеной
|
||||
explosion = StoneExplosion(bullet.rect.centerx, bullet.rect.centery) # Создание анимации удара о стену
|
||||
all_sprites.add(explosion) # Добавление анимации удара о стену в группу спрайтов
|
||||
bullet.kill() # Удаление пули
|
||||
|
||||
class PlayerBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса снаряда бота
|
||||
class BotBullet(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, angle):
|
||||
super().__init__()
|
||||
self.original_image = bullet_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = angle
|
||||
|
||||
def update(self):
|
||||
self.rect.x += BULLET_SPEED * math.cos(math.radians(self.angle))
|
||||
self.rect.y += BULLET_SPEED * math.sin(math.radians(self.angle))
|
||||
if not screen.get_rect().colliderect(self.rect):
|
||||
self.kill()
|
||||
if pygame.sprite.spritecollideany(self, walls):
|
||||
self.kill() # Удаляем снаряд, если он столкнулся со стеной
|
||||
|
||||
|
||||
# Определение класса для бота
|
||||
class Bot(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y):
|
||||
super().__init__()
|
||||
self.original_image = loh_image
|
||||
self.image = self.original_image
|
||||
self.rect = self.image.get_rect(center=(x, y))
|
||||
self.angle = 0 # Угол поворота бота
|
||||
self.speed = BOT_SPEED # Скорость бота
|
||||
|
||||
def update(self):
|
||||
# Находим координаты игрока
|
||||
player_x, player_y = player.rect.center
|
||||
|
||||
# Вычисляем угол к игроку
|
||||
dx = player_x - self.rect.centerx
|
||||
dy = player_y - self.rect.centery
|
||||
self.angle = math.degrees(math.atan2(dy, dx)) + 90
|
||||
|
||||
# Поворачиваем изображение бота
|
||||
self.image = pygame.transform.rotate(self.original_image, -self.angle)
|
||||
self.rect = self.image.get_rect(center=self.rect.center)
|
||||
|
||||
# Двигаем бота в направлении игрока
|
||||
angle_rad = math.radians(self.angle + 270)
|
||||
self.rect.x += self.speed * math.cos(angle_rad)
|
||||
self.rect.y += self.speed * math.sin(angle_rad)
|
||||
|
||||
# Проверяем, не выходит ли бот за границы экрана
|
||||
self.check_bounds()
|
||||
|
||||
# Проверяем столкновения с другими ботами
|
||||
self.check_bot_collisions()
|
||||
|
||||
def check_bounds(self):
|
||||
# Проверка выхода за границы экрана
|
||||
if self.rect.left < 0:
|
||||
self.rect.left = 0
|
||||
elif self.rect.right > SCREEN_WIDTH:
|
||||
self.rect.right = SCREEN_WIDTH
|
||||
if self.rect.top < 0:
|
||||
self.rect.top = 0
|
||||
elif self.rect.bottom > SCREEN_HEIGHT:
|
||||
self.rect.bottom = SCREEN_HEIGHT
|
||||
|
||||
def check_bot_collisions(self):
|
||||
# Проверяем столкновения с другими ботами
|
||||
for bot in tanks:
|
||||
if bot != self:
|
||||
# Проверяем расстояние между ботами
|
||||
distance = math.sqrt(
|
||||
(self.rect.centerx - bot.rect.centerx) ** 2 + (self.rect.centery - bot.rect.centery) ** 2)
|
||||
min_distance = 100 # Минимальное допустимое расстояние между ботами
|
||||
if distance < min_distance:
|
||||
# Если боты слишком близко, переместим текущий бот подальше от другого бота
|
||||
dx = self.rect.centerx - bot.rect.centerx
|
||||
dy = self.rect.centery - bot.rect.centery
|
||||
self.rect.x += dx / distance * min_distance / 2
|
||||
self.rect.y += dy / distance * min_distance / 2
|
||||
|
||||
|
||||
|
||||
class Wall(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, image):
|
||||
super().__init__()
|
||||
self.image = image
|
||||
self.rect = self.image.get_rect(topleft=(x, y))
|
||||
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
walls = pygame.sprite.Group() # Группа для всех стен
|
||||
|
||||
# Создание стен
|
||||
wall_positions = [
|
||||
(360, 40), (460, 730), (460, 830), (460, 930),
|
||||
(960, 40), (960, 140), (960, 240),
|
||||
(660, 240),
|
||||
(960, 440), (960, 540), (960, 640), (960, 740),
|
||||
(1260, 740), (1360, 740), (1460, 740), (1560, 740), (1660, 740),
|
||||
(360, 240), (360, 340), (360, 440),
|
||||
(0, 540), (60, 540), (260, 540), (360, 540), (460, 540),
|
||||
(560, 540), (660, 540), (760, 540), (860, 540),
|
||||
(1160, 240), (1260, 240), (1360, 240), (1460, 240), (1460, 340),
|
||||
(1760, 340), (1860, 340)
|
||||
]
|
||||
|
||||
for pos in wall_positions:
|
||||
wall = Wall(*pos, stena)
|
||||
all_sprites.add(wall)
|
||||
walls.add(wall)
|
||||
|
||||
# Создание стен "stenki"
|
||||
wall_stenki_positions = [
|
||||
(-150, 0), (-150, 200), (-150, 400), (-150, 600), (-150, 800), (-150, 1000),
|
||||
(0, -150), (200, -150), (400, -150), (600, -150), (800, -150), (1000, -150),
|
||||
(1200, -150), (1400, -150), (1600, -150), (1800, -150), (1870, 0), (1870, 200),
|
||||
(1870, 400), (1870, 600), (1870, 800), (1870, 1000), (0, 1030), (200, 1030),
|
||||
(400, 1030), (600, 1030), (800, 1030), (1000, 1030), (1200, 1030), (1400, 1030),
|
||||
(1600, 1030), (1800, 1030)
|
||||
]
|
||||
|
||||
for pos in wall_stenki_positions:
|
||||
wall_stenki = Wall(*pos, stenki)
|
||||
all_sprites.add(wall_stenki)
|
||||
walls.add(wall_stenki)
|
||||
|
||||
# Создание групп спрайтов
|
||||
all_sprites = pygame.sprite.Group()
|
||||
tanks = pygame.sprite.Group()
|
||||
bullets = pygame.sprite.Group()
|
||||
|
||||
# Создание игрока
|
||||
player = Tank(SCREEN_WIDTH // 8, SCREEN_HEIGHT // 7)
|
||||
all_sprites.add(player)
|
||||
tanks.add(player)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
|
||||
all_sprites.add(bot)
|
||||
tanks.add(bot)
|
||||
|
||||
|
||||
def draw_menu():
|
||||
screen.blit(menu_background, (0, 0))
|
||||
font = pygame.font.Font(None, 50)
|
||||
|
||||
# Рисуем кнопку "Старт"
|
||||
start_text = font.render("Start", True, WHITE)
|
||||
start_rect = start_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 100))
|
||||
screen.blit(start_text, start_rect)
|
||||
|
||||
# Рисуем кнопку "Настройки"
|
||||
settings_text = font.render("Settings", True, WHITE)
|
||||
settings_rect = settings_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
|
||||
screen.blit(settings_text, settings_rect)
|
||||
|
||||
# Рисуем кнопку "Выйти"
|
||||
quit_text = font.render("Quit", True, WHITE)
|
||||
quit_rect = quit_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 100))
|
||||
screen.blit(quit_text, quit_rect)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
return start_rect, settings_rect, quit_rect
|
||||
|
||||
|
||||
def respawn_bot():
|
||||
# Создание нового экземпляра бота
|
||||
new_bot = Bot(random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
|
||||
all_sprites.add(new_bot)
|
||||
tanks.add(new_bot)
|
||||
|
||||
|
||||
|
||||
|
||||
def draw_settings_menu():
|
||||
settings_background = pygame.transform.scale(pygame.image.load("settings_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
screen.blit(settings_background, (0, 0))
|
||||
font = pygame.font.Font(None, 50)
|
||||
|
||||
# Рисуем кнопку "Выйти" в правом верхнем углу
|
||||
quit_text = font.render("Quit", True, WHITE)
|
||||
quit_rect = quit_text.get_rect(topright=(SCREEN_WIDTH - 20, 20))
|
||||
screen.blit(quit_text, quit_rect)
|
||||
|
||||
# Рисуем кнопку для управления музыкой
|
||||
if pygame.mixer.music.get_busy():
|
||||
music_text = font.render("Music On", True, WHITE)
|
||||
else:
|
||||
music_text = font.render("Music Off", True, WHITE)
|
||||
music_rect = music_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 100))
|
||||
screen.blit(music_text, music_rect)
|
||||
|
||||
pygame.display.flip()
|
||||
|
||||
return quit_rect, music_rect
|
||||
|
||||
|
||||
|
||||
# Главный цикл программы
|
||||
menu_active = True
|
||||
settings_active = False # Флаг, показывающий, активно ли меню настроек
|
||||
|
||||
while menu_active:
|
||||
if not settings_active:
|
||||
start_rect, settings_rect, quit_rect = draw_menu()
|
||||
else:
|
||||
quit_rect, music_rect = draw_settings_menu()
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # Левая кнопка мыши
|
||||
if not settings_active:
|
||||
if start_rect.collidepoint(event.pos):
|
||||
menu_active = False # Нажата кнопка "Старт"
|
||||
elif settings_rect.collidepoint(event.pos):
|
||||
settings_active = True # Нажата кнопка "Настройки"
|
||||
elif quit_rect.collidepoint(event.pos):
|
||||
pygame.quit()
|
||||
quit()
|
||||
else:
|
||||
if quit_rect.collidepoint(event.pos):
|
||||
settings_active = False
|
||||
elif music_rect.collidepoint(event.pos):
|
||||
if pygame.mixer.music.get_busy():
|
||||
pygame.mixer.music.stop() # Выключение музыки
|
||||
else:
|
||||
pygame.mixer.music.play(-1) # Включение музыки
|
||||
|
||||
|
||||
# Основной игровой цикл
|
||||
clock = pygame.time.Clock()
|
||||
running = True
|
||||
paused = False # Track pause state
|
||||
while running:
|
||||
# Handle events
|
||||
current_time = pygame.time.get_ticks()
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
|
||||
# Handle left mouse button click
|
||||
if not paused:
|
||||
player.shoot()
|
||||
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_k:
|
||||
if current_time - last_meme_time > meme_delay: # Проверка задержки
|
||||
meme_sound.play()
|
||||
last_meme_time = current_time # Обновление времени последнего воспроизведения звука
|
||||
elif event.key == pygame.K_ESCAPE:
|
||||
if not menu_active: # Если меню неактивно, то активируем его
|
||||
menu_active = True
|
||||
settings_active = False # При этом настройки неактивны
|
||||
else: # Если меню уже активно, то деактивируем его
|
||||
menu_active = False
|
||||
settings_active = False
|
||||
all_sprites.update()
|
||||
|
||||
if not paused: # If not paused, update game state
|
||||
# Update sprites
|
||||
all_sprites.update()
|
||||
|
||||
# Проверка столкновений пуль с танками
|
||||
for bullet in bullets:
|
||||
if isinstance(bullet, PlayerBullet):
|
||||
tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
|
||||
if tank_hit and isinstance(tank_hit, Bot):
|
||||
explosion_sound.play() # Воспроизведение звука взрыва
|
||||
explosion = Explosion(tank_hit.rect.centerx, tank_hit.rect.centery) # Создание взрыва
|
||||
all_sprites.add(explosion) # Добавление взрыва в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю
|
||||
tank_hit.kill() # Удаляем бота
|
||||
respawn_bot() # Создаем нового бота
|
||||
score += 1
|
||||
|
||||
elif isinstance(bullet, BotBullet):
|
||||
# Проверяем столкновение пули бота с стенами
|
||||
if pygame.sprite.spritecollideany(bullet, walls):
|
||||
stoneexplosion_sound.play() # Воспроизведение звука взрыва камня
|
||||
explosion = Explosion(bullet.rect.centerx, bullet.rect.centery) # Создание взрыва камня
|
||||
all_sprites.add(explosion) # Добавление взрыва камня в группу спрайтов
|
||||
bullet.kill() # Удаляем пулю бота
|
||||
|
||||
# Отрисовка фона
|
||||
for i in range(2):
|
||||
for j in range(2):
|
||||
screen.blit(background_image, (i * 960, j * 540))
|
||||
|
||||
all_sprites.draw(screen)
|
||||
screen.blit(stena, (360, 40))
|
||||
|
||||
screen.blit(stena, (460, 730))
|
||||
screen.blit(stena, (460, 830))
|
||||
screen.blit(stena, (460, 930))
|
||||
|
||||
screen.blit(stena, (960, 40))
|
||||
screen.blit(stena, (960, 140))
|
||||
screen.blit(stena, (960, 240))
|
||||
|
||||
screen.blit(stena, (660, 240))
|
||||
|
||||
screen.blit(stena, (960, 440))
|
||||
screen.blit(stena, (960, 540))
|
||||
screen.blit(stena, (960, 640))
|
||||
screen.blit(stena, (960, 740))
|
||||
|
||||
screen.blit(stena, (1260, 740))
|
||||
screen.blit(stena, (1360, 740))
|
||||
screen.blit(stena, (1460, 740))
|
||||
screen.blit(stena, (1560, 740))
|
||||
screen.blit(stena, (1660, 740))
|
||||
|
||||
screen.blit(stena, (360, 240))
|
||||
screen.blit(stena, (360, 340))
|
||||
screen.blit(stena, (360, 440))
|
||||
|
||||
screen.blit(stena, (0, 540))
|
||||
screen.blit(stena, (60, 540))
|
||||
screen.blit(stena, (260, 540))
|
||||
screen.blit(stena, (360, 540))
|
||||
screen.blit(stena, (460, 540))
|
||||
screen.blit(stena, (560, 540))
|
||||
screen.blit(stena, (660, 540))
|
||||
screen.blit(stena, (760, 540))
|
||||
screen.blit(stena, (860, 540))
|
||||
|
||||
screen.blit(stena, (1160, 240))
|
||||
screen.blit(stena, (1260, 240))
|
||||
screen.blit(stena, (1360, 240))
|
||||
screen.blit(stena, (1460, 240))
|
||||
screen.blit(stena, (1460, 340))
|
||||
screen.blit(stena, (1760, 340))
|
||||
screen.blit(stena, (1860, 340))
|
||||
|
||||
screen.blit(stenki, (-150, 0))
|
||||
screen.blit(stenki, (-150, 200))
|
||||
screen.blit(stenki, (-150, 400))
|
||||
screen.blit(stenki, (-150, 600))
|
||||
screen.blit(stenki, (-150, 800))
|
||||
screen.blit(stenki, (-150, 1000))
|
||||
screen.blit(stenki, (0, -150))
|
||||
screen.blit(stenki, (200, -150))
|
||||
screen.blit(stenki, (400, -150))
|
||||
screen.blit(stenki, (600, -150))
|
||||
screen.blit(stenki, (800, -150))
|
||||
screen.blit(stenki, (1000, -150))
|
||||
screen.blit(stenki, (1200, -150))
|
||||
screen.blit(stenki, (1400, -150))
|
||||
screen.blit(stenki, (1600, -150))
|
||||
screen.blit(stenki, (1800, -150))
|
||||
screen.blit(stenki, (1870, 0))
|
||||
screen.blit(stenki, (1870, 200))
|
||||
screen.blit(stenki, (1870, 400))
|
||||
screen.blit(stenki, (1870, 600))
|
||||
screen.blit(stenki, (1870, 800))
|
||||
screen.blit(stenki, (1870, 1000))
|
||||
screen.blit(stenki, (0, 1030))
|
||||
screen.blit(stenki, (200, 1030))
|
||||
screen.blit(stenki, (400, 1030))
|
||||
screen.blit(stenki, (600, 1030))
|
||||
screen.blit(stenki, (800, 1030))
|
||||
screen.blit(stenki, (1000, 1030))
|
||||
screen.blit(stenki, (1200, 1030))
|
||||
screen.blit(stenki, (1400, 1030))
|
||||
screen.blit(stenki, (1600, 1030))
|
||||
screen.blit(stenki, (1800, 1030))
|
||||
|
||||
font = pygame.font.Font(None, 36)
|
||||
score_text = font.render(f'Score: {score}', True, WHITE)
|
||||
screen.blit(score_text, (10, 10))
|
||||
score_rect = score_text.get_rect(topleft=(10, 10))
|
||||
pygame.draw.rect(screen, (0, 255, 0), (
|
||||
score_rect.topleft, (score_rect.width, score_rect.height))) # Draw a green rectangle behind the score
|
||||
screen.blit(score_text, score_rect.topleft)
|
||||
pygame.display.flip()
|
||||
clock.tick(FPS)
|
||||
|
||||
# Завершение работы Pygame
|
||||
pygame.quit()
|