bullets are go
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
|
@ -4,4 +4,17 @@ IMAGE bgWall1 "bg/wall1.png" FAST
|
||||||
IMAGE bgCeil1 "bg/ceil1.png" FAST
|
IMAGE bgCeil1 "bg/ceil1.png" FAST
|
||||||
IMAGE bgFloor1 "bg/floor1.png" FAST
|
IMAGE bgFloor1 "bg/floor1.png" FAST
|
||||||
|
|
||||||
SPRITE nitori "player/nitori.png" 4 4 FAST
|
SPRITE nitori "player/nitori.png" 4 4 FAST
|
||||||
|
|
||||||
|
SPRITE smallRedBullet "bullets/smallred.png" 1 1 FAST 5
|
||||||
|
SPRITE smallBlueBullet "bullets/smallblue.png" 1 1 FAST 5
|
||||||
|
SPRITE smallGreenBullet "bullets/smallgreen.png" 1 1 FAST 5
|
||||||
|
SPRITE smallPinkBullet "bullets/smallpink.png" 1 1 FAST 5
|
||||||
|
SPRITE smallYellowBullet "bullets/smallyellow.png" 1 1 FAST 5
|
||||||
|
SPRITE smallWhiteBullet "bullets/smallwhite.png" 1 1 FAST 5
|
||||||
|
SPRITE bigRedBullet "bullets/bigred.png" 2 2 FAST 5
|
||||||
|
SPRITE bigBlueBullet "bullets/bigblue.png" 2 2 FAST 5
|
||||||
|
SPRITE bigGreenBullet "bullets/biggreen.png" 2 2 FAST 5
|
||||||
|
SPRITE bigPinkBullet "bullets/bigpink.png" 2 2 FAST 5
|
||||||
|
SPRITE bigYellowBullet "bullets/bigyellow.png" 2 2 FAST 5
|
||||||
|
SPRITE bigWhiteBullet "bullets/bigwhite.png" 2 2 FAST 5
|
|
@ -0,0 +1,124 @@
|
||||||
|
// bullets
|
||||||
|
|
||||||
|
#define BULLET_COUNT 64
|
||||||
|
|
||||||
|
struct bullet {
|
||||||
|
bool active, player;
|
||||||
|
fix16 speed;
|
||||||
|
fix32 dist;
|
||||||
|
Vect2D_f16 pos, vel;
|
||||||
|
s16 angle, clock;
|
||||||
|
Sprite* image;
|
||||||
|
bool dead, big;
|
||||||
|
void (*updater)(s16);
|
||||||
|
bool bools[COUNT_INT];
|
||||||
|
s16 ints[COUNT_INT];
|
||||||
|
fix16 fixes[COUNT_INT];
|
||||||
|
};
|
||||||
|
struct bullet bullets[BULLET_COUNT];
|
||||||
|
|
||||||
|
|
||||||
|
// lifecycle
|
||||||
|
|
||||||
|
#define BULLET_OFF 4
|
||||||
|
#define BULLET_OFF_BIG 8
|
||||||
|
|
||||||
|
#define BULLET_DIST FIX32(4)
|
||||||
|
#define BULLET_DIST_BIG FIX32(8)
|
||||||
|
|
||||||
|
void spawnBullet(struct bulletSpawner spawner, void(*updater)){
|
||||||
|
s16 i = -1;
|
||||||
|
for(s16 j = 0; j < BULLET_COUNT; j++) if(!bullets[j].active && i == -1) i = j;
|
||||||
|
if(i > -1 && (spawner.player || (player.invincibleClock < INVINCIBLE_LIMIT))){
|
||||||
|
bullets[i].active = TRUE;
|
||||||
|
bullets[i].pos.x = spawner.x;
|
||||||
|
bullets[i].pos.y = spawner.y;
|
||||||
|
bullets[i].dist = fix16ToFix32(spawner.big ? BULLET_DIST_BIG : BULLET_DIST);
|
||||||
|
bullets[i].speed = spawner.speed;
|
||||||
|
bullets[i].angle = spawner.angle;
|
||||||
|
bullets[i].player = spawner.player;
|
||||||
|
bullets[i].clock = 0;
|
||||||
|
bullets[i].dead = FALSE;
|
||||||
|
bullets[i].big = spawner.big;
|
||||||
|
for(u8 j = 0; j < COUNT_INT; j++){
|
||||||
|
bullets[i].bools[j] = spawner.bools[j];
|
||||||
|
bullets[i].ints[j] = spawner.ints[j];
|
||||||
|
bullets[i].fixes[j] = spawner.fixes[j];
|
||||||
|
}
|
||||||
|
if(spawner.vel.x && spawner.vel.y){
|
||||||
|
bullets[i].vel.x = spawner.vel.x;
|
||||||
|
bullets[i].vel.y = spawner.vel.y;
|
||||||
|
if(bullets[i].vel.x > 0 && !bullets[i].player) bullets[i].vel.x = -bullets[i].vel.x;
|
||||||
|
} else {
|
||||||
|
bullets[i].vel.x = fix16Mul(cosFix16(spawner.angle), spawner.speed);
|
||||||
|
bullets[i].vel.y = fix16Mul(sinFix16(spawner.angle), spawner.speed);
|
||||||
|
}
|
||||||
|
bullets[i].updater = updater;
|
||||||
|
bullets[i].image = SPR_addSprite(spawner.image,
|
||||||
|
fix16ToInt(fix16Sub(bullets[i].pos.x, spawner.big ? BULLET_OFF_BIG : BULLET_OFF)),
|
||||||
|
fix16ToInt(fix16Sub(bullets[i].pos.y,spawner.big ? BULLET_OFF_BIG : BULLET_OFF)),
|
||||||
|
TILE_ATTR(PAL1, 0, 0, 0));
|
||||||
|
// SPR_setDepth(bullets[i].image, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void killBullet(s16 i){
|
||||||
|
bullets[i].active = FALSE;
|
||||||
|
SPR_releaseSprite(bullets[i].image);
|
||||||
|
if(bullets[i].dead){
|
||||||
|
// spawnExplosion(bullets[i].pos.x, bullets[i].pos.y, 0);
|
||||||
|
bullets[i].dead = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBulletVel(s16 i){
|
||||||
|
bullets[i].vel.x = fix16Mul(cosFix16(bullets[i].angle), bullets[i].speed);
|
||||||
|
bullets[i].vel.y = fix16Mul(sinFix16(bullets[i].angle), bullets[i].speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// collision
|
||||||
|
|
||||||
|
#define BULLET_LIMIT FIX16(-BULLET_OFF)
|
||||||
|
#define BULLET_LIMIT_W FIX16(GAME_W + BULLET_OFF)
|
||||||
|
#define BULLET_LIMIT_H FIX16(GAME_H + BULLET_OFF)
|
||||||
|
|
||||||
|
#define BULLET_LIMIT_BIG FIX16(-BULLET_OFF_BIG)
|
||||||
|
#define BULLET_LIMIT_W_BIG FIX16(GAME_W + BULLET_OFF_BIG)
|
||||||
|
#define BULLET_LIMIT_H_BIG FIX16(GAME_H + BULLET_OFF_BIG)
|
||||||
|
|
||||||
|
static void collideBullet(s16 i){
|
||||||
|
if(bullets[i].pos.x < (bullets[i].big ? BULLET_LIMIT_BIG : BULLET_LIMIT) ||
|
||||||
|
bullets[i].pos.x > (bullets[i].big ? BULLET_LIMIT_W_BIG : BULLET_LIMIT_W) ||
|
||||||
|
bullets[i].pos.y < (bullets[i].big ? BULLET_LIMIT_BIG : BULLET_LIMIT) ||
|
||||||
|
bullets[i].pos.y > (bullets[i].big ? BULLET_LIMIT_H_BIG : BULLET_LIMIT_H)){
|
||||||
|
killBullet(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// loop
|
||||||
|
|
||||||
|
static void updateBullet(s16 i){
|
||||||
|
bullets[i].pos.x = fix16Add(bullets[i].pos.x, bullets[i].vel.x);
|
||||||
|
bullets[i].pos.y = fix16Add(bullets[i].pos.y, bullets[i].vel.y);
|
||||||
|
bullets[i].updater(i);
|
||||||
|
collideBullet(i);
|
||||||
|
SPR_setPosition(
|
||||||
|
bullets[i].image,
|
||||||
|
fix16ToInt(fix16Sub(bullets[i].pos.x, bullets[i].big ? BULLET_OFF_BIG : BULLET_OFF)),
|
||||||
|
fix16ToInt(fix16Sub(bullets[i].pos.y, bullets[i].big ? BULLET_OFF_BIG : BULLET_OFF)));
|
||||||
|
bullets[i].clock++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBullets(){
|
||||||
|
if(killBullets){
|
||||||
|
for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active){
|
||||||
|
if(i % 4 == 0) bullets[i].dead = TRUE;
|
||||||
|
killBullet(i);
|
||||||
|
}
|
||||||
|
killBullets = FALSE;
|
||||||
|
} else {
|
||||||
|
for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active) updateBullet(i);
|
||||||
|
}
|
||||||
|
}
|
21
src/global.h
|
@ -19,8 +19,27 @@
|
||||||
#define GAME_Y 0
|
#define GAME_Y 0
|
||||||
|
|
||||||
#define CLOCK_LIMIT 32000
|
#define CLOCK_LIMIT 32000
|
||||||
|
#define COUNT_INT 8
|
||||||
|
|
||||||
|
bool killBullets;
|
||||||
|
|
||||||
s16 clock;
|
s16 clock;
|
||||||
|
|
||||||
u32 score,
|
u32 score,
|
||||||
highScore;
|
highScore;
|
||||||
|
|
||||||
|
void EMPTY(s16 i){}
|
||||||
|
|
||||||
|
|
||||||
|
// structs
|
||||||
|
|
||||||
|
struct bulletSpawner {
|
||||||
|
fix16 x, y, speed;
|
||||||
|
Vect2D_f16 vel;
|
||||||
|
s16 angle;
|
||||||
|
Sprite* image;
|
||||||
|
bool big, player;
|
||||||
|
bool bools[COUNT_INT];
|
||||||
|
s16 ints[COUNT_INT];
|
||||||
|
fix16 fixes[COUNT_INT];
|
||||||
|
};
|
|
@ -7,6 +7,7 @@
|
||||||
#include "controls.h"
|
#include "controls.h"
|
||||||
#include "background.h"
|
#include "background.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "bullets.h"
|
||||||
#include "chrome.h"
|
#include "chrome.h"
|
||||||
|
|
||||||
// game loop
|
// game loop
|
||||||
|
@ -30,6 +31,7 @@ static void loadGame(){
|
||||||
|
|
||||||
static void updateGame(){
|
static void updateGame(){
|
||||||
updatePlayer();
|
updatePlayer();
|
||||||
|
updateBullets();
|
||||||
updateBg();
|
updateBg();
|
||||||
updateChrome();
|
updateChrome();
|
||||||
clock++;
|
clock++;
|
||||||
|
|
39
src/player.h
|
@ -4,10 +4,13 @@
|
||||||
#define PLAYER_INIT_X FIX16(40)
|
#define PLAYER_INIT_X FIX16(40)
|
||||||
#define PLAYER_INIT_Y FIX16(GAME_H / 2)
|
#define PLAYER_INIT_Y FIX16(GAME_H / 2)
|
||||||
|
|
||||||
|
#define INVINCIBLE_LIMIT 60 * 4
|
||||||
|
#define SHOT_INTERVAL 15
|
||||||
|
|
||||||
struct playerStruct {
|
struct playerStruct {
|
||||||
Vect2D_f16 pos, vel;
|
Vect2D_f16 pos, vel;
|
||||||
Sprite* image;
|
Sprite* image;
|
||||||
s16 clock;
|
s16 clock, invincibleClock, shotClock;
|
||||||
};
|
};
|
||||||
struct playerStruct player;
|
struct playerStruct player;
|
||||||
|
|
||||||
|
@ -17,6 +20,7 @@ struct playerStruct player;
|
||||||
static void spawnPlayer(){
|
static void spawnPlayer(){
|
||||||
player.pos.x = PLAYER_INIT_X;
|
player.pos.x = PLAYER_INIT_X;
|
||||||
player.pos.y = PLAYER_INIT_Y;
|
player.pos.y = PLAYER_INIT_Y;
|
||||||
|
player.shotClock = SHOT_INTERVAL;
|
||||||
player.image = SPR_addSprite(&nitori,
|
player.image = SPR_addSprite(&nitori,
|
||||||
fix16ToInt(fix16Sub(player.pos.x, PLAYER_OFF)),
|
fix16ToInt(fix16Sub(player.pos.x, PLAYER_OFF)),
|
||||||
fix16ToInt(fix16Sub(player.pos.y, PLAYER_OFF)),
|
fix16ToInt(fix16Sub(player.pos.y, PLAYER_OFF)),
|
||||||
|
@ -40,8 +44,8 @@ static void checkPlayerBounds(){
|
||||||
|
|
||||||
// movement
|
// movement
|
||||||
|
|
||||||
#define PLAYER_SPEED FIX16(2.25)
|
#define PLAYER_SPEED FIX16(2.5)
|
||||||
#define PLAYER_SPEED_NORM FIX16(2.25 * 0.707)
|
#define PLAYER_SPEED_NORM FIX16(2.5 * 0.707)
|
||||||
|
|
||||||
s16 playerFrame;
|
s16 playerFrame;
|
||||||
|
|
||||||
|
@ -74,6 +78,34 @@ static void movePlayer(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// shooting
|
||||||
|
|
||||||
|
// shoot
|
||||||
|
|
||||||
|
#define PLAYER_BULLET_SPEED FIX16(16)
|
||||||
|
#define PLAYER_BULLET_ANGLE 0
|
||||||
|
|
||||||
|
static void spawnPlayerBullet(){
|
||||||
|
struct bulletSpawner spawner = {
|
||||||
|
.x = player.pos.x,
|
||||||
|
.y = player.pos.y,
|
||||||
|
.image = &smallWhiteBullet,
|
||||||
|
.speed = PLAYER_BULLET_SPEED,
|
||||||
|
.angle = PLAYER_BULLET_ANGLE,
|
||||||
|
.player = TRUE
|
||||||
|
};
|
||||||
|
spawnBullet(spawner, EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void shotPlayer(){
|
||||||
|
if(player.shotClock >= SHOT_INTERVAL && ctrl.a) player.shotClock = 0;
|
||||||
|
if(player.shotClock == 0) spawnPlayerBullet();
|
||||||
|
player.shotClock++;
|
||||||
|
if(player.shotClock >= CLOCK_LIMIT) player.shotClock = SHOT_INTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// loop
|
// loop
|
||||||
|
|
||||||
void loadPlayer(){
|
void loadPlayer(){
|
||||||
|
@ -82,6 +114,7 @@ void loadPlayer(){
|
||||||
|
|
||||||
void updatePlayer(){
|
void updatePlayer(){
|
||||||
movePlayer();
|
movePlayer();
|
||||||
|
shotPlayer();
|
||||||
SPR_setPosition(player.image,
|
SPR_setPosition(player.image,
|
||||||
fix16ToInt(fix16Sub(player.pos.x, PLAYER_OFF)),
|
fix16ToInt(fix16Sub(player.pos.x, PLAYER_OFF)),
|
||||||
fix16ToInt(fix16Sub(player.pos.y, PLAYER_OFF)));
|
fix16ToInt(fix16Sub(player.pos.y, PLAYER_OFF)));
|
||||||
|
|