안녕하세요. BlockDMask 입니다.
오늘은 제가 SFML과 C++ 을 이용해서 만들었던 마지막 게임인 Arrow Defense 라는 게임을 저 폴더 구석탱이에 있는걸 발견해서 가지고 왔습니다.
<목차>
1. 간단한 게임 설명
2. 게임 영상
3. 소스코드와 깃허브 주소
1. 간단한 게임 설명
> SFML Arrow Defense 게임 설명
C++ SFML 으로 만든 간단한 게임 입니다. 제가 이름을 화살표 디펜스라고 지었습니다.
이 게임은 화살표가 나오는 순서대로 같은 방향의 화살표를 입력하면 되는 간단한 게임 입니다. 맨 좌측에 있는 빨간색 라인에 화살표가 닿게 되면 게임이 끝납니다.
SFML은 간단히 설명하자면 게임(멀티미디어)를 편하게 만들 수 있게 도와주는 함수들을 모아둔 라이브러리 입니다. C++로 만들어져 있습니다.
> 코드를 보기전에 알면 좋을 지식
1. C++ STL deque [바로가기]
이 게임에서는 화살표들을 담기 위해서 deque 컨테이너를 사용하였습니다. 맨 뒤에 화살표가 계속 채워지고, 유저가 맨앞에 화살표를 맞추면 맨 앞에 화살표가 살아져야 하기 때문에 deque를 이용해서 해당 작업을 편리하게 하였습니다.
deque의 push_back 멤버 함수를 이용해서 맨 뒤에 화살표를 넣어주고
deque의 pop_front 멤버 함수를 이용해서 맨 앞의 화살표를 제거 해주었습니다.
deque에 대해서 궁금하시다면 [바로가기] 에 가시면 더 자세한 포스팅이 준비되어있습니다.
2. 랜덤을 생성 하는 방법 [바로가기]
이 게임에서 화살표의 방향이 4방향으로 랜덤하게 생성을 하기 위해서, 랜덤 함수를 이용했습니다.
srand(static_cast<unsigned int>(time(nullptr))); 을 이용해서 시간 값을 srand의 시드값으로 넣어주고
rand() % 4 를 이용해서 4방향을 랜덤하게 만들 수 있도록 하였습니다.
랜덤함수, 난수 생성에 대해서 더 궁금하시다면 [바로가기] 에 가시면 더 자세한 포스팅이 있습니다.
2. 게임 영상
영상 주소 : https://youtu.be/FmAmkHbaLQU
3. 소스코드와 깃허브 주소
깃허브에는 소스코드와 이미지 파일을 업로드 해두었습니다.
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | //Youtube : https://youtu.be/FmAmkHbaLQU //Blog : https://blockdmask.tistory.com/431 #include<SFML/Graphics.hpp> #include<iostream> #include<deque> #include<time.h> using namespace sf; using namespace std; #define WIDTH 1000 #define HEIGHT 300 struct ArrowShape { int direction; int x; int y; }; class Arrow { private: enum Dir { UP = 0, DOWN, LEFT, RIGHT, }; Texture t; Sprite s; deque<ArrowShape> questions; float frame; float frameSpeed; int frameLimit; int dir[4] = { -90, 90, 180, 0 }; private: bool CheckArrow(int idx) { if (questions.empty()) return false; if (idx == questions[0].direction) { cout << "correct" << endl; return true; } return false; } public: Arrow() { srand(static_cast<unsigned int>(time(nullptr))); t.loadFromFile("images/arrow.png"); s = Sprite(t); Rect<float> rect = s.getGlobalBounds(); s.setOrigin(Vector2f(rect.width / 2, rect.height / 2)); frame = 20.f; frameSpeed = 0.6f; frameLimit = 20; } ~Arrow() {} void Init() { questions.clear(); } bool CheckKey() { if (Keyboard::isKeyPressed(Keyboard::Up)) { cout << "UP" << endl; return CheckArrow(Dir::UP); } if (Keyboard::isKeyPressed(Keyboard::Down)) { cout << "DOWN" << endl; return CheckArrow(Dir::DOWN); } if (Keyboard::isKeyPressed(Keyboard::Left)) { cout << "LEFT" << endl; return CheckArrow(Dir::LEFT); } if (Keyboard::isKeyPressed(Keyboard::Right)) { cout << "RIGHT" << endl; return CheckArrow(Dir::RIGHT); } return false; } void ArrowSetting() { //check frame frame += frameSpeed; if (frame <= frameLimit) return; frame -= frameLimit; //check arrow number if (questions.size() > 10) return; ArrowShape as; int dirIdx = rand() % 4; as.direction = dirIdx; as.x = WIDTH; as.y = 100; s.setPosition(as.x, as.y); questions.push_back(as); } void Move(const int& speed, bool& isGameOver) { deque<ArrowShape>::iterator iter; for (iter = questions.begin(); iter != questions.end(); ++iter) { iter->x -= speed; if (iter->x <= 0) { //gameover; isGameOver = true; break; } } } void Draw(RenderWindow& _window) { for (auto iter = questions.begin(); iter != questions.end(); ++iter) { s.setRotation(dir[iter->direction]); s.setPosition(iter->x, iter->y); _window.draw(s); } } ArrowShape GetFirstArrowPos() { return questions[0]; } void RemoveFirstArrow() { if (questions.empty()) return; questions.pop_front(); } bool IsEmpty() const { return questions.empty(); } }; | cs |
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | class GameManager { private: enum GameState { NONE, CORRECT, WRONG, }; int arrowSpeed; bool isGameOver; Arrow* pArrow; Texture tw; Texture tl; Sprite imgWrong; Sprite imgDeadLine; GameState state; ArrowShape firstArrowPos; public: GameManager() { arrowSpeed = 10; isGameOver = false; pArrow = new Arrow(); state = NONE; tw.loadFromFile("images/wrong.png"); tl.loadFromFile("images/line.png"); imgWrong = Sprite(tw); imgDeadLine = Sprite(tl); imgDeadLine.setPosition(0, 45); Rect<float> rect = imgWrong.getGlobalBounds(); imgWrong.setOrigin(Vector2f(rect.width / 2, rect.height / 2)); } void Init() { pArrow->Init(); } void CheckKey() { if (pArrow->IsEmpty()) return; if (pArrow->CheckKey()) { //correct firstArrowPos = pArrow->GetFirstArrowPos(); pArrow->RemoveFirstArrow(); state = CORRECT; } else { //wrong firstArrowPos = pArrow->GetFirstArrowPos(); pArrow->RemoveFirstArrow(); state = WRONG; } } void Move() { pArrow->ArrowSetting(); pArrow->Move(arrowSpeed, isGameOver); } void Draw(RenderWindow& window) { switch (state) { case WRONG: //game over. state = NONE; imgWrong.setPosition(firstArrowPos.x, firstArrowPos.y); window.draw(imgWrong); isGameOver = true; break; case CORRECT: //score up. state = NONE; break; } pArrow->Draw(window); window.draw(imgDeadLine); } void CheckGameOver() { if (isGameOver) { sleep(seconds(3)); isGameOver = false; Init(); } } }; int main(void) { RenderWindow window(VideoMode(WIDTH, HEIGHT), "Arrow Defense. By BlockDMask."); window.setFramerateLimit(60); GameManager* pGameMgr = new GameManager(); pGameMgr->Init(); while (window.isOpen()) { Event e; while (window.pollEvent(e)) { if (e.type == Event::Closed) { window.close(); } if (e.type == Event::KeyPressed) { pGameMgr->CheckKey(); } } //logic. pGameMgr->Move(); //draw. window.clear(Color::Black); pGameMgr->Draw(window); window.display(); pGameMgr->CheckGameOver(); } delete(pGameMgr); return 0; } | cs |
감사합니다. 이상으로 C++ SFML로 만든 Arrow defense 게임 소개를 마치겠습니다.
'<토이프로젝트> > [C++ SFML 게임]' 카테고리의 다른 글
[C++ SFML 게임] 두들 점프 게임 (13) | 2020.09.01 |
---|---|
[C++ SFML 게임] 구글 공룡 게임 (14) | 2019.11.29 |