sound update and cmake addition for sfml sound!
This commit is contained in:
@@ -12,6 +12,7 @@ target_link_libraries(cppsnek
|
||||
sfml-graphics
|
||||
sfml-window
|
||||
sfml-system
|
||||
sfml-audio
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
||||
151
main.cpp
151
main.cpp
@@ -1,14 +1,17 @@
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/Audio.hpp>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
#include <array>
|
||||
|
||||
// Set namespaces for SFML and STD
|
||||
using namespace sf;
|
||||
using namespace std;
|
||||
|
||||
constexpr int WIDTH = 800;
|
||||
constexpr int HEIGHT = 600;
|
||||
constexpr int GRID_SIZE = 40;
|
||||
// Init window / sprite variables ( constant and will never change )
|
||||
constexpr int WIDTH = 640;
|
||||
constexpr int HEIGHT = 480;
|
||||
constexpr int GRID_SIZE = 20;
|
||||
constexpr int GRID_WIDTH = WIDTH / GRID_SIZE;
|
||||
constexpr int GRID_HEIGHT = HEIGHT / GRID_SIZE;
|
||||
constexpr int SPRITE_SIZE = GRID_SIZE;
|
||||
@@ -51,6 +54,127 @@ public:
|
||||
void setPosition(float x, float y) { sprite.setPosition(x, y); }
|
||||
};
|
||||
|
||||
class SoundManager {
|
||||
private:
|
||||
SoundBuffer moveBuffer;
|
||||
SoundBuffer eatBuffer;
|
||||
SoundBuffer gameOverBuffer;
|
||||
Sound moveSound;
|
||||
Sound eatSound;
|
||||
Sound gameOverSound;
|
||||
bool soundLoaded;
|
||||
|
||||
public:
|
||||
SoundManager() : soundLoaded(true) {
|
||||
// Create simple beep sounds programmatically
|
||||
createMoveSound();
|
||||
createEatSound();
|
||||
createGameOverSound();
|
||||
|
||||
// Set volumes to be quieter
|
||||
moveSound.setVolume(15.0f); // Very quiet for movement
|
||||
eatSound.setVolume(25.0f); // Bit louder for eating
|
||||
gameOverSound.setVolume(30.0f); // Louder for game over
|
||||
}
|
||||
|
||||
void createMoveSound() {
|
||||
const unsigned SAMPLE_RATE = 44100;
|
||||
const unsigned DURATION = 5000; // Very short duration (in samples)
|
||||
|
||||
std::vector<Int16> samples(DURATION);
|
||||
|
||||
// Generate a simple beep for movement (higher pitch, shorter)
|
||||
for (unsigned i = 0; i < DURATION; i++) {
|
||||
double time = i / static_cast<double>(SAMPLE_RATE);
|
||||
samples[i] = 10000 * sin(2 * 3.14159 * 880 * time); // 880 Hz tone
|
||||
}
|
||||
|
||||
// Apply fade-out
|
||||
for (unsigned i = DURATION / 2; i < DURATION; i++) {
|
||||
double fadeOut = 1.0 - (static_cast<double>(i - DURATION / 2) / (DURATION / 2));
|
||||
samples[i] = static_cast<Int16>(samples[i] * fadeOut);
|
||||
}
|
||||
|
||||
if (!moveBuffer.loadFromSamples(&samples[0], samples.size(), 1, SAMPLE_RATE)) {
|
||||
soundLoaded = false;
|
||||
}
|
||||
moveSound.setBuffer(moveBuffer);
|
||||
}
|
||||
|
||||
void createEatSound() {
|
||||
const unsigned SAMPLE_RATE = 44100;
|
||||
const unsigned DURATION = 8000; // Slightly longer duration for eat sound
|
||||
|
||||
std::vector<Int16> samples(DURATION);
|
||||
|
||||
// Generate eat sound (rising pitch)
|
||||
for (unsigned i = 0; i < DURATION; i++) {
|
||||
double time = i / static_cast<double>(SAMPLE_RATE);
|
||||
double frequency = 440 + (i * 400 / DURATION); // Rising from 440Hz to 840Hz
|
||||
samples[i] = 12000 * sin(2 * 3.14159 * frequency * time);
|
||||
}
|
||||
|
||||
// Apply fade-in and fade-out
|
||||
for (unsigned i = 0; i < DURATION / 4; i++) {
|
||||
double fadeIn = static_cast<double>(i) / (DURATION / 4);
|
||||
samples[i] = static_cast<Int16>(samples[i] * fadeIn);
|
||||
}
|
||||
|
||||
for (unsigned i = 3 * DURATION / 4; i < DURATION; i++) {
|
||||
double fadeOut = 1.0 - (static_cast<double>(i - 3 * DURATION / 4) / (DURATION / 4));
|
||||
samples[i] = static_cast<Int16>(samples[i] * fadeOut);
|
||||
}
|
||||
|
||||
if (!eatBuffer.loadFromSamples(&samples[0], samples.size(), 1, SAMPLE_RATE)) {
|
||||
soundLoaded = false;
|
||||
}
|
||||
eatSound.setBuffer(eatBuffer);
|
||||
}
|
||||
|
||||
void createGameOverSound() {
|
||||
const unsigned SAMPLE_RATE = 44100;
|
||||
const unsigned DURATION = 44100 / 2; // Half second
|
||||
|
||||
std::vector<Int16> samples(DURATION);
|
||||
|
||||
// Generate game over sound (descending pitch)
|
||||
for (unsigned i = 0; i < DURATION; i++) {
|
||||
double time = i / static_cast<double>(SAMPLE_RATE);
|
||||
double frequency = 440 - (i * 200 / DURATION); // Falling from 440Hz to 240Hz
|
||||
samples[i] = 15000 * sin(2 * 3.14159 * frequency * time);
|
||||
}
|
||||
|
||||
// Apply "wah wah" effect with fading
|
||||
for (unsigned i = 0; i < DURATION; i++) {
|
||||
double envelope = 1.0 - 0.8 * (static_cast<double>(i) / DURATION);
|
||||
samples[i] = static_cast<Int16>(samples[i] * envelope);
|
||||
}
|
||||
|
||||
if (!gameOverBuffer.loadFromSamples(&samples[0], samples.size(), 1, SAMPLE_RATE)) {
|
||||
soundLoaded = false;
|
||||
}
|
||||
gameOverSound.setBuffer(gameOverBuffer);
|
||||
}
|
||||
|
||||
void playMoveSound() {
|
||||
if (soundLoaded) {
|
||||
moveSound.play();
|
||||
}
|
||||
}
|
||||
|
||||
void playEatSound() {
|
||||
if (soundLoaded) {
|
||||
eatSound.play();
|
||||
}
|
||||
}
|
||||
|
||||
void playGameOverSound() {
|
||||
if (soundLoaded) {
|
||||
gameOverSound.play();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Game {
|
||||
private:
|
||||
RenderWindow window;
|
||||
@@ -63,6 +187,8 @@ private:
|
||||
int score;
|
||||
Font font;
|
||||
Text scoreText;
|
||||
SoundManager soundManager;
|
||||
Vector2f lastDirection;
|
||||
|
||||
// Numeric sprites
|
||||
NumericSprite snakeHeadSprite;
|
||||
@@ -99,8 +225,8 @@ private:
|
||||
}};
|
||||
|
||||
public:
|
||||
Game() : window(VideoMode(WIDTH, HEIGHT), "SFML CPPSNEK V1.2"), direction(1, 0),
|
||||
isMoving(false), speed(0.1f), score(0), grid(Lines) {
|
||||
Game() : window(VideoMode(WIDTH, HEIGHT), "SFML CPPSNEK V1.3 With Sound"), direction(1, 0),
|
||||
isMoving(false), speed(0.1f), score(0), grid(Lines), lastDirection(1, 0) {
|
||||
window.setFramerateLimit(60);
|
||||
|
||||
// Initialize snake
|
||||
@@ -165,21 +291,32 @@ public:
|
||||
}
|
||||
|
||||
void handleInput() {
|
||||
bool directionChanged = false;
|
||||
|
||||
if (Keyboard::isKeyPressed(Keyboard::Left) && direction.x == 0) {
|
||||
direction = Vector2f(-1, 0);
|
||||
isMoving = true;
|
||||
directionChanged = true;
|
||||
}
|
||||
else if (Keyboard::isKeyPressed(Keyboard::Right) && direction.x == 0) {
|
||||
direction = Vector2f(1, 0);
|
||||
isMoving = true;
|
||||
directionChanged = true;
|
||||
}
|
||||
else if (Keyboard::isKeyPressed(Keyboard::Up) && direction.y == 0) {
|
||||
direction = Vector2f(0, -1);
|
||||
isMoving = true;
|
||||
directionChanged = true;
|
||||
}
|
||||
else if (Keyboard::isKeyPressed(Keyboard::Down) && direction.y == 0) {
|
||||
direction = Vector2f(0, 1);
|
||||
isMoving = true;
|
||||
directionChanged = true;
|
||||
}
|
||||
|
||||
if (directionChanged && (direction.x != lastDirection.x || direction.y != lastDirection.y)) {
|
||||
soundManager.playMoveSound();
|
||||
lastDirection = direction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,12 +329,14 @@ public:
|
||||
SnakeSegment newHead = {snake[0].x + direction.x, snake[0].y + direction.y};
|
||||
|
||||
if (newHead.x < 0 || newHead.x >= GRID_WIDTH || newHead.y < 0 || newHead.y >= GRID_HEIGHT) {
|
||||
soundManager.playGameOverSound();
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < snake.size(); i++) {
|
||||
if (newHead.x == snake[i].x && newHead.y == snake[i].y) {
|
||||
soundManager.playGameOverSound();
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
@@ -208,6 +347,7 @@ public:
|
||||
spawnFruit();
|
||||
score += 10;
|
||||
updateScoreText();
|
||||
soundManager.playEatSound();
|
||||
|
||||
if (score % 50 == 0 && speed > 0.05f) {
|
||||
speed -= 0.01f;
|
||||
@@ -224,6 +364,7 @@ public:
|
||||
snake.push_back({GRID_WIDTH / 2 - 1, GRID_HEIGHT / 2});
|
||||
snake.push_back({GRID_WIDTH / 2 - 2, GRID_HEIGHT / 2});
|
||||
direction = Vector2f(1, 0);
|
||||
lastDirection = Vector2f(1, 0);
|
||||
isMoving = false;
|
||||
speed = 0.1f;
|
||||
score = 0;
|
||||
|
||||
Reference in New Issue
Block a user