Fixed a bug when rendering the player's remaining number of lives.

This commit is contained in:
2013-08-18 10:58:03 -04:30
parent 42d7007a35
commit a5a8650836

View File

@@ -1,449 +1,450 @@
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
; File : NXTInvaders.nxc ; File : NXTInvaders.nxc
; Description : A Space Invaders clone for the Mindstorms NXT. ; Description : A Space Invaders clone for the Mindstorms NXT.
; Programmed by : Miguel Angel Astor, sonofgrendel@gmail.com ; Programmed by : Miguel Angel Astor, sonofgrendel@gmail.com
; Version: 1.0 ; Version: 1.0
; Date: 8/13/2013 ; Date: 8/13/2013
;-----------------------------------------------------------------------------*/ ;-----------------------------------------------------------------------------*/
#download "ship.ric" #download "ship.ric"
#download "splash.ric" #download "splash.ric"
#download "invader.ric" #download "invader.ric"
#download "victory.ric" #download "victory.ric"
#download "defeat.ric" #download "defeat.ric"
#define X_MAX 99 #define X_MAX 99
#define Y_MAX 63 #define Y_MAX 63
#define X_MID (X_MAX + 1) / 2 #define X_MID (X_MAX + 1) / 2
#define Y_MID (Y_MAX + 1) / 2 #define Y_MID (Y_MAX + 1) / 2
#define DRAW_PARAMS DRAW_OPT_NORMAL | DRAW_OPT_LOGICAL_XOR | DRAW_OPT_FILL_SHAPE #define DRAW_PARAMS DRAW_OPT_NORMAL | DRAW_OPT_LOGICAL_XOR | DRAW_OPT_FILL_SHAPE
#define ALIEN_WIDTH 11 #define ALIEN_WIDTH 11
#define BASE_ALIEN_X 2 #define BASE_ALIEN_X 2
#define BASE_ALIEN_Y 32 #define BASE_ALIEN_Y 32
#define ALIENS 6 #define ALIENS 6
/******************* /*******************
* Data structures * * Data structures *
*******************/ *******************/
struct PLAYER_T{ struct PLAYER_T{
int x; int x;
int lives; int lives;
int score; int score;
}; };
struct BULLET_T{ struct BULLET_T{
int x, y; int x, y;
bool alive; bool alive;
}; };
struct ALIEN_T{ struct ALIEN_T{
int x, y; int x, y;
bool alive; bool alive;
}; };
/**************** /****************
* Global data. * * Global data. *
****************/ ****************/
const int alien_update_speed[] = {50, 72, 95, const int alien_update_speed[] = {50, 72, 95,
118, 140, 163, 118, 140, 163,
186, 209, 231, 186, 209, 231,
254, 277, 300 }; 254, 277, 300 };
int dead_aliens; int dead_aliens;
bool victory; bool victory;
// keys[0] -> Left button; keys[1] -> Right button; keys[2] -> Center button. // keys[0] -> Left button; keys[1] -> Right button; keys[2] -> Center button.
bool keys[3]; bool keys[3];
// State: 0 -> Splash screen; 1 -> Game; 2 -> Hall of fame screen. // State: 0 -> Splash screen; 1 -> Game; 2 -> Hall of fame screen.
int state, alien_frame, alien_x_offset; int state, alien_frame, alien_x_offset;
bool alien_x_forward, done; bool alien_x_forward, done;
long then, then2; long then, then2;
PLAYER_T player; PLAYER_T player;
BULLET_T p_bullets[3]; BULLET_T p_bullets[3];
ALIEN_T aliens1[ALIENS]; ALIEN_T aliens1[ALIENS];
ALIEN_T aliens2[ALIENS]; ALIEN_T aliens2[ALIENS];
BULLET_T a_bullets1[ALIENS]; BULLET_T a_bullets1[ALIENS];
BULLET_T a_bullets2[ALIENS]; BULLET_T a_bullets2[ALIENS];
/******************* /*******************
* Game functions. * * Game functions. *
*******************/ *******************/
/** /**
* Catch the 3 possible player inputs. * Catch the 3 possible player inputs.
*/ */
void input(){ void input(){
if(ButtonPressed(BTNLEFT, false)){ if(ButtonPressed(BTNLEFT, false)){
keys[0] = true; keys[0] = true;
}else{ }else{
keys[0] = false; keys[0] = false;
} }
if(ButtonPressed(BTNRIGHT, false)){ if(ButtonPressed(BTNRIGHT, false)){
keys[1] = true; keys[1] = true;
}else{ }else{
keys[1] = false; keys[1] = false;
} }
if(ButtonPressed(BTNCENTER, false)){ if(ButtonPressed(BTNCENTER, false)){
keys[2] = true; keys[2] = true;
}else{ }else{
keys[2] = false; keys[2] = false;
} }
} }
/** /**
* Processes player input, moves game objects and updates the game's state. * Processes player input, moves game objects and updates the game's state.
*/ */
void update(){ void update(){
long now, delta_t, fire; long now, delta_t, fire;
if(state == 0){ if(state == 0){
if(keys[2]){ if(keys[2]){
state = 1; state = 1;
} }
}else if(state == 1){ }else if(state == 1){
// Move the player. // Move the player.
if(keys[0]){ if(keys[0]){
if(player.x - 1 >= 3){ if(player.x - 1 >= 3){
player.x -= 1; player.x -= 1;
} }
} }
if(keys[1]){ if(keys[1]){
if(player.x + 1 <= X_MAX - 4){ if(player.x + 1 <= X_MAX - 4){
player.x += 1; player.x += 1;
} }
} }
// If the center button was pressed, fire a bullet. // If the center button was pressed, fire a bullet.
if(keys[2]){ if(keys[2]){
now = CurrentTick(); now = CurrentTick();
delta_t = now - then; delta_t = now - then;
if(delta_t >= 500){ if(delta_t >= 500){
// One bullet every 500 miliseconds. // One bullet every 500 miliseconds.
for(int i = 0; i < 3; i++){ for(int i = 0; i < 3; i++){
if(!p_bullets[i].alive){ if(!p_bullets[i].alive){
p_bullets[i].x = player.x; p_bullets[i].x = player.x;
p_bullets[i].y = 0; p_bullets[i].y = 0;
p_bullets[i].alive = true; p_bullets[i].alive = true;
PlayTone(262, 100); PlayTone(262, 100);
break; break;
} }
} }
then = now; then = now;
} }
} }
// Update the player's bullets. // Update the player's bullets.
for(int i = 0; i < 3; i++){ for(int i = 0; i < 3; i++){
if(p_bullets[i].alive){ if(p_bullets[i].alive){
p_bullets[i].y += 1; p_bullets[i].y += 1;
if(p_bullets[i].y >= Y_MAX + 2){ if(p_bullets[i].y >= Y_MAX + 2){
p_bullets[i].alive = false; p_bullets[i].alive = false;
} }
} }
} }
// Update the aliens. // Update the aliens.
now = CurrentTick(); now = CurrentTick();
delta_t = now - then2; delta_t = now - then2;
if(delta_t >= alien_update_speed[11 - dead_aliens]){ if(delta_t >= alien_update_speed[11 - dead_aliens]){
// Change the frame. // Change the frame.
if(alien_frame == 0){ if(alien_frame == 0){
alien_frame = 11; alien_frame = 11;
}else{ }else{
alien_frame = 0; alien_frame = 0;
} }
// Move in the correct direction. // Move in the correct direction.
if(alien_x_forward){ if(alien_x_forward){
alien_x_offset += 1; alien_x_offset += 1;
if(alien_x_offset >= 15){ if(alien_x_offset >= 15){
// Change direction 2 pixels before the edge of the screen. // Change direction 2 pixels before the edge of the screen.
alien_x_offset -= 1; alien_x_offset -= 1;
alien_x_forward = false; alien_x_forward = false;
} }
}else{ }else{
alien_x_offset -= 1; alien_x_offset -= 1;
if(alien_x_offset <= 0){ if(alien_x_offset <= 0){
// Change direction 2 pixels before the edge of the screen. // Change direction 2 pixels before the edge of the screen.
alien_x_offset += 1; alien_x_offset += 1;
alien_x_forward = true; alien_x_forward = true;
} }
} }
// Fire on the player. // Fire on the player.
for(int i = 0; i < ALIENS; i++){ for(int i = 0; i < ALIENS; i++){
// First row. // First row.
if(aliens1[i].alive && !a_bullets1[i].alive){ if(aliens1[i].alive && !a_bullets1[i].alive){
fire = rand() % 100; fire = rand() % 100;
if(fire < 25){ if(fire < 25){
// 0.25 probability of firing. // 0.25 probability of firing.
a_bullets1[i].alive = true; a_bullets1[i].alive = true;
a_bullets1[i].x = aliens1[i].x + alien_x_offset + 5; a_bullets1[i].x = aliens1[i].x + alien_x_offset + 5;
a_bullets1[i].y = aliens1[i].y; a_bullets1[i].y = aliens1[i].y;
PlayTone(400, 100); PlayTone(400, 100);
} }
} }
// Second row. // Second row.
if(aliens2[i].alive && !a_bullets2[i].alive){ if(aliens2[i].alive && !a_bullets2[i].alive){
fire = rand() % 100; fire = rand() % 100;
if(fire > 75){ if(fire > 75){
// 0.25 probability of firing. // 0.25 probability of firing.
a_bullets2[i].alive = true; a_bullets2[i].alive = true;
a_bullets2[i].x = aliens2[i].x + alien_x_offset + 5; a_bullets2[i].x = aliens2[i].x + alien_x_offset + 5;
a_bullets2[i].y = aliens2[i].y; a_bullets2[i].y = aliens2[i].y;
PlayTone(400, 100); PlayTone(400, 100);
} }
} }
} }
then2 = now; then2 = now;
} }
// Update the alien's bullets. // Update the alien's bullets.
for(int i = 0; i < ALIENS; i++){ for(int i = 0; i < ALIENS; i++){
// First row. // First row.
if(a_bullets1[i].alive){ if(a_bullets1[i].alive){
a_bullets1[i].y -= 1; a_bullets1[i].y -= 1;
if(a_bullets1[i].y < -2){ if(a_bullets1[i].y < -2){
a_bullets1[i].alive = false; a_bullets1[i].alive = false;
} }
} }
// Second row. // Second row.
if(a_bullets2[i].alive){ if(a_bullets2[i].alive){
a_bullets2[i].y -= 1; a_bullets2[i].y -= 1;
if(a_bullets2[i].y < -2){ if(a_bullets2[i].y < -2){
a_bullets2[i].alive = false; a_bullets2[i].alive = false;
} }
} }
} }
// Check if any bullet shot by the player hit an alien. // Check if any bullet shot by the player hit an alien.
for(int i = 0; i < 3; i++){ for(int i = 0; i < 3; i++){
if(p_bullets[i].alive){ if(p_bullets[i].alive){
if(p_bullets[i].y >= 22 && p_bullets[i].y <= 30){ if(p_bullets[i].y >= 22 && p_bullets[i].y <= 30){
// Check the second row first. // Check the second row first.
for(int j = 0; j < ALIENS; j++){ for(int j = 0; j < ALIENS; j++){
if(aliens2[j].alive){ if(aliens2[j].alive){
if(p_bullets[i].x >= aliens2[j].x + alien_x_offset && if(p_bullets[i].x >= aliens2[j].x + alien_x_offset &&
p_bullets[i].x <= aliens2[j].x + alien_x_offset + 11){ p_bullets[i].x <= aliens2[j].x + alien_x_offset + 11){
aliens2[j].alive = false; aliens2[j].alive = false;
p_bullets[i].alive = false; p_bullets[i].alive = false;
player.score += 100; player.score += 100;
dead_aliens += 1; dead_aliens += 1;
PlayTone(100, 250); PlayTone(100, 250);
break; break;
} }
} }
} }
}else if(p_bullets[i].y >= 32 && p_bullets[i].y <= 40){ }else if(p_bullets[i].y >= 32 && p_bullets[i].y <= 40){
// Check the first row last. // Check the first row last.
for(int j = 0; j < ALIENS; j++){ for(int j = 0; j < ALIENS; j++){
if(aliens1[j].alive){ if(aliens1[j].alive){
if(p_bullets[i].x >= aliens1[j].x + alien_x_offset && if(p_bullets[i].x >= aliens1[j].x + alien_x_offset &&
p_bullets[i].x <= aliens1[j].x + alien_x_offset + 11){ p_bullets[i].x <= aliens1[j].x + alien_x_offset + 11){
aliens1[j].alive = false; aliens1[j].alive = false;
p_bullets[i].alive = false; p_bullets[i].alive = false;
player.score += 150; player.score += 150;
dead_aliens += 1; dead_aliens += 1;
PlayTone(100, 250); PlayTone(100, 250);
break; break;
} }
} }
} }
} }
} }
} }
// Check alien bullet collisions with player. // Check alien bullet collisions with player.
// First row. // First row.
for(int i = 0; i < ALIENS; i++){ for(int i = 0; i < ALIENS; i++){
if(a_bullets1[i].alive && a_bullets1[i].y <= 2){ if(a_bullets1[i].alive && a_bullets1[i].y <= 2){
if(a_bullets1[i].x >= player.x - 3 && a_bullets1[i].x <= player.x + 4){ if(a_bullets1[i].x >= player.x - 3 && a_bullets1[i].x <= player.x + 4){
// If the bullet hit the player, reset the game. // If the bullet hit the player, reset the game.
player.x = X_MID; player.x = X_MID;
player.lives -= 1; player.lives -= 1;
alien_x_offset = 0; alien_x_offset = 0;
alien_x_forward = true; alien_x_forward = true;
for(int j = 0; j < ALIENS; j++){ for(int j = 0; j < ALIENS; j++){
a_bullets1[i].alive = false; a_bullets1[i].alive = false;
a_bullets2[i].alive = false; a_bullets2[i].alive = false;
} }
PlayTone(100, 250); PlayTone(100, 250);
break; break;
} }
} }
} }
// Second row // Second row
for(int i = 0; i < ALIENS; i++){ for(int i = 0; i < ALIENS; i++){
if(a_bullets2[i].alive && a_bullets2[i].y <= 2){ if(a_bullets2[i].alive && a_bullets2[i].y <= 2){
if(a_bullets2[i].x >= player.x - 3 && a_bullets2[i].x <= player.x + 4){ if(a_bullets2[i].x >= player.x - 3 && a_bullets2[i].x <= player.x + 4){
// If the bullet hit the player, reset the game. // If the bullet hit the player, reset the game.
player.x = X_MID; player.x = X_MID;
player.lives -= 1; player.lives -= 1;
alien_x_offset = 0; alien_x_offset = 0;
alien_x_forward = true; alien_x_forward = true;
for(int j = 0; j < ALIENS; j++){ for(int j = 0; j < ALIENS; j++){
a_bullets1[i].alive = false; a_bullets1[i].alive = false;
a_bullets2[i].alive = false; a_bullets2[i].alive = false;
} }
PlayTone(100, 250); PlayTone(100, 250);
break; break;
} }
} }
} }
// Check victory/defeat conditions. // Check victory/defeat conditions.
if(dead_aliens == 12){ if(dead_aliens == 12){
state = 2; state = 2;
victory = true; victory = true;
PlayTone(500, 1000); PlayTone(500, 1000);
ClearScreen(); ClearScreen();
}else if(player.lives < 0){ }else if(player.lives < 0){
state = 2; state = 2;
victory = false; victory = false;
PlayTone(100, 1000); PlayTone(100, 1000);
ClearScreen(); ClearScreen();
} }
}else{ }else{
if(keys[2]){ if(keys[2]){
done = true; done = true;
} }
} }
} }
/** /**
* Draws all game objects to the LCD screen of the robot. * Draws all game objects to the LCD screen of the robot.
*/ */
void render(){ void render(){
int params[3] = {0, 0, 0}; int params[3] = {0, 0, 0};
if(state == 0){ if(state == 0){
// Render the splash screen. // Render the splash screen.
GraphicOut(0, 0, "splash.ric"); GraphicOut(0, 0, "splash.ric");
}else if(state == 1){ }else if(state == 1){
ClearScreen(); ClearScreen();
// Render informative text. // Render informative text.
TextOut(0, LCD_LINE1, "LIVES:"); TextOut(0, LCD_LINE1, "LIVES:");
//NumOut(35, LCD_LINE1, player.lives); params[0] = 35;
params[0] = 35; if(player.lives > 0){
GraphicOutEx(0, LCD_LINE1 + 1, "ship.ric", params); GraphicOutEx(0, LCD_LINE1 + 1, "ship.ric", params);
if(player.lives > 1){ if(player.lives > 1){
params[0] = 44; params[0] = 44;
GraphicOutEx(0, LCD_LINE1 + 1, "ship.ric", params); GraphicOutEx(0, LCD_LINE1 + 1, "ship.ric", params);
if(player.lives > 2){ if(player.lives > 2){
params[0] = 53; params[0] = 53;
GraphicOutEx(0, LCD_LINE1 + 1, "ship.ric", params); GraphicOutEx(0, LCD_LINE1 + 1, "ship.ric", params);
} }
} }
TextOut(0, LCD_LINE2, "SCORE:"); }
NumOut(35, LCD_LINE2, player.score); TextOut(0, LCD_LINE2, "SCORE:");
NumOut(35, LCD_LINE2, player.score);
// Render the player's sprite.
params[0] = player.x - 3; // Render the player's sprite.
GraphicOutEx(0, 0, "ship.ric", params); params[0] = player.x - 3;
GraphicOutEx(0, 0, "ship.ric", params);
// Render the player's bullets.
for(int i = 0; i < 3; i++){ // Render the player's bullets.
if(p_bullets[i].alive){ for(int i = 0; i < 3; i++){
RectOut(p_bullets[i].x, p_bullets[i].y, 0, 2, DRAW_PARAMS); if(p_bullets[i].alive){
} RectOut(p_bullets[i].x, p_bullets[i].y, 0, 2, DRAW_PARAMS);
} }
}
// Render the aliens.
for(int i = 0; i < ALIENS; i++){ // Render the aliens.
if(aliens1[i].alive){ for(int i = 0; i < ALIENS; i++){
// First row. if(aliens1[i].alive){
params[0] = alien_frame; // First row.
params[1] = aliens1[i].x + alien_x_offset; params[0] = alien_frame;
params[2] = aliens1[i].y; params[1] = aliens1[i].x + alien_x_offset;
GraphicOutEx(0, 0, "invader.ric", params); params[2] = aliens1[i].y;
} GraphicOutEx(0, 0, "invader.ric", params);
if(aliens2[i].alive){ }
// Second row. if(aliens2[i].alive){
params[0] = alien_frame; // Second row.
params[1] = aliens2[i].x + alien_x_offset; params[0] = alien_frame;
params[2] = aliens2[i].y; params[1] = aliens2[i].x + alien_x_offset;
GraphicOutEx(0, 0, "invader.ric", params); params[2] = aliens2[i].y;
} GraphicOutEx(0, 0, "invader.ric", params);
} }
}
// Render the aliens's bullets.
for(int i = 0; i < ALIENS; i++){ // Render the aliens's bullets.
if(a_bullets1[i].alive){ for(int i = 0; i < ALIENS; i++){
RectOut(a_bullets1[i].x, a_bullets1[i].y, 0, 2, DRAW_PARAMS); if(a_bullets1[i].alive){
} RectOut(a_bullets1[i].x, a_bullets1[i].y, 0, 2, DRAW_PARAMS);
if(a_bullets2[i].alive){ }
RectOut(a_bullets2[i].x, a_bullets2[i].y, 0, 2, DRAW_PARAMS); if(a_bullets2[i].alive){
} RectOut(a_bullets2[i].x, a_bullets2[i].y, 0, 2, DRAW_PARAMS);
} }
}else{ }
// Render the hall of fame. }else{
if(victory){ // Render the hall of fame.
params[0] = player.score; if(victory){
GraphicOutEx(0, 0, "victory.ric", params); params[0] = player.score;
}else{ GraphicOutEx(0, 0, "victory.ric", params);
GraphicOut(0, 0, "defeat.ric"); }else{
} GraphicOut(0, 0, "defeat.ric");
} }
} }
}
/**
* The heart of the game. /**
*/ * The heart of the game.
void game_loop(){ */
while(!done){ void game_loop(){
input(); while(!done){
update(); input();
render(); update();
Wait(50); render();
} Wait(50);
} }
}
/**
* Initializes all game data and call the game loop. /**
*/ * Initializes all game data and call the game loop.
task main(){ */
// Initialize game data. task main(){
state = 0; // Initialize game data.
done = false; state = 0;
alien_frame = 0; done = false;
alien_x_offset = 0; alien_frame = 0;
alien_x_forward = true; alien_x_offset = 0;
alien_x_forward = true;
// Initialize the player and bullets.
player.x = X_MID; // Initialize the player and bullets.
player.lives = 3; player.x = X_MID;
player.score = 0; player.lives = 3;
player.score = 0;
for(int i = 0; i < 3; i++){
p_bullets[i].x = 0; for(int i = 0; i < 3; i++){
p_bullets[i].y = 0; p_bullets[i].x = 0;
p_bullets[i].alive = false; p_bullets[i].y = 0;
} p_bullets[i].alive = false;
}
// Initialize the aliens.
dead_aliens = 0; // Initialize the aliens.
for(int i = 0; i < ALIENS; i++){ dead_aliens = 0;
// First row. for(int i = 0; i < ALIENS; i++){
aliens1[i].x = BASE_ALIEN_X + (i * 14); // First row.
aliens1[i].y = BASE_ALIEN_Y; aliens1[i].x = BASE_ALIEN_X + (i * 14);
aliens1[i].alive = true; aliens1[i].y = BASE_ALIEN_Y;
// Second row. aliens1[i].alive = true;
aliens2[i].x = BASE_ALIEN_X + (i * 14); // Second row.
aliens2[i].y = BASE_ALIEN_Y - 10; aliens2[i].x = BASE_ALIEN_X + (i * 14);
aliens2[i].alive = true; aliens2[i].y = BASE_ALIEN_Y - 10;
// Alien bullets, first row. aliens2[i].alive = true;
a_bullets1[i].x = 0; // Alien bullets, first row.
a_bullets1[i].y = 0; a_bullets1[i].x = 0;
a_bullets1[i].alive = false; a_bullets1[i].y = 0;
// Second row. a_bullets1[i].alive = false;
a_bullets2[i].x = 0; // Second row.
a_bullets2[i].y = 0; a_bullets2[i].x = 0;
a_bullets2[i].alive = false; a_bullets2[i].y = 0;
} a_bullets2[i].alive = false;
}
// Initialize time variables.
then = CurrentTick(); // Initialize time variables.
then2 = CurrentTick(); then = CurrentTick();
then2 = CurrentTick();
// Start the game!
PlayTone(500, 1000); // Start the game!
game_loop(); PlayTone(500, 1000);
} game_loop();
}