1) 스파르타 파이터 - pygame을 이용한 격투게임 만들기
2) 목적 : 직접 게임을 설계해보고 python을 이용하여 설계한 내용을 구현해봄으로써 설계과 구현에 익숙해지고 python 실력을 향상시키고자 함
3) 진행상황 : 공격준비동작, 타이머, hp게이지, 크리티컬, 넉백 구현, 타격, 수비 이펙트 추가
4) 더 개발할 부분 : 궁극기, 캐릭터 다양화, 공격콤보, 태그매치
class Fighter:
...
damages = [0, 15, 5, 10] # 0, 상단, 중단, 하단 공격 데미지
critical_p = 4 # 크리티컬 확률 = 1/critical_p
critical_d = 2 # 크리티컬 데미지 ( critical_d배)
# 공격 모션
attack_delay = 0.5 # 모션 시간
attack_ticks = 0 # 공격 성공한 시간
attack_temp = 0 # 공격의 종류를 담는 변수
ready_delay = 0.7 # 공격 전 준비동작 시간
# 피격 모션
hit_delay = 0.7 # 피격 당하는 시간
hit_ticks = 0 # 피격 당한 시간
hit_type = 0 # 피격 종류 - 0:피격아님, 1:상단피격, 2:중단피격, 3:하단피격
critical_hit = False # 크리티컬 피격 여부 - True:크리티컬발생, False:크리티컬발생안함
effect_delay = 0.5 # 공격 / 수비 이펙트 지속 시간
effect_bool = False # 수비 이펙트 여부 - True:이펙트나오는중, False:이펙트안나오는중
effect_ticks = 0 # 수비 이펙트 시작 시간
...
# pygame 캐릭터 생성
# images_path : 캐릭터 이지미 경로 / image : 이미지 명
def __init__(self, images_path, image):
...
self.attack_high_ready = pygame.image.load(os.path.join(images_path, 'attack_high_ready.png'))
self.attack_middle_ready = pygame.image.load(os.path.join(images_path, 'attack_middle_ready.png'))
self.attack_low_ready = pygame.image.load(os.path.join(images_path, 'attack_low_ready.png'))
self.attack_effect = pygame.image.load(os.path.join(images_path, 'attack_effect.png'))
self.font = pygame.font.Font(None, 30) # 효과 폰트
self.defend_effect = self.font.render('defend!!', True, (0, 0, 0)) # 수비 성공시 이펙트 메시지
self.critical_effect = self.font.render('critical!!', True, (0, 0, 0)) # 크리티컬시 이펙트 메시지
# 상단/중단/하단 공격
# attack_type : 공격 종류 - 1:상단, 2:중단, 3:하단
# enemy : 적의 캐릭터
def attack(self, attack_type, enemy):
if self.attack_check(attack_type, enemy):
critical = False # 크리티컬 발생 유무
p = random.randint(1, self.critical_p)
if p == 1:
critical = True
if critical:
damage = self.critical_d * self.damages[attack_type]
else:
damage = self.damages[attack_type]
enemy.get_hit(attack_type, critical, damage)
# 캐릭터 그리기
# screen : 화면
# enemy : 적의 캐릭터
# attack_bool : 공격 모션 중인지 여부
# attack_delay : 공격 모션 시간
# attack_ticks : 공격 성공한 시간
# attack_temp : 공격의 종류를 담는 변수
def draw_char(self, screen, enemy):
if self.hit_bool:
# 피격 상태이면 다른 행동 못함
screen.blit(self.hit_img, (self.x_pos, self.y_pos))
hit_time = (pygame.time.get_ticks() - self.hit_ticks) / 1000
if hit_time < self.effect_delay:
if self.hit_type == 1:
screen.blit(self.attack_effect, (self.x_pos + 50 * -1 * self.position, self.y_pos - 50))
if self.critical_hit:
screen.blit(self.critical_effect, (self.x_pos + 50 * -1 * self.position, self.y_pos - 50))
elif self.hit_type == 2:
screen.blit(self.attack_effect,
(self.x_pos + 50 * -1 * self.position, self.y_pos - 50 + self.high_rage))
if self.critical_hit:
screen.blit(self.critical_effect,
(self.x_pos + 50 * -1 * self.position, self.y_pos - 50 + self.high_rage))
elif self.hit_type == 3:
screen.blit(self.attack_effect, (
self.x_pos + 50 * -1 * self.position, self.y_pos - 50 + self.high_rage + self.middle_rage))
if self.critical_hit:
screen.blit(self.critical_effect, (
self.x_pos + 50 * -1 * self.position, self.y_pos - 50 + self.high_rage + self.middle_rage))
if hit_time > self.hit_delay:
self.hit_bool = False
self.hit_ticks = 0
self.critical_hit = False
else:
screen.blit(self.char, (self.x_pos, self.y_pos))
# 공격 그리기
# 수비 중이 아닐 때만 가능
if self.defend_mode == 0:
# 공격 준비 중인지 확인
if self.ready_bool:
# 공격 후 흐른 시간
ready_time = (pygame.time.get_ticks() - self.attack_ticks) / 1000
if ready_time > self.ready_delay:
self.ready_bool = False
self.attack_bool = True
else:
if self.attack_mode == 1:
screen.blit(self.attack_high_ready, (self.x_pos, self.y_pos))
elif self.attack_mode == 2:
screen.blit(self.attack_middle_ready, (self.x_pos, self.y_pos + self.high_rage))
elif self.attack_mode == 3:
screen.blit(self.attack_low_ready,
(self.x_pos, self.y_pos + self.high_rage + self.middle_rage))
# 공격 모션 중인지 확인
if self.attack_bool:
attack_time = (pygame.time.get_ticks() - self.attack_ticks) / 1000 - self.ready_delay
if attack_time > self.attack_delay:
self.attack_mode = 0
self.attack_bool = False
else:
self.attack(self.attack_mode, enemy)
if self.attack_mode == 1:
screen.blit(self.attack_high_img, (self.x_pos + self.vector, self.y_pos))
elif self.attack_mode == 2:
screen.blit(self.attack_middle_img, (self.x_pos + self.vector, self.y_pos + self.high_rage))
elif self.attack_mode == 3:
screen.blit(self.attack_low_img,
(self.x_pos + self.vector, self.y_pos + self.high_rage + self.middle_rage))
# 공겨 준비 중 아니고
# 공격 모션 중 아니면 공격 가능
if not self.ready_bool and not self.attack_bool:
# 최초 공격 버튼 눌렀을 때
if self.attack_temp != 0:
self.attack_ticks = pygame.time.get_ticks()
self.attack_mode = self.attack_temp
self.ready_bool = True
# 수비 그리기
# 공격 중이 아닐 때, 점프 중이 아닐 때만 가능
elif self.attack_mode == 0 and self.defend_mode != 0:
if self.defend_mode == 1:
screen.blit(self.defend_high_img, (self.x_pos, self.y_pos))
elif self.defend_mode == 2:
screen.blit(self.defend_middle_img, (self.x_pos, self.y_pos + self.high_rage))
elif self.defend_mode == 3:
screen.blit(self.defend_low_img, (self.x_pos, self.y_pos + self.high_rage + self.middle_rage))
if self.effect_bool:
defend_time = (pygame.time.get_ticks() - self.effect_ticks) / 1000
if defend_time < self.effect_delay:
if self.defend_mode == 1:
screen.blit(self.defend_effect, (self.x_pos + 50 * -1 * self.position, self.y_pos - 20))
elif self.defend_mode == 2:
screen.blit(self.defend_effect,
(self.x_pos + 50 * -1 * self.position, self.y_pos + self.high_rage + 20))
elif self.defend_mode == 3:
screen.blit(self.defend_effect,
(self.x_pos + 50 * -1 * self.position,
self.y_pos + self.high_rage + self.middle_rage - 10))
else:
self.effect_bool = False
self.effect_ticks = 0
# 타이머
elapsed_time = (pygame.time.get_ticks() - start_ticks) / 1000
current_time = int(total_time - elapsed_time)
if current_time < 10:
time_text = '0' + str(current_time)
timer = game_font.render(time_text, True, (255, 0, 0))
else:
time_text = str(current_time)
timer = game_font.render(time_text, True, (0, 0, 0))
screen.blit(timer, (460, 45))
# 타임 아웃 시 체력이 더 많은 캐릭터가 승리, 체력이 같으면 무승부
if total_time - elapsed_time <= 0:
if a.hp > b.hp:
winner = a.name
elif b.hp > a.hp:
winner = b.name
else:
winner = 0
if winner == 0:
game_result = f'Time out - Draw'
else:
game_result = f'Time out - Winner {winner}'
running = False
# 체력바 그리기
screen.blit(hp_bar, (50, 50))
screen.blit(hp_bar, (550, 50))
if a.hp > 0:
a_hp_width = a.hp / 100 * 400
a_hp_x_pos = 450 - a_hp_width
while a_hp_width > 0:
a_hp_width -= 20
if a.hp > 30:
screen.blit(hp_point, (a_hp_x_pos, 50))
else:
screen.blit(hp_point_red, (a_hp_x_pos, 50))
a_hp_x_pos += 20
if b.hp > 0:
b_hp_width = b.hp / 100 * 400
b_hp_x_pos = 550
while b_hp_width > 0:
b_hp_width -= 20
if b.hp > 30:
screen.blit(hp_point, (b_hp_x_pos, 50))
else:
screen.blit(hp_point_red, (b_hp_x_pos, 50))
b_hp_x_pos += 20
와.... 진짜 잘해주셨네요
해당 기능을 함수 단위로 한번 더 짜보시는 것도 해보세요!