Boss with satellite guns - Bullet Hell versions to test framerate

This commit is contained in:
Sylvain PILLOT 2023-08-22 23:34:18 +02:00
parent 22f087db76
commit a524c5f08e
16 changed files with 478 additions and 18 deletions

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -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;
}

View File

@ -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 );
};

View File

@ -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;
}
}

View File

@ -11,6 +11,8 @@ enum
BULLET_BLUE,
BULLET_LASER,
BULLET_ENEMY_BLUE,
BULLET_ENEMY_RED,
BULLET_ENEMY_GREEN,
};

View File

@ -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

View File

@ -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 );
}
}

View File

@ -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())
{

278
src/vector2D.h Normal file
View File

@ -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