Looking to generate random sprite colours

StevenH
Posts: 133
Joined: Sun Feb 22, 2009 7:59 pm

Re: Looking to generate random sprite colours

Post by StevenH » Thu Jul 16, 2009 11:16 am

After a quick glance:

in setupgraphics():

SPRITE_PALETTE_SUB[(n*16)+2] = SPRITE_PALETTE[(n*16)+1];

Should that not be:

SPRITE_PALETTE_SUB[(n*16)+2] = SPRITE_PALETTE[(n*16)+2];

also you are dmaCopying 32x32 pixels, the sprite is 16x32 pixels - you might want to change that and see if it fixes your issue.

---

Since you are using 1 sprite that is the same for all of the objects, what I would do is to pre-allocate the sprite in both sprite vram area's and pass the offset to the balloon init code as a pointer, that way you don't need to allocate a new balloon every time you create one. This will reduce the amount of ram that your using in the sprite VRAM, and also allow for some kind of animation. Look at the simple_animation example for 2 ways to do animation with the current oam* functions.

For example in my current little play around nds project I'm using 2 sprites of 32x32 that are artificially linked togther to animate a 32x40 - 32x64 size sprite, and I've got the following stored in a temporary buffer:

Image

The first 32x32 block is stored in VRAM, and never changes, the other images are dmaCopied only when I change the displayed image.

I've also got the following loaded into VRAM, before the above sprite is loaded:

Image

As you can see I have all the animation frames loaded for the other objects, this is so that different sprites can have a different frame of animation at the time it is displayed (I've not completed the animation frames for the other sprites yet, and at the moment it's just placeholder graphics).

The first way (the dmaCopy every fram change) is good for single sprites, where as the larger image is good if you have multiple sprites all sharing animation frames, but they can have different animation frames shown at the same time.

The large image has 4 placeholder colours - 3 greys (main ship top, main ship engine, bullets) and a purple (boss graphics), for some reason the files are stored with colour 0 being set to transparent, when it should be black.

hassifa
Posts: 15
Joined: Thu Jul 16, 2009 2:22 am

Re: Looking to generate random sprite colours

Post by hassifa » Thu Jul 16, 2009 11:51 am

StevenH wrote:After a quick glance:

in setupgraphics():

SPRITE_PALETTE_SUB[(n*16)+2] = SPRITE_PALETTE[(n*16)+1];

Should that not be:

SPRITE_PALETTE_SUB[(n*16)+2] = SPRITE_PALETTE[(n*16)+2];

also you are dmaCopying 32x32 pixels, the sprite is 16x32 pixels - you might want to change that and see if it fixes your issue.
Just a quick reply, in regards to the sprite palette, i want them to be the same colour, so i am just copying the 1st main entry into the 2nd main entry, and the 1st and 2nd sub palette entry.
And the sprite is actually a 32x32 sprite, its just that the balloon is in the middle of the sprite with space to the left and right of it.

I changed around where i allocate the sprite, so now i only have a single reference point that all of the balloons use themselves, and it has fixed the misaligned tiling problem. So now the only problem that i have left, is that some 'artifact' balloons appear right when a new wave occurs. They are unclickable which proper ballons are, and they also dont float onto the top-sub screen. i'll post my wave creation below.

Image

Code: Select all

void setupGraphics()	// function to setup the gfx engine
{
	oamInit(&oamMain, SpriteMapping_1D_64, false	);
	oamInit(&oamSub, SpriteMapping_1D_64, false);
	oamClear(&oamMain,0,127);
	oamClear(&oamSub,0,127);

	lcdMainOnBottom();	// switch main / sub engine on screens
	vramSetBankF( VRAM_F_MAIN_SPRITE );	// set VRAM Bank F to use sprites
	vramSetBankC( VRAM_C_SUB_BG );
	vramSetBankI( VRAM_I_SUB_SPRITE );
	videoSetMode( MODE_0_2D | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D_LAYOUT );	//
	videoSetModeSub( MODE_0_2D | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D_LAYOUT );	// 	
	
	consoleInit(&topScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true);
	consoleSelect(&topScreen);

	dmaCopy(gfx_balloonPal, SPRITE_PALETTE, gfx_balloonPalLen);
	dmaCopy(gfx_balloonPal, SPRITE_PALETTE_SUB, gfx_balloonPalLen);

	balloon_gfx_mem = oamAllocateGfx(&oamMain,SpriteSize_32x32, SpriteColorFormat_16Color);
	balloon_gfx_mem_sub = oamAllocateGfx(&oamSub,SpriteSize_32x32, SpriteColorFormat_16Color);

	dmaCopy(gfx_balloonTiles, balloon_gfx_mem, gfx_balloonTilesLen);
	dmaCopy(gfx_balloonTiles, balloon_gfx_mem_sub, gfx_balloonTilesLen);

	int n;
	for(n = 1; n < 16; n++)
	{
		SPRITE_PALETTE[(n*16)+1] = RGB15(rand()%32,rand()%32,rand()%32);
		SPRITE_PALETTE[(n*16)+2] = SPRITE_PALETTE[(n*16)+1];
		SPRITE_PALETTE_SUB[(n*16)+1] = SPRITE_PALETTE[(n*16)+1];
		SPRITE_PALETTE_SUB[(n*16)+2] = SPRITE_PALETTE[(n*16)+1];
	}
	for( n = 0; n < MAX_NUM_OF_BALLOONS; n++) // assign a sprite index to each balloon instance for rendering
	{
		balloonArray[n].setSpriteIndex(sprite_count);
		balloonArray[n].initialize();
		balloonArray[n].setX(50 << 8);
		balloonArray[n].setY(250 << 8);
		sprite_count++;
	}	
}

void startWave()		// function to start the next wave
{
	int n;
	for( n = 0; n < BALLOONS_PER_WAVE*wave; n++)
	{
		balloonArray[n].setX(((rand() % 224) + 16) << 8);	// assign a random x location
		balloonArray[n].setY(((rand() % 100*wave) + 195) << 8);	// assign a random y location underneath
		balloonArray[n].resetActive();	// reset balloon to active
		balloonArray[n].setOnBottom();
	}
}

void updateLogic()		// function to update game logic
{
	bool ready = true;
	if(wave == 0)
	{
		if(time(NULL) - oldtime >= TIME_BEFORE_START || advancewave == true) // check time for next wave
		{
			advancewave = false;
			wave++;
			startWave();
			oldtime = time(NULL);
		}
	}
	else if(time(NULL) - oldtime >= (TIME_BETWEEN_WAVES+2*wave) || advancewave == true)
	{
		int n;
		for(n = 0; n < BALLOONS_PER_WAVE*wave; n++)
			if(balloonArray[n].isActive())
			{
				ready = false;
				break;
			}
		if(ready)
		{
			advancewave = false;
			wave++;
			startWave();
			if(wave > 10)
					wave = 10;
			oldtime = time(NULL);
		}
	}
	int m;
	for( m = 0; m < BALLOONS_PER_WAVE*wave; m++)	// for each balloon that is active in the wave
		if(balloonArray[m].isActive())
			balloonArray[m].update();	// change its location
}

StevenH
Posts: 133
Joined: Sun Feb 22, 2009 7:59 pm

Re: Looking to generate random sprite colours

Post by StevenH » Thu Jul 16, 2009 12:18 pm

Sorry I meant your 32x32 pixel ballon is only using 16x32 bytes of memory (a 4 bit sprite stores 2 pixels in each byte, thus using half the memory that you are copying).

Those artifact balloons could be down to a wrapping of the Y location of other ballons. basically your Y position is limited to 0-255, and is signed (-127-128), so ((rand() % 100*wave) + 195) = somewhere near the top of the screen in some cases of your init code, or even wrapping the screen twice.

I would put some debug outputs in your render loop to show the Y position of each balloon, and it's state - that way you will be able to see which balloons are the ones that are causing you some issues.

hassifa
Posts: 15
Joined: Thu Jul 16, 2009 2:22 am

Re: Looking to generate random sprite colours

Post by hassifa » Thu Jul 16, 2009 12:45 pm

StevenH wrote: Those artifact balloons could be down to a wrapping of the Y location of other ballons. basically your Y position is limited to 0-255, and is signed (-127-128), so ((rand() % 100*wave) + 195) = somewhere near the top of the screen in some cases of your init code, or even wrapping the screen twice.

I would put some debug outputs in your render loop to show the Y position of each balloon, and it's state - that way you will be able to see which balloons are the ones that are causing you some issues.
The artifacting was what you thought it was. Because of the random value, it was wrapped back onto the screen, which is easily fixable.
StevenH wrote: Sorry I meant your 32x32 pixel ballon is only using 16x32 bytes of memory (a 4 bit sprite stores 2 pixels in each byte, thus using half the memory that you are copying).
So what would be the correct settings for me to use memory wise. There are still some things that i am confused upon, and i would really like to get the memory management down pat since the ds is a somewhat limited platform.

StevenH
Posts: 133
Joined: Sun Feb 22, 2009 7:59 pm

Re: Looking to generate random sprite colours

Post by StevenH » Thu Jul 16, 2009 1:30 pm

I can't suggest any settings to use, you just have to know about the way things are stored in the system, most of the time the only overhead you will face is a lack of debugging support if you are used to the IDE's of MS and the like.

The only thing I can sugest is that you keep in mind a few simple facts:

1) Your not coding on a high end PC, keep everything as simple as possible, for me this means I do everything in plain C (which means no fancy classes or default parameters, or even function overloading)
2) Know your NDS pre-defined variable sizes (s8, u8, s16, u16, s32, u32) and use them to keep you right when it comes to memory access.
3) Know the difference between the graphic modes, and how information is saved to them (4bit - 2 pixels per byte, 8bit - 1 pixel per byte, 16 bit - 2 bytes per pixel ). This comes in handy when you want to put a picture on the screen in 8 bit mode and your reading the file manually (most video memory is accessed as 16bit words, not the u8 that the image is stored in)
4) Know the memory structures (OAM entry bitfields etc), they will help with most silly mistakes.
4) Understand that most tutorials are out of date within a week or 3, unless WinterMute is having a hacking time with the tool chains, in which case it could be out of date after a day or two XD

Keep a link to the libnds docs hand all the time.

Oh and most importantly - if your on the IRC channel and ask any questions about devkitPro / devkitARM - get the capitalisation correct before hitting the return key, as well as the actual part of the devkit that you are talking about, otherwise you might find a kick, slap or something thrown at you from WinterMute (he hates it when people say that they are having a problem with DevKitPRO, and they mean a small compiler issue with a function in libnds)...

User avatar
vuurrobin
Posts: 219
Joined: Fri Jul 11, 2008 8:49 pm
Location: The Netherlands
Contact:

Re: Looking to generate random sprite colours

Post by vuurrobin » Thu Jul 16, 2009 1:59 pm

StevenH wrote:1) Your not coding on a high end PC, keep everything as simple as possible, for me this means I do everything in plain C (which means no fancy classes or default parameters, or even function overloading)
I don't know where your coding on, but I'm coding on a IMHO pretty good laptop. seeing as classes, default parameters and function overloading are processed at compile time, there will be no performance penalties on the ds.

it could be that you just prefer c, but there is nothing wrong with c++. just wanted to say that.

StevenH
Posts: 133
Joined: Sun Feb 22, 2009 7:59 pm

Re: Looking to generate random sprite colours

Post by StevenH » Thu Jul 16, 2009 2:18 pm

I prefer C++, but to me the overhead on most of the nice things that C++ gives you is too much on the DS IMHO.

C on the otherhand, to me at least, is a little closer to the hardware level than C++, and when it comes to coding on the DS I'd rather be closer to the hardware level than what C++ is.

And I think I got my on and for mixed on there XD

That should have been "Your not coding for a high end PC, ...". My PC is pretty high end for me at least...

hassifa
Posts: 15
Joined: Thu Jul 16, 2009 2:22 am

Re: Looking to generate random sprite colours

Post by hassifa » Thu Jul 16, 2009 2:49 pm

Well its not like i dont know the c / c++ languages, as i am doing a degree at university in computer science. Its more getting used to the toolchain and the available methods and structures in it. My group in the uni game making club decided to make one on the ds, so here i am.

hassifa
Posts: 15
Joined: Thu Jul 16, 2009 2:22 am

Re: Looking to generate random sprite colours

Post by hassifa » Sat Jul 18, 2009 1:54 pm

Ok, now i have a different sort of problem.
I wanted to have a simple popping animation for when a balloon is touched, so what i have done is
loaded the 3 32x32 4bit sprites into memory, using the following piece of code.

Code: Select all

//balloon.h
static u16* balloon_gfx_mem;
static u16* balloon_pop1_gfx_mem;
static u16* balloon_pop2_gfx_mem;
static u16* balloon_gfx_mem_sub;

//main.cpp setupGraphics()
	balloon_gfx_mem = oamAllocateGfx(&oamMain,SpriteSize_32x32, SpriteColorFormat_16Color);
	balloon_pop1_gfx_mem = oamAllocateGfx(&oamMain,SpriteSize_32x32, SpriteColorFormat_16Color);
	balloon_pop2_gfx_mem = oamAllocateGfx(&oamMain,SpriteSize_32x32, SpriteColorFormat_16Color);
	balloon_gfx_mem_sub = oamAllocateGfx(&oamSub,SpriteSize_32x32, SpriteColorFormat_16Color);

	dmaCopy(gfx_balloonTiles, balloon_gfx_mem, gfx_balloonTilesLen);// copy sprite tile into allocated space
	dmaCopy(gfx_balloon_pop1Tiles, balloon_pop1_gfx_mem, gfx_balloon_pop1TilesLen);
	dmaCopy(gfx_balloon_pop2Tiles, balloon_pop2_gfx_mem, gfx_balloon_pop2TilesLen);
	dmaCopy(gfx_balloonTiles, balloon_gfx_mem_sub, gfx_balloonTilesLen);
Now for each balloon, i have a pointer that goes directly to one of these pointers, and each balloon render method calls the oamSet() method with its own pointer. My problem is that the sprites doesnt change properly when i want it to 'aniamte'.
The following is the programming i use to try and modify the sprites during the animation.

Code: Select all

//balloon.cpp update()
	if(popping)
	{
		switch(frame)
		{
			case 1:
				paletteAlpha = 1;
				//pToGfx = balloon_pop1_gfx_mem;
				break;
			case 6:
				paletteAlpha = 2;
				//pToGfx = balloon_pop2_gfx_mem;
				break;
			case 12:
				switchActive();
				paletteAlpha = 0;
				break;
		}
		frame++;
		return;
	}
The two commented lines are where i want to try and change the sprite, but it doesnt seem to work. I know the tiles are in the program and do display correctly when i set the sprites gfx during the wave setup method.

Code: Select all

//main.cpp
void startWave()		// function to start the next wave
{
	resetBalloons();
	int n;
	for( n = 0; n < BALLOONS_PER_WAVE*wave; n++)
	{
		balloonArray[n].setX(((rand() % 224) + 16) << 8);	// assign a random x location
		balloonArray[n].setY(((rand() % (100*wave)) + 195) << 8);	// assign a random y location underneath
	}
}
void resetBalloons()		// function to reset balloon status
{
	int n;
	for( n = 0; n < MAX_NUM_OF_BALLOONS; n++)
	{
		balloonArray[n].resetActive();
		balloonArray[n].setOnBottom();
		balloonArray[n].resetPopping();
		balloonArray[n].resetFrame();
	}
}

//balloon.h
void setOnBottom() {onBottomScreen = true; pToGfx = balloon_gfx_mem;}
When i change pToGfx in this location to one of the other sprite variables, it displayed the correct animation slice i want, but when i try to change it in the update function above, it just defaults back to the full balloon again, and i dont know why this is happening for.

My main game loop essentially calls the balloon update method for every balloon in the wave, waits for vBlank, and then updates all of the associated graphics, including a call to the balloon render() method .

Code: Select all

void Balloon::render()
{
	int renx, reny;
	renx = ((x - (16<<8)) >> 8);	// get the render co-ordinates
	reny = ((y - (16<<8)) >> 8);	// using fixed point arithmatic

	oamSet(	onBottomScreen ? &oamMain : &oamSub,
			sprite_index,
			renx, reny,
			priority,
			paletteAlpha,
			size,
			format,
			pToGfx,
			rotationIndex,
			false,
			(!active || hide),
			false, false, false);
}
I'll keep playing around with it, but i dont know why its not updating for.

User avatar
vuurrobin
Posts: 219
Joined: Fri Jul 11, 2008 8:49 pm
Location: The Netherlands
Contact:

Re: Looking to generate random sprite colours

Post by vuurrobin » Sat Jul 18, 2009 6:40 pm

Code: Select all

balloon_pop1_gfx_mem = oamAllocateGfx(&oamMain,SpriteSize_32x32, SpriteColorFormat_16Color);
balloon_pop2_gfx_mem = oamAllocateGfx(&oamMain,SpriteSize_32x32, SpriteColorFormat_16Color);
the balloon pops on the bottom screen, but you allocate vram for the main engine (while the main engine defaults to the top screen). is there any reason why you switched the engines around? AFAIK, there aren't many differences between them when just using 2d, and it makes things harder to follow (at least, it does for me), which means it is easier to make mistakes.

Code: Select all

switch(frame)
{
	case 1:
		paletteAlpha = 1;
		//pToGfx = balloon_pop1_gfx_mem;
		break;
	case 6:
		paletteAlpha = 2;
		//pToGfx = balloon_pop2_gfx_mem;
		break;
	case 12:
		switchActive();
		paletteAlpha = 0;
		break;
}
have you made sure that the function enters the cases? try placing a few printf() in it. also, you might want to either use constants/defines instead of 1,6 and 12, or place some comments with it.


I hope this helps

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests