Users browsing this thread: 1 Guest(s)
Monster assembling code (c#) *SOLVED*
I'm trying to mimic part of Terii Senshi's FF3se code in C# to assemble monsters. However I ran into a bug that I am unable to fix at the moment.
Here's part of my C# function. The graphics data, mold and palette seems to be right. However I get a weird result, an oversized guard due to some spaces on the x axis and I cannot pinpoint what is doing this. (I suck)
Any help would be appreciated!
the loadTile() function:
Terii's Senshi code:
Here's part of my C# function. The graphics data, mold and palette seems to be right. However I get a weird result, an oversized guard due to some spaces on the x axis and I cannot pinpoint what is doing this. (I suck)
Any help would be appreciated!
Code:
private WriteableBitmap createBitmap(Monster monster, byte[] graphicsData)
{
int moldPtr = 0;
int graphPtr = 0;
byte[] tile = new byte[64];
byte[] moldData;
byte[] graphics;
BitmapPalette bPal;
Color[] pal;
WriteableBitmap wBmp;
Int32Rect rect;
// if monster is 8 colors, get the right palette.
if (monster.numColors == 8)
{
pal = this.monsPals.ElementAt(monster.palette);
}
// if monster is 16 colors, build the palette based on monster palette and next palette.
// Seems to be good in the guard example
else
{
pal = new Color[16];
Color[] pal1 = this.monsPals.ElementAt(monster.palette);
Color[] pal2 = this.monsPals.ElementAt(monster.palette + 1);
for(int j = 0; j < 8; j++)
{
pal[j] = pal1[j];
pal[j + 8] = pal2[j];
}
}
// Apply transparency to first color of palette.
pal[0].A = 0;
// Used by WriteableBitmap constructor
bPal = new BitmapPalette(pal);
// if size is 64x64
if(monster.size == 0)
{
// create new bitmap
wBmp = new WriteableBitmap(64, 64, 96, 96, PixelFormats.Indexed4, bPal);
// Get mold data (this is correct in the guard example)
moldData = ByteUtils.GetBytes(this.molds8, monster.mold * 64, 64);
for(int y = 0; y < 8; y++)
{
for(int x = 0; x < 8; x++)
{
// if there's a tile present in the 8x8 mold array
if(moldData[moldPtr++] == 1)
{
if(monster.numColors == 16)
{
// Get the graphics of the tile
graphics = ByteUtils.GetBytes(graphicsData, graphPtr, 32);
graphPtr += 32;
}
else
{
graphics = ByteUtils.GetBytes(graphicsData, graphPtr, 24);
graphPtr += 24;
}
// Get a 8x8 indexed tile
tile = Graphics.loadTile(graphics, monster.numColors);
// (x position, y position, width, height)
rect = new Int32Rect(x * 8, y * 8, 8, 8);
// write the pixel on the main bitmap
// (rectangle to update, pixel array, stride, input buffer offset)
wBmp.WritePixels(rect, tile, 8, 0);
}
}
}
}
the loadTile() function:
Code:
public static byte[] loadTile(byte[] graphics, int colors)
{
byte[] tile = new byte[64];
int i = 0;
byte c;
for(int y = 0; y < 8; y++)
{
c = graphics[i++];
tile[y * 8 + 7] += (byte)((c & 0x01) >> 0);
tile[y * 8 + 6] += (byte)((c & 0x02) >> 1);
tile[y * 8 + 5] += (byte)((c & 0x04) >> 2);
tile[y * 8 + 4] += (byte)((c & 0x08) >> 3);
tile[y * 8 + 3] += (byte)((c & 0x10) >> 4);
tile[y * 8 + 2] += (byte)((c & 0x20) >> 5);
tile[y * 8 + 1] += (byte)((c & 0x40) >> 6);
tile[y * 8 + 0] += (byte)((c & 0x80) >> 7);
c = graphics[i++];
tile[y * 8 + 7] += (byte)((c & 0x01) >> 1);
tile[y * 8 + 6] += (byte)((c & 0x02) >> 0);
tile[y * 8 + 5] += (byte)((c & 0x04) >> 1);
tile[y * 8 + 4] += (byte)((c & 0x08) >> 2);
tile[y * 8 + 3] += (byte)((c & 0x10) >> 3);
tile[y * 8 + 2] += (byte)((c & 0x20) >> 4);
tile[y * 8 + 1] += (byte)((c & 0x40) >> 5);
tile[y * 8 + 0] += (byte)((c & 0x80) >> 6);
}
for (int y = 0; y < 8; y++)
{
c = graphics[i++];
tile[y * 8 + 7] += (byte)((c & 0x01) >> 2);
tile[y * 8 + 6] += (byte)((c & 0x02) >> 1);
tile[y * 8 + 5] += (byte)((c & 0x04) >> 0);
tile[y * 8 + 4] += (byte)((c & 0x08) >> 1);
tile[y * 8 + 3] += (byte)((c & 0x10) >> 2);
tile[y * 8 + 2] += (byte)((c & 0x20) >> 3);
tile[y * 8 + 1] += (byte)((c & 0x40) >> 4);
tile[y * 8 + 0] += (byte)((c & 0x80) >> 5);
if (colors == 16)
{
c = graphics[i++];
tile[y * 8 + 7] += (byte)((c & 0x01) >> 3);
tile[y * 8 + 6] += (byte)((c & 0x02) >> 2);
tile[y * 8 + 5] += (byte)((c & 0x04) >> 1);
tile[y * 8 + 4] += (byte)((c & 0x08) >> 0);
tile[y * 8 + 3] += (byte)((c & 0x10) >> 1);
tile[y * 8 + 2] += (byte)((c & 0x20) >> 2);
tile[y * 8 + 1] += (byte)((c & 0x40) >> 3);
tile[y * 8 + 0] += (byte)((c & 0x80) >> 4);
}
}
return tile;
}
}
Terii's Senshi code:
Code:
void Monster::createBitmap(BYTE *ptr)
{
int x,y,i;
BYTE tile[64];
BYTE *moldPtr;
if(ptr == NULL)
ptr = monsters.image[imageNum].graphicsData;
mold = monsters.image[imageNum].mold;
size = monsters.image[imageNum].size;
numColors = monsters.image[imageNum].numColors;
if(size == 0)
{
pic.createBlank(64,64);
for(i = 0;i < numColors;i++)
{
pic.setColor(i,monsters.monsPals[palette][i]);
}
moldPtr = &(monsters.molds8[mold * 64]);
for(y = 0;y < 8;y++)
{
for(x = 0;x < 8;x++)
{
if(*(moldPtr++) == 1)
{
loadTile(ptr,tile,numColors);
pic.copyTile(tile,x,y);
if(numColors == 16)
ptr += 32;
else
ptr += 24;
}
}
}
}
**************************************
void loadTile(BYTE *ptr,BYTE *tile,BYTE colors)
{
int y;
BYTE c;
ZeroMemory(tile,64);
for(y = 0;y < 8;y++)
{
c = *(ptr++);
tile[7 + y * 8] += (c & 0x01) >> 0;
tile[6 + y * 8] += (c & 0x02) >> 1;
tile[5 + y * 8] += (c & 0x04) >> 2;
tile[4 + y * 8] += (c & 0x08) >> 3;
tile[3 + y * 8] += (c & 0x10) >> 4;
tile[2 + y * 8] += (c & 0x20) >> 5;
tile[1 + y * 8] += (c & 0x40) >> 6;
tile[0 + y * 8] += (c & 0x80) >> 7;
c = *(ptr++);
tile[7 + y * 8] += (c & 0x01) << 1;
tile[6 + y * 8] += (c & 0x02) >> 0;
tile[5 + y * 8] += (c & 0x04) >> 1;
tile[4 + y * 8] += (c & 0x08) >> 2;
tile[3 + y * 8] += (c & 0x10) >> 3;
tile[2 + y * 8] += (c & 0x20) >> 4;
tile[1 + y * 8] += (c & 0x40) >> 5;
tile[0 + y * 8] += (c & 0x80) >> 6;
}
for(y = 0;y < 8;y++)
{
c = *(ptr++);
tile[7 + y * 8] += (c & 0x01) << 2;
tile[6 + y * 8] += (c & 0x02) << 1;
tile[5 + y * 8] += (c & 0x04) >> 0;
tile[4 + y * 8] += (c & 0x08) >> 1;
tile[3 + y * 8] += (c & 0x10) >> 2;
tile[2 + y * 8] += (c & 0x20) >> 3;
tile[1 + y * 8] += (c & 0x40) >> 4;
tile[0 + y * 8] += (c & 0x80) >> 5;
if(colors == 16)
{
c = *(ptr++);
tile[7 + y * 8] += (c & 0x01) << 3;
tile[6 + y * 8] += (c & 0x02) << 2;
tile[5 + y * 8] += (c & 0x04) << 1;
tile[4 + y * 8] += (c & 0x08) >> 0;
tile[3 + y * 8] += (c & 0x10) >> 1;
tile[2 + y * 8] += (c & 0x20) >> 2;
tile[1 + y * 8] += (c & 0x40) >> 3;
tile[0 + y * 8] += (c & 0x80) >> 4;
}
}
}
********************************************
BYTE Bitmap::copyTile(BYTE *tile,int x,int y)
{
BYTE *ptr;
int x2,y2;
if(((x * 8) >= (width - 7)) || ((y * 8) >= (height - 7)))
return 1;
ptr = &(pixels[x * 8 + (y * 8) * width]);
for(y2 = 0; y2 < 8;y2++)
{
for(x2 = 0;x2 < 8;x2++)
{
*(ptr++) = *(tile++);
}
ptr += width - 8;
}
return 0;
}
You seem to have a number of right shifts where there should be left shifts.
Example:
this line has a wrong shift (right shift, should be left) according to Senshi's code:
There are more left shifts you have written as right shifts.
Edit: btw, the tool looks really nice, nice work.
Example:
Code:
tile[y * 8 + 7] += (byte)((c & 0x01) >> 1);
this line has a wrong shift (right shift, should be left) according to Senshi's code:
Code:
tile[7 + y * 8] += (c & 0x01) << 1;
There are more left shifts you have written as right shifts.
Edit: btw, the tool looks really nice, nice work.
06-23-2015, 03:30 PM
I think the order of your arithmetic operations is wrong aswell.
If y = 2
You write: y * 8 + 7
Your result is: 23
Senshi writes: 7 + y * 8
Senshi's result is: 72
This is happens because programming languages process arithmetics from left to right and not in order of priority as is taught in math (in math both should result in 23).
You can think of it like this:
You: ((y * 8) + 7)
Senshi: ((7 + y) * 8)
If y = 2
You write: y * 8 + 7
Your result is: 23
Senshi writes: 7 + y * 8
Senshi's result is: 72
This is happens because programming languages process arithmetics from left to right and not in order of priority as is taught in math (in math both should result in 23).
You can think of it like this:
You: ((y * 8) + 7)
Senshi: ((7 + y) * 8)
(06-23-2015, 03:58 PM)m06 Wrote: I think the order of your arithmetic operations is wrong aswell.
Thanks! I did changed that like you suggested. I found out the oversizing of the monster was the result of my preview window resizing it automatically. Now the sprite is the good size, but there's still some lines on it:
Edit: prioritizing the addition first will get an exception because if y = 7, (7 + 7) * 8 is higher than 64 (112) . So the right way is 7 * 8 + 7, 63, the last index of the tile array.
Edit2: I will try applying the byte shift to the whole addition, something like this:
tile[7 + y * 8] = (byte)((tile[7 + y * 8] + (c & 0x01)) >> 0);
Edit3: ^this was a bad idea
06-23-2015, 06:08 PM
I implemented a method that writes each pixels individually instead of WritePixels() and the output is good:
It's a bit slower I think but unless someone come with the proper way to use WritePixels() with a rectangle, we can consider this case closed.
It's a bit slower I think but unless someone come with the proper way to use WritePixels() with a rectangle, we can consider this case closed.
06-23-2015, 06:08 PM
Senshi's byte accessing is really weird. I guess you were doing it correctly before.
It looks like you are doing things correctly, and the bug looks very strange.
One thing I could think of is if the stride is wrong. If each pixel is 2 bytes in the final image the stride should be 16 I guess.
For some dynamic stride:
It looks like you are doing things correctly, and the bug looks very strange.
One thing I could think of is if the stride is wrong. If each pixel is 2 bytes in the final image the stride should be 16 I guess.
For some dynamic stride:
Code:
wBmp.WritePixels(rect, tile, 8, 0);
change to:
wBmp.WritePixels(rect, tile, 8 * (wBmp.Format.BitsPerPixel/8), 0);
06-23-2015, 06:17 PM
I think you may be right (wrong stride and/or format) but I tried changing the stride to 16 and it cause an exception. But anyway, since my WriteableBitmap library can only manage the Pbgra32 format, I have to use the method I described in my previous post. I'm glad the part of assembling a sprite is over me now, I should be able to manage the rest alone (hopefully).
06-23-2015, 06:43 PM
I'm glad you have a working solution
I suggest trying the dynamic version I posted, it's derived from this tutorial I found:
http://www.i-programmer.info/programming...ml?start=1
I suggest trying the dynamic version I posted, it's derived from this tutorial I found:
http://www.i-programmer.info/programming...ml?start=1
« Next Oldest | Next Newest »
Users browsing this thread: 1 Guest(s)