-
SFML / 테트리스활동 기록 😵💫/SFML 테트리스 2023. 2. 19. 22:18
이전에 중간에 급하게 넣어서 설명 안한 기능들
1. 게임 BGM
SoundBuffer buffer; if (!buffer.loadFromFile("C:/Users/User/OneDrive/바탕 화면/bgm.wav")) { cout << "sound error" << endl; } Sound sound; sound.setBuffer(buffer); sound.play(); sound.setLoop(true);메인에 선언해주어서 게임 시작창이랑 게임창에서 노래가 나올수 있도록 해줬다.
#include <SFML/Audio.hpp>
그리고 GameOver 되었을때는 sound.stop();
참고해야 할 점은 음악이나 폰트을 첨부할 때 호환되는 파일인지 확인 해야 한다 !!!
내 경우 wav로 변환시켜주어야 했음
2. 테트리스 게임엔진은 기존에 있는 걸로 하는게 너무 어려워서 해당 유튜브 코드를 사용했다.
https://www.youtube.com/watch?v=zH_omFPqMO4
최종 테트리스 구현 코드
#include <SFML/Graphics.hpp> #include <cassert> #include <stdio.h> #include <iostream> #include <windows.h> #include <time.h> #include <string> #include <exception> #include <conio.h> #include <stdlib.h> #include <cstdlib> #include <algorithm> #include <SFML/Config.hpp> #include <SFML/System/Export.hpp> #include <SFML/Audio.hpp> #include <sstream> #include <vector> #include <cmath> using namespace std; using namespace sf; bool automaticPlaying = true; //테트리스 메인 보드 const int M = 20; const int N = 10; int board[M][N] = { 0 }; //새 벽돌을 만들어야 하는 상태 struct Point { int x, y; //좌표 }; Point a[4]; Point c[4]; //점이 4개 들어있는 배열 생성 int abc = 0; //현재 내려간 블록 카운트 int preabc = 0; //이전 int tiles[7][4] = { 1,3,5,7, //I 2,4,5,7, //Z 3,5,4,6, //S 3,5,4,7, //T 2,3,5,7, //L 3,5,7,6, //J 2,3,4,5, //O }; bool check() { for (int i = 0; i < 4; ++i) { if (a[i].x < 0 || a[i].x >= N || a[i].y >= M) return false; else if (board[a[i].y][a[i].x]) return false; } return true; } const float windowWidth = 500; const float windowHeight = 500; //text 함수 int textprint(Text& text, Font& font, int size, float x, float y, const Color& color, const Color& outColor, string p) { text.setFont(font); text.setCharacterSize(size); text.setPosition(x, y); text.setFillColor(color); text.setOutlineColor(outColor); text.setOutlineThickness(1.f); text.setString(p); return 0; } int main() { srand(time(0)); int score = 0; Text text; Text text2; Uint8 r = 0, g = 0, b = 0; string comment = "tetris Game Start"; string hi = "PRESS THIS BUTTON TO START !"; //마우스를 누르면 게임시작 int x = 0, y = 0; RenderWindow window(VideoMode(windowWidth, windowHeight), "tetris"); window.setFramerateLimit(60); //시작화면 text Font font; if (!font.loadFromFile("./자료/DungGeunMo.ttf")) throw exception("font error"); textprint(text, font, 100, 700, 30, Color::Green, Color::Black, comment); textprint(text2, font, 30, 50, 300, Color::Black, Color::Black, hi); Text scoreCurrent; scoreCurrent.setFont(font); scoreCurrent.setFillColor(Color::Red); scoreCurrent.setStyle(Text::Regular); scoreCurrent.setCharacterSize(30); scoreCurrent.setPosition(250, 30); Texture button; button.loadFromFile("./자료/NicePng_start-button-png_1108890.png"); Sprite button2(button); button2.setPosition(220, 370); button2.setScale(0.09f, 0.09f); SoundBuffer buffer; if (!buffer.loadFromFile("./자료/bgm.wav")) { cout << "sound error" << endl; } Sound sound; sound.setBuffer(buffer); sound.play(); sound.setLoop(true); window.display(); while (window.isOpen()) { text.move(-1, 0); window.clear(Color::White); window.draw(text); window.draw(button2); window.draw(text2); window.display(); Event event; while (window.pollEvent(event)) { switch (event.type) { case Event::Closed: window.close(); break; case Event::MouseButtonPressed: if (event.mouseButton.button == Mouse::Left) { window.create(VideoMode(windowWidth, windowHeight), "tetris game"); button2.move(1000, 0); text2.move(1000, 0); time_t start, end; double result; start = time(NULL); Texture t1; t1.loadFromFile("./자료/tile.png"); Sprite tileSprite(t1); Texture t2; t2.loadFromFile("./자료/line2.png"); Sprite deadline(t2); deadline.setPosition(0, 23.0001); /* Texture t3; t3.loadFromFile("./자료/frame.jpg"); Sprite frame; frame.setTexture(t3); 프레임도 적용 가능한데 디자인상 지웠습니다 rame을 그리면 보드의 정확한 넓이를 확인 할 수 있습니다. */ int dx = 0; bool rotate = false; int colorNum = 1; float timer = 0; float delay = 0.3; int currentScore = 0; Clock clock; bool collide; a[0].x = 0; a[0].y = 1; a[1].x = 1; a[1].y = 1; a[2].x = 1; a[2].y = 2; a[3].x = 1; a[3].y = 3; while (window.isOpen()) { float time = clock.getElapsedTime().asSeconds(); //초 단위로 경과시간을 얻음 clock.restart(); //시계 재시작 timer += time; //시간 누적 Event e; while (window.pollEvent(e)) { if (e.type == Event::Closed) window.close(); if (e.type == Event::KeyPressed) if (e.key.code == Keyboard::Up) rotate = true; else if (e.key.code == Keyboard::Left) dx = -1; else if (e.key.code == Keyboard::Right) dx = 1; //원래 dx =0이니까 왼쪽 -1 오른쪽 +1 } if (Keyboard::isKeyPressed(Keyboard::Down)) delay = 0.05; //이동// for (int i = 0; i < 4; ++i) { c[i] = a[i]; a[i].x += dx; //좌우로 } if (!check()) for (int i = 0; i < 4; ++i) a[i] = c[i]; // Rotate // if (rotate) { Point p = a[1]; // center of rotation for (int i = 0; i < 4; ++i) { int x = a[i].y - p.y; int y = a[i].x - p.x; a[i].x = p.x - x; a[i].y = p.y + y; } if (!check()) for (int i = 0; i < 4; ++i) a[i] = c[i]; } //시간// if (timer > delay) { for (int i = 0; i < 4; ++i) { c[i] = a[i]; a[i].y += 1; //아래로 } if (!check()) { if ((preabc == abc) && preabc != 0 && preabc == 1) { //이전움직임과 현재 움직임 동일(움직임이 없다고 볼때), 0으로 선언했으니까 시작과 동시에 꺼지는 것 방지, 움직임 같을때도 꺼지니까 이전움직임 1일때 window.close(); sound.stop(); } for (int i = 0; i < 4; ++i) { board[c[i].y][c[i].x] = colorNum; } cout << "preabc :" << preabc << endl; colorNum = 1 + rand() % 7; int n = rand() % 7; for (int i = 0; i < 4; ++i) { a[i].x = tiles[n][i] % 2; a[i].y = tiles[n][i] / 2; } cout << "abc: " << abc << endl; preabc = abc; //abc를 이전의 것으로 저장 abc = 0; //abc는 다시 세야되니까 초기화 } timer = 0; abc++; } //한줄 차면 지우기 // int k = M - 1; for (int i = M - 1; i > 0; i--) { int count = 0; for (int j = 0; j < N; ++j) { if (board[i][j]) count++; board[k][j] = board[i][j]; } if (count < N) k--; else { score++; } } dx = 0; delay = 0.3; rotate = false; //그리기// window.clear(Color::Black); for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { if (board[i][j] == 0) continue; tileSprite.setTextureRect(IntRect(board[i][j] * 18, 0, 18, 18)); tileSprite.setPosition(j * 18, i * 18); tileSprite.move(28, 31); window.draw(tileSprite); } } //출력// for (int i = 0; i < 4; ++i) { tileSprite.setTextureRect(IntRect(colorNum * 18, 0, 18, 18)); tileSprite.setPosition(a[i].x * 18, a[i].y * 18); tileSprite.move(28, 31); window.draw(tileSprite); } currentScore = ("%f", score); stringstream s; s << currentScore; scoreCurrent.setString("Score : " + s.str()); window.draw(scoreCurrent); window.draw(deadline); window.display(); } } } } } window.create(VideoMode(windowWidth, windowHeight), "Game Over"); Text gameover; String over = "GAMEOVER !!"; textprint(gameover, font, 70, 60, 30, Color::Magenta, Color::White, over); scoreCurrent.move(-90, 100); scoreCurrent.setFillColor(Color::White); while (window.isOpen()) { Event e; while (window.pollEvent(e)) { if (e.type == Event::Closed) { window.close(); break; } window.clear(Color::Black); window.draw(gameover); window.draw(scoreCurrent); window.display(); } } return 0; }'활동 기록 😵💫 > SFML 테트리스' 카테고리의 다른 글
SFML /3. 테트리스 게임오버 구현 (4) 2023.02.19 SFML/ 2. 게임 화면 (1) 2023.02.12 SFML / 1. 게임시작화면 구현 (1) 2023.02.08 SFML /프로젝트 시작 ! 1. 시작화면 만들기 (2) 2023.02.06 SFML / Texture Sprite(이미지) (3) 2023.02.05