Transferred from GitHub

This commit is contained in:
Maddox Werts 2024-05-08 13:50:29 -04:00
parent 53130bf748
commit 16ccfe61b4
19 changed files with 1282 additions and 0 deletions

28
Makefile Normal file
View file

@ -0,0 +1,28 @@
# Variables
LIBS:= -lSDL2main -lSDL2 -lSDL2_image -lSDL2_ttf
TARGET:= minesweeper
# Instructions
build: compile link run
compile:
g++ -c -I include source/engine/vectors.cpp -o bin/vectors.o
g++ -c -I include source/engine/engine.cpp -o bin/engine.o
g++ -c -I include source/game/tilemap.cpp -o bin/tilemap.o
g++ -c -I include source/game/navbar.cpp -o bin/navbar.o
g++ -c -I include source/game/message.cpp -o bin/message.o
g++ -c -I include source/main.cpp -o bin/main.o
link:
g++ bin/*.o -L lib $(LIBS) -o build/$(TARGET)
cpydat:
cp data -r build
run:
./build/$(TARGET)
# Complimentary
clean:
rm build/*
rm bin/*

BIN
assets/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
{"modelVersion":2,"piskel":{"name":"Tileset","description":"","fps":12,"height":16,"width":16,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":12,\"chunks\":[{\"layout\":[[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMAAAAAQCAYAAABA4nAoAAADLElEQVRoQ+2avW7CMBDHg1QxsXZhZ2Nphk48ACtT36ElSyekzpWYupT2HfoeTB3ShQdgQCxdmVAl2gu61rne+SskGOEsSAkXn8//n8/nuJVl2S7xuFarVbJYLJLhcOhhnSRo72UcjWIEDhSBlg8Aqnh9AKDi73Q6bHcGg0Eyn8/Frm42m+KZZG+KUbSP8fsFQCc0TkgoHgTA114n4AiAHmEO4JuLvDB6+0pLxtx9aj9er01zRvF81u0Wv1z7l4+vxnd8Ptyy9nm+9113pelfv6QJLB9/sK9IZ1el+2BfOwDv223R6HW7/a9xvIEzOAoefukFgFEg6p7B77P9gDw9l8WEvnHtv+SZOH536TMbA+w/xkp6gRRDNQP6AmArfh0ANuIH+yoAgD1CwMVfEj/GVIWgVgDoYNoAAE5y4kfnaZapEwAUvwsAOvFjH1QIqP8mAOhEcsgMgADg7G6YiIvHtH0EAAVueofr+GGGsAGAzvYIRiMAcANpAwCKH3+5ZZV6zzWAdEAke1X8PgDQmR7egXDoANAJhsukEYD/NQwndIhrowBAgz4ZIAQAqPhdANAJuGkAJF/U2kAFyGYJRLNDkxmAzv5cBpKEfhQAcABsagCfnSTIBHVlAPTdpwaQhGcLgGkZpGZSqf9YB3C+SADAf10h0AEg1QPq8shl/FwBkMahkSUQbXwymSTT6bR0GzsPN9Ui2LRubGIJdEgAaF1gWgLpALApgqX42ewC6WLP1Qg+AEAbUhEstc+JX8oA6mxP33eUXSBw4hwB0AkfB8ZlBrStAUIBgPODFsm2/XcBIJgaQA2ALQBgE8ouEPjiswSyEX4EgP8OwEEjiV/KAMEAAKLnLlwKSUsg3O+ntqfwHUAVP7cTRPtkOwOC3TlmAJ34gwZAEj8KACDgAKACOdaXYG4nCHyjH8SogEP4DlBlCXSoIlhXS7jUAFUAkHxgi2A4m7NcLk1+l56rRyGq2MNLQzsLFCoAdRfBJgBM26AwlqavwS67QD4AgA9ORyFGo9EOTnX6Xv1+vzgVWuWKh9n4w4CmmLosobh3Rfufs0C9Xs/rOLRpcOLzGIFTiMA3iwMNLeSNeBkAAAAASUVORK5CYII=\"}]}"],"hiddenFrames":[null]}}

View file

@ -0,0 +1 @@
{"modelVersion":2,"piskel":{"name":"glyph","description":"","fps":12,"height":16,"width":16,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":13,\"chunks\":[{\"layout\":[[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]],\"base64PNG\":\"data:image/png;base64,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\"}]}"],"hiddenFrames":[null]}}

BIN
data/fonts/font.ttf Normal file

Binary file not shown.

BIN
data/sprites/glyph.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
data/sprites/tileset.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 B

45
include/engine/engine.h Normal file
View file

@ -0,0 +1,45 @@
// Define once
#ifndef H_ENGINE
#define H_ENGINE
// Includes
/// External
#include "externals.h"
/// Engine
#include "vectors.h"
// Constants
#define SCR_WIDTH 512
#define SCR_HEIGHT 562
#define SCR_H_BUFFER 50
// Classes
class Engine{
private:
// Variables
SDL_Window* window;
Uint32 last;
public:
// Variables
static double deltaTime;
static SDL_Renderer* renderer;
static Vector2 mousePos;
static int clicking;
bool running;
// Constructor
Engine();
// Functions
void Update();
void Clear();
void Display();
void Delete();
};
// End definition
#endif

View file

@ -0,0 +1,20 @@
// Define once
#ifndef H_EXTERNALS
#define H_EXTERNALS
// Includes
/// System
#include <iostream>
#include <random>
#include <fstream>
#include <vector>
#include <math.h>
#include <cstdlib>
#include <ctime>
/// SDL2
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
// End definition
#endif

25
include/engine/vectors.h Normal file
View file

@ -0,0 +1,25 @@
// Define once
#ifndef H_VECTORS
#define H_VECTORS
// Includes
#include <iostream>
// Structure
typedef struct Vector2{
// Variables
float x,y;
// Constructor
Vector2();
Vector2(float x, float y);
// Operations
Vector2 operator+(Vector2 b);
Vector2 operator*(float b);
void operator+=(Vector2 b);
void operator*=(float b);
} Vector2;
// End definition
#endif

34
include/game/message.h Normal file
View file

@ -0,0 +1,34 @@
// Define once
#ifndef H_MESSAGE
#define H_MESSAGE
// Includes
/// Externals
#include <engine/externals.h>
/// Engine
#include <engine/engine.h>
/// Game
#include "tilemap.h"
// Classes
class Message{
private:
// Variables
SDL_Texture* texture;
int x,y;
int w,h;
public:
// Variables
// Constructors
Message(const char* msg);
// Functions
void Update();
void Draw();
};
// End definition
#endif

42
include/game/navbar.h Normal file
View file

@ -0,0 +1,42 @@
// Define once
#ifndef H_NAVBAR
#define H_NAVBAR
// Includes
/// Externals
#include <engine/externals.h>
/// Engine
#include <engine/engine.h>
/// Game
#include <game/tilemap.h>
// Classes
class Navbar{
private:
// Variables
Tilemap* tilemap;
SDL_Texture* texture;
bool didClick;
// Functions
void _drawBackground();
void _drawFlagCounter();
void _drawFace();
void _drawTime();
Vector2 _getNumber(int number);
public:
// Variables
// Constructor
Navbar(Tilemap* tilemap);
// Functions
void Update();
void Draw();
};
// End definition
#endif

65
include/game/tilemap.h Normal file
View file

@ -0,0 +1,65 @@
// Define once
#ifndef H_TILEMAP
#define H_TILEMAP
// Includes
/// Externals
#include <engine/externals.h>
/// Engine
#include <engine/engine.h>
// Constants
#define GRID_W 10
#define GRID_H 10
#define GRID_B 10
// Classes
class Tilemap{
private:
// Variables
std::vector<int> grid_bomb;
std::vector<int> grid_flag;
std::vector<int> grid_show;
SDL_Texture* texture;
int savedClick = 0;
bool didClick;
bool gameBegan;
bool cascading;
float timepassed;
// Functions
void _init();
void createGrid(Vector2 mousePos);
int getSurrounding(Vector2 tilePos);
void revealTiles(Vector2 mousePos);
void spawnCascade(Vector2 position);
void _leftClick();
void _rightClick();
void winDetection();
void clickDetection();
public:
// Variables
bool playing;
bool win;
int flags;
int gameTime;
// Constructors
Tilemap();
// Functions
void Update();
void Draw();
void Reset();
};
// End definiton
#endif

85
source/engine/engine.cpp Normal file
View file

@ -0,0 +1,85 @@
// Header
#include <engine/engine.h>
// Variables
double Engine::deltaTime;
SDL_Renderer* Engine::renderer;
Vector2 Engine::mousePos;
int Engine::clicking;
// Constructor
Engine::Engine(){
// Init SDL2
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
// Create a window
window = SDL_CreateWindow("Minesweeper",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
SCR_WIDTH, SCR_HEIGHT,
SDL_WINDOW_SHOWN);
if(window == NULL){
throw("Failed to create an SDL window.\n");
}
// Create a renderer
Engine::renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED);
if(Engine::renderer == NULL){
throw("Failed to create an SDL renderer.\n");
}
// Staring SDL2 subsystems
IMG_Init(IMG_INIT_PNG);
TTF_Init();
// We're running!
running = true;
clicking = false;
}
// Functions
void Engine::Update(){
// Getting events
SDL_Event event;
// Polling
while(SDL_PollEvent(&event)){
switch(event.type){
case SDL_QUIT:
running = false;
break;
case SDL_MOUSEMOTION:
Engine::mousePos = Vector2(event.motion.x, event.motion.y);
break;
case SDL_MOUSEBUTTONDOWN:
if(event.button.button == SDL_BUTTON_LEFT){
clicking = 1;
}
else if(event.button.button == SDL_BUTTON_RIGHT){
clicking = 2;
}
break;
case SDL_MOUSEBUTTONUP:
clicking = 0;
break;
}
}
// Calculate deltaTime
Uint32 now = SDL_GetTicks();
Engine::deltaTime = (now - last) / 1000.0f;
last = now;
}
void Engine::Clear(){
SDL_SetRenderDrawColor(Engine::renderer, 0,0,0, 1);
SDL_RenderClear(Engine::renderer);
}
void Engine::Display(){
SDL_RenderPresent(Engine::renderer);
}
void Engine::Delete(){
SDL_DestroyRenderer(Engine::renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}

26
source/engine/vectors.cpp Normal file
View file

@ -0,0 +1,26 @@
// Header
#include <engine/vectors.h>
// Constructor
Vector2::Vector2(){
x = 0;
y = 0;
}
Vector2::Vector2(float x, float y){
this->x = x;
this->y = y;
}
// Operations
Vector2 Vector2::operator+(Vector2 b){
return Vector2(x + b.x, y + b.y);
}
Vector2 Vector2::operator*(float b){
return Vector2(x * b, y * b);
}
void Vector2::operator+=(Vector2 b){
x += b.x; y += b.y;
}
void Vector2::operator*=(float b){
x *= b; y *= b;
}

38
source/game/message.cpp Normal file
View file

@ -0,0 +1,38 @@
// Header
#include <game/message.h>
// Constructors
Message::Message(const char* msg){
// Loading fonts
TTF_Font* font = TTF_OpenFont("data/fonts/font.ttf", 64);
if(font == NULL){
throw("Failed to load font.\n");
}
// Surface to texture
SDL_Surface* surf = TTF_RenderText_Blended(font, msg, {255,255,255});
texture = SDL_CreateTextureFromSurface(Engine::renderer, surf);
// Variables
this->x = (SCR_WIDTH/2) - (surf->w / 2);
this->y = (SCR_HEIGHT/2) - (surf->h / 2);
this->w = surf->w;
this->h = surf->h;
// Cleanup
SDL_FreeSurface(surf);
}
// Functions
void Message::Update(){
}
void Message::Draw(){
SDL_SetRenderDrawColor(Engine::renderer, 255,255,255, 1);
SDL_Rect rect;
rect.x = x; rect.y = y;
rect.w = w; rect.h = h;
SDL_RenderCopy(Engine::renderer, texture, NULL, &rect);
}

359
source/game/navbar.cpp Normal file
View file

@ -0,0 +1,359 @@
// Header
#include <game/navbar.h>
// Constructor
Navbar::Navbar(Tilemap* tilemap){
// Setting variables
this->tilemap = tilemap;
didClick = false;
// Getting texture
SDL_Surface* surf = IMG_Load("data/sprites/glyph.png");
if(surf == NULL){
throw("Failed to load Glyph surface.\n");
}
texture = SDL_CreateTextureFromSurface(Engine::renderer, surf);
SDL_FreeSurface(surf);
}
// Functions
/// Private
void Navbar::_drawBackground(){
// Making a rect for the top
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = SCR_WIDTH;
rect.h = SCR_H_BUFFER;
// Color
SDL_SetRenderDrawColor(Engine::renderer, 190,190,190, 1);
SDL_RenderFillRect(Engine::renderer, &rect);
}
void Navbar::_drawFlagCounter(){
if(tilemap->flags < 10){
// Positional rect
SDL_Rect rect;
rect.x = SCR_WIDTH / 10;
rect.y = 0;
rect.w = 50; rect.h = 50;
// Frame
SDL_Rect frame;
frame.x = 0; frame.y = 0;
frame.w = 16; frame.h = 16;
// What number?
switch(tilemap->flags){
case 0:
frame.x = 0;
frame.y = 0;
break;
case 1:
frame.x = 1;
frame.y = 0;
break;
case 2:
frame.x = 2;
frame.y = 0;
break;
case 3:
frame.x = 3;
frame.y = 0;
break;
case 4:
frame.x = 4;
frame.y = 0;
break;
case 5:
frame.x = 0;
frame.y = 1;
break;
case 6:
frame.x = 1;
frame.y = 1;
break;
case 7:
frame.x = 2;
frame.y = 1;
break;
case 8:
frame.x = 3;
frame.y = 1;
break;
case 9:
frame.x = 4;
frame.y = 1;
break;
}
// Scaling to size
frame.x *= 16;
frame.y *= 16;
// Drawing
SDL_SetRenderDrawColor(Engine::renderer, 255,255,255, 1);
SDL_RenderCopy(Engine::renderer, texture, &frame, &rect);
}
else{
// Positional rect
SDL_Rect rect;
rect.x = SCR_WIDTH / 10;
rect.y = 0;
rect.w = 50; rect.h = 50;
// Frame
SDL_Rect frame;
frame.x = 0; frame.y = 0;
frame.w = 16; frame.h = 16;
Vector2 fPos = _getNumber(tilemap->flags%10);
frame.x = fPos.x;
frame.y = fPos.y;
// Drawing
SDL_SetRenderDrawColor(Engine::renderer, 255,255,255, 1);
SDL_RenderCopy(Engine::renderer, texture, &frame, &rect);
// The second one
rect.x -= 50;
fPos = _getNumber((tilemap->flags / 10)%10);
frame.x = fPos.x;
frame.y = fPos.y;
// Drawing
SDL_SetRenderDrawColor(Engine::renderer, 255,255,255, 1);
SDL_RenderCopy(Engine::renderer, texture, &frame, &rect);
}
}
void Navbar::_drawFace(){
// Shapes
SDL_Rect rect;
SDL_Rect frame;
rect.x = (SCR_WIDTH / 2) - (25);
rect.y = 0;
rect.w = 50; rect.h = 50;
frame.w = 16;
frame.h = 16;
// This face is gonna be weird to draw..
if(Engine::clicking){
// Anxious face
frame.x = 1;
frame.y = 2;
}
else if(!tilemap->playing && !tilemap->win){
// Sad face
frame.x = 2;
frame.y = 2;
}
else{
// Happy face
frame.x = 0;
frame.y = 2;
}
// Scaling to size
frame.x *= 16;
frame.y *= 16;
// Drawing
SDL_SetRenderDrawColor(Engine::renderer, 255,255,255, 1);
SDL_RenderCopy(Engine::renderer, texture, &frame, &rect);
}
void Navbar::_drawTime(){
if(tilemap->gameTime < 10){
// Positional rect
SDL_Rect rect;
rect.x = SCR_WIDTH / 1.2f;
rect.y = 0;
rect.w = 50; rect.h = 50;
// Frame
SDL_Rect frame;
frame.x = 0; frame.y = 0;
frame.w = 16; frame.h = 16;
// What number?
switch(tilemap->gameTime){
case 0:
frame.x = 0;
frame.y = 0;
break;
case 1:
frame.x = 1;
frame.y = 0;
break;
case 2:
frame.x = 2;
frame.y = 0;
break;
case 3:
frame.x = 3;
frame.y = 0;
break;
case 4:
frame.x = 4;
frame.y = 0;
break;
case 5:
frame.x = 0;
frame.y = 1;
break;
case 6:
frame.x = 1;
frame.y = 1;
break;
case 7:
frame.x = 2;
frame.y = 1;
break;
case 8:
frame.x = 3;
frame.y = 1;
break;
case 9:
frame.x = 4;
frame.y = 1;
break;
}
// Scaling to size
frame.x *= 16;
frame.y *= 16;
// Drawing
SDL_SetRenderDrawColor(Engine::renderer, 255,255,255, 1);
SDL_RenderCopy(Engine::renderer, texture, &frame, &rect);
}
else{
// Positional rect
SDL_Rect rect;
rect.x = SCR_WIDTH / 1.2f;
rect.y = 0;
rect.w = 50; rect.h = 50;
// Frame
SDL_Rect frame;
frame.x = 0; frame.y = 0;
frame.w = 16; frame.h = 16;
Vector2 fPos = _getNumber(tilemap->gameTime%10);
frame.x = fPos.x;
frame.y = fPos.y;
// Drawing
SDL_SetRenderDrawColor(Engine::renderer, 255,255,255, 1);
SDL_RenderCopy(Engine::renderer, texture, &frame, &rect);
// The second one
rect.x -= 50;
fPos = _getNumber((tilemap->gameTime / 10)%10);
frame.x = fPos.x;
frame.y = fPos.y;
// Drawing
SDL_SetRenderDrawColor(Engine::renderer, 255,255,255, 1);
SDL_RenderCopy(Engine::renderer, texture, &frame, &rect);
}
}
Vector2 Navbar::_getNumber(int number){
// Result
Vector2 frame(0,0);
// What number?
switch(number){
case 0:
frame.x = 0;
frame.y = 0;
break;
case 1:
frame.x = 1;
frame.y = 0;
break;
case 2:
frame.x = 2;
frame.y = 0;
break;
case 3:
frame.x = 3;
frame.y = 0;
break;
case 4:
frame.x = 4;
frame.y = 0;
break;
case 5:
frame.x = 0;
frame.y = 1;
break;
case 6:
frame.x = 1;
frame.y = 1;
break;
case 7:
frame.x = 2;
frame.y = 1;
break;
case 8:
frame.x = 3;
frame.y = 1;
break;
case 9:
frame.x = 4;
frame.y = 1;
break;
}
// Scaling to size
frame.x *= 16;
frame.y *= 16;
// Return result
return frame;
}
/// Public
void Navbar::Update(){
// Did we click on the face?
if(Engine::clicking
&& !didClick){
// Clicking!
didClick = true;
// Getting the mouse position
Vector2 mPos = Engine::mousePos;
// Constant
const int mid_w = SCR_WIDTH / 2;
// Face clicking?
if(mPos.x >= mid_w - 50
&& mPos.x <= mid_w + 50
&& mPos.y <= SCR_H_BUFFER){
// Restart game
tilemap->Reset();
}
}
if(!Engine::clicking){
didClick = false;
}
}
void Navbar::Draw(){
// Drawing stuff in order
/// Background
_drawBackground();
/// Flags counter
_drawFlagCounter();
/// Smiley face
_drawFace();
/// Time
_drawTime();
}

453
source/game/tilemap.cpp Normal file
View file

@ -0,0 +1,453 @@
// Header
#include <game/tilemap.h>
// Constructors
Tilemap::Tilemap(){
_init();
}
// Functions
/// Private
void Tilemap::_init(){
// Reset all of our grids
grid_bomb.clear();
grid_flag.clear();
grid_show.clear();
// Adding all tiles to the map
for(int y = 0; y < GRID_H; y++){
for(int x = 0; x < GRID_W; x++){
grid_bomb.push_back(0);
grid_flag.push_back(0);
grid_show.push_back(0);
}
}
// Loading texture
SDL_Surface* surf = IMG_Load("data/sprites/tileset.png");
if(surf == NULL){
printf("ERROR: %s\n", IMG_GetError());
throw("Failed to load tiles.\n");
}
texture = SDL_CreateTextureFromSurface(Engine::renderer, surf);
SDL_FreeSurface(surf);
// Variables
playing = true;
flags = GRID_B;
savedClick = 0;
didClick = true;
cascading = false;
win = true;
gameTime = 0;
timepassed = 0;
gameBegan = false;
}
void Tilemap::createGrid(Vector2 mousePos){
for(int i = 0; i < GRID_B; i++){
// Completly random number
srand(time(NULL));
// Placeholder position
Vector2 _bombPos = Vector2(0,0);
// Loop!
while(true){
_bombPos = Vector2(
floor(rand() % GRID_W),
floor(rand() % GRID_H)
);
if(!grid_bomb[_bombPos.y*GRID_H+_bombPos.x]
&& _bombPos.x != mousePos.x
&& _bombPos.y != mousePos.y){
break;
}
}
// Apply position
grid_bomb[_bombPos.y*GRID_H+_bombPos.x] = 1;
}
gameBegan = true;
}
int Tilemap::getSurrounding(Vector2 tilePos){
// Result
int result = 0;
// Finding surrounding tiles
for(int y = -1; y < 2; y++){
for(int x = -1; x < 2; x++){
// Out of bounds?
if(tilePos.x + x < 0
|| tilePos.x + x >= GRID_W
|| tilePos.y + y < 0
|| tilePos.y + y >= GRID_H){
continue;
}
// Otherwise good to go!
result += grid_bomb[(y+tilePos.y)*GRID_H+(x+tilePos.x)];
}
}
// Return result
return result;
}
void Tilemap::revealTiles(Vector2 mousePos){
// What's the mouse position
int _gridPos = mousePos.y*GRID_H+mousePos.x;
printf("Grid Position: %i\n", _gridPos); // Debug
// Was it a flag?
if(grid_flag[_gridPos]) {return;}
// Setting the grid position to VISIBLE
grid_show[_gridPos] = 1;
// Rippling
cascading = true;
while(cascading){
spawnCascade(mousePos);
}
// Clicked on a bomb?
// TODO: Add game over functionality
if(grid_bomb[_gridPos]){
win = false;
playing = false;
}
}
void Tilemap::spawnCascade(Vector2 position){
// For clicking on a tile with a bomb next to it,
// it gets annoying when it clears everything
// when you're trying to click on a tile right next
// to the bomb.
if(getSurrounding(position) != 0){
cascading = false;
return;
}
// Checking if there is a bomb near the current tile
// And duplication
for(int y = -1; y < 2; y++){
for(int x = -1; x < 2; x++){
// Checking for failure cases
if(x == 0 && y == 0){
// Center
continue;
}
if(x + position.x < 0 || x + position.x > GRID_W
|| y + position.y < 0 || y + position.y > GRID_H){
// Out of bounds
continue;
}
// Diagonal
if(x == -1 && y == -1
&& x == -1 && y == +1
&& x == +1 && y == +1
&& x == +1 && y == -1){
continue;
}
// Flag near?
if(grid_flag[(position.y+y)*GRID_W+(position.x+x)]){
continue;
}
// Bombs near?
if(getSurrounding(position + Vector2(x,y)) != 0){
grid_show[(position.y+y)*GRID_W+(position.x+x)] = 1;
continue;
}
// Duplication
if(!grid_show[(position.y+y)*GRID_W+(position.x+x)]
&& !grid_bomb[(position.y+y)*GRID_W+(position.x+x)]){
grid_show[(position.y+y)*GRID_W+(position.x+x)] = 1;
spawnCascade(Vector2(position.x + x, position.y + y));
}
}
}
// Checking for a failure
for(int y = -1; y < 2; y++){
for(int x = -1; x < 2; x++){
// Checking for failure cases
if(x == 0 && y == 0){
// Center
continue;
}
if(x + position.x < 0 || x + position.x > GRID_W
|| y + position.y < 0 || y + position.y > GRID_H){
// Out of bounds
continue;
}
// Checking if there is a space that needs to be filled
if(!grid_show[(position.y+y)*GRID_W+(position.x+x)]
&& !grid_bomb[(position.y+y)*GRID_W+(position.x+x)]){
return;
}
}
}
// Failing
cascading = false;
}
void Tilemap::_leftClick(){
// Convert mouse position into local grid position
Vector2 _mGridPos = Vector2(
floor(Engine::mousePos.x / (SCR_WIDTH / GRID_W)),
floor(
(Engine::mousePos.y + SCR_H_BUFFER) / ((SCR_HEIGHT - SCR_H_BUFFER) / GRID_H))
- ((SCR_H_BUFFER / ((SCR_HEIGHT - SCR_H_BUFFER) / GRID_H)) + 2)
);
// Do we need a new grid?
int _totalBombs = 0;
for(int i = 0; i < grid_bomb.size(); i++){
_totalBombs += grid_bomb[i];
}
if(_totalBombs == 0){
createGrid(_mGridPos);
}
// Reveal the tiles!
revealTiles(_mGridPos);
}
void Tilemap::_rightClick(){
// Convert mouse position into local grid position
Vector2 _mGridPos = Vector2(
floor(Engine::mousePos.x / (SCR_WIDTH / GRID_W)),
floor(
(Engine::mousePos.y + SCR_H_BUFFER) / ((SCR_HEIGHT - SCR_H_BUFFER) / GRID_H))
- ((SCR_H_BUFFER / ((SCR_HEIGHT - SCR_H_BUFFER) / GRID_H)) + 2)
);
int _gridPos = _mGridPos.y*GRID_H+_mGridPos.x;
// Are we clicking on an existing tile?
if(grid_show[_gridPos]) {return;}
// Do we want to add or remove?
if(grid_flag[_gridPos]){
// Remove
flags++;
grid_flag[_gridPos] = 0;
}
else{
// Add
if(flags <= 0) {return;}
flags--;
grid_flag[_gridPos] = 1;
}
}
void Tilemap::winDetection(){
// How many bombs are there, and do they match
// Up with our flag positions?
int _matchedBombs = 0;
for(int y = 0; y < GRID_H; y++){
for(int x = 0; x < GRID_W; x++){
if(grid_bomb[y*GRID_H+x]
&& grid_flag[y*GRID_H+x]){
_matchedBombs++;
}
}
}
// Matched bombs == Bombs?
if(_matchedBombs == GRID_B){
playing = false;
win = true;
}
}
void Tilemap::clickDetection(){
// Are we even playing?
if(!playing) {return;}
// Left clicking
if(!didClick
&& Engine::clicking == 1){
// One click at a time!
savedClick = 1;
didClick = true;
}
// Right clicking
else if(!didClick
&& Engine::clicking == 2){
// One click at a time!
savedClick = 2;
didClick = true;
// Right click
_rightClick();
}
// Allow new click (LEFT)
else if(didClick
&& savedClick == 1
&& Engine::clicking == 0){
// Allow new click
didClick = false;
// Left click
_leftClick();
savedClick = 0;
}
else if(didClick
&& Engine::clicking == 0){
didClick = false;
savedClick = 0;
}
}
/// Public
void Tilemap::Update(){
// Win detection
winDetection();
// Click detection
clickDetection();
// Time passing
if(gameBegan
&& playing){
if(timepassed >= 1.0f){
timepassed = 0;
gameTime++;
if(gameTime > 99) {gameTime = 99;}
}
else{
timepassed += (float)Engine::deltaTime;
}
}
}
void Tilemap::Draw(){
// Getting sizes
int tileWidth = (int)(SCR_WIDTH / GRID_W);
int tileHeight = (int)((SCR_HEIGHT - SCR_H_BUFFER) / GRID_H);
// Going through all tiles
for(int y = 0; y < GRID_H; y++){
for(int x = 0; x < GRID_W; x++){
// Global Tile
SDL_Rect rect;
rect.x = x * tileWidth;
rect.y = (y * tileHeight) + SCR_H_BUFFER;
rect.w = tileWidth;
rect.h = tileHeight;
// Frame
SDL_Rect frame_rect;
frame_rect.w = 16;
frame_rect.h = 16;
int frame = 0;
// Shown tile, not a bomb
if(!playing
&& grid_bomb[y*GRID_H+x]){
frame = 2;
}
else if(grid_show[y*GRID_W+x]
&& !grid_bomb[y*GRID_H+x]){
frame = 0;
}
else if(grid_flag[y*GRID_H+x]){
frame = 1;
}
else{
frame = 3;
}
// Setting frame rect
switch(frame){
case 0:
switch(getSurrounding(Vector2(x,y))){
case 0:
frame_rect.x = 3;
frame_rect.y = 0;
break;
case 1:
frame_rect.x = 0;
frame_rect.y = 1;
break;
case 2:
frame_rect.x = 1;
frame_rect.y = 1;
break;
case 3:
frame_rect.x = 2;
frame_rect.y = 1;
break;
case 4:
frame_rect.x = 3;
frame_rect.y = 1;
break;
case 5:
frame_rect.x = 0;
frame_rect.y = 2;
break;
case 6:
frame_rect.x = 1;
frame_rect.y = 2;
break;
case 7:
frame_rect.x = 2;
frame_rect.y = 2;
break;
case 8:
frame_rect.x = 3;
frame_rect.y = 2;
break;
default:
printf("Something went very wrong while checking for SURROUNDING.\n");
break;
}
break;
case 1:
frame_rect.x = 1;
frame_rect.y = 0;
break;
case 2:
frame_rect.x = 2;
frame_rect.y = 0;
break;
case 3:
frame_rect.x = 0;
frame_rect.y = 0;
break;
default:
printf("TILESET RENDERING ERROR.\n");
break;
}
// Multiplying
frame_rect.x *= 16;
frame_rect.y *= 16;
// Drawing
SDL_SetRenderDrawColor(Engine::renderer, 255, 255,255, 1);
SDL_RenderFillRect(Engine::renderer, &rect);
SDL_RenderCopy(Engine::renderer, texture, &frame_rect, &rect);
}
}
// DEBUG
}
void Tilemap::Reset(){
// Resetting the game! (VERY DIFFICULT)
printf("Reset.\n");
// Reset!
_init();
}

60
source/main.cpp Normal file
View file

@ -0,0 +1,60 @@
// For windows
#define SDL_MAIN_HANDLED
// Includes
/// External
#include <engine/externals.h>
/// Engine
#include <engine/engine.h>
/// Game
#include <game/tilemap.h>
#include <game/navbar.h>
#include <game/message.h>
// Entry Point
int main(int argc, char* argv[]){
// Creating an engine
Engine engine = Engine();
Tilemap tilemap = Tilemap();
Navbar navbar = Navbar(&tilemap);
// Messages
Message gameOver("Game Over!");
Message youWin("You Win!");
// Game loop
while(engine.running){
// Update
engine.Update();
// Clear
engine.Clear();
// Game code..
tilemap.Update();
navbar.Update();
// Render code..
tilemap.Draw();
navbar.Draw();
/// Messages?
if(!tilemap.playing){
if(tilemap.win){
youWin.Draw();
}
else{
gameOver.Draw();
}
}
// Displaying
engine.Display();
}
// Cleanup
engine.Delete();
// Quit app
return 0;
}