Camera following functionality, first pass
This commit is contained in:
parent
3fd60d76ea
commit
b4daac6e0c
|
@ -22,14 +22,22 @@ void EntityManager::update()
|
||||||
//if (m_entitiesToAdd.size())
|
//if (m_entitiesToAdd.size())
|
||||||
// m_entitiesToAdd.erase(m_entitiesToAdd.begin(), m_entitiesToAdd.end());
|
// m_entitiesToAdd.erase(m_entitiesToAdd.begin(), m_entitiesToAdd.end());
|
||||||
m_entitiesToAdd = EntityVec();
|
m_entitiesToAdd = EntityVec();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::removeDeadEntities(EntityVec & vec)
|
void EntityManager::removeDeadEntities(EntityVec & vec)
|
||||||
{
|
{
|
||||||
EntityVec survivors; // New vector
|
EntityVec survivors; // New vector
|
||||||
for (auto& e : m_entities)
|
for (auto& e : m_entities){
|
||||||
{
|
|
||||||
if (e->isActive()) survivors.push_back(e); // populate new vector
|
if (e->isActive()) survivors.push_back(e); // populate new vector
|
||||||
|
else if (e->cGrid) { // erase vector from grid
|
||||||
|
for( auto it = e->cGrid->grid->entities.begin(); it != e->cGrid->grid->entities.end(); it++){
|
||||||
|
if( *it == e ){
|
||||||
|
e->cGrid->grid->entities.erase( it );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//std::cout << "All entities: " << m_entities.size() << " Survivors: " << survivors.size() << std::endl;
|
//std::cout << "All entities: " << m_entities.size() << " Survivors: " << survivors.size() << std::endl;
|
||||||
m_entities = survivors; // point to new vector
|
m_entities = survivors; // point to new vector
|
||||||
|
|
|
@ -14,6 +14,7 @@ sf::Sound McRFPy_API::sfx;
|
||||||
std::string McRFPy_API::input_mode;
|
std::string McRFPy_API::input_mode;
|
||||||
int McRFPy_API::turn_number;
|
int McRFPy_API::turn_number;
|
||||||
std::string McRFPy_API::active_grid;
|
std::string McRFPy_API::active_grid;
|
||||||
|
bool McRFPy_API::do_camfollow;
|
||||||
|
|
||||||
EntityManager McRFPy_API::entities;
|
EntityManager McRFPy_API::entities;
|
||||||
|
|
||||||
|
@ -93,6 +94,7 @@ static PyMethodDef mcrfpyMethods[] = {
|
||||||
{"createEntity", McRFPy_API::_createEntity, METH_VARARGS, ""},
|
{"createEntity", McRFPy_API::_createEntity, METH_VARARGS, ""},
|
||||||
//{"listEntities", McRFPy_API::_listEntities, METH_VARARGS, ""},
|
//{"listEntities", McRFPy_API::_listEntities, METH_VARARGS, ""},
|
||||||
{"refreshFov", McRFPy_API::_refreshFov, METH_VARARGS, ""},
|
{"refreshFov", McRFPy_API::_refreshFov, METH_VARARGS, ""},
|
||||||
|
{"camFollow", McRFPy_API::_camFollow, METH_VARARGS, ""},
|
||||||
|
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
@ -638,7 +640,7 @@ PyObject* McRFPy_API::_modGrid(PyObject* self, PyObject* args) {
|
||||||
PyObject* o;
|
PyObject* o;
|
||||||
PyObject* bool_is_entityonly = Py_False;
|
PyObject* bool_is_entityonly = Py_False;
|
||||||
if (!PyArg_ParseTuple(args, "O|O", &o, &bool_is_entityonly)) return NULL;
|
if (!PyArg_ParseTuple(args, "O|O", &o, &bool_is_entityonly)) return NULL;
|
||||||
std::cout << "EntOnly Flag: " << PyUnicode_AsUTF8(PyObject_Repr(bool_is_entityonly)) << std::endl;
|
//std::cout << "EntOnly Flag: " << PyUnicode_AsUTF8(PyObject_Repr(bool_is_entityonly)) << std::endl;
|
||||||
std::string title = PyUnicode_AsUTF8(PyObject_GetAttrString(o, "title"));
|
std::string title = PyUnicode_AsUTF8(PyObject_GetAttrString(o, "title"));
|
||||||
int grid_x = PyLong_AsLong(PyObject_GetAttrString(o, "grid_x"));
|
int grid_x = PyLong_AsLong(PyObject_GetAttrString(o, "grid_x"));
|
||||||
int grid_y = PyLong_AsLong(PyObject_GetAttrString(o, "grid_y"));
|
int grid_y = PyLong_AsLong(PyObject_GetAttrString(o, "grid_y"));
|
||||||
|
@ -847,7 +849,7 @@ PyObject* McRFPy_API::_createAnimation(PyObject *self, PyObject *args) {
|
||||||
[=](int s){obj->sprites[target_id].sprite_index = s;},
|
[=](int s){obj->sprites[target_id].sprite_index = s;},
|
||||||
loop)
|
loop)
|
||||||
);
|
);
|
||||||
std::cout << "Frame animation constructed, there are now " <<McRFPy_API::animations.size() << std::endl;
|
//std::cout << "Frame animation constructed, there are now " <<McRFPy_API::animations.size() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (CEQ(target_type, "entity")) {
|
else if (CEQ(target_type, "entity")) {
|
||||||
|
@ -954,7 +956,7 @@ PyObject* McRFPy_API::_unlockPlayerInput(PyObject* self, PyObject* args) {
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
PyObject* McRFPy_API::_lockPlayerInput(PyObject* self, PyObject* args) {
|
PyObject* McRFPy_API::_lockPlayerInput(PyObject* self, PyObject* args) {
|
||||||
McRFPy_API::input_mode = "computerturn";
|
McRFPy_API::input_mode = "computerturnwait";
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
@ -1004,13 +1006,13 @@ PyObject* McRFPy_API::_listEntities(PyObject* self, PyObject* args) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void McRFPy_API::player_input(int dx, int dy) {
|
void McRFPy_API::player_input(int dx, int dy) {
|
||||||
std::cout << "# entities tagged 'player': " << McRFPy_API::entities.getEntities("player").size() << std::endl;
|
//std::cout << "# entities tagged 'player': " << McRFPy_API::entities.getEntities("player").size() << std::endl;
|
||||||
auto player_entity = McRFPy_API::entities.getEntities("player")[0];
|
auto player_entity = McRFPy_API::entities.getEntities("player")[0];
|
||||||
auto grid = player_entity->cGrid->grid;
|
auto grid = player_entity->cGrid->grid;
|
||||||
std::cout << "Grid pointed to: " << (long)player_entity->cGrid->grid << std::endl;
|
//std::cout << "Grid pointed to: " << (long)player_entity->cGrid->grid << std::endl;
|
||||||
if (!McRFPy_API::input_mode.compare("computerturn")) {
|
if (McRFPy_API::input_mode.compare("playerturn") != 0) {
|
||||||
// no input accepted while computer moving
|
// no input accepted while computer moving
|
||||||
std::cout << "Can't move while computer is moving." << std::endl;
|
std::cout << "Can't move while it's not player's turn." << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: selection cursor via keyboard
|
// TODO: selection cursor via keyboard
|
||||||
|
@ -1026,9 +1028,9 @@ void McRFPy_API::player_input(int dx, int dy) {
|
||||||
") + (" << dx << ", " << dy << ") is OOB." << std::endl;
|
") + (" << dx << ", " << dy << ") is OOB." << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::cout << PyUnicode_AsUTF8(PyObject_Repr(player_entity->cBehavior->object)) << std::endl;
|
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(player_entity->cBehavior->object)) << std::endl;
|
||||||
PyObject* move_fn = PyObject_GetAttrString(player_entity->cBehavior->object, "move");
|
PyObject* move_fn = PyObject_GetAttrString(player_entity->cBehavior->object, "move");
|
||||||
std::cout << PyUnicode_AsUTF8(PyObject_Repr(move_fn)) << std::endl;
|
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(move_fn)) << std::endl;
|
||||||
if (move_fn) {
|
if (move_fn) {
|
||||||
std::cout << "Calling `move`" << std::endl;
|
std::cout << "Calling `move`" << std::endl;
|
||||||
PyObject* move_args = Py_BuildValue("(ii)", dx, dy);
|
PyObject* move_args = Py_BuildValue("(ii)", dx, dy);
|
||||||
|
@ -1037,3 +1039,47 @@ void McRFPy_API::player_input(int dx, int dy) {
|
||||||
std::cout << "player_input called on entity with no `move` method" << std::endl;
|
std::cout << "player_input called on entity with no `move` method" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void McRFPy_API::computerTurn() {
|
||||||
|
McRFPy_API::input_mode = "computerturnrunning";
|
||||||
|
for (auto e : McRFPy_API::grids[McRFPy_API::active_grid]->entities) {
|
||||||
|
if (e->cBehavior) {
|
||||||
|
PyObject_Call(PyObject_GetAttrString(e->cBehavior->object, "ai_act"), PyTuple_New(0), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void McRFPy_API::playerTurn() {
|
||||||
|
McRFPy_API::input_mode = "playerturn";
|
||||||
|
for (auto e : McRFPy_API::entities.getEntities("player")) {
|
||||||
|
if (e->cBehavior) {
|
||||||
|
PyObject_Call(PyObject_GetAttrString(e->cBehavior->object, "player_act"), PyTuple_New(0), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void McRFPy_API::camFollow() {
|
||||||
|
if (!McRFPy_API::do_camfollow) return;
|
||||||
|
auto& ag = McRFPy_API::grids[McRFPy_API::active_grid];
|
||||||
|
for (auto e : McRFPy_API::entities.getEntities("player")) {
|
||||||
|
//std::cout << "grid center: " << ag->center_x << ", " << ag->center_y << std::endl <<
|
||||||
|
// "player grid pos: " << e->cGrid->x << ", " << e->cGrid->y << std::endl <<
|
||||||
|
// "player sprite pos: " << e->cGrid->indexsprite.x << ", " << e->cGrid->indexsprite.y << std::endl;
|
||||||
|
ag->center_x = e->cGrid->indexsprite.x * ag->grid_size + ag->grid_size * 0.5;
|
||||||
|
ag->center_y = e->cGrid->indexsprite.y * ag->grid_size + ag->grid_size * 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* McRFPy_API::_camFollow(PyObject* self, PyObject* args) {
|
||||||
|
PyObject* set_camfollow;
|
||||||
|
if (!PyArg_ParseTuple(args, "|O", &set_camfollow)) return NULL;
|
||||||
|
if (set_camfollow == NULL) {
|
||||||
|
// return value
|
||||||
|
Py_INCREF(McRFPy_API::do_camfollow ? Py_True : Py_False);
|
||||||
|
return McRFPy_API::do_camfollow ? Py_True : Py_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
McRFPy_API::do_camfollow = PyObject_IsTrue(set_camfollow);
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
|
@ -108,10 +108,15 @@ public:
|
||||||
static int turn_number;
|
static int turn_number;
|
||||||
static PyObject* _turnNumber(PyObject*, PyObject*);
|
static PyObject* _turnNumber(PyObject*, PyObject*);
|
||||||
static PyObject* _refreshFov(PyObject*, PyObject*);
|
static PyObject* _refreshFov(PyObject*, PyObject*);
|
||||||
|
static bool do_camfollow;
|
||||||
|
static void camFollow();
|
||||||
|
static PyObject* _camFollow(PyObject*, PyObject*);
|
||||||
|
|
||||||
// accept keyboard input from scene
|
// accept keyboard input from scene
|
||||||
static sf::Vector2i cursor_position;
|
static sf::Vector2i cursor_position;
|
||||||
static void player_input(int, int);
|
static void player_input(int, int);
|
||||||
|
static void computerTurn();
|
||||||
|
static void playerTurn();
|
||||||
|
|
||||||
// Jank Functionality
|
// Jank Functionality
|
||||||
static UIMenu* createMenu(int posx, int posy, int sizex, int sizey);
|
static UIMenu* createMenu(int posx, int posy, int sizex, int sizey);
|
||||||
|
|
|
@ -36,6 +36,7 @@ PythonScene::PythonScene(GameEngine* g, std::string pymodule)
|
||||||
registerAction(0, "event");
|
registerAction(0, "event");
|
||||||
|
|
||||||
dragging = false;
|
dragging = false;
|
||||||
|
McRFPy_API::do_camfollow = false;
|
||||||
drag_grid = NULL;
|
drag_grid = NULL;
|
||||||
|
|
||||||
// import pymodule and call start()
|
// import pymodule and call start()
|
||||||
|
@ -53,7 +54,7 @@ void PythonScene::animate() {
|
||||||
(*it)->step(frametime);
|
(*it)->step(frametime);
|
||||||
//std::cout << "Step complete" << std::endl;
|
//std::cout << "Step complete" << std::endl;
|
||||||
if ((*it)->isDone()) {
|
if ((*it)->isDone()) {
|
||||||
std::cout << "Cleaning up Animation" << std::endl;
|
//std::cout << "Cleaning up Animation" << std::endl;
|
||||||
auto prev = it;
|
auto prev = it;
|
||||||
it++;
|
it++;
|
||||||
McRFPy_API::animations.erase(prev);
|
McRFPy_API::animations.erase(prev);
|
||||||
|
@ -101,6 +102,15 @@ void PythonScene::animate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonScene::update() {
|
void PythonScene::update() {
|
||||||
|
|
||||||
|
// turn cycle: If player's input made the state "computerturnwait", finish
|
||||||
|
// all animations and then let the NPCs act
|
||||||
|
if (McRFPy_API::animations.size() == 0 && McRFPy_API::input_mode.compare("computerturnwait") == 0) {
|
||||||
|
McRFPy_API::input_mode = "computerturn";
|
||||||
|
}
|
||||||
|
else if (McRFPy_API::animations.size() == 0 && McRFPy_API::input_mode.compare("computerturnrunning") == 0) {
|
||||||
|
McRFPy_API::input_mode = "playerturnstart";
|
||||||
|
}
|
||||||
McRFPy_API::entities.update();
|
McRFPy_API::entities.update();
|
||||||
|
|
||||||
// check if left click is still down & mouse has moved
|
// check if left click is still down & mouse has moved
|
||||||
|
@ -116,6 +126,9 @@ void PythonScene::update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
animate();
|
animate();
|
||||||
|
McRFPy_API::camFollow();
|
||||||
|
if (McRFPy_API::input_mode.compare(std::string("computerturn")) == 0) McRFPy_API::computerTurn();
|
||||||
|
if (McRFPy_API::input_mode.compare(std::string("playerturnstart")) == 0) McRFPy_API::playerTurn();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonScene::doLClick(sf::Vector2i mousepos) {
|
void PythonScene::doLClick(sf::Vector2i mousepos) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ class TestEntity:
|
||||||
self.y = y
|
self.y = y
|
||||||
self.facing_direction = 0
|
self.facing_direction = 0
|
||||||
self.do_fov = do_fov
|
self.do_fov = do_fov
|
||||||
|
self.label = label
|
||||||
#print(f"Calling C++ with: {repr((self.grid, label, tex_index, self.basesprite, x, y, self))}")
|
#print(f"Calling C++ with: {repr((self.grid, label, tex_index, self.basesprite, x, y, self))}")
|
||||||
grids = mcrfpy.listGrids()
|
grids = mcrfpy.listGrids()
|
||||||
for g in grids:
|
for g in grids:
|
||||||
|
@ -31,6 +32,16 @@ class TestEntity:
|
||||||
self.entity_index = len(g.entities)
|
self.entity_index = len(g.entities)
|
||||||
mcrfpy.createEntity(self.grid, label, tex_index, self.basesprite, x, y, self)
|
mcrfpy.createEntity(self.grid, label, tex_index, self.basesprite, x, y, self)
|
||||||
|
|
||||||
|
def ai_act(self):
|
||||||
|
if self.label == "player": return
|
||||||
|
self.move(randint(-1, 1), randint(-1, 1))
|
||||||
|
scene.actors += 1
|
||||||
|
|
||||||
|
def player_act(self):
|
||||||
|
#print("I'M INTERVENING")
|
||||||
|
mcrfpy.unlockPlayerInput()
|
||||||
|
scene.updatehints()
|
||||||
|
|
||||||
def move(self, dx, dy):
|
def move(self, dx, dy):
|
||||||
# select animation direction
|
# select animation direction
|
||||||
# prefer left or right for diagonals.
|
# prefer left or right for diagonals.
|
||||||
|
@ -40,6 +51,9 @@ class TestEntity:
|
||||||
if g.at(self.x + dx, self.y + dy) is None or not g.at(self.x + dx, self.y + dy).walkable:
|
if g.at(self.x + dx, self.y + dy) is None or not g.at(self.x + dx, self.y + dy).walkable:
|
||||||
print("Blocked at target location.")
|
print("Blocked at target location.")
|
||||||
return
|
return
|
||||||
|
if self.label == "player":
|
||||||
|
mcrfpy.lockPlayerInput()
|
||||||
|
scene.updatehints()
|
||||||
if (dx == 0 and dy == 0):
|
if (dx == 0 and dy == 0):
|
||||||
direction = self.facing_direction # TODO, jump straight to computer turn
|
direction = self.facing_direction # TODO, jump straight to computer turn
|
||||||
elif (dx):
|
elif (dx):
|
||||||
|
@ -64,8 +78,8 @@ class TestEntity:
|
||||||
False, #loop: repeat indefinitely
|
False, #loop: repeat indefinitely
|
||||||
animation_frames # values: iterable of frames for 'sprite', lerp target for others
|
animation_frames # values: iterable of frames for 'sprite', lerp target for others
|
||||||
)
|
)
|
||||||
global animations_in_progress
|
#global animations_in_progress
|
||||||
animations_in_progress += 1
|
#animations_in_progress += 1
|
||||||
if move:
|
if move:
|
||||||
pos = [self.x, self.y]
|
pos = [self.x, self.y]
|
||||||
if (direction == 0): pos[1] += 1
|
if (direction == 0): pos[1] += 1
|
||||||
|
@ -96,18 +110,22 @@ class TestEntity:
|
||||||
False, #loop: repeat indefinitely
|
False, #loop: repeat indefinitely
|
||||||
animove # values: iterable of frames for 'sprite', lerp target for others
|
animove # values: iterable of frames for 'sprite', lerp target for others
|
||||||
)
|
)
|
||||||
animations_in_progress += 1
|
#animations_in_progress += 1
|
||||||
|
|
||||||
|
|
||||||
def animation_done(self):
|
def animation_done(self):
|
||||||
global animations_in_progress
|
#global animations_in_progress
|
||||||
animations_in_progress -= 1
|
#animations_in_progress -= 1
|
||||||
#print(f"{self} done animating")
|
scene.actors -= 1
|
||||||
# if animations_in_progress == 0: mcrfpy.unlockPlayerInput()
|
#print(f"{self} done animating - {scene.actors} remaining")
|
||||||
|
if scene.actors == 0:
|
||||||
|
mcrfpy.unlockPlayerInput()
|
||||||
|
scene.updatehints()
|
||||||
|
|
||||||
class TestScene:
|
class TestScene:
|
||||||
def __init__(self, ui_name = "demobox1", grid_name = "demogrid"):
|
def __init__(self, ui_name = "demobox1", grid_name = "demogrid"):
|
||||||
# Texture & Sound Loading
|
# Texture & Sound Loading
|
||||||
|
self.actors = 0
|
||||||
print("Load textures")
|
print("Load textures")
|
||||||
mcrfpy.createTexture("./assets/test_portraits.png", 32, 8, 8) #0 - portraits
|
mcrfpy.createTexture("./assets/test_portraits.png", 32, 8, 8) #0 - portraits
|
||||||
mcrfpy.createTexture("./assets/alives_other.png", 16, 64, 64) #1 - TinyWorld NPCs
|
mcrfpy.createTexture("./assets/alives_other.png", 16, 64, 64) #1 - TinyWorld NPCs
|
||||||
|
@ -287,11 +305,12 @@ class TestScene:
|
||||||
p.walkable = False
|
p.walkable = False
|
||||||
p.transparent = False
|
p.transparent = False
|
||||||
|
|
||||||
room_centers = [(randint(0, self.grids[0].grid_x-1), randint(0, self.grids[0].grid_y-1)) for i in range(6)]
|
room_centers = [(randint(0, self.grids[0].grid_x-1), randint(0, self.grids[0].grid_y-1)) for i in range(20)] + \
|
||||||
room_centers.append((3, 5))
|
[ (3, 5), (10, 10), (20, 20), (30, 30), (40, 40) ]
|
||||||
|
#room_centers.append((3, 5))
|
||||||
for r in room_centers:
|
for r in room_centers:
|
||||||
print(r)
|
print(r)
|
||||||
room_color = (randint(128, 192), randint(128, 192), randint(128, 192))
|
room_color = (randint(16, 24)*8, randint(16, 24)*8, randint(16, 24)*8)
|
||||||
#self.grids[0].at(r[0], r[1]).walkable = True
|
#self.grids[0].at(r[0], r[1]).walkable = True
|
||||||
#self.grids[0].at(r[0], r[1]).color = room_color
|
#self.grids[0].at(r[0], r[1]).color = room_color
|
||||||
halfx, halfy = randint(2, 11), randint(2,11)
|
halfx, halfy = randint(2, 11), randint(2,11)
|
||||||
|
|
Loading…
Reference in New Issue