Gamedev Framework (gf)  0.19.0
A C++17 framework for 2D games
Activities.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2021 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #ifndef GF_ACTIVITIES_H
22 #define GF_ACTIVITIES_H
23 
24 #include <cassert>
25 #include <functional>
26 #include <vector>
27 
28 #include "Activity.h"
29 #include "CoreApi.h"
30 #include "Ref.h"
31 #include "Tween.h"
32 #include "Vector.h"
33 
34 namespace gf {
35 #ifndef DOXYGEN_SHOULD_SKIP_THIS
36 inline namespace v1 {
37 #endif
38 
45  class GF_CORE_API ValueActivity : public Activity {
46  public:
56  ValueActivity(float origin, float target, float& value, Time duration, Easing easing = Ease::linear);
57 
63  void setOrigin(float origin) {
64  m_tween.setOrigin(origin);
65  }
66 
72  float getOrigin() const noexcept {
73  return m_tween.getOrigin();
74  }
75 
81  void setTarget(float target) {
82  m_tween.setTarget(target);
83  }
84 
90  float getTarget() const noexcept {
91  return m_tween.getTarget();
92  }
93 
99  void setDuration(Time duration) {
100  m_tween.setDuration(duration);
101  }
102 
108  Time getDuration() const noexcept {
109  return m_tween.getDuration();
110  }
111 
112  ActivityStatus run(Time time) override;
113  void restart() override;
114 
115  private:
116  Tween<float> m_tween;
117  };
118 
119 
128  class GF_CORE_API RotateToActivity : public Activity {
129  public:
139  RotateToActivity(float origin, float target, float& angle, Time duration, Easing easing = Ease::linear);
140 
146  void setOrigin(float origin) {
147  m_tween.setOrigin(origin);
148  normalize();
149  }
150 
156  float getOrigin() const noexcept {
157  return m_tween.getOrigin();
158  }
159 
165  void setTarget(float target) {
166  m_tween.setTarget(target);
167  normalize();
168  }
169 
175  float getTarget() const noexcept {
176  return m_tween.getTarget();
177  }
178 
184  void setDuration(Time duration) {
185  m_tween.setDuration(duration);
186  }
187 
193  Time getDuration() const noexcept {
194  return m_tween.getDuration();
195  }
196 
197  ActivityStatus run(Time time) override;
198  void restart() override;
199 
200  private:
201  void normalize();
202 
203  private:
204  Tween<float> m_tween;
205  };
206 
207 
214  class GF_CORE_API MoveToActivity : public Activity {
215  public:
225  MoveToActivity(Vector2f origin, Vector2f target, Vector2f& position, Time duration, Easing easing = Ease::linear);
226 
232  void setOrigin(Vector2f origin) {
233  m_tween.setOrigin(origin);
234  }
235 
241  Vector2f getOrigin() const noexcept {
242  return m_tween.getOrigin();
243  }
244 
250  void setTarget(Vector2f target) {
251  m_tween.setTarget(target);
252  }
253 
259  Vector2f getTarget() const noexcept {
260  return m_tween.getTarget();
261  }
262 
268  void setDuration(Time duration) {
269  m_tween.setDuration(duration);
270  }
271 
277  Time getDuration() const noexcept {
278  return m_tween.getDuration();
279  }
280 
281  ActivityStatus run(Time time) override;
282  void restart() override;
283 
284  private:
285  Tween<Vector2f> m_tween;
286  };
287 
288 
295  class GF_CORE_API ColorActivity : public Activity {
296  public:
306  ColorActivity(Color4f origin, Color4f target, Color4f& color, Time duration, Easing easing = Ease::linear);
307 
313  void setOrigin(Color4f origin) {
314  m_tween.setOrigin(origin);
315  }
316 
322  Color4f getOrigin() const noexcept {
323  return m_tween.getOrigin();
324  }
325 
331  void setTarget(Color4f target) {
332  m_tween.setTarget(target);
333  }
334 
340  Color4f getTarget() const noexcept {
341  return m_tween.getTarget();
342  }
343 
349  void setDuration(Time duration) {
350  m_tween.setDuration(duration);
351  }
352 
358  Time getDuration() const noexcept {
359  return m_tween.getDuration();
360  }
361 
362  ActivityStatus run(Time time) override;
363  void restart() override;
364 
365  private:
366  Tween<Color4f> m_tween;
367  };
368 
369 
374  class GF_CORE_API CallbackActivity : public Activity {
375  public:
381  CallbackActivity(std::function<void()> callback);
382 
383  ActivityStatus run(Time time) override;
384  void restart() override;
385 
386  private:
387  std::function<void()> m_callback;
388  bool m_called;
389  };
390 
391 
396  class GF_CORE_API DelayActivity : public Activity {
397  public:
403  DelayActivity(Time duration);
404 
405  ActivityStatus run(Time time) override;
406  void restart() override;
407 
408  private:
409  Time m_elapsed;
410  Time m_duration;
411  };
412 
413 
418  class GF_CORE_API SequenceActivity : public Activity {
419  public:
424 
430  void addActivity(Activity& activity);
431 
435  void clear();
436 
437  ActivityStatus run(Time time) override;
438  void restart() override;
439 
440  private:
441  std::size_t m_current;
442  std::vector<Ref<Activity>> m_activities;
443  };
444 
445 
450  class GF_CORE_API RepeatActivity : public Activity {
451  public:
458  RepeatActivity(Activity& activity, int repeat = 0);
459 
460  ActivityStatus run(Time time) override;
461  void restart() override;
462 
463  private:
464  Ref<Activity> m_activity;
465  int m_count;
466  int m_repeat;
467  };
468 
472  enum class ActivityFinish {
473  Any,
474  All,
475  };
476 
481  class GF_CORE_API ParallelActivity : public Activity {
482  public:
483 
490 
496  void addActivity(Activity& activity);
497 
501  void clear();
502 
503  ActivityStatus run(Time time) override;
504  void restart() override;
505 
506  private:
507  ActivityFinish m_finish;
508  ActivityStatus m_status;
509  std::vector<Ref<Activity>> m_activities;
510  };
511 
515  namespace activity {
525  inline
526  ValueActivity value(float origin, float target, float& value, Time duration, Easing easing = Ease::linear) {
527  return ValueActivity(origin, target, value, duration, easing);
528  }
529 
539  inline
540  RotateToActivity rotateTo(float origin, float target, float& angle, Time duration, Easing easing = Ease::linear) {
541  return RotateToActivity(origin, target, angle, duration, easing);
542  }
543 
553  inline
554  MoveToActivity moveTo(Vector2f origin, Vector2f target, Vector2f& position, Time duration, Easing easing = Ease::linear) {
555  return MoveToActivity(origin, target, position, duration, easing);
556  }
557 
567  inline
568  ColorActivity color(Color4f origin, Color4f target, Color4f& color, Time duration, Easing easing = Ease::linear) {
569  return ColorActivity(origin, target, color, duration, easing);
570  }
571 
577  inline
578  CallbackActivity call(std::function<void()> callback) {
579  return CallbackActivity(std::move(callback));
580  }
581 
587  inline
589  return DelayActivity(duration);
590  }
591 
592 #ifndef DOXYGEN_SHOULD_SKIP_THIS
593  // inspired by https://accu.org/journals/overload/25/139/williams_2382/
594 
595  template<typename Tuple, std::size_t I>
596  Activity& activityTupleGet(Tuple& tuple) {
597  return std::get<I>(tuple);
598  }
599 
600  template<typename Tuple, typename Indices = std::make_index_sequence<std::tuple_size_v<Tuple>>>
601  struct ActivityTupleGetters;
602 
603  template<typename Tuple, std::size_t ... Indices>
604  struct ActivityTupleGetters<Tuple, std::index_sequence<Indices...>>
605  {
606  using Getter = Activity& (*)(Tuple&);
607  static inline constexpr Getter table[std::tuple_size_v<Tuple>] = { &activityTupleGet<Tuple, Indices>... };
608  };
609 
610  template<typename Tuple>
611  Activity& activityTupleGetIth(Tuple& tuple, std::size_t i) {
612  assert(i < std::tuple_size_v<Tuple>);
613  return ActivityTupleGetters<Tuple>::table[i](tuple);
614  }
615 
616 #endif
617 
621  template<typename... Args>
622  class SequenceActivityEx : public Activity {
623  public:
629  SequenceActivityEx(Args... activities)
630  : m_current(0)
631  , m_activities(std::forward<Args>(activities)...)
632  {
633  }
634 
635  ActivityStatus run(Time time) override {
636  if (m_current == sizeof... (Args)) {
638  }
639 
640  Activity& currentActivity = activityTupleGetIth(m_activities, m_current);
641  auto status = currentActivity.run(time);
642 
643  if (status == ActivityStatus::Finished) {
644  m_current++;
645  }
646 
647  return m_current == sizeof... (Args) ? ActivityStatus::Finished : ActivityStatus::Running;
648  }
649 
650  void restart() override {
651  m_current = 0;
652 
653  for (std::size_t i = 0; i < sizeof ... (Args); ++i) {
654  activityTupleGetIth(m_activities, i).restart();
655  }
656  }
657 
658  private:
659  std::size_t m_current;
660  std::tuple<Args...> m_activities;
661  };
662 
668  template<typename... Args>
669  SequenceActivityEx<Args...> sequence(Args... activities) {
670  return SequenceActivityEx<Args...>(std::forward<Args>(activities)...);
671  }
672 
676  template<typename Other>
677  class RepeatActivityEx : public Activity {
678  public:
685  RepeatActivityEx(Other activity, int repeat)
686  : m_activity(std::move(activity))
687  , m_count(0)
688  , m_repeat(repeat)
689  {
690  }
691 
692  ActivityStatus run(Time time) override {
693  if (m_count > 0 && m_repeat == m_count) {
695  }
696 
697  auto status = m_activity.run(time);
698 
699  if (status == ActivityStatus::Finished) {
700  m_activity.restart();
701  m_count++;
702  }
703 
704  return (m_repeat > 0 && m_repeat == m_count) ? ActivityStatus::Finished : ActivityStatus::Running;
705  }
706 
707  void restart() override {
708  m_count = 0;
709  m_activity.restart();
710  }
711 
712  private:
713  Other m_activity;
714  int m_count;
715  int m_repeat;
716  };
717 
724  template<typename Other>
725  RepeatActivityEx<Other> repeat(Other activity, int repeat = 0) {
726  return RepeatActivityEx<Other>(std::move(activity), repeat);
727  }
728 
732  template<typename... Args>
733  class ParallelActivityEx : public Activity {
734  public:
741  ParallelActivityEx(ActivityFinish finish, Args... activities)
742  : m_finish(finish)
743  , m_status(ActivityStatus::Running)
744  , m_activities(std::forward<Args>(activities)...)
745  {
746  }
747 
748  ActivityStatus run(Time time) override {
749  if (m_status == ActivityStatus::Finished) {
751  }
752 
753  std::size_t finished = 0;
754 
755  for (std::size_t i = 0; i < sizeof ... (Args); ++i) {
756  auto status = activityTupleGetIth(m_activities, i).run(time);
757 
758  if (status == ActivityStatus::Finished) {
759  finished++;
760  }
761  }
762 
763  switch (m_finish) {
764  case ActivityFinish::Any:
765  if (finished > 0) {
766  m_status = ActivityStatus::Finished;
767  }
768  break;
769 
770  case ActivityFinish::All:
771  if (finished == sizeof ... (Args)) {
772  m_status = ActivityStatus::Finished;
773  }
774  break;
775  }
776 
777  return m_status;
778  }
779 
780  void restart() override {
781  m_status = ActivityStatus::Running;
782 
783  for (std::size_t i = 0; i < sizeof ... (Args); ++i) {
784  activityTupleGetIth(m_activities, i).restart();
785  }
786  }
787 
788 
789  private:
790  ActivityFinish m_finish;
791  ActivityStatus m_status;
792  std::tuple<Args...> m_activities;
793  };
794 
800  template<typename... Args>
801  ParallelActivityEx<Args...> parallelAny(Args... activities) {
802  return ParallelActivityEx<Args...>(ActivityFinish::Any, std::forward<Args>(activities)...);
803  }
804 
810  template<typename... Args>
811  ParallelActivityEx<Args...> parallelAll(Args... activities) {
812  return ParallelActivityEx<Args...>(ActivityFinish::All, std::forward<Args>(activities)...);
813  }
814 
818  class AnyActivity : public Activity {
819  public:
825  template<typename Other>
826  explicit AnyActivity(Other other)
827  : m_activity(std::make_unique<Other>(std::move(other)))
828  {
829  }
830 
831  ActivityStatus run(Time time) override {
832  return m_activity->run(time);
833  }
834 
835  void restart() override {
836  m_activity->restart();
837  }
838 
839  private:
840  std::unique_ptr<Activity> m_activity;
841  };
842 
843  }
844 
845 #ifndef DOXYGEN_SHOULD_SKIP_THIS
846 }
847 #endif
848 }
849 
850 #endif // GF_ACTIVITIES_H
Time getDuration() const noexcept
Get the duration of the activity.
Definition: Activities.h:277
A gf::ParallelActivity that holds its activities.
Definition: Activities.h:733
virtual ActivityStatus run(Time time)=0
Run the activity.
Time getDuration() const noexcept
Get the duration of the activity.
Definition: Activities.h:108
float(*)(float) Easing
An easing function.
Definition: Easings.h:48
AnyActivity(Other other)
Constructor.
Definition: Activities.h:826
void setOrigin(Vector2f origin)
Change the origin of the activity.
Definition: Activities.h:232
ActivityStatus run(Time time) override
Run the activity.
Definition: Activities.h:692
ActivityStatus
Status of an activity.
Definition: Activity.h:38
Color4f getTarget() const noexcept
Get the target of the activity.
Definition: Activities.h:340
An activity for a change of position.
Definition: Activities.h:214
ParallelActivityEx< Args... > parallelAny(Args... activities)
Create a gf::ParallelActivityEx.
Definition: Activities.h:801
void setTarget(float target)
Change the target of the activity.
Definition: Activities.h:81
void setOrigin(float origin)
Change the origin of the activity.
Definition: Activities.h:63
void setDuration(Time duration)
Change the duration of the activity.
Definition: Activities.h:99
ActivityStatus run(Time time) override
Run the activity.
Definition: Activities.h:635
A gf::RepeatActivity that holds its activity.
Definition: Activities.h:677
RepeatActivityEx< Other > repeat(Other activity, int repeat=0)
Definition: Activities.h:725
RepeatActivityEx(Other activity, int repeat)
Constructor.
Definition: Activities.h:685
Represents a time value.
Definition: Time.h:65
void setTarget(Color4f target)
Change the target of the activity.
Definition: Activities.h:331
Time getDuration() const noexcept
Get the duration of the activity.
Definition: Activities.h:193
An activity that can hold any other activity.
Definition: Activities.h:818
ParallelActivityEx(ActivityFinish finish, Args... activities)
Constructor.
Definition: Activities.h:741
Time getDuration() const noexcept
Get the duration of the activity.
Definition: Activities.h:358
ActivityStatus run(Time time) override
Run the activity.
Definition: Activities.h:748
CallbackActivity call(std::function< void()> callback)
Create a gf::CallbackActivity.
Definition: Activities.h:578
SequenceActivityEx(Args... activities)
Constructor.
Definition: Activities.h:629
An activity to run an activity several times.
Definition: Activities.h:450
void setOrigin(Color4f origin)
Change the origin of the activity.
Definition: Activities.h:313
void setDuration(Time duration)
Change the duration of the activity.
Definition: Activities.h:184
void restart() override
Restart the activity.
Definition: Activities.h:780
An activity to wait for a predefined duration.
Definition: Activities.h:396
ValueActivity value(float origin, float target, float &value, Time duration, Easing easing=Ease::linear)
Create a gf::ValueActivity.
Definition: Activities.h:526
SequenceActivityEx< Args... > sequence(Args... activities)
Definition: Activities.h:669
The namespace for gf classes.
Definition: Action.h:35
static float linear(float t)
Linear easing.
DelayActivity delay(Time duration)
Create a gf::DelayActivity.
Definition: Activities.h:588
void setOrigin(float origin)
Change the origin of the activity.
Definition: Activities.h:146
Vector2f getTarget() const noexcept
Get the target of the activity.
Definition: Activities.h:259
If all of the activities ends.
An activity for a change of angle.
Definition: Activities.h:128
An activity to run several activities in parallel.
Definition: Activities.h:481
A 4D vector.
Definition: Vector.h:852
The activity is finished.
void setTarget(float target)
Change the target of the activity.
Definition: Activities.h:165
A gf::SequenceActivity that holds its activities.
Definition: Activities.h:622
If any of the activities ends.
void setDuration(Time duration)
Change the duration of the activity.
Definition: Activities.h:268
void restart() override
Restart the activity.
Definition: Activities.h:650
Vector2f getOrigin() const noexcept
Get the origin of the activity.
Definition: Activities.h:241
void setDuration(Time duration)
Change the duration of the activity.
Definition: Activities.h:349
An activity for a change of color.
Definition: Activities.h:295
An activity to run several activities sequentially.
Definition: Activities.h:418
An activity for a simple float value.
Definition: Activities.h:45
ColorActivity color(Color4f origin, Color4f target, Color4f &color, Time duration, Easing easing=Ease::linear)
Create a gf::ColorActivity.
Definition: Activities.h:568
An activity for calling a function once.
Definition: Activities.h:374
GF_CORE_API float angle(Direction direction)
Get an angle from a direction.
ActivityFinish
The type of finish for the activity.
Definition: Activities.h:472
void restart() override
Restart the activity.
Definition: Activities.h:835
General purpose math vector.
Definition: Vector.h:61
A reference wrapper.
Definition: Ref.h:39
void restart() override
Restart the activity.
Definition: Activities.h:707
ParallelActivityEx< Args... > parallelAll(Args... activities)
Create a gf::ParallelActivityEx.
Definition: Activities.h:811
Another unknown button (may happen with touchpads)
float getTarget() const noexcept
Get the target of the activity.
Definition: Activities.h:90
The activity is still running.
float getOrigin() const noexcept
Get the origin of the activity.
Definition: Activities.h:72
float getOrigin() const noexcept
Get the origin of the activity.
Definition: Activities.h:156
MoveToActivity moveTo(Vector2f origin, Vector2f target, Vector2f &position, Time duration, Easing easing=Ease::linear)
Create a gf::MoveToActivity.
Definition: Activities.h:554
A game activity.
Definition: Activity.h:62
ActivityStatus run(Time time) override
Run the activity.
Definition: Activities.h:831
RotateToActivity rotateTo(float origin, float target, float &angle, Time duration, Easing easing=Ease::linear)
Create a gf::RotateToActivity.
Definition: Activities.h:540
float getTarget() const noexcept
Get the target of the activity.
Definition: Activities.h:175
void setTarget(Vector2f target)
Change the target of the activity.
Definition: Activities.h:250
Color4f getOrigin() const noexcept
Get the origin of the activity.
Definition: Activities.h:322