Allow player movement
This commit is contained in:
parent
c9b41bc102
commit
11e77a9d65
8 changed files with 165 additions and 8 deletions
73
src/control/InputHandler.hpp
Normal file
73
src/control/InputHandler.hpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2014, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
|
||||||
|
namespace RPGEdit {
|
||||||
|
|
||||||
|
namespace Control {
|
||||||
|
|
||||||
|
class InputHandler {
|
||||||
|
private:
|
||||||
|
std::unordered_set<uint16_t> pressedKeys;
|
||||||
|
std::unordered_set<uint16_t> unhandledKeys;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void keyPressed(SDL_Scancode key) {
|
||||||
|
pressedKeys.insert(key);
|
||||||
|
unhandledKeys.insert(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyReleased(SDL_Scancode key) {
|
||||||
|
pressedKeys.erase(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyHandled(SDL_Scancode key) {
|
||||||
|
unhandledKeys.erase(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetHandled() {
|
||||||
|
unhandledKeys.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isKeyPressed(SDL_Scancode key) {
|
||||||
|
return pressedKeys.count(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isKeyUnhandled(SDL_Scancode key) {
|
||||||
|
return unhandledKeys.count(key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ImageLoader.hpp"
|
#include "ImageLoader.hpp"
|
||||||
|
#include "InputHandler.hpp"
|
||||||
#include "../model/Map.hpp"
|
#include "../model/Map.hpp"
|
||||||
#include "../view/MapView.hpp"
|
#include "../view/MapView.hpp"
|
||||||
|
|
||||||
|
@ -47,9 +48,31 @@ private:
|
||||||
std::vector<SDL_Surface *> tiles;
|
std::vector<SDL_Surface *> tiles;
|
||||||
std::map<std::string, SDL_Surface *> entities;
|
std::map<std::string, SDL_Surface *> entities;
|
||||||
|
|
||||||
|
uint64_t totalTicks = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MapContext(ImageLoader *imageLoader0, const std::shared_ptr<const Model::Map> &map0);
|
MapContext(ImageLoader *imageLoader0, const std::shared_ptr<const Model::Map> &map0);
|
||||||
|
|
||||||
|
void advance(InputHandler *inputHandler, uint32_t ticks) {
|
||||||
|
uint64_t totalTicksOld = totalTicks;
|
||||||
|
totalTicks += ticks;
|
||||||
|
|
||||||
|
uint64_t advanced = totalTicks/100 - totalTicksOld/100;
|
||||||
|
|
||||||
|
if (inputHandler->isKeyPressed(SDL_SCANCODE_UP)) {
|
||||||
|
map->getPlayerEntity().move(Model::NORTH, advanced);
|
||||||
|
}
|
||||||
|
else if (inputHandler->isKeyPressed(SDL_SCANCODE_RIGHT)) {
|
||||||
|
map->getPlayerEntity().move(Model::EAST, advanced);
|
||||||
|
}
|
||||||
|
else if (inputHandler->isKeyPressed(SDL_SCANCODE_DOWN)) {
|
||||||
|
map->getPlayerEntity().move(Model::SOUTH, advanced);
|
||||||
|
}
|
||||||
|
else if (inputHandler->isKeyPressed(SDL_SCANCODE_LEFT)) {
|
||||||
|
map->getPlayerEntity().move(Model::WEST, advanced);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<View::MapView> initView(const std::shared_ptr<View::Window> &window) {
|
std::shared_ptr<View::MapView> initView(const std::shared_ptr<View::Window> &window) {
|
||||||
return std::make_shared<View::MapView>(window, map, tiles, entities);
|
return std::make_shared<View::MapView>(window, map, tiles, entities);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
namespace RPGEdit {
|
||||||
|
|
||||||
|
namespace Model {
|
||||||
|
|
||||||
enum Direction {
|
enum Direction {
|
||||||
NORTH,
|
NORTH,
|
||||||
EAST,
|
EAST,
|
||||||
SOUTH,
|
SOUTH,
|
||||||
WEST,
|
WEST,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -63,10 +63,31 @@ public:
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void move(float newX, float newY) {
|
void moveTo(float newX, float newY) {
|
||||||
x = newX;
|
x = newX;
|
||||||
y = newY;
|
y = newY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void move(Direction direction, float amount = 1) {
|
||||||
|
dir = direction;
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case NORTH:
|
||||||
|
y -= amount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EAST:
|
||||||
|
x += amount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOUTH:
|
||||||
|
y += amount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WEST:
|
||||||
|
x -= amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,10 @@ std::shared_ptr<Map> Map::load(__attribute__((unused)) const std::string &name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Entity> square(new Entity("square"));
|
map->playerEntity.reset(new Entity("square"));
|
||||||
square->move(6, 6);
|
map->playerEntity->moveTo(6, 6);
|
||||||
|
|
||||||
map->entities.push_back(square);
|
map->entities.push_back(map->playerEntity);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ private:
|
||||||
size_t width, height;
|
size_t width, height;
|
||||||
std::unique_ptr<uint32_t[]> tiles;
|
std::unique_ptr<uint32_t[]> tiles;
|
||||||
|
|
||||||
|
std::shared_ptr<Entity> playerEntity;
|
||||||
mutable std::deque<std::shared_ptr<Entity>> entities;
|
mutable std::deque<std::shared_ptr<Entity>> entities;
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,6 +67,10 @@ public:
|
||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entity & getPlayerEntity() const {
|
||||||
|
return *playerEntity;
|
||||||
|
}
|
||||||
|
|
||||||
size_t getWidth() const {
|
size_t getWidth() const {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "control/InputHandler.hpp"
|
||||||
#include "control/MapContext.hpp"
|
#include "control/MapContext.hpp"
|
||||||
#include "view/MapView.hpp"
|
#include "view/MapView.hpp"
|
||||||
#include "model/Entity.hpp"
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -34,6 +34,9 @@
|
||||||
#include <SDL_main.h>
|
#include <SDL_main.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define MIN_FRAME_DELAY 10
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[]) {
|
int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[]) {
|
||||||
using namespace RPGEdit;
|
using namespace RPGEdit;
|
||||||
|
@ -41,6 +44,8 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[])
|
||||||
SDL_Init(SDL_INIT_VIDEO);
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Control::InputHandler inputHandler;
|
||||||
|
|
||||||
Control::ImageLoader tileLoader;
|
Control::ImageLoader tileLoader;
|
||||||
std::shared_ptr<Model::Map> map = Model::Map::load("test");
|
std::shared_ptr<Model::Map> map = Model::Map::load("test");
|
||||||
|
|
||||||
|
@ -50,11 +55,28 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[])
|
||||||
std::shared_ptr<View::MapView> mapView = ctx->initView(window);
|
std::shared_ptr<View::MapView> mapView = ctx->initView(window);
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
uint32_t ticks = SDL_GetTicks();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (running) {
|
||||||
if (event.type == SDL_QUIT) {
|
int timeout = ticks + MIN_FRAME_DELAY - SDL_GetTicks();
|
||||||
|
if (timeout < 0)
|
||||||
|
timeout = 0;
|
||||||
|
|
||||||
|
if (!SDL_WaitEventTimeout(&event, timeout))
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
inputHandler.keyPressed(event.key.keysym.scancode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYUP:
|
||||||
|
inputHandler.keyReleased(event.key.keysym.scancode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_QUIT:
|
||||||
running = false;
|
running = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +85,11 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[])
|
||||||
if (!running)
|
if (!running)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
uint32_t newTicks = SDL_GetTicks();
|
||||||
|
ctx->advance(&inputHandler, newTicks - ticks);
|
||||||
|
|
||||||
|
ticks = newTicks;
|
||||||
|
|
||||||
mapView->render(8, 8);
|
mapView->render(8, 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ void MapView::render(float centerX, float centerY) {
|
||||||
|
|
||||||
for (const std::shared_ptr<Model::Entity> &entity : map->getEntities()) {
|
for (const std::shared_ptr<Model::Entity> &entity : map->getEntities()) {
|
||||||
std::pair<float, float> pos = entity->getPosition();
|
std::pair<float, float> pos = entity->getPosition();
|
||||||
Direction dir = entity->getDirection();
|
Model::Direction dir = entity->getDirection();
|
||||||
|
|
||||||
SDL_Rect src = {
|
SDL_Rect src = {
|
||||||
.x = 16*dir,
|
.x = 16*dir,
|
||||||
|
|
Reference in a new issue