Movimento sprite tecnico

di il
4 risposte

Movimento sprite tecnico

Ciao ragazzi! Sono finalmente ritornato sul forum perche' ho riscontrato un problema abbastanza grave su un minigioco che sto facendo...
L'esempio che sto per scrivere non ha nulla in comune con il gioco ma ritrae il programma.
Immaginiamoci un piano inclinato. Ogni 5 secondi circa spawna una pallina che cade a VELOCITA' COSTANTE(anche contro le leggi della fisica) verso destra, fino a un massimo di 50 palline.
Il problema e' che con il normale movimento (nelle SFML e immagino il concetto sia uguale in quasi tutte le librerie grafiche) e'
while(...){
x = x + 1,
sprite.setPosition(x, y);
}

immaginando che il while ogni volta che passa per quell'istruzione aggiunga un valore alla coordinata x(preferisco non mettere "sprite.move(x, y)" perche' non sono variabili ma semplici valori) per simulare il movimento a destra(giusto?), che simula la caduta a velocita' costante di una pallina. Il problema e' che nel vettore di 50 elementi(la pallina) inizio a sommarlo solo ad 1 elemento, e ogni 5 secondi sommo sia a quello/quelli che stavo sommando prima sia al nuovo, provocando un rallentamento degli sprite. Inoltre la velocita' non e' costante per ogni pc ma dipende dalla sua potenza... Come faccio a trasformare il movimento in un movimento costante per ogni pc e ogni secondo? E al posto di rallentare il programma generare il famoso "lag" di fps ma mettere la stessa distanza nello stesso tempo?

Ecco il codice, se riuscite ad eseguirlo con 1 sprite preso a caso noterete che dopo qualche sprite il movimento inizia a rallentare collettivamente...
#include <iostream>
#include <SFML/Graphics.hpp>
#include <time.h>

using namespace std;
using namespace sf;

void Coordinates(int tank_number);
void Sprites(Sprite palla, int& tank_spawned);
void SpawnNewTank(int& tank_spawned, double seconds, time_t officialtime, time_t& time_1);



RenderWindow window(sf::VideoMode(1920, 1080), "The Last Tank");
    float x[50];



int main()
{

    time_t officialtime, time_1;// time_2;
    double seconds;

    int tank_spawned;


    tank_spawned = 0;
    Texture ball;
    ball.loadFromFile("ball.jpg");
    Sprite palla;
    palla.setTexture(ball);
time_1 = time(NULL);

    while (window.isOpen())
    {

        sf::Event event;
        while (window.pollEvent(event))
        {

            if (event.type == sf::Event::Closed)
                window.close();
        }
window.clear();
          officialtime = time(NULL);
          SpawnNewTank(tank_spawned, seconds, officialtime, time_1);
          Coordinates(tank_spawned);
       //Sprites(palla, tank_spawned);
    int cont;
    cont = 0;
    while (cont <= tank_spawned)
    {
window.draw(palla);
palla.setPosition(x[cont], 0);
        cont = cont + 1;
    }
        window.display();


    }
    return 0;
}


void Coordinates(int tank_spawned) //tank == palla, e' troppo lungo spiegarvi perche' l'ho chiamato tank e non palla
{
    int cont;
    cont = 0;
    while (cont <= tank_spawned)
    {
        x[cont] = x[cont] + 0.3;

        cout<<x[cont]<<" ";
        cont = cont + 1;
    }
}





void SpawnNewTank(int& tank_spawned, double seconds, time_t officialtime, time_t& time_1)
{
if (tank_spawned < 49){
 seconds = difftime(officialtime, time_1);
 if (seconds >= 3){
    time_1 = time(NULL);
    tank_spawned = tank_spawned+1;;
 }
}
cout <<tank_spawned<<" "<<seconds<<endl;
}


void Sprites(Sprite palla, int& tank_spawned)
{
    int cont;
    cont = 0;
    while (cont <= tank_spawned)
    {
window.draw(palla);
palla.setPosition(x[cont], 0);
        cont = cont + 1;
    }
    cout <<cont<<endl;
cont = 0;
}
La qualita' del codice e' pari a zero, ma pls abbiate pieta' per uno studente al 3 anno in un tecnico(anche se loro stanno studiando le librerie Allegro e hanno appena iniziato i vettori... a me non piace allegro e linux e' troppo poco user friendly, anche se ammetto che e' un sistema operativo ottimo), e il programma e' stato fatto molto con i piedi e superficialmente, diciamo che e' solo una prova per il programma ufficiale

4 Risposte

  • Re: Movimento sprite tecnico

    I giochi vanno gestiti a "tick", ovvero a tempi prestabiliti, questo permetterà di far girare alla stessa velocità il gioco su tutti i pc piu o meno datati.
    La seconda regola è che va disegnato tutto solo alla fine o inizio del tick, in modo da non aver sfarfallii nel gioco.
    pseudocode:
    
    
    tempoTick = 50 millisecondi;
    direction = 1;
    while(1)
    {
        startTick = clockCpu();
        //muovo
        palla.x += direction;
        //collisioni
        if ( palla.x >= schermo.w - 1 )
            direction = -direction;
        if ( palla.x <= 0 )
            direction = -direction;
        //disegno
        drawGame();
        //aspetto il termine del tick
        while ( clockCpu() < startTick + tempoTick) cpuRelax();
    }
    
    
  • Re: Movimento sprite tecnico

    Grazie mille! Era esattamente come immaginavo, anzi quasi esattamente, io pensavo che il loop con i millisecondi andasse solo sul movimento e non su tutto il programma.
    Il codice che mi hai mostrato di che libreria e'?
  • Re: Movimento sprite tecnico

    Di nessuna libreria, l'ho scritto appositamente per te, è pseudocodice solo per far comprendere meglio il concetto.
  • Re: Movimento sprite tecnico

    Grazie
    Qualche consiglio per il tempo in millisecondi? So farlo con i secondi(come si vede dal programma) ma in millisecondi no... Per fortuna c'e' internet e i miei professori, che qualche settimana fa mi hanno risposto appositamente per prendere il tempo in millisecondi.

    Professore ha scritto:


    ciao davide
    prova questo codice
    clock_t clock_start;
    .........
    clock_start=clock();
    ........
    time_c=(double)(clock()-clock_start)/CLOCKS_PER_SEC;
    .........
    
    in time_c dovresti ritrovare il tempo trascorso in millisecondi
    Provero' questo
Devi accedere o registrarti per scrivere nel forum
4 risposte