Controls settings.

This commit is contained in:
Andrea Orrù 2014-05-31 18:28:29 +02:00
parent 9f6e0ad180
commit fe10ae4e44
4 changed files with 132 additions and 27 deletions

View file

@ -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()
{

View file

@ -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);

View file

@ -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);

View file

@ -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;