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
|
||||
|
||||
#include "ImageLoader.hpp"
|
||||
#include "InputHandler.hpp"
|
||||
#include "../model/Map.hpp"
|
||||
#include "../view/MapView.hpp"
|
||||
|
||||
|
@ -47,9 +48,31 @@ private:
|
|||
std::vector<SDL_Surface *> tiles;
|
||||
std::map<std::string, SDL_Surface *> entities;
|
||||
|
||||
uint64_t totalTicks = 0;
|
||||
|
||||
public:
|
||||
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) {
|
||||
return std::make_shared<View::MapView>(window, map, tiles, entities);
|
||||
}
|
||||
|
|
|
@ -27,9 +27,17 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
namespace RPGEdit {
|
||||
|
||||
namespace Model {
|
||||
|
||||
enum Direction {
|
||||
NORTH,
|
||||
EAST,
|
||||
SOUTH,
|
||||
WEST,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,10 +63,31 @@ public:
|
|||
return dir;
|
||||
}
|
||||
|
||||
void move(float newX, float newY) {
|
||||
void moveTo(float newX, float newY) {
|
||||
x = newX;
|
||||
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"));
|
||||
square->move(6, 6);
|
||||
map->playerEntity.reset(new Entity("square"));
|
||||
map->playerEntity->moveTo(6, 6);
|
||||
|
||||
map->entities.push_back(square);
|
||||
map->entities.push_back(map->playerEntity);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ private:
|
|||
size_t width, height;
|
||||
std::unique_ptr<uint32_t[]> tiles;
|
||||
|
||||
std::shared_ptr<Entity> playerEntity;
|
||||
mutable std::deque<std::shared_ptr<Entity>> entities;
|
||||
|
||||
|
||||
|
@ -66,6 +67,10 @@ public:
|
|||
return entities;
|
||||
}
|
||||
|
||||
Entity & getPlayerEntity() const {
|
||||
return *playerEntity;
|
||||
}
|
||||
|
||||
size_t getWidth() const {
|
||||
return width;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "control/InputHandler.hpp"
|
||||
#include "control/MapContext.hpp"
|
||||
#include "view/MapView.hpp"
|
||||
#include "model/Entity.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -34,6 +34,9 @@
|
|||
#include <SDL_main.h>
|
||||
|
||||
|
||||
#define MIN_FRAME_DELAY 10
|
||||
|
||||
|
||||
extern "C"
|
||||
int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[]) {
|
||||
using namespace RPGEdit;
|
||||
|
@ -41,6 +44,8 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[])
|
|||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
{
|
||||
Control::InputHandler inputHandler;
|
||||
|
||||
Control::ImageLoader tileLoader;
|
||||
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);
|
||||
|
||||
bool running = true;
|
||||
uint32_t ticks = SDL_GetTicks();
|
||||
|
||||
while (true) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
while (running) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
@ -63,6 +85,11 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[])
|
|||
if (!running)
|
||||
break;
|
||||
|
||||
uint32_t newTicks = SDL_GetTicks();
|
||||
ctx->advance(&inputHandler, newTicks - ticks);
|
||||
|
||||
ticks = newTicks;
|
||||
|
||||
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()) {
|
||||
std::pair<float, float> pos = entity->getPosition();
|
||||
Direction dir = entity->getDirection();
|
||||
Model::Direction dir = entity->getDirection();
|
||||
|
||||
SDL_Rect src = {
|
||||
.x = 16*dir,
|
||||
|
|
Reference in a new issue