oldcode – RallyNDS, Rally-X en tu NDS

Jul 10, 2012 No Comments by

Hace un tiempo atrás (en la epoca que desarrollar para Android o Iphone era impensable para un analista xD), hubo una gran euforia en el desarrollo de apps homebrew para Nintendo DS, gracias a la librería libnds (libre pero de desarrollo a bajo nivel) y sobre todo a Palib, está última, muy sencilla en base a funciones de alto nivel (nos abstrae mucho el uso de libnds).

A si fue, durante el 2009, con un poco de tiempo, trate de implementar un sencillo juego style Rally-X para Nintendo DS, utilizando la librería Palib (hoy en día sin mantenimiento desde Jul, 2010).

Palib, implementa una serie de funciones de muy fácil uso para trabajar con todo lo necesario en un juego, es decir, backgrounds, sprites, lógica, etc.

El desarrollo del juego es sencillo, en general, existe un auto que representa al usuario (centrado en la pantalla), mientras los otros son manejados por la cpu. Bajo este contexto, existe un gran diferencia entre el desplazamiento del auto usuario versus los autos cpu.

Ya que el auto del usuario siempre esta centrado en la pantalla , mientras el resto es lo que realmente se mueve (el fondo avanza, dando la sensación de que el auto del usuario avanza al igual como los autos de la cpu, por lo tanto hay que extrapolar la posición del resto (autos cpu) respecto al centro (auto usuario).

Sobre la detección de colisiones, he utilizado una de las capas que maneja Nintendo DS, para insertar una imagen que representa el mapa (en dos colores), de esta manera, podemos detectar si los vehículos han llegado a un tope del mapa.

El resto simplemente son png con sprites “tomados” de los juegos Pokemon xD.

Rally NDS … solo un demo en palib – libnds

Source Code

main.cpp

#include <PA9.h>
#define ATTR0_DISABLED   (2<<8) 

#define SCREEN_TOP     1
#define SCREEN_BOTTOM  0

#define BACKGROUND_ZERO  0
#define BACKGROUND_ONE   1
#define BACKGROUND_TWO   2
#define BACKGROUND_THREE 3

#define COLOR_MODE_256 1

/*
#define BACKGROUND_X 120
#define BACKGROUND_Y -88
*/

int BACKGROUND_X = 120;
int BACKGROUND_Y = -88;

#define MAP_MW 736
#define MAP_MH 672

#define CAR_PALLETE 0
#define CAR_SPRITE 0
#define CAR_REFLEJO_SPRITE 1

#define MAX_COMPUTER 7
#define MAX_PLAYERS 9

#define MAX_ITEM 64
#define MAX_ITEM_STARS 32

int CAR_X = 241;
int CAR_Y = 0;
/*
#define CAR_X 241
#define CAR_Y 0
*/

#define CAR_CENTER_X 120
#define CAR_CENTER_Y 88

/*
#define CARCPU_X 241
#define CARCPU_Y 0
*/

int CARCPU_X = 241;
int CARCPU_Y = 0;

#define CARCPU_CENTER_X 120
#define CARCPU_CENTER_Y 88

#define CAR_VELOCIDAD 5

#define ANIMACION_PAUSA 0
#define ANIMACION_ABAJO 1
#define ANIMACION_ARRIBA 2
#define ANIMACION_IZQUIERDA 3
#define ANIMACION_DERECHA 4

#define ESPACIO_LIBRE 0
#define DEBUGMODE	1

#include "rallye.h"
#include "gfx/all_gfx.h"
#include "gfx/all_gfx.c"

#include "dev/devRallyN.cpp"

//u8 obtenerBaldosa(s32 x, s32 y);
//void cargarPortadas();

int main(int argc, char ** argv)
{
	PA_Init();
	PA_InitVBL();
	PA_InitSound();
	/*
	PA_InitWifi();
    PA_ConnectWifiWFC();
	*/

	/*
	PA_InitText(0, 3);
	PA_InitText(1, 0);
	*/

	PA_InitCustomText(0, //screen
					  3, //background number
					  font); //font name
	PA_InitCustomText(1, //screen
					  1, //background number
					  font); //font name

	Game *mygame = new Game();
	// Load Presentation
	mygame->loadPresentation();
	// Show Principal Menu
	mygame->loadMainMenu();

	// Iniciamos el Juego
	mygame->runGame();
	while( 1 == 1)
	{
		PA_WaitForVBL();
	}

	PA_WaitForVBL();
	return 0;
}

devRallyN.h


// 		0-31
//		0-23

int playerLocalX = 0;
int playerLocalY = 0;
int nplayerGlobal = 0;

char buffer[256];

char debugGame[23][31];
int  pdebugGame = 0;
int fps = 0;
int time = 0;
void addStringDebug( char str[] )
{

	if ( pdebugGame == 22 )
		pdebugGame = 0;

	strcpy(debugGame[pdebugGame],str);
	pdebugGame++;
}
// Function debugin xD
void sleep()
{
	while(1 == 1)
	{
	}
}
// Funciones Globales
int getId()
{
	static int icount = 0;
	icount++;
	if ( icount == 127 )
		icount = 1;
	return ( icount-1 );
}

int getNumberSprite()
{
	static int scount = 0;
	scount++;
	if ( scount == 127 )
		scount = 1;
	return ( scount-1 );
}

int getNumberPallete()
{
	static int pcount = 0;
	pcount++;
	if ( pcount == 15 )
		pcount = 1;
	return ( pcount-1 );
}

int getNumberPlayer()
{
	static int npcount = 0;
	npcount++;

	return ( npcount -1 );
}

int getNumberItem()
{
	static int nicount = 0;
	nicount++;

	return ( nicount -1 );
}

struct infplayer
{
	int x;
	int y;
	int score;
	int life;
};

infplayer infoPlayer[MAX_PLAYERS]; 

class itemMaps
{
	private:
		int type,enabled,x,y;

	public:
	int id;
	int pallete;
	int nsprite;
	void setType( int gType );
	void setEnabled( int gEnabled );

	void setX( int gX );
	void setY( int gY );

	void renderer();
	int getPallete();
	int getType();
	int getEnabled();
	int getX();
	int getY();

	itemMaps();
};

class pointCar
{
	private:
		int x,y;
	public:
		pointCar();

		void setX( int gX );
		void setY( int gY );

		int getX();
		int getY();

};

class MapWorld
{
	private:
		int run,num;

	public:	

		int arrPointCar[MAX_PLAYERS][2];

		pointCar *myPointCar[MAX_PLAYERS];

		//itemMaps *myItem[32];
		//itemMaps *myItem[32];
		itemMaps *myItem;

		MapWorld();
		void setMap( int gNum );
		void loadMap();
		// In the map
		bool isAvailable( int *px , int *py , int *pncar , int *life , int *score );
		// Collision Map
		bool thereAreCarCollision( int *x , int *y , int *ncar , int *life , int *score );

		void positionRandom(int &gX , int &gY);
		void setPlayerPosition(int np , int mX , int mY);
		int getXPlayerPosition(int np );
		int getYPlayerPosition(int np );

		void renderer();

};

class Car
{
	private:

		// x,y		map
		// sx,sy	screen

		int x, y , sx ,sy , a , v, ang, cf1, cf2, csp, lcf1, lcf2;
		void* pallete;
		void* sprite;

	public:

		int vel;
		int *score;
		int *life;
		int nplayer;
		int car_sprite;
		int car_pallete;
		MapWorld* mymap;
		Car();

		void setSx( int sX );
		void setSy( int sY );

		int getSx();
		int getSy();

		void setX(int gX );
		void setY(int gY );
		void setAng( int gAng );
		void setRandomAng();

		int getX();
		int getY();
		int getAng();

		void runCar();
		void setPallete( void* p );
		void setSprite( void* s);
		void createCar();
};

class Player
{
	private:
		int	idplayer;
		bool connect;

	public:
		int score;
		int life;
		int nplayer;
		char name[64];
		MapWorld* mymap;
		// Constructor
		Car* myCar;
		Player();
		void setMyCar( void* pal , void* spr , int mX , int mY , int sX , int sY );
		void setName( char gName[] );

};

class PlayerLocal : public Player
{

	public:
		// Constructor
		PlayerLocal();

		void play();
		void renderer();

};

class PlayerComputer : public Player
{
	public:
		// Constructor
		PlayerComputer();

		void play();
		void renderer();
};

class Game
{
	private:
		int loop;
		// Local
		PlayerLocal* player;
		// Computer
		PlayerComputer* playercpu;
		// String

	public:
		// Constructor
		MapWorld* mymap;
		Game();
		void loadPresentation();
		void runGame();
		void showDebug();
		void loadMainMenu();
		void renderScore( char gName[] , int pos , int score , int life );

};

devRallyN.cpp

#include "devRallyN.h"

void* getSpriteCar( int c )
{
	if ( c == 1 )
		return (void*)car1_Sprite;
	else if ( c == 2 )
		return (void*)car2_Sprite;
	else if ( c == 3 )
		return (void*)car3_Sprite;
	else if ( c == 4 )
		return (void*)car3_Sprite;
	else
		return (void*)car1_Sprite;

}

void* getPalleteCar( int c )
{
	if ( c == 1 )
		return (void*)car1_Pal;
	else if ( c == 2 )
		return (void*)car2_Pal;
	else if ( c == 3 )
		return (void*)car3_Pal;
	else if ( c == 4 )
		return (void*)car4_Pal;
	else
		return (void*)car1_Pal;
}

// PointCar

pointCar::pointCar()
{
	this->x = -1;
	this->y = -1;
}

void pointCar::setX( int gX )
{
	this->x = gX;
}
void pointCar::setY( int gY )
{
	this->y = gY;
}

int pointCar::getX()
{
	return this->x;
}
int pointCar::getY()
{
	return this->y;
}

// itemMaps

itemMaps::itemMaps()
{
	this->y = -1;
	this->x = -1;
	this->type = -1;
	this->enabled = -1;
	this->pallete = this->getPallete();
	this->nsprite = -1;
	this->id = getNumberItem();	

};

void itemMaps::setX(int gX){ this->x = gX; }
void itemMaps::setY(int gY){ this->y = gY; }
int  itemMaps::getY(){ return this->y ; }
int  itemMaps::getX(){ return this->x ; }

void itemMaps::setType( int gType ){ this->type = gType; };
void itemMaps::setEnabled( int gEnabled ){ this->enabled = gEnabled; };

int itemMaps::getType(){ return this->type; };
int itemMaps::getEnabled(){ return this->enabled; };

int itemMaps::getPallete()
{
	static int pallete = 0;

	if ( pallete == 0 )
		pallete = getNumberSprite();

	return pallete;
}

void itemMaps::renderer()
{
	int xl,yl;
	if ( this->nsprite == -1 )
		this->nsprite = getNumberSprite();

	this->y = this->y * (-1);

	/*
	char out[32] = "                              ";
	sprintf(out,"START(%03d,%03d)xy", x , y );
	addStringDebug(out);
	*/

	// ¿  Esta en el espacio visual del player local ?

	if ( playerLocalX -128 <= this->x && playerLocalX +128 >= this->x /*&&  (playerLocalY*(-1)) - 95 <= this->y && (playerLocalY*(-1)) + 95 >=  this->y*/  )
	{
		// Mostramos el Sprite
		PA_obj[SCREEN_TOP][this->nsprite].atr0 &= ~(2<<8);
		// Calculamos el punto de referencia
		xl = this->x - ( playerLocalX - 128 );
		yl = this->y - ( playerLocalY*-1 - 95 );																		// Fixme				// Fixme
		PA_SetSpriteXY(SCREEN_TOP,this->nsprite , xl -9 , yl  -4 );

	}
	else
	{
		// Deberiamos ocultar al Sprite
		PA_obj[SCREEN_TOP][this->nsprite ].atr0 |= (2<<8);

	}		

}

// MapWorld
MapWorld::MapWorld()
{
	run = 1;
	for(int i = 0 ; i < MAX_PLAYERS ; i++)
	{
		this->setPlayerPosition(i,-1,-1);
		this->myPointCar[i] = new pointCar();

	}

	// Pedimos memorias y instanciamos
	myItem = new itemMaps[32];
	char out[32] = "                              "; 

	for(int i=0; i < 32 ; i++)
	{
		sprintf(out,"SI(%02d)id",  (myItem+i)->id );
		addStringDebug(out);
	}

	/*
	myItem = new itemMaps[32];
	//this->myItem = new itemMaps[32];
	// Cada Mapa tiene 32 Banderitas
	for(int i=0; i < 32 ; i++)
	{
		//this->(myItem+i) = new itemMaps();
		(myItem+i)->setType(0);
		(myItem+i)->setX(100);
		(myItem+i)->setY(100);
	}
	*/

}

void MapWorld::renderer()
{
	// Renderizo las Banditas
	/*
	for(int i=0; i < 32 ; i++)
	{
		(myItem+i)->renderer();
		PA_OutputText(SCREEN_BOTTOM, 1, i, "%d,%d", (myItem+i)->id , (myItem+i)->id );		

	}
	sleep();
	*/

	char out[32] = "                              ";
	//for(int i=0; i < 10 ; i++)
	//{
		sprintf(out,"SI(%02d)id",  (myItem+1)->id );
		addStringDebug(out);
	//}

}

void MapWorld::setMap( int gNum )
{
	num = gNum;
}
void MapWorld::loadMap()
{
	if ( num == 1 )
	{
		PA_EasyBgLoad(SCREEN_TOP, BACKGROUND_THREE, map1Col);
		PA_EasyBgLoad(SCREEN_TOP, BACKGROUND_TWO, map1Med);
		//PA_EasyBgLoad(SCREEN_TOP, BACKGROUND_ONE, map1Top);
		PA_PlayMod(rallye);
	}
}

void MapWorld::setPlayerPosition(int np , int mX , int mY)
{	

	char out[32] = "                              ";
	/*
	if ( np == 0 )
	{
		sprintf(out,"SET(%02d,%03d,%03d)np,x,y",np,mX,mY);
		addStringDebug(out);
	}
	*/
	/*
	if ( np >= 0 && np < MAX_PLAYERS )
	{
		this->myPointCar[np]->setX(mX);
		this->myPointCar[np]->setY(mY);
	}
	*/
	if ( np >= 0 && np < MAX_PLAYERS )
	{
		this->arrPointCar[np][0] = mX;
		this->arrPointCar[np][1] = mY;
	}

	/*
	if ( np == 0 )
	{
		sprintf(out,"GET(%02d,%03d,%03d)np,x,y",np,this->arrPointCar[np][0],this->arrPointCar[np][1]);
		addStringDebug(out);
	}
	*/
}

int MapWorld::getXPlayerPosition( int np  )
{
	if ( np >= 0 && np < MAX_PLAYERS )
	{
		//return this->myPointCar[np]->getX();
		return this->arrPointCar[np][0];
	}
	else
		return -1;
	//return this->arrPointCar[np][0];
}
int MapWorld::getYPlayerPosition(int np )
{
	if ( np >= 0 && np < MAX_PLAYERS )
	{
		//return this->myPointCar[np]->getY();
		return this->arrPointCar[np][1];
	}
	else
		return -1;
	//return this->arrPointCar[np][1];
}
void MapWorld::positionRandom(int &gX , int &gY)
{
	int xl = PA_RandMinMax(1,MAP_MW);
	int yl = PA_RandMinMax(1,MAP_MH);

	while( !isAvailable(&xl,&yl,NULL,NULL,NULL) && !( xl == 0 || yl ==0 ) )
	{
		xl = PA_RandMinMax(1,MAP_MW);
		yl = PA_RandMinMax(1,MAP_MH);
	}

	gX = xl;
	gY = yl;
}

bool MapWorld::thereAreCarCollision(int *x , int *y , int *ncar , int *life , int *score)
{
	bool myreturn = true;

	if ( ncar == NULL && life == NULL && score == NULL  )
		return true;

	if ( *y < 0 )
		*y = *y *-1;

	if (  *ncar == -1 )
		return true;

	// Vamos a Recorrer infoPlayer de 0 a MAX_PLAYERS

	for(int i = 0 ; i < MAX_PLAYERS ; i++ )
	{
		if ( i != *ncar )
		{
			if ( *x >= infoPlayer[i].x && *x <= (infoPlayer[i].x+16) && *y >= (infoPlayer[i].y*-1) && *y <= ((infoPlayer[i].y*-1)+16) )
			{
				(*life)--;
				myreturn = false;
			}
			if ( infoPlayer[i].x >= *x && (infoPlayer[i].x+16) <= *x &&  (infoPlayer[i].y*-1) >= *y &&  ((infoPlayer[i].y*-1)+16) <= *y )
			{
				(*life)--;
				myreturn = false;
			}
		}
	}

	return myreturn;

}

bool MapWorld::isAvailable(int *px , int *py , int *pncar , int *life , int *score  )
{
	// 0 Disponible
	// 1 Ocupado
	int x = *px;
	int y = *py;
	int ncar = *pncar;
	y = y * (-1);
	if ( y < 0  )
		y = y*(-1);

	if ( y == 0)
		return false;

	if ( ( PA_EasyBgGetPixel(SCREEN_TOP,BACKGROUND_THREE,x, y) == 0 ) && ( PA_EasyBgGetPixel(SCREEN_TOP,BACKGROUND_THREE,x+8, y) == 0 ) && ( PA_EasyBgGetPixel(SCREEN_TOP,BACKGROUND_THREE,x, y+8) == 0 ) && ( PA_EasyBgGetPixel(SCREEN_TOP,BACKGROUND_THREE,x+8, y+8) == 0 ) && thereAreCarCollision(&x,&y,&ncar , life , score) )
	{
		return true;
	}
	else
	{
		return false;
	}

}

// Car
Car::Car()
{
	x = 0;
	y = 0;
	a = 0;
	v = 0;
	sx = 0;
	sy = 0;
	ang = 270;
	// 0.5px/s
	vel = 60;
	//vel = 0;

	cf1 = 0;
	cf2 = 1;
	csp = 6;

	lcf1=255;
	lcf2=255;

	car_pallete = getNumberPallete();
	car_sprite = getNumberSprite();

	//mymap = new MapWorld();
}

void Car::setRandomAng()
{
	int n = PA_RandMinMax(0,3);
	if ( n == 0 )
	{
		setAng(0);
	}
	else if( n == 1 )
	{
		setAng(90);
	}
	else if( n == 2 )
	{
		setAng(270);
	}
	else if( n == 3 )
	{
		setAng(180);
	}
}
void Car::setAng( int gAng )
{
	ang = gAng;
}
int Car::getAng()
{
	return ang;
}

void Car::runCar()
{
	// En teoria runCar debe ejecutarse a 30fps
	int yt=0;
	int xt=0;

	/*
	char out[32] = "                              ";
	sprintf(out,"(%d,%d,%d,%d)",x,y,sx,sy);
	addStringDebug(out);
	*/

	if ( DEBUGMODE == 1 )
	{
		PA_OutputText(SCREEN_BOTTOM, 20, 21, "ang:%d  ", ang);
		PA_OutputText(SCREEN_BOTTOM, 20, 22, "vel:%d  ", vel);
	}

	/*
		Cada Car ocupa una dimensión de 16x16 px
	*/
	/*
	if ( fps%30 == 0 )
	{
		char out[32] = "                              ";
		sprintf(out,"CAR - (%03d,%03d)xy ang:%d vel:%d  ",x,y,ang,vel);
		addStringDebug(out);
	}
	*/

	if ( ang == 90 )
	{
		yt = y + ( vel / 30  );
		if ( mymap->isAvailable(&x,&yt,&nplayer,this->life,this->score) )
		{
			y = yt;
			//PA_StartSpriteAnim(SCREEN_TOP, car_sprite, 3, 4, 10);
			cf1=3;cf2=4;
		}
		else
		{
			// Giro
			//ang = 180;
			setRandomAng();
		}

	}
	if ( ang == 180 )
	{
		xt = x - ( vel / 30  );
		if ( mymap->isAvailable(&xt,&y,&nplayer,this->life,this->score) )
		{
			x = xt;
			//PA_StartSpriteAnim(SCREEN_TOP, car_sprite, 7, 8, 10 );
			cf1=7;cf2=8;
			PA_SetSpriteHflip(SCREEN_TOP, car_sprite, 1);
		}
		else
		{
			//ang = 270;
			setRandomAng();
		}

	}
	if ( ang == 270 )
	{
		yt = y - ( vel / 30  );
		if ( mymap->isAvailable(&x,&yt,&nplayer,this->life,this->score) )
		{
			y = yt;
			cf1=0;cf2=1;
			//PA_StartSpriteAnim(SCREEN_TOP, car_sprite, 0, 1, 10 );
		}
		else
		{
			//ang = 0;
			setRandomAng();
		}

	}
	if ( ang == 0 )
	{
		xt = x + ( vel / 30  );

		if ( mymap->isAvailable(&xt,&y,&nplayer,this->life,this->score) )
		{
			x = xt;
			//PA_StartSpriteAnim(SCREEN_TOP, car_sprite, 7, 8, 10  );
			cf1=7;cf2=8;
			PA_SetSpriteHflip(SCREEN_TOP, car_sprite, 0);
		}
		else
		{
			//ang = 90;
			setRandomAng();
		}
	}

	if ( cf1 != lcf1 && cf2 != lcf2 )
	{
		PA_StartSpriteAnim(SCREEN_TOP, car_sprite, cf1, cf2, csp);
		lcf1=cf1;
		lcf2=cf2;
	}

	//this->mymap->setPlayerPosition(nplayer,this->x,this->y);

	if ( nplayer > 0 && nplayer < MAX_PLAYERS )
	{
		infoPlayer[nplayer].x = x;
		infoPlayer[nplayer].y = y;
	}	

}

void Car::setX( int gX )
{
	x = gX;
}
void Car::setY( int gY )
{
	y = gY;
}

void Car::setSx( int sX )
{
	sx = sX;
}
void Car::setSy( int sY )
{
	sy = sY;
}

int Car::getSy()
{
	return sy;
}
int Car::getSx()
{
	return sx;
}

int Car::getY()
{
	return y;
}
int Car::getX()
{
	return x;
}
void Car::setPallete( void* p )
{
	pallete = p;
}
void Car::setSprite( void* s )
{
	sprite = s;
}
void Car::createCar()
{
	// Cargamos y Creamos Sprite
	PA_LoadSpritePal(SCREEN_TOP, car_pallete,pallete);
	PA_CreateSprite(SCREEN_TOP, car_sprite, sprite, OBJ_SIZE_16X32, COLOR_MODE_256, car_pallete, sx, sy);
}

// Game
Game::Game(){}

void Game::showDebug()
{
	/*
	char url[512] = "                              ";
	*/
	for(int i=0; i <= pdebugGame ; i++)
	{
		PA_OutputText(SCREEN_BOTTOM, 0, i+3, "%02d-%s", i , debugGame[i] );
		/*
		sprintf(url,"http://deerme.piloto.cl/rand.php?s=%s",debugGame[i]);
		PA_GetHTTP(buffer, url);
		*/

	}
}

void Game::loadPresentation()
{
	// Developer deerme
	PA_EasyBgLoad(SCREEN_TOP, BACKGROUND_ZERO, gameP0);
	// GPL Lic
	PA_EasyBgLoad(SCREEN_BOTTOM, BACKGROUND_ZERO, gameP3);

	int lfps = 0;

	while( lfps < 120 )
	{
		if ( lfps < 30 )
		{
			if ( lfps%2 )
				PA_SetScreenLight(SCREEN_TOP, 1);
			else
				PA_SetScreenLight(SCREEN_TOP, 0);
		}
		PA_WaitForVBL();
		lfps++;
	}
	PA_SetScreenLight(SCREEN_TOP, 1);
	PA_EasyBgLoad(SCREEN_TOP, BACKGROUND_ZERO, gameP1);
	// Mientras haga Click
	bool click = false;
	while (!click)
	{
		click = Stylus.Held;
		PA_WaitForVBL();
	}

	int i = 0;
	for (i = 0; i < 64; i++)
	{
		PA_SetBrightness(SCREEN_TOP, -i);
		PA_SetBrightness(SCREEN_BOTTOM, -i);
		PA_WaitForVBL();
	}
	PA_DeleteBg(SCREEN_BOTTOM, BACKGROUND_ZERO);
	PA_DeleteBg(SCREEN_TOP, BACKGROUND_ZERO);
	PA_SetBrightness(SCREEN_TOP, 0);
	PA_SetBrightness(SCREEN_BOTTOM, 0);

	/*
	if ( DEBUGMODE != 1 )
		PA_EasyBgLoad(SCREEN_BOTTOM, BACKGROUND_ZERO, gameP1);
	*/
	return;

}
void Game::loadMainMenu()
{
	// Load Fondo menu
	PA_EasyBgLoad(SCREEN_BOTTOM, 3, gameP6);
	// Init Text
	PA_InitCustomText(SCREEN_BOTTOM, 0, font);
	// Iniciamos Menu

	char menu[2][16];

	sprintf(menu[0],"ARCADE        \n");
	sprintf(menu[1],"MULTIPLAYER   \n");
	sprintf(menu[2],"OPTIONS       \n");

	//strcpy(menu[0],"ARCADE\n");

	/*
	for(int i=0; i <= 2 ; i++)
	{
		//PA_OutputText(SCREEN_BOTTOM, 0, i+3, "%s", i , menu[i] );
		PA_OutputText(SCREEN_BOTTOM, 5, 7+i, "%s", menu[i] );
	}
	*/

	// Deber
	PA_DeleteBg(SCREEN_BOTTOM, 3);
	PA_EasyBgLoad(SCREEN_BOTTOM, 3, gameP7);

}

void Game::renderScore( char gName[] , int pos , int score , int life)
{	

	char tempChar[32];
	sprintf(tempChar,"%-7.7s  %03d %03d" , gName , score , life );
	PA_OutputText(SCREEN_BOTTOM, 2, 5+pos, "%s", tempChar );	

}

void Game::runGame()
{
	// Instanciamos el Mapa
	//
	/*
	PA_EasyBgLoad(SCREEN_TOP, BACKGROUND_TWO, map1Med);
	PA_EasyBgLoad(SCREEN_TOP, BACKGROUND_THREE, agua);
	PA_EasyBgLoad(SCREEN_TOP, BACKGROUND_ONE, map1Top);
	*/

	addStringDebug("Instance World");

	mymap = new MapWorld();
	mymap->setMap(1);
	mymap->loadMap();

	// Instanciamos PlayerLocal

	addStringDebug("Instance Player and CPU");
	PlayerLocal *player = new PlayerLocal();
	player = new PlayerLocal();

	char temporalName[64];
	strcpy(temporalName,(char*)PA_UserInfo.Name);
	player->setName(temporalName);
	player->mymap = mymap;
	// Instanciamos PlayerComputer

	PlayerComputer *playercpu[MAX_COMPUTER];
	// Load PlayerComputer
	for(int i=0; i<MAX_COMPUTER;i++)
	{
		mymap->positionRandom(CARCPU_X,CARCPU_Y);
		CARCPU_Y = CARCPU_Y*(-1);

		// Palleta y Sprite Aleatorio
		int styleCar = PA_RandMinMax(1,4);

		playercpu[i] = new PlayerComputer();
		playercpu[i]->mymap = mymap;
		playercpu[i]->setMyCar( getPalleteCar(styleCar) , getSpriteCar(styleCar) , CARCPU_X , CARCPU_Y , CARCPU_CENTER_X , CARCPU_CENTER_Y  );
		char temporalNameCPU[64];
		sprintf(temporalNameCPU,"CPU %d",i);
		playercpu[i]->setName(temporalNameCPU);

	}

	// Pruebas (voy a mover a CAR)

	CAR_X = 225;
	CAR_Y = 0;

	mymap->positionRandom(CAR_X,CAR_Y);
	CAR_Y = CAR_Y*(-1);

	mymap->positionRandom(CARCPU_X,CARCPU_Y);
	CARCPU_Y = CARCPU_Y*(-1);

	BACKGROUND_X = CAR_X - CAR_CENTER_X;
	BACKGROUND_Y = CAR_Y - CAR_CENTER_Y;

	// Centrado
	player->setMyCar( (void*)car1_Pal , (void*)car1_Sprite , CAR_X , CAR_Y , CAR_CENTER_X , CAR_CENTER_Y  );

	// Prioriodad de Fondos
	PA_SetSpritePrio(SCREEN_TOP, CAR_SPRITE, BACKGROUND_TWO);
	PA_EnableSpecialFx(SCREEN_TOP, SFX_ALPHA, 0, SFX_BG0 | SFX_BG1 | SFX_BG2 | SFX_BG3 | SFX_BD);
	PA_SetSFXAlpha(SCREEN_TOP, 12, 15);

	PA_InitParallaxX(SCREEN_TOP, 0, 256, 256, 0);
	PA_InitParallaxY(SCREEN_TOP, 0, 256, 256, 0);
	//PA_ParallaxScrollXY(SCREEN_TOP, BACKGROUND_X, BACKGROUND_Y);

	// Movemos la Pantalla
	int i = 0;

	while( 1 == 1)
	{
		/*
		if ( fps%15 )
		*/

		// Rally NDS by deerme.org
		player->play();
		if ( fps%25 )
			renderScore( player->name , player->nplayer , player->score , player->life );

		for(int i=0; i<MAX_COMPUTER;i++)
		{
			playercpu[i]->play();

			if ( fps%25 )
				renderScore( playercpu[i]->name , playercpu[i]->nplayer , playercpu[i]->score , playercpu[i]->life );
		}

		// !! runCar !!
		player->myCar->runCar();
		for(int i=0; i<MAX_COMPUTER;i++)
		{
			playercpu[i]->myCar->runCar();
		}

		/*
		if ( time == 10 )
		{

			char out[32] = "                              ";
			for( int i = 0 ; i< MAX_COMPUTER; i++ )
			{
				sprintf(out,"(%02d,%03d,%03d)" , i, this->mymap->getXPlayerPosition(i) ,  this->mymap->getYPlayerPosition(i) );
				addStringDebug(out);
			}
			showDebug();

		}
		*/
		if ( fps%25 )
		{
			showDebug();
		}

		// Renderizamos
		player->renderer();
		for(int i=0; i<MAX_COMPUTER;i++)
		{
			playercpu[i]->renderer();
		}
		playercpu[0]->renderer();
		playercpu[1]->renderer();

		mymap->renderer();

		if ( fps == 30 )
		{
			fps = 0;
			time++;
		}
		if ( time == 10000 )
		{
			time = 0;
		}
		if ( DEBUGMODE == 1 )
			PA_OutputText(SCREEN_BOTTOM, 20, 20, "fps:%d", fps);

		fps++;
		PA_WaitForVBL();
	}

	//PA_WaitForVBL();
}

// Player
Player::Player()
{
	//mymap = new MapWorld();
	strcpy(name,"NOTENGONOMBRE                                                ");
	nplayer = getNumberPlayer();
	this->score = 0;
	this->life = 100;

}
void Player::setMyCar( void* pal , void* spr , int mX , int mY , int sX , int sY)
{
	// Instanciamos a myCar
	//Car *myCar = new Car();		Corregido por lgm
	myCar = new Car();
	myCar->setPallete( pal );
	myCar->setSprite( spr );

	// Score y Life
	myCar->life = &this->life;
	myCar->score = &this->score;		

	// Mapa
	myCar->setX( mX );
	myCar->setY( mY );
	// Screen
	myCar->setSx( sX );
	myCar->setSy( sY );
	myCar->createCar();
	// Paso al Auto una referencia del mapa
	myCar->mymap = mymap;
	myCar->nplayer = this->nplayer;
	// Seteo el valor
	mymap->setPlayerPosition(nplayer,mX,mY);

}
void Player::setName( char gName[] )
{
	strcpy(this->name,gName);
}

PlayerLocal::PlayerLocal(){}
void PlayerLocal::play()
{
	// Como soy el Player local debo analizar las Teclas Presionadas
	if ( Pad.Held.Up )
	{
		myCar->setAng(90);
	}
	if ( Pad.Held.Down )
	{
		myCar->setAng(270);
	}
	if ( Pad.Held.Left )
	{
		myCar->setAng(180);
	}
	if ( Pad.Held.Right )
	{
		myCar->setAng(0);
	}
	if ( Pad.Held.A )
	{
		if ( this->myCar->vel < 120 )
			this->myCar->vel++;
	}

	if ( Pad.Held.B )
	{
		if ( this->myCar->vel > 60 )
			this->myCar->vel--;
	}

	// Analizamos la Aceleracion

}
void PlayerLocal::renderer()
{
	// Soy el PlayerLocal, yo muevo la pantalla :) 

	playerLocalX = (int)myCar->getX();
	playerLocalY = (int)myCar->getY();

	PA_ParallaxScrollXY(SCREEN_TOP, BACKGROUND_X - CAR_X +  (int)myCar->getX() , BACKGROUND_Y - CAR_Y + ((int)myCar->getY()*-1)  );

	/*
	PA_ParallaxScrollXY(SCREEN_TOP, CAR_CENTER_X - CAR_X +  (int)myCar->getX() , (CAR_CENTER_Y*-1) - CAR_Y + ((int)myCar->getY()*-1)  );
	*/

}

PlayerComputer::PlayerComputer(){}
void PlayerComputer::play()
{
	// Por el momento no tengo logica xD
	//myCar->setAng(0);

	if ( time%100 == 0 )
	{
		int n = PA_RandMinMax(0,3);
		if ( n == 0 )
		{
			myCar->setAng(0);
		}
		else if( n == 1 )
		{
			myCar->setAng(90);
		}
		else if( n == 2 )
		{
			myCar->setAng(270);
		}
		else if( n == 3 )
		{
			myCar->setAng(180);
		}

	}

}
void PlayerComputer::renderer()
{
	// Por el momento no tengo logica xD

	int xl = myCar->getX();
	int yl = myCar->getY();

	yl = yl * (-1);

	/*
	if ( fps%30 == 0 )
	{
		char out[32] = "                              ";
		sprintf(out,"CPU - (%d,%d)xy",xl,yl);
		addStringDebug(out);
	}
	*/
	// ¿  Esta en el espacio visual del player local ?

	///if ( playerLocalX + 128 <=  xl && playerLocalX - 128 >= xl /*&& (playerLocalY*(-1)) + 95 <  yl && (playerLocalY*(-1)) - 95 >  yl*/ )*/
	if ( playerLocalX -128 <= xl && playerLocalX +128 >= xl &&  (playerLocalY*(-1)) - 95 <= yl && (playerLocalY*(-1)) + 95 >=   yl  )
	{
		PA_obj[SCREEN_TOP][myCar->car_sprite].atr0 &= ~(2<<8);
		// Calculamos el punto de referencia
		xl = xl - ( playerLocalX - 128 );
		yl = yl - ( playerLocalY*-1 - 95 );

		myCar->setSx(xl);
		myCar->setSy(yl);
																	// Fixme				// Fixme
		PA_SetSpriteXY(SCREEN_TOP, myCar->car_sprite , myCar->getSx() -9 , myCar->getSy() -4 );

	}
	else
	{
		// Deberiamos ocultar al Sprite

		PA_obj[SCREEN_TOP][myCar->car_sprite].atr0 |= (2<<8);
		/*
		char out[32] = "                              ";
		sprintf(out,"No entro :(  :P ");
		addStringDebug(out);
		*/

	}
};

Descarga Rally NDS rom

Rally NDS Source Pat01Rally NDS Source Pat02

Dev NDS, Old Code

About the author

Ingeniero en Informática, Oracle Certified Master Java EE 6 Enterprise Architect, Oracle Certified Professional Java Programmer. Experto en distintas ramas de la computación y otras "yerbas" xD. Si te gusto este post, sígueme en @deerme_org, escríbeme a info AT deerme.org o contactame por linkedin.
No Responses to “oldcode – RallyNDS, Rally-X en tu NDS”

Leave a Reply


6 * seven =