Compare commits

..

1 Commits
v1.28 ... main

Author SHA1 Message Date
theredbluecube2@gmail.com
e9814dea3e add controller support 2025-08-07 17:48:03 +03:00
4 changed files with 230 additions and 163 deletions

1
.gitignore vendored
View File

@ -6,4 +6,3 @@ lib
.vscode
bin
build
Makefile

View File

@ -9,7 +9,7 @@ DBG_CXXFLAGS := $(CXXFLAGS) -g
RLS_CXXFLAGS := $(CXXFLAGS) -O2
# linker stuff
LDFLAGS := -lncursesw
LDFLAGS := -lncursesw -lSDL2
DBG_LDFLAGS := $(LDFLAGS)
RLS_LDFLAGS := $(LDFLAGS) -s

View File

@ -1,72 +0,0 @@
# SPDX-FileCopyrightText: 2025 thorium1256
#
# SPDX-License-Identifier: GPL-3.0-or-later
# compiler stuff
CXX := c++
CXXFLAGS := -I include -std=c++11 -Wall -Wextra
DBG_CXXFLAGS := $(CXXFLAGS) -g
RLS_CXXFLAGS := $(CXXFLAGS) -O2
# linker stuff
LDFLAGS := -L C:\msys64\mingw64\bin -lncursesw6
DBG_LDFLAGS := $(LDFLAGS)
RLS_STRP_LDFLAGS := $(LDFLAGS) -s
# directories
BUILD_DIR := build
SRC_DIR := src
BIN_DIR := bin
DBG_DIR := $(BIN_DIR)\debug
RLS_DIR := $(BIN_DIR)\release
LIB_DIR := lib
DBG_EXEC := $(DBG_DIR)\debug.exe
RLS_STRIPPED_EXEC := $(RLS_DIR)\tuimine.exe
# sources and objects
LIBS := $(wildcard $(LIB_DIR)/*.dll)
LIBS_DBG := $(patsubst $(LIB_DIR)/%.dll, $(DBG_DIR)\\%.dll, $(LIBS))
LIBS_RLS := $(patsubst $(LIB_DIR)/%.dll, $(RLS_DIR)\\%.dll, $(LIBS))
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
DBG_OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/debug_%.o,$(SRCS))
RLS_OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_DIR)/release_%.o,$(SRCS))
$(shell if not exist $(BIN_DIR) mkdir $(BIN_DIR))
$(shell if not exist $(DBG_DIR) mkdir $(DBG_DIR))
$(shell if not exist $(RLS_DIR) mkdir $(RLS_DIR))
$(shell if not exist $(BUILD_DIR) mkdir $(BUILD_DIR))
# phony rules
.PHONY = all debug release clean libraries_debug libraries_release both
all: release
debug: $(DBG_EXEC) libraries_debug
release: $(RLS_STRIPPED_EXEC) libraries_release
both: debug release
libraries_debug: $(LIBS_DBG)
libraries_release: $(LIBS_RLS)
# linking
$(DBG_EXEC): $(DBG_OBJS)
$(CXX) -o $@ $^ $(DBG_LDFLAGS)
$(RLS_STRIPPED_EXEC): $(RLS_OBJS)
$(CXX) -o $@ $^ $(RLS_STRP_LDFLAGS)
# compiling
$(BUILD_DIR)/debug_%.o: $(SRC_DIR)/%.cpp
$(CXX) -c -o $@ $< $(DBG_CXXFLAGS)
$(BUILD_DIR)/release_%.o: $(SRC_DIR)/%.cpp
$(CXX) -c -o $@ $< $(RLS_CXXFLAGS)
$(DBG_DIR)\\%.dll: $(LIB_DIR)\\%.dll
xcopy $< $(DBG_DIR)\ >nul
$(RLS_DIR)\\%.dll: $(LIB_DIR)\\%.dll
xcopy $< $(RLS_DIR)\ >nul
clean:
rmdir /s /q $(BUILD_DIR) $(DBG_DIR) $(RLS_DIR)

View File

@ -4,9 +4,10 @@
#include <iostream>
#include <stdexcept>
#include <ncursesw/ncurses.h>
#include <ncurses.h>
#include <ctime>
#include <unistd.h>
#include <SDL2/SDL.h>
#include "Board.h"
#ifndef _WIN32
#include <signal.h>
@ -20,6 +21,8 @@ void handleSIGWINCH(int sig)
#define MAX_TIME 60
SDL_GameController *controller;
void startGame(Board &board)
{
int minesLeft = board.getMineCount();
@ -161,8 +164,115 @@ void startGame(Board &board)
c = getch();
if (c == ERR)
{
if (controller != nullptr)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_CONTROLLERBUTTONDOWN)
{
switch (event.cbutton.button)
{
case SDL_CONTROLLER_BUTTON_DPAD_UP:
cursorY = (cursorY > 0) ? cursorY - 1 : boardSize.y - 1;
break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
cursorY = (cursorY < boardSize.y - 1) ? cursorY + 1 : 0;
break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
cursorX = (cursorX > 0) ? cursorX - 1 : boardSize.x - 1;
break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
cursorX = (cursorX < boardSize.x - 1) ? cursorX + 1 : 0;
break;
case SDL_CONTROLLER_BUTTON_START:
if (isPaused)
{
pauseTime = difftime(time(NULL), startPauseTime);
totalpausetime += pauseTime;
}
else
{
startPauseTime = time(NULL);
}
isPaused = !isPaused;
break;
case SDL_CONTROLLER_BUTTON_A:
if (!somethingHasBeenDone)
{
startTime = time(nullptr);
somethingHasBeenDone = true;
}
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Revealed)
{
if (!somethingHasBeenDone)
{
startTime = time(nullptr);
somethingHasBeenDone = true;
}
auto neighbors = board.getNeighborsOf(cursorX, cursorY);
int flagCount = 0;
for (const Cell &neighbor : neighbors)
{
if (neighbor.getState() == Cell::State::Flagged)
flagCount++;
}
if (static_cast<int>(board.revealCellAt(cursorX, cursorY).getContent()) > flagCount)
break;
for (const Cell &neighbor : neighbors)
{
if (neighbor.getState() == Cell::State::Flagged)
continue;
board.revealCellAt(neighbor.getPosition().x, neighbor.getPosition().y);
}
break;
}
board.revealCellAt(cursorX, cursorY);
break;
case SDL_CONTROLLER_BUTTON_B:
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Revealed)
break;
if (!somethingHasBeenDone)
{
startTime = time(nullptr);
somethingHasBeenDone = true;
}
if (board.getCellStateAt(cursorX, cursorY) == Cell::State::Flagged)
{
minesLeft++;
}
else
{
minesLeft--;
}
board.flagCellAt(cursorX, cursorY);
break;
case SDL_CONTROLLER_BUTTON_MISC1:
startTime = time(NULL);
minesLeft = board.getMineCount();
board.regenerateBoard();
somethingHasBeenDone = false;
elapsedTime = 0;
break;
case SDL_CONTROLLER_BUTTON_BACK:
echo();
cbreak();
endwin();
exit(0);
break;
}
}
else
{
break;
}
}
}
}
if (!(c == ERR))
{
switch (c)
{
case KEY_UP:
@ -255,6 +365,7 @@ void startGame(Board &board)
}
break;
}
}
if (isPaused)
continue;
@ -327,6 +438,19 @@ void startGame(Board &board)
}
}
SDL_GameController *findController()
{
for (int i = 0; i < SDL_NumJoysticks(); i++)
{
if (SDL_IsGameController(i))
{
return SDL_GameControllerOpen(i);
}
}
return nullptr;
}
int main()
{
#ifndef _WIN32
@ -342,6 +466,22 @@ int main()
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
#endif
bool controllerSupport;
if (SDL_Init(SDL_INIT_GAMECONTROLLER) < 0)
{
std::cerr << "SDL failed to initialize GameController API! Controller support will not be available!" << std::endl;
controllerSupport = false;
}
else
{
controllerSupport = true;
}
controller = findController();
if (controller != nullptr)
controllerSupport = false; // no controller for you
start_color();
init_pair(1, COLOR_BLUE, COLOR_BLACK);
init_pair(2, COLOR_GREEN, COLOR_BLACK);