-1
\$\begingroup\$

I'm new to game programming and my first project is a platformer.

All things are going well, I draw the map, got the scrolling working, there's only one problem. I can't get the collision to work, I tried several things but can't find my own mistake.

It's probably a beginners mistake, could anyone help me out ?

My .cpp

// Include
#include "Application.h"
#include "FrameworkTest.h"
#include "Tile.h"
#include <iostream>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/ext.hpp>


// Define
APPLICATION_ENTRY(FrameworkTest);
#define DEFAULT_SCREENWIDTH 1280
#define DEFAULT_SCREENHEIGHT 720
#define TileSize 64  // 64 x 64 tiles (pixels)

using namespace std;

// Vector with tiles
vector <Tile*> TileList;

FrameworkTest::FrameworkTest()
{

}

FrameworkTest::~FrameworkTest()
{

}

bool FrameworkTest::onCreate(int a_argc, char* a_argv[])
{
    // Background color
    setBackgroundColor(NHTV::SColour(0x204, 0x255, 0x255, 0xFF));
    AddFont("./fonts/invaders.fnt");

    // Player sprite
    m_iPlayerSprite = CreateSprite("./images/Player.png", 76, 68, false);


    // Store the screen size
    GetScreenSize(m_iScreenWidth, m_iScreenHeight);

    // Position the player
    MoveSprite(m_iPlayerSprite, m_iScreenWidth * 0.1f, m_iScreenHeight * 0.3f);


    // My Tiles, (9 tiles for now...)
    // 1 Corner left grass
    // 2 No corner grass
    // 3 Corner right grass
    // 4 Mud left corner
    // 5 No corner mud
    // 6 Mud right corner
    // 7 Crate (later on I want this to increase the score.)
    // 8 Direction
    // 9 Plain blue tile



    // Corner left grass tile
    // Create the sprite, give it dimensions, don't draw from center.
    unsigned int TileHandle = CreateSprite("./images/1.png", 64, 64, false);
    Tile* Temp = new Tile();
    Temp->TileHandler = TileHandle;
    // Put tile in TileList (vector)
    TileList.push_back(Temp);

    // No corner grass tile
    TileHandle = CreateSprite("./images/2.png", 64, 64, false);
    Temp = new Tile();
    Temp->TileHandler = TileHandle;
    TileList.push_back(Temp);

    // Corner right grass tile
    TileHandle = CreateSprite("./images/3.png", 64, 64, false);
    Temp = new Tile();
    Temp->TileHandler = TileHandle;
    TileList.push_back(Temp);

    // Mud left tile
    TileHandle = CreateSprite("./images/4.png", 64, 64, false);
    Temp = new Tile();
    Temp->TileHandler = TileHandle;
    TileList.push_back(Temp);

    // Mud central tile
    TileHandle = CreateSprite("./images/5.png", 64, 64, false);
    Temp = new Tile();
    Temp->TileHandler = TileHandle;
    TileList.push_back(Temp);

    // Mud right tile
    TileHandle = CreateSprite("./images/6.png", 64, 64, false);
    Temp = new Tile();
    Temp->TileHandler = TileHandle;
    TileList.push_back(Temp);

    // Crate tile
    TileHandle = CreateSprite("./images/7.png", 64, 64, false);
    Temp = new Tile();
    Temp->TileHandler = TileHandle;
    TileList.push_back(Temp);

    // Arrow Tile
    TileHandle = CreateSprite("./images/8.png", 64, 64, false);
    Temp = new Tile();
    Temp->TileHandler = TileHandle;
    TileList.push_back(Temp);

    // Blue .png file (...)
    TileHandle = CreateSprite("./images/9.png", 64, 64, false);
    Temp = new Tile();
    Temp->TileHandler = TileHandle;
    TileList.push_back(Temp);

    return true;
}

void FrameworkTest::onUpdate(float a_deltaTime)
{
    // Position of player
    float xPos = 0; float yPos = 0;
    // Store position in xPos and yPos.
    GetSpritePosition(m_iPlayerSprite, xPos, yPos);

    // Collision


    float testX, testY;
    GetSpritePosition(m_iPlayerSprite, testX, testY);
    int test = TMap[(int)(yPos / TileSize)][(int)(xPos / TileSize)];

    if (test != 8)
    {
        xPos = testX;
        yPos = testY;
        cout << "TEST"<< endl;
    }




    // Scrolling
    GetSpritePosition(m_iPlayerSprite, MainScreenXpos, MainScreenYpos);
    MainScreenXpos = MainScreenXpos - (m_iScreenWidth / 2);
    MainScreenYpos = MainScreenYpos - (m_iScreenHeight / 2);



    if (MainScreenXpos < 0)
    {
        MainScreenXpos = 0;
    }

    if (MainScreenYpos < 0)
    {
        MainScreenYpos = 0;
    }

    if (MainScreenXpos >(30 * TileSize) - m_iScreenWidth)
    {
        MainScreenXpos = (30 * TileSize) - m_iScreenWidth;
    }

    if (MainScreenYpos > (30 * TileSize) - m_iScreenHeight)
    {
        MainScreenYpos = (30 * TileSize) - m_iScreenHeight;
    }





    // Stable movement
    float deltaTime = GetDeltaTime();
    float moveSpeed = 400.0 * deltaTime;





    // Player input
    // Right
    if (IsKeyDown(NHTV::KEY_RIGHT))
    {
        MoveSprite(m_iPlayerSprite, xPos + moveSpeed, yPos);
    }

    // Left
    if (IsKeyDown(NHTV::KEY_LEFT))
    {
        MoveSprite(m_iPlayerSprite, xPos - moveSpeed, yPos);

    }

    // Up
    if (IsKeyDown(NHTV::KEY_UP))
    {
        MoveSprite(m_iPlayerSprite, xPos, yPos + moveSpeed);
    }

    // Down
    if (IsKeyDown(NHTV::KEY_DOWN))
    {
        MoveSprite(m_iPlayerSprite, xPos, yPos - 4.0f);
    }

    // ESC
    if (IsKeyDown(NHTV::KEY_ESCAPE))
        destroy();
}








void FrameworkTest::onDraw()
{
    clearScreen();
    float fDeltaT = GetDeltaTime();
    int XscreenOffset = MainScreenXpos / TileSize;
    int XcellOffset = (int)MainScreenXpos % TileSize;



    // Draw my tiles,
    // column and row, loop, loop

    for (int ROW = 0; ROW < (m_iScreenHeight / TileSize) + 1; ROW++)
    {

        for (int COLUMN = 0; COLUMN < (m_iScreenWidth / TileSize) + 1; COLUMN++)
        {
            MoveSprite(TileList[TMap[ROW][COLUMN + XscreenOffset]]->TileHandler, (COLUMN*TileSize) - XcellOffset, m_iScreenHeight - (ROW*TileSize));
            DrawSprite(TileList[TMap[ROW][COLUMN + XscreenOffset]]->TileHandler);
        }

    }

    // tmap = 24248523854835
    //TileHandle = CreateSprite("./images/2.png", 64, 64, false);
    //Temp = new Tile();
    //Temp->TileHandler = TileHandle;
    //TileList.push_back(Temp);


    //Draw player
    DrawSprite(m_iPlayerSprite);

    // Draw HUD
    SetFont("./fonts/invaders.fnt");
    DrawString("SCORE", m_iScreenWidth * 0.725f, m_iScreenHeight - 2, 1.0f, NHTV::SColour(0x204, 0x255, 0x255, 0xFF));          // I want to use this later on to display my score.
    DrawString("Platformer", m_iScreenWidth * 0.8f, 38);                                    // Name of the game.


                                                                                            // Deltatime frame
    std::string timeFrame = "DeltaTime: ";
    timeFrame.append(std::to_string(fDeltaT));
    SetFont(nullptr);
    DrawString(timeFrame.c_str(), 10, 720, 0.75f, NHTV::SColour(0x204, 0x255, 0x255, 0xFF));


}

void FrameworkTest::onDestroy()
{

}

My .h

#ifndef __Tutorial1_H_
#define __Tutorial1_H_

#include "Application.h"
#include <glm/glm.hpp>

// Application class wrap
class FrameworkTest : public NHTV::Application
{

    // Make public
public:

    FrameworkTest();
    virtual ~FrameworkTest();


    // Scrolling
    float MainScreenXpos, MainScreenYpos;



    // Level (14 height, 50 width.)
    int TMap[14][50] =
    {
        { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 1, 1, 1, 1, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 8, 8, 8, 8, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 1, 1, 1, 1, 2, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8 },
        { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 8, 8, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
        { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 8, 8, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
        { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 8, 8, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
        { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 3, 4, 4, 4, 4, 5, 8, 8, 8, 8, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
    };

protected:

    virtual bool onCreate(int a_argc, char* a_argv[]);
    virtual void onUpdate(float a_deltaTime);
    virtual void onDraw();
    virtual void onDestroy();

private:
    // ScreenSize
    int m_iScreenWidth;
    int m_iScreenHeight;


    // Player
    unsigned int m_iPlayerSprite;
    unsigned int m_Enemy;
    unsigned int m_Coin;
};

#endif // __Tutorial1_H_

My game looks like this right now, don't be fooled by the players position, there's no gravity and the starting point is above a tile, no collision happening here.

When the game starts

\$\endgroup\$
  • 1
    \$\begingroup\$ Don't keep an array (vector) of pointers to tiles, keep an array of tiles instead. \$\endgroup\$ – Casper Beyer Feb 25 '17 at 22:37
0
\$\begingroup\$

As far as I can see you are first of all testing what block your sprite position is in, so not what block you're standing next to or on top of. This means that if you want to stop the player if it collides, it will be already in the block.

If this position is the corner of your sprite, it is important to keep in mind that this means that you only test collision on one corner and not the opposite one. This means that if you're xpos and ypos are in the bottom left corner, you are not testing for the other side. This means that your entire right side can be inside a block, and you still won't detect collision. This can be solved by simply also checking collision for the other corner(s).

If you want the code to reset the position of the sprite when colliding, based upon your code, you will get something like this:

float testX, testY;
GetSpritePosition(m_iPlayerSprite, testX, testY);

//for Y (with original X)
int test = TMap[(int)(yPos / TileSize)][(int)(originalX / TileSize)];

if (test != 8)
{
    yPos = originalY;
    cout << "TEST_Y"<< endl;
}

//For X (with original Y)
int test = TMap[(int)(originalY / TileSize)][(int)(xPos / TileSize)];

if (test != 8)
{
    xPos = originalX;
    cout << "TEST_X"<< endl;
}

//For X and Y
int test = TMap[(int)(yPos / TileSize)][(int)(xPos / TileSize)];

if (test != 8)
{
    xPos = originalX;
    yPos = originalY;
    cout << "TEST_XY"<< endl;
}

Where originalX and originalY are the xPos and yPos before the movements.

Note that you will have to do x and y separately, otherwise the x position will also reset if you collide with a block below you because gravity wants to move you down. In the end you do test for both, but if in one of the former the xPos or yPos has already been reset, this code will be the same as one of the first two sets. The last test is only necessary of you move diagonally from one block to another.

If you want to test for the other corners, you just add the sprite width to xPos and/or add the sprite height.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Could you give me a code example?, I understand the concept of collision detection but I'm really struggling with the programming. \$\endgroup\$ – Labrador Oct 15 '16 at 23:05
  • \$\begingroup\$ are you trying to make your player be unable to collide with blocks or are you just testing if the player is in a block? Could you describe the exact problems you're experiencing right now? \$\endgroup\$ – dragonfly Oct 16 '16 at 10:54
  • \$\begingroup\$ I want the player to collide with everything except the blue sky (block 8), after collision the position resets to the original position outside of the block. \$\endgroup\$ – Labrador Oct 16 '16 at 11:27
  • \$\begingroup\$ Several things I tried didn't work, I tried different concepts like AABB, it's the code part where everything goes south on me. I just need some good example code to understand how to do something like this. \$\endgroup\$ – Labrador Oct 16 '16 at 11:29
  • \$\begingroup\$ I'll have a look into it \$\endgroup\$ – dragonfly Oct 16 '16 at 11:53

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.