diff --git a/.gitignore b/.gitignore index 87361b7..96365f9 100755 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ __pycache__/ *.sublime-project *.sublime-workspace .vscode + diff --git a/Pinball.g3a b/Pinball.g3a index d922ff0..b655e3d 100644 Binary files a/Pinball.g3a and b/Pinball.g3a differ diff --git a/TODO.txt b/TODO.txt index 5a830a0..93f6401 100644 --- a/TODO.txt +++ b/TODO.txt @@ -6,17 +6,25 @@ Add background pictures Add targets and enable bonus +[WIP] Add return locker to avoir the ball to enter back to the launch chanel + [DONE] Add multiple flippers all around the tables/boards Add the possibilty to have connected tables using a kind on tunnel -Add ball launcher with user control initial velocity +[WIP] Add ball launcher with user control initial velocity Add "Board Importation" system with "scanf" feature [DONE] Create a "Pinball" font -Create text effect like : +Create text effects like : - rolling texts +- scrolling effects +- appearance/disappearance effects +Check why 1 single ball make the game crash +Ultimately create a Table Designer to ease the creation of new tables. + +Add the possibility to import new tables with adhoc interface diff --git a/src/main.cpp b/src/main.cpp index 35a26bf..7ca4e73 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -65,13 +65,7 @@ libnum::num32 cScale; libnum::num32 simWidth; libnum::num32 simHeight; -/* return the scaled x component of a vector */ -uint16_t CX(Vector2D pos) { return (int)(pos.x * cScale) + 25; } -/* return the scaled y component of a vector */ -uint16_t CY(Vector2D pos) { - return (int)(libnum::num32(azrp_height) - pos.y * cScale); -} /* create the pinball board */ void SetupScene(int which_table) { @@ -170,87 +164,30 @@ static void update(float dt) { static void render(void) { + /* Clear Screen */ azrp_clear(RGB565_BLACK); if (MyPinball.sideimage != nullptr) azrp_image_p8(azrp_width - MyPinball.sideimage->width - 25, 5, MyPinball.sideimage, DIMAGE_NONE); - int mod = MyPinball.borders.size(); - for (int i = 0; i < mod; i++) - azrp_line(CX(MyPinball.borders[i]), CY(MyPinball.borders[i]), - CX(MyPinball.borders[(i + 1) % mod]), - CY(MyPinball.borders[(i + 1) % mod]), C_WHITE); + CollectionRender( MyPinball.borders, RGB565_WHITE ); - if (MyPinball.has_locker) { - int modZ = MyPinball.locker.size(); - for (int i = 0; i < modZ; i++) - azrp_line(CX(MyPinball.locker[i]), CY(MyPinball.locker[i]), - CX(MyPinball.locker[(i + 1) % modZ]), - CY(MyPinball.locker[(i + 1) % modZ]), - MyPinball.locker_is_enabled ? C_WHITE : RGB565_BLOODYRED); - // azrp_circle( CX(MyPinball.Locker_enabler[0].pos), - // CY(MyPinball.Locker_enabler[0].pos), - // (int)(MyPinball.Locker_enabler[0].radius * cScale), - // MyPinball.Locker_enabler[0].color); - } + if (MyPinball.has_locker) + CollectionRender( MyPinball.locker, MyPinball.locker_is_enabled ? RGB565_WHITE : RGB565_BLOODYRED); - for (int i = 0; i < MyPinball.obstacles.size(); i++) - azrp_filledcircle(CX(MyPinball.obstacles[i].pos), - CY(MyPinball.obstacles[i].pos), - (int)(MyPinball.obstacles[i].radius * cScale), - MyPinball.obstacles[i].color); - for (int i = 0; i < MyPinball.islands.size(); i++) { - int temp = MyPinball.islands[i].size(); - for (int j = 0; j < temp; j++) - azrp_line(CX(MyPinball.islands[i][j]), CY(MyPinball.islands[i][j]), - CX(MyPinball.islands[i][(j + 1) % temp]), - CY(MyPinball.islands[i][(j + 1) % temp]), C_WHITE); - } + for (int i = 0; i < MyPinball.obstacles.size(); i++) MyPinball.obstacles[i].Render(); - for (int i = 0; i < MyPinball.balls.size(); i++) - azrp_filledcircle(CX(MyPinball.balls[i].pos), CY(MyPinball.balls[i].pos), - (int)(MyPinball.balls[i].radius * cScale), - MyPinball.balls[i].color); - for (int i = 0; i < MyPinball.flippers.size(); i++) { - Vector2D start = MyPinball.flippers[i].pos; - Vector2D end = MyPinball.flippers[i].getTip(); + for (int i = 0; i < MyPinball.islands.size(); i++) + CollectionRender( MyPinball.islands[i] , RGB565_WHITE); - Vector2D SE; - SE.Set(end - start); - Vector2D Norm; - Norm.Set(SE.PerpCW()); - Norm.Normalise(); + for (int i = 0; i < MyPinball.balls.size(); i++) MyPinball.balls[i].Render(); - Vector2D A = start.Clone(); - A.Add(Norm, MyPinball.flippers[i].radius); - Vector2D B = end.Clone(); - B.Add(Norm, MyPinball.flippers[i].radius); - - Vector2D C = end.Clone(); - C.Add(Norm, -MyPinball.flippers[i].radius); - - Vector2D D = start.Clone(); - D.Add(Norm, -MyPinball.flippers[i].radius); - - int Xpoly[4] = {CX(A), CX(B), CX(C), CX(D)}; - int Ypoly[4] = {CY(A), CY(B), CY(C), CY(D)}; - - azrp_filledpoly(Xpoly, Ypoly, 4, MyPinball.flippers[i].color); - - azrp_filledcircle(CX(start), CY(start), - (int)(MyPinball.flippers[i].radius * cScale), - MyPinball.flippers[i].color); - azrp_filledcircle(CX(end), CY(end), - (int)(MyPinball.flippers[i].radius * cScale), - MyPinball.flippers[i].color); - azrp_line(CX(start), CY(start), CX(end), CY(end), - MyPinball.flippers[i].color); - } + for (int i = 0; i < MyPinball.flippers.size(); i++) MyPinball.flippers[i].Render(); // azrp_draw_text(150, 0, "FPS = %.0f - Mem Free = %d - Time = %.2 f" , // (float)(1.0f / elapsedTime), @@ -258,16 +195,6 @@ static void render(void) { azrp_draw_pinball(250, 200, RGB565_DEEPPURPLE, "Score:%d", MyPinball.score); - - /* - azrp_draw_text(150, 40, "Ball1 : " ); - azrp_draw_text(200, 40, "X = : %.2f", (float) MyPinball.balls[0].pos.x ); - azrp_draw_text(200, 50, "Y = : %.2f", (float) MyPinball.balls[0].pos.y ); - - azrp_draw_text(150, 70, "Ball2 : " ); - azrp_draw_text(200, 70, "X = : %.2f", (float) MyPinball.balls[1].pos.x ); - azrp_draw_text(200, 80, "Y = : %.2f", (float) MyPinball.balls[1].pos.y ); - */ } static void get_inputs(float dt) { diff --git a/src/pinball_entities.h b/src/pinball_entities.h index 331331b..47f802c 100644 --- a/src/pinball_entities.h +++ b/src/pinball_entities.h @@ -10,9 +10,10 @@ #include +#include +#include -enum -{ +enum { LEFT = 0, RIGHT = 1, }; @@ -31,6 +32,11 @@ public: ~Ball() {} + void Render() { + azrp_filledcircle(CX(this->pos), CY(this->pos), CR(this->radius), + this->color); + } + void Simulate(libnum::num32 dt, Vector2D gravity) { this->vel.Add(gravity, dt); this->pos.Add(this->vel, dt); @@ -41,10 +47,10 @@ public: uint16_t color; }; - class Obstacle { public: - Obstacle(libnum::num32 radius, Vector2D pos, libnum::num32 pushVel, uint16_t color, uint16_t points) { + Obstacle(libnum::num32 radius, Vector2D pos, libnum::num32 pushVel, + uint16_t color, uint16_t points) { this->radius = radius; this->pos = pos.Clone(); this->pushVel = pushVel; @@ -54,13 +60,17 @@ public: ~Obstacle() {} Obstacle() {} + void Render() { + azrp_filledcircle(CX(this->pos), CY(this->pos), CR(this->radius), + this->color); + } + libnum::num32 radius, pushVel; Vector2D pos; uint16_t color; uint16_t points; }; - class Target { public: Target(libnum::num32 radius, Vector2D pos, uint16_t color, uint16_t points) { @@ -72,18 +82,22 @@ public: ~Target() {} + void Render() { + azrp_circle(CX(this->pos), CY(this->pos), CR(this->radius), this->color); + } + libnum::num32 radius; Vector2D pos; uint16_t color; uint16_t points; }; - class Flipper { public: Flipper(libnum::num32 radius, Vector2D pos, libnum::num32 length, libnum::num32 restAngle, libnum::num32 maxRotation, - libnum::num32 angularVelocity, libnum::num32 restitution, uint8_t side, uint16_t color ) { + libnum::num32 angularVelocity, libnum::num32 restitution, + uint8_t side, uint16_t color) { this->radius = radius; this->pos = pos.Clone(); this->length = length; @@ -94,30 +108,63 @@ public: this->rotation = libnum::num32(0); this->currentAngularVelocity = libnum::num32(0); this->touchIdentifier = libnum::num32(-1); - this->side=side; - this->color=color; + this->side = side; + this->color = color; } void Simulate(libnum::num32 dt) { libnum::num32 prevRotation = this->rotation; bool pressed = this->touchIdentifier >= 0; if (pressed) - this->rotation = MIN(this->rotation + dt * this->angularVelocity, this->maxRotation); + this->rotation = + MIN(this->rotation + dt * this->angularVelocity, this->maxRotation); else - this->rotation = MAX(this->rotation - dt * this->angularVelocity, libnum::num(0.0) ); - this->currentAngularVelocity = this->sign * (this->rotation - prevRotation) / dt; + this->rotation = + MAX(this->rotation - dt * this->angularVelocity, libnum::num(0.0)); + this->currentAngularVelocity = + this->sign * (this->rotation - prevRotation) / dt; } - Vector2D getTip() - { + Vector2D getTip() { libnum::num32 angle = this->restAngle + this->sign * this->rotation; - Vector2D D( COS(angle) , SIN(angle) ); + Vector2D D(COS(angle), SIN(angle)); Vector2D tip = this->pos.Clone(); tip.Add(D, this->length); return tip; } + void Render() { + Vector2D start = this->pos; + Vector2D end = this->getTip(); + + Vector2D SE; + SE.Set(end - start); + Vector2D Norm; + Norm.Set(SE.PerpCW()); + Norm.Normalise(); + + Vector2D A = start.Clone(); + A.Add(Norm, this->radius); + + Vector2D B = end.Clone(); + B.Add(Norm, this->radius); + + Vector2D C = end.Clone(); + C.Add(Norm, -this->radius); + + Vector2D D = start.Clone(); + D.Add(Norm, -this->radius); + + int Xpoly[4] = {CX(A), CX(B), CX(C), CX(D)}; + int Ypoly[4] = {CY(A), CY(B), CY(C), CY(D)}; + + azrp_filledpoly(Xpoly, Ypoly, 4, this->color); + azrp_filledcircle(CX(start), CY(start), CR(this->radius), this->color); + azrp_filledcircle(CX(end), CY(end), CR(this->radius), this->color); + azrp_line(CX(start), CY(start), CX(end), CY(end), this->color); + } + libnum::num32 radius; Vector2D pos; libnum::num32 length; @@ -132,26 +179,34 @@ public: uint16_t color; }; +struct Scene { + Vector2D gravity; + libnum::num32 dt; + uint32_t score; + bool pause; + std::vector borders; + std::vector balls; + std::vector obstacles; + std::vector> islands; + std::vector flippers; + bopti_image_t *sideimage; - -struct Scene -{ - Vector2D gravity; - libnum::num32 dt; - uint32_t score; - bool pause; - std::vector borders; - std::vector balls; - std::vector obstacles; - std::vector< std::vector< Vector2D> > islands; - std::vector flippers; - bopti_image_t *sideimage; - - bool has_locker; - std::vector< Vector2D > locker; - bool locker_is_enabled; - std::vector< Target > Locker_enabler; + bool has_locker; + std::vector locker; + bool locker_is_enabled; + std::vector Locker_enabler; }; + +void CollectionRender( std::vector collection, uint16_t color ) +{ + int mod = collection.size(); + for (int i = 0; i < mod; i++) + azrp_line(CX(collection[i]), CY(collection[i]), + CX(collection[(i + 1) % mod]), + CY(collection[(i + 1) % mod]), color ); +} + + #endif \ No newline at end of file diff --git a/src/utilities.h b/src/utilities.h index 6d5ca22..22f1e0e 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -66,8 +66,23 @@ libnum::num32 SIN( libnum::num32 angle ) } +extern libnum::num32 flipperHeight; +extern libnum::num32 cScale; +extern libnum::num32 simWidth; +extern libnum::num32 simHeight; +/* return the scaled x component of a vector */ +uint16_t CX(Vector2D pos) { return (int)(pos.x * cScale) + 25; } +/* return the scaled y component of a vector */ +uint16_t CY(Vector2D pos) { + return (int)(libnum::num32(azrp_height) - pos.y * cScale); +} + +/* return the scaled disctance given in argument (typically for circles radii) */ +uint16_t CR(libnum::num distance ) { + return (int)(distance * cScale); +} #define MIN(a,b) ( ((a)>=(b)) ? (b) : (a) ) #define MAX(a,b) ( ((a)<=(b)) ? (b) : (a) )