quick & dirty timer functionality

This commit is contained in:
John McCardle 2024-03-07 08:59:26 -05:00
parent 9d728ee902
commit ccd79fc551
6 changed files with 118 additions and 0 deletions

View File

@ -37,6 +37,7 @@ GameEngine::GameEngine()
IndexSprite::game = this;
clock.restart();
runtime.restart();
}
Scene* GameEngine::currentScene() { return scenes[scene]; }
@ -55,6 +56,7 @@ void GameEngine::run()
while (running)
{
currentScene()->update();
testTimers();
sUserInput();
if (!paused)
{
@ -67,6 +69,36 @@ void GameEngine::run()
}
}
void GameEngine::manageTimer(std::string name, PyObject* target, int interval)
{
//std::cout << "Manage timer called. " << name << " " << interval << std::endl;
if (timers.find(name) != timers.end()) // overwrite existing
{
if (target == NULL || target == Py_None) // delete
{
Py_DECREF(target);
timers.erase(name);
return;
}
}
if (target == NULL || target == Py_None)
{
std::cout << "Refusing to initialize timer to None. It's not an error, it's just pointless." << std::endl;
return;
}
timers[name] = Timer(target, interval, runtime.getElapsedTime().asMilliseconds());
Py_INCREF(target);
}
void GameEngine::testTimers()
{
int now = runtime.getElapsedTime().asMilliseconds();
for (auto& [name, timer]: timers)
{
timer.test(now);
}
}
void GameEngine::sUserInput()
{
sf::Event event;

View File

@ -6,6 +6,7 @@
#include "Scene.h"
#include "McRFPy_API.h"
#include "IndexTexture.h"
#include "Timer.h"
class GameEngine
{
@ -20,6 +21,10 @@ class GameEngine
float frameTime;
std::string window_title;
sf::Clock runtime;
std::map<std::string, Timer> timers;
void testTimers();
public:
std::string scene;
GameEngine();
@ -35,6 +40,7 @@ public:
int getFrame() { return currentFrame; }
float getFrameTime() { return frameTime; }
sf::View getView() { return visible; }
void manageTimer(std::string, PyObject*, int);
// global textures for scripts to access
std::vector<IndexTexture> textures;

View File

@ -32,6 +32,9 @@ static PyMethodDef mcrfpyMethods[] = {
{"createScene", McRFPy_API::_createScene, METH_VARARGS, "createScene(scene) - create a new blank scene with given name"},
{"keypressScene", McRFPy_API::_keypressScene, METH_VARARGS, "keypressScene(callable) - assign a callable object to the current scene receive keypress events"},
{"setTimer", McRFPy_API::_setTimer, METH_VARARGS, "setTimer(name:str, callable:object, interval:int) - callable will be called with args (runtime:float) every `interval` milliseconds"},
{"delTimer", McRFPy_API::_delTimer, METH_VARARGS, "delTimer(name:str) - stop calling the timer labelled with `name`"},
{NULL, NULL, 0, NULL}
};
@ -450,3 +453,21 @@ PyObject* McRFPy_API::_keypressScene(PyObject* self, PyObject* args) {
Py_INCREF(Py_None);
return Py_None;
}
PyObject* McRFPy_API::_setTimer(PyObject* self, PyObject* args) { // TODO - compare with UIDrawable mouse & Scene Keyboard methods - inconsistent responsibility for incref/decref around mcrogueface
const char* name;
PyObject* callable;
int interval;
if (!PyArg_ParseTuple(args, "sOi", &name, &callable, &interval)) return NULL;
game->manageTimer(name, callable, interval);
Py_INCREF(Py_None);
return Py_None;
}
PyObject* McRFPy_API::_delTimer(PyObject* self, PyObject* args) {
const char* name;
if (!PyArg_ParseTuple(args, "s", &name)) return NULL;
game->manageTimer(name, NULL, 0);
Py_INCREF(Py_None);
return Py_None;
}

View File

@ -74,6 +74,11 @@ public:
static PyObject* _currentScene(PyObject*, PyObject*);
static PyObject* _createScene(PyObject*, PyObject*);
static PyObject* _keypressScene(PyObject*, PyObject*);
// timer control
static PyObject* _setTimer(PyObject*, PyObject*);
static PyObject* _delTimer(PyObject*, PyObject*);
// accept keyboard input from scene
static sf::Vector2i cursor_position;
static void player_input(int, int);

37
src/Timer.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "Timer.h"
Timer::Timer(PyObject* _target, int _interval, int now)
: target(_target), interval(_interval), last_ran(now)
{
//Py_INCREF(target);
}
Timer::Timer()
: target(Py_None), interval(0), last_ran(0)
{}
Timer::Timer(Timer& other)
: target(other.target), interval(other.interval), last_ran(other.last_ran)
{
//Py_INCREF(target);
}
Timer::~Timer()
{
//if (target && target != Py_None)
// Py_DECREF(target);
}
bool Timer::test(int now)
{
if (!target || target == Py_None) return false;
if (now > last_ran + interval)
{
last_ran = now;
PyObject* args = Py_BuildValue("(i)", now);
std::cout << PyUnicode_AsUTF8(PyObject_Repr(args)) << std::endl;
PyObject_Call(target, args, NULL);
return true;
}
return false;
}

17
src/Timer.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include "Common.h"
#include "Python.h"
class GameEngine; // forward declare
class Timer
{
public:
PyObject* target;
int interval;
int last_ran;
Timer(); // for map to build
Timer(Timer& other); // copy constructor
Timer(PyObject*, int, int);
~Timer();
bool test(int);
};