Skip to content

Instantly share code, notes, and snippets.

@felipemanga
Last active January 19, 2021 20:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felipemanga/b852269f550f62dc34696f36bc2eb123 to your computer and use it in GitHub Desktop.
Save felipemanga/b852269f550f62dc34696f36bc2eb123 to your computer and use it in GitHub Desktop.
Entities
#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();
}
#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