https://jubrodev.tistory.com/3
지난 시간에는 총알 구현과 UI 표시를 하였다.
오늘은 이제 적을 구현해볼거다!
난수생성 랜덤함수 - rand(), srand(), time()
오늘 중점적으로 이용할 함수는 rand()함수 이다.
rand함수란?
0 부터 RAND_MAX사이의 정수를 반환해준다.
RAND_MAX는 stdio.h에 정의된 상수이다.
하지만 rand함수는 프로그램이 생성됨과 동시에 정해져 있어서 프로그램을 몇번 실행하더라도 똑같은 랜덤값을 낸다
이게 무슨 랜덤함수냐!!
보시다싶이 랜덤값들이 나오긴했는데 첫번째 실행하던 두번째 실행하던 다 똑같다.
그래서 필요한 srand함수!
#include<stdlib,h> 헤더파일이 필요하고
srand(unsigned int seed) 형태이다.
srand()함수는 rand()함수의 시드값을 초기화해줘서 매번 다른 값의 난수를 생성할 수 있다.
그리고 통상적으로 시간을 받아와서 난수를 생성한다.
여기서 필요한게 time()함수이다.
time 함수는 <time.h> 헤더파일을 필요로 하고,
말 그래도 시간을 불러 올 수 있는 함수입니다.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
// 랜덤 시드 생성으로 rand 함수 초기화
srand(time(NULL));
// 랜덤함수 - 난수생성
int randomNumber = rand();
printf("Random number: %d\n", randomNumber);
return 0;
}
그래서 위 세 함수를 합쳐서, 난수생성 랜덤 변수 생성함수는 일반적으로 다음과 같이 쓴다.
실제로 해봐도 두 결과가 다르게 나온다!!
+내가 0부터 일정 수준까지의 수만 랜덤 생성하고 싶으면
rand()%100+1
// 100으로 나눈 나머지 +1
//1부터 100까지의 수 랜덤생성
나누기의 나머지 연산자인 % 를 사용하여 응용하면 된다.
자세한 예제는 아래 코드를 통해서~
적 생성 코드
서론이 너무 길었고 이제 코드로 오자
typedef struct bullet {
int x, y;
bool Active;
}Bullet;
Bullet Bullet_info[MAXBULLET];
Bullet Enemy[10];
Bullet Enemy_Bullet[MAXBULLET];
일단 적의 위치, 생성 정보를 담을 구조체를 선언해준다.
귀찮아서 저번 총알 구조체를 그대로 사용했다 ㅎㅎ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void Enemy_Create(Bullet* Enemy, int count) {
int a = rand() % 60 + 10;
int b = rand() % 10 + 5;
if(count%200==0){
Enemy[i_index].x = a;
Enemy[i_index].y = b;
Enemy[i_index].Active = TRUE;
i_index++;
}
for(int i=0; i<10; i++){
if (Enemy[i].Active)
mapData[Enemy[i].y * Map_X_MAX + Enemy[i].x - 1] = '@';
}
}
|
cs |
일단 적을 생성하는 코드를 짠다.
화면 위쪽 부분에서 랜덤위치에서 생성하고,
main 함수에서 한 루프당 count++을 하고 있는데,
한 루프가 Sleep(50) 즉 50ms 여서 200회 반복, 즉 10초가 지나면 적을 한마리씩 더 생성하는 코드이다.
적 이동 코드
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
|
void Enemy_Move(Bullet* Enemy) {
for (int i = 0; i < 10; i++) {
if (Enemy[i].Active == FALSE) {
continue;
}
else {
if (Enemy[i].x <= 0)Enemy[i].x++;
else if (Enemy[i].x >= 80)Enemy[i].x--;
else if (Enemy[i].y <= 0)Enemy[i].y++;
else if (Enemy[i].y >= 17)Enemy[i].y--;
else {
if (rand() % 4 == 0) {
Enemy[i].x++;
}
else if (rand() % 4 == 1) {
Enemy[i].x--;
}
else if (rand() % 4 == 2) {
Enemy[i].y++;
}
else if (rand() % 4 == 3) {
Enemy[i].y--;
}
}
}
}
}
|
cs |
적이 가만히 있으면 재미없으니까 이동하는 모션을 넣었다.
그런데 우리가 rand()함수를 통해서 난수를 생성하는데,
이를 4로 나눈 나머지를 따져서, 4가지 방향으로 이동하게 하였다.(4가지 경우의 수가 생기게)
그림으로 보면 다음과 같이 생성, 이동하게 제한해뒀다.
적들이 잘 움직이고 생성도 잘 된다.
적 총알 피격 판정
1
2
3
4
5
6
7
|
//총알 적 충돌
for (int j = 0; j < 10; j++) {
if (Enemy[j].Active && Enemy[j].x == pBullet[i].x && Enemy[j].y == pBullet[i].y) {
Enemy[j].Active = false; //적 상태 비활성화
pBullet[i].Active = false; //총알 상태 비활성화
}
}
|
cs |
적 총알 피격은 상당히 간단하다.
총알의 위치와 적의 위치를 비교해서 같으면, 둘다 상태를 false로 바꿔주면 된다.
참고로 저 코드는 따로 collision함수로 만들어도 되겠지만, 총알을 쏘는 함수 안에 넣었다.
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
31
32
33
34
35
36
37
38
39
40
41
|
void Bullet_Shoot(Bullet* pBullet, plane* pPlane, Bullet* Enemy) {
//총알 이동
for (int i = 0; i < MAXBULLET; i++) {
if (pBullet[i].Active) {
pBullet[i].y--;
mapData[pBullet[i].y * Map_X_MAX + pBullet[i].x] = '*';
if (pBullet[i].y < 1) {
pBullet[i].Active = false;
}
//총알 적 충돌
for (int j = 0; j < 10; j++) {
if (Enemy[j].Active && Enemy[j].x == pBullet[i].x && Enemy[j].y == pBullet[i].y) {
Enemy[j].Active = false; //적 상태 비활성화
pBullet[i].Active = false; //총알 상태 비활성화
}
}
}
}
int a = pPlane->x;
int b = pPlane->y;
//총알 발사
if (GetAsyncKeyState(VK_SPACE)) {
if (b_index > 10) return b_index = 0;
pBullet[b_index].x = a;
pBullet[b_index].y = b;
pBullet[b_index].Active = true;
b_index++;
}
if (GetAsyncKeyState(VK_CONTROL)) {
for (int i = 0; i < 10; i++) {
pBullet[b_index].Active = FALSE;
}
return b_index = 0;
}
}
|
cs |
이렇게 말이다!
실행결과 총알을 맞았을 시 잘 없어진다.
근데 에임이..ㅋㅋ 생각보다 맞추기가 어렵네 ㅎㅎ
적 총알 구현
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
31
32
33
|
void Enemy_Attack(Bullet* Enemy_Bullet, Bullet* Enemy) {
//적 총알 이동
for (int i = 0; i < MAXBULLET; i++) {
if (Enemy_Bullet[i].Active) {
Enemy_Bullet[i].y++;
mapData[Enemy_Bullet[i].y*Map_X_MAX + Enemy_Bullet[i].x-1] = '!';
if (Enemy_Bullet[i].y >= 37) {
Enemy_Bullet[i].Active = false;
}
}
}
if (rand() % 10 != 0)return; //발사될 확률
if (eb_index == MAXBULLET - 1)eb_index = 0; //총알 초기화
//적 총알 발사
for (int i = 0; i < MAXBULLET; i++) {
if (Enemy[i].Active) {
Enemy_Bullet[eb_index].x = Enemy[i].x;
Enemy_Bullet[eb_index].y = Enemy[i].y + 1;
Enemy_Bullet[eb_index].Active = true;
eb_index++;
}
}
}
|
cs |
적 총알은 캐릭터의 총알을 구현했으면 쉽다.
단순히 캐릭터의 총알 발사는 space를 누르면 발사했지만, 얘는 랜덤으로 발사하는걸로 적용시키면 된다.
나머지 이론은 똑같으니 헷갈리면 저번 포스팅을 다시 보면 될거같다.
다음과 같이 잘 작동이 된다. 허헣
다음시간엔 게임오버 화면, 점수 등을 만들어봐야겠다
사실 지금 테스트 하면서 자잘한 버그들이 있는데...그건 일단 다 만들고 수정해야지
그냥 C로 하니 죽을거같다 C++로 할껄...
Reference
'코딩 > C, C++' 카테고리의 다른 글
C언어로 게임 만들기(7) - 완성. (코드, 구현 영상) (0) | 2023.06.02 |
---|---|
C언어로 게임 만들기(5) - 게임 씬 추가(getch함수, exit함수) (0) | 2023.05.28 |
C언어로 게임 만들기(3) - 총알 발사 및 UI 표시 (0) | 2023.05.19 |
C언어 게임 만들기(2) - 캐릭터 출력 및 이동 (1) | 2023.05.14 |
C언어로 게임 만들기(1) - (콘솔창 세팅, window.h, conio.h) (6) | 2023.05.13 |