Last active
January 19, 2021 20:18
-
-
Save felipemanga/b852269f550f62dc34696f36bc2eb123 to your computer and use it in GitHub Desktop.
Entities
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Pokitto.h> | |
#include <miloslav.h> | |
#include "Smile.h" | |
#include "Entity.h" | |
using PC=Pokitto::Core; | |
using PD=Pokitto::Display; | |
using PB=Pokitto::Buttons; | |
class EntityXYWH : public Entity { | |
public: | |
int x, y, w, h; | |
static bool checkCollision(const EntityXYWH &a, const EntityXYWH &b){ | |
return !( | |
(a.x + a.w < b.x) || | |
(a.x > b.x + b.w) || | |
(a.y + a.h < b.y) || | |
(a.y > b.y + b.h) | |
); | |
} | |
}; | |
class Boop : public EntityXYWH { | |
public: | |
bool flip; | |
Boop(){ | |
collisionId = 1; | |
collisionMask = 1; | |
x = 0; | |
y = 50; | |
w = Smile[0]; | |
h = Smile[1]; | |
} | |
void update() override { | |
flip = false; | |
if(PB::aBtn()) | |
x = (rand() % 20) * 10; | |
priority = x; | |
} | |
void draw() override { | |
Pokitto::Display::drawSprite(x, y, Smile, flip); | |
} | |
void hit(Entity &other) override { | |
flip = true; | |
} | |
}; | |
void init(){ | |
PD::loadRGBPalette(miloslav); | |
Entity::setCollisionCheck(EntityXYWH::checkCollision); | |
for(int i=0; i<5; ++i) | |
new Boop(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
class Entity { | |
protected: | |
unsigned char collisionMask = 0, collisionId = 0, priority = 0; | |
virtual void update(){} | |
virtual void hit(Entity &other){} | |
virtual void draw(){} | |
private: | |
unsigned char deletionFlag = 0; | |
#ifdef POKITTO | |
using short_ptr = unsigned short; | |
static short_ptr toShort(Entity *entity){ | |
return entity ? reinterpret_cast<std::uintptr_t>(entity) - 0x10000000 : 0; | |
} | |
static Entity *fromShort(short_ptr ptr){ | |
return ptr ? reinterpret_cast<Entity*>(0x10000000 + ptr) : 0; | |
} | |
#else | |
using short_ptr = Entity*; | |
static short_ptr toShort(Entity *entity){ | |
return entity; | |
} | |
static Entity *fromShort(short_ptr ptr){ | |
return ptr; | |
} | |
#endif | |
short_ptr previous, next; | |
static inline short_ptr first = short_ptr{}; | |
static void entityUpdate(){ | |
for(auto ptr = fromShort(first); ptr; ){ | |
auto next = fromShort(ptr->next); | |
if (ptr->deletionFlag) delete ptr; | |
else ptr->update(); | |
ptr = next; | |
} | |
for(auto ptr = fromShort(first); ptr; ptr = fromShort(ptr->next)) { | |
auto id = ptr->collisionId, mask = ptr->collisionMask; | |
if (!id && !mask) continue; | |
for(auto ptr2 = fromShort(first); ptr2; ptr2 = fromShort(ptr2->next)) { | |
if (ptr2 == ptr) continue; | |
bool p2check = ptr2->collisionMask & id; | |
bool p1check = ptr2->collisionId & mask; | |
if ((!p2check && !p1check) || !collision(*ptr, *ptr2)) | |
continue; | |
if (p2check) | |
ptr2->hit(*ptr); | |
if (p1check) | |
ptr->hit(*ptr2); | |
} | |
} | |
sort(); | |
for(auto ptr = fromShort(first); ptr; ) { | |
auto next = fromShort(ptr->next); | |
if (ptr->deletionFlag) delete ptr; | |
else ptr->draw(); | |
ptr = next; | |
} | |
} | |
static void entityInit(){ | |
static void (*nextHook)(bool) = nullptr; | |
if(nextHook) return; | |
nextHook = Pokitto::Core::updateHook; | |
Pokitto::Core::updateHook = | |
+[](bool isFrame){ | |
if (isFrame) Entity::entityUpdate(); | |
nextHook(isFrame); | |
}; | |
} | |
protected: | |
virtual ~Entity(){ | |
auto next = fromShort(this->next); | |
auto previous = fromShort(this->previous); | |
if(previous) previous->next = this->next; | |
else first = this->next; | |
if(next) next->previous = this->previous; | |
} | |
public: | |
Entity(){ | |
entityInit(); | |
next = first; | |
previous = short_ptr{}; | |
first = toShort(this); | |
} | |
virtual void destroy(){ | |
deletionFlag = 1; | |
collisionMask = 0; | |
} | |
static inline bool (*collision)(const Entity &, const Entity &) = +[](const Entity &a, const Entity &b){ return false; }; | |
template<typename Derived, typename std::enable_if<std::is_base_of<Entity, Derived>::value>::type* = nullptr> | |
static void setCollisionCheck(bool (*check)(const Derived&, const Derived&)){ | |
collision = reinterpret_cast<decltype(collision)>(check); | |
} | |
static inline bool (*compare)(const Entity &, const Entity &) = +[](const Entity &a, const Entity &b){ | |
return a.priority > b.priority; | |
}; | |
static inline void (*sort)() = +[](){ | |
if (!first) return; | |
for(auto ptr = fromShort(first); ptr->next;){ | |
auto next = fromShort(ptr->next); | |
auto check = next; | |
auto prev = fromShort(ptr->previous); | |
while(check && compare(*ptr, *check)){ | |
prev = check; | |
check = fromShort(check->next); | |
} | |
if(check != next){ | |
if(ptr->previous) fromShort(ptr->previous)->next = ptr->next; | |
else first = ptr->next; | |
next->previous = ptr->previous; | |
ptr->previous = toShort(prev); | |
prev->next = toShort(ptr); | |
if (check) check->previous = prev->next; | |
ptr->next = toShort(check); | |
} | |
ptr = next; | |
} | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment