Added code and data files.
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Ignore NXT executable files, RIC edit data and Gedit backup files.
|
||||
*.rxe
|
||||
*.RPA
|
||||
*~
|
25
LICENSE
25
LICENSE
@@ -0,0 +1,25 @@
|
||||
A Space Invaders clone for the Mindstorms NXT.
|
||||
|
||||
Copyright (c) 2013, Miguel Angel Astor Romero
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
*) Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following disclaimer.
|
||||
*) Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITSOR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
5
Makefile
Normal file
5
Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
all: NXTInvaders.nxc
|
||||
nbc NXTInvaders.nxc -O=NXTInvaders.rxe -sm+ -d -S=usb
|
||||
|
||||
clean:
|
||||
rm -f NXTInvaders.rxe
|
449
NXTInvaders.nxc
Normal file
449
NXTInvaders.nxc
Normal file
@@ -0,0 +1,449 @@
|
||||
/*------------------------------------------------------------------------------
|
||||
; File : NXTInvaders.nxc
|
||||
; Description : A Space Invaders clone for the Mindstorms NXT.
|
||||
; Programmed by : Miguel Angel Astor, sonofgrendel@gmail.com
|
||||
; Version: 1.0
|
||||
; Date: 8/13/2013
|
||||
;-----------------------------------------------------------------------------*/
|
||||
|
||||
#download "ship.ric"
|
||||
#download "splash.ric"
|
||||
#download "invader.ric"
|
||||
#download "victory.ric"
|
||||
#download "defeat.ric"
|
||||
#define X_MAX 99
|
||||
#define Y_MAX 63
|
||||
#define X_MID (X_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 ALIEN_WIDTH 11
|
||||
#define BASE_ALIEN_X 2
|
||||
#define BASE_ALIEN_Y 32
|
||||
#define ALIENS 6
|
||||
|
||||
/*******************
|
||||
* Data structures *
|
||||
*******************/
|
||||
struct PLAYER_T{
|
||||
int x;
|
||||
int lives;
|
||||
int score;
|
||||
};
|
||||
|
||||
struct BULLET_T{
|
||||
int x, y;
|
||||
bool alive;
|
||||
};
|
||||
|
||||
struct ALIEN_T{
|
||||
int x, y;
|
||||
bool alive;
|
||||
};
|
||||
|
||||
/****************
|
||||
* Global data. *
|
||||
****************/
|
||||
const int alien_update_speed[] = {50, 72, 95,
|
||||
118, 140, 163,
|
||||
186, 209, 231,
|
||||
254, 277, 300 };
|
||||
int dead_aliens;
|
||||
bool victory;
|
||||
// keys[0] -> Left button; keys[1] -> Right button; keys[2] -> Center button.
|
||||
bool keys[3];
|
||||
// State: 0 -> Splash screen; 1 -> Game; 2 -> Hall of fame screen.
|
||||
int state, alien_frame, alien_x_offset;
|
||||
bool alien_x_forward, done;
|
||||
long then, then2;
|
||||
PLAYER_T player;
|
||||
BULLET_T p_bullets[3];
|
||||
ALIEN_T aliens1[ALIENS];
|
||||
ALIEN_T aliens2[ALIENS];
|
||||
BULLET_T a_bullets1[ALIENS];
|
||||
BULLET_T a_bullets2[ALIENS];
|
||||
|
||||
/*******************
|
||||
* Game functions. *
|
||||
*******************/
|
||||
/**
|
||||
* Catch the 3 possible player inputs.
|
||||
*/
|
||||
void input(){
|
||||
if(ButtonPressed(BTNLEFT, false)){
|
||||
keys[0] = true;
|
||||
}else{
|
||||
keys[0] = false;
|
||||
}
|
||||
|
||||
if(ButtonPressed(BTNRIGHT, false)){
|
||||
keys[1] = true;
|
||||
}else{
|
||||
keys[1] = false;
|
||||
}
|
||||
|
||||
if(ButtonPressed(BTNCENTER, false)){
|
||||
keys[2] = true;
|
||||
}else{
|
||||
keys[2] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes player input, moves game objects and updates the game's state.
|
||||
*/
|
||||
void update(){
|
||||
long now, delta_t, fire;
|
||||
|
||||
if(state == 0){
|
||||
if(keys[2]){
|
||||
state = 1;
|
||||
}
|
||||
}else if(state == 1){
|
||||
// Move the player.
|
||||
if(keys[0]){
|
||||
if(player.x - 1 >= 3){
|
||||
player.x -= 1;
|
||||
}
|
||||
}
|
||||
if(keys[1]){
|
||||
if(player.x + 1 <= X_MAX - 4){
|
||||
player.x += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If the center button was pressed, fire a bullet.
|
||||
if(keys[2]){
|
||||
now = CurrentTick();
|
||||
delta_t = now - then;
|
||||
if(delta_t >= 500){
|
||||
// One bullet every 500 miliseconds.
|
||||
for(int i = 0; i < 3; i++){
|
||||
if(!p_bullets[i].alive){
|
||||
p_bullets[i].x = player.x;
|
||||
p_bullets[i].y = 0;
|
||||
p_bullets[i].alive = true;
|
||||
PlayTone(262, 100);
|
||||
break;
|
||||
}
|
||||
}
|
||||
then = now;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the player's bullets.
|
||||
for(int i = 0; i < 3; i++){
|
||||
if(p_bullets[i].alive){
|
||||
p_bullets[i].y += 1;
|
||||
if(p_bullets[i].y >= Y_MAX + 2){
|
||||
p_bullets[i].alive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the aliens.
|
||||
now = CurrentTick();
|
||||
delta_t = now - then2;
|
||||
if(delta_t >= alien_update_speed[11 - dead_aliens]){
|
||||
// Change the frame.
|
||||
if(alien_frame == 0){
|
||||
alien_frame = 11;
|
||||
}else{
|
||||
alien_frame = 0;
|
||||
}
|
||||
|
||||
// Move in the correct direction.
|
||||
if(alien_x_forward){
|
||||
alien_x_offset += 1;
|
||||
if(alien_x_offset >= 15){
|
||||
// Change direction 2 pixels before the edge of the screen.
|
||||
alien_x_offset -= 1;
|
||||
alien_x_forward = false;
|
||||
}
|
||||
}else{
|
||||
alien_x_offset -= 1;
|
||||
if(alien_x_offset <= 0){
|
||||
// Change direction 2 pixels before the edge of the screen.
|
||||
alien_x_offset += 1;
|
||||
alien_x_forward = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Fire on the player.
|
||||
for(int i = 0; i < ALIENS; i++){
|
||||
// First row.
|
||||
if(aliens1[i].alive && !a_bullets1[i].alive){
|
||||
fire = rand() % 100;
|
||||
if(fire < 25){
|
||||
// 0.25 probability of firing.
|
||||
a_bullets1[i].alive = true;
|
||||
a_bullets1[i].x = aliens1[i].x + alien_x_offset + 5;
|
||||
a_bullets1[i].y = aliens1[i].y;
|
||||
PlayTone(400, 100);
|
||||
}
|
||||
}
|
||||
// Second row.
|
||||
if(aliens2[i].alive && !a_bullets2[i].alive){
|
||||
fire = rand() % 100;
|
||||
if(fire > 75){
|
||||
// 0.25 probability of firing.
|
||||
a_bullets2[i].alive = true;
|
||||
a_bullets2[i].x = aliens2[i].x + alien_x_offset + 5;
|
||||
a_bullets2[i].y = aliens2[i].y;
|
||||
PlayTone(400, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
then2 = now;
|
||||
}
|
||||
|
||||
// Update the alien's bullets.
|
||||
for(int i = 0; i < ALIENS; i++){
|
||||
// First row.
|
||||
if(a_bullets1[i].alive){
|
||||
a_bullets1[i].y -= 1;
|
||||
if(a_bullets1[i].y < -2){
|
||||
a_bullets1[i].alive = false;
|
||||
}
|
||||
}
|
||||
// Second row.
|
||||
if(a_bullets2[i].alive){
|
||||
a_bullets2[i].y -= 1;
|
||||
if(a_bullets2[i].y < -2){
|
||||
a_bullets2[i].alive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any bullet shot by the player hit an alien.
|
||||
for(int i = 0; i < 3; i++){
|
||||
if(p_bullets[i].alive){
|
||||
if(p_bullets[i].y >= 22 && p_bullets[i].y <= 30){
|
||||
// Check the second row first.
|
||||
for(int j = 0; j < ALIENS; j++){
|
||||
if(aliens2[j].alive){
|
||||
if(p_bullets[i].x >= aliens2[j].x + alien_x_offset &&
|
||||
p_bullets[i].x <= aliens2[j].x + alien_x_offset + 11){
|
||||
aliens2[j].alive = false;
|
||||
p_bullets[i].alive = false;
|
||||
player.score += 100;
|
||||
dead_aliens += 1;
|
||||
PlayTone(100, 250);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if(p_bullets[i].y >= 32 && p_bullets[i].y <= 40){
|
||||
// Check the first row last.
|
||||
for(int j = 0; j < ALIENS; j++){
|
||||
if(aliens1[j].alive){
|
||||
if(p_bullets[i].x >= aliens1[j].x + alien_x_offset &&
|
||||
p_bullets[i].x <= aliens1[j].x + alien_x_offset + 11){
|
||||
aliens1[j].alive = false;
|
||||
p_bullets[i].alive = false;
|
||||
player.score += 150;
|
||||
dead_aliens += 1;
|
||||
PlayTone(100, 250);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check alien bullet collisions with player.
|
||||
// First row.
|
||||
for(int i = 0; i < ALIENS; i++){
|
||||
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 the bullet hit the player, reset the game.
|
||||
player.x = X_MID;
|
||||
player.lives -= 1;
|
||||
alien_x_offset = 0;
|
||||
alien_x_forward = true;
|
||||
for(int j = 0; j < ALIENS; j++){
|
||||
a_bullets1[i].alive = false;
|
||||
a_bullets2[i].alive = false;
|
||||
}
|
||||
PlayTone(100, 250);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second row
|
||||
for(int i = 0; i < ALIENS; i++){
|
||||
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 the bullet hit the player, reset the game.
|
||||
player.x = X_MID;
|
||||
player.lives -= 1;
|
||||
alien_x_offset = 0;
|
||||
alien_x_forward = true;
|
||||
for(int j = 0; j < ALIENS; j++){
|
||||
a_bullets1[i].alive = false;
|
||||
a_bullets2[i].alive = false;
|
||||
}
|
||||
PlayTone(100, 250);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check victory/defeat conditions.
|
||||
if(dead_aliens == 12){
|
||||
state = 2;
|
||||
victory = true;
|
||||
PlayTone(500, 1000);
|
||||
ClearScreen();
|
||||
}else if(player.lives < 0){
|
||||
state = 2;
|
||||
victory = false;
|
||||
PlayTone(100, 1000);
|
||||
ClearScreen();
|
||||
}
|
||||
}else{
|
||||
if(keys[2]){
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws all game objects to the LCD screen of the robot.
|
||||
*/
|
||||
void render(){
|
||||
int params[3] = {0, 0, 0};
|
||||
if(state == 0){
|
||||
// Render the splash screen.
|
||||
GraphicOut(0, 0, "splash.ric");
|
||||
}else if(state == 1){
|
||||
ClearScreen();
|
||||
// Render informative text.
|
||||
TextOut(0, LCD_LINE1, "LIVES:");
|
||||
//NumOut(35, LCD_LINE1, player.lives);
|
||||
params[0] = 35;
|
||||
GraphicOutEx(0, LCD_LINE1 + 1, "ship.ric", params);
|
||||
if(player.lives > 1){
|
||||
params[0] = 44;
|
||||
GraphicOutEx(0, LCD_LINE1 + 1, "ship.ric", params);
|
||||
if(player.lives > 2){
|
||||
params[0] = 53;
|
||||
GraphicOutEx(0, LCD_LINE1 + 1, "ship.ric", params);
|
||||
}
|
||||
}
|
||||
TextOut(0, LCD_LINE2, "SCORE:");
|
||||
NumOut(35, LCD_LINE2, player.score);
|
||||
|
||||
// Render the player's sprite.
|
||||
params[0] = player.x - 3;
|
||||
GraphicOutEx(0, 0, "ship.ric", params);
|
||||
|
||||
// Render the player's bullets.
|
||||
for(int i = 0; i < 3; i++){
|
||||
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++){
|
||||
if(aliens1[i].alive){
|
||||
// First row.
|
||||
params[0] = alien_frame;
|
||||
params[1] = aliens1[i].x + alien_x_offset;
|
||||
params[2] = aliens1[i].y;
|
||||
GraphicOutEx(0, 0, "invader.ric", params);
|
||||
}
|
||||
if(aliens2[i].alive){
|
||||
// Second row.
|
||||
params[0] = alien_frame;
|
||||
params[1] = aliens2[i].x + alien_x_offset;
|
||||
params[2] = aliens2[i].y;
|
||||
GraphicOutEx(0, 0, "invader.ric", params);
|
||||
}
|
||||
}
|
||||
|
||||
// Render the aliens's bullets.
|
||||
for(int i = 0; i < ALIENS; i++){
|
||||
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);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// Render the hall of fame.
|
||||
if(victory){
|
||||
params[0] = player.score;
|
||||
GraphicOutEx(0, 0, "victory.ric", params);
|
||||
}else{
|
||||
GraphicOut(0, 0, "defeat.ric");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The heart of the game.
|
||||
*/
|
||||
void game_loop(){
|
||||
while(!done){
|
||||
input();
|
||||
update();
|
||||
render();
|
||||
Wait(50);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes all game data and call the game loop.
|
||||
*/
|
||||
task main(){
|
||||
// Initialize game data.
|
||||
state = 0;
|
||||
done = false;
|
||||
alien_frame = 0;
|
||||
alien_x_offset = 0;
|
||||
alien_x_forward = true;
|
||||
|
||||
// Initialize the player and bullets.
|
||||
player.x = X_MID;
|
||||
player.lives = 3;
|
||||
player.score = 0;
|
||||
|
||||
for(int i = 0; i < 3; i++){
|
||||
p_bullets[i].x = 0;
|
||||
p_bullets[i].y = 0;
|
||||
p_bullets[i].alive = false;
|
||||
}
|
||||
|
||||
// Initialize the aliens.
|
||||
dead_aliens = 0;
|
||||
for(int i = 0; i < ALIENS; i++){
|
||||
// First row.
|
||||
aliens1[i].x = BASE_ALIEN_X + (i * 14);
|
||||
aliens1[i].y = BASE_ALIEN_Y;
|
||||
aliens1[i].alive = true;
|
||||
// Second row.
|
||||
aliens2[i].x = BASE_ALIEN_X + (i * 14);
|
||||
aliens2[i].y = BASE_ALIEN_Y - 10;
|
||||
aliens2[i].alive = true;
|
||||
// Alien bullets, first row.
|
||||
a_bullets1[i].x = 0;
|
||||
a_bullets1[i].y = 0;
|
||||
a_bullets1[i].alive = false;
|
||||
// Second row.
|
||||
a_bullets2[i].x = 0;
|
||||
a_bullets2[i].y = 0;
|
||||
a_bullets2[i].alive = false;
|
||||
}
|
||||
|
||||
// Initialize time variables.
|
||||
then = CurrentTick();
|
||||
then2 = CurrentTick();
|
||||
|
||||
// Start the game!
|
||||
PlayTone(500, 1000);
|
||||
game_loop();
|
||||
}
|
@@ -1,4 +1,8 @@
|
||||
NXTInvaders
|
||||
===========
|
||||
|
||||
An Space Invaders clone for the Lego Mindstorms NXT
|
||||
A Space Invaders clone for the Lego Mindstorms NXT.
|
||||
|
||||
This game is written in the NXC language. To compile on Windows use the BricxCC
|
||||
IDE avaliable at http://bricxcc.sourceforge.net/nbc/. On Linux systems install
|
||||
the NBC compiler available on the same page and run make.
|
||||
|
BIN
defeat.ric
Normal file
BIN
defeat.ric
Normal file
Binary file not shown.
BIN
invader.ric
Normal file
BIN
invader.ric
Normal file
Binary file not shown.
BIN
splash.ric
Normal file
BIN
splash.ric
Normal file
Binary file not shown.
BIN
victory.ric
Normal file
BIN
victory.ric
Normal file
Binary file not shown.
Reference in New Issue
Block a user