| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 부산광역시
- 대한민국
- LDA
- 사회
- Latent Dirichlet Allocation
- 헌법
- 고통에
- 한미관세협상
- 과학의과학
- 만들기
- 글쓰기
- 지속가능한도시
- 점프
- 응답하는
- 다정한것이살아남는다
- 연구하며
- python
- 파이썬
- 공부
- 정치
- 네트워크
- 파이게임
- 인사청문회
- 연구하며글쓰기
- 공간밀도
- pygame
- 사회면
- 맵
- 주요일간지
- 타인의
- Today
- Total
RoNS 님의 블로그
[Pygame(파이게임)] 가시 함정 생성 본문
이번 글에서는 이전 글의 마지막에 이야기했듯이 맵을 게임 실행 전에 완성(로딩)을 하도록 만들고,
드디어 플레이어를 방해할 수 있는 첫번째 요소로 가시 함정을 추가 할 것이다.
이전 글에서는 평면 상태의 땅만 게임창에 보이게 하여서, 조금 심심해 보이기도 했었다.

같은 높이의 땅이더라도,
왼쪽의 땅이 한칸 더 낮다면, 땅의 왼쪽 모서리가 둥글게,
오른쪽의 땅이 한칸 더 낮다면, 땅의 오른쪽 모서리가 둥글게~
만들어주기 위하여
"왼쪽 모서리가 둥근 땅", "오른쪽 모서리가 둥근 땅" 그리고 원래의 "평면 땅"을 세가지 타입으로 나누어, 각각 다른 확률로 나타나게 하면 된다. ( [Pygame(파이게임)] 게임 맵 랜덤 생성 에서 확률적으로 맵을 생성하는 것은 설명했다.)
new_P = np.array([
#-5 #-4 #-3 #-2 #-1 #0 #1 #2 #3 #4
#깊이 -5 #최대 깊이(점프 거리 고려) 다음 생성은 무조건 깊이 0 땅
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
#깊이 -4 #한칸 아래 or 땅
[0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
#깊이 -3 #한칸 아래 or 땅
[0.0, 0.0, 0.0, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
#깊이 -2 #한칸 아래 or 땅
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
#깊이 -1 #한칸 아래 or 땅
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
#깊이 0
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.2, 0.2, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.2, 0.2, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
#깊이 1
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.2, 0.2, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.2, 0.2, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.3, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
#깊이 2
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.2, 0.2, 0.0, 0.0, 0.1, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.2, 0.2, 0.0, 0.0, 0.1, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.1, 0.1, 0.0, 0.3, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
#깊이 3
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.3, 0.2, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.3, 0.2, 0.0, 0.0,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.1, 0.1, 0.0, 0.3, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,],
#깊이 4
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.7, 0.3,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.7, 0.3,],
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.0, 0.1, 0.1, 0.0, 0.3, 0.2, 0.0, 0.0, 0.0,],
])
땅을 세가지의 타입으로 만드니, 게임에서 맵의 깊이를 10가지로 밖에 나누지 않았음에도, 행렬의 크기가 어마무시하다..
코드를 통해, 맵이 적절하게 나올지를 우선 파이썬의 scatter함수로 그렸다.

5 이하는 화면상에서는 보이지 않는 낭떠러지이고,
파란색은 왼쪽으로 둥근 땅, 주황색은 평면, 초록색은 오른쪽으로 둥근 땅이다. 적절하게 잘 계산 된 것 같다!
그 다음은 이제 "가시 함정"이다.
가시는 넘파이의 랜덤 확률(30%)로 나타나게 하고, 위 맵에서 왼쪽으로 둥근 땅 일 때, 오른쪽으로 둥근 땅 일 때는 삭제하였다.
(맵을 미리 만들기 때문에, 가시 함정도 맵의 총 길이 만큼 나타날 곳을 미리 모두 계산해 두었다.)
또, 캐릭터가 가시 함정을 밟으면 데미지/게임오버가 되어야 한다.
pygame에서는 colliderect 함수를 통해, 그린 그림의 영역과 닿았는지를 확인 할 수 있는 기능이 있지만,
현재는 가시의 그림을 배경 그림과 한번에 그려서 렉을 줄이는게 우선 목표이기 때문에 다른 방법을 이용한다.
가시 또한 맵처럼 그래프로 그려서 플레이어가 이 그래프의 위치에 닿게 된다면!
게임오버가 되도록 한다.

파란 선이 맵, 주황색 선이 가시에 대한 그래프이다. 플레이어는 파란 선 위로 이동하다가, 주황선에 몸이 닿게 되면 게임오버가 된다.
아래는 현재까지의 과정과 맵을 미리 만드는 과정의 전체 코드이다.
np.random.seed(seed_v)
## 가시함정의 위치 랜덤으로 만들기
is_spike = np.random.random(map_length)
is_spike[is_spike>0.7] = 1 # 30% 확률로 생성
is_spike[is_spike!=1] = 0 # 나머지 70%는 빈 땅
is_spike[m_type==0] = 0 # 모서리가 둥근땅이면 삭제1
is_spike[m_type==2] = 0 # 모서리가 둥근땅이면 삭제2
is_spike[0:5] = [0,0,0,0,0] #시작지점은 가시 삭제
## (물리적인) 가시함정 위치 계산하기
m_spike = (m_ground-30) * np.repeat(is_spike,50)
m_spike[m_spike==0] = 800
for i in list(range(0,2*5))+list(range(7*5,10*5)):
m_spike[np.array(np.where(is_spike))*50 + i] = 800
## 모든 맵에 대한 지형지물, 가시, 배경 조립하기 (map_length길이만큼)
map_v=[]
for i in range(map_length):
# 가시 있으면
if is_spike[i]:
sp = np.hstack([sky_block, spike_block])
# 돌,풀 등 지형지물 있으면
elif is_backgorund_block[i]:
sp = background_blocks[is_backgorund_block[i]]
# 아무것도 없음
else:
sp = np.hstack([sky_block,sky_block])
#아래 블록~위 블록 조립하기
map_v.append(np.hstack((
np.hstack([sky_block for i in range(17-m_deep[i]-2)]),
sp,
map_RGB[m_type[i],0], map_RGB[m_type[i],1], map_RGB[m_type[i],2],
np.hstack([map_RGB[1,2] for i in range(m_deep[i])]) )))
#왼쪽 블록~ 오른쪽 블록 조립하기
long_map = np.vstack(map_v)
(만들어둔 맵, 가시, 지형지물을 합치는 코드에서 np.hstack과 np.vstack이 아주 중요하게 쓰였다.)
아래는 플레이 화면이다.
동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.
저번 글에서 말한 멈추는 렉이 사라지고, 모두 직각이던 맵이 조금은 부드러워졌다.
또, 가시 역시 잘 작동한다
'Pygame' 카테고리의 다른 글
| [Pygame(파이게임)] 넘파이 행렬 맵 생성 (29) | 2025.07.23 |
|---|---|
| [Pygame(파이게임)] 게임 맵 랜덤 생성 (1) | 2025.06.04 |
| [Pygame(파이게임)] 캐릭터와 맵 적용 (0) | 2025.05.15 |
| [Pygame(파이게임)] 그림판 (0) | 2025.05.07 |
| [Pygame(파이게임)] 플레이어 움직이기3 (점프 강약 만들기) (0) | 2025.04.30 |