• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Ping Pong SFML Kąt odbicia

Object Storage Arubacloud
0 głosów
746 wizyt
pytanie zadane 6 kwietnia 2017 w C i C++ przez K4mczi Nowicjusz (120 p.)
edycja 6 kwietnia 2017 przez K4mczi

Witam! Otóż zacząłem się uczyć SFML'a i zrobiłem taki o to program z tej strony: http://gamecodeschool.com/sfml/coding-a-simple-pong-game-with-sfml/ . Wszystko ładnie działało więc postanowiłem ją nieco przerobić tak aby były dwie paletki na 2 graczy. Problemem jest fakt że piłka nie odbija się pod kątem. Jeśli znacie rozwiązanie będe wdzięczny!

Kody źródłowe:

 

Main.cpp

 

#include <SFML/Graphics.hpp>
#include "Bat.h"
#include "Ball.h"
#include <sstream>
#include <cstdlib>

#include <SFML/Audio.hpp>

using namespace sf;
int main()
{
    int windowWidth=1000;
    int windowHeight=600;
    RenderWindow window(VideoMode(windowWidth,windowHeight),"Pong");
    int score=0;
    int lives=3;

    Bat bat(windowWidth-20,windowHeight/2);
    Bat bacik(20,windowHeight/2);

    Ball ball(500,250);

    Text hud;

    Font font;
    font.loadFromFile("DS-DIGIT.TTF");
    hud.setFont(font);
    hud.setCharacterSize(75);
    hud.setFillColor(sf::Color::White);

    while(window.isOpen())
    {
        /*

        */

        Event event;
        while(window.pollEvent(event))
        {
            if(event.type==Event::Closed)
                window.close();
        }
        if(Keyboard::isKeyPressed(Keyboard::Up))
        {
            bat.moveUp();
        }
        else if(Keyboard::isKeyPressed(Keyboard::Down))
        {
            bat.moveDown();
        }
        else if(Keyboard::isKeyPressed(Keyboard::Escape))
        {
            window.close();
        }

        if(Keyboard::isKeyPressed(Keyboard::W))
        {
            bacik.moveUp();
        }
        else if(Keyboard::isKeyPressed(Keyboard::S))
        {
            bacik.moveDown();
        }

    if(ball.getPosition().top>windowHeight||ball.getPosition().top<windowHeight)
    {
       ball.reboundTopOrBottom();
    }

    if (ball.getPosition().left < 0 )
    {
       ball.reboundSideLeft();

    }
    if(ball.getPosition().left+10>windowWidth)
    {
        ball.reboundSideRight();
    }
    if(ball.getPosition().intersects(bat.getPosition()))
    {
        ball.reboundBat();

    }
    if(ball.getPosition().intersects(bacik.getPosition()))
    {
        ball.reboundBat();

    }
    ball.update();
    bat.update();
    bacik.update();
    std::stringstream ss;
    ss<<"Score: "<<score<<"   Lives: "<<lives;
    hud.setString(ss.str());

    window.clear(Color(26,128,182,255));
    window.draw(bat.getShape());
    window.draw(bacik.getShape());
    window.draw(ball.getShape());
    window.draw(hud);

    window.display();}
   getchar();
   return 0;
}
 

 

 

 

 

 

Ball.cpp

#include "Ball.h"

Ball::Ball(float startX, float startY)
{
    position.x=startX;
    position.y=startY;

    ballShape.setSize(sf::Vector2f(10,10));
    ballShape.setPosition(position);
}
FloatRect Ball::getPosition()
{
    return ballShape.getGlobalBounds();
}
RectangleShape Ball::getShape()
{
    return ballShape;
}
float Ball::getYVelocity()
{
    return yVelocity;
}
void Ball::reboundTopOrBottom()
{
    yVelocity=-yVelocity;
}
void Ball::reboundSideLeft()
{
    position.y = 250;
    position.x = 500;

}
void Ball::reboundSideRight()
{
    position.y = 250;
    position.x = 500;
}
void Ball::reboundBat()
{
    position.x -= (xVelocity * 30);
    xVelocity = -xVelocity;

}

void Ball::update()
{
    position.y+=yVelocity;
    position.x+=xVelocity;

    ballShape.setPosition(position);
}
 

 

 

 

ball.h

#pragma once
#include <SFML/Graphics.hpp>

using namespace sf;

class Ball
{private:
    Vector2f position;
    RectangleShape ballShape;

    float xVelocity= .2f;
    float yVelocity= .2f;

public:
    Ball (float startX, float startY);
    FloatRect getPosition();
    RectangleShape getShape();
    float getYVelocity();
    void reboundSideLeft();
    void reboundSideRight();
    void reboundTopOrBottom();
    void reboundBat();

    void update();

};
 

 

 

 

 

 

 

Bat.h

 

#pragma once
#include <SFML/Graphics.hpp>
using namespace sf;

