Boss with satellite guns - Bullet Hell versions to test framerate
|
@ -64,6 +64,8 @@ set(ASSETS_cg
|
|||
assets-cg/Sprites/Bullets/bullet_blue.png
|
||||
assets-cg/Sprites/Bullets/bullet_laser.png
|
||||
assets-cg/Sprites/Bullets/bullet_enemy_blue.png
|
||||
assets-cg/Sprites/Bullets/bullet_enemy_red.png
|
||||
assets-cg/Sprites/Bullets/bullet_enemy_green.png
|
||||
|
||||
assets-cg/Sprites/Players/mainship1.png
|
||||
assets-cg/Sprites/Players/Satellite_Lvl1.png
|
||||
|
@ -74,7 +76,8 @@ set(ASSETS_cg
|
|||
assets-cg/Sprites/Enemies/Enemy_Red_Lvl1.png
|
||||
|
||||
assets-cg/Sprites/Boss/Boss1.png
|
||||
|
||||
assets-cg/Sprites/Boss/BossGun.png
|
||||
|
||||
assets-cg/Levels/tileset.png
|
||||
assets-cg/Levels/Level2.json
|
||||
# assets-cg/Levels/Tileset_Space.json
|
||||
|
|
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 118 B After Width: | Height: | Size: 131 B |
After Width: | Height: | Size: 136 B |
After Width: | Height: | Size: 137 B |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 13 KiB |
157
src/boss.cpp
|
@ -10,15 +10,23 @@
|
|||
|
||||
#include <gint/gint.h>
|
||||
#include "collections.h"
|
||||
#include "player.h"
|
||||
|
||||
#include "vector2D.h"
|
||||
|
||||
extern bopti_image_t img_Lifebar;
|
||||
extern bopti_image_t img_Boss1;
|
||||
extern bopti_image_t img_BossGun;
|
||||
|
||||
extern font_t milifont_prop;
|
||||
|
||||
|
||||
extern std::vector<Bullet*> MyEnemiesBullets;
|
||||
extern Player *MyPlayer;
|
||||
|
||||
#define NB_PIECES_BOSS 12
|
||||
#define NB_GUNS 12
|
||||
|
||||
libnum::num XdataBossInternal[NB_PIECES_BOSS];
|
||||
libnum::num YdataBossInternal[NB_PIECES_BOSS];
|
||||
libnum::num XdataBossExternal[NB_PIECES_BOSS];
|
||||
|
@ -26,6 +34,10 @@ libnum::num YdataBossExternal[NB_PIECES_BOSS];
|
|||
|
||||
BossPart Pieces[NB_PIECES_BOSS*2];
|
||||
|
||||
libnum::num xGuns[NB_GUNS];
|
||||
libnum::num yGuns[NB_GUNS];
|
||||
|
||||
BossGun Guns[NB_GUNS];
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -108,10 +120,9 @@ Boss::Boss( int16_t _x, int16_t _y, uint8_t _id )
|
|||
|
||||
lastshoot0 = rtc_ticks();
|
||||
lastshoot1 = rtc_ticks();
|
||||
lastshoot2 = rtc_ticks();
|
||||
|
||||
radiusInt = libnum::num( 75 );
|
||||
radiusExt = libnum::num( 100 );
|
||||
radiusInt = libnum::num( 80 );
|
||||
radiusExt = libnum::num( 90 );
|
||||
|
||||
rotAngle = 0.0f;
|
||||
rotSpeed = 2;
|
||||
|
@ -135,6 +146,11 @@ Boss::Boss( int16_t _x, int16_t _y, uint8_t _id )
|
|||
Pieces[i*2+1].color = 0x528a; //darker gray
|
||||
}
|
||||
|
||||
for( int i=0; i<NB_GUNS; i++ )
|
||||
{
|
||||
Guns[i].life = 100;
|
||||
Guns[i].toberemoved = false;
|
||||
}
|
||||
|
||||
/* FOR DEBUGGING */
|
||||
// gint_world_switch( GINT_CALL( savedata ) );
|
||||
|
@ -159,6 +175,7 @@ void Boss::Update( float dt )
|
|||
if (rotAngle>360.0f) rotAngle-=360.0f;
|
||||
|
||||
|
||||
/* Management of the shield part of the boss (rotating circles made of triangles)*/
|
||||
uint16_t angleint = (uint16_t) rotAngle;
|
||||
uint16_t angledelta = (uint16_t) (360/NB_PIECES_BOSS);
|
||||
|
||||
|
@ -182,6 +199,63 @@ void Boss::Update( float dt )
|
|||
if (angleint>=360) angleint -= 360;
|
||||
}
|
||||
|
||||
/* Management of the Guns part of the boss (rotating cannons made of sprites)*/
|
||||
|
||||
angledelta = (uint16_t) (360/NB_GUNS);
|
||||
angleint = (uint16_t) rotAngle + angledelta/2;
|
||||
if (angleint>=360) angleint -= 360;
|
||||
|
||||
for( int i=0; i<NB_GUNS; i++ )
|
||||
{
|
||||
xGuns[i] = this->x + (this->radiusInt + this->radiusExt) / 2 * FastCosInt( angleint );
|
||||
yGuns[i] = this->y + (this->radiusInt + this->radiusExt) / 2 * FastSinInt( angleint );
|
||||
angleint += angledelta;
|
||||
if (angleint>=360) angleint -= 360;
|
||||
}
|
||||
|
||||
|
||||
uint32_t tempshoot = rtc_ticks();
|
||||
|
||||
bool hasExternalGun = false;
|
||||
|
||||
if (Shoot_OK( tempshoot, BULLET_ENEMY_RED ))
|
||||
{
|
||||
/* shoot from the rotating cannons (aiming directly the position of the player )*/
|
||||
for( int i=0; i<NB_GUNS; i++ )
|
||||
{
|
||||
if (Guns[i].toberemoved==false)
|
||||
{
|
||||
Vector2D shootDirection( MyPlayer->x - xGuns[i], MyPlayer->y - yGuns[i] );
|
||||
shootDirection.Normalise();
|
||||
|
||||
Bullet *b = new Bullet( (int) xGuns[i] , (int) yGuns[i], (int) shootDirection.x, (int) shootDirection.y, BULLET_ENEMY_RED );
|
||||
MyEnemiesBullets.push_back( b );
|
||||
|
||||
hasExternalGun = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasExternalGun==false)
|
||||
if(Shoot_OK( tempshoot, BULLET_ENEMY_GREEN ))
|
||||
{
|
||||
/* central shoot from the main ship only if no more other gun shooting */
|
||||
|
||||
Bullet *b0 = new Bullet( xmin, (int) y, -3, 0, BULLET_ENEMY_GREEN );
|
||||
MyEnemiesBullets.push_back( b0 );
|
||||
|
||||
Bullet *b1 = new Bullet( xmin, (int) y, -2, -2, BULLET_ENEMY_BLUE );
|
||||
MyEnemiesBullets.push_back( b1 );
|
||||
|
||||
Bullet *b2 = new Bullet( xmin, (int) y, -2, 2, BULLET_ENEMY_BLUE );
|
||||
MyEnemiesBullets.push_back( b2 );
|
||||
|
||||
Bullet *b3 = new Bullet( xmin, (int) y, -3, -1, BULLET_ENEMY_GREEN );
|
||||
MyEnemiesBullets.push_back( b3 );
|
||||
|
||||
Bullet *b4 = new Bullet( xmin, (int) y, -3, 1, BULLET_ENEMY_GREEN );
|
||||
MyEnemiesBullets.push_back( b4 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -189,7 +263,7 @@ void Boss::Update( float dt )
|
|||
void Boss::Render( void )
|
||||
{
|
||||
|
||||
if (ID==0 && toberemoved==false)
|
||||
if (toberemoved==false)
|
||||
{
|
||||
for( int i=0; i<NB_PIECES_BOSS; i++ )
|
||||
{
|
||||
|
@ -224,17 +298,38 @@ void Boss::Render( void )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
for( int i=0; i<NB_GUNS; i++ )
|
||||
{
|
||||
if (Guns[i].toberemoved==false)
|
||||
{
|
||||
azrp_image_p8_effect( (int) xGuns[i] - img_BossGun.width/2,
|
||||
(int) yGuns[i] - img_BossGun.height/2,
|
||||
&img_BossGun, DIMAGE_NONE);
|
||||
|
||||
#if(DEBUG_MODE)
|
||||
dfont( &milifont_prop );;
|
||||
int X = (int) xGuns[i] - img_BossGun.width/2 + 15 ;
|
||||
int Y = (int) yGuns[i] - img_BossGun.height/2 +15;
|
||||
azrp_print( X, Y, C_WHITE, "%d", Guns[i].life );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
azrp_image_p8_effect(xmin, ymin, &img_Boss1, DIMAGE_NONE);
|
||||
|
||||
|
||||
if (life>life0*2/3) azrp_subimage_p8_effect((int) x - img_Lifebar.width/2, ymin - 9, &img_Lifebar, 0, 7, (img_Lifebar.width*life)/life0, 5, DIMAGE_NONE );
|
||||
else if (life>life0/3) azrp_subimage_p8_effect((int) x - img_Lifebar.width/2, ymin - 9, &img_Lifebar, 0, 12, (img_Lifebar.width*life)/life0, 5, DIMAGE_NONE );
|
||||
else azrp_subimage_p8_effect((int) x - img_Lifebar.width/2, ymin - 9, &img_Lifebar, 0, 17, (img_Lifebar.width*life)/life0, 5, DIMAGE_NONE );
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
bool Boss::Test_Impact( Bullet *projectile )
|
||||
{
|
||||
/* We check if the bullet collides with teh shield of the boss */
|
||||
for( int i=0; i< NB_PIECES_BOSS; i++ )
|
||||
{
|
||||
if (Pieces[i*2].toberemoved == false)
|
||||
|
@ -273,13 +368,65 @@ bool Boss::Test_Impact( Bullet *projectile )
|
|||
}
|
||||
}
|
||||
|
||||
/* We check if the bullet collides with the cannons of the boss */
|
||||
for( int i=0; i<NB_GUNS; i++ )
|
||||
{
|
||||
if (Guns[i].toberemoved==false)
|
||||
{
|
||||
if (projectile->x >= (int) xGuns[i] - img_BossGun.width/2 &&
|
||||
projectile->x <= (int) xGuns[i] + img_BossGun.width/2 &&
|
||||
projectile->y >= (int) yGuns[i] - img_BossGun.height/2 &&
|
||||
projectile->y <= (int) yGuns[i] + img_BossGun.height/2 )
|
||||
{
|
||||
Guns[i].life -= projectile->strength;
|
||||
if (Guns[i].life<0)
|
||||
{
|
||||
Guns[i].toberemoved = true;
|
||||
Create_Explosion( (int) projectile->x, (int) projectile->y );
|
||||
}
|
||||
projectile->toberemoved = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We check if the bullet collides with the main ship part of the boss */
|
||||
if (projectile->x >= xmin && projectile->x <= xmax && projectile->y >= ymin && projectile->y <= ymax )
|
||||
{
|
||||
life -= projectile->strength;
|
||||
if (life<0) this->toberemoved = true;
|
||||
if (life<0)
|
||||
{
|
||||
this->toberemoved = true;
|
||||
Create_Explosion( (int) projectile->x, (int) projectile->y );
|
||||
}
|
||||
projectile->toberemoved = true;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Boss::Shoot_OK( uint32_t tempshoot, uint8_t shootID )
|
||||
{
|
||||
if (shootID==BULLET_ENEMY_RED)
|
||||
{
|
||||
if(tempshoot-lastshoot0>10)
|
||||
{
|
||||
lastshoot0=tempshoot;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
else if (shootID==BULLET_ENEMY_GREEN)
|
||||
{
|
||||
if(tempshoot-lastshoot1>25)
|
||||
{
|
||||
lastshoot1=tempshoot;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
else return false;
|
||||
|
||||
}
|
22
src/boss.h
|
@ -10,7 +10,7 @@
|
|||
#include <num/num.h>
|
||||
#include <sys/types.h>
|
||||
#include "bullet.h"
|
||||
|
||||
#include "trajectory.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
|
@ -22,6 +22,12 @@ typedef struct
|
|||
} BossPart;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16_t life;
|
||||
bool toberemoved;
|
||||
} BossGun;
|
||||
|
||||
|
||||
class Boss
|
||||
{
|
||||
|
@ -40,15 +46,21 @@ class Boss
|
|||
uint8_t ID;
|
||||
int16_t life, life0;
|
||||
uint8_t speed; // speed of the boss
|
||||
uint32_t lastshoot0 = 0;
|
||||
uint32_t lastshoot1 = 0;
|
||||
uint32_t lastshoot2 = 0;
|
||||
uint32_t lastshoot = 0;
|
||||
uint8_t rotSpeed;
|
||||
bool toberemoved;
|
||||
|
||||
bool hasTrajectory = false;
|
||||
Trajectory *pathToFollow;
|
||||
|
||||
private:
|
||||
float rotAngle;
|
||||
libnum::num radiusInt, radiusExt;
|
||||
libnum::num radiusInt, radiusExt;
|
||||
|
||||
uint32_t lastshoot0 = 0;
|
||||
uint32_t lastshoot1 = 0;
|
||||
|
||||
bool Shoot_OK( uint32_t tempshoot, uint8_t shootID );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@ extern bopti_image_t img_bullet_normal;
|
|||
extern bopti_image_t img_bullet_blue;
|
||||
extern bopti_image_t img_bullet_laser;
|
||||
extern bopti_image_t img_bullet_enemy_blue;
|
||||
|
||||
extern bopti_image_t img_bullet_enemy_red;
|
||||
extern bopti_image_t img_bullet_enemy_green;
|
||||
|
||||
|
||||
Bullet::Bullet( uint16_t lx, uint16_t ly, int16_t dx, int16_t dy, uint8_t id )
|
||||
|
@ -44,6 +45,14 @@ Bullet::Bullet( uint16_t lx, uint16_t ly, int16_t dx, int16_t dy, uint8_t id )
|
|||
{
|
||||
strength = 2;
|
||||
}
|
||||
else if (ID==BULLET_ENEMY_RED)
|
||||
{
|
||||
strength = 3;
|
||||
}
|
||||
else if (ID==BULLET_ENEMY_GREEN)
|
||||
{
|
||||
strength = 5;
|
||||
}
|
||||
toberemoved = false;
|
||||
}
|
||||
|
||||
|
@ -87,5 +96,15 @@ void Bullet::Render( )
|
|||
azrp_image_p8( px-img_bullet_enemy_blue.width/2, py-img_bullet_enemy_blue.height/2, &img_bullet_enemy_blue, DIMAGE_NONE );
|
||||
return;
|
||||
}
|
||||
else if (ID==BULLET_ENEMY_RED)
|
||||
{
|
||||
azrp_image_p8( px-img_bullet_enemy_red.width/2, py-img_bullet_enemy_red.height/2, &img_bullet_enemy_red, DIMAGE_NONE );
|
||||
return;
|
||||
}
|
||||
else if (ID==BULLET_ENEMY_GREEN)
|
||||
{
|
||||
azrp_image_p8( px-img_bullet_enemy_green.width/2, py-img_bullet_enemy_green.height/2, &img_bullet_enemy_green, DIMAGE_NONE );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ enum
|
|||
BULLET_BLUE,
|
||||
BULLET_LASER,
|
||||
BULLET_ENEMY_BLUE,
|
||||
BULLET_ENEMY_RED,
|
||||
BULLET_ENEMY_GREEN,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
|
||||
|
||||
#define DEBUG_MODE 0
|
||||
#define USB 0
|
||||
#define MORE_RAM 0
|
||||
#define DEBUG_MODE 0
|
||||
#define USB 1
|
||||
#define MORE_RAM 1
|
||||
#define CALCEMU 0
|
||||
|
||||
|
||||
|
|
|
@ -107,7 +107,6 @@ void Enemy::Update( float dt )
|
|||
Bullet *b = new Bullet( xmin, (int) y, -1, 0, BULLET_ENEMY_BLUE );
|
||||
MyEnemiesBullets.push_back( b );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -484,7 +484,7 @@ int main(void)
|
|||
|
||||
azrp_starfield_init( 250 );
|
||||
|
||||
Create_Enemies( );
|
||||
//Create_Enemies( );
|
||||
|
||||
MyPlayer = new Player( azrp_width/4, azrp_height/2, 0);
|
||||
|
||||
|
@ -546,7 +546,7 @@ int main(void)
|
|||
|
||||
elapsedTime = ((float) (time_update+time_render));
|
||||
|
||||
#if(DEBUG_MODE)
|
||||
#if(DEBUG_MODE && USB)
|
||||
if (textoutput && usb_is_open())
|
||||
{
|
||||
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
#ifndef VECTOR2D_H
|
||||
#define VECTOR2D_H
|
||||
|
||||
#include <num/num.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define numPI 3.14159265
|
||||
|
||||
libnum::num32 sqrt_num32(libnum::num32 v) {
|
||||
uint32_t t, q, b, r;
|
||||
r = v.v;
|
||||
b = 0x40000000;
|
||||
q = 0;
|
||||
while (b > 0x40) {
|
||||
t = q + b;
|
||||
if (r >= t) {
|
||||
r -= t;
|
||||
q = t + b;
|
||||
}
|
||||
r <<= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
q >>= 8;
|
||||
libnum::num32 ret;
|
||||
ret.v = q;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TO DO : rework these functions for sine and cosine calculation */
|
||||
|
||||
libnum::num32 cos_num32(libnum::num32 angle) {
|
||||
// Taylor serie for cos(x) = 1 - x²/2! + x⁴/4! + x⁶/6! + x⁸/8! + ...
|
||||
|
||||
// Cosine function is even
|
||||
if (angle < libnum::num32(0))
|
||||
return cos_num32(-angle);
|
||||
|
||||
// Look for an angle in the range [0, 2*pi [
|
||||
libnum::num32 anglereduced = angle;
|
||||
while (anglereduced >= libnum::num32(2 * numPI))
|
||||
anglereduced -= libnum::num32(2 * numPI);
|
||||
|
||||
// Exploit the symetry for angle and angle+Pi to reduce the order of the
|
||||
// limited developpement
|
||||
if (anglereduced >= libnum::num(numPI))
|
||||
return -cos_num32(anglereduced - libnum::num(numPI));
|
||||
|
||||
libnum::num32 sum = libnum::num32(1);
|
||||
libnum::num32 angle2 = anglereduced * anglereduced;
|
||||
|
||||
// set first value of the Taylor serie : x⁰/0! = 1/1
|
||||
libnum::num32 numerator = libnum::num32(1);
|
||||
libnum::num32 denominator = libnum::num32(1);
|
||||
|
||||
for (int i = 2; i <= 8; i += 2) {
|
||||
numerator *= (-angle2);
|
||||
denominator *= libnum::num32(i - 1) * libnum::num32(i);
|
||||
sum += (numerator / denominator);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
libnum::num32 sin_num32(libnum::num32 angle) {
|
||||
// Taylor serie for cos(x) = x/1! - x³/3! + x⁵/5! - x⁷/7! + x⁹/9! + ...
|
||||
|
||||
// Sine function is odd
|
||||
if (angle < libnum::num32(0))
|
||||
return -sin_num32(-angle);
|
||||
|
||||
// Look for an angle in the range [0, 2*pi [
|
||||
libnum::num32 anglereduced = angle;
|
||||
while (anglereduced >= libnum::num32(2 * numPI))
|
||||
anglereduced -= libnum::num32(2 * numPI);
|
||||
|
||||
// Exploit the symetry for angle and angle+Pi to reduce the order of the
|
||||
// limited developpement
|
||||
if (anglereduced >= libnum::num(numPI))
|
||||
return -sin_num32(anglereduced - libnum::num(numPI));
|
||||
|
||||
libnum::num32 sum = anglereduced;
|
||||
libnum::num32 angle2 = anglereduced * anglereduced;
|
||||
|
||||
// set first value of the Taylor serie : x¹/1! = x/1
|
||||
libnum::num32 numerator = anglereduced;
|
||||
libnum::num32 denominator = libnum::num32(1);
|
||||
|
||||
for (int i = 2; i <= 8; i += 2) {
|
||||
numerator *= (-angle2);
|
||||
denominator *= libnum::num32(i) * libnum::num32(i + 1);
|
||||
sum += (numerator / denominator);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
class Vector2D {
|
||||
|
||||
public:
|
||||
Vector2D() {
|
||||
this->x = libnum::num32(0);
|
||||
this->y = libnum::num32(0);
|
||||
}
|
||||
|
||||
Vector2D(float x, float y) {
|
||||
this->x = libnum::num32(x);
|
||||
this->y = libnum::num32(y);
|
||||
}
|
||||
|
||||
Vector2D(libnum::num32 x, libnum::num32 y) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
Vector2D(const Vector2D &v) {
|
||||
this->x = v.x;
|
||||
this->y = v.y;
|
||||
}
|
||||
|
||||
~Vector2D() {}
|
||||
|
||||
void Set(Vector2D v) {
|
||||
this->x = v.x;
|
||||
this->y = v.y;
|
||||
}
|
||||
|
||||
void Normalise(void) {
|
||||
libnum::num32 len = this->Length();
|
||||
this->x /= len;
|
||||
this->y /= len;
|
||||
}
|
||||
|
||||
Vector2D Clone(void) {
|
||||
Vector2D NewVector(this->x, this->y);
|
||||
return NewVector;
|
||||
}
|
||||
|
||||
Vector2D MakeVector(Vector2D A, Vector2D B) {
|
||||
Vector2D NewVector(B.x - A.x, B.y - A.y);
|
||||
return NewVector;
|
||||
}
|
||||
|
||||
void AddVectors(Vector2D a, Vector2D b) {
|
||||
this->x = a.x + b.x;
|
||||
this->y = a.y + b.y;
|
||||
}
|
||||
|
||||
void Add(Vector2D v, libnum::num32 scale) {
|
||||
this->x += v.x * scale;
|
||||
this->y += v.y * scale;
|
||||
}
|
||||
|
||||
void SubtractVectors(Vector2D a, Vector2D b) {
|
||||
this->x = a.x - b.x;
|
||||
this->y = a.y - b.y;
|
||||
}
|
||||
|
||||
void Subtract(Vector2D v, libnum::num32 scale) {
|
||||
this->x -= v.x * scale;
|
||||
this->y -= v.y * scale;
|
||||
}
|
||||
|
||||
libnum::num32 Length(void) {
|
||||
return sqrt_num32(this->x * this->x + this->y * this->y);
|
||||
}
|
||||
|
||||
void Scale(libnum::num32 scale) {
|
||||
this->x *= scale;
|
||||
this->y *= scale;
|
||||
}
|
||||
|
||||
libnum::num32 Dot(Vector2D v) { return (this->x * v.x + this->y * v.y); }
|
||||
|
||||
libnum::num32 Det(Vector2D v) { return (this->x * v.y - this->y * v.x); }
|
||||
|
||||
Vector2D PerpCW(void) {
|
||||
Vector2D temp(-this->y, this->x);
|
||||
return temp;
|
||||
}
|
||||
|
||||
Vector2D PerpCCW(void) {
|
||||
Vector2D temp(this->y, -this->x);
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* overloading of most interesting operators */
|
||||
libnum::num32 operator[](uint8_t pos) { return pos == 0 ? x : y; }
|
||||
|
||||
Vector2D &operator=(const Vector2D &v) {
|
||||
this->x = v.x;
|
||||
this->y = v.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2D operator+(const Vector2D &v) const {
|
||||
return Vector2D(x + v.x, y + v.y);
|
||||
}
|
||||
|
||||
Vector2D operator-(const Vector2D &v) const {
|
||||
return Vector2D(x - v.x, y - v.y);
|
||||
}
|
||||
|
||||
Vector2D &operator+=(Vector2D const &other) {
|
||||
this->x += other.x;
|
||||
this->y += other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2D operator-() const { return (Vector2D(-x, -y)); }
|
||||
|
||||
Vector2D operator+() const { return *this; }
|
||||
|
||||
Vector2D &operator-=(Vector2D const &other) {
|
||||
this->x -= other.x;
|
||||
this->y -= other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2D &operator*=(libnum::num32 scale) {
|
||||
this->x *= scale;
|
||||
this->y *= scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2D &operator/=(libnum::num32 scale) {
|
||||
this->x /= scale;
|
||||
this->y /= scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend Vector2D operator*(libnum::num32 scale, Vector2D const &v) {
|
||||
Vector2D r;
|
||||
r.x = v.x * scale;
|
||||
r.y = v.y * scale;
|
||||
return r;
|
||||
}
|
||||
|
||||
friend Vector2D operator*(Vector2D const &v, libnum::num32 scale) {
|
||||
Vector2D r;
|
||||
r.x = v.x * scale;
|
||||
r.y = v.y * scale;
|
||||
return r;
|
||||
}
|
||||
|
||||
friend Vector2D operator/(Vector2D const &v, libnum::num32 scale) {
|
||||
Vector2D r;
|
||||
r.x = v.x / scale;
|
||||
r.y = v.y / scale;
|
||||
return r;
|
||||
}
|
||||
|
||||
libnum::num32 x;
|
||||
libnum::num32 y;
|
||||
};
|
||||
|
||||
|
||||
Vector2D ClosestPointOnSegment(Vector2D P, Vector2D A, Vector2D B) {
|
||||
Vector2D AB = B - A;
|
||||
|
||||
libnum::num32 t = AB.Dot(AB);
|
||||
|
||||
if (t == 0)
|
||||
return A;
|
||||
|
||||
libnum::num32 t2 = (P.Dot(AB) - A.Dot(AB)) / t;
|
||||
|
||||
if (t2 < libnum::num32(0))
|
||||
t2 = libnum::num32(0);
|
||||
if (t2 > libnum::num32(1))
|
||||
t2 = libnum::num32(1);
|
||||
|
||||
Vector2D C = A.Clone();
|
||||
C.Add(AB, t2);
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
#endif
|