Controls settings.
This commit is contained in:
parent
9f6e0ad180
commit
fe10ae4e44
70
src/gui.cpp
70
src/gui.cpp
|
@ -25,10 +25,20 @@ Menu* menu;
|
|||
Menu* mainMenu;
|
||||
Menu* settingsMenu;
|
||||
Menu* videoMenu;
|
||||
Menu* controlMenu;
|
||||
FileMenu* fileMenu;
|
||||
|
||||
bool pause = true;
|
||||
|
||||
SDL_Scancode CTRL_A = SDL_SCANCODE_A;
|
||||
SDL_Scancode CTRL_B = SDL_SCANCODE_S;
|
||||
SDL_Scancode CTRL_SELECT = SDL_SCANCODE_SPACE;
|
||||
SDL_Scancode CTRL_START = SDL_SCANCODE_RETURN;
|
||||
SDL_Scancode CTRL_UP = SDL_SCANCODE_UP;
|
||||
SDL_Scancode CTRL_DOWN = SDL_SCANCODE_DOWN;
|
||||
SDL_Scancode CTRL_LEFT = SDL_SCANCODE_LEFT;
|
||||
SDL_Scancode CTRL_RIGHT = SDL_SCANCODE_RIGHT;
|
||||
|
||||
|
||||
/* Set the window size multiplier */
|
||||
void set_size(int mul)
|
||||
|
@ -74,9 +84,9 @@ void init()
|
|||
mainMenu->add(new Entry("Exit", []{ exit(0); }));
|
||||
|
||||
settingsMenu = new Menu;
|
||||
settingsMenu->add(new Entry("<", []{ menu = mainMenu; }));
|
||||
settingsMenu->add(new Entry("Video", []{ menu = videoMenu; }));
|
||||
settingsMenu->add(new Entry("Controls"));
|
||||
settingsMenu->add(new Entry("<", []{ menu = mainMenu; }));
|
||||
settingsMenu->add(new Entry("Video", []{ menu = videoMenu; }));
|
||||
settingsMenu->add(new Entry("Controls", []{ menu = controlMenu; }));
|
||||
|
||||
videoMenu = new Menu;
|
||||
videoMenu->add(new Entry("<", []{ menu = settingsMenu; }));
|
||||
|
@ -84,20 +94,37 @@ void init()
|
|||
videoMenu->add(new Entry("Size 2x", []{ set_size(2); }));
|
||||
videoMenu->add(new Entry("Size 3x", []{ set_size(3); }));
|
||||
|
||||
controlMenu = new Menu;
|
||||
controlMenu->add(new Entry("<", []{ menu = settingsMenu; }));
|
||||
controlMenu->add(new ControlEntry("Up", &CTRL_UP));
|
||||
controlMenu->add(new ControlEntry("Down", &CTRL_DOWN));
|
||||
controlMenu->add(new ControlEntry("Left", &CTRL_LEFT));
|
||||
controlMenu->add(new ControlEntry("Right", &CTRL_RIGHT));
|
||||
controlMenu->add(new ControlEntry("A", &CTRL_A));
|
||||
controlMenu->add(new ControlEntry("B", &CTRL_B));
|
||||
controlMenu->add(new ControlEntry("Start", &CTRL_START));
|
||||
controlMenu->add(new ControlEntry("Select", &CTRL_SELECT));
|
||||
|
||||
fileMenu = new FileMenu;
|
||||
|
||||
menu = mainMenu;
|
||||
}
|
||||
|
||||
/* Render a texture on screen (-1 to center on an axis) */
|
||||
/* Render a texture on screen */
|
||||
void render_texture(SDL_Texture* texture, int x, int y)
|
||||
{
|
||||
int w, h;
|
||||
SDL_Rect dest;
|
||||
|
||||
SDL_QueryTexture(texture, NULL, NULL, &dest.w, &dest.h);
|
||||
dest.x = (x < 0) ? ((width / 2) - (dest.w / 2)) : x;
|
||||
dest.y = (y < 0) ? ((height / 2) - (dest.h / 2)) : y;
|
||||
if (x == TEXT_CENTER)
|
||||
dest.x = width/2 - dest.w/2;
|
||||
else if (x == TEXT_RIGHT)
|
||||
dest.x = width - dest.w - 10;
|
||||
else
|
||||
dest.x = x + 10;
|
||||
dest.y = y + 5;
|
||||
|
||||
SDL_RenderCopy(renderer, texture, NULL, &dest);
|
||||
}
|
||||
|
||||
|
@ -117,14 +144,14 @@ u8 get_joypad_state(int n)
|
|||
u8 j = 0;
|
||||
if (n == 0)
|
||||
{
|
||||
j |= (keys[SDL_SCANCODE_A]) << 0; // A.
|
||||
j |= (keys[SDL_SCANCODE_S]) << 1; // B.
|
||||
j |= (keys[SDL_SCANCODE_SPACE]) << 2; // Select.
|
||||
j |= (keys[SDL_SCANCODE_RETURN]) << 3; // Start.
|
||||
j |= (keys[SDL_SCANCODE_UP]) << 4; // Up.
|
||||
j |= (keys[SDL_SCANCODE_DOWN]) << 5; // Down.
|
||||
j |= (keys[SDL_SCANCODE_LEFT]) << 6; // Left.
|
||||
j |= (keys[SDL_SCANCODE_RIGHT]) << 7; // Right.
|
||||
j |= (keys[CTRL_A]) << 0;
|
||||
j |= (keys[CTRL_B]) << 1;
|
||||
j |= (keys[CTRL_SELECT]) << 2;
|
||||
j |= (keys[CTRL_START]) << 3;
|
||||
j |= (keys[CTRL_UP]) << 4;
|
||||
j |= (keys[CTRL_DOWN]) << 5;
|
||||
j |= (keys[CTRL_LEFT]) << 6;
|
||||
j |= (keys[CTRL_RIGHT]) << 7;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
@ -164,6 +191,21 @@ void toggle_pause()
|
|||
SDL_SetTextureColorMod(gameTexture, 255, 255, 255);
|
||||
}
|
||||
|
||||
SDL_Scancode query_key()
|
||||
{
|
||||
SDL_Texture* question = gen_text("Press a key...", { 255, 255, 255 });
|
||||
render_texture(question, TEXT_CENTER, height - fontSz*4);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
SDL_Event e;
|
||||
while (true)
|
||||
{
|
||||
SDL_PollEvent(&e);
|
||||
if (e.type == SDL_KEYDOWN)
|
||||
return e.key.keysym.scancode;
|
||||
}
|
||||
}
|
||||
|
||||
/* Run the emulator */
|
||||
void run()
|
||||
{
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
namespace GUI {
|
||||
|
||||
|
||||
const int TEXT_CENTER = -1;
|
||||
const int TEXT_RIGHT = -2;
|
||||
const unsigned fontSz = 15;
|
||||
|
||||
void init();
|
||||
void toggle_pause();
|
||||
SDL_Scancode query_key();
|
||||
void run();
|
||||
|
||||
SDL_Texture* gen_text(std::string text, SDL_Color color);
|
||||
|
|
57
src/menu.cpp
57
src/menu.cpp
|
@ -1,7 +1,6 @@
|
|||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include "cartridge.hpp"
|
||||
#include "gui.hpp"
|
||||
#include "menu.hpp"
|
||||
|
||||
namespace GUI {
|
||||
|
@ -9,10 +8,9 @@ namespace GUI {
|
|||
using namespace std;
|
||||
|
||||
|
||||
Entry::Entry(string label, function<void()> callback, int x, int y) : label(label), callback(callback), x(x), y(y)
|
||||
Entry::Entry(string label, function<void()> callback, int x, int y) : callback(callback), x(x), y(y)
|
||||
{
|
||||
whiteTexture = gen_text(label, { 255, 255, 255 });
|
||||
redTexture = gen_text(label, { 255, 0, 0 });
|
||||
setLabel(label);
|
||||
}
|
||||
|
||||
Entry::~Entry()
|
||||
|
@ -21,6 +19,53 @@ Entry::~Entry()
|
|||
SDL_DestroyTexture(redTexture);
|
||||
}
|
||||
|
||||
void Entry::setLabel(string label)
|
||||
{
|
||||
this->label = label;
|
||||
|
||||
if (whiteTexture != nullptr) SDL_DestroyTexture(whiteTexture);
|
||||
if (redTexture != nullptr) SDL_DestroyTexture(redTexture);
|
||||
|
||||
whiteTexture = gen_text(label, { 255, 255, 255 });
|
||||
redTexture = gen_text(label, { 255, 0, 0 });
|
||||
}
|
||||
|
||||
|
||||
ControlEntry::ControlEntry(string action, SDL_Scancode* key, int x, int y) : key(key),
|
||||
Entry::Entry(
|
||||
action,
|
||||
[&]{ keyEntry->setLabel(SDL_GetScancodeName(*(this->key) = query_key())); },
|
||||
x,
|
||||
y)
|
||||
{
|
||||
this->keyEntry = new Entry(SDL_GetScancodeName(*key), []{}, TEXT_RIGHT, y);
|
||||
}
|
||||
|
||||
void ControlEntry::setY(int y)
|
||||
{
|
||||
Entry::setY(y);
|
||||
this->keyEntry->setY(y);
|
||||
}
|
||||
|
||||
void ControlEntry::select()
|
||||
{
|
||||
Entry::select();
|
||||
this->keyEntry->select();
|
||||
}
|
||||
|
||||
void ControlEntry::unselect()
|
||||
{
|
||||
Entry::unselect();
|
||||
this->keyEntry->unselect();
|
||||
}
|
||||
|
||||
void ControlEntry::render()
|
||||
{
|
||||
Entry::render();
|
||||
this->keyEntry->render();
|
||||
}
|
||||
|
||||
|
||||
void Entry::render()
|
||||
{
|
||||
render_texture(selected ? redTexture : whiteTexture, getX(), getY());
|
||||
|
@ -84,13 +129,13 @@ void FileMenu::change_dir(string dir)
|
|||
{
|
||||
add(new Entry(name + "/",
|
||||
[=]{ change_dir(path); },
|
||||
10));
|
||||
0));
|
||||
}
|
||||
else if (name.size() > 4 and name.substr(name.size() - 4) == ".nes")
|
||||
{
|
||||
add(new Entry(name,
|
||||
[=]{ Cartridge::load(path.c_str()); toggle_pause(); },
|
||||
10));
|
||||
0));
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
|
|
29
src/menu.hpp
29
src/menu.hpp
|
@ -3,6 +3,7 @@
|
|||
#include <SDL2/SDL.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "gui.hpp"
|
||||
|
||||
namespace GUI {
|
||||
|
||||
|
@ -15,24 +16,38 @@ class Entry
|
|||
std::function<void()> callback;
|
||||
|
||||
bool selected = false;
|
||||
SDL_Texture* whiteTexture;
|
||||
SDL_Texture* redTexture;
|
||||
SDL_Texture* whiteTexture = nullptr;
|
||||
SDL_Texture* redTexture = nullptr;
|
||||
|
||||
public:
|
||||
Entry(std::string label, std::function<void()> callback = []{}, int x = -1, int y = -1);
|
||||
Entry(std::string label, std::function<void()> callback = []{}, int x = TEXT_CENTER, int y = 0);
|
||||
~Entry();
|
||||
|
||||
void setX(int x) { this->x = x; }
|
||||
void setY(int y) { this->y = y; }
|
||||
virtual void setX(int x) { this->x = x; }
|
||||
virtual void setY(int y) { this->y = y; }
|
||||
int getX() { return x; }
|
||||
int getY() { return y; }
|
||||
void setLabel(std::string label);
|
||||
|
||||
void select() { selected = true; };
|
||||
void unselect() { selected = false; };
|
||||
virtual void select() { selected = true; };
|
||||
virtual void unselect() { selected = false; };
|
||||
void trigger() { callback(); };
|
||||
virtual void render();
|
||||
};
|
||||
|
||||
class ControlEntry : public Entry
|
||||
{
|
||||
SDL_Scancode* key;
|
||||
Entry* keyEntry;
|
||||
|
||||
public:
|
||||
ControlEntry(std::string action, SDL_Scancode* key, int x = 0, int y = 0);
|
||||
void setY(int y);
|
||||
void select();
|
||||
void unselect();
|
||||
void render();
|
||||
};
|
||||
|
||||
class Menu
|
||||
{
|
||||
std::vector<Entry*> entries;
|
||||
|
|
Reference in a new issue