class Bat
{
private:
    Vector2f position;
    //rectangleshape object
    RectangleShape batShape;
    float batSpeed = .3f;
public:
    Bat(float startX, float startY);
    FloatRect getPosition();
    RectangleShape getShape();
    void moveUp();
    void moveDown();
    void update();
};
 

 

 

 

 

 

 

Bat.cpp

#include "Bat.h"

Bat::Bat(float startX, float startY)
{
    position.x=startX;
    position.y=startY;

    batShape.setSize(sf::Vector2f(5,100));
    batShape.setPosition(position);
}
FloatRect Bat::getPosition()
{
    return batShape.getGlobalBounds();
}
RectangleShape Bat::getShape()
{
    return batShape;
}
void Bat::moveUp()
{
    position.y-=batSpeed;
}
void Bat::moveDown()
{
    position.y+=batSpeed;
}
void Bat::update()
{
    batShape.setPosition(position);
}



 

 

 

komentarz 6 kwietnia 2017 przez __new__in__town Bywalec (2,100 p.)
Kod Ci sie posypal. Wyedutuj posta, bo mniej czytelne jest.
komentarz 6 kwietnia 2017 przez K4mczi Nowicjusz (120 p.)
W jakim sensie posypał?
komentarz 6 kwietnia 2017 przez __new__in__town Bywalec (2,100 p.)
Nie jest w zakladce "code snippet". Nie widac podswietlenia skladni. Drobiazg, ale dlaczego nie uzywac skoro jest i ulatwia zycie? :)
komentarz 6 kwietnia 2017 przez K4mczi Nowicjusz (120 p.)
Rozumiem. Nie wiedziałem o tym, co dopiero założyłem konto na forum :D

1 odpowiedź

+2 głosów
odpowiedź 6 kwietnia 2017 przez Ehlert Ekspert (212,670 p.)

Cześć wink

Kilka cennych uwag:

  1. Z tego co dojrzałem na moim kompie piłeczka ma nieregularne tempo. Może to wynikać z braku pętli stałokrokowej.
    while (game.isOpen())
    {
       inputHandling();
       fps = timer.restart();
       accumulator += fps;
       if (accumulator >= sf::seconds(0.33))
       {
          //tutaj update obiektów
          // w metodzie obiektu update przekazujesz wartość z accumulator
          accumulator = sf::Time::Zero;
       }
       //...
    }
    
  2. Co do logiki. Randuj na początku miejsce piłeczki. Nadaj jej kierunek. 
    sf::Vector2f downRightDirection(1,1);
    sf::Vector2f upLeftDirection(-1,-1);
    
    sf::Vector2f normalizeVector(sf::Vector2f vector) {
        float length = std::sqrt(std::pow(vector.x, 2) + std::pow(vector.y, 2));
        return sf::Vector2f(vector.x / length, vector.y / length);
    }
    

    Kierunki trzymaj w postaci wektorów znormalizowanych. W momencie jak wykrywasz kolizję z jakąś ścianą zmieniasz znak jednego z koordynatów wektora. Przy odbiciu od paletki możesz (w zależności od miejsca paletki) wykorzystywać funkcje logarytmiczną, wykładniczą itp żeby utrudnić odbiór piłki przeciwnikowi.

  3. Te ify w pętli głównej powinny być częścią metody update. 

komentarz 8 kwietnia 2017 przez K4mczi Nowicjusz (120 p.)
Dziękuje za wszelkie uwagi, postaram się do nich zastosować :) Mam jeszcze jedno pytanie czy jest jakaś możliwość w SFML'u aby ustawic limit przycisku. Ponieważ robię grę i tam chciałem zastosować skok jednak jak naciskam odpowiedni przycisk to postać stoi na gorze póki go nie puszcze pozdrawiam :)
1
komentarz 8 kwietnia 2017 przez Ehlert Ekspert (212,670 p.)

Masz dwa antagonistyczne eventy:

  • KeyPressed
  • KeyReleased

Jeśli event.type to ten drugi, to event.key.code ​​​​​​​zawiera enum przycisku zwolnionego. 

komentarz 8 kwietnia 2017 przez K4mczi Nowicjusz (120 p.)
Wydaje mi się że wyjdzie na to samo. Postać opada na dół jeśli puszcze przycisk, ale chodzi mi o to, aby nie mogła ona "latać". Chce aby po naciśnięciu przycisku skoku postać opadała zawsze po takim samym czasie nie zależnie od czasu trzymania przycisku.

Podobne pytania

0 głosów
2 odpowiedzi 317 wizyt
0 głosów
1 odpowiedź 256 wizyt
pytanie zadane 17 marca 2018 w C i C++ przez zpawlo00 Początkujący (310 p.)
+4 głosów
3 odpowiedzi 550 wizyt
pytanie zadane 13 września 2016 w Nasze projekty przez bimbrownik Mądrala (5,180 p.)

92,572 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...