294 lines
9.2 KiB
C++
294 lines
9.2 KiB
C++
#include "SDL2/SDL.h"
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
typedef struct {
|
|
uint8_t a;
|
|
uint8_t b;
|
|
bool isMinus;
|
|
int8_t result;
|
|
} Priklad;
|
|
|
|
Priklad priklad;
|
|
|
|
typedef struct {
|
|
SDL_Rect rekt;
|
|
int8_t value;
|
|
}Vysledok;
|
|
|
|
|
|
// Constants
|
|
const int SCREEN_WIDTH = 1280;
|
|
const int SCREEN_HEIGHT = 720;
|
|
const int PLAYER_HEIGHT = 20;
|
|
const int OBJECT_SIZE = 30;
|
|
|
|
const int PLAYER_SPEED = 10;
|
|
const int SEGMENT_WIDTH = 10;
|
|
const int DIGIT_WIDTH = 40;
|
|
const int DIGIT_HEIGHT = 60;
|
|
const int PLAYER_WIDTH = (DIGIT_WIDTH * 3) / 2;
|
|
|
|
const int MAX_FALL_SPEED = 8;
|
|
const int ORIG_FALL_SPEED = 2;
|
|
|
|
int FALL_SPEED = ORIG_FALL_SPEED;
|
|
|
|
const int vyslWidth = DIGIT_WIDTH * 4;
|
|
Vysledok vysledky[(SCREEN_WIDTH / vyslWidth)];
|
|
|
|
|
|
int score = 0;
|
|
|
|
// SDL Variables
|
|
SDL_Window* window = nullptr;
|
|
SDL_Renderer* renderer = nullptr;
|
|
SDL_Rect player, object;
|
|
|
|
const int numResults = sizeof(vysledky) / sizeof(Vysledok);
|
|
|
|
void generatePriklad() {
|
|
priklad.a = rand() % 10;
|
|
priklad.b = rand() % 10;
|
|
priklad.isMinus = rand() > (RAND_MAX / 2);
|
|
priklad.result = priklad.isMinus ? (priklad.a - priklad.b) : (priklad.a + priklad.b);
|
|
}
|
|
|
|
void generateVysledky() {
|
|
generatePriklad();
|
|
for (size_t i = 0; i < numResults; i++) {
|
|
vysledky[i].rekt.x = i * vyslWidth;
|
|
vysledky[i].rekt.y = DIGIT_HEIGHT * 2;
|
|
vysledky[i].rekt.w = (DIGIT_WIDTH + 10) * 3;
|
|
vysledky[i].rekt.h = DIGIT_HEIGHT;
|
|
vysledky[i].value = rand() % 19;
|
|
}
|
|
// Choose a random index to set to a specific value
|
|
size_t randomIndex = rand() % numResults; // Pick a random index
|
|
vysledky[randomIndex].value = priklad.result; // Set this specific element to a value (e.g., 42)
|
|
}
|
|
|
|
void stepVysledky() {
|
|
for (size_t i = 0; i < sizeof(vysledky) / sizeof(Vysledok); i++) {
|
|
vysledky[i].rekt.y += FALL_SPEED;
|
|
if (SDL_HasIntersection(&player, &vysledky[i].rekt)) {
|
|
if (vysledky[i].value == priklad.result) {
|
|
score++;
|
|
FALL_SPEED = score / 4 + 2;
|
|
|
|
} else {
|
|
score = 0;
|
|
FALL_SPEED = ORIG_FALL_SPEED;
|
|
}
|
|
if (FALL_SPEED > MAX_FALL_SPEED) {
|
|
FALL_SPEED = MAX_FALL_SPEED;
|
|
}
|
|
if (FALL_SPEED < ORIG_FALL_SPEED) {
|
|
FALL_SPEED = ORIG_FALL_SPEED;
|
|
}
|
|
generateVysledky();
|
|
}
|
|
if (vysledky[i].rekt.y >= SCREEN_HEIGHT) {
|
|
generateVysledky();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Function to initialize SDL
|
|
bool init() {
|
|
srand(time(NULL));
|
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
|
std::cout << "SDL Initialization Failed: " << SDL_GetError() << std::endl;
|
|
return false;
|
|
}
|
|
window = SDL_CreateWindow("Catch the Falling Object", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
|
|
if (!window) {
|
|
std::cout << "Window Creation Failed: " << SDL_GetError() << std::endl;
|
|
return false;
|
|
}
|
|
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
|
if (!renderer) {
|
|
std::cout << "Renderer Creation Failed: " << SDL_GetError() << std::endl;
|
|
return false;
|
|
}
|
|
generateVysledky();
|
|
return true;
|
|
}
|
|
|
|
// Function to close SDL
|
|
void close() {
|
|
SDL_DestroyRenderer(renderer);
|
|
SDL_DestroyWindow(window);
|
|
SDL_Quit();
|
|
}
|
|
|
|
|
|
|
|
// Function to draw a single 7-segment style digit
|
|
void drawSegmentedDigit(int digit, int x, int y) {
|
|
static const std::vector<std::vector<bool>> segments = {
|
|
{1, 1, 1, 0, 1, 1, 1, 0}, // 0
|
|
{0, 0, 1, 0, 0, 1, 0, 0}, // 1
|
|
{1, 0, 1, 1, 1, 0, 1, 0}, // 2
|
|
{1, 0, 1, 1, 0, 1, 1, 0}, // 3
|
|
{0, 1, 1, 1, 0, 1, 0, 0}, // 4
|
|
{1, 1, 0, 1, 0, 1, 1, 0}, // 5
|
|
{1, 1, 0, 1, 1, 1, 1, 0}, // 6
|
|
{1, 0, 1, 0, 0, 1, 0, 0}, // 7
|
|
{1, 1, 1, 1, 1, 1, 1, 0}, // 8
|
|
{1, 1, 1, 1, 0, 1, 1, 0}, // 9
|
|
{0, 0, 0, 1, 0, 0, 0, 0}, //plus
|
|
{0, 0, 0, 1, 0, 0, 1, 0}, //equals
|
|
{0, 0, 0, 1, 0, 0, 0, 1}, //minus
|
|
};
|
|
|
|
SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
|
|
SDL_Rect seg[8] = {
|
|
{x + SEGMENT_WIDTH, y, DIGIT_WIDTH - 2 * SEGMENT_WIDTH, SEGMENT_WIDTH}, // Top
|
|
{x, y + SEGMENT_WIDTH, SEGMENT_WIDTH, DIGIT_HEIGHT / 2 - SEGMENT_WIDTH}, // Top-left
|
|
{x + DIGIT_WIDTH - SEGMENT_WIDTH, y + SEGMENT_WIDTH, SEGMENT_WIDTH, DIGIT_HEIGHT / 2 - SEGMENT_WIDTH}, // Top-right
|
|
{x + SEGMENT_WIDTH, y + DIGIT_HEIGHT / 2 - SEGMENT_WIDTH / 2, DIGIT_WIDTH - 2 * SEGMENT_WIDTH, SEGMENT_WIDTH}, // Middle
|
|
{x, y + DIGIT_HEIGHT / 2, SEGMENT_WIDTH, DIGIT_HEIGHT / 2 - SEGMENT_WIDTH}, // Bottom-left
|
|
{x + DIGIT_WIDTH - SEGMENT_WIDTH, y + DIGIT_HEIGHT / 2, SEGMENT_WIDTH, DIGIT_HEIGHT / 2 - SEGMENT_WIDTH}, // Bottom-right
|
|
{x + SEGMENT_WIDTH, y + DIGIT_HEIGHT - SEGMENT_WIDTH, DIGIT_WIDTH - 2 * SEGMENT_WIDTH, SEGMENT_WIDTH}, // Bottom
|
|
{x + DIGIT_WIDTH / 2 - SEGMENT_WIDTH / 2, y + DIGIT_HEIGHT / 2 - DIGIT_HEIGHT / 4 + (SEGMENT_WIDTH / 2), SEGMENT_WIDTH, SEGMENT_WIDTH * 2}, // Bottom-right
|
|
};
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
if (segments[digit][i]) {
|
|
SDL_RenderFillRect(renderer, &seg[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawVysledok(Vysledok vysledok) {
|
|
char scoreStr[4]; // Array to store the digits and sign (+ or -)
|
|
size_t index = 0;
|
|
|
|
// Handle the sign (+ or -)
|
|
if (vysledok.value >= 0) {
|
|
scoreStr[index++] = '+'; // Add '+' for positive numbers or zero
|
|
} else {
|
|
scoreStr[index++] = '-'; // Add '-' for negative numbers
|
|
vysledok.value = -vysledok.value; // Make the value positive for easier processing
|
|
}
|
|
|
|
// Handle the digits (1 or 2 digit numbers)
|
|
if (vysledok.value < 10) {
|
|
scoreStr[index++] = '0' + vysledok.value; // Single digit number
|
|
} else {
|
|
scoreStr[index++] = '0' + (vysledok.value / 10); // Tens digit
|
|
scoreStr[index++] = '0' + (vysledok.value % 10); // Ones digit
|
|
}
|
|
|
|
// Add null terminator to the string
|
|
scoreStr[index] = '\0';
|
|
|
|
// Draw the segments
|
|
for (size_t i = 0; i < index; i++) {
|
|
// Handle '-' and '+' signs as special cases
|
|
if (scoreStr[i] == '-') {
|
|
scoreStr[i] = 10; // ASCII value for '-' is converted to 10 for rendering
|
|
} else if (scoreStr[i] == '+') {
|
|
scoreStr[i] = 12; // ASCII value for '+' is converted to 11 for rendering
|
|
} else {
|
|
scoreStr[i] -= '0'; // Convert from ASCII char to integer
|
|
}
|
|
|
|
// Draw the digit
|
|
drawSegmentedDigit(scoreStr[i], vysledok.rekt.x + i * (DIGIT_WIDTH + 10), vysledok.rekt.y);
|
|
}
|
|
}
|
|
|
|
|
|
// Function to draw score
|
|
void drawScore(int score, int x, int y) {
|
|
std::string scoreStr = std::to_string(score);
|
|
for (size_t i = 0; i < scoreStr.size(); i++) {
|
|
drawSegmentedDigit(scoreStr[i] - '0', x + i * (DIGIT_WIDTH + 10), y);
|
|
}
|
|
}
|
|
|
|
// Render priklad
|
|
void drawPriklad(int x, int y) {
|
|
uint8_t i = 0;
|
|
drawSegmentedDigit(priklad.a, x + i++ * (DIGIT_WIDTH), y);
|
|
drawSegmentedDigit(priklad.isMinus ? 10 : 12, x + i++ * (DIGIT_WIDTH), y);
|
|
drawSegmentedDigit(priklad.b, x + i++ * (DIGIT_WIDTH), y);
|
|
drawSegmentedDigit(11, x + i++ * (DIGIT_WIDTH), y);
|
|
}
|
|
|
|
int main(int argv, char** args) {
|
|
if (!init()) return -1;
|
|
|
|
// Initialize player & object
|
|
player = {SCREEN_WIDTH / 2 - PLAYER_WIDTH / 2, SCREEN_HEIGHT - 50, PLAYER_WIDTH, PLAYER_HEIGHT};
|
|
|
|
bool running = true;
|
|
SDL_Event e;
|
|
|
|
while (running) {
|
|
// Event Handling
|
|
while (SDL_PollEvent(&e) != 0) {
|
|
if (e.type == SDL_QUIT) running = false;
|
|
}
|
|
|
|
// Player Movement
|
|
//const Uint8* keystate = SDL_GetKeyboardState(NULL);
|
|
//if (keystate[SDL_SCANCODE_LEFT] && player.x > 0) player.x -= PLAYER_SPEED;
|
|
//if (keystate[SDL_SCANCODE_RIGHT] && player.x < SCREEN_WIDTH - PLAYER_WIDTH) player.x += PLAYER_SPEED;
|
|
SDL_GetMouseState(&player.x, NULL);
|
|
player.x -= PLAYER_WIDTH / 2;
|
|
if (player.x < 0) {
|
|
player.x = 0;
|
|
}
|
|
else if (player.x > SCREEN_WIDTH - PLAYER_WIDTH) {
|
|
player.x = SCREEN_WIDTH - PLAYER_WIDTH;
|
|
}
|
|
|
|
stepVysledky();
|
|
|
|
// Collision Check
|
|
if (object.y + OBJECT_SIZE >= player.y && object.x + OBJECT_SIZE >= player.x && object.x <= player.x + PLAYER_WIDTH) {
|
|
score++;
|
|
std::cout << "Score: " << score << std::endl;
|
|
}
|
|
|
|
// Render
|
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
|
SDL_RenderClear(renderer);
|
|
|
|
|
|
// Draw Score
|
|
drawScore(score, 20, 20);
|
|
drawPriklad(200, 20);
|
|
|
|
// Draw Player
|
|
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
|
SDL_RenderFillRect(renderer, &player);
|
|
|
|
//printf("%d %d\n", object.x, object.y);
|
|
// Draw Falling Object
|
|
|
|
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
|
SDL_RenderFillRect(renderer, &object);
|
|
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
|
for (int i = 0; i< sizeof(vysledky)/sizeof(Vysledok); i++) {
|
|
SDL_SetRenderDrawColor(renderer, 20, 20, 20, 255);
|
|
SDL_RenderFillRect(renderer, &vysledky[i].rekt);
|
|
drawVysledok(vysledky[i]);
|
|
}
|
|
|
|
|
|
|
|
SDL_RenderPresent(renderer);
|
|
SDL_Delay(16);
|
|
}
|
|
|
|
close();
|
|
return 0;
|
|
}
|