Rushed version (with some stuff almost hardcoded :E) to drop in time at the CPC#30

This commit is contained in:
Sylvain PILLOT 2023-06-03 18:42:46 +02:00
parent cf2f762873
commit e71b75fb24
6 changed files with 223 additions and 200 deletions

Binary file not shown.

View File

@ -24,6 +24,7 @@
#include "extrakeyboard.h"
#include "pinball_entities.h"
#include "simulations.h"
#include "stdint-gcc.h"
#include "tables.h"
#include "utilities.h"
@ -46,6 +47,7 @@ uint8_t texttodraw = 1;
#define Y_RESOL (DHEIGHT / SCALE_PIXEL)
float elapsedTime = 0.0f;
float cumulatedTime = 0.0f;
uint32_t time_update = 0, time_render = 0;
prof_t perf_update, perf_render;
@ -74,169 +76,20 @@ uint16_t CY(Vector2D pos) {
/* create the pinball board */
void SetupScene(int which_table) {
if (which_table == 0) Setup_Table_0();
else if (which_table == 1) Setup_Table_1();
else if (which_table == 2) Setup_Table_2();
else if (which_table == 3) Setup_Table_3();
else if (which_table == 4) Setup_Table_4();
else Setup_Table_0();
}
if (which_table == 0)
Setup_Table_0();
else if (which_table == 1)
Setup_Table_1();
else if (which_table == 2)
Setup_Table_2();
else if (which_table == 3)
Setup_Table_3();
else if (which_table == 4)
Setup_Table_4();
else
Setup_Table_0();
void HandleBallBallCollision(Ball *ball1, Ball *ball2) {
libnum::num32 restitution = MIN(ball1->restitution, ball2->restitution);
Vector2D dir = ball2->pos - ball1->pos;
libnum::num32 d = dir.Length();
if (d == libnum::num32(0) || d > (ball1->radius + ball2->radius))
return;
dir.Normalise();
libnum::num32 corr = (ball1->radius + ball2->radius - d) / libnum::num32(2);
ball1->pos.Add(dir, -corr);
ball2->pos.Add(dir, corr);
libnum::num32 v1 = ball1->vel.Dot(dir);
libnum::num32 v2 = ball2->vel.Dot(dir);
libnum::num32 m1 = ball1->mass;
libnum::num32 m2 = ball2->mass;
libnum::num32 newV1 =
(m1 * v1 + m2 * v2 - m2 * (v1 - v2) * restitution / (m1 + m2));
libnum::num32 newV2 =
(m1 * v1 + m2 * v2 - m1 * (v2 - v1) * restitution / (m1 + m2));
ball1->vel.Add(dir, newV1 - v1);
ball2->vel.Add(dir, newV2 - v2);
}
void HandleBallObstacleCollision(Ball *ball, Obstacle obstacle) {
Vector2D dir = ball->pos - obstacle.pos;
libnum::num32 d = dir.Length();
if (d == libnum::num32(0) || d > (ball->radius + obstacle.radius))
return;
dir.Normalise();
libnum::num32 corr = ball->radius + obstacle.radius - d;
ball->pos.Add(dir, corr);
libnum::num32 v = ball->vel.Dot(dir);
ball->vel.Add(dir, obstacle.pushVel - v);
MyPinball.score += obstacle.points;
}
void HandleBallIslandCollision(Ball *ball, std::vector<Vector2D> island,
libnum::num32 rad) {
int mod = island.size();
for (int i = 0; i < mod; i++) {
Vector2D closest =
ClosestPointOnSegment(ball->pos, island[i], island[(i + 1) % mod]);
Vector2D dir;
dir.SubtractVectors(ball->pos, closest);
libnum::num32 d = dir.Length();
if (!(d == libnum::num32(0) || d > (ball->radius + rad))) {
dir.Normalise();
libnum::num32 corr = ball->radius + rad - d;
ball->pos.Add(dir, corr);
/* Update velocity */
Vector2D radius = closest.Clone();
radius.Add(dir, rad);
radius.Subtract(island[i], libnum::num32(1));
libnum::num32 v = ball->vel.Dot(dir);
libnum::num32 newV = ABS(v) * ball->restitution;
ball->vel.Add(dir, newV - v);
}
}
}
void HandleBallFlipperCollision(Ball *ball, Flipper flipper) {
Vector2D closest =
ClosestPointOnSegment(ball->pos, flipper.pos, flipper.getTip());
Vector2D dir;
dir.SubtractVectors(ball->pos, closest);
libnum::num32 d = dir.Length();
if (d == libnum::num32(0) || d > (ball->radius + flipper.radius))
return;
dir.Normalise();
libnum::num32 corr = ball->radius + flipper.radius - d;
ball->pos.Add(dir, corr);
/* Update velocity */
Vector2D radius = closest.Clone();
radius.Add(dir, flipper.radius);
radius.Subtract(flipper.pos, libnum::num32(1));
Vector2D surfaceVel = radius.PerpCW();
surfaceVel.Scale(flipper.currentAngularVelocity);
libnum::num32 v = ball->vel.Dot(dir);
libnum::num32 newV = surfaceVel.Dot(dir);
ball->vel.Add(dir, newV - v);
}
void HandleBallBorderCollision(Ball *ball, std::vector<Vector2D> border) {
int mod = border.size();
if (mod < 3)
return;
/* Find closest segment */
Vector2D d, closest, ab, normal;
libnum::num32 minDist = libnum::num32(0);
for (int i = 0; i < mod; i++) {
Vector2D a = border[i];
Vector2D b = border[(i + 1) % mod];
Vector2D c = ClosestPointOnSegment(ball->pos, a, b);
d.SubtractVectors(ball->pos, c);
libnum::num32 dist = d.Length();
if (i == 0 || dist < minDist) {
minDist = dist;
closest.Set(c);
ab.SubtractVectors(b, a);
normal = ab.PerpCW();
}
}
/* Push out */
d.SubtractVectors(ball->pos, closest);
libnum::num32 dist = d.Length();
if (dist == libnum::num32(0)) {
d.Set(normal);
dist = normal.Length();
}
d.Normalise();
if (d.Dot(normal) >= libnum::num32(0)) {
if (dist > ball->radius)
return;
ball->pos.Add(d, ball->radius - dist);
} else
ball->pos.Add(d, -(ball->radius + dist));
/* Update velocity */
libnum::num32 v = ball->vel.Dot(d);
libnum::num32 newV = ABS(v) * ball->restitution;
ball->vel.Add(d, newV - v);
cumulatedTime = 0.0f;
}
static void hook_prefrag(int id, void *fragment, int size) {
@ -273,6 +126,9 @@ static void hook_prefrag(int id, void *fragment, int size) {
static void update(float dt) {
MyPinball.dt = libnum::num32(dt);
if (cumulatedTime>1.0f)
MyPinball.locker_is_enabled = true;
for (int i = 0; i < MyPinball.flippers.size(); i++)
MyPinball.flippers[i].Simulate(MyPinball.dt);
@ -284,7 +140,8 @@ static void update(float dt) {
* balls) */
if (MyPinball.balls.size() >= 2) {
for (int j = 0; j < MyPinball.balls.size(); j++)
HandleBallBallCollision(&MyPinball.balls[i], &MyPinball.balls[j]);
if (i != j)
HandleBallBallCollision(&MyPinball.balls[i], &MyPinball.balls[j]);
}
/* Check for collision with bumpers (improve the score) */
@ -299,7 +156,8 @@ static void update(float dt) {
/* Check for collision with the pinball entry locker borders */
if (MyPinball.has_locker && MyPinball.locker_is_enabled)
HandleBallIslandCollision(&MyPinball.balls[i], MyPinball.locker, libnum::num(0.01));
HandleBallIslandCollision(&MyPinball.balls[i], MyPinball.locker,
libnum::num(0.01));
/* Check for collision with flippers */
for (int j = 0; j < MyPinball.flippers.size(); j++)
@ -310,10 +168,9 @@ static void update(float dt) {
}
}
static void render(void) {
azrp_clear(C_BLACK);
azrp_clear(RGB565_BLACK);
if (MyPinball.sideimage != nullptr)
azrp_image_p8(azrp_width - MyPinball.sideimage->width - 25, 5,
@ -325,17 +182,18 @@ static void render(void) {
CX(MyPinball.borders[(i + 1) % mod]),
CY(MyPinball.borders[(i + 1) % mod]), C_WHITE);
if (MyPinball.has_locker)
{
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 );
CY(MyPinball.locker[(i + 1) % modZ]),
MyPinball.locker_is_enabled ? C_WHITE : RGB565_BLOODYRED);
azrp_circle(CX(MyPinball.Locker_enabler.pos), CY(MyPinball.Locker_enabler.pos),
(int)(MyPinball.Locker_enabler.radius * cScale),
MyPinball.Locker_enabler.color);
// 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);
}
for (int i = 0; i < MyPinball.obstacles.size(); i++)
@ -394,11 +252,13 @@ static void render(void) {
MyPinball.flippers[i].color);
}
azrp_draw_text(150, 0, "FPS = %.0f - Mem Free = %d",
(float)(1.0f / elapsedTime),
_uram_stats->free_memory + extram_stats->free_memory);
// azrp_draw_text(150, 0, "FPS = %.0f - Mem Free = %d - Time = %.2 f" ,
// (float)(1.0f / elapsedTime),
// _uram_stats->free_memory + extram_stats->free_memory, cumulatedTime);
azrp_draw_pinball(250, 200, RGB565_DEEPPURPLE, "Score:%d", MyPinball.score);
azrp_draw_pinball(220, 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 );
@ -462,10 +322,10 @@ static void get_inputs(float dt) {
SetupScene(4);
}
if (MyKeyboard.IsKeyReleasedEvent(MYKEY_VARS) && MyPinball.has_locker)
{
MyPinball.locker_is_enabled = !MyPinball.locker_is_enabled;
}
// TODO : to be changed to remove cumulatedTime
if (MyKeyboard.IsKeyReleasedEvent(MYKEY_VARS) && MyPinball.has_locker && cumulatedTime<1.0f) {
MyPinball.locker_is_enabled = !MyPinball.locker_is_enabled;
}
#if (DEBUG_MODE)
if (MyKeyboard.IsKeyPressed(MYKEY_OPTN) &&
@ -563,7 +423,7 @@ int main(void) {
usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL};
usb_open(interfaces, GINT_CALL_NULL);
SetupScene(0);
SetupScene(4);
prof_init();
@ -604,6 +464,7 @@ int main(void) {
// elapsedTime = ((float)(time_update + time_render)) / 1000000.0f;
elapsedTime = ((float)1.0f / 60.0f);
cumulatedTime += elapsedTime;
} while (exitToOS == false);

View File

@ -70,15 +70,6 @@ public:
this->points = points;
}
void Set( Target t )
{
this->radius = t.radius;
this->pos = t.pos.Clone();
this->color = t.color;
this->points = t.points;
}
Target() {}
~Target() {}
libnum::num32 radius;
@ -157,9 +148,9 @@ struct Scene
bopti_image_t *sideimage;
bool has_locker;
std::vector<Vector2D> locker;
Target Locker_enabler;
std::vector< Vector2D > locker;
bool locker_is_enabled;
std::vector< Target > Locker_enabler;
};

170
src/simulations.h Normal file
View File

@ -0,0 +1,170 @@
#ifndef SIMULATIONS_H
#define SIMULATIONS_H
#include "vector2D.h"
#include <num/num.h>
#include "pinball_entities.h"
extern Scene MyPinball;
void HandleBallBallCollision(Ball *ball1, Ball *ball2) {
libnum::num32 restitution = MIN(ball1->restitution, ball2->restitution);
Vector2D dir = ball2->pos - ball1->pos;
libnum::num32 d = dir.Length();
if (d == libnum::num32(0) || d > (ball1->radius + ball2->radius))
return;
dir.Normalise();
libnum::num32 corr = (ball1->radius + ball2->radius - d) / libnum::num32(2);
ball1->pos.Add(dir, -corr);
ball2->pos.Add(dir, corr);
libnum::num32 v1 = ball1->vel.Dot(dir);
libnum::num32 v2 = ball2->vel.Dot(dir);
libnum::num32 m1 = ball1->mass;
libnum::num32 m2 = ball2->mass;
libnum::num32 newV1 =
(m1 * v1 + m2 * v2 - m2 * (v1 - v2) * restitution / (m1 + m2));
libnum::num32 newV2 =
(m1 * v1 + m2 * v2 - m1 * (v2 - v1) * restitution / (m1 + m2));
ball1->vel.Add(dir, newV1 - v1);
ball2->vel.Add(dir, newV2 - v2);
}
void HandleBallObstacleCollision(Ball *ball, Obstacle obstacle) {
Vector2D dir = ball->pos - obstacle.pos;
libnum::num32 d = dir.Length();
if (d == libnum::num32(0) || d > (ball->radius + obstacle.radius))
return;
dir.Normalise();
libnum::num32 corr = ball->radius + obstacle.radius - d;
ball->pos.Add(dir, corr);
libnum::num32 v = ball->vel.Dot(dir);
ball->vel.Add(dir, obstacle.pushVel - v);
MyPinball.score += obstacle.points;
}
void HandleBallIslandCollision(Ball *ball, std::vector<Vector2D> island,
libnum::num32 rad) {
int mod = island.size();
for (int i = 0; i < mod; i++) {
Vector2D closest =
ClosestPointOnSegment(ball->pos, island[i], island[(i + 1) % mod]);
Vector2D dir;
dir.SubtractVectors(ball->pos, closest);
libnum::num32 d = dir.Length();
if (!(d == libnum::num32(0) || d > (ball->radius + rad))) {
dir.Normalise();
libnum::num32 corr = ball->radius + rad - d;
ball->pos.Add(dir, corr);
/* Update velocity */
Vector2D radius = closest.Clone();
radius.Add(dir, rad);
radius.Subtract(island[i], libnum::num32(1));
libnum::num32 v = ball->vel.Dot(dir);
libnum::num32 newV = ABS(v) * ball->restitution;
ball->vel.Add(dir, newV - v);
}
}
}
void HandleBallFlipperCollision(Ball *ball, Flipper flipper) {
Vector2D closest =
ClosestPointOnSegment(ball->pos, flipper.pos, flipper.getTip());
Vector2D dir;
dir.SubtractVectors(ball->pos, closest);
libnum::num32 d = dir.Length();
if (d == libnum::num32(0) || d > (ball->radius + flipper.radius))
return;
dir.Normalise();
libnum::num32 corr = ball->radius + flipper.radius - d;
ball->pos.Add(dir, corr);
/* Update velocity */
Vector2D radius = closest.Clone();
radius.Add(dir, flipper.radius);
radius.Subtract(flipper.pos, libnum::num32(1));
Vector2D surfaceVel = radius.PerpCW();
surfaceVel.Scale(flipper.currentAngularVelocity);
libnum::num32 v = ball->vel.Dot(dir);
libnum::num32 newV = surfaceVel.Dot(dir);
ball->vel.Add(dir, newV - v);
}
void HandleBallBorderCollision(Ball *ball, std::vector<Vector2D> border) {
int mod = border.size();
if (mod < 3)
return;
/* Find closest segment */
Vector2D d, closest, ab, normal;
libnum::num32 minDist = libnum::num32(0);
for (int i = 0; i < mod; i++) {
Vector2D a = border[i];
Vector2D b = border[(i + 1) % mod];
Vector2D c = ClosestPointOnSegment(ball->pos, a, b);
d.SubtractVectors(ball->pos, c);
libnum::num32 dist = d.Length();
if (i == 0 || dist < minDist) {
minDist = dist;
closest.Set(c);
ab.SubtractVectors(b, a);
normal = ab.PerpCW();
}
}
/* Push out */
d.SubtractVectors(ball->pos, closest);
libnum::num32 dist = d.Length();
if (dist == libnum::num32(0)) {
d.Set(normal);
dist = normal.Length();
}
d.Normalise();
if (d.Dot(normal) >= libnum::num32(0)) {
if (dist > ball->radius)
return;
ball->pos.Add(d, ball->radius - dist);
} else
ball->pos.Add(d, -(ball->radius + dist));
/* Update velocity */
libnum::num32 v = ball->vel.Dot(d);
libnum::num32 newV = ABS(v) * ball->restitution;
ball->vel.Add(d, newV - v);
}
#endif

View File

@ -16,7 +16,6 @@ extern libnum::num32 simHeight;
extern bopti_image_t img_abyss;
void Setup_Table_0(void) {
libnum::num32 offset = libnum::num32(0.02);
@ -405,22 +404,21 @@ void Setup_Table_4(void) {
MyPinball.locker.push_back( Vector2D(libnum::num32(0.98), libnum::num32(1.20)));
MyPinball.locker.push_back( Vector2D(libnum::num32(0.96), libnum::num32(1.34)));
MyPinball.locker_is_enabled = false;
// Target MyTarget( 0.06, Vector2D(libnum::num32(0.90), libnum::num32(1.40)), RGB565_APPLEGREEN, 0);
// MyPinball.Locker_enabler.Set( MyTarget );
// MyPinball.Locker_enabler.push_back( Target( libnum::num32(0.06), Vector2D(libnum::num32(0.83), libnum::num32(1.39)), RGB565_APPLEGREEN, 0 ) );
MyPinball.balls.clear();
libnum::num32 ball_radius = libnum::num32(0.03);
libnum::num32 ball_mass = libnum::num32(PI) * ball_radius * ball_radius;
// Vector2D ball_pos1(libnum::num32(0.70), libnum::num32(0.70));
// Vector2D ball_vel1(libnum::num32(0.2), libnum::num32(3.5));
Vector2D ball_pos1(libnum::num32(1.075), libnum::num32(0.15));
Vector2D ball_vel1(libnum::num32(0.0), libnum::num32(3.5));
MyPinball.balls.push_back( Ball(ball_radius, ball_mass, ball_pos1, ball_vel1, 0.2, RGB565_LEMONYELLOW));
Vector2D ball_pos2(libnum::num32(0.30), libnum::num32(0.70));
Vector2D ball_vel2(libnum::num32(-0.2), libnum::num32(3.5));
Vector2D ball_pos2(libnum::num32(1.075), libnum::num32(0.45));
Vector2D ball_vel2(libnum::num32(0.0), libnum::num32(3.5));
MyPinball.balls.push_back( Ball(ball_radius, ball_mass, ball_pos2, ball_vel2, 0.2, RGB565_LEMONYELLOW ));

View File

@ -66,6 +66,9 @@ libnum::num32 SIN( libnum::num32 angle )
}
#define MIN(a,b) ( ((a)>=(b)) ? (b) : (a) )
#define MAX(a,b) ( ((a)<=(b)) ? (b) : (a) )
#define ABS(a) ( ((a)>=0) ? (a) : -(a) )