FabGL
ESP32 Display Controller and Graphics Library
scene.cpp
1 /*
2  Created by Fabrizio Di Vittorio (fdivitto2013@gmail.com) - <http://www.fabgl.com>
3  Copyright (c) 2019-2021 Fabrizio Di Vittorio.
4  All rights reserved.
5 
6 
7 * Please contact fdivitto2013@gmail.com if you need a commercial license.
8 
9 
10 * This library and related software is available under GPL v3. Feel free to use FabGL in free software and hardware:
11 
12  FabGL is free software: you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation, either version 3 of the License, or
15  (at your option) any later version.
16 
17  FabGL is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with FabGL. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 
27 #include "freertos/FreeRTOS.h"
28 #include "freertos/task.h"
29 #include "freertos/semphr.h"
30 
31 #include "fabutils.h"
32 #include "scene.h"
33 
34 
35 
36 #pragma GCC optimize ("O2")
37 
38 
39 namespace fabgl {
40 
41 
42 Scene::Scene(int maxSpritesCount, int updateTimeMS, int width, int height, int stackSize)
43  : m_width(width),
44  m_height(height),
45  m_updateTimeMS(updateTimeMS),
46  m_collisionDetector(maxSpritesCount, width, height),
47  m_suspendedTask(nullptr),
48  m_running(false)
49 {
50  m_mutex = xSemaphoreCreateMutex();
51  xSemaphoreTake(m_mutex, portMAX_DELAY); // suspend update task
52  xTaskCreate(updateTask, "", FABGL_DEFAULT_SCENETASK_STACKSIZE, this, 5, &m_updateTaskHandle);
53 }
54 
55 
56 Scene::~Scene()
57 {
58  stop();
59  xSemaphoreTake(m_mutex, portMAX_DELAY); // suspend update task
60  vTaskDelete(m_updateTaskHandle);
61  vSemaphoreDelete(m_mutex);
62 }
63 
64 
65 void Scene::start(bool suspendTask)
66 {
67  if (!m_running) {
68  m_running = true;
69  m_updateCount = 0;
70  init();
71  xSemaphoreGive(m_mutex); // resume update task
72  if (suspendTask) {
73  m_suspendedTask = xTaskGetCurrentTaskHandle();
74  vTaskSuspend(m_suspendedTask);
75  } else
76  m_suspendedTask = nullptr;
77  }
78 }
79 
80 
82 {
83  if (m_running) {
84  // are we inside update task?
85  if (xTaskGetCurrentTaskHandle() != m_updateTaskHandle)
86  xSemaphoreTake(m_mutex, portMAX_DELAY); // no, suspend update task
87  m_running = false;
88  if (m_suspendedTask)
89  vTaskResume(m_suspendedTask);
90  }
91 }
92 
93 
94 void Scene::updateTask(void * pvParameters)
95 {
96  Scene * scene = (Scene*) pvParameters;
97 
98  while (true) {
99 
100  xSemaphoreTake(scene->m_mutex, portMAX_DELAY);
101 
102  int64_t t0 = esp_timer_get_time(); // us
103 
104  if (scene->m_running) {
105  scene->m_updateCount += 1;
106  scene->update(scene->m_updateCount);
107  }
108 
109  xSemaphoreGive(scene->m_mutex);
110 
111  int64_t t1 = esp_timer_get_time(); // us
112  int delayMS = (scene->m_updateTimeMS - (t1 - t0) / 1000);
113  if (delayMS > 0)
114  vTaskDelay(delayMS / portTICK_PERIOD_MS);
115  }
116 }
117 
118 
119 void collisionDetectionCallback(void * callbackObj, Sprite * spriteA, Sprite * spriteB, Point collisionPoint)
120 {
121  ((Scene*)callbackObj)->collisionDetected(spriteA, spriteB, collisionPoint);
122 }
123 
124 
126 {
127  m_collisionDetector.updateAndDetectCollision(sprite, collisionDetectionCallback, this);
128 }
129 
130 
131 
132 
133 } // end of namespace
Scene(int maxSpritesCount, int updateTimeMS, int width, int height, int stackSize=2048)
The Scene constructor.
Definition: scene.cpp:42
Represents a sprite.
This file contains fabgl::Scene definition.
Scene is an abstract class useful to encapsulate functionalities of a scene (sprites, collision detector and updates).
Definition: scene.h:55
This file contains some utility classes and functions.
Definition: canvas.cpp:36
virtual void init()=0
This is an abstract method called when the scene needs to be initialized.
Sprite * updateAndDetectCollision(Sprite *sprite, bool removeCollidingSprites=true)
Updates collision detector and detect collision with the specified sprite.
void updateSpriteAndDetectCollisions(Sprite *sprite)
Updates collision detector and generate collision events.
Definition: scene.cpp:125
uint8_t height
void start(bool suspendTask=true)
Starts scene updates and suspends current task.
Definition: scene.cpp:65
void stop()
Stops scene updates and resumes suspended task.
Definition: scene.cpp:81
uint8_t width
virtual void update(int updateCount)=0
This is an abstract method called whenever the scene needs to be updated.