import pygame
import random
import math
# 게임 초기화
pygame.init()
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("Tower Defense")
clock = pygame.time.Clock()
is_running = True
COIN_START = 200
PLAYER_START_HP = 100
BACKGROUND_COLOR = (0, 0, 0)
WHITE = (255, 255, 255)
FONT = pygame.font.Font(None, 36)
# 클래스 정의
class Tower(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y):
super().__init__()
self.image = pygame.Surface((40, 40))
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect()
self.rect.centerx = pos_x
self.rect.centery = pos_y
self.attack_damage = 20
self.attack_range = 150
self.attack_speed = 1
self.last_attack_time = 0
def attack(self, target):
now = pygame.time.get_ticks()
if now - self.last_attack_time >= 1000 / self.attack_speed:
bullet = Bullet(self.rect.centerx, self.rect.centery, target)
all_sprites.add(bullet)
bullets.add(bullet)
self.last_attack_time = now
class Monster(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y, hp, speed):
super().__init__()
self.image = pygame.Surface((30, 30))
self.image.fill((0, 255, 0))
self.rect = self.image.get_rect()
self.rect.x = pos_x
self.rect.y = pos_y
self.hp = hp
self.max_hp = hp
self.speed = speed
def update(self):
self.rect.x += self.speed
class Bullet(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y, target):
super().__init__()
self.image = pygame.Surface((10, 10))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect()
self.rect.centerx = pos_x
self.rect.centery = pos_y
self.target = target
self.speed = 5
self.damage = 30
def update(self):
angle = math.atan2(self.target.rect.centery - self.rect.centery, self.target.rect.centerx - self.rect.centerx)
self.rect.x += self.speed * math.cos(angle)
self.rect.y += self.speed * math.sin(angle)
if pygame.sprite.collide_rect(self, self.target):
self.target.hp -= self.damage
bullets.remove(self)
all_sprites.remove(self)
class Player:
def __init__(self):
self.coin = COIN_START
self.hp = PLAYER_START_HP
# 게임 객체 초기화
all_sprites = pygame.sprite.Group()
towers = pygame.sprite.Group()
monsters = pygame.sprite.Group()
bullets = pygame.sprite.Group()
player = Player()
# 웨이브 데이터
waves = [
[{"hp": 50, "speed": 1}, {"hp": 80, "speed": 0.8}],
[{"hp": 60, "speed": 1.2}, {"hp": 100, "speed": 1}]
]
wave_index = 0
wave_timer = pygame.time.get_ticks()
# 몬스터 스폰 변수
monster_spawn_interval = 2000
monster_spawn_timer = 0
# 추가 함수
def show_next_wave_prompt():
font = pygame.font.Font(None, 36)
text = font.render("다음 웨이브로 넘어가시겠습니까? (y/n)", True, WHITE)
text_rect = text.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2))
window.blit(text, text_rect)
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
pos = pygame.mouse.get_pos()
if text_rect.collidepoint(pos):
return True, False
elif text_rect.collidepoint(pos):
return False, True
def increase_wave_difficulty(wave):
for monster_data in wave:
monster_data["hp"] += 10
def update_wave():
global wave_index
if wave_index < len(waves):
wave = waves[wave_index]
if show_next_wave_prompt():
wave_index += 1
if wave_index < len(waves):
increase_wave_difficulty(wave)
# 게임 루프
while is_running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
is_running = False
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
pos = pygame.mouse.get_pos()
if player.coin >= 50:
tower = Tower(pos[0], pos[1])
all_sprites.add(tower)
towers.add(tower)
player.coin -= 50
now = pygame.time.get_ticks()
if now - wave_timer >= 5000 and wave_index < len(waves):
wave_timer = now
wave = waves[wave_index]
monster_spawn_timer = now
for monster_data in wave:
monster = Monster(0, WINDOW_HEIGHT // 2, monster_data["hp"], monster_data["speed"])
all_sprites.add(monster)
monsters.add(monster)
monster_spawn_timer += monster_spawn_interval # 몬스터 생성 간격 누적
wave_index += 1
if wave_index >= len(waves):
wave_index = 0
if now - monster_spawn_timer >= monster_spawn_interval and wave_index < len(waves):
monster_data = waves[wave_index][0]
monster = Monster(0, WINDOW_HEIGHT // 2, monster_data["hp"], monster_data["speed"])
all_sprites.add(monster)
monsters.add(monster)
monster_spawn_timer += monster_spawn_interval # 몬스터 생성 간격 누적
for monster in monsters:
monster.update()
for tower in towers:
target = None
for monster in monsters:
if abs(monster.rect.centery - tower.rect.centery) < tower.attack_range and monster.rect.x > tower.rect.x:
if not target or monster.rect.x > target.rect.x:
target = monster
if target:
tower.attack(target)
for bullet in bullets:
bullet.update()
for monster in monsters:
if monster.rect.x >= WINDOW_WIDTH:
player.hp -= 10
monsters.remove(monster)
all_sprites.remove(monster)
if monster.hp <= 0:
player.coin += 20
monsters.remove(monster)
all_sprites.remove(monster)
window.fill(BACKGROUND_COLOR)
all_sprites.draw(window)
for monster in monsters:
hp_text = FONT.render(f"HP: {monster.hp}/{monster.max_hp}", True, WHITE)
window.blit(hp_text, (monster.rect.x, monster.rect.y - 20))
hud_text = FONT.render(f"Coin: {player.coin} HP: {player.hp}", True, WHITE)
window.blit(hud_text, (20, 20))
pygame.display.flip()
clock.tick(60)
if player.hp <= 0:
is_running = False
if len(monsters) == 0:
next_wave, continue_game = show_next_wave_prompt()
if next_wave:
update_wave()
elif continue_game:
pass # 게임 계속 진행
pygame.display.flip()
clock.tick(60)
pygame.quit()