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

Author Topic: Enemy intersection trouble  (Read 2375 times)

0 Members and 1 Guest are viewing this topic.

spoty76

  • Newbie
  • *
  • Posts: 21
    • View Profile
Enemy intersection trouble
« on: April 21, 2017, 09:44:45 pm »
Hello, so I added enemy iterator and my purpose was to check where from the player touched the enemy when the player intersects enemy sprite, but the problem is that when I just start the programm, all the commands in this: are being triggered rapidly, I mean they don't stop doing that, my player flies away and his health bar is always decreasing (p.dy -= 0.5; p.health-= 25;):
 
for (it = entities.begin(); it != entities.end();)
                        {
                                Entity *b = *it;
                                b->update(time);
                                if (b->life == false)
                                {
                                        it = entities.erase(it);
                                        delete b;
                                }
                                else it++;
                        }

                        for (it = entities.begin(); it != entities.end(); it++)
                        {
                                if ((*it)->getRect().intersects(p.getRect()));
                                {
                                        if ((*it)->name == "EasyEnemy")
                                        {
                                                if ((p.dy > 0) && (p.onGround == false))
                                                {
                                                        (*it)->dx = 0;
                                                        p.dy -= 0.5;
                                                        (*it)->health = 0;
                                                }
                                                else
                                                {
                                                        p.dy -= 0.5;
                                                        p.dx -= 0.5;
                                                        p.health -= 25;
                                                }
                                        }
                                }
                        }
Another thing that I noticed is that the enemy stops (the command (*it)->dx=0; triggers), and by the way if I delete the code upper, the programm works ok. So it looks like when I start the game player always intersects the enemy, no matter where the he is, I've checked location issues in Tile Map Editor and haven't found anything unusual. Here is my main.cpp code:
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "view.h"
#include <iostream>
#include <sstream>
#include "mission.h"
#include "iostream"
#include "level.h"
#include <vector>
#include <list>
#include "tinyxml\tinyxml.h"

using namespace sf;

class Entity {
public:
        std::vector<Object> obj;
        float dx, dy, x, y, speed, moveTimer;
        int w, h, health;
        bool life, isMove, onGround;
        Texture texture;
        Sprite sprite;
        String name;
        Entity(Image &image, float X, float Y, int W, int H, String Name) {
                x = X; y = Y; w = W; h = H; name = Name; moveTimer = 0;
                speed = 0;
                dx = 0; dy = 0;
                life = true; onGround = false; isMove = false;
                texture.loadFromImage(image);
                sprite.setTexture(texture);
                sprite.setOrigin(w / 2, h / 2);
        }

        FloatRect getRect()
        {
                return FloatRect(x, y, w, h);
        }

        virtual void update(float time) = 0;
};

        class Player :public Entity {
        public:
                int health = 100;
                enum { left, right, jump, stay } state;
                int playerScore;
                Music death;
                Music deathS;
                Music soundtrack;
                Music soundtrack2;
                Music claySong;
                Player(Image &image, Level &lev, float X, float Y, int W, int H, String Name) :Entity(image, X, Y, W, H, Name){
                        playerScore = 0; state = stay; obj = lev.GetAllObjects();
                        death.openFromFile("music/death.ogg"); death.setLoop(true);
                        deathS.openFromFile("sounds/deathS.ogg"); deathS.setVolume(100); deathS.setLoop(true);
                   soundtrack.openFromFile("music/soundtrack.ogg"); soundtrack.setVolume(50);
                   soundtrack2.openFromFile("music/soundtrack2.ogg");
                   claySong.openFromFile("sounds/claySong.ogg");
                   soundtrack.play(); soundtrack.setLoop(true);
                   claySong.play(); claySong.setLoop(true);
                   if (name == "Player1"){
                           sprite.setTextureRect(IntRect(10, 306, w, h));
                   }
           }

        void  control() {

                if (life == true) {
                        if (Keyboard::isKeyPressed(Keyboard::A)) {
                                state = left;
                                speed = 0.3;
                        }

                        if (Keyboard::isKeyPressed(Keyboard::D)) {
                                state = right;
                                speed = 0.3;
                        }

                        if ((Keyboard::isKeyPressed(Keyboard::Space) && (onGround == true))) {
                                state = jump;
                                dy = -0.5;
                                //onGround = false;
                        }
                }
        }

        void update(float time)
        {
                control();
                switch (state) {
                case left: dx = -speed; break;
                case right: dx = speed; break;
                case jump: break;
                case stay: break;
                }
                x += dx*time;
                checkCollisionWithMap(dx, 0);
                y += dy*time;
                checkCollisionWithMap(0, dy);
                if (!isMove) speed = 0;
                sprite.setPosition(x + w / 2, y + h / 2);
                if (health <= 0) { life = false; }
                if (life == true) { getplayercoordinateforview(x, y); }
                dy = dy + 0.0015*time; 
        }

        float getplayercoordinateX() {
                return x;
        }

        void checkCollisionWithMap(float Dx, float Dy) {
                onGround = false;
                for (int i = 0; i<obj.size(); i++)
                if (getRect().intersects(obj[i].rect))
                {
                        if (obj[i].name == "solid")
                        {
                                if (Dy>0)       { y = obj[i].rect.top - h;  dy = 0; onGround = true; }
                                if (Dy<0)       { y = obj[i].rect.top + obj[i].rect.height;   dy = 0; }
                                if (Dx>0)       { x = obj[i].rect.left - w; }
                                if (Dx<0)       { x = obj[i].rect.left + obj[i].rect.width; }
                        }

                        if (obj[i].name == "lava")
                        {
                                if (Dy>0)       { y = obj[i].rect.top - h;  dy = 0; onGround = true; }
                                if (Dy<0)       { y = obj[i].rect.top + obj[i].rect.height;   dy = 0; }
                                if (Dx>0)       { x = obj[i].rect.left - w; }
                                if (Dx < 0)     { x = obj[i].rect.left + obj[i].rect.width; }

                                if (life = true) { life = false; }

                                if (death.getStatus() == Sound::Playing)
                                {
                                        continue;
                                }
                                else {
                                        death.play();
                                        deathS.play();
                                        claySong.stop();
                                        soundtrack.stop();
                                        soundtrack2.stop();
                                }
                        }

                        if (obj[i].name == "jumper")
                        {
                                if (Dy > 0)     { y = obj[i].rect.top - h;  dy = 0; }
                                if (Dy < 0)     { y = obj[i].rect.top + obj[i].rect.height;   dy = 0; }
                                if (Dx > 0)     { x = obj[i].rect.left - w; }
                                if (Dx < 0)     { x = obj[i].rect.left + obj[i].rect.width; }
                                dy -= 1.5; onGround = false;
                        }

                        if (obj[i].name == "enemy")
                        {
                                soundtrack.stop();
                                claySong.stop();
                                if (soundtrack2.getStatus() == Sound::Playing) { continue; }
                                else {
                                        soundtrack2.play();
                                     }
                                sprite.setColor(Color(237, 28, 36));
                               
                        }

                }
        }

};

        class Enemy :public Entity{
        public:
                int health;
                Enemy(Image &image, Level &lvl, float X, float Y, int W, int H, String Name) :Entity(image, X, Y, W, H, Name) {
                        obj = lvl.GetObjects("solid"); health = 100;
                        if (name == "EasyEnemy") {
                                sprite.setTextureRect(IntRect(0, 0, w, h));
                                dx = 0.1;
                        }
                }

                void checkCollisionWithMap(float Dx, float Dy) {
                        for (int i = 0; i<obj.size(); i++)
                        if (getRect().intersects(obj[i].rect))
                        {
                                        if (Dy>0)       { y = obj[i].rect.top - h;  dy = 0; onGround = true; }
                                        if (Dy<0)       { y = obj[i].rect.top + obj[i].rect.height;   dy = 0; }
                                        if (Dx>0)       { x = obj[i].rect.left - w;  dx = -0.1; sprite.scale(-1, 1); }
                                        if (Dx<0)       { x = obj[i].rect.left + obj[i].rect.width; dx = 0.1; sprite.scale(-1, 1); }
                        }
                }

                void update(float time) {
                        if (name == "EasyEnemy")
                        {
                                //moveTime += time; if (moveTimer>3000) {dx*=-1; moveTimer = 0; }
                                checkCollisionWithMap(dx, 0);
                                x += dx*time;
                                sprite.setPosition(x + w / 2, y + h / 2);
                                if (health <= 0) { life = false; }
                        }
                }
        };

        int main()
        {
                sf::RenderWindow window(sf::VideoMode(1980, 1080), "Glinskii Adventures");
                view.reset(sf::FloatRect(0, 0, 640, 400));
                window.setFramerateLimit(90); // fps

                Level lvl;
                lvl.LoadFromFile("mainmap.tmx");

                Image heroImage;
                heroImage.loadFromFile("images/hero.jpg");
                heroImage.createMaskFromColor(Color(125, 99, 86));

                Image easyEnemyImage;
                easyEnemyImage.loadFromFile("images/enemy1.jpg");
                easyEnemyImage.createMaskFromColor(Color(255, 255, 255));

                Image quest_image;
                quest_image.loadFromFile("images/tab.jpg");
                Texture quest_texture;
                quest_texture.loadFromImage(quest_image);
                Sprite s_quest;
                s_quest.setTexture(quest_texture);
                s_quest.setTextureRect(IntRect(0, 0, 224, 352));

               

                Object player = lvl.GetObject("player");

                Font font;
                font.loadFromFile("fonts/classic.TTF");

                Text text("", font, 20);
                text.setStyle(Text::Bold);

                Text pickText("", font, 20);
                pickText.setStyle(Text::Bold);

                Text text2("", font, 20);
                text2.setStyle(Text::Bold);

                Text glinPlate("", font, 20);
                glinPlate.setStyle(Text::Bold);
                glinPlate.setStyle(Text::Underlined);

                Text nickname("", font, 20);

                [b]std::list<Entity*> entities;
                std::list<Entity*>::iterator it;
                std::vector<Object> e = lvl.GetObjects("EasyEnemy");
                for (int i = 0; i < e.size(); i++)
                        entities.push_back(new Enemy(easyEnemyImage, lvl, e[i].rect.left, e[i].rect.top, 79, 59, "EasyEnemy"));[/b]

                Player p(heroImage, lvl, player.rect.left, player.rect.top, 70, 86, "Player1");
       
                Clock clock;

                Clock deathCl;

                Clock gameTimeClock;
                int gameTime = 0;

                bool showMissionText = true;

                while (window.isOpen())
                {

                        float time = clock.getElapsedTime().asMicroseconds();
                        clock.restart();
                        time = time / 800;
                        if (p.life == true) gameTime = gameTimeClock.getElapsedTime().asSeconds();

                        else {
                                p.sprite.setColor(Color(235, 65, 7));
                                view.zoom(0.997);
                                view.move(0, 0.05);
                                view.move(0.07, 0);
                                view.rotate(0.05);
                        }

                        sf::Event event;

                        while (window.pollEvent(event))
                        {
                                window.setKeyRepeatEnabled(false);

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

                               
                                if (event.type == Event::KeyPressed)
                                if ((event.key.code == Keyboard::Tab))
                                {
                                        switch (showMissionText)
                                        {
                                        case true:
                                        {
                                                                 std::ostringstream task;
                                                                 task << getTextMission(getCurrentMission(p.getplayercoordinateX()));
                                                                 text2.setString("\n" + task.str());
                                                                 showMissionText = false;

                                                                 glinPlate.setString("entry");

                                                                 nickname.setString("XxX_Daun_XxX");

                                                                 break;
                                        }
                                        case false:
                                        {
                                                                  text2.setString("");
                                                                  showMissionText = true;
                                                                  break;
                                        }
                                        }
                                }
                        }

                        p.update(time);

                        [b]for (it = entities.begin(); it != entities.end();)
                        {
                                Entity *b = *it;
                                b->update(time);
                                if (b->life == false)
                                {
                                        it = entities.erase(it);
                                        delete b;
                                }
                                else it++;
                        }

                        for (it = entities.begin(); it != entities.end(); it++)
                        {
                                if ((*it)->getRect().intersects(p.getRect()));
                                {
                                        if ((*it)->name == "EasyEnemy")
                                        {
                                                if ((p.dy > 0) && (p.onGround == false))
                                                {
                                                        (*it)->dx = 0;
                                                        p.dy -= 0.5;
                                                        (*it)->health = 0;
                                                }
                                                else
                                                {
                                                        p.dy -= 0.5;
                                                        p.dx -= 0.5;
                                                        p.health -= 25;
                                                }
                                        }
                                }
                        }[/b]

                        changeview();
                        window.setView(view);

                        window.clear();

                        lvl.Draw(window);

                        std::ostringstream playerHealthString, gameTimeString;
                        playerHealthString << p.health; gameTimeString << gameTime;
                        text.setString("&#1047;&#1076;&#1086;&#1088;&#1086;&#1074;&#1100;&#1077;: " + playerHealthString.str() + "\n&#1042;&#1088;&#1077;&#1084;&#1103; &#1080;&#1075;&#1088;&#1099;: " + gameTimeString.str());
                        text.setPosition(view.getCenter().x - 315, view.getCenter().y - 200);
                        window.draw(text);

                        std::ostringstream playerScoreString;
                        playerScoreString << p.playerScore;
                        pickText.setString("&#1057;&#1086;&#1073;&#1088;&#1072;&#1085;&#1086; &#1095;&#1083;&#1077;&#1085;&#1086;&#1074;: " + playerScoreString.str());
                        pickText.setPosition(view.getCenter().x + 140, view.getCenter().y - 200);
                        window.draw(pickText);

                        if (!showMissionText)
                        {
                                text2.setPosition(view.getCenter().x - 315, view.getCenter().y - 100);
                                s_quest.setPosition(view.getCenter().x - 320, view.getCenter().y - 100);
                                glinPlate.setPosition(view.getCenter().x - 315, view.getCenter().y - 100);
                                nickname.setPosition(view.getCenter().x - 20, view.getCenter().y);
                                window.draw(s_quest); window.draw(text2); window.draw(glinPlate); window.draw(nickname);
                        }

                        [b]for (it = entities.begin(); it != entities.end(); it++)
                        {
                                window.draw((*it)->sprite);
                        }[/b]

                        window.draw(p.sprite);

                        window.display();
                }

                return 0;
        }
 
So what could be the problem? I'm quiet confused, I tried to use debug, but didn't get any useful info.
« Last Edit: April 22, 2017, 10:09:29 am by spoty76 »

sjaustirni

  • Jr. Member
  • **
  • Posts: 94
    • View Profile
Re: Enemy intersection trouble
« Reply #1 on: April 23, 2017, 09:58:41 am »
I am quite confused as well :D .It seems that you have been just adding stuff to your game loop without any proper refactoring and thinking about the code design (which is not really uncommon for the novice programmers, I was the same when I was starting out :D). The result is something which we call Big ball of mud. It is hard to write, hard to test and most importantly, hard to read.

I would suggest you to
  • break down the main.cpp file into multiple ones, so that every class has its own header and source file, which is a widespread practice
  • (if you want to go OOP) implement one common public interface for Entity (update(), render(), control())  and for the descendants of Entity (remember, each one in its own file) you would just call free functions and private/protected member functions inside those three methods, so your main loop would only know about those three public functions form Entity
  • make your functions as short as possible by decomposing them into multiple functions

As an example, here's a small SFML game using OOP I have just found on Github. From a basic skimming through it it seems it's written pretty well to illustrate my points. https://github.com/hlilje/sfml-game

I am sorry I was lazy enough not to fix your issue with collision, but I believe collision is currently not your main problem, the code structure is.

GL and have fun, because programming should be :D ;)

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Enemy intersection trouble
« Reply #2 on: April 23, 2017, 12:03:04 pm »
It looks odd that you are deleting the object after erasing the iterator. If this is a vector (contiguous data), wouldn't "b" point to the next item pointed to by it, which is now the following item, and then delete the memory from that pointer (it's a pointer, right?).
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

spoty76

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Enemy intersection trouble
« Reply #3 on: May 07, 2017, 04:12:40 pm »
THIS IS SO FUNNY, actually the problem was this little thing)))))
if (p.getRect().intersects((*iter1)->getRect()));
This little semicolon didn't allow to check if the player intersects and all the commands below started to triger
This is crazy  ;D