Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SDL.h>
- #include <SDL_image.h>
- #include <SDL_ttf.h>
- #include <algorithm>
- #include <chrono>
- #include <iterator>
- #include <stdio.h>
- #include <random>
- #include <string>
- #include <vector>
- #include "Shape.h"
- #include "Text.h"
- typedef std::vector<int> intArray;
- typedef std::vector<float> floatArray;
- typedef std::vector<std::vector<Tile>> gridArray;
- typedef std::vector<Text> textArray;
- enum fallState {
- FELL,
- PLACED,
- };
- enum gameState {
- PLAYING,
- ENDED,
- PAUSED,
- MAIN_MENU
- };
- bool handleEvents();
- bool update(float deltaTime);
- void paintGame();
- void paintMenu(float deltaTime);
- fallState fall();
- void addShape();
- void newShape();
- bool init();
- void close();
- SDL_Window* window;
- SDL_Renderer* renderer;
- Text scoreT, scoreNumT, linesT, linesNumT, levelT, levelNumT, nextT, menuT, holdT;
- int tileLength = 34, tiles = 4, width = 10, height = 22, gridLineWidth = 2;
- int screenWidth = tileLength * (width + 12), screenHeight = tileLength * (height - 2);
- int selectedMenuIndex = 0, selectedSubmenuIndex = 0;
- Shape* currentShape;
- intArray shapeIndexes;
- intArray nextShapeIndexes;
- int currentShapeIndex = 0, heldIndex = -1;
- gridArray grid(height, std::vector<Tile>(width));
- unsigned int score = 0, lines = 0, level = 1, lineClearCombos = 0, startingLevel = 1;
- floatArray lineClearPoints = {100, 300, 500, 800, 1.5, 50};
- bool lastClearDifficult = false;
- float fastSpeed = 30.0F, normalSpeed = (float) level, fastFallTime = 0.0F, normalFallTime = 0.0F, lockTime = 0.0F, lockDelay = .25F;
- int nextShapes = 3; // No more than 7
- bool isFast = false, canHold = true, isLocking = false, menuFocus = true, debugShowDataArea = false;
- gameState state = MAIN_MENU;
- Text title;
- struct menuOption {
- Text text;
- float y, size = (float) Text::defaultSize;
- } mainSubs[5];
- int playX = 0, playY = 0;
- textArray playOptions(10);
- enum displayType {
- BOOLEAN,
- INTEGER,
- FLOAT,
- STRING
- };
- struct customOption {
- Text text, valueText;
- displayType type;
- int currentOption;
- int Imin, Imax;
- float Fmin, Fmax;
- std::vector<std::string> strings;
- } custom[11], options[9];
- struct controlOption {
- Text text, keyText;
- SDL_Keycode key;
- } controls[9];
- int currentEditingIndex = -1;
- int wmain() {
- init();
- Uint32 lastTime, currentTime = SDL_GetTicks();
- float deltaTime;
- while (true) {
- lastTime = currentTime;
- currentTime = SDL_GetTicks();
- deltaTime = (currentTime - lastTime) / 1000.0f;
- if (!handleEvents()) break;
- if (!update(deltaTime)) break;
- }
- close();
- return 0;
- }
- bool handleEvents() {
- SDL_Event e;
- while (SDL_PollEvent(&e) != 0) {
- switch (e.type) {
- case SDL_QUIT:
- return false;
- case SDL_WINDOWEVENT:
- if ((e.window.event == SDL_WINDOWEVENT_MOVED || e.window.event == SDL_WINDOWEVENT_FOCUS_LOST) && state == PLAYING) {
- state = PAUSED;
- }
- break;
- case SDL_KEYDOWN:
- switch (state) {
- case PLAYING:
- if (e.key.keysym.sym == controls[0].key || e.key.keysym.sym == controls[1].key) {
- if (currentShape->move(grid, e.key.keysym.sym == controls[1].key))
- lockTime = 0;
- }
- if (e.key.keysym.sym == controls[4].key || e.key.keysym.sym == controls[5].key) {
- if (currentShape->rotate(grid, e.key.keysym.sym == controls[4].key))
- lockTime = 0;
- }
- if (e.key.keysym.sym == controls[2].key && e.key.repeat == 0) {
- isFast = true;
- }
- if (e.key.keysym.sym == controls[3].key && e.key.repeat == 0) {
- while (fall() == FELL) {
- score += 2;
- scoreNumT.change(std::to_string(score));
- }
- lockTime = lockDelay;
- }
- if (e.key.keysym.sym == controls[6].key && canHold) {
- int p = currentShapeIndex;
- bool first = heldIndex == -1;
- if (first) newShape(); else currentShapeIndex = heldIndex;
- heldIndex = p;
- if (!first) {
- if (currentShape != NULL) delete[] currentShape; // Breaks here if held
- currentShape = new Shape;
- currentShape->data = Shape::shapes[currentShapeIndex];
- }
- canHold = false;
- }
- if (e.key.keysym.sym == controls[7].key || e.key.keysym.sym == SDLK_ESCAPE) {
- state = PAUSED;
- }
- if (e.key.keysym.sym == controls[8].key) {
- debugShowDataArea = !debugShowDataArea;
- }
- break;
- case PAUSED:
- if (e.key.keysym.sym == controls[7].key || e.key.keysym.sym == SDLK_ESCAPE) {
- state = PLAYING;
- }
- if (e.key.keysym.sym == SDLK_RETURN || e.key.keysym.sym == SDLK_RETURN2) {
- state = MAIN_MENU; // TODO: Fix Pause menu
- }
- break;
- case MAIN_MENU:
- if (selectedMenuIndex == 3 && currentEditingIndex >= 0) {
- controls[currentEditingIndex].key = e.key.keysym.sym;
- currentEditingIndex = -1;
- } else {
- if (e.key.keysym.sym == SDLK_UP && e.key.repeat == 0) {
- if (menuFocus) {
- selectedMenuIndex = std::max(0, std::min(4, selectedMenuIndex - 1));
- playX = playY = selectedSubmenuIndex = 0;
- } else {
- switch (selectedMenuIndex) {
- case 0:
- playY = std::max(0, std::min(1, playY - 1));
- break;
- case 1:
- if (currentEditingIndex < 0)
- selectedSubmenuIndex = std::max(0, std::min(10, selectedSubmenuIndex - 1));
- else {
- switch (custom[currentEditingIndex].type) {
- case BOOLEAN:
- custom[currentEditingIndex].currentOption = 1 - custom[currentEditingIndex].currentOption;
- break;
- case INTEGER:
- custom[currentEditingIndex].currentOption = std::min(custom[currentEditingIndex].Imax, std::max(custom[currentEditingIndex].Imin, custom[currentEditingIndex].currentOption + 1));
- break;
- case FLOAT:
- custom[currentEditingIndex].currentOption = std::min((int) log2(custom[currentEditingIndex].Fmax), std::max((int) log2(custom[currentEditingIndex].Fmin), custom[currentEditingIndex].currentOption + 1));
- break;
- case STRING:
- custom[currentEditingIndex].currentOption++;
- if (custom[currentEditingIndex].currentOption >= custom[currentEditingIndex].strings.size()) custom[currentEditingIndex].currentOption = 0;
- }
- }
- break;
- case 2:
- if (currentEditingIndex < 0)
- selectedSubmenuIndex = std::max(0, std::min(4, selectedSubmenuIndex - 1));
- else {
- switch (options[currentEditingIndex].type) {
- case BOOLEAN:
- options[currentEditingIndex].currentOption = 1 - options[currentEditingIndex].currentOption;
- break;
- case INTEGER:
- options[currentEditingIndex].currentOption = std::min(options[currentEditingIndex].Imax, std::max(options[currentEditingIndex].Imin, options[currentEditingIndex].currentOption + 1));
- break;
- }
- }
- break;
- case 3:
- selectedSubmenuIndex = std::max(0, std::min(8, selectedSubmenuIndex - 1));
- break;
- }
- }
- }
- if (e.key.keysym.sym == SDLK_DOWN && e.key.repeat == 0) {
- if (menuFocus) {
- selectedMenuIndex = std::max(0, std::min(4, selectedMenuIndex + 1));
- playX = playY = selectedSubmenuIndex = 0;
- } else {
- switch (selectedMenuIndex) {
- case 0:
- playY = std::max(0, std::min(1, playY + 1));
- break;
- case 1:
- if (currentEditingIndex < 0)
- selectedSubmenuIndex = std::max(0, std::min(10, selectedSubmenuIndex + 1));
- else {
- switch (custom[currentEditingIndex].type) {
- case BOOLEAN:
- custom[currentEditingIndex].currentOption = 1 - custom[currentEditingIndex].currentOption;
- break;
- case INTEGER:
- custom[currentEditingIndex].currentOption = std::min(custom[currentEditingIndex].Imax, std::max(custom[currentEditingIndex].Imin, custom[currentEditingIndex].currentOption - 1));
- break;
- case FLOAT:
- custom[currentEditingIndex].currentOption = std::min((int) log2(custom[currentEditingIndex].Fmax), std::max((int) log2(custom[currentEditingIndex].Fmin), custom[currentEditingIndex].currentOption - 1));
- break;
- case STRING:
- custom[currentEditingIndex].currentOption--;
- if (custom[currentEditingIndex].currentOption < 0) custom[currentEditingIndex].currentOption = custom[currentEditingIndex].strings.size() - 1;
- }
- }
- break;
- case 2:
- if (currentEditingIndex < 0)
- selectedSubmenuIndex = std::max(0, std::min(4, selectedSubmenuIndex + 1));
- else {
- switch (options[currentEditingIndex].type) {
- case BOOLEAN:
- options[currentEditingIndex].currentOption = 1 - options[currentEditingIndex].currentOption;
- break;
- case INTEGER:
- options[currentEditingIndex].currentOption = std::min(options[currentEditingIndex].Imax, std::max(options[currentEditingIndex].Imin, options[currentEditingIndex].currentOption + 1));
- break;
- }
- }
- break;
- case 3:
- selectedSubmenuIndex = std::max(0, std::min(8, selectedSubmenuIndex + 1));
- break;
- }
- }
- }
- if (e.key.keysym.sym == SDLK_LEFT && !menuFocus) {
- switch (selectedMenuIndex) {
- case 0:
- if (playX - 1 < 0) {
- menuFocus = true;
- } else {
- playX = std::max(0, std::min(4, playX - 1));
- }
- break;
- case 1:
- if (currentEditingIndex < 0)
- menuFocus = true;
- else {
- switch (custom[currentEditingIndex].type) {
- case BOOLEAN:
- custom[currentEditingIndex].currentOption = 1 - custom[currentEditingIndex].currentOption;
- break;
- case INTEGER:
- custom[currentEditingIndex].currentOption = std::min(custom[currentEditingIndex].Imax, std::max(custom[currentEditingIndex].Imin, custom[currentEditingIndex].currentOption - 1));
- break;
- case FLOAT:
- custom[currentEditingIndex].currentOption = std::min((int) log2(custom[currentEditingIndex].Fmax), std::max((int) log2(custom[currentEditingIndex].Fmin), custom[currentEditingIndex].currentOption - 1));
- break;
- case STRING:
- custom[currentEditingIndex].currentOption--;
- if (custom[currentEditingIndex].currentOption < 0) custom[currentEditingIndex].currentOption = custom[currentEditingIndex].strings.size() - 1;
- }
- }
- break;
- case 2:
- if (currentEditingIndex < 0)
- menuFocus = true;
- else {
- switch (options[currentEditingIndex].type) {
- case BOOLEAN:
- options[currentEditingIndex].currentOption = 1 - options[currentEditingIndex].currentOption;
- break;
- case INTEGER:
- options[currentEditingIndex].currentOption = std::min(options[currentEditingIndex].Imax, std::max(options[currentEditingIndex].Imin, options[currentEditingIndex].currentOption - 1));
- break;
- }
- }
- break;
- case 3:
- menuFocus = true;
- break;
- }
- }
- if (e.key.keysym.sym == SDLK_RIGHT && !menuFocus) {
- switch (selectedMenuIndex) {
- case 0:
- playX = std::max(0, std::min(4, playX + 1));
- break;
- case 1:
- switch (custom[currentEditingIndex].type) {
- case BOOLEAN:
- custom[currentEditingIndex].currentOption = 1 - custom[currentEditingIndex].currentOption;
- break;
- case INTEGER:
- custom[currentEditingIndex].currentOption = std::min(custom[currentEditingIndex].Imax, std::max(custom[currentEditingIndex].Imin, custom[currentEditingIndex].currentOption + 1));
- break;
- case FLOAT:
- custom[currentEditingIndex].currentOption = std::min((int) log2(custom[currentEditingIndex].Fmax), std::max((int) log2(custom[currentEditingIndex].Fmin), custom[currentEditingIndex].currentOption + 1));
- break;
- case STRING:
- custom[currentEditingIndex].currentOption++;
- if (custom[currentEditingIndex].currentOption >= custom[currentEditingIndex].strings.size()) custom[currentEditingIndex].currentOption = 0;
- }
- break;
- case 2:
- switch (options[currentEditingIndex].type) {
- case BOOLEAN:
- options[currentEditingIndex].currentOption = 1 - options[currentEditingIndex].currentOption;
- break;
- case INTEGER:
- options[currentEditingIndex].currentOption = std::min(options[currentEditingIndex].Imax, std::max(options[currentEditingIndex].Imin, options[currentEditingIndex].currentOption + 1));
- break;
- }
- break;
- }
- }
- if ((e.key.keysym.sym == SDLK_RETURN || e.key.keysym.sym == SDLK_RETURN2) && !menuFocus) {
- switch (selectedMenuIndex) {
- case 0:
- startingLevel = 1 + playX + playY * 5;
- level = startingLevel;
- levelNumT.change(std::to_string(level));
- normalSpeed = 0.3F * (float) pow(level, 1.5F) + 0.7F;
- lockDelay = (float) (sqrt(level) + 2) / 6;
- fastSpeed = std::max(fastSpeed, normalSpeed);
- state = PLAYING;
- break;
- case 1:
- case 2:
- case 3:
- if (currentEditingIndex >= 0) {
- if (selectedMenuIndex == 2 && currentEditingIndex == 3) tileLength = options[3].currentOption;
- currentEditingIndex = -1;
- } else {
- currentEditingIndex = selectedSubmenuIndex;
- }
- break;
- }
- }
- if ((e.key.keysym.sym == SDLK_RETURN || e.key.keysym.sym == SDLK_RETURN2 || e.key.keysym.sym == SDLK_RIGHT) && menuFocus) {
- if (selectedMenuIndex == 4) {
- if (e.key.keysym.sym != SDLK_RIGHT)
- return false;
- } else {
- menuFocus = false;
- }
- }
- }
- break;
- default:
- break;
- }
- break;
- case SDL_KEYUP:
- if (e.key.keysym.sym == SDLK_DOWN) {
- isFast = false;
- }
- default:
- break;
- }
- }
- return true;
- }
- bool update(float deltaTime) {
- if (state == PLAYING) {
- if (isLocking) {
- lockTime += deltaTime;
- if (lockTime >= lockDelay) {
- addShape();
- isLocking = false;
- lockTime = 0;
- } else if (currentShape->fall(grid, false)) {
- isLocking = false;
- lockTime = 0;
- }
- } else {
- (isFast ? fastFallTime : normalFallTime) += deltaTime;
- if ((isFast ? fastFallTime : normalFallTime) >= 1 / (isFast ? fastSpeed : normalSpeed)) {
- (isFast ? fastFallTime : normalFallTime) -= 1 / (isFast ? fastSpeed : normalSpeed);
- if (isFast) {
- score++;
- scoreNumT.change(std::to_string(score));
- }
- fall();
- }
- }
- }
- if (state == MAIN_MENU) paintMenu(deltaTime);
- else paintGame();
- SDL_RenderPresent(renderer);
- return true;
- }
- void paintGame() {
- if (state != PAUSED) {
- int one = state == ENDED ? 208 : 64;
- SDL_SetRenderDrawColor(renderer, one, one, one, 255);
- SDL_RenderClear(renderer);
- int ghostY = currentShape->y;
- bool stop = false;
- do {
- ghostY++;
- for (int y = 0; y < tiles && !stop; y++) {
- for (int x = 0; x < tiles && !stop; x++) {
- if (currentShape->data[y][x].exists) {
- stop = (ghostY + y > 21 || grid[ghostY + y][currentShape->x + x].exists);
- }
- }
- }
- } while (!stop);
- for (int y = 0; y < tiles; y++) {
- for (int x = 0; x < tiles; x++) {
- if (currentShape->data[y][x].exists) {
- SDL_Rect tile = {tileLength * (x + currentShape->x + 6), tileLength * (y - 3 + ghostY), tileLength, tileLength};
- SDL_SetRenderDrawColor(renderer, 96, 96, 96, 255);
- SDL_RenderFillRect(renderer, &tile);
- }
- }
- }
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- if (grid[y][x].exists) {
- SDL_Rect tile = {tileLength * (x + 6), tileLength * (y - 2), tileLength, tileLength};
- if (state == PLAYING) {
- SDL_SetRenderDrawColor(renderer, grid[y][x].r, grid[y][x].g, grid[y][x].b, 255);
- } else {
- SDL_SetRenderDrawColor(renderer, (grid[y][x].r + 765) / 4, (grid[y][x].g + 765) / 4, (grid[y][x].b + 765) / 4, 255);
- }
- SDL_RenderFillRect(renderer, &tile);
- }
- }
- }
- for (int y = 0; y < tiles; y++) {
- for (int x = 0; x < tiles; x++) {
- if (!currentShape->data[y][x].exists && !debugShowDataArea) continue;
- SDL_Rect tile = {tileLength * (x + currentShape->x + 6), tileLength * (y - 2 + currentShape->y), tileLength, tileLength};
- if (debugShowDataArea)
- SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
- if (currentShape->data[y][x].exists || !debugShowDataArea) {
- if (state == PLAYING) {
- SDL_SetRenderDrawColor(renderer, (Uint8) ((1 - (lockTime / lockDelay)) * currentShape->data[y][x].r + (72 * (lockTime / lockDelay))), (Uint8) ((1 - (lockTime / lockDelay)) * currentShape->data[y][x].g + (72 * (lockTime / lockDelay))), (Uint8) ((1 - (lockTime / lockDelay)) * currentShape->data[y][x].b + (72 * (lockTime / lockDelay))), 255);
- } else {
- SDL_SetRenderDrawColor(renderer, (currentShape->data[y][x].r + 765) / 4, (currentShape->data[y][x].g + 765) / 4, (currentShape->data[y][x].b + 765) / 4, 255);
- }
- }
- SDL_RenderFillRect(renderer, &tile);
- }
- }
- int two = state == ENDED ? 224 : 128;
- SDL_SetRenderDrawColor(renderer, two, two, two, 255);
- for (int x = 0; x < width; x++) {
- SDL_Rect line = {tileLength * (6 + x) - gridLineWidth / 2, 0, gridLineWidth, screenHeight};
- SDL_RenderFillRect(renderer, &line);
- }
- for (int y = 1; y < height - 2; y++) {
- SDL_Rect line = {tileLength * 6, tileLength * y - gridLineWidth / 2, screenWidth - (tileLength * 6), gridLineWidth};
- SDL_RenderFillRect(renderer, &line);
- }
- }
- if (state != PLAYING) {
- if (state == ENDED) {
- SDL_SetRenderDrawColor(renderer, 64, 64, 64, 255);
- SDL_Rect pauseBox = {(int) (tileLength * 7.5), (int) (tileLength * 8.5), tileLength * 7, tileLength * 3};
- SDL_RenderFillRect(renderer, &pauseBox);
- } else {
- SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
- SDL_RenderClear(renderer);
- }
- menuT.change(state == ENDED ? "Game Over" : "Paused");
- menuT.paint(tileLength * 11, (int) (tileLength * 9.5));
- }
- SDL_Rect bar = {0, 0, tileLength * 6, tileLength * 20};
- SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
- SDL_RenderFillRect(renderer, &bar);
- bar = {tileLength * 16, 0, tileLength * 6, tileLength * 20};
- SDL_RenderFillRect(renderer, &bar);
- scoreT.paint(tileLength * 3, tileLength / 2);
- scoreNumT.paint(tileLength * 3, tileLength * 2);
- linesT.paint(tileLength * 3, (int) (tileLength * 3.5));
- linesNumT.paint(tileLength * 3, tileLength * 5);
- levelT.paint(tileLength * 3, (int) (tileLength * 6.5));
- levelNumT.paint(tileLength * 3, tileLength * 8);
- nextT.paint(tileLength * 19, tileLength / 2);
- SDL_Rect next = {(int) (tileLength * 16.5), (int) (tileLength * 2.5), tileLength * 5, tileLength * (3 * nextShapes)};
- SDL_SetRenderDrawColor(renderer, 64, 64, 64, 255);
- SDL_RenderFillRect(renderer, &next);
- int nextShapeIndex = shapeIndexes.size();
- for (unsigned x = 0; x < shapeIndexes.size(); x++) {
- if (shapeIndexes[x] != -1) {
- nextShapeIndex = x;
- break;
- }
- }
- for (int n = 0; n < nextShapes; n++) {
- int nextShape;
- gridArray shape(tiles, std::vector<Tile>(tiles));
- if (nextShapeIndex + n >= (int) shapeIndexes.size()) {
- nextShape = nextShapeIndexes[nextShapeIndex + n - shapeIndexes.size()];
- } else {
- nextShape = shapeIndexes[nextShapeIndex + n];
- }
- shape = Shape::shapes[nextShape];
- float dx = (nextShape == 0 || nextShape == 3 ? 17 : 17.5F);
- float dy = (nextShape == 3 ? 1 : (nextShape == 0 ? 0.5F : 0));
- for (int y = 0; y < tiles; y++) {
- for (int x = 0; x < tiles; x++) {
- if (!shape[y][x].exists) continue;
- SDL_Rect tile = {(int) (tileLength * (x + dx)), (int) (tileLength * (3 + y + (n * 3) - dy)), tileLength, tileLength};
- SDL_SetRenderDrawColor(renderer, shape[y][x].r, shape[y][x].g, shape[y][x].b, 255);
- SDL_RenderFillRect(renderer, &tile);
- }
- }
- }
- holdT.paint(tileLength * 3, tileLength * 11);
- SDL_Rect hold = {tileLength / 2, (int) (tileLength * 12.5), tileLength * 5, tileLength * 5};
- SDL_SetRenderDrawColor(renderer, 64, 64, 64, 255);
- SDL_RenderFillRect(renderer, &hold);
- if (heldIndex >= 0) {
- gridArray shape(tiles, std::vector<Tile>(tiles));
- shape = Shape::shapes[heldIndex];
- float dx = (heldIndex == 0 || heldIndex == 3 ? 1 : 1.5F);
- float dy = (heldIndex == 3 ? 1 : (heldIndex == 0 ? 0.5F : 0));
- for (int y = 0; y < tiles; y++) {
- for (int x = 0; x < tiles; x++) {
- if (!shape[y][x].exists) continue;
- SDL_Rect tile = {(int) (tileLength * (x + dx)), (int) (tileLength * (14 + y - dy)), tileLength, tileLength};
- SDL_SetRenderDrawColor(renderer, shape[y][x].r, shape[y][x].g, shape[y][x].b, 255);
- SDL_RenderFillRect(renderer, &tile);
- }
- }
- }
- }
- void paintMenu(float deltaTime) {
- SDL_SetRenderDrawColor(renderer, 64, 64, 64, 255);
- SDL_RenderClear(renderer);
- title.paint(screenWidth * 5 / 8, tileLength);
- for (int y = 0; y < 5; y++) {
- if (y == selectedMenuIndex) {
- float oldSize = mainSubs[y].size;
- mainSubs[y].size = std::min(1.75F, mainSubs[y].size + deltaTime * 6);
- if (menuFocus) {
- SDL_Color selected = {255, selectedMenuIndex == 4 ? 192 : 255, 192};
- mainSubs[y].text.change(mainSubs[y].text.text, (int) (tileLength * mainSubs[y].size), selected);
- } else {
- mainSubs[y].text.change(mainSubs[y].text.text, (int) (tileLength * mainSubs[y].size));
- }
- if (mainSubs[y].y > 0) {
- mainSubs[y].y = std::max(0.0F, mainSubs[y].y - deltaTime * 18);
- } else if (mainSubs[y].y < 0) {
- mainSubs[y].y = std::min(0.0F, mainSubs[y].y + deltaTime * 18);
- }
- } else {
- float oldSize = mainSubs[y].size;
- mainSubs[y].size = std::max(1.0F, mainSubs[y].size - deltaTime * 6);
- if (oldSize != mainSubs[y].size)
- mainSubs[y].text.change(mainSubs[y].text.text, (int) (tileLength * mainSubs[y].size));
- float targetY = 2.0F * (y - selectedMenuIndex);
- if (y > selectedMenuIndex) targetY++;
- if (mainSubs[y].y > targetY) {
- mainSubs[y].y = std::max(targetY, mainSubs[y].y - deltaTime * 18);
- } else if (mainSubs[y].y < targetY) {
- mainSubs[y].y = std::min(targetY, mainSubs[y].y + deltaTime * 18);
- }
- }
- mainSubs[y].text.paint(tileLength * 4, (int) (tileLength * (10.5 + mainSubs[y].y)));
- }
- if (selectedMenuIndex != 0 && selectedMenuIndex != 4) {
- SDL_Rect box = {(int) (tileLength * 7.5), (int) (tileLength * (5.75 + 1.25 * (float) selectedSubmenuIndex)), tileLength * 13, (int) (tileLength * 1.25)};
- if (menuFocus) {
- SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
- } else {
- SDL_SetRenderDrawColor(renderer, 128, 0, 255, 255);
- }
- SDL_RenderFillRect(renderer, &box);
- }
- switch (selectedMenuIndex) {
- case 0: // PLAY
- for (int n = 0; n < 10; n++) {
- SDL_Rect box = {(int) (tileLength * 7.25 + tileLength * 3 * (n < 5 ? n : n - 5)), (int) (tileLength * 9.75 + (n < 5 ? 0 : tileLength * 3)), (int) (tileLength * 2.25), (int) (tileLength * 2.25)};
- if (playX + playY * 5 == n && !menuFocus)
- SDL_SetRenderDrawColor(renderer, 128, 0, 255, 255);
- else
- SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
- SDL_RenderFillRect(renderer, &box);
- playOptions[n].paint((int) (tileLength * 8.25 + tileLength * 3 * (n < 5 ? n : n - 5)), tileLength * 10 + (n < 5 ? 0 : tileLength * 3));
- }
- break;
- case 1: // CUSTOM
- for (int n = 0; n < 11; n++) {
- custom[n].text.paint(tileLength * 8, (int) (tileLength * (6 + 1.25 * (float) n)), LEFT);
- switch (custom[n].type) {
- case BOOLEAN:
- if (custom[n].currentOption == 0) {
- custom[n].valueText.change("Disabled", (int) (tileLength * .6));
- } else {
- custom[n].valueText.change("Enabled", (int) (tileLength * .6));
- }
- break;
- case INTEGER:
- custom[n].valueText.change(std::to_string(custom[n].currentOption), (int) (tileLength * .6));
- break;
- case FLOAT:
- custom[n].valueText.change((custom[n].currentOption < 0 ? "1 / " : "") + (std::to_string((int) pow(2, abs(custom[n].currentOption)))), (int) (tileLength * .6));
- break;
- case STRING:
- custom[n].valueText.change(custom[n].strings[custom[n].currentOption], (int) (tileLength * .6));
- break;
- default:
- break;
- }
- if (n == currentEditingIndex) {
- SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
- SDL_Rect box = {(int) (tileLength * 19.9 - custom[n].valueText.getWidth()), (int) (tileLength * (5.9 + 1.25 * (float) n)), custom[n].valueText.getWidth() + (int) (tileLength * 0.3), (int) (tileLength * 0.95)};
- SDL_RenderFillRect(renderer, &box);
- }
- custom[n].valueText.paint(tileLength * 20, (int) (tileLength * (6 + 1.25 * (float) n)), RIGHT);
- }
- break;
- case 2: // OPTIONS
- for (int n = 0; n < 9; n++) {
- options[n].text.paint(tileLength * 8, (int) (tileLength * (6 + 1.25 * (float) n)), LEFT);
- switch (options[n].type) {
- case BOOLEAN:
- if (options[n].currentOption == 0) {
- options[n].valueText.change("Disabled", (int) (tileLength * .6));
- } else {
- options[n].valueText.change("Enabled", (int) (tileLength * .6));
- }
- break;
- case INTEGER:
- options[n].valueText.change(std::to_string(options[n].currentOption), (int) (tileLength * .6));
- break;
- default:
- break;
- }
- if (n == currentEditingIndex) {
- SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
- SDL_Rect box = {(int) (tileLength * 19.9 - options[n].valueText.getWidth()), (int) (tileLength * (5.9 + 1.25 * (float) n)), options[n].valueText.getWidth() + (int) (tileLength * 0.3), (int) (tileLength * 0.95)};
- SDL_RenderFillRect(renderer, &box);
- }
- options[n].valueText.paint(tileLength * 20, (int) (tileLength * (6 + 1.25 * (float) n)), RIGHT);
- }
- break;
- case 3: // CONTROLS
- for (int n = 0; n < 9; n++) {
- controls[n].text.paint(tileLength * 8, (int) (tileLength * (6 + 1.25 * (float) n)), LEFT);
- controls[n].keyText.change(n == currentEditingIndex ? "" : SDL_GetKeyName(controls[n].key), (int) (tileLength * .6));
- controls[n].keyText.paint(tileLength * 20, (int) (tileLength * (6 + 1.25 * (float) n)), RIGHT);
- }
- break;
- case 4: // EXIT
- break;
- default:
- while (true) {
- new int;
- } // TODO: YES
- }
- }
- fallState fall() {
- if (!currentShape->fall(grid, true)) {
- isLocking = true;
- return PLACED;
- }
- return FELL;
- }
- void addShape() {
- for (int x = 0; x < tiles; x++) {
- for (int y = 0; y < tiles; y++) {
- if (currentShape->data[y][x].exists) {
- grid[currentShape->y + y][currentShape->x + x] = currentShape->data[y][x];
- }
- }
- }
- int yMin = 0, linesCleared = 0;
- for (int y = height - 1; y >= yMin;) {
- bool blank = false;
- for (int x = 0; x < width; x++) {
- if (!grid[y][x].exists) {
- blank = true;
- break;
- }
- }
- if (!blank) {
- linesCleared++;
- lines++;
- linesNumT.change(std::to_string(lines));
- yMin++;
- for (int yy = y; yy >= 1; yy--) {
- for (int x = 0; x < width; x++) {
- grid[yy][x] = grid[yy - 1][x];
- }
- }
- for (int x = 0; x < width; x++) {
- grid[0][x].exists = false;
- }
- } else {
- y--;
- }
- }
- if (linesCleared > 0) {
- score += (int) (lineClearPoints[linesCleared - 1] * level * (linesCleared == 4 && lastClearDifficult ? lineClearPoints[4] : 1) + lineClearPoints[5] * lineClearCombos * level);
- scoreNumT.change(std::to_string(score));
- lastClearDifficult = linesCleared == 4;
- lineClearCombos++;
- level = lines / 10 + startingLevel;
- levelNumT.change(std::to_string(level));
- linesNumT.change(std::to_string(lines));
- normalSpeed = 0.3F * (float) pow(level, 1.5F) + 0.7F;
- lockDelay = (float) (sqrt(level) + 2.0F) / 6.0F;
- fastSpeed = std::max(fastSpeed, normalSpeed);
- } else {
- lineClearCombos = 0;
- }
- newShape();
- }
- void newShape() {
- for (unsigned i = 0; i < shapeIndexes.size(); i++) {
- if (shapeIndexes[i] == -1) continue;
- if (currentShape != NULL) {
- delete[] currentShape; // This is where it breaks to in the error
- }
- currentShape = new Shape;
- currentShape->data = Shape::shapes[shapeIndexes[i]];
- currentShapeIndex = shapeIndexes[i];
- shapeIndexes[i] = -1;
- for (int x = 0; x < tiles; x++) {
- for (int y = 0; y < tiles; y++) {
- if (currentShape->data[y][x].exists) {
- if (grid[currentShape->y + y][currentShape->x + x].exists) {
- state = ENDED;
- return;
- }
- }
- }
- }
- isFast = false;
- canHold = true;
- return;
- }
- shapeIndexes = nextShapeIndexes;
- for (int i = 0; i < 7; i++) nextShapeIndexes[i] = i;
- std::random_shuffle(nextShapeIndexes.begin(), nextShapeIndexes.end());
- newShape();
- }
- bool init() {
- if (SDL_INIT_VIDEO < 0) {
- printf("Error: Failed to initiate SDL Video Subsystem. SDL_Error: %s\n", SDL_GetError());
- return false;
- }
- window = SDL_CreateWindow("Polyis", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screenWidth, screenHeight, NULL);
- if (window == NULL) {
- printf("Error: Failed to create window. SDL Error: %s\n", SDL_GetError());
- return false;
- }
- renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
- if (renderer == NULL) {
- printf("Error: Failed to create renderer. SDL Error: %s\n", SDL_GetError());
- return false;
- }
- int imgFlags = IMG_INIT_PNG;
- if (!(IMG_Init(imgFlags) & imgFlags)) {
- printf("Error: Failed to initiate Image Subsystem. SDL_IMG Error: %s\n", IMG_GetError());
- return false;
- }
- if (TTF_Init() == -1) {
- printf("Error: Failed to initiate TTF Subsystem. SDL_TTF Error: %s\n", TTF_GetError());
- return false;
- }
- Text::defaultSize = tileLength;
- Text::renderer = renderer;
- SDL_Surface* icon = IMG_Load("icon.png");
- if (icon == NULL) {
- printf("Error: Failed to instatiate icon. Error: %s", IMG_GetError());
- }
- SDL_SetWindowIcon(window, icon);
- for (unsigned i = 0; i < Shape::shapes.size(); i++) {
- nextShapeIndexes.push_back(i);
- }
- std::random_shuffle(nextShapeIndexes.begin(), nextShapeIndexes.end());
- newShape();
- title.change("POLYIS", tileLength * 3, {0, 255, 0});
- mainSubs[0].text.change("Play", tileLength * 2);
- mainSubs[1].text.change("Custom");
- mainSubs[2].text.change("Options");
- mainSubs[3].text.change("Controls");
- mainSubs[4].text.change("Exit");
- mainSubs[0].size = 2;
- for (int i = 1; i < 5; i++) {
- mainSubs[i].y = 2.0F * i + 1.0F;
- }
- for (int i = 0; i < 10; i++) {
- playOptions[i].change(std::to_string(i + 1), (int) (tileLength * 1.5));
- }
- options[0].text.change("Master Volume", (int) (tileLength * .6));
- options[1].text.change("Music Volume", (int) (tileLength * .6));
- options[2].text.change("Sound FX Volume", (int) (tileLength * .6));
- options[3].text.change("Game Resolution", (int) (tileLength * .6));
- options[4].text.change("Ghost Piece", (int) (tileLength * .6));
- options[0].type = INTEGER;
- options[1].type = INTEGER;
- options[2].type = INTEGER;
- options[3].type = INTEGER;
- options[4].type = BOOLEAN;
- options[0].Imax = 100;
- options[1].Imax = 100;
- options[2].Imax = 100;
- options[3].Imax = 40;
- options[0].currentOption = 100;
- options[1].currentOption = 100;
- options[2].currentOption = 100;
- options[3].currentOption = 34;
- options[4].currentOption = 1;
- custom[0].text.change("Tiles per Polyomino", (int) (tileLength * .6));
- custom[1].text.change("Grid Width", (int) (tileLength * .6));
- custom[2].text.change("Grid Height", (int) (tileLength * .6));
- custom[3].text.change("Grid Shape", (int) (tileLength * .6));
- custom[4].text.change("Gravity Multiplier", (int) (tileLength * .6));
- custom[5].text.change("Gravity Direction", (int) (tileLength * .6));
- custom[6].text.change("Flood Fill Gravity", (int) (tileLength * .6));
- custom[7].text.change("Lives", (int) (tileLength * .6));
- custom[8].text.change("Shape Visibility", (int) (tileLength * .6));
- custom[9].text.change("Lock Delay Time", (int) (tileLength * .6));
- custom[10].text.change("Lines per Level", (int) (tileLength * .6));
- custom[0].type = INTEGER;
- custom[1].type = INTEGER;
- custom[2].type = INTEGER;
- custom[3].type = STRING;
- custom[4].type = FLOAT;
- custom[5].type = STRING;
- custom[6].type = BOOLEAN;
- custom[7].type = INTEGER;
- custom[8].type = STRING;
- custom[9].type = FLOAT;
- custom[10].type = INTEGER;
- custom[0].Imin = 1;
- custom[0].Imax = 15;
- custom[1].Imin = 1;
- custom[1].Imax = 255;
- custom[2].Imin = 1;
- custom[2].Imax = 255;
- custom[3].strings = {"Rectangle", "Circle", "Triangle", "Hexagon", "Arrow"};
- custom[4].Fmin = 0.125F;
- custom[4].Fmax = 16;
- custom[5].strings = {"Down", "Up", "Left", "Right"};
- custom[7].Imax = 15;
- custom[8].strings = {"Always", "On Ground Only", "Falling Only", "After Falling (Momentary)", "Never", "LSD Mode"};
- custom[9].Fmin = 0.125F;
- custom[9].Fmax = 16;
- custom[10].Imin = 2;
- custom[10].Imax = 255;
- custom[0].currentOption = 4;
- custom[1].currentOption = 10;
- custom[2].currentOption = 22;
- custom[10].currentOption = 10;
- controls[0].text.change("Move Left", (int) (tileLength * .6));
- controls[1].text.change("Move Right", (int) (tileLength * .6));
- controls[2].text.change("Soft Drop (Move down)", (int) (tileLength * .6));
- controls[3].text.change("Hard Drop", (int) (tileLength * .6));
- controls[4].text.change("Rotate Clockwise", (int) (tileLength * .6));
- controls[5].text.change("Rotate Counterclockwise", (int) (tileLength * .6));
- controls[6].text.change("Hold Shape", (int) (tileLength * .6));
- controls[7].text.change("Pause", (int) (tileLength * .6));
- controls[8].text.change("Debug Mode", (int) (tileLength * .6));
- controls[0].key = SDLK_LEFT;
- controls[1].key = SDLK_RIGHT;
- controls[2].key = SDLK_DOWN;
- controls[3].key = SDLK_SPACE;
- controls[4].key = SDLK_UP;
- controls[5].key = SDLK_z;
- controls[6].key = SDLK_c;
- controls[7].key = SDLK_p;
- controls[8].key = SDLK_F7;
- scoreT.change("Score");
- scoreNumT.change("0");
- linesT.change("Lines");
- linesNumT.change("0");
- levelT.change("Level");
- levelNumT.change("1");
- nextT.change("Next");
- holdT.change("Hold");
- return true;
- }
- void close() {
- SDL_DestroyWindow(window);
- SDL_DestroyRenderer(renderer);
- window = NULL;
- renderer = NULL;
- IMG_Quit();
- TTF_Quit();
- SDL_Quit();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement