#72590 - Linkiboy - Mon Feb 20, 2006 3:58 am
This has been bugging me for ages.
I'm trying to display two different sprites, but they come out as one sprite which is one on top of the other. Here is a picture of what is happening:
http://img132.imageshack.us/img132/3878/problem6pu.jpg
Someone explain how this works, please.
Here is my code....
Code: |
#include "..\nds.h"
#include "..\memory.h"
#include "..\screen.h"
#include "..\system.h"
#include "..\keys.h"
#include "..\ipc.h"
#include "ship.h"
int x,y,spritex,spritey,tempx,tempy,wait,i;
void removesprites() //function, outside main, must be called from within main
{
int i;
for(i = 0; i < 1024; i++)
OAM[i * 4] = ATTR0_DISABLED;
}
int main()
{
powerON(POWER_ALL);
videoSetMode(MODE_0_2D | SPR_1D_LAYOUT | SPR_ACTIVE); //activates 2d and turns on sprites in 1d mode
VRAM_BANK_A(VRAM_SPRITE); //sprite vram
for(i = 0; i < 512; i++)
SPRITE_PALETTE[i] = ((u16*)shipPalette)[i];
for(i = 0; i < 32*16; i++)
SPRITE_GFX[i] = ((u16*)shipData)[i];
for(i = 0; i < 256; i++)
removesprites();
y = 150;
x = 120;
SPRITE_PALETTE[1] = RGB(31,0,0); //sprites pallet
SPRITE_GFX[0] = 0x0000; //sprite image data
SPRITE_GFX[1] = 0x0101;
SPRITE_GFX[2] = 0x0101;
SPRITE_GFX[3] = 0x0000;
SPRITE_GFX[4] = 0x0100;
SPRITE_GFX[5] = 0x0000;
SPRITE_GFX[6] = 0x0000;
SPRITE_GFX[7] = 0x0001;
SPRITE_GFX[8] = 0x0100;
SPRITE_GFX[9] = 0x0000;
SPRITE_GFX[10] = 0x0000;
SPRITE_GFX[11] = 0x0001;
SPRITE_GFX[12] = 0x0000;
SPRITE_GFX[13] = 0x0101;
SPRITE_GFX[14] = 0x0101;
SPRITE_GFX[15] = 0x0000;
SPRITE_GFX[16] = 0x0000;
SPRITE_GFX[17] = 0x0100;
SPRITE_GFX[18] = 0x0001;
SPRITE_GFX[19] = 0x0000;
SPRITE_GFX[20] = 0x0000;
SPRITE_GFX[21] = 0x0101;
SPRITE_GFX[22] = 0x0101;
SPRITE_GFX[23] = 0x0000;
SPRITE_GFX[24] = 0x0000;
SPRITE_GFX[25] = 0x0100;
SPRITE_GFX[26] = 0x0001;
SPRITE_GFX[27] = 0x0000;
SPRITE_GFX[28] = 0x0000;
SPRITE_GFX[29] = 0x0001;
SPRITE_GFX[30] = 0x0100;
SPRITE_GFX[31] = 0x0000;
removesprites(); //uses function to remove sprites from the screen
spritey = 50;
spritex = 100;
while(1)
{
if(READ_KEYS & KEY_LEFT)
{
tempx = x;
tempx--;
if(tempx>0 & (tempx<spritex-16 | tempx>spritex+16 | y<spritey-16 | y>spritey+16)){x = tempx;}
}
if(READ_KEYS & KEY_RIGHT)
{
tempx = x;
tempx++;
if(tempx<248 & (tempx<spritex-16 | tempx>spritex+16 | y<spritey-16 | y>spritey+16)){x = tempx;}
}
OAM[0] = ATTR0_COLOR_256 | ATTR0_SQUARE | spritey; //ATTR0, atribute which controls sprites colour, shape and x coord
OAM[1] = ATTR1_SIZE_16 | spritex; //ATTR1 is size and y coord
OAM[2] = 0; //ATTR2 is sprite img no.
OAM[4] = ATTR0_COLOR_256 | ATTR0_SQUARE | y; //ATTR0, atribute which controls sprites colour, shape and y coord
OAM[5] = ATTR1_SIZE_16 | x; //ATTR1 is size and x coord
OAM[6] = 0; //ATTR2 is sprite img no.
//oam3 rotates and zooms but is not needed
WaitForVBlank();
}
} |
#72637 - waruwaru - Mon Feb 20, 2006 6:40 pm
Code: |
if(tempx>0 & (tempx<spritex-16 | tempx>spritex+16 | y<spritey-16 | y>spritey+16)){x = tempx;}
}
if(READ_KEYS & KEY_RIGHT)
{
tempx = x;
tempx++;
if(tempx<248 & (tempx<spritex-16 | tempx>spritex+16 | y<spritey-16 | y>spritey+16)){x = tempx;}
}
|
Not sure if this is your problem, but I think you want the boolean operators && and ||, instead of the bit operators & and |. Also, personally, I like to put () around each expression, so I don't have to worry about operator precedence. Something like:
Code: |
if( (tempx>0) && ( (tempx<(spritex-16)) || (tempx>(spritex+16)) || (y<(spritey-16)) || (y>(spritey+16))))
{
x = tempx;
}
|
#72706 - Linkiboy - Tue Feb 21, 2006 4:05 am
No thats not the problem, but thanks for trying.
#72708 - tepples - Tue Feb 21, 2006 4:21 am
Linkiboy wrote: |
Code: | for(i = 0; i < 32*16; i++)
SPRITE_GFX[i] = ((u16*)shipData)[i];
// ...
SPRITE_GFX[0] = 0x0000; //sprite image data
SPRITE_GFX[1] = 0x0101;
SPRITE_GFX[2] = 0x0101;
SPRITE_GFX[3] = 0x0000;
SPRITE_GFX[4] = 0x0100;
SPRITE_GFX[5] = 0x0000;
SPRITE_GFX[6] = 0x0000;
SPRITE_GFX[7] = 0x0001;
SPRITE_GFX[8] = 0x0100;
SPRITE_GFX[9] = 0x0000;
SPRITE_GFX[10] = 0x0000;
SPRITE_GFX[11] = 0x0001;
SPRITE_GFX[12] = 0x0000;
SPRITE_GFX[13] = 0x0101;
SPRITE_GFX[14] = 0x0101;
SPRITE_GFX[15] = 0x0000;
SPRITE_GFX[16] = 0x0000;
SPRITE_GFX[17] = 0x0100;
SPRITE_GFX[18] = 0x0001;
SPRITE_GFX[19] = 0x0000;
SPRITE_GFX[20] = 0x0000;
SPRITE_GFX[21] = 0x0101;
SPRITE_GFX[22] = 0x0101;
SPRITE_GFX[23] = 0x0000;
SPRITE_GFX[24] = 0x0000;
SPRITE_GFX[25] = 0x0100;
SPRITE_GFX[26] = 0x0001;
SPRITE_GFX[27] = 0x0000;
SPRITE_GFX[28] = 0x0000;
SPRITE_GFX[29] = 0x0001;
SPRITE_GFX[30] = 0x0100;
SPRITE_GFX[31] = 0x0000;
|
|
Here you copy in the ship, but then you overwrite it with the spaceman.
Quote: |
Code: | OAM[0] = ATTR0_COLOR_256 | ATTR0_SQUARE | spritey; //ATTR0, atribute which controls sprites colour, shape and x coord
OAM[1] = ATTR1_SIZE_16 | spritex; //ATTR1 is size and y coord
OAM[2] = 0; //ATTR2 is sprite img no.
OAM[4] = ATTR0_COLOR_256 | ATTR0_SQUARE | y; //ATTR0, atribute which controls sprites colour, shape and y coord
OAM[5] = ATTR1_SIZE_16 | x; //ATTR1 is size and x coord
OAM[6] = 0; //ATTR2 is sprite img no.
|
|
Here you use the same "sprite img no." for both sprites, which turns out to be a ship partially overwritten with a spaceman.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#72710 - Linkiboy - Tue Feb 21, 2006 4:28 am
tepples wrote: |
Linkiboy wrote: | Code: | for(i = 0; i < 32*16; i++)
SPRITE_GFX[i] = ((u16*)shipData)[i];
// ...
SPRITE_GFX[0] = 0x0000; //sprite image data
SPRITE_GFX[1] = 0x0101;
SPRITE_GFX[2] = 0x0101;
SPRITE_GFX[3] = 0x0000;
SPRITE_GFX[4] = 0x0100;
SPRITE_GFX[5] = 0x0000;
SPRITE_GFX[6] = 0x0000;
SPRITE_GFX[7] = 0x0001;
SPRITE_GFX[8] = 0x0100;
SPRITE_GFX[9] = 0x0000;
SPRITE_GFX[10] = 0x0000;
SPRITE_GFX[11] = 0x0001;
SPRITE_GFX[12] = 0x0000;
SPRITE_GFX[13] = 0x0101;
SPRITE_GFX[14] = 0x0101;
SPRITE_GFX[15] = 0x0000;
SPRITE_GFX[16] = 0x0000;
SPRITE_GFX[17] = 0x0100;
SPRITE_GFX[18] = 0x0001;
SPRITE_GFX[19] = 0x0000;
SPRITE_GFX[20] = 0x0000;
SPRITE_GFX[21] = 0x0101;
SPRITE_GFX[22] = 0x0101;
SPRITE_GFX[23] = 0x0000;
SPRITE_GFX[24] = 0x0000;
SPRITE_GFX[25] = 0x0100;
SPRITE_GFX[26] = 0x0001;
SPRITE_GFX[27] = 0x0000;
SPRITE_GFX[28] = 0x0000;
SPRITE_GFX[29] = 0x0001;
SPRITE_GFX[30] = 0x0100;
SPRITE_GFX[31] = 0x0000;
|
|
Here you copy in the ship, but then you overwrite it with the spaceman.
Quote: | Code: | OAM[0] = ATTR0_COLOR_256 | ATTR0_SQUARE | spritey; //ATTR0, atribute which controls sprites colour, shape and x coord
OAM[1] = ATTR1_SIZE_16 | spritex; //ATTR1 is size and y coord
OAM[2] = 0; //ATTR2 is sprite img no.
OAM[4] = ATTR0_COLOR_256 | ATTR0_SQUARE | y; //ATTR0, atribute which controls sprites colour, shape and y coord
OAM[5] = ATTR1_SIZE_16 | x; //ATTR1 is size and x coord
OAM[6] = 0; //ATTR2 is sprite img no.
|
|
Here you use the same "sprite img no." for both sprites, which turns out to be a ship partially overwritten with a spaceman. |
OK, so I changed it so that the image no. is 1 instead of 0. But how do I make it so the spaceman is not owerwriting the ship? That is the question that has REALLY been killing me.
#72714 - tepples - Tue Feb 21, 2006 5:00 am
The ship is 4 256-color tiles, right? Each tile is 32 u16s, so try writing the spaceman starting at SPRITE_GFX[128].
And why are you using 256-color tiles for such simple graphics?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#72760 - Linkiboy - Tue Feb 21, 2006 2:20 pm
tepples wrote: |
The ship is 4 256-color tiles, right? Each tile is 32 u16s, so try writing the spaceman starting at SPRITE_GFX[128].
And why are you using 256-color tiles for such simple graphics? |
ATM it's only temporary, they will be much more complex for the actual game. Thanks, tepples.
edit: and one more question...
What if I wanted to have 2 sprite files that are like this:
for(i = 0; i < 128; i++)
SPRITE_PALETTE[i] = ((u16*)testPalette)[i];
for(i = 0; i < 32*16; i++)
SPRITE_GFX[i] = ((u16*)testData)[i];
for(i = 0; i < 64; i++)
would the second sprite be something like:
for(i = 128; i < 128; i++)
SPRITE_PALETTE[i] = ((u16*)test2Palette)[i];
for(i = 128; i < 32*16; i++)
SPRITE_GFX[i] = ((u16*)test2Data)[i];
for(i = 128; i < 64; i++)
I'm sorry if the answer is obvious/i'm posting a really stupid attempt.
#72780 - Maverick - Tue Feb 21, 2006 6:38 pm
for(i = 0; i < 128; i++)
SPRITE_PALETTE[i+128] = ((u16*)test2Palette)[i];
for(i = 0; i < 32*16; i++)
SPRITE_GFX[i+(32*16)] = ((u16*)test2Data)[i];
for(i = 0; i < 64; i++)
_________________
http://downtou.ne1.net/
#72815 - strager - Tue Feb 21, 2006 11:06 pm
Quote: |
and one more question...
What if I wanted to have 2 sprite files that are like this:
[...]
would the second sprite be something like:
[...]
I'm sorry if the answer is obvious/i'm posting a really stupid attempt. |
I would say create some temporary variables, and update those:
Code: |
typedef u16 color; // In case you are going to port the prog. to another system, this may help.
typedef u8 index; // Same here
// ...
color *curpal = SPRITE_PALETTE;
index *curidx = SPRITE_GFX;
// ...
// Load first sprite
for(i = 0; i < palette1_size; i++, curpal++) {
*curpal = palette1[i];
}
for(i = 0; i < data1_size; i++, curidx++) {
*curidx = data1[i];
}
// Load second sprite
for(i = 0; i < palette2_size; i++, curpal++) {
*curpal = palette2[i];
}
for(i = 0; i < data2_size; i++, curidx++) {
*curidx = data2[i];
}
// Add more for every dataN
// Load sprite attribute data
// ...
|
Although this works, it may be easier to make some support functions to do it for you. This would help clean up some space in your main function, as well as save some ROM space. Two static variables would be used for the counters, and if it receives an input of NULL, reset the counters (if you want to restart the whole process...).
#72819 - Linkiboy - Tue Feb 21, 2006 11:34 pm
I tried that..
for(i = 0; i < 128; i++)
SPRITE_PALETTE[i] = ((u16*)shipPalette)[i];
for(i = 0; i < 32*16; i++)
SPRITE_GFX[i] = ((u16*)shipData)[i];
for(i = 0; i < 64; i++)
removesprites();
y = 150;
x = 120;
for(i = 0; i < 128; i++)
SPRITE_PALETTE[i+128] = ((u16*)enemyshipPalette)[i];
for(i = 0; i < 32*16; i++)
SPRITE_GFX[i+(32*16)] = ((u16*)enemyshipData)[i];
for(i = 0; i < 64; i++)
removesprites();
enemyx=50;
enemyy=50;
...but the enemy ship is jumbled. Anything else that I should know about?
(Both are 16x16 256 color tiles)
#72830 - Linkiboy - Wed Feb 22, 2006 1:12 am
strager wrote: |
Quote: | and one more question...
What if I wanted to have 2 sprite files that are like this:
[...]
would the second sprite be something like:
[...]
I'm sorry if the answer is obvious/i'm posting a really stupid attempt. |
I would say create some temporary variables, and update those:
Code: |
typedef u16 color; // In case you are going to port the prog. to another system, this may help.
typedef u8 index; // Same here
// ...
color *curpal = SPRITE_PALETTE;
index *curidx = SPRITE_GFX;
// ...
// Load first sprite
for(i = 0; i < palette1_size; i++, curpal++) {
*curpal = palette1[i];
}
for(i = 0; i < data1_size; i++, curidx++) {
*curidx = data1[i];
}
// Load second sprite
for(i = 0; i < palette2_size; i++, curpal++) {
*curpal = palette2[i];
}
for(i = 0; i < data2_size; i++, curidx++) {
*curidx = data2[i];
}
// Add more for every dataN
// Load sprite attribute data
// ...
|
Although this works, it may be easier to make some support functions to do it for you. This would help clean up some space in your main function, as well as save some ROM space. Two static variables would be used for the counters, and if it receives an input of NULL, reset the counters (if you want to restart the whole process...). |
Hhmm... that seems like an interesting method. I shall try it... I'll post when results arrive.
#73048 - Linkiboy - Wed Feb 22, 2006 11:51 pm
Code: |
#include "..\nds.h"
#include "..\memory.h"
#include "..\screen.h"
#include "..\system.h"
#include "..\keys.h"
#include "..\ipc.h"
#include "ship.h"
#include "eship.h"
int x,y,spritex,spritey,tempx,tempy,wait,i,bulletx,bullety,ableto,enemyx,enemyy;
void removesprites()
{
int i;
for(i = 0; i < 2048; i++)
OAM[i * 4] = ATTR0_DISABLED;
}
int main()
{
powerON(POWER_ALL);
videoSetMode(MODE_0_2D | SPR_1D_LAYOUT | SPR_ACTIVE); //activates 2d and turns on sprites in 1d mode
VRAM_BANK_A(VRAM_SPRITE); //sprite vram
typedef u16 color; // In case you are going to port the prog. to another system, this may help.
typedef u8 index; // Same here
color *curpal = SPRITE_PALETTE;
index *curidx = SPRITE_GFX;
for(i = 0; i < 256; i++, curpal++) {
*curpal = shipPalette[i];
}
for(i = 0; i < SHIP_SIZE; i++, curidx++) {
*curidx = shipData[i];
}
x = 50;
y = 50;
// Load second sprite
for(i = 0; i < 256; i++, curpal++) {
*curpal = enemyshipPalette[i];
}
for(i = 0; i < ENEMYSHIP_SIZE; i++, curidx++) {
*curidx = enemyshipData[i];
}
enemyy = 100;
enemyx = 100;
while(1)
{
if(READ_KEYS & KEY_LEFT)
{
tempx = x;
tempx--;
if(tempx>0 & (tempx<spritex-16 | tempx>spritex+16 | y<spritey-16 | y>spritey+16)){x = tempx;}
}
if(READ_KEYS & KEY_RIGHT)
{
tempx = x;
tempx++;
if(tempx<248 & (tempx<spritex-16 | tempx>spritex+16 | y<spritey-16 | y>spritey+16)){x = tempx;}
}
OAM[0] = ATTR0_COLOR_256 | ATTR0_SQUARE | y; //ATTR0, atribute which controls sprites colour, shape and y coord
OAM[1] = ATTR1_SIZE_16 | x; //ATTR1 is size and x coord
OAM[2] = 0; //ATTR2 is sprite img no.
OAM[4] = ATTR0_COLOR_256 | ATTR0_SQUARE | enemyy; //ATTR0, atribute which controls sprites colour, shape and y coord
OAM[5] = ATTR1_SIZE_16 | enemyx; //ATTR1 is size and x coord
OAM[6] = 1; //ATTR2 is sprite img no.
//oam3 rotates and zooms but is not needed
WaitForVBlank();
}
}
|
Doesn't work. Did I make a mistake again?