Keyboard control

This commit is contained in:
John McCardle 2023-03-10 09:21:56 -05:00
parent 8d9148b88d
commit 486a1cd17c
6 changed files with 200 additions and 22 deletions

BIN
assets/custom_player.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -24,7 +24,7 @@ GameEngine::GameEngine()
McRFPy_API::executePyString("from UIMenu import *"); McRFPy_API::executePyString("from UIMenu import *");
McRFPy_API::executePyString("from Grid import *"); McRFPy_API::executePyString("from Grid import *");
scenes["py"] = new PythonScene(this, "MusicScene"); scenes["py"] = new PythonScene(this, "TestScene");
IndexSprite::game = this; IndexSprite::game = this;

View File

@ -575,12 +575,14 @@ PyObject* McRFPy_API::_listGrids(PyObject*, PyObject*) {
auto grid = it->second; auto grid = it->second;
auto p = grid->box.getPosition(); auto p = grid->box.getPosition();
auto s = grid->box.getSize(); auto s = grid->box.getSize();
PyObject* grid_args = Py_BuildValue("(siiiiiii)", PyObject* grid_args = Py_BuildValue("(siiiiiiiO)",
title.c_str(), title.c_str(),
(int)grid->grid_x, (int)grid->grid_y, (int)grid->grid_size, (int)grid->grid_x, (int)grid->grid_y, (int)grid->grid_size,
(int)p.x, (int)p.y, (int)s.x, (int)s.y); (int)p.x, (int)p.y, (int)s.x, (int)s.y,
grid->visible? Py_True: Py_False);
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(grid_args)) << std::endl; grid->visible ? Py_INCREF(Py_True) : Py_INCREF(Py_False);
std::cout << PyUnicode_AsUTF8(PyObject_Repr(grid_args)) << std::endl;
PyObject* gridobj = PyObject_CallObject((PyObject*) grid_type, grid_args); PyObject* gridobj = PyObject_CallObject((PyObject*) grid_type, grid_args);
//std::cout << (long)gridobj << std::flush <<std::endl; //std::cout << (long)gridobj << std::flush <<std::endl;
@ -678,6 +680,17 @@ PyObject* McRFPy_API::_modGrid(PyObject* self, PyObject* args) {
grid->points[i].uisprite = PyLong_AsLong(PyObject_GetAttrString(gpointobj, "uisprite")); grid->points[i].uisprite = PyLong_AsLong(PyObject_GetAttrString(gpointobj, "uisprite"));
} }
PyObject* entlist = PyObject_GetAttrString(o, "entities");
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(entlist)) << std::endl;
for (int i = 0; i < grid->entities.size(); i++) {
PyObject* entobj = PyList_GetItem(entlist, i);
//std::cout << PyUnicode_AsUTF8(PyObject_Repr(entobj)) << std::endl;
grid->entities[i]->cGrid->x = PyLong_AsLong(PyObject_GetAttrString(entobj, "x"));
grid->entities[i]->cGrid->y = PyLong_AsLong(PyObject_GetAttrString(entobj, "y"));
grid->entities[i]->cGrid->indexsprite.texture_index = PyLong_AsLong(PyObject_GetAttrString(entobj, "tex_index"));
grid->entities[i]->cGrid->indexsprite.sprite_index = PyLong_AsLong(PyObject_GetAttrString(entobj, "sprite_index"));
}
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
@ -964,3 +977,38 @@ PyObject* McRFPy_API::_listEntities(PyObject* self, PyObject* args) {
return Py_None; return Py_None;
} }
*/ */
void McRFPy_API::player_input(int dx, int dy) {
std::cout << "# entities tagged 'player': " << McRFPy_API::entities.getEntities("player").size() << std::endl;
auto player_entity = McRFPy_API::entities.getEntities("player")[0];
auto grid = player_entity->cGrid->grid;
std::cout << "Grid pointed to: " << (long)player_entity->cGrid->grid << std::endl;
if (!McRFPy_API::input_mode.compare("computerturn")) {
// no input accepted while computer moving
std::cout << "Can't move while computer is moving." << std::endl;
return;
}
// TODO: selection cursor via keyboard
// else if (!input_mode.compare("selectpoint") {}
// else if (!input_mode.compare("selectentity") {}
// grid bounds check
if (player_entity->cGrid->x + dx < 0 ||
player_entity->cGrid->y + dy < 0 ||
player_entity->cGrid->x + dx > grid->grid_x - 1 ||
player_entity->cGrid->y + dy > grid->grid_y - 1) {
std::cout << "(" << player_entity->cGrid->x << ", " << player_entity->cGrid->y <<
") + (" << dx << ", " << dy << ") is OOB." << std::endl;
return;
}
std::cout << PyUnicode_AsUTF8(PyObject_Repr(player_entity->cBehavior->object)) << std::endl;
PyObject* move_fn = PyObject_GetAttrString(player_entity->cBehavior->object, "move");
std::cout << PyUnicode_AsUTF8(PyObject_Repr(move_fn)) << std::endl;
if (move_fn) {
std::cout << "Calling `move`" << std::endl;
PyObject* move_args = Py_BuildValue("(ii)", dx, dy);
PyObject_CallObject((PyObject*) move_fn, move_args);
} else {
std::cout << "player_input called on entity with no `move` method" << std::endl;
}
}

View File

@ -107,6 +107,10 @@ public:
static int turn_number; static int turn_number;
static PyObject* _turnNumber(PyObject*, PyObject*); static PyObject* _turnNumber(PyObject*, PyObject*);
// accept keyboard input from scene
static sf::Vector2i cursor_position;
static void player_input(int, int);
// 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);
static void createCaption(std::string menukey, std::string text, int fontsize, sf::Color textcolor); static void createCaption(std::string menukey, std::string text, int fontsize, sf::Color textcolor);

View File

@ -212,6 +212,15 @@ void PythonScene::doAction(std::string name, std::string type) {
// try zoom out // try zoom out
doZoom(mousepos, -1); doZoom(mousepos, -1);
} }
else if (ACTIONONCE("up")) { McRFPy_API::player_input(+0, -1); }
else if (ACTIONONCE("upright")) { McRFPy_API::player_input(+1, -1); }
else if (ACTIONONCE("right")) { McRFPy_API::player_input(+1, +0); }
else if (ACTIONONCE("downright")) { McRFPy_API::player_input(+1, +1); }
else if (ACTIONONCE("down")) { McRFPy_API::player_input(+0, +1); }
else if (ACTIONONCE("downleft")) { McRFPy_API::player_input(-1, +1); }
else if (ACTIONONCE("left")) { McRFPy_API::player_input(-1, +0); }
else if (ACTIONONCE("upleft")) { McRFPy_API::player_input(-1, -1); }
else if (ACTIONONCE("wait")) { McRFPy_API::player_input(+0, +0); }
} }
void PythonScene::sRender() { void PythonScene::sRender() {

View File

@ -8,8 +8,90 @@ WHITE = (255, 255, 255)
RED, GREEN, BLUE = (255, 0, 0), (0, 255, 0), (0, 0, 255) RED, GREEN, BLUE = (255, 0, 0), (0, 255, 0), (0, 0, 255)
DARKRED, DARKGREEN, DARKBLUE = (192, 0, 0), (0, 192, 0), (0, 0, 192) DARKRED, DARKGREEN, DARKBLUE = (192, 0, 0), (0, 192, 0), (0, 0, 192)
animations_in_progress = 0
class TestEntity: class TestEntity:
pass def __init__(self, grid, label, tex_index, basesprite, x, y, texture_width=64, walk_frames=5, attack_frames=6):
self.grid = grid
self.basesprite = basesprite
self.texture_width = texture_width
self.walk_frames = walk_frames
self.attack_frames = attack_frames
self.x = x
self.y = y
self.facing_direction = 0
#print(f"Calling C++ with: {repr((self.grid, label, tex_index, self.basesprite, x, y, self))}")
grids = mcrfpy.listGrids()
for g in grids:
if g.title == self.grid:
self.entity_index = len(g.entities)
mcrfpy.createEntity(self.grid, label, tex_index, self.basesprite, x, y, self)
def move(self, dx, dy):
# select animation direction
# prefer left or right for diagonals.
if (dx == 0 and dy == 0):
direction = self.facing_direction # TODO, jump straight to computer turn
elif (dx):
direction = 2 if dx == +1 else 3
else:
direction = 0 if dy == +1 else 1
self.animate(direction, move=True, animove=(self.x + dx, self.y+dy))
self.facing_direction = direction
def animate(self, direction, attacking=False, move=False, animove=None):
start_sprite = self.basesprite + (self.texture_width * (direction + (4 if attacking else 0)))
animation_frames = [start_sprite + i for i in range((self.attack_frames if attacking else self.walk_frames))]
mcrfpy.createAnimation(
0.25, # duration, seconds
self.grid, # parent: a UIMenu or Grid key
"entity", # target type: 'menu', 'grid', 'caption', 'button', 'sprite', or 'entity'
self.entity_index, # target id: integer index for menu or grid objs; None for grid/menu
"sprite", # field: 'position', 'size', 'bgcolor', 'textcolor', or 'sprite'
self.animation_done, #callback: callable once animation is complete
False, #loop: repeat indefinitely
animation_frames # values: iterable of frames for 'sprite', lerp target for others
)
global animations_in_progress
animations_in_progress += 1
if move:
pos = [self.x, self.y]
if (direction == 0): pos[1] += 1
elif (direction == 1): pos[1] -= 1
elif (direction == 2): pos[0] += 1
elif (direction == 3): pos[0] -= 1
if not animove:
self.x, self.y = pos
animove = pos
else:
pos = animove
self.x, self.y = animove
#scene.move_entity(self.grid, self.entity_index, pos)
for g in mcrfpy.listGrids():
if g.title == self.grid:
g.entities[self.entity_index].x = pos[0]
g.entities[self.entity_index].y = pos[1]
mcrfpy.modGrid(g)
if animove:
mcrfpy.createAnimation(
0.25, # duration, seconds
self.grid, # parent: a UIMenu or Grid key
"entity", # target type: 'menu', 'grid', 'caption', 'button', 'sprite', or 'entity'
self.entity_index, # target id: integer index for menu or grid objs; None for grid/menu
"position", # field: 'position', 'size', 'bgcolor', 'textcolor', or 'sprite'
self.animation_done, #callback: callable once animation is complete
False, #loop: repeat indefinitely
animove # values: iterable of frames for 'sprite', lerp target for others
)
animations_in_progress += 1
def animation_done(self):
global animations_in_progress
animations_in_progress -= 1
#print(f"{self} done animating")
# if animations_in_progress == 0: mcrfpy.unlockPlayerInput()
class TestScene: class TestScene:
def __init__(self, ui_name = "demobox1", grid_name = "demogrid"): def __init__(self, ui_name = "demobox1", grid_name = "demogrid"):
@ -18,24 +100,25 @@ class TestScene:
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
mcrfpy.createTexture("./assets/alives_other.png", 32, 32, 32) #2 - TinyWorld NPCs - 2x2 sprite mcrfpy.createTexture("./assets/alives_other.png", 32, 32, 32) #2 - TinyWorld NPCs - 2x2 sprite
mcrfpy.createTexture("./assets/custom_player.png", 16, 5, 13) #3 - player
self.ui_name = ui_name self.ui_name = ui_name
self.grid_name = grid_name self.grid_name = grid_name
print("Create UI") print("Create UI")
# Create dialog UI # Create dialog UI
mcrfpy.createMenu(ui_name, 20, 520, 500, 200) mcrfpy.createMenu(ui_name, 20, 540, 500, 200)
#mcrfpy.createCaption(ui_name, "Hello There", 18, BLACK) #mcrfpy.createCaption(ui_name, "Hello There", 18, BLACK)
mcrfpy.createCaption(ui_name, "", 24, RED) mcrfpy.createCaption(ui_name, "", 24, RED)
#mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKBLUE, (0, 0, 0), "clicky", "testaction") #mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKBLUE, (0, 0, 0), "clicky", "testaction")
mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKRED, (0, 0, 0), "REPL", "startrepl") mcrfpy.createButton(ui_name, 250, 0, 130, 40, DARKRED, (0, 0, 0), "REPL", "startrepl")
mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKGREEN, (0, 0, 0), "map gen", "gridgen") mcrfpy.createButton(ui_name, 250, 0, 130, 40, DARKGREEN, (0, 0, 0), "map gen", "gridgen")
#mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKGREEN, (0, 0, 0), "mapL", "gridgen2") #mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKGREEN, (0, 0, 0), "mapL", "gridgen2")
#mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKBLUE, (192, 0, 0), "a_menu", "animtest") #mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKBLUE, (192, 0, 0), "a_menu", "animtest")
#mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKRED, GREEN, "a_spr", "animtest2") #mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKRED, GREEN, "a_spr", "animtest2")
mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKBLUE, GREEN, "Next sp", "nextsp") mcrfpy.createButton(ui_name, 250, 0, 130, 40, DARKBLUE, GREEN, "Next sp", "nextsp")
mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKBLUE, RED, "Prev sp", "prevsp") mcrfpy.createButton(ui_name, 250, 0, 130, 40, DARKBLUE, RED, "Prev sp", "prevsp")
mcrfpy.createButton(ui_name, 250, 20, 100, 50, DARKBLUE, RED, "+16 sp", "skipsp") mcrfpy.createButton(ui_name, 250, 0, 130, 40, DARKBLUE, DARKGREEN, "+16 sp", "skipsp")
mcrfpy.createSprite(ui_name, 2, randint(0, 3), 20, 40, 5.0) mcrfpy.createSprite(ui_name, 1, 0, 20, 40, 3.0)
print("Create UI 2") print("Create UI 2")
entitymenu = "entitytestmenu" entitymenu = "entitytestmenu"
@ -46,7 +129,7 @@ class TestScene:
mcrfpy.createButton(entitymenu, 0, 110, 150, 40, DARKBLUE, BLACK, "Left", "test_left") mcrfpy.createButton(entitymenu, 0, 110, 150, 40, DARKBLUE, BLACK, "Left", "test_left")
mcrfpy.createButton(entitymenu, 0, 160, 150, 40, DARKBLUE, BLACK, "Right", "test_right") mcrfpy.createButton(entitymenu, 0, 160, 150, 40, DARKBLUE, BLACK, "Right", "test_right")
mcrfpy.createButton(entitymenu, 0, 210, 150, 40, DARKBLUE, BLACK, "Attack", "test_attack") mcrfpy.createButton(entitymenu, 0, 210, 150, 40, DARKBLUE, BLACK, "Attack", "test_attack")
mcrfpy.createButton(entitymenu, 0, 210, 150, 40, DARKBLUE, RED, "TE", "testent")
print("Make UIs visible") print("Make UIs visible")
self.menus = mcrfpy.listMenus() self.menus = mcrfpy.listMenus()
self.menus[0].visible = True self.menus[0].visible = True
@ -54,22 +137,42 @@ class TestScene:
self.menus[1].visible = True self.menus[1].visible = True
mcrfpy.modMenu(self.menus[0]) mcrfpy.modMenu(self.menus[0])
mcrfpy.modMenu(self.menus[1]) mcrfpy.modMenu(self.menus[1])
print(mcrfpy.listMenus())
print("Create grid") print("Create grid")
# create grid (title, gx, gy, gs, x, y, w, h) # create grid (title, gx, gy, gs, x, y, w, h)
mcrfpy.createGrid(grid_name, 20, 20, 16, 20, 20, 800, 500) mcrfpy.createGrid(grid_name, 20, 20, 16, 20, 20, 800, 500)
self.grids = mcrfpy.listGrids() self.grids = mcrfpy.listGrids()
print(self.grids)
print("Create entities") print("Create entities")
mcrfpy.createEntity("demogrid", "dragon", 2, 545, 10, 10, lambda: None) #mcrfpy.createEntity("demogrid", "dragon", 2, 545, 10, 10, lambda: None)
mcrfpy.createEntity("demogrid", "tinyenemy", 1, 1538, 3, 6, lambda: None) #mcrfpy.createEntity("demogrid", "tinyenemy", 1, 1538, 3, 6, lambda: None)
print("Create fancy entity")
self.tes = [
TestEntity("demogrid", "classtest", 1, 1538, 5, 7, 64, walk_frames=5, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 1545, 7, 9, 64, walk_frames=5, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 1552, 9, 11, 64, walk_frames=5, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 1566, 11, 13, 64, walk_frames=4, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 1573, 13, 15, 64, walk_frames=4, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 1583, 15, 17, 64, walk_frames=4, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 130, 9, 7, 64, walk_frames=5, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 136, 11, 9, 64, walk_frames=5, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 143, 13, 11, 64, walk_frames=5, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 158, 15, 13, 64, walk_frames=5, attack_frames=6),
TestEntity("demogrid", "classtest", 1, 165, 17, 15, 64, walk_frames=5, attack_frames=6),
TestEntity("demogrid", "player", 3, 20, 17, 3, 5, walk_frames=4, attack_frames=5)
]
self.grids = mcrfpy.listGrids()
self.entity_direction = 0 self.entity_direction = 0
mcrfpy.registerPyAction("test_down", lambda: self.animate_entity(0, False)) mcrfpy.registerPyAction("test_down", lambda: [te.animate(0, False, True) for te in self.tes])
mcrfpy.registerPyAction("test_up", lambda: self.animate_entity(1, False)) mcrfpy.registerPyAction("test_up", lambda: [te.animate(1, False, True) for te in self.tes])
mcrfpy.registerPyAction("test_right", lambda: self.animate_entity(2, False)) mcrfpy.registerPyAction("test_right", lambda: [te.animate(2, False, True) for te in self.tes])
mcrfpy.registerPyAction("test_left", lambda: self.animate_entity(3, False)) mcrfpy.registerPyAction("test_left", lambda: [te.animate(3, False, True) for te in self.tes])
mcrfpy.registerPyAction("test_attack", lambda: self.animate_entity(None, True)) mcrfpy.registerPyAction("test_attack", lambda: [te.animate(0, True) for te in self.tes])
mcrfpy.registerPyAction("testent", lambda: [te.animate(2, True) for te in self.tes])
# Button behavior # Button behavior
self.clicks = 0 self.clicks = 0
@ -115,6 +218,18 @@ class TestScene:
orc_animation # values: iterable of frames for 'sprite', lerp target for others orc_animation # values: iterable of frames for 'sprite', lerp target for others
) )
#def move_entity(self, targetgrid, entity_index, position):
# for i, g in enumerate(self.grids):
# if g.title == targetgrid:
# g.entities[entity_index].x = position[0]
# g.entities[entity_index].y = position[1]
# #pts = g.points
# g.visible = True
# mcrfpy.modGrid(g)
# self.grids = mcrfpy.listGrids()
# #self.grids[i].points = pts
# return
def changesprite(self, n): def changesprite(self, n):
self.sprite_index += n self.sprite_index += n
@ -129,12 +244,14 @@ class TestScene:
mcrfpy.modMenu(self.menus[0]) mcrfpy.modMenu(self.menus[0])
def gridgen(self): def gridgen(self):
print(f"[Python] modifying {len(self.grids[0].points)} grid points") #print(f"[Python] modifying {len(self.grids[0].points)} grid points")
for p in self.grids[0].points: for p in self.grids[0].points:
p.color = (randint(0, 255), randint(64, 192), 0) p.color = (randint(0, 255), randint(64, 192), 0)
print("[Python] Modifying:") #print("[Python] Modifying:")
self.grids[0].visible = True self.grids[0].visible = True
mcrfpy.modGrid(self.grids[0]) mcrfpy.modGrid(self.grids[0])
print(f"Sent grid: {repr(self.grids[0])}")
print(f"Received grid: {repr(mcrfpy.listGrids()[0])}")
def animation_done(self, s): def animation_done(self, s):
print(f"The `{s}` animation completed.") print(f"The `{s}` animation completed.")