1
\$\begingroup\$

First of all, the XNA Framework works on my computer, but I do not wish to use it for reasons. I am set with the task of coding my own sprite sheet class. I do not know if a class is the best way to do it, but I have tried my best. I am not an advanced C# user, but I know enough to have got this far with the class:

class Spritesheet
{
    //w: 50px h: 96px
    Bitmap sheet;
    int fWidth, fHeight;
    int framesPerRow, framesPerCol;
    int x, y;
    public Bitmap curState;

    public Spritesheet(string path, int width, int height)
    {
        sheet = new Bitmap(path);
        fWidth = width;
        fHeight = height;
        framesPerRow = sheet.Width / fWidth;
        framesPerCol = sheet.Height / fHeight;
        curState = new Bitmap(path);
    }

    public void playSprite(int frameSpeed, int endFrame, int row)
    {
        int curFrame = 0;
        int count = 0;
        bool play = true;

        while (play)
        {
            if (count == (frameSpeed - 1))
            {
                curFrame = curFrame++ % endFrame;
                Rectangle cloneRect = new Rectangle(row * fWidth, curFrame * fHeight, fWidth, fHeight);
                System.Drawing.Imaging.PixelFormat pFormat = sheet.PixelFormat;
                Bitmap curState = sheet.Clone(cloneRect, pFormat);
            }

            count = (count + 1) % frameSpeed;
        }
    }
}

I am aware that class variables should never be public, but this is just until I get it working. My Form1 looks like this:

public partial class Form1 : Form
{
    Spritesheet player = new Spritesheet("Content/Sprite/charzera.png", 700, 270);

    public Form1()
    {
        InitializeComponent();
        pb_char.Image = player.curState;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        player.playSprite(5, 13, 0);
        pb_char.Image = player.curState;
    }

}

The form builds but doesn't launch now. I am just lost on where to go with this now. I want a spritesheet to be created for the main character, and from there I want to be able to pick a row based on what action is happening and then the game to run along the row animating the PictureBox that I am using for the character.

I've never done this before, so its probably completely wrong.

\$\endgroup\$
4
  • \$\begingroup\$ Reasons? It might be helpful if you elaborated exactly why you won't use XNA. \$\endgroup\$
    – Sturlen
    Nov 29, 2015 at 18:32
  • \$\begingroup\$ From your posted code, it looks like you have many gaps in your knowledge and are taking too many steps at once. SE is not a good platform for walking people through complex procedures like this, so I think you should break this up into smaller tasks, like: how to display an image, how to show a basic animation (e.g. single image flickering), how to display different frames in a multi-frame spritesheet, how to show a spritesheet as an animation, and finally how to show different animations in a spritesheet. \$\endgroup\$ Nov 30, 2015 at 1:11
  • \$\begingroup\$ As a matter of a fact, the entire code logic for deciding what sprite to draw on a spritesheet can be developed without using XNA or other graphics library. You just develop a system to obtain some coordinates and pass that to you graphics subsystem, whatever it is. \$\endgroup\$
    – rlam12
    Nov 30, 2015 at 2:29
  • \$\begingroup\$ Thanks for the help. I got it eventually. Yeah it might have been too big a jump. \$\endgroup\$ Nov 30, 2015 at 18:50

1 Answer 1

1
\$\begingroup\$

I'm not sure how to do this in C# as I haven't used it but the basic idea is to cut out each section of the sprite sheet when you need it and crop the rest. I have C++/SFML code for it but I will try to generalize it

enum Direction {Down, Left, Right, Up};

int source_x = 1;
int source_y = Down;

int loop = 0;

float frameCounter = 0, switchframe = 100, frameSpeed = 500;

Clock clock;

Sprite PlayerImage;
Texture PlayerT;

bool updateFrame = false;

if (!PlayerT.loadImage("Player.png"))
{
    std::cout << "Error Image could not load" << std::endl;
}

PlayerImage.setTexture(PlayerT);
while (window.isOpen())
{
    if (Keyboard::isKeyPressed(sf::Keyboard::W))
        {
            source_y = Up;
            PlayerImage.move(0, -0.05);
            updateFrame = true;
        }
    else if (Keyboard::isKeyPressed(sf::Keyboard::S))
        {
            source_y = Down;
            PlayerImage.move(0, 0.05);
            updateFrame = true;
        }
    else if (Keyboard::isKeyPressed(sf::Keyboard::D))
        {
            source_y = Right;
            PlayerImage.move(0.05, 0);
            updateFrame = true;
        }
    else if (Keyboard::isKeyPressed(sf::Keyboard::A))
        {
            source_y = Left;
            PlayerImage.move(-0.05, 0);
            updateFrame = true;
        }

    loop++;
    if (loop >= 3000)
    {
        loop = 0;
        updateFrame = false;
    }

    if (updateFrame)
    {
        frameCounter += frameSpeed * clock.restart().asSeconds();
    }
    else
    {
        frameCounter = 0;
    }

    if (frameCounter >= switchframe)
    {
        frameCounter = 0;
        source_x++;
        if (source_x * 32 >= PlayerT.getSize().x)
            source_x = 0;
    }

    window.clear();
    PlayerImage.setTextureRect(sf::IntRect(source_x * 32, source_y * 32, 32, 32));

    window.draw(PlayerImage);
    window.display();
}

I hope that this helps however it is for another language.

Also I found this thread over on Stack Overflow which could help: https://stackoverflow.com/questions/16112622/2d-sprite-animations-without-using-xna-or-other-third-party-libraries

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .