Woohoo, another massive Mega wall-of-text that is going to be TL;DR'd by the majority of the internet!
The reason I've been offline for a while is twofold, but both sides to the problem lie in the fact that I don't have my own internet connection, I use my dad's. Independance is great, but requires gainful employment first. And I still haven't got the latter. So basically, because of an argument/dispute/I'mRightSoShutUp I had a few days before writing this, I was told:"OK. Sure. You're right, but you can't use the internet now for <x> amount of time." (Where x is an unknown variable that depends on whether my parents decide I'm being condescending enough to deserve my time on the internet).Anyway, it doesn't hurt me. Since I do most of my work offline, I got a lot done. I did kinda just disappear from the Minecraft server, which was annoying (I had just started building a shelter/outhouse when I was 'kicked' by Windows >_>). Anyway… disclaimer:This blog may contain traces of Error, a sprinkling of Length, and just a Dash of Awesome…As the title explains, I'm now working with XNA (Which is made a lot easier now that I understand the ins and outs of the C# language).So I sat down this evening and opened the VC# Express 2010 IDE, and started working on a platformer. As per tradition, I'm using placeholder art, but even so, to my dismay I discovered that there is no built in support for animated sprites. So the first thing I had to do? Make a class that can load and draw animated sprites with all the bells and whistles (Origin, Scaling, Flipping). And I did. The result is as follows:
Source code
class MXSprite
{
private Texture2D spriteData;
private int x;
private int y;
private int width;
private int height;
private int origin_x;
private int origin_y;
private int numframes;
private double speed;
private double scale;
private bool flip_x;
private bool flip_y;
private bool isLoaded;
// Current Frame and Frame Counter
private int c_frame;
private double fcount;
// Status values and properties
private bool isFrameEnd;
private bool IsFrameEnd { get { return this.isFrameEnd; } }
private bool isFrameStart;
private bool IsFrameStart { get { return this.isFrameStart; } }
// A sprite that can handle multiple frames in a single image.
// I'll also make a MXListSprite that uses a container.
public MXSprite()
{
spriteData = null;
x = y = 0;
width = height = 0;
numframes = 0;
scale = speed = 1.0;
flip_x = false;
flip_y = false;
isLoaded = false;
}
public void Load(ContentManager cmanager, string resName)
{
if (isLoaded) return;
spriteData = cmanager.Load<Texture2D>(resName);
isLoaded = true;
}
public void Setup(int width, int height, double speed = 1.0, int origin_x = 0, int origin_y = 0)
{
this.width = width;
this.height = height;
this.speed = speed;
this.origin_x = origin_x;
this.origin_y = origin_y;
this.numframes = spriteData.Width / this.width;
this.c_frame = 0;
this.fcount = 0.0;
}
public void Step()
{
// Perform a frame step. Adjust if necessary
fcount += speed;
if (fcount >= 1.0)
{
fcount = 0.0; // This could be clipped instead of clamped
// while(fcount >= 1.0)fcount -= 1.0; // This will work too, and retain the fractional part.
// But it's a potential bottleneck if somebody accidentally sets
// the Speed property to something stupid like 500.
c_frame += 1;
}
if (c_frame == numframes - 1)
{
isFrameEnd = true;
}
else isFrameEnd = false;
if (c_frame > numframes - 1)
{
c_frame = 0;
}
if (c_frame == 0)
{
isFrameStart = true;
}
else isFrameStart = false;
}
// Methods
public void Draw(SpriteBatch spriteBatch)
{
Rectangle srcRect = new Rectangle(this.c_frame * this.width, 0, this.width, this.height);
SpriteEffects fx = (flip_x ? SpriteEffects.FlipHorizontally : 0) | (flip_y ? SpriteEffects.FlipVertically : 0);
spriteBatch.Draw(spriteData, new Vector2(x, y), srcRect, Color.White, (float)0.0, new Vector2(origin_x, origin_y), new Vector2((float)
scale,(float)scale), SpriteEffects.None, (float)0.0);
}
// Properties
public int X { get { return this.x; } set { this.x = value; } }
public int Y { get { return this.y; } set { this.y = value; } }
public int Width { get { return this.width; } }
public int Height { get { return this.height; } }
public int NumFrames { get { return this.numframes; } }
public int CurrentFrame { get { return this.c_frame; } set { this.c_frame = (value < this.numframes ? value : numframes-1); } }
public double Speed { get { return this.speed; } set { this.speed = value; } }
public double Scale { get { return this.scale; } set { this.scale = value; } }
public bool FlipX { get { return this.flip_x; } set { this.flip_x = value; } }
public bool FlipY { get { return this.flip_y; } set { this.flip_y = value; } }
public bool IsLoaded { get { return this.isLoaded; } }
}
// This array stores the tiles.
Tile[] tiles; // Size varies depending on map size
// This is the absolute view coordinate being 'mapped' to tile-space
// I offset it by (-1,-1) to render the border tiles
int tvx = (view_x / tile_width)-1;
int tvy = (view_y / tile_height)-1;
// Calculate the width and height of the view in tiles
int tvw = view_width/tile_width;
int tvh = view_height/tile_height;
// Calculate the start index
// map_width is the width of the map in tiles, _not the absolute value_
int start_index = tvy * map_width + tvx;
// Number of tiles to process + 2 extra rows|columns
int p_count = (tvw*tvh) + (map_width*2);
// Clamp values
if(start_index < 0)start_index = 0;
if(start_index > tiles.count()-1)break; // Out of bounds
for(int i = start_index; i < start_index + p_count; i++)
{
// Check values for validity and break loop if out of bounds
if(i > tiles.count()-1)break;
// Otherwise process
DrawTile(i);
}
public void Draw(SpriteBatch sb, Rectangle? viewRect = null)
{
int w = 32;
int h = 32;
Rectangle rr;
if (viewRect != null)
{
rr = (Rectangle)viewRect;
}
else rr = new Rectangle(0, 0, 512, 480);
int tvx = (rr.X / w)-1;
int tvy = (rr.Y / h)-1;
int tvw = (rr.Width / w)+2;
int tvh = (rr.Height / h)+2;
for (int iy = tvy; iy < tvy + tvh; iy++)
for (int ix = tvx; ix < tvx + tvw; ix++)
{
int i = iy * width + ix;
if (i > numtiles - 1)
{
i = (i % numtiles);
if (i > numtiles - 1) i = numtiles - 1;
}
if (i < 0)
{
i = -i;
i = numtiles - (i % numtiles);
}
int x = ix * w;
int y = iy * h;
x -= rr.X;
y -= rr.Y;
if (i > numtiles - 1) i = numtiles - 1;
if (backlayer[i].t >= 0) myTileset.Draw(sb, backlayer[i].t, x, y, 1.0);
if (midlayer[i].t >= 0) myTileset.Draw(sb, midlayer[i].t, x, y, 0.9);
if (frontlayer[i].t >= 0) myTileset.Draw(sb, frontlayer[i].t, x, y, 0.1);
}
}
My next task is to fix my buggy view code. It doesn't work the way you'd expect it to (All in reverse, and not working for Entities). I'm first going to see what options XNA offers, then make something myself if I have to.Not too shabby, for three days of on-and-off work with lots of Minecraft in between (I'm designing an interesting mod).Well, it looks like I've broken my own long-blog record. 2523 words. Not bad at all! Of course, you're all going to TL;DR this. Shame on you. TL;DR SectionIcodedstuffwannaseeitlookimmamakingagaeminxnasinceyoucantbebotheredtoreadthefullblogyougetthisunreadablepieceofcrapinsteadlol.
If youre a listed school in microsoft's dreamspark, then you can get visual studio for free.
also, the TL;DR was much easier for me to read than the actual blog.what was with skipping lines half way through sentences? anyway i love the parent excuse lol. parent logic is the best. read about half than realized i was spending too much time on this blog xD
seriously though, i wish i had that kinda time to kill, you seem like you always got something cool going on. i don't even have enough time to read this blog let alone work on anything =\