Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: SGM (Simple Game Engine): work in progress [part 1 - collision]  (Read 3227 times)

0 Members and 1 Guest are viewing this topic.

Mark Weyland

  • Guest
SGM (Simple Game Engine): work in progress [part 1 - collision]
« on: December 28, 2014, 12:42:48 pm »
Hello everybody! I want to create a simple game called Bug by the New Year. To do that, I'm developing a SGM (Simple Game Engine). This is how it works:

There are multiple level data files. There is one linear list of objectives. SGM takes one objective, constantly checks if it is accomplished, and when it is, loads a new level data file. Even though it's horribly inefficient, it allows very high scenario flexibility and super easy scripting. I've successfully completed one of the most complicated code segments inside the SGM: square grid collision detection and correct response mechanism. The segment itself is mere 37 lines of code, with 100 in total to be able to test it. Here it is:

#include <fstream>
#include <SFML/Graphics.hpp>

int main ()
{
    int w, h, **lvl, posX, posY, block;
    float velX(0), velY(0), inertia, friction;
    std::ifstream data("data.txt");

    /// I ASSUME THAT FILE EXISTS AND HAS VALID DATA. BEWARE - ERRORS UNHANDLED!
    data >> w >> h >> posX >> posY >> block >> inertia >> friction;
    posX *= block; posY *= block;
    lvl = new int*[h]; for (int i = 0; i < h; ++i) lvl[i] = new int[w];
    for (int i = 0; i < h; ++i)
        for (int j = 0; j < w; ++j)
            data >> lvl[i][j];
    data.close();

    sf::RenderWindow window(sf::VideoMode(w*block,h*block),"Collision", sf::Style::Close);
    window.setFramerateLimit(30);
    sf::Event event;
    sf::Keyboard kboard;
    sf::RectangleShape rectangle(sf::Vector2f(block,block));
    event.type = sf::Event::GainedFocus; // In case event.type==sf::Event::Closed at the very beginning

    while (window.isOpen())
    {
        if (kboard.isKeyPressed(sf::Keyboard::Up   )) velY -= inertia;
        if (kboard.isKeyPressed(sf::Keyboard::Down )) velY += inertia;
        if (kboard.isKeyPressed(sf::Keyboard::Left )) velX -= inertia;
        if (kboard.isKeyPressed(sf::Keyboard::Right)) velX += inertia;
        if (velX >  friction) velX -= friction; else
        if (velX < -friction) velX += friction; else
        velX = 0;
        if (velY >  friction) velY -= friction; else
        if (velY < -friction) velY += friction; else
        velY = 0;

        /// SQUARE GRID COLLISION DETECTION AND CORRECT RESPONSE MECHANISM
        bool collisionX(false), collisionY(false);
        int positionX, positionY;
        sf::IntRect hero(posX+velX, posY+velY, block, block);
        for (int i = 0; i < h; ++i)
            for (int j = 0; j < w; ++j)
                if (lvl[i][j] == 1)
                {
                    sf::IntRect rect(j*block, i*block, block, block);
                    if (hero.intersects(rect))
                    {
                        hero.left = posX;
                        if(hero.intersects(rect))
                        {
                            collisionY = true;
                            positionY = rect.top;
                        }
                        hero.left += velX; hero.top = posY;
                        if (hero.intersects(rect))
                        {
                            collisionX = true;
                            positionX = rect.left;
                        }
                        hero.top += velY;
                    }
                }
        if (collisionX)
        {
            if (velX > 0) posX = positionX - block; else
            if (velX < 0) posX = positionX + block;
            velX = 0;
        }
        if (collisionY)
        {
            if (velY > 0) posY = positionY - block; else
            if (velY < 0) posY = positionY + block;
            velY = 0;
        }
        /// END OF SQUARE GRID COLLISION DETECTION AND RESPONSE MECHANISM

        posX += velX; posY += velY;
        rectangle.setPosition(posX, posY);

        window.clear(sf::Color(255,255,255));
        rectangle.setFillColor(sf::Color(255,0,0));
        window.draw(rectangle);
        rectangle.setFillColor(sf::Color(0,0,0));
        for (int i = 0; i < h; ++i)
            for (int j = 0; j < w; ++j)
                if (lvl[i][j] == 1)
                {
                    rectangle.setPosition(j*block,i*block);
                    window.draw(rectangle);
                }
        window.display();

        window.pollEvent(event);
        if (event.type == sf::Event::Closed) window.close();
    }

    for (int i = 0; i < h; ++i) delete [] lvl[i];
    delete [] lvl;
    return 0;
}

I hope that maybe someone someday will find it useful. Code improvement discussion would be very appreciated :)

Oh, and "data.txt" contents:
Code: [Select]
10 10 1 1 20 0.9 0.5
1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 1 1 0 0 0 1
1 0 0 0 1 1 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1
« Last Edit: December 28, 2014, 12:47:42 pm by Mark Weyland »

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: SGM (Simple Game Engine): work in progress [part 1 - collision]
« Reply #1 on: December 28, 2014, 03:01:35 pm »
Might as well do a bit of code review.

- Do not use manual memory management without a very good reason.  lvl should be an STL container of some kind (presumably a vector of vectors), not a pointer to a pointer that requires tons of new/delete calls and is guaranteed to leak if there are any exceptions or early returns.

- Obviously, you should handle those potential ifstream errors.  At least do an if(data) to make sure the file opened successfully.

- You don't need to instantiate sf::Keyboard.  All of its methods are static, so it's more typical and less misleading to call them as sf::Keyboard::isKeyPressed().

- If event.type was one of the sf::Event types before you called pollEvent, that would be a bug in SFML.  If you are experiencing this bug, please start a thread with a minimal and complete example that reproduces it.  If not, take out that hack.

- You should really use curly braces around the bodies of at least some of your if/else/for statements.

- The "block" variable does not appear to be representing a block. Should it be called "blockSize"?

- imo the lines like this:
if (velX >  friction) velX -= friction; else
        if (velX < -friction) velX += friction; else
        velX = 0;
would be more readable as:
if(velX < 0) { velX += friction } else { velX -= friction }
if(std::abs(velX) < friction) { velX = 0; }
Assuming I understand the intent correctly.

- In general I'm a bit confused about the relationship between "hero", "rectangle", "rect" and "posX/Y".  More descriptive names might help, eg I think at least one of those is "herosNextPosition" but I can't quite tell which.  I also *think* you're reusing "rectangle" to display the hero and all the blocks he can collide with, when it would be clearer and easier (and probably just as efficient) to have one heroRectangle and a std::vector of RectangleShapes called "blocks" (which you only need to set the position/color of once).

That's probably enough for one post.
« Last Edit: December 28, 2014, 03:07:06 pm by Ixrec »

Gambit

  • Sr. Member
  • ****
  • Posts: 283
    • View Profile
Re: SGM (Simple Game Engine): work in progress [part 1 - collision]
« Reply #2 on: December 28, 2014, 03:30:14 pm »
would be more readable as:
if(velX < 0) { velX += friction } else { velX -= friction }
if(std::abs(velX) < friction) { velX = 0; }
Assuming I understand the intent correctly.

if (velX >  friction)
   velX -= friction;
else if (velX < -friction)
   velX += friction;
else
   velX = 0;
 
?

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: SGM (Simple Game Engine): work in progress [part 1 - collision]
« Reply #3 on: December 28, 2014, 05:17:42 pm »
Yeah, that's also an improvement.  I chose to mention the lack of curly braces and the lack of abs() since those seemed slightly worse to me personally.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: SGM (Simple Game Engine): work in progress [part 1 - collision]
« Reply #4 on: December 28, 2014, 06:06:03 pm »
Yep I've learned the hard way always put {} curly braces around things like if statements and other things that can go without them because it makes them easier to read and also it prevents bugs with them as well.
I have many ideas but need the help of others to find way to make use of them.

Mark Weyland

  • Guest
Re: SGM (Simple Game Engine): work in progress [part 1 - collision]
« Reply #5 on: December 28, 2014, 07:27:51 pm »
Ixrex, I'm very thankful for your code revision! I will fix it as soon as I complete this engine, and that will happen very soon. Now I've got to get some good nice fresh cold night air, because my head is going so dizzy and I don't think I can think straight anymore... I just wanted to say that I'm successfully moving further on and completed dialog-web code segment. It's a total mess and I myself can barely grasp what's going on there, but it surely works!!! After I come back home I promise You I'll clean the segment and post it here... Thank you, I'm out.

Xafi

  • Newbie
  • *
  • Posts: 18
  • My project, http://1ndieidea.hol.es/
    • View Profile
Re: SGM (Simple Game Engine): work in progress [part 1 - collision]
« Reply #6 on: December 30, 2014, 12:08:11 am »
Quote
if(velX < 0) { velX += friction } else { velX -= friction }
velX = (velX < 0 ? velX+friction : velX-friction);

xD