Compare commits

...

3 Commits

73 changed files with 1629 additions and 808 deletions

View File

@ -28,25 +28,31 @@ add_custom_command(
set(SOURCES
src/main.cpp
src/fast_trig.cpp
src/extrakeyboard.cpp
src/collections.cpp
src/impact.cpp
src/player.cpp
src/utilities.cpp
src/particles.cpp
src/bullet.cpp
src/enemy.cpp
src/starfieldshader.cpp
src/background.cpp
src/bonus.cpp
src/boss.cpp
src/point2D.cpp
src/trajectory.cpp
src/utilities/fast_trig.cpp
src/utilities/extrakeyboard.cpp
src/utilities/utilities.cpp
src/utilities/vector2D.cpp
src/shaders/circle.cpp
src/shaders/poly.cpp
src/shaders/filledcircle.cpp
src/shaders/filledpoly.cpp
src/shaders/line.cpp
src/shaders/starfieldshader.cpp
src/shmup/collections.cpp
src/shmup/impact.cpp
src/shmup/player.cpp
src/shmup/particles.cpp
src/shmup/bullet.cpp
src/shmup/enemy.cpp
src/shmup/background.cpp
src/shmup/bonus.cpp
src/shmup/boss.cpp
src/shmup/trajectory.cpp
# ...
)
set(ASSETS_cg
@ -69,6 +75,15 @@ set(ASSETS_cg
assets-cg/Sprites/Players/mainship1.png
assets-cg/Sprites/Players/Satellite_Lvl1.png
assets-cg/Sprites/Players/player_ship1.png
assets-cg/Sprites/Players/player_ship2.png
assets-cg/Sprites/Players/player_ship3.png
assets-cg/Sprites/Players/player_ship4.png
assets-cg/Sprites/Players/player_ship5.png
assets-cg/Sprites/Players/player_ship6.png
assets-cg/Sprites/Players/player_ship7.png
assets-cg/Sprites/Players/player_ship8.png
assets-cg/Sprites/Enemies/Lifebar.png
assets-cg/Sprites/Enemies/mainship2.png
@ -79,8 +94,9 @@ set(ASSETS_cg
assets-cg/Sprites/Boss/BossGun.png
assets-cg/Levels/tileset.png
assets-cg/Levels/Level1.json
assets-cg/Levels/Level2.json
# assets-cg/Levels/Tileset_Space.json
# assets-cg/Levels/Tileset_Space.json
# ...
)

View File

@ -4,6 +4,7 @@
## Engine
- [DONE] better keyboard management engine for keypressed() and keyreleased() events
- Mettre une système d'ajustement de FPS mini avec switch des niveaux d'overclock à la volée de manière dynamique
- [DONE] Mettre en place un système de collision en "pixel perfect" pour mode jeu "Asteroids Alert !!!"
## Partie décors :
@ -11,6 +12,7 @@
- animer des éléments du décors (clignotements, sprites animés, ...)
- interaction avec le décors (collisions possibles avec certaines tiles) qui imposent donc de suivre un "chemin" dans le niveau
- [DONE] multiple layers de tiles pour avoir des niveaux plus beaux
- implémenter des vitesses de défilement variables pour les décors de fond.
## Partie mouvement :
@ -26,8 +28,9 @@
- implémenter les collisions de bullets avec les satellites pour que ceux-ci perdent de la vie aussi
- implémenter le tir des satellites
- [DONE] implémenter un système de bonus (points, upgrade tir/satellites/... )
- implémenter un système d'amélioration de compétence de tirs (bullet -> mega bullet -> laser -> )
- implémenter un système d'amélioration de compétence de tirs (bullet -> mega bullet -> laser -> mega laser -> bomb -> etc.)
- implémenter un système d'animation du vaisseau (réacteurs par exemple)
- implémenter un système de boost des munitions si on garde le doigt appuyé sur la touche de laser
## Scenario
@ -57,6 +60,8 @@
o boss 3 : "Gun Crab"
o boss 4 : "Demoniac Snake"
o boss 5 : "Space Octopus"
o ...
o boss of the boss "Zgrog Master"
- création de séquences avec les boss (différentes phases)
- créations de différentes armes
- [DONE - CAN BE IMPROVED] créations de différents bonus
@ -83,10 +88,14 @@
## Histoire (à peaufiner)
En tant de Space Marshall, votre rôle est de faire respecter
la loi intergalactique et de punir les contrevenants.
Votre périmètre se situe dans le Grand Amas de RUZA-25f/s
la loi intergalactique et de punir les contrevenants afin d'assurer
la paix et le bon vivre ensemble des différentes civilisations aliens
vivant dans votre zone de l'espace à surveiller.
Votre périmètre englobe le Grand Amas de RUZA-25f/s dans ons entièreté
et armé de votre vaisseau, vous devez aider les civilisations
locales en pourchassant et anéantissant les hordes de Zgrog.
Cette race alien robotique a pour but de coloniser les planètes
et les stations orbitales géantes pour faire disparaître tout
vie organique.
Cette race alien robotique s'est donné pour but de coloniser les planètes
et les stations orbitales géantes afin d'y faire disparaître toute
vie organique.
C'est donc un combat sans relâche que de traquer et de détruire cet
envahisseur dénué d'âme.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,112 +0,0 @@
{ "frames": {
"asteroide1_12frames 0.ase": {
"frame": { "x": 0, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 1.ase": {
"frame": { "x": 32, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 2.ase": {
"frame": { "x": 64, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 3.ase": {
"frame": { "x": 96, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 4.ase": {
"frame": { "x": 128, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 5.ase": {
"frame": { "x": 160, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 6.ase": {
"frame": { "x": 192, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 7.ase": {
"frame": { "x": 224, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 8.ase": {
"frame": { "x": 256, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 9.ase": {
"frame": { "x": 288, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 10.ase": {
"frame": { "x": 320, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
},
"asteroide1_12frames 11.ase": {
"frame": { "x": 352, "y": 0, "w": 32, "h": 32 },
"rotated": false,
"trimmed": false,
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
"sourceSize": { "w": 32, "h": 32 },
"duration": 100
}
},
"meta": {
"app": "https://github.com/LibreSprite/LibreSprite/",
"version": "1.0",
"image": "/home/sylvain/Programmes/Casio/shmup/assets-cg/Sprites/Rocks/asteroide1_12frames.png",
"format": "RGBA8888",
"size": { "w": 384, "h": 32 },
"scale": "1",
"frameTags": [
],
"layers": [
{ "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,16 +0,0 @@
#ifndef MYAZURSHADERS_H
#define MYAZURSHADERS_H
#include <vector>
#define SHOW_PIXELS 1
#define SHOW_STARS 2
void azrp_starfield( void );
void azrp_starfield_init( uint8_t nbstars );
void azrp_starfield_close( void );
void azrp_tilesmap( int shifttile, int *tilemap, bopti_image_t *image, int tileset_size );
#endif //MYAZURSHADERS_H

View File

@ -1,94 +0,0 @@
#include "fast_trig.h"
#include "num/num.h"
static libnum::num cosTable[360];
static libnum::num sinTable[360];
static bool is_fast_trig_initialised = false;
void Fast_Trig_Init( void )
{
for(int u=0; u<360; u++)
{
cosTable[u] = libnum::num( cos( u * PI / 180 ) );
sinTable[u] = libnum::num( sin( u * PI / 180 ) );
}
is_fast_trig_initialised = true;
}
libnum::num FastCosInt( int16_t angle )
{
if (!is_fast_trig_initialised) Fast_Trig_Init();
if (angle>=0 and angle<360) return cosTable[ angle ];
else
{
int16_t input = angle;
if (input<0)
{
while (input<0) input+=360;
return cosTable[ input ];
}
else
{
while (input>=360) input-=360;
return cosTable[ input ];
}
}
}
libnum::num FastSinInt( int16_t angle )
{
if (!is_fast_trig_initialised) Fast_Trig_Init();
if (angle>=0 and angle<360) return sinTable[ angle ];
else
{
int16_t input = angle;
if (input<0)
{
while (input<0) input+=360;
return sinTable[ input ];
}
else
{
while (input>=360) input-=360;
return sinTable[ input ];
}
}
}
libnum::num FastTanInt( int16_t angle )
{
if (!is_fast_trig_initialised) Fast_Trig_Init();
int16_t input = angle;
if (input<0)
{
while (input<0) input+=360;
}
else if (input>=360)
{
while (input>=360) input-=360;
}
libnum::num value;
if (input==90)
{
value.v = INT32_MAX;
return value;
}
else if (input==270)
{
value.v = INT32_MIN;
return value;
}
else
{
value = FastSinInt(input) / FastCosInt(input);
return value;
}
}

View File

@ -26,23 +26,24 @@
#include <num/num.h>
#include "fast_trig.h"
#include "extrakeyboard.h"
#include "utilities/fast_trig.h"
#include "utilities/extrakeyboard.h"
#include "utilities/utilities.h"
#include "collections.h"
#include "shmup/collections.h"
#include "MyAzurShaders.h"
#include "shaders/MyAzurShaders.h"
#include "player.h"
#include "utilities.h"
#include "particles.h"
#include "bullet.h"
#include "enemy.h"
#include "bonus.h"
#include "impact.h"
#include "background.h"
#include "boss.h"
#include "trajectory.h"
#include "shmup/player.h"
#include "shmup/particles.h"
#include "shmup/bullet.h"
#include "shmup/enemy.h"
#include "shmup/bonus.h"
#include "shmup/impact.h"
#include "shmup/background.h"
#include "shmup/boss.h"
#include "shmup/trajectory.h"
#include <vector>
#include <algorithm>
@ -83,6 +84,7 @@ std::vector<Bullet*> MyEnemiesBullets;
std::vector<Enemy*> MyEnemies;
std::vector<Impact*> MyImpacts;
std::vector<Bonus*> MyBonuses;
std::vector<Trajectory*> MyTrajectories;
Background MyBackground;
@ -350,6 +352,11 @@ static void get_inputs( float dt )
if(MyKeyboard.IsKeyPressed(MYKEY_SHIFT) && MyKeyboard.IsKeyPressedEvent(MYKEY_F2)) {texttodraw=1;}
if(MyKeyboard.IsKeyPressed(MYKEY_SHIFT) && MyKeyboard.IsKeyPressedEvent(MYKEY_F3)) {texttodraw=2;}
if(MyKeyboard.IsKeyPressed(MYKEY_SHIFT) && MyKeyboard.IsKeyPressedEvent(MYKEY_F4)) {texttodraw=3;}
if(MyKeyboard.IsKeyPressed(MYKEY_SHIFT) && MyKeyboard.IsKeyPressedEvent(MYKEY_F5))
{
drawback = !drawback;
drawstars = ! drawstars;
}
if(MyKeyboard.IsKeyPressed(MYKEY_SHIFT) && MyKeyboard.IsKeyPressedEvent(MYKEY_F6))
{
azrp_starfield_close( );
@ -474,20 +481,18 @@ int main(void)
__printf_enable_fixed();
azrp_config_scale(SCALE_PIXEL);
//azrp_shader_clear_configure();
//azrp_shader_image_rgb16_configure();
//azrp_shader_image_p8_configure();
//azrp_shader_image_p4_configure();
#if(USB)
azrp_hook_set_prefrag(hook_prefrag);
#endif
azrp_starfield_init( 250 );
//Create_Enemies( );
Create_Enemies( );
MyPlayer = new Player( azrp_width/4, azrp_height/2, 0);
/*
MyBoss = new Boss( 3*azrp_width/4, azrp_height/2, 0);
@ -510,7 +515,7 @@ int main(void)
MyBoss->hasTrajectory = true;
MyBoss->pathToFollow = MyTrajectory;
*/
/*
#if(DBGCRSH)

View File

@ -1,21 +0,0 @@
#include "point2D.h"
Point2D::Point2D( )
{
x = libnum::num( 0 );
y = libnum::num( 0 );
}
Point2D::Point2D( int16_t _x, int16_t _y )
{
x = libnum::num( _x );
y = libnum::num( _y );
}
Point2D::~Point2D( )
{
}

View File

@ -1,19 +0,0 @@
#ifndef POINT2D_H
#define POINT2D_H
#include <cstdint>
#include <stdlib.h>
#include <num/num.h>
class Point2D
{
public:
libnum::num x, y;
Point2D( );
Point2D( int16_t _x, int16_t _y );
~Point2D( );
};
#endif

View File

@ -0,0 +1,39 @@
#ifndef MYAZURSHADERS_H
#define MYAZURSHADERS_H
#include <vector>
#define SHOW_PIXELS 1
#define SHOW_STARS 2
void azrp_starfield( void );
void azrp_starfield_init( uint8_t nbstars );
void azrp_starfield_close( void );
void azrp_shader_line_configure(void);
void azrp_shader_circle_configure(void);
void azrp_shader_filledcircle_configure(void);
void azrp_shader_filledpoly_configure(void);
void azrp_shader_poly_configure(void);
/* azrp_line(): Draw a line with clipping to the screen resolution between point (x1,y1) and (x2,y2) */
void azrp_line( int x1, int y1, int x2, int y2, uint16_t color );
/* azrp_circle() : Draw a circle with clipping to the screen resolution with a center (xc,yc) and a radius rad */
void azrp_circle( int xc, int yx, uint16_t rad, uint16_t color );
/* azrp_filledcircle() : Draw a filled circle with clipping to the screen resolution with a center (xc,yc) and a radius rad */
void azrp_filledcircle( int xc, int yx, uint16_t rad, uint16_t color );
/* azrp_poly() : Draw a polygon with clipping*/
void azrp_poly(int *x, int *y, int nb_vertices, uint16_t color);
/* azrp_filledpoly() : Draw a filled polygon with clipping*/
void azrp_filledpoly(int *x, int *y, int nb_vertices, uint16_t color);
#endif //MYAZURSHADERS_H

147
src/shaders/circle.cpp Normal file
View File

@ -0,0 +1,147 @@
#include <azur/gint/render.h>
uint8_t AZRP_SHADER_CIRCLE = -1;
static void azrp_shader_circle_configure(void)
{
azrp_set_uniforms(AZRP_SHADER_CIRCLE, (void *)azrp_width);
}
__attribute__((constructor))
static void register_shader(void)
{
extern azrp_shader_t azrp_shader_circle;
AZRP_SHADER_CIRCLE = azrp_register_shader(azrp_shader_circle, azrp_shader_circle_configure);
}
static int min(int x, int y)
{
return (x < y) ? x : y;
}
static int max(int x, int y)
{
return (x > y) ? x : y;
}
//---
#define TABLE_WIDTH 256
struct command {
uint8_t shader_id;
uint16_t color;
uint8_t curr_frag;
uint16_t NbPixels[14]; // Nunmber of pixels in each fragment
uint16_t DataPixelsX[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width
uint16_t DataPixelsY[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width
};
void AddPixelCircle( int16_t xp, int16_t yp, struct command *cmd )
{
if (xp >= 0 && xp < azrp_width && yp >= 0 && yp < azrp_height)
{
uint8_t cfrag = yp / azrp_frag_height;
uint16_t nbpixinfrag = cmd->NbPixels[ cfrag ];
uint16_t index = cfrag * TABLE_WIDTH + nbpixinfrag;
cmd->DataPixelsX[ index ] = xp;
cmd->DataPixelsY[ index ] = yp & 15;
cmd->NbPixels[ cfrag ]++;
}
}
void azrp_circle(int xc, int yc, uint16_t rad, uint16_t color)
{
prof_enter(azrp_perf_cmdgen);
int xmin = xc - rad;
int xmax = xc + rad;
int ymin = yc - rad;
int ymax = yc + rad;
// The circle is fully outside the screen
if ((xmax < 0) || (xmin >= azrp_width) || (ymax < 0) || (ymin >= azrp_height))
{
prof_leave(azrp_perf_cmdgen);
return;
}
int ytop = max( ymin, 0 );
int ybot = min( ymax, azrp_height-1 );
int frag_first = ytop / azrp_frag_height;
int frag_last = ybot / azrp_frag_height;
int frag_count = frag_last - frag_first + 1;
struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count);
if(!cmd) {
prof_leave(azrp_perf_cmdgen);
return;
}
cmd->shader_id = AZRP_SHADER_CIRCLE;
cmd->color = color;
cmd->curr_frag = frag_first;
// reset the point counters in each cell of the table
for( int i = 0; i < 14; i++ )
cmd->NbPixels[i]=0;
int x = 0;
int y = rad;
int m = 5 - 4*rad;
while (x <= y)
{
AddPixelCircle( xc+x, yc+y, cmd );
AddPixelCircle( xc+y, yc+x, cmd );
AddPixelCircle( xc-x, yc+y, cmd );
AddPixelCircle( xc-y, yc+x, cmd );
AddPixelCircle( xc+x, yc-y, cmd );
AddPixelCircle( xc+y, yc-x, cmd );
AddPixelCircle( xc-x, yc-y, cmd );
AddPixelCircle( xc-y, yc-x, cmd );
if (m > 0)
{
y--;
m -= 8*y;
}
x++;
m += 8*x + 4;
}
prof_leave(azrp_perf_cmdgen);
}
void azrp_shader_circle( void *uniforms, void *comnd, void *fragment )
{
struct command *cmd = (struct command *) comnd;
uint16_t *frag = (uint16_t *) fragment;
uint16_t *taille = (uint16_t *) cmd->NbPixels;
uint16_t *DX = (uint16_t *) cmd->DataPixelsX;
uint16_t *DY = (uint16_t *) cmd->DataPixelsY;
uint16_t nbpix = taille[ cmd->curr_frag ];
int BaseAdress = cmd->curr_frag * TABLE_WIDTH;
for( int i = 0; i < nbpix; i++ )
{
uint16_t X = DX[ BaseAdress + i ];
uint16_t Y = DY[ BaseAdress + i ];
frag[ azrp_width * Y + X ] = cmd->color;
}
cmd->curr_frag++;
}

View File

@ -0,0 +1,124 @@
#include <azur/gint/render.h>
uint8_t AZRP_SHADER_FILLEDCIRCLE = -1;
static void azrp_shader_filledcircle_configure(void) {
azrp_set_uniforms(AZRP_SHADER_FILLEDCIRCLE, (void *)azrp_width);
}
__attribute__((constructor)) static void register_shader(void) {
extern azrp_shader_t azrp_shader_filledcircle;
AZRP_SHADER_FILLEDCIRCLE = azrp_register_shader(azrp_shader_filledcircle, azrp_shader_filledcircle_configure);
}
static int min(int x, int y) { return (x < y) ? x : y; }
static int max(int x, int y) { return (x > y) ? x : y; }
//---
#define TABLE_WIDTH
struct command {
uint8_t shader_id;
uint16_t color;
uint8_t curr_frag;
int16_t DataFilling[2 * 224]; // Each line of the screen can have a xmin and
// a xmax value
};
void AddPixelFilledCircle(int16_t xpmin, int16_t xpmax, int16_t yp,
struct command *cmd) {
if (yp >= 0 && yp < azrp_height) {
if (xpmin >= 0)
cmd->DataFilling[2 * yp] = xpmin;
else
cmd->DataFilling[2 * yp] = 0;
if (xpmax < azrp_width)
cmd->DataFilling[2 * yp + 1] = xpmax;
else
cmd->DataFilling[2 * yp + 1] = azrp_width - 1;
}
}
void azrp_filledcircle(int xc, int yc, uint16_t rad, uint16_t color) {
prof_enter(azrp_perf_cmdgen);
int xmin = xc - rad;
int xmax = xc + rad;
int ymin = yc - rad;
int ymax = yc + rad;
// The circle is fully outside the screen
if ((xmax < 0) || (xmin >= azrp_width) || (ymax < 0) ||
(ymin >= azrp_height)) {
prof_leave(azrp_perf_cmdgen);
return;
}
int ytop = max(ymin, 0);
int ybot = min(ymax, azrp_height - 1);
int frag_first = ytop / azrp_frag_height;
int frag_last = ybot / azrp_frag_height;
int frag_count = frag_last - frag_first + 1;
struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count);
if(!cmd) {
prof_leave(azrp_perf_cmdgen);
return;
}
cmd->shader_id = AZRP_SHADER_FILLEDCIRCLE;
cmd->color = color;
cmd->curr_frag = frag_first;
// reset the point counters in each cell of the table
for (int i = 0; i < 224; i++) {
cmd->DataFilling[2 * i] = -1; // reset with value equels -1
cmd->DataFilling[2 * i + 1] = -1; // reset with value equals -1
}
int x = 0;
int y = rad;
int m = 5 - 4 * rad;
while (x <= y) {
AddPixelFilledCircle(xc - x, xc + x, yc - y, cmd);
AddPixelFilledCircle(xc - y, xc + y, yc - x, cmd);
AddPixelFilledCircle(xc - x, xc + x, yc + y, cmd);
AddPixelFilledCircle(xc - y, xc + y, yc + x, cmd);
if (m > 0) {
y--;
m -= 8 * y;
}
x++;
m += 8 * x + 4;
}
prof_leave(azrp_perf_cmdgen);
}
void azrp_shader_filledcircle(void *uniforms, void *comnd, void *fragment) {
struct command *cmd = (struct command *)comnd;
uint16_t *frag = (uint16_t *)fragment;
int16_t *data = (int16_t *)cmd->DataFilling;
int BaseAdress = cmd->curr_frag * azrp_frag_height * 2;
for (int i = 0; i < azrp_frag_height; i++) {
int16_t Xmin = data[BaseAdress + 2 * i];
int16_t Xmax = data[BaseAdress + 2 * i + 1];
if (Xmin != -1 && Xmax != -1)
for (int j = Xmin; j <= Xmax; j++)
frag[azrp_width * i + j] = cmd->color;
}
cmd->curr_frag++;
}

171
src/shaders/filledpoly.cpp Normal file
View File

@ -0,0 +1,171 @@
#include <azur/gint/render.h>
#include <cstdlib>
uint8_t AZRP_SHADER_FILLEDPOLY = -1;
static void azrp_shader_filledpoly_configure(void) {
azrp_set_uniforms(AZRP_SHADER_FILLEDPOLY, (void *)azrp_width);
}
__attribute__((constructor)) static void register_shader(void) {
extern azrp_shader_t azrp_shader_filledpoly;
AZRP_SHADER_FILLEDPOLY = azrp_register_shader(azrp_shader_filledpoly, azrp_shader_filledpoly_configure);
}
static int min(int x, int y) { return (x < y) ? x : y; }
static int max(int x, int y) { return (x > y) ? x : y; }
//---
#define TABLE_WIDTH
struct command {
uint8_t shader_id;
uint16_t color;
uint8_t curr_frag;
int16_t xmin[224];
int16_t xmax[224];
uint8_t empty[224];
};
void AddPixelFilledPoly(int16_t xpmin, int16_t xpmax, int16_t yp,
struct command *cmd) {
if (yp >= 0 && yp < azrp_height) {
if (xpmin >= 0)
cmd->xmin[yp] = xpmin;
else
cmd->xmin[yp] = 0;
if (xpmax < azrp_width)
cmd->xmax[yp] = xpmax;
else
cmd->xmax[yp] = azrp_width - 1;
}
}
void azrp_filledpoly(int *x, int *y, int nb_vertices, uint16_t color) {
prof_enter(azrp_perf_cmdgen);
int i, ymin, ymax, xmin2, xmax2, *xmin, *xmax;
char *empty;
if(nb_vertices < 3) {
prof_leave(azrp_perf_cmdgen);
return;
}
ymin = ymax = y[0];
xmin2 = xmax2 = x[0];
for(i=0 ; i<nb_vertices ; i++) {
if(y[i] < ymin) ymin = y[i];
if(y[i] > ymax) ymax = y[i];
if(x[i] < xmin2) xmin2 = x[i];
if(x[i] > xmax2) xmax2 = x[i];
}
// The polygon is fully outside the screen
if ((xmax2 < 0) || (xmin2 >= azrp_width) || (ymax < 0) ||
(ymin >= azrp_height)) {
prof_leave(azrp_perf_cmdgen);
return;
}
xmin = (int*) malloc((ymax-ymin+1)*sizeof(int));
xmax = (int*) malloc((ymax-ymin+1)*sizeof(int));
empty = (char*) malloc(ymax-ymin+1);
int ytop = max(ymin, 0);
int ybot = min(ymax, azrp_height - 1);
int frag_first = ytop / azrp_frag_height;
int frag_last = ybot / azrp_frag_height;
int frag_count = frag_last - frag_first + 1;
struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count);
if(!cmd) {
prof_leave(azrp_perf_cmdgen);
return;
}
cmd->shader_id = AZRP_SHADER_FILLEDPOLY;
cmd->color = color;
cmd->curr_frag = frag_first;
// reset the point counters in each cell of the table
for (int i = 0; i < 224; i++) {
cmd->xmin[i] = -1; // reset with value equels -1
cmd->xmax[i] = -1; // reset with value equals -1
}
if(xmin && xmax && empty) {
for(i=0 ; i<ymax-ymin+1 ; i++) empty[i] = 1;
for(i=0 ; i<nb_vertices ; i++) {
int j, px, py, dx, dy, sx, sy, cumul;
px = x[i];
py = y[i];
dx = x[(i+1)%nb_vertices]-px;
dy = y[(i+1)%nb_vertices]-py;
sx = (dx > 0) ? 1 : -1;
sy = (dy > 0) ? 1 : -1;
dx = (dx > 0) ? dx : -dx;
dy = (dy > 0) ? dy : -dy;
if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px;
if(dx > dy) {
cumul = dx >> 1;
for(j=1 ; j<dx ; j++) {
px += sx;
cumul += dy;
if(cumul > dx) cumul -= dx, py += sy;
if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px;
}
} else {
cumul = dy >> 1;
for(j=1 ; j<dy ; j++) {
py += sy;
cumul += dx;
if(cumul > dy) cumul -= dy, px += sx;
if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px;
}
}
}
for(i=0 ; i<ymax-ymin+1 ; i++)
AddPixelFilledPoly(xmin[i], xmax[i], ymin+i, cmd);
}
free(xmin);
free(xmax);
free(empty);
prof_leave(azrp_perf_cmdgen);
}
void azrp_shader_filledpoly(void *uniforms, void *comnd, void *fragment) {
struct command *cmd = (struct command *)comnd;
uint16_t *frag = (uint16_t *)fragment;
int16_t *Xmindata = (int16_t *)cmd->xmin;
int16_t *Xmaxdata = (int16_t *)cmd->xmax;
int BaseAdress = cmd->curr_frag * azrp_frag_height;
for (int i = 0; i < azrp_frag_height; i++)
{
int16_t Xmin = Xmindata[BaseAdress + i];
int16_t Xmax = Xmaxdata[BaseAdress + i];
if (Xmin != -1 && Xmax != -1)
{
if (Xmin<=Xmax)
for (int j = Xmin; j <= Xmax; j++) frag[azrp_width * i + j] = cmd->color;
else
for (int j = Xmax; j <= Xmin; j++) frag[azrp_width * i + j] = cmd->color;
}
}
cmd->curr_frag++;
}

211
src/shaders/line.cpp Normal file
View File

@ -0,0 +1,211 @@
#include <azur/gint/render.h>
uint8_t AZRP_SHADER_LINE = -1;
static void azrp_shader_line_configure(void)
{
azrp_set_uniforms(AZRP_SHADER_LINE, (void *)azrp_width);
}
__attribute__((constructor))
static void register_shader(void)
{
extern azrp_shader_t azrp_shader_line;
AZRP_SHADER_LINE = azrp_register_shader(azrp_shader_line, azrp_shader_line_configure );
}
//---
struct command {
uint8_t shader_id;
uint16_t color;
uint16_t curr_y;
uint16_t curr_x;
int16_t dx, dy, sx, sy;
int16_t cumul;
int16_t i;
};
int ABS( int x1 )
{
if (x1 >= 0) return x1;
else return (-1 * x1);
}
int SGN( int x1 )
{
if (x1 > 0) return 1;
else if (x1 == 0) return 0;
else return -1;
}
void azrp_line(int xA, int yA, int xB, int yB, uint16_t color)
{
prof_enter(azrp_perf_cmdgen);
//clipping algorithm as per "Another Simple but Faster Method for 2D Line Clipping"
//from Dimitrios Matthes and Vasileios Drakopoulos
//International Journal of Computer Graphics & Animation (IJCGA) Vol.9, No.1/2/3, July 2019
int xmin = 0;
int xmax = azrp_width-1;
int ymin = 0;
int ymax = azrp_height-1;
//step 1 line are fully out of the screen
if ((xA<xmin && xB<xmin) || (xA>xmax && xB>xmax) || (yA<ymin && yB<ymin) || (yA>ymax && yB>ymax)) {
prof_leave(azrp_perf_cmdgen);
return;
}
int x1, x2, y1, y2;
// step 1.5 - specific to Azur fragment approach
// we swap to always start with the point on top as the fragment are updated from top to bottom
// (x1,y1) is the most top point and (x2,y2) is the most bottom point (rankig as per y values only
if (yA <= yB) {
x1 = xA; y1 = yA;
x2 = xB; y2 = yB;
}
else {
x1 = xB; y1 = yB;
x2 = xA; y2 = yA;
}
//step 2 line clipping within the box (xmin,ymin) --> (xmax,ymax)
int x[2];
int y[2];
x[0] = x1; x[1] = x2;
y[0] = y1; y[1] = y2;
for(int i=0; i<2; i++) {
if (x[i] < xmin) {
x[i] = xmin; y[i] = ((y2-y1) * (xmin-x1)) / (x2-x1) + y1;
}
else if (x[i] > xmax) {
x[i] = xmax; y[i] = ((y2-y1) * (xmax-x1)) / (x2-x1) + y1;
}
if (y[i] < ymin) {
x[i] = ((x2-x1) * (ymin-y1)) / (y2-y1) + x1; y[i] = ymin;
}
else if (y[i] > ymax) {
x[i] = ((x2-x1) * (ymax-y1)) / (y2-y1) + x1; y[i] = ymax;
}
}
if((x[0] < xmin && x[1] < xmin) || (x[0] > xmax && x[1] > xmax)) {
prof_leave(azrp_perf_cmdgen);
return;
}
x1 = x[0];
y1 = y[0];
x2 = x[1];
y2 = y[1];
int frag_first = y1 / azrp_frag_height;
int frag_last = y2 / azrp_frag_height;
int frag_count = frag_last - frag_first + 1;
struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count);
if(!cmd) {
prof_leave(azrp_perf_cmdgen);
return;
}
cmd->shader_id = AZRP_SHADER_LINE;
cmd->color = color;
cmd->curr_x = x1;
cmd->curr_y = y1 & 15;
cmd->dx = ABS(x2-x1);
cmd->sx = SGN(x2-x1);
cmd->dy = ABS(y2-y1);
cmd->sy = SGN(y2-y1);
cmd->i = 0;
cmd->cumul = (cmd->dx >= cmd->dy) ? cmd->dx/2 : cmd->dy/2;
prof_leave(azrp_perf_cmdgen);
}
void azrp_shader_line( void *uniforms, void *comnd, void *fragment )
{
struct command *cmd = (struct command *) comnd;
uint16_t *frag = (uint16_t *) fragment;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
int i;
if (cmd->dy == 0)
{
for( i = cmd->i; i < cmd->dx ; i++ )
{
cmd->curr_x += cmd->sx;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
}
}
else if (cmd->dx == 0)
{
for( i = cmd->i; i < cmd->dy ; i++ )
{
cmd->curr_y += cmd->sy;
// if curr_y=16, this means we are changing to next fragment
if (cmd->curr_y == azrp_frag_height) break;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
}
}
else if (cmd->dx >= cmd->dy)
{
for( i = cmd->i; i < cmd->dx; i++ )
{
cmd->curr_x += cmd->sx;
cmd->cumul += cmd->dy;
if (cmd->cumul > cmd->dx)
{
cmd->cumul -= cmd->dx;
cmd->curr_y += cmd->sy;
}
// if curr_y=16, this means we are changing to next fragment
if (cmd->curr_y == azrp_frag_height ) break;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
}
}
else
{
for( i = cmd->i; i < cmd->dy; i++ )
{
cmd->curr_y += cmd->sy;
cmd->cumul += cmd->dx;
if (cmd->cumul > cmd->dy)
{
cmd->cumul -= cmd->dy;
cmd->curr_x += cmd->sx;
}
// if curr_y=16, this means we are changing to next fragment
if (cmd->curr_y == azrp_frag_height) break;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
}
}
cmd->curr_y = cmd->curr_y & 15;
cmd->i = i+1;
}

16
src/shaders/poly.cpp Normal file
View File

@ -0,0 +1,16 @@
#include <azur/gint/render.h>
#include "MyAzurShaders.h"
void azrp_poly(int *x, int *y, int nb_vertices, uint16_t color) {
prof_enter(azrp_perf_cmdgen);
for( int i=0 ; i<nb_vertices ; i++) {
int px = x[i];
int py = y[i];
int px2 = x[(i+1)%nb_vertices];
int py2 = y[(i+1)%nb_vertices];
azrp_line( px, py, px2, py2, color );
}
prof_leave(azrp_perf_cmdgen);
}

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "../config.h"
#include <azur/gint/render.h>
#include "MyAzurShaders.h"

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "../config.h"
#include "background.h"
#include <azur/azur.h>
@ -8,13 +8,14 @@
#include <stdlib.h>
extern struct Map map_Level1;
extern struct Map map_Level2;
Map *map_Level;
Background::Background( )
{
map_Level = &map_Level1;
speed = libnum::num(1.0);
}
Background::~Background( )
@ -29,18 +30,18 @@ void Background::Render( void )
int y0 = (int) ylevel;
int yshifttile = (int) (16*ylevel.frac());
for(int u=0; u<map_Level2.nblayers;u++)
for(int u=0; u<map_Level->nblayers;u++)
for(int i=0; i<=25; i++)
{
for(int j=0; j<=14; j++)
{
uint16_t index = (j+y0) * map_Level2.w + (x0+i) % map_Level2.w;
uint16_t currentTile = map_Level2.layers[u][ index ];
uint16_t index = (j+y0) * map_Level->w + (x0+i) % map_Level->w;
uint16_t currentTile = map_Level->layers[u][ index ];
if (currentTile!=0)
{
uint16_t xtile = ((currentTile % map_Level2.tileset_size)-1) * 16;
uint16_t ytile = (currentTile / map_Level2.tileset_size) * 16;
azrp_subimage_p8( i*16-xshifttile, j*16-yshifttile, map_Level2.tileset, xtile, ytile, 16, 16, DIMAGE_NONE );
uint16_t xtile = ((currentTile % map_Level->tileset_size)-1) * 16;
uint16_t ytile = (currentTile / map_Level->tileset_size) * 16;
azrp_subimage_p8( i*16-xshifttile, j*16-yshifttile, map_Level->tileset, xtile, ytile, 16, 16, DIMAGE_NONE );
}
}
}
@ -51,17 +52,17 @@ void Background::Render( void )
uint16_t tilemap[25*14]={0};
for(int u=0; u<map_Level2.nblayers;u++)
for(int u=0; u<map_Level->nblayers;u++)
{
for(int j=0; j<14; j++)
{
for(int i=0; i<=25; i++)
{
uint16_t index = j * map_Level2.w + (x0+i) % map_Level2.w;
tilemap[25*j+i]= cmap_Level2.layers[u][ index ];
uint16_t index = j * map_Level->w + (x0+i) % map_Level->w;
tilemap[25*j+i]= cmap_Level->layers[u][ index ];
}
}
azrp_tilesmap( shifttile, tilemap, map_Level2.tileset, map_Level2.tileset_size);
azrp_tilesmap( shifttile, tilemap, map_Level->tileset, map_Level->tileset_size);
}
*/
}
@ -69,7 +70,13 @@ void Background::Render( void )
void Background::Update( float dt )
{
libnum::num a = libnum::num( dt / 90000.0f); //18000.0f );
xlevel += a;
xlevel += speed*a;
}
void Background::SetSpeed(libnum::num s)
{
speed = s;
}
@ -82,7 +89,7 @@ void Background::IncYCoordinate( libnum::num y )
{
ylevel += y ;
if (ylevel<0) ylevel=libnum::num(0);
if (ylevel>map_Level2.h-14) ylevel=libnum::num(map_Level2.h-14);
if (ylevel>map_Level->h-14) ylevel=libnum::num(map_Level->h-14);
}

View File

@ -38,8 +38,11 @@ class Background
int GetXCoordinate( void );
int GetYCoordinate( void );
void SetSpeed( libnum::num s );
private:
libnum::num xlevel, ylevel;
libnum::num speed;
};

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "../config.h"
#include "bonus.h"
#include <num/num.h>
@ -37,12 +37,13 @@ Bonus::Bonus( int16_t _x, int16_t _y, uint8_t _id )
currentframe = libnum::num(0);
accumulatedTime = 0.0f;
}
Bonus::~Bonus()
{
if (hasTrajectory)
delete(pathToFollow);
pathToFollow->DeleteRegistry();
}
void Bonus::Update( float dt )
@ -61,7 +62,7 @@ void Bonus::Update( float dt )
}
else
{
pathToFollow->CalculatePosition( dt, speed, true, &x, &y );
pathToFollow->CalculatePosition( &accumulatedTime, dt, speed, true, &x, &y );
}
xmin = (int) x - width;

View File

@ -32,7 +32,9 @@ class Bonus
private:
int8_t dirx, diry;
libnum::num currentframe;
libnum::num currentframe;
float accumulatedTime;
};

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "../config.h"
#include "boss.h"
#include "bullet.h"
@ -6,13 +6,13 @@
#include <num/num.h>
#include <gint/rtc.h>
#include <sys/types.h>
#include "fast_trig.h"
#include "../utilities/fast_trig.h"
#include <gint/gint.h>
#include "collections.h"
#include "player.h"
#include "vector2D.h"
#include "../utilities/vector2D.h"
extern bopti_image_t img_Lifebar;
extern bopti_image_t img_Boss1;
@ -154,6 +154,7 @@ Boss::Boss( int16_t _x, int16_t _y, uint8_t _id )
Guns[i].toberemoved = false;
}
accumulatedTime = 0.0f;
/* FOR DEBUGGING */
// gint_world_switch( GINT_CALL( savedata ) );
@ -162,7 +163,7 @@ Boss::Boss( int16_t _x, int16_t _y, uint8_t _id )
Boss::~Boss()
{
if (hasTrajectory)
delete(pathToFollow);
pathToFollow->DeleteRegistry();
}
@ -171,7 +172,7 @@ void Boss::Update( float dt )
if (hasTrajectory)
{
pathToFollow->CalculatePosition( dt, speed, true, &x, &y );
pathToFollow->CalculatePosition( &accumulatedTime, dt, speed, true, &x, &y );
}
xmin = (int) x - width;

View File

@ -60,6 +60,8 @@ class Boss
uint32_t lastshoot0 = 0;
uint32_t lastshoot1 = 0;
float accumulatedTime;
bool Shoot_OK( uint32_t tempshoot, uint8_t shootID );
};

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "../config.h"
#include "bullet.h"

View File

@ -1,19 +1,18 @@
#include "config.h"
#include "../config.h"
#include "collections.h"
#include "trajectory.h"
#include <vector>
#include <gint/rtc.h>
extern std::vector<Particle*> MyParticles;
extern std::vector<Bullet*> MyPlayerBullets;
extern std::vector<Bullet*> MyEnemiesBullets;
extern std::vector<Enemy*> MyEnemies;
extern std::vector<Impact*> MyImpacts;
extern std::vector<Trajectory*> MyTrajectories;
extern Player *MyPlayer;
@ -50,6 +49,7 @@ void Create_Player_Shoot( uint8_t id )
void Create_Enemies( void )
{
/*
Enemy* e1 = new Enemy( 348, 112, 0);
e1->Set_Speed_Vector( 1, 1, -6 );
MyEnemies.push_back( e1 );
@ -65,32 +65,51 @@ void Create_Enemies( void )
Enemy* e4 = new Enemy( 348, 112, 1);
e4->Set_Speed_Vector( 1, 3, 3 );
MyEnemies.push_back( e4 );
*/
Point2D *A = new Point2D( 348, 112 );
Point2D *B = new Point2D( 371, 199 );
Point2D *C = new Point2D( 198, 149 );
Point2D *D = new Point2D( 25, 199 );
Point2D *E = new Point2D( 25, 25 );
Point2D *F = new Point2D( 198, 75 );
Point2D *G = new Point2D( 371, 25 );
Vector2D *A = new Vector2D( 348, 112 );
Vector2D *B = new Vector2D( 371, 199 );
Vector2D *C = new Vector2D( 198, 149 );
Vector2D *D = new Vector2D( 25, 199 );
Vector2D *E = new Vector2D( 25, 25 );
Vector2D *F = new Vector2D( 198, 75 );
Vector2D *G = new Vector2D( 371, 25 );
Trajectory *MyTrajectory= new Trajectory();
MyTrajectory->AddPoint( A );
MyTrajectory->AddPoint( B );
MyTrajectory->AddPoint( C );
MyTrajectory->AddPoint( D );
MyTrajectory->AddPoint( E );
MyTrajectory->AddPoint( F );
MyTrajectory->AddPoint( G );
Trajectory *MyPath= new Trajectory();
MyPath->AddPoint( A );
MyPath->AddPoint( B );
MyPath->AddPoint( C );
MyPath->AddPoint( D );
MyPath->AddPoint( E );
MyPath->AddPoint( F );
MyPath->AddPoint( G );
MyTrajectories.push_back( MyPath );
Enemy* e5 = new Enemy( 348, 112, 2);
e5->hasTrajectory = true;
e5->pathToFollow = MyTrajectory;
e5->pathToFollow = MyPath;
MyPath->AddRegistry();
e5->Set_Accumulated_Time(0.0f);
Enemy* e6 = new Enemy( 348, 112, 2);
e6->hasTrajectory = true;
e6->pathToFollow = MyPath;
MyPath->AddRegistry();
e6->Set_Accumulated_Time(-1.0f);
Enemy* e7 = new Enemy( 348, 112, 2);
e7->hasTrajectory = true;
e7->pathToFollow = MyPath;
MyPath->AddRegistry();
e7->Set_Accumulated_Time(-2.0f);
MyEnemies.push_back( e5 );
MyEnemies.push_back( e6 );
MyEnemies.push_back( e7 );
}
@ -151,6 +170,13 @@ void Clean_Everything( void )
}
MyImpacts.clear();
for(unsigned int i=0; i<MyTrajectories.size(); i++)
{
delete( MyTrajectories[i] );
MyTrajectories.erase( MyTrajectories.begin() + i );
}
MyTrajectories.clear();
}

View File

@ -3,11 +3,11 @@
#include "player.h"
#include "utilities.h"
#include "../utilities/utilities.h"
#include "particles.h"
#include "bullet.h"
#include "enemy.h"
#include "MyAzurShaders.h"
#include "../shaders/MyAzurShaders.h"
#include "impact.h"
#include "trajectory.h"

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "../config.h"
#include "enemy.h"
#include "bullet.h"
@ -55,12 +55,14 @@ Enemy::Enemy( int16_t _x, int16_t _y, uint8_t _id )
toberemoved = false;
lastshottime = 0;
accumulatedTime = 0.0f;
}
Enemy::~Enemy()
{
if (hasTrajectory)
delete(pathToFollow);
pathToFollow->DeleteRegistry();
}
void Enemy::Update( float dt )
@ -76,7 +78,7 @@ void Enemy::Update( float dt )
}
else
{
pathToFollow->CalculatePosition( dt, speed, true, &x, &y );
pathToFollow->CalculatePosition( &accumulatedTime, dt, speed, true, &x, &y );
}
xmin = (int) x - width;
@ -87,7 +89,7 @@ void Enemy::Update( float dt )
uint32_t tempshoot = rtc_ticks();
if (Shoot_OK( tempshoot ))
if (Shoot_OK( tempshoot, 0 ))
{
if ( ID==0 )
{
@ -153,14 +155,19 @@ bool Enemy::Test_Impact( Bullet *projectile )
else return false;
}
void Enemy::Set_Speed_Vector( uint8_t _sp, uint8_t _xd, uint8_t _yd)
void Enemy::Set_Speed_Vector( uint8_t _sp, uint8_t _xd, uint8_t _yd )
{
speed = _sp;
dirx = _xd;
diry = _yd;
}
bool Enemy::Shoot_OK( uint32_t tempshoot )
void Enemy::Set_Accumulated_Time( float value )
{
accumulatedTime = value;
}
bool Enemy::Shoot_OK( uint32_t tempshoot, uint8_t shootID )
{
if(tempshoot-lastshottime>15)
{

View File

@ -24,6 +24,8 @@ class Enemy
bool Test_Impact( Bullet *projectile );
void Set_Speed_Vector( uint8_t _sp, uint8_t _xd, uint8_t _yd);
void Set_Accumulated_Time( float value );
libnum::num x, y; // center position of the ennemy
uint8_t width, height; // width and height -for the hitbox
int16_t xmin, xmax, ymin, ymax; // square hitbox (to speed up the bullet impact calculations)
@ -39,8 +41,9 @@ class Enemy
int8_t dirx, diry; // vector of the current direction of the ennemy (TODO : to implement more complex displacement pattern)
uint32_t lastshottime;
float accumulatedTime;
bool Shoot_OK( uint32_t tempshoot );
bool Shoot_OK( uint32_t tempshoot, uint8_t shootID );
};

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "../config.h"
#include "impact.h"

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "../config.h"
#include "particles.h"

View File

@ -1,28 +1,40 @@
#include "config.h"
#include "../config.h"
#include "player.h"
#include "bullet.h"
#include "enemy.h"
#include <num/num.h>
#include <gint/rtc.h>
#include "fast_trig.h"
#include "../utilities/fast_trig.h"
#include "background.h"
extern bopti_image_t img_Lifebar;
extern bopti_image_t img_mainship1;
extern bopti_image_t *img_mainship1;
extern bopti_image_t img_player_ship1;
extern bopti_image_t img_player_ship2;
extern bopti_image_t img_player_ship3;
extern bopti_image_t img_player_ship4;
extern bopti_image_t img_player_ship5;
extern bopti_image_t img_player_ship6;
extern bopti_image_t img_player_ship7;
extern bopti_image_t img_player_ship8;
extern bopti_image_t img_Satellite_Lvl1;
extern Background MyBackground;
Player::Player( int16_t _x, int16_t _y, uint8_t _id )
{
img_mainship1 = &img_player_ship7;
x = libnum::num(_x);
y = libnum::num(_y);
ID = _id;
width = img_mainship1.width/2;
height = img_mainship1.height/2;
width = img_mainship1->width/2;
height = img_mainship1->height/2;
speed = 10;
xmin = (int) x - width;
@ -68,7 +80,7 @@ void Player::Render( void )
{
azrp_subimage_p8_effect( (int) x - img_Lifebar.width/2, ymin - 10, &img_Lifebar, 0, 0, img_Lifebar.width, 7, DIMAGE_NONE );
if (ID==0) azrp_image_p8_effect(xmin, ymin, &img_mainship1, DIMAGE_NONE);
if (ID==0) azrp_image_p8_effect(xmin, ymin, img_mainship1, DIMAGE_NONE);
int w = img_Satellite_Lvl1.width/2;
int h = img_Satellite_Lvl1.height/2;

View File

@ -1,47 +1,59 @@
#include "config.h"
#include "../config.h"
#include "trajectory.h"
Trajectory::Trajectory( )
{
accumulatedTime = 0.0f;
registration = 0;
//accumulatedTime = 0.0f;
}
Trajectory::~Trajectory( )
{
for( auto& p : ControlPoints )
delete( p );
ControlPoints.clear();
for( auto& p : ControlPoints )
delete( p );
ControlPoints.clear();
}
void Trajectory::AddPoint( Point2D *p )
void Trajectory::AddPoint( Vector2D *p )
{
ControlPoints.push_back( p );
}
void Trajectory::CalculatePosition( float time, uint16_t speed, bool looped, libnum::num *xreturn, libnum::num *yreturn )
void Trajectory::AddRegistry( void )
{
accumulatedTime += speed * time / 2000000.0f;
if (accumulatedTime>ControlPoints.size()) accumulatedTime-=ControlPoints.size();
registration++;
}
libnum::num t = libnum::num( accumulatedTime - (int) accumulatedTime );
void Trajectory::DeleteRegistry( void )
{
registration--;
}
void Trajectory::CalculatePosition( float *accumulatedTime, float time, uint16_t speed, bool looped, libnum::num *xreturn, libnum::num *yreturn )
{
*accumulatedTime += speed * time / 2000000.0f;
if (*accumulatedTime>ControlPoints.size()) *accumulatedTime-=ControlPoints.size();
if (*accumulatedTime<0) *accumulatedTime+=ControlPoints.size();
libnum::num t = libnum::num( *accumulatedTime - (int) *accumulatedTime );
int p0, p1, p2, p3;
if (!looped)
{
p1 = (int) accumulatedTime + 1;
p1 = (int) *accumulatedTime + 1;
p2 = p1 + 1;
p3 = p2 + 1;
p0 = p1 - 1;
}
else
{
p1 = (int) accumulatedTime;
p1 = (int) *accumulatedTime;
p2 = (p1 + 1) % ControlPoints.size();
p3 = (p2 + 1) % ControlPoints.size();
p0 = p1 >= 1 ? p1 - 1 : ControlPoints.size() - 1;

33
src/shmup/trajectory.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef TRAJECTORY_H
#define TRAJECTORY_H
#include <cstdint>
#include <stdlib.h>
#include <num/num.h>
#include <vector>
#include "../utilities/vector2D.h"
#include "num/num.h"
class Trajectory
{
public:
Trajectory( );
~Trajectory( );
void AddPoint( Vector2D *p );
void AddRegistry( void );
void DeleteRegistry( void );
void CalculatePosition( float *accumulatedTime, float time, uint16_t speed, bool looped, libnum::num *xreturn, libnum::num *yreturn );
std::vector<Vector2D*> ControlPoints;
bool isLoop;
uint16_t registration;
//float accumulatedTime;
};
#endif

View File

@ -1,68 +0,0 @@
#include "config.h"
#include <azur/gint/render.h>
#include "MyAzurShaders.h"
#include <cstdlib>
#include <cstdio>
#include <gint/rtc.h>
uint8_t AZRP_SHADER_TILESMAP = -1;
__attribute__((constructor))
static void register_shader(void)
{
extern azrp_shader_t azrp_shader_tilesmap;
AZRP_SHADER_TILESMAP = azrp_register_shader(azrp_shader_tilesmap);
}
void azrp_shader_tilesmap_configure(void)
{
azrp_set_uniforms(AZRP_SHADER_TILESMAP, (void *)azrp_width);
}
struct command {
uint8_t shader_id;
uint8_t current_frag;
int shifttile;
int *tilemap;
bopti_image_t *image;
int tileset_size;
};
void azrp_tilesmap( int shifttile, int *tilemap, bopti_image_t *image, int tileset_size );
{
prof_enter(azrp_perf_cmdgen);
struct command cmd;
cmd.shader_id = AZRP_SHADER_TILESMAP;
cmd.current_frag = 0;
cmd.shifttile = shifttile;
cmd.tilemap = tilemap;
cmd.image = image;
cmd.tileset_size = tileset_size;
azrp_queue_command(&cmd, sizeof cmd, 0, azrp_frag_count);
prof_leave(azrp_perf_cmdgen);
}
void azrp_shader_tilesmap( void *uniforms, void *comnd, void *fragment )
{
struct command *cmd = (struct command *) comnd;
uint16_t *frag = (uint16_t *) fragment;
int currentile = cmd->tilemap[cmd->current_frag*25];
for(int u=0; u<=25;u++)
cmd->current_frag++;
}

View File

@ -1,27 +0,0 @@
#ifndef TRAJECTORY_H
#define TRAJECTORY_H
#include <cstdint>
#include <stdlib.h>
#include <num/num.h>
#include <vector>
#include "point2D.h"
#include "num/num.h"
class Trajectory
{
public:
Trajectory( );
~Trajectory( );
void AddPoint( Point2D *p );
void CalculatePosition( float time, uint16_t speed, bool looped, libnum::num *xreturn, libnum::num *yreturn );
std::vector<Point2D*> ControlPoints;
bool isLoop;
float accumulatedTime;
};
#endif

View File

@ -1,42 +0,0 @@
#include "config.h"
#include <azur/azur.h>
#include <azur/gint/render.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fxlibc/printf.h>
extern font_t milifont_prop;
/* Render text with Azur images - quite bad, but I don't have time lol. */
void Azur_draw_text(int x, int y, char const *fmt, ...)
{
/* char str[128];
va_list args;
va_start(args, fmt);
vsnprintf(str, 128, fmt, args);
va_end(args);
extern bopti_image_t img_font;
for(int i = 0; str[i]; i++) {
if(str[i] < 32 || str[i] >= 0x7f) continue;
int row = (str[i] - 32) >> 4;
int col = (str[i] - 32) & 15;
azrp_subimage(x + 5 * i, y, &img_font, 7 * col + 1, 9 * row + 1, 6, 8, DIMAGE_NONE);
}
*/
char str[128];
va_list args;
va_start(args, fmt);
vsnprintf(str, 128, fmt, args);
va_end(args);
dfont( &milifont_prop );
azrp_text( x, y, C_WHITE, str );
}

View File

@ -1,6 +0,0 @@
#ifndef UTILITIES_H
#define UTILITIES_H
void Azur_draw_text(int x, int y, char const *fmt, ...);
#endif

View File

@ -1,4 +1,4 @@
#include "config.h"
#include "../config.h"
#include "extrakeyboard.h"
#include <gint/keyboard.h>

183
src/utilities/fast_trig.cpp Normal file
View File

@ -0,0 +1,183 @@
#include "fast_trig.h"
#include "num/num.h"
static libnum::num cosTable[360];
static libnum::num sinTable[360];
static bool is_fast_trig_initialised = false;
void Fast_Trig_Init( void )
{
for(int u=0; u<360; u++)
{
cosTable[u] = libnum::num( cos( u * PI / 180 ) );
sinTable[u] = libnum::num( sin( u * PI / 180 ) );
}
is_fast_trig_initialised = true;
}
libnum::num FastCosInt( int16_t angle )
{
if (!is_fast_trig_initialised) Fast_Trig_Init();
if (angle>=0 and angle<360) return cosTable[ angle ];
else
{
int16_t input = angle;
if (input<0)
{
while (input<0) input+=360;
return cosTable[ input ];
}
else
{
while (input>=360) input-=360;
return cosTable[ input ];
}
}
}
libnum::num FastSinInt( int16_t angle )
{
if (!is_fast_trig_initialised) Fast_Trig_Init();
if (angle>=0 and angle<360) return sinTable[ angle ];
else
{
int16_t input = angle;
if (input<0)
{
while (input<0) input+=360;
return sinTable[ input ];
}
else
{
while (input>=360) input-=360;
return sinTable[ input ];
}
}
}
libnum::num FastTanInt( int16_t angle )
{
if (!is_fast_trig_initialised) Fast_Trig_Init();
int16_t input = angle;
if (input<0)
{
while (input<0) input+=360;
}
else if (input>=360)
{
while (input>=360) input-=360;
}
libnum::num value;
if (input==90)
{
value.v = INT32_MAX;
return value;
}
else if (input==270)
{
value.v = INT32_MIN;
return value;
}
else
{
value = FastSinInt(input) / FastCosInt(input);
return value;
}
}
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 * PI))
anglereduced -= libnum::num32(2 * PI);
// Exploit the symetry for angle and angle+Pi to reduce the order of the
// limited developpement
if (anglereduced >= libnum::num(PI))
return -cos_num32(anglereduced - libnum::num(PI));
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 * PI))
anglereduced -= libnum::num32(2 * PI);
// Exploit the symetry for angle and angle+Pi to reduce the order of the
// limited developpement
if (anglereduced >= libnum::num(PI))
return -sin_num32(anglereduced - libnum::num(PI));
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;
}

View File

@ -5,9 +5,7 @@
#include <cmath>
#include <num/num.h>
#define PI 3.141592
#define PI 3.14159265
void Fast_Trig_Init( void );
@ -15,5 +13,10 @@ libnum::num FastCosInt( int16_t angle );
libnum::num FastSinInt( int16_t angle );
libnum::num FastTanInt( int16_t angle );
libnum::num32 sqrt_num32(libnum::num32 v);
libnum::num32 cos_num32(libnum::num32 angle);
libnum::num32 sin_num32(libnum::num32 angle);
#endif

214
src/utilities/utilities.cpp Normal file
View File

@ -0,0 +1,214 @@
#include "../config.h"
#include <azur/azur.h>
#include <azur/gint/render.h>
#include "utilities.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fxlibc/printf.h>
#include <sys/types.h>
extern font_t milifont_prop;
void Azur_draw_text(int x, int y, char const *fmt, ...)
{
char str[128];
va_list args;
va_start(args, fmt);
vsnprintf(str, 128, fmt, args);
va_end(args);
dfont( &milifont_prop );
azrp_text( x, y, C_WHITE, str );
}
bool AABB_Collision( SpriteLocator image1, SpriteLocator image2 )
{
if( (image2.x >= image1.x + image1.image->width)
|| (image2.x + image2.image->width <= image1.x)
|| (image2.y >= image1.y + image1.image->height)
|| (image2.y + image2.image->height <= image1.y) )
return false;
// no need to do pixel perfect detection
return true;
}
bool Pixel_Perfect_Collision( SpriteLocator image1, SpriteLocator image2 )
{
if( !AABB_Collision( image1, image2 ) )
return false; // bounding boxes not overlapping, impossible to have collision
/* if we reach that point, this means that we need to perform pixel perfect collsion detection */
/* First we will calculate the corners of the zone to be tested for collision */
/* as it is not usefull to check for all the surface of the image, only the */
/* overlapping area will be verified */
/* WARNING !! */
/* P4 format is not supported yet has it is currently focused on use with Azur */
/* that is mostly P8/RGB565 oriented for ultra fast performances */
if ( IMAGE_IS_P4(image1.image->format) || IMAGE_IS_P4(image2.image->format) )
return false;
int astartx, aendx;
int astarty, aendy;
int adeltax, adeltay;
int bstartx, bendx;
int bstarty, bendy;
int bdeltax, bdeltay;
int rows, columns;
if (image1.x <= image2.x)
{
adeltax = image2.x - image1.x;
columns = MIN(image1.image->width - adeltax, image2.image->width);
bdeltax = 0;
}
else
{
bdeltax = image1.x - image2.x;
columns = MIN(image2.image->width - bdeltax, image1.image->width);
adeltax = 0;
}
if (image1.y <= image2.y)
{
adeltay = image2.y - image1.y;
rows = MIN(image1.image->height - adeltay, image2.image->height);
bdeltay = 0;
}
else
{
bdeltay = image1.y - image2.y;
rows = MIN(image2.image->height - bdeltay, image1.image->height);
adeltay = 0;
}
/* if BOTH images are in a 16bits color format, we will not use masks and will quicken the process */
if ( IMAGE_IS_RGB16(image1.image->format) && IMAGE_IS_RGB16(image2.image->format) )
{
void *data1 = image1.image->data + adeltay * image1.image->stride;
void *data2 = image2.image->data + bdeltay * image2.image->stride;
uint16_t *data_u16_1 = (uint16_t *) data1;
uint16_t *data_u16_2 = (uint16_t *) data2;
int transp1 = image_alpha(image1.image->format);
int transp2 = image_alpha(image2.image->format);
for( int j=0; j<rows; j++)
{
for (int i=0; i<columns; i++)
{
if( (data_u16_1[ adeltax + i ] != transp1 )
&& (data_u16_2[ bdeltax + i ] != transp2 ) )
return true;
}
data1 += image1.image->stride;
data_u16_1 = (uint16_t *) data1;
data2 += image2.image->stride;
data_u16_2 = (uint16_t *) data2;
}
return false;
}
/* if BOTH images are in a 8bits color format, we will not use masks and will quicken the process */
if ( IMAGE_IS_P8(image1.image->format) && IMAGE_IS_P8(image2.image->format) )
{
void *data1 = image1.image->data + adeltay * image1.image->stride;
void *data2 = image2.image->data + bdeltay * image2.image->stride;
int8_t *data_u8_1 = (int8_t *) data1;
int8_t *data_u8_2 = (int8_t *) data2;
int transp1 = image_alpha(image1.image->format);
int transp2 = image_alpha(image2.image->format);
for( int j=0; j<rows; j++)
{
for (int i=0; i<columns; i++)
{
if( (data_u8_1[ adeltax + i ] != transp1 )
&& (data_u8_2[ bdeltax + i ] != transp2 ) )
return true;
}
data1 += image1.image->stride;
data_u8_1 = (int8_t *) data1;
data2 += image2.image->stride;
data_u8_2 = (int8_t *) data2;
}
return false;
}
/* if we reach that point, this means that images have differnt format and we need to manage this */
uint8_t d1;
uint8_t d2;
void *data1 = image1.image->data + adeltay * image1.image->stride;
void *data2 = image2.image->data + bdeltay * image2.image->stride;
int8_t *data_u8_1 = (int8_t *) data1;
uint16_t *data_u16_1 = (uint16_t *) data1;
int8_t *data_u8_2 = (int8_t *) data2;
uint16_t *data_u16_2 = (uint16_t *) data2;
int transp1 = image_alpha(image1.image->format);
int transp2 = image_alpha(image2.image->format);
bool im1_P16 = IMAGE_IS_RGB16(image1.image->format);
bool im1_P8 = IMAGE_IS_P8(image1.image->format);
bool im2_P16 = IMAGE_IS_RGB16(image2.image->format);
bool im2_P8 = IMAGE_IS_P8(image2.image->format);
for( int j=0; j<rows; j++)
{
for (int i=0; i<columns; i++)
{
/* d1 is set to 1 if pixel of image1 is not transparent and to 0 if transparent */
/* need to be format dependant here so quite time consumming test at each loop :( )*/
if (im1_P16)
d1 = data_u16_1[ adeltax + i ] == transp1 ? 0 : 1;
else if (im1_P8)
d1 = data_u8_1[ adeltax + i ] == transp1 ? 0 : 1;
/* d2 is set to 1 if pixel of image2 is not transparent and to 0 if transparent */
/* need to be format dependant here so quite time consumming test at each loop :( )*/
if (im2_P16)
d2 = data_u16_2[ bdeltax + i ] == transp2 ? 0 : 1;
else if (im2_P8)
d2 = data_u8_2[ bdeltax + i ] == transp2 ? 0 : 1;
/* if d1 + d2 = 2 means that both coincident pixels are not transparent and then we have collision*/
if (d1 + d2 == 2) return true;
}
/* we move the pointer to the next line of both images */
data1 += image1.image->stride;
data2 += image2.image->stride;
data_u8_1 = (int8_t *) data1;
data_u8_2 = (int8_t *) data2;
data_u16_1 = (uint16_t *) data1;
data_u16_2 = (uint16_t *) data2;
}
return false;
}

34
src/utilities/utilities.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef UTILITIES_H
#define UTILITIES_H
#include <cstdint>
#include "gint/image.h"
typedef struct
{
/* position of the picture */
int16_t x, y;
/* pointer to the image structure */
image_t *image;
} SpriteLocator;
#define ABS(a) ((a) < 0 ? -(a) : (a))
#define FLOOR(a) ((a) < 0 ? (int)((a)-1.0) : (int)(a))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
bool AABB_Collision( SpriteLocator image1, SpriteLocator image2 );
bool Pixel_Perfect_Collision( SpriteLocator image1, SpriteLocator image2 );
void Azur_draw_text(int x, int y, char const *fmt, ...);
#endif

111
src/utilities/vector2D.cpp Normal file
View File

@ -0,0 +1,111 @@
#include "vector2D.h"
#include "fast_trig.h"
Vector2D::Vector2D() {
this->x = libnum::num32(0);
this->y = libnum::num32(0);
}
Vector2D::Vector2D(float x, float y) {
this->x = libnum::num32(x);
this->y = libnum::num32(y);
}
Vector2D::Vector2D(libnum::num32 x, libnum::num32 y) {
this->x = x;
this->y = y;
}
Vector2D::Vector2D(const Vector2D &v) {
this->x = v.x;
this->y = v.y;
}
Vector2D::~Vector2D() {}
void Vector2D::Set(Vector2D v) {
this->x = v.x;
this->y = v.y;
}
void Vector2D::Normalise(void) {
libnum::num32 len = this->Length();
this->x /= len;
this->y /= len;
}
Vector2D Vector2D::Clone(void) {
Vector2D NewVector(this->x, this->y);
return NewVector;
}
Vector2D Vector2D::MakeVector(Vector2D A, Vector2D B) {
Vector2D NewVector(B.x - A.x, B.y - A.y);
return NewVector;
}
void Vector2D::AddVectors(Vector2D a, Vector2D b) {
this->x = a.x + b.x;
this->y = a.y + b.y;
}
void Vector2D::Add(Vector2D v, libnum::num32 scale) {
this->x += v.x * scale;
this->y += v.y * scale;
}
void Vector2D::SubtractVectors(Vector2D a, Vector2D b) {
this->x = a.x - b.x;
this->y = a.y - b.y;
}
void Vector2D::Subtract(Vector2D v, libnum::num32 scale) {
this->x -= v.x * scale;
this->y -= v.y * scale;
}
libnum::num32 Vector2D::Length(void) {
return sqrt_num32(this->x * this->x + this->y * this->y);
}
void Vector2D::Scale(libnum::num32 scale) {
this->x *= scale;
this->y *= scale;
}
libnum::num32 Vector2D::Dot(Vector2D v) { return (this->x * v.x + this->y * v.y); }
libnum::num32 Vector2D::Det(Vector2D v) { return (this->x * v.y - this->y * v.x); }
Vector2D Vector2D::PerpCW(void) {
Vector2D temp(-this->y, this->x);
return temp;
}
Vector2D Vector2D::PerpCCW(void) {
Vector2D temp(this->y, -this->x);
return temp;
}
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;
}

112
src/utilities/vector2D.h Normal file
View File

@ -0,0 +1,112 @@
#ifndef VECTOR2D_H
#define VECTOR2D_H
#include <num/num.h>
#include <stdint.h>
#include "fast_trig.h"
class Vector2D {
public:
Vector2D();
Vector2D(float x, float y);
Vector2D(libnum::num32 x, libnum::num32 y);
Vector2D(const Vector2D &v);
~Vector2D();
void Set(Vector2D v);
void Normalise(void);
Vector2D Clone(void);
Vector2D MakeVector(Vector2D A, Vector2D B);
void AddVectors(Vector2D a, Vector2D b);
void Add(Vector2D v, libnum::num32 scale);
void SubtractVectors(Vector2D a, Vector2D b);
void Subtract(Vector2D v, libnum::num32 scale);
libnum::num32 Length(void);
void Scale(libnum::num32 scale);
libnum::num32 Dot(Vector2D v);
libnum::num32 Det(Vector2D v);
Vector2D PerpCW(void);
Vector2D PerpCCW(void);
/* 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);
#endif

View File

@ -1,278 +0,0 @@
#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