import pygame import sys import math # 초기화 및 화면 설정 pygame.init() WIDTH, HEIGHT = 800, 600 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("모바일 RPG 칼 싸움 게임") clock = pygame.time.Clock() # 색상 정의 WHITE = (255, 255, 255) BLUE = (0, 102, 204) # 플레이어 RED = (204, 0, 0) # 적 YELLOW = (255, 204, 0) # 칼 효과 및 버튼 GRAY = (50, 50, 50) UI_ALPHA = (255, 255, 255, 100) # 가상 조이스틱 클래스 class Joystick: def __init__(self, x, y, radius): self.base_x = x self.base_y = y self.radius = radius self.handle_x = x self.handle_y = y self.handle_radius = radius // 2 self.is_dragging = False self.vector_x = 0.0 self.vector_y = 0.0 def handle_event(self, event): if event.type == pygame.MOUSEBUTTONDOWN or event.type == pygame.FINGERDOWN: pos = event.pos if hasattr(event, 'pos') else (event.x * WIDTH, event.y * HEIGHT) dist = math.hypot(pos[0] - self.base_x, pos[1] - self.base_y) if dist <= self.radius: self.is_dragging = True elif event.type == pygame.MOUSEBUTTONUP or event.type == pygame.FINGERUP: self.is_dragging = False self.handle_x = self.base_x self.handle_y = self.base_y self.vector_x = 0.0 self.vector_y = 0.0 elif (event.type == pygame.MOUSEMOTION or event.type == pygame.FINGERMOTION) and self.is_dragging: pos = event.pos if hasattr(event, 'pos') else (event.x * WIDTH, event.y * HEIGHT) dx = pos[0] - self.base_x dy = pos[1] - self.base_y dist = math.hypot(dx, dy) if dist > self.radius: dx = (dx / dist) * self.radius dy = (dy / dist) * self.radius self.handle_x = self.base_x + dx self.handle_y = self.base_y + dy self.vector_x = dx / self.radius self.vector_y = dy / self.radius def draw(self, surface): # 조이스틱 배경 베이스 pygame.draw.circle(surface, (200, 200, 200), (self.base_x, self.base_y), self.radius, 3) # 조이스틱 손잡이 pygame.draw.circle(surface, (255, 255, 255), (int(self.handle_x), int(self.handle_y)), self.handle_radius) # 공격 버튼 클래스 class AttackButton: def __init__(self, x, y, radius): self.x = x self.y = y self.radius = radius def is_touched(self, pos): dist = math.hypot(pos[0] - self.x, pos[1] - self.y) return dist <= self.radius def draw(self, surface): pygame.draw.circle(surface, YELLOW, (self.x, self.y), self.radius) # 버튼 텍스트 font = pygame.font.SysFont(None, 24) text = font.render("ATTACK", True, (0, 0, 0)) surface.blit(text, (self.x - 28, self.y - 8)) # 캐릭터 클래스 class Character: def __init__(self, x, y, color): self.x = x self.y = y self.radius = 20 self.color = color self.hp = 100 self.speed = 4 self.is_attacking = False self.attack_timer = 0 self.angle = 0 # 라디안 단위 방향각 self.attack_rect = pygame.Rect(0, 0, 0, 0) def move(self, vx, vy): if vx != 0 or vy != 0: self.x += vx * self.speed self.y += vy * self.speed self.angle = math.atan2(vy, vx) def attack(self): if not self.is_attacking: self.is_attacking = True self.attack_timer = 12 def update(self): if self.is_attacking: self.attack_timer -= 1 if self.attack_timer <= 0: self.is_attacking = False def draw(self, surface): # 캐릭터 본체 (원형) pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius) # 칼 공격 이펙트 (부채꼴/원호 형태) if self.is_attacking: sword_length = 50 end_x = self.x + math.cos(self.angle) * sword_length end_y = self.y + math.sin(self.angle) * sword_length pygame.draw.line(surface, YELLOW, (self.x, self.y), (end_x, end_y), 10) # 체력바 pygame.draw.rect(surface, RED, (self.x - 20, self.y - 30, 40, 5)) pygame.draw.rect(surface, (0, 255, 0), (self.x - 20, self.y - 30, 40 * (max(0, self.hp) / 100), 5)) # UI 객체 생성 joystick = Joystick(120, HEIGHT - 120, 60) attack_btn = AttackButton(WIDTH - 100, HEIGHT - 100, 40) # 캐릭터 생성 player = Character(200, 300, BLUE) enemy = Character(600, 300, RED) hit_cooldown = 0 running = True while running: clock.tick(60) screen.fill(GRAY) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 조이스틱 입력 전달 joystick.handle_event(event) # 공격 버튼 클릭 판정 if event.type == pygame.MOUSEBUTTONDOWN: if attack_btn.is_touched(event.pos): player.attack() # 플레이어 이동 (조이스틱 벡터 사용) player.move(joystick.vector_x, joystick.vector_y) # 단순 적 AI (플레이어를 향해 이동) if enemy.hp > 0: edx = player.x - enemy.x edy = player.y - enemy.y dist = math.hypot(edx, edy) if dist > 30: enemy.move(edx / dist, edy / dist) # 상태 업데이트 player.update() enemy.update() # 공격 피격 판정 (거리 및 각도 기준) if player.is_attacking and enemy.hp > 0 and hit_cooldown == 0: dist_to_enemy = math.hypot(enemy.x - player.x, enemy.y - player.y) if dist_to_enemy <= 60: # 사정거리 내 angle_to_enemy = math.atan2(enemy.y - player.y, enemy.x - player.x) # 공격 방향 각도 차이 확인 angle_diff = abs(player.angle - angle_to_enemy) if angle_diff < 1.0 or angle_diff > (2 * math.pi - 1.0): enemy.hp -= 25 hit_cooldown = 15 if hit_cooldown > 0: hit_cooldown -= 1 # 그리기 player.draw(screen) if enemy.hp > 0: enemy.draw(screen) # 모바일 UI 그리기 (화면 제일 위) joystick.draw(screen) attack_btn.draw(screen) pygame.display.flip() pygame.quit() sys.exit()
Hosted & Compiled with HtmlRunner.com