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\$
  • \$\begingroup\$ Reasons? It might be helpful if you elaborated exactly why you won't use XNA. \$\endgroup\$ – ZEKE Nov 29 '15 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\$ – congusbongus Nov 30 '15 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 '15 at 2:29
  • \$\begingroup\$ Thanks for the help. I got it eventually. Yeah it might have been too big a jump. \$\endgroup\$ – Tiernan Watson Nov 30 '15 at 18:50
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

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.