일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 운석 피하기 게임
- 아무도 없는 숲속에서
- Ai
- 매트로폴리탄
- 운석피하기 게임
- 나는 매트로폴리탄 미술관 경비원입니다.
- Python
- 숨결이 바람이 될 때
- 인생의 해상도
- 타이핑 몬스터
- gymnasium
- 쿠바전통음악
- 어른의 행복은 조용하다
- frozen lake
- 시집
- 부에노비스타 소셜클럽
- 트렌드코리아2025
- 타이핑좀비
- pygame
- Stable diffusion
- 황선엽
- 에르난 디아스
- Gym
- openAI
- 게임개발
- 나는 스물일곱 2등 항해사입니다.
- 타자연습게임
- comfyui
- 고양이발 살인사건
- 단어가 품은 세계
- Today
- Total
스푸79 기록 보관소
운석 피하기 게임 개발(13)- 충돌 시 폭발 효과 만들기 본문
지난 포스트에서는 충돌 시점 파편이 터지는 효과를 넣었다.
이번 포스트는 여러 번 충돌 시
체력(?)이 모두 떨어진 운석이 사라지면서 폭발하는 효과를 넣어보았다.
폭발하는 효과를 넣으니 타격감이 조금 생긴 듯 한 기분이 든다.
나중에 효과음까지 넣으면 좋을 듯 싶다.
충돌 시점 폭발효과는 원을 그리도록 했고
아래 그림처럼 폭발하는 개체의
중심으로부터 원이 무작위로 발생하도록 했다.
폭발하는 효과의 순서가 중요한데
가장 큰 원은 회색으로 그리고
그 위에 원은 빨간색과 노란색, 주황색이 무작위로 그려지도록 했다.
당연히 회색 이외의 원은 크기가 좀 더 작아야한다.
원의 위치도 매번 달라지도록 설정해준다.
폭팔 이후에 바로 사라지는게 아니라
화면에 잔상이 남도록 투명도를 조절하여
천천히 사라지도록 처리하면
꽤 그럴싸한 폭발효과가 완성이 된다.
이번에는 코드를 제법 많이 수정 해야한다.
우선 Util.py 에 이미지의 투명도를 처리하는 staticmethod를 생성한다.
@staticmethod
def set_opacity(surface, opacity):
temp_surface = surface.copy()
temp_surface.set_alpha(opacity)
return temp_surface
코드는 ChatGPT에게 물어봤다. 역시 금방 짜준다.
그리고 staticmethod를 하나 더 추가할 건데, 이미지를 다른 색으로 변경하는 메소드를 추가한다.
#@staticmethod
def transfer_color(image, new_color):
new_image = pygame.Surface(image.get_size(), pygame.SRCALPHA)
for x in range(image.get_width()):
for y in range(image.get_height()):
pixel_color = image.get_at((x, y))
if pixel_color.a >= 255:
new_image.set_at((x, y), new_color)
else:
new_image.set_at((x, y), (0, 0, 0, 0))
return new_image
나는 회색으로 된 원을 하나만 만들었다.
그리고 해당 원을 색깔을 transfer_color 메서드로 붉은색, 주황색, 노란색 이미지를 만들 것이다.
import pygame
from util import Util
from enviroment import Enviroment as env
class Resources:
def __init__(self):
# .. 중략 ..
self.explosion0 = [] #white explosion
self.explosion1 = [] #red
self.explosion2 = [] #orange
self.explosion3 = [] #yellow
self.render()
def render(self):
# .. (중략) ..
explosion0_image = pygame.image.load(env.GAME_IMG_DIR + "explosion.png").convert_alpha()
explosion1_image = Util.transfer_color(explosion0_image, (255, 0, 0))
explosion2_image = Util.transfer_color(explosion0_image, (255, 165, 0))
explosion3_image = Util.transfer_color(explosion0_image, (255, 255, 0))
for i in range(env.METEOR_SIZE + 1):
self.explosion0.append(Util.resize_image(explosion0_image, i))
self.explosion1.append(Util.resize_image(explosion1_image, i))
self.explosion2.append(Util.resize_image(explosion2_image, i))
self.explosion3.append(Util.resize_image(explosion3_image, i))
resource.py는 꽤나 코드가 길어지고 있다. explosion0, 1, 2, 3으로 색상이 다른 원을 생성한 후, 사이즈 별로
self.explosion 배열에 추가했다.
운석의 사이즈가 다르기 때문에 폭발하는 시점의 생성되는 원의 크기를 다르게 하기 위해
기존에 작성한 resize_image를 재사용했다.
@staticmethod
def resize_image(image, resize_px):
width = image.get_width()
height = image.get_height()
aspect_ratio = width / height
target_width = resize_px
target_height = int(target_width / aspect_ratio)
return pygame.transform.scale(image, (target_width, target_height))
기존에 사용하는 resize_image 를 조금 수정했다.
기존 코드의 경우는 원하는 사이즈를 줄이면서 이미지를 생성하는 거였다.
이렇게 되면 이미지 사이즈가 순차적으로 배열에 담아지지가 않는 문제가 발생한다.
혼자서 아무 생각없이 신나게 강좌용 코드를 개발하다 보니
나중에 운석의 체력 설정이나 무게 설정할 때 이 문제로 상당히 코드가 꼬여있다는 걸 늦게 발견하게 되었다.
이제 대망의 effect.py 코드를 보도록 하자.
Explosion class를 하나 추가한다. update부분은 꽤나 다르게 되어 있은 걸 볼 수 있다.
class Explosion(pygame.sprite.Sprite):
def __init__(self, x, y, max_size, sprites):
pygame.sprite.Sprite.__init__(self)
self.sprites = sprites
self.idx = 0
self.image = sprites[self.idx]
self.rect = self.image.get_rect()
self.pos = (x, y)
self.rect.center = self.pos
self.frame = 0
self.max_size = max_size
self.opacity = 255
def update(self):
if self.idx > len(self.sprites) - 1 or self.idx >= self.max_size:
self.opacity -= 10
self.image = Util.set_opacity(self.image, self.opacity)
if self.opacity <= 0:
self.kill()
else:
self.idx += 2
self.image = self.sprites[self.idx]
self.rect = self.image.get_rect()
self.rect.center = self.pos
idx 값은 원의 크기로 원의 최대 크기는 배열의 끝이 된다.
객체 생성 시 최대 원의 크기를 받는데
이때 배열 끝까지 가거나 최대 크기에 다다르게 되면
set_opacity를 통해 투명도를 변경하게 된다.
이렇게 되면 원의 모양은 화면에 그대로 계속 그려지는데
점검 투명하게 처리가 되다가
opacity값이 0이 되는 시점에 객체는 소멸되도록 처리했다.
def circle_explode(self, x, y, size, cnt):
for _ in range(cnt):
max_size = random.randint(int(size/2), size)
dir = random.randint(0, 359)
theta = math.radians(dir)
r = (size/2) * math.sqrt(random.uniform(0, 1))
tx = x + r * math.cos(theta)
ty = y + r * math.sin(theta)
self.main.effect_sprites.add(Explosion(tx, ty, max_size, getattr(self, "explosion0")))
for _ in range(int(cnt/2)):
max_size = random.randint(int(size/2), size)
dir = random.randint(0, 359)
theta = math.radians(dir)
r = (size/4) * math.sqrt(random.uniform(0, 1))
tx = x + r * math.cos(theta)
ty = y + r * math.sin(theta)
color = random.choice(['1', '2', '3'])
self.main.effect_sprites.add(Explosion(tx, ty, max_size, \
getattr(self, "explosion" + str(color))))
위에서 원을 그리면서 설명한 부분을 구현한 코드이다.
최초에는 밑에 깔리는 회색은 조금 더 크게 그리고
회색 원 위에 덮어지는 원은 조금 더 작게 그려지도록 설정했다.
붉은색, 노란색, 주황색 원의 경우는 random.choice를 통해 그때 그때 색상이 바뀌도록 처리했다.
전체 코드를 아래 첨부한다.
여기 포스트에서 설명하지 않은 변경된 부분이 꽤 있지만
크게 게임에 영향을 주는 요소는 전부 설명한 것 같다.
다음 포스트에서는 게임에 있어서 가장 재미있는 부분인 총알 발사하는 로직을 넣도록 하겠다.
'게임공작소' 카테고리의 다른 글
운석 피하기 게임 개발(15) - 아이템효과(파워업, 방어막) (54) | 2024.10.07 |
---|---|
운석 피하기 게임 개발(14)- 조준 및 총알 발사 (33) | 2024.10.04 |
운석 피하기 게임 개발(12)- 충돌 시 파편 만들기 (25) | 2024.09.22 |
운석 피하기 게임 개발(11)- 충돌처리(3)(Sweep And Prune알고리즘) (29) | 2024.09.18 |
운석 피하기 게임 개발(10)- 충돌 처리(2) (11) | 2024.09.08 |