Hướng di chuyển của nhân vật bị fail

Chào mọi người. :grin:
Hiện tại em đang học SFML và muốn thêm bớt 1 chút yếu tố vật lí (ở đây là gia tốc) cho nhân vật.
Tuy nhiên thì em bị gặp một số lỗi về hướng di chuyển của nhân vật. Cụ thể lỗi thì em cũng chưa biết cách diễn đạt nên dùng tạm Paint vẽ 1 hình cho mọi người dễ hình dung.
Chú thích:

  • Đường màu đỏ là đường đi của nhân vật
  • Mũi tên đen chỉ hướng di chuyển của nhân vật
  • A -> W là thứ tự phím bấm

Khi em A -> W thì nhân vật đang đi sang trái sẽ đi dần lên như hình. Thế nhưng khi nhân vật đang đi sang(D -> W) phải thì lại bị trôi tiếp đến khi vận tốc bằng 0 mới đổi hướng.

Ban đầu em đã nghĩ là di thứ tự sắp xếp các câu lệnh điều kiển nhân vật nhưng sau khi đổi lại vẫn không được. Một cái nữa là không phải do bộ gõ vì em thử đổi tiếng Anh với tiếng Việt rồi nhưng đều vậy.
Ai biết em sai ở đâu thì gợi ý cho em với ạ. Em cảm ơn mọi người rất nhiều.
Dưới đây là code của em ạ.
P/s : Ai có thuật toán tốt hơn cho cái gia tốc thì gợi ý cho em nữa nhé. :grin:

#include <SFML/Graphics.hpp>
#include <iostream>
#include<vector>

using namespace sf;

int main()
{
    // Create the main window
    RenderWindow window(VideoMode(800,600) , "Wall");
    window.setFramerateLimit(60);
    //Grid
    float girdSize = 50.f;
    //Creat player
    RectangleShape player(Vector2f(girdSize , girdSize));
    player.setFillColor(Color::Green);

    //Creat acceleration, drag, maxVelocity, ..
    float acceleration = 2.5f;
    float drag = 0.5f;
    float maxVelocity = 6.f;
    Vector2f currentVelocity( 0 , 0);
    float deltaTime = 0;
    float multi = 15;

    Clock clock;
    //Main loop
    while(window.isOpen()){
        Event event;
        while(window.pollEvent(event)){
            if(event.type == Event::Closed){
                window.close();
            }
        }

        //Update
        //Restart deltaTime
        deltaTime = clock.restart().asSeconds();

        //Acceleration

        if(Keyboard::isKeyPressed(Keyboard::A)){
            if(currentVelocity.x > -maxVelocity){
                currentVelocity.x -= acceleration * deltaTime * multi;
            }
        }
        if(Keyboard::isKeyPressed(Keyboard::D)){
            if(currentVelocity.x < maxVelocity){
                currentVelocity.x += acceleration * deltaTime * multi;
            }
        }
        if(Keyboard::isKeyPressed(Keyboard::S)){
            if(currentVelocity.y < maxVelocity){
                currentVelocity.y += acceleration * deltaTime * multi;
            }
        }
        if(Keyboard::isKeyPressed(Keyboard::W)){
            if(currentVelocity.y > -maxVelocity){
                currentVelocity.y -= acceleration * deltaTime * multi;
            }
        }

        //Drag
        if(currentVelocity.x > 0){
            currentVelocity.x -= drag  * deltaTime * multi;
            if(currentVelocity.x < 0){
                currentVelocity.x = 0 ;
            }
        }
        if(currentVelocity.x < 0){
            currentVelocity.x += drag  * deltaTime * multi;
            if(currentVelocity.x > 0){
                currentVelocity.x = 0 ;
            }
        }
        if(currentVelocity.y > 0){
            currentVelocity.y -= drag  * deltaTime * multi;
            if(currentVelocity.y < 0){
                currentVelocity.y = 0 ;
            }
        }
        if(currentVelocity.y < 0){
            currentVelocity.y += drag  * deltaTime * multi;
            if(currentVelocity.x > 0){
                currentVelocity.y = 0 ;
            }
        }

        player.move(currentVelocity);

        //Render
        window.clear();

        window.draw(player);

        window.display();

    }



    return EXIT_SUCCESS;
}

Code có lẽ sai ở phần gia tốc và kéo thả nhưng em post full code vì sợ có thể sai ở chỗ khác.

Giải thích thuật toán phần gia tốc và kéo thả

Phần gia tốc em sử dụng 1 biến gia tốc acceleration để minh họa cho gia tốc. Khi press A thì sẽ so sánh vận tốc hiện thời currentVelocity với vận tốc tối đa maxVelocity. Nếu nhỏ hơn thì tăng vận tốc theo gia tốc.

Khi nhả A thì sẽ so sánh currentVelocity với 0. Nếu còn lớn hơn 0 thì trừ đi drag .Nếu currentVeclocity mà nhỏ hơn thì sẽ đưa currentVelocity về 0.

Bản chất thì accelerationdrag đều là gia tốc nhưng 1 cái là gia tốc bắt đầu và gia tốc khi phanh.

1 Like

app.cpp:19:21: error: ‘wall’ was not declared in this scope
walls.push_back(wall);

code này có chạy được đâu
gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)

4 Likes

Code do em chưa xoá hết phần tạo wall nên bị lỗi. Em đã sửa lại rồi ạ. Cảm ơn anh đã nhắc nhở.

2 Likes

Sao ở trường hợp nhấn phím D bạn lại dùng currentVelocity.x += maxVelocity * deltaTime * multi mà không phải là
currentVelocity.x += acceleration * deltaTime * multi. Phím W cũng thế.

4 Likes

Cảm ơn anh /chị nhiều ạ :grin: . Em đã sửa lại vào code rồi ạ.
Cái này do em copy từ condition xuống mà quên chưa sửa :man_facepalming:
Nhưng mà cái đấy không phải lí do làm cho hướng của nhân vậy bị fail. Nó chỉ ảnh hưởng đến tốc độ thôi.
Phát hiện ra sai nhiều lỗi quá. Vậy mà lúc debug không biết gì luôn :man_facepalming:

2 Likes
if(currentVelocity.y < 0){
    currentVelocity.y += drag  * deltaTime * multi;
    if(currentVelocity.x > 0){
        currentVelocity.y = 0 ;
    }
}

lỗi ở đòng thứ 3 của đoạn này

8 Likes

Cảm ơn anh đã chỉ cho em :grin:.
Hậu quả của việc copy/paste mà không nhìn kĩ :man_facepalming: .
Cách giải quyết là sửa currentVeclocity.x thành currentVeclocity.y dành cho ai bị lag như em.

2 Likes

hiện tại cái ô màu xanh đó nó vẫn bị vượt ra khỏi khung view, chỉnh lại một chút cho nó không được ra khỏi khung view đó xem
học tập thì cứ thấy gì chưa ưng ý là làm cho nó ưng ý hơn thôi, cứ thoải mái mà challenge

4 Likes

À phần này thì em có fix bằng cách getPosition() của player sau đó so sách với 4 đường thẳng
x = 0 ,
x = window.getSize().x ,
y= 0 ,
y= window.getSize().y
nếu thấy vượt thì em có 2 hướng là:

  • setPos cho nhân vật về tọa độ phù hợp
  • move() 1 đoạn nhỏ theo hướng ngược lại

Tuy nhiên cũng chưa biết có phải là cách tối ưu nhất không nên vẫn đang tìm kiếm thêm. Ngoài ra thì còn cách setView cho window nhưng em chưa quen cách này lắm, còn đang lơ mơ.

FIGHTING !! :grin:

3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?