Jump to content
  • Advertisement
Sign in to follow this  
White Scorpion

CPU-eating Sprites

This topic is 4862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys. I'm building a small game and I am now to test the Sprite class and all its features but I have a small problem. I first tried simply displaying a still image (not moving) and the problem is that the program eats so much CPU it makes the computer almost freeze. How is it possible ? I don't think I've done anything different that usually... :? I'll spare you most of the code, you don't need to see all of it. In "graphics.hpp"
/*====================================================================

                            STRUCT POINT
                            
    This structure holds a coordinate point and represents the
    top-left corner of each Sprite object.

                            CLASS VECTOR_2D

    The Vector_2D class is a class that the programmer does not need
    to deal with. It represents a mathematical/physical of which the
    length represents the speed(includes direction) of a Sprite object.
    
====================================================================*/


struct Point {
    int x, y;
    
    Point() : x(0), y(0) { }
    Point& operator+=(const Vector_2D&);
    Point& operator-=(const Vector_2D&);
    Point& operator=(const Point&);
    
};


class Vector_2D {
    public:
        Vector_2D();
        Vector_2D(int, int);
        Vector_2D(const Vector_2D&);
        
        int GetLength();
        int GetX();
        int GetY();
        void SetX(int);
        void SetY(int);
        void SetVec(int, int);
        
        operator int();
        Vector_2D& operator=(const Vector_2D&);
        Vector_2D& operator+=(const Vector_2D&);
        Vector_2D& operator-=(const Vector_2D&);
        bool operator==(const Vector_2D&);
        bool operator!=(const Vector_2D&);

        friend Point& Point::operator+=(const Vector_2D&);
        friend Point& Point::operator-=(const Vector_2D&);
        friend Vector_2D operator*(int, Vector_2D&);
    private:
        int i, j;
};


/*====================================================================

                            CLASS SPRITE

    The Sprite class regroups a set of various operations to allow
    the programmer to deal easily with bitmap, png or jpeg image
    loading and move the image. All these operations are done
    internally, through the interface.
    
====================================================================*/


class Sprite {
    public:
        Sprite();
        Sprite(HDC, const char*, int, int);
        Sprite(const Sprite&);
        ~Sprite();
        
        void Create(HDC, const char*, int, int);
        void KillSelf();
        
        void Render(HDC, KEY_STATE);
        void SetAcceleration(int, int);
        void SetXSpeed(int);
        void SetYSpeed(int);
        void SetSpeed(int, int);
    private:
        HDC device_context;
        Vector_2D speed;
        Vector_2D init_speed;
        Vector_2D accel;
        HBITMAP default_bmp;
        HBITMAP loaded_bmp;
        int width;
        int height;
        int elapsed_time;
        Point position;
        Point init_position;
        bool accelerated;
};

In "graphics.cpp"
int Vector_2D::GetLength() { return sqrt(pow(i, 2) + pow(j, 2)); }

Vector_2D::operator int() {
    // A conversion to an int returns
    // the length of the vector
    return GetLength();
}


/*====================================================================

                            CLASS SPRITE

    - Provide the create() method as an alternative to the constructor;
    - Automatically loads and set up the image;
    - Set the speed of the sprite through SetXSpeed, SetYSpeed and SetSpeed.

====================================================================*/


Sprite::Sprite(HDC hdc, const char* file, int x, int y) {
    Create(hdc, file, x, y);
}

void Sprite::Create(HDC hdc, const char* file, int x, int y) {
    // Load the bitmap into the compatible device context
    device_context = CreateCompatibleDC(hdc);
    loaded_bmp = (HBITMAP)LoadImage(0, file, IMAGE_BITMAP, x, y, LR_LOADFROMFILE);
    default_bmp = (HBITMAP)SelectObject(device_context, loaded_bmp);
    
    // Retrieve the height and width
    BITMAP bmp;
    GetObject(loaded_bmp, sizeof(bmp), &bmp);
    width = bmp.bmWidth;
    height = bmp.bmHeight;
    
    // No default acceleration, speed nor initial speed
    init_speed.SetVec(0, 0);
    speed.SetVec(0, 0);
    accel.SetVec(0, 0);
    
    accelerated = false;
}

void Sprite::Render(HDC hdc, KEY_STATE state) {
    if(state != IDLE) {
        // Set the acceleration depending on the key that
        // is currently pressed by the user
        if(state == LEFT_PRESSED) {
            accel.SetX(-1);
        }
        
        if(state == RIGHT_PRESSED) {
            accel.SetX(1);
        }
        
        // A key is pressed, meaning that the sprite is accelerated
        // Set the initial speed and set acceleration to true
        if(accelerated == false) {
            init_speed = speed;
            accelerated = true;
        }
        
        // If the player has changed direction reset
        // elapsed time and initial position
        if(((int)accel/(int)accel) + ((int)speed/(int)speed) == 0) {
            init_position.x = position.x;
            elapsed_time = 0;
        }
        // Otherwise update the time counter
        else {
            elapsed_time += _SYS_UPDATE_DELAY_;
        }
        
        // Vx = Vix + ax * t
        speed = init_speed;
        speed += (_SYS_UPDATE_DELAY_ * accel);
        
        // If the stop speed is reached, stop accelerating
        if((int)speed >= _SYS_TOP_SPEED_) {
            speed.SetX(_SYS_TOP_SPEED_);
            accelerated = false;
        }
        
        if((int)speed <= -_SYS_TOP_SPEED_) {
            speed.SetX(_SYS_TOP_SPEED_);
            accelerated = false;
        }
    }
    // x = xi + 0.5 * (Vix + Vx) * t
    position = init_position;
    position += (_SYS_UPDATE_DELAY_ / 2) * init_speed;
    position += (_SYS_UPDATE_DELAY_ / 2) * speed;
    
    BitBlt(hdc, position.x, position.y, width, height, device_context, 0, 0, SRCCOPY);
}

In "main.cpp"
#include <windows.h>
#include "graphics.hpp"

Sprite obj;
HDC hdc;

// ...

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nFunsterStil)
{
    // ...

    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }

    // ...
}

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        case WM_CREATE:
            hdc = GetDC(hwnd);
            obj.Create(hdc, "file.bmp", 0, 0);
            break;
        case WM_PAINT:
            obj.Render(hdc, IDLE);
            break;
        // ...
    }

    return 0;
}

I'm sorry, I know this is pretty big to post on a forum, but I assure you I really cut everything I thought was irrelevent to the problem. The picture displays fine, but my computer freezes badly. *Edit* I wouldn't mind a preview button.

Share this post


Link to post
Share on other sites
Advertisement
What typically eats CPU are loops. Your message loop looks ok, it may not be optimally suited for a game, but it shouldn't be eating CPU. Perhaps it's something that happens in one of the other message handlers inside the MsgProc.

Share this post


Link to post
Share on other sites
There aren't any, I just removed the 'default' processing and 'WM_DESTROY' message processing for the sake of brevity. As for the message loop, I haven't optimized it yet because I used Dev-C++'s Win32 project's base code. I plan on changing it and a few other things but nothing that could cause much slowdown at all.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
All you are doing is drawing endlessly (with nothing to delay it it will eat all available CPU). Stick a sleep call in like sleep(50) to simulate other things being done (your system will probably now sit almost idle when cycling approx 20 frames per second). If you had set your object mode to actually move the sprite, you would have seen how fast it actually was running. Do that and see how fast (probably make it shift random X Y to keep it on screen). Then, make an array of the sprites (like 100) and see how many can run at once at a desired rate. Keep upping the number to see really how fast your program really is capable of drawing.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!