Epharos

Java
Timer pour libgdx

15 messages dans ce sujet

Coucou les ironcraftiens !

Etant actuellement en train de développer un jeu avec libgdx et ayant besoin de me faire pleiiiiin de timer, je trouvais cette façon très peu pratique :

int timer = 0;

public void render(Batch batch)
{
    timer++;

    if(timer == 80)
    {
        System.out.println("Il s'est passé 2 secondes !");
        timer = 0;
    }
}

Du coup pour palier à ce problème je me suis créé une class Timer que je trouve relativement pratique, et je vous la partage pour savoir si vous trouvez d'autres méthodes qui pourraient améliorer mon système (et aussi parce qu'elle pourrait vous servir) :

Timer.java :

package ...;

import java.util.HashMap;
import java.util.Map;

public class Timer 
{
	private static Map<String, Timer> timers = new HashMap<String, Timer>();
	
	private int time = 0;
	public final int max;
	public final String key;
	
	public Timer(String key, int max)
	{
		this.max = max;
		this.key = key;
		Timer.timers.put(key, this);
	}

	public static Timer getTimer(String s)
	{
		return Timer.timers.get(s);
	}
	
	public static void update()
	{
		for(Map.Entry<String, Timer> entry : Timer.timers.entrySet())
		{
			Timer timer = ((Timer) entry.getValue());
			
			timer.time++;
			
			if(timer.time == timer.max)
			{
				timer.execute();
				timer.time = 0;
			}
		}
	}
	
	public void kill()
	{
		Timer.timers.remove(this.key);
	}
	
	public void execute()
	{
		
	}
}

MonScreen.java :

public void render(Batch batch)
{
    Timer.update();
}

Pour son utilisation c'est très simple, je vous donne trois utilisations :

new Timer("timer1", 80) //on crée un timer de 2 secondes du nom de "timer1"
{
    public void execute()
    {
        System.out.println("Il s'est passé 2 secondes !"); //on affiche qu'il s'est passé 2 secondes
    }
};

new Timer("timer2", 40) //on crée un timer d'une seconde du nom de "timer2"
{
    int seconds = 0; //on crée une variable qui va compter les secondes

    public void execute() //à chaque exécution du timer ...
    {
        this.seconds++; //on augmente les secondes d'un
        
        System.out.println("Mon timer est en route depuis " + this.seconds + " secondes"); //on affiche le temps depuis que le timer est actif
    }
};

new Timer("timer3", 40) //on crée un autre timer d'une seconde qui s'appelle "timer3"
{
    int seconds = 0; //pareil, une variable qui compte les secondes

    public void execute() //à chaque exécution du timer ...
    {
        if(this.seconds == 10) //si ça fait 10 secondes que le timer tourne ...
        {
            System.out.println("BONNE ANNEE !"); //on souhaite une bonne année
            this.kill(); //on arrête le timer
            return; //et on sort de la fonction pour éviter qu'il fasse la suite
        }

        System.out.println((10 - this.seconds) + ", "); //10, 9, 8, 7, ...

        this.seconds++; //on augmente le nombre de secondes d'un
    }
};

J'espère pouvoir vous aider avec vos prochains jeux ;) a fonctionne sous libgdx, mais ça peut fonctionner avec tout hein :P

See ya !

2

Partager ce message


Lien à poster
Partager sur d’autres sites

Hello o/

Alors, je ne connais pas les besoins spécifiques qui t'ont conduit à ce design, par contre je me demande pourquoi ne pas avoir implémenté une quelconque forme de callbacks?

Si je ne me trompe pas, ici tu redéfinis la méthode execute() à l'instanciation de chaque Timer, c'est bien ça?

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Je vais te poser un problème : comment 40 "tick" peuvent représenter 1 seconde ? :P

1

Partager ce message


Lien à poster
Partager sur d’autres sites

C'est vrai que je n'ai pas réfléchi à ça, mais c'est aussi un problème! Comment comptes-tu le temps afin de t'assurer qu'il s'écoule de façon disons linéaire?

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Mais c'est très gentil de ta part !

(Il me semble qu'une seconde = 20 ticks :P)

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Merci pour le partage ! :)

Effectivement, 1 seconde = 20 ticks dans Minecraft, mais le système de timer n'est pas qu'une incrémentation dans la boucle de render. ^^

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Bah en fait le problème c'est que le timer marche uniquement si on a 40 FPS constants, genre une chute de fps et tu break tout.

Du coup un moyen simple : le delta time. Si tu sais pas exactement, c'est le temps entre la frame en cours et celle d'avant, sous libgdx il est en seconde : ça nous simplifie la tache.

Donc si je reprend ton code :

package ...;

import java.util.HashMap;
import java.util.Map;

public class Timer 
{
	private static Map<String, Timer> timers = new HashMap<String, Timer>();
	
	private int time = 0;
	public final int max;
	public final String key;
	
	public Timer(String key, int max)
	{
		this.max = max;
		this.key = key;
		Timer.timers.put(key, this);
	}

	public static Timer getTimer(String s)
	{
		return Timer.timers.get(s);
	}
	
	public static void update(float delta)
	{
		for(Map.Entry<String, Timer> entry : Timer.timers.entrySet())
		{
			Timer timer = ((Timer) entry.getValue());
			
			timer.time += delta;
			
			if(timer.time >= timer.max)
			{
				timer.execute();
				timer.time -= timer.max;
			}
		}
	}
	
	public void kill()
	{
		Timer.timers.remove(this.key);
	}
	
	public void execute()
	{
		
	}
}

Du coup pour update :

Timer.update(Gdx.graphics.getDeltaTime());

Et pour créer un timer

new Timer("timer1", 2f) //on crée un timer de 2 secondes du nom de "timer1" <-- le second argument est désormais en seconde
{
    public void execute()
    {
        System.out.println("Il s'est passé 2 secondes !"); //on affiche qu'il s'est passé 2 secondes
    }
};

Mais sinon un système de callback serais plus intéressant je pense.

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Effectivement, ayant bloqué le nombre de fps à 40 et ce nombre restant constant quand je fais mes test je n'avais pas pris ça en compte :o

Mais du coup à partir de ton code @Zetsyog, il se peut par exemple que mon code s'exécute à partir de 1,001 seconde (ou autre hein), du coup au bout de 1000 secondes on s'est décalé d'une seconde, non ?

Un système de callback ? C-a-d ?

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Effectivement, ayant bloqué le nombre de fps à 40 et ce nombre restant constant quand je fais mes test je n'avais pas pris ça en compte :o

Mais du coup à partir de ton code @Zetsyog, il se peut par exemple que mon code s'exécute à partir de 1,001 seconde (ou autre hein), du coup au bout de 1000 secondes on s'est décalé d'une seconde, non ?

Le décalage peut être plus embêtant que ça si par exemple tu tournes à 120 fps ^^

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Bah oui, ya un toujours un risque de décalage, après faut juste espérer que si les fps chutent, ils remontent après que ça se lisse, sinon on peut mettre un while à la place du if...

1

Partager ce message


Lien à poster
Partager sur d’autres sites

Merci ! ^-^

Le décalage peut être plus embêtant que ça si par exemple tu tournes à 120 fps ^^

Malheureusement sur ce pc je pense pas pouvoir monter à 120 fps :P

Bah oui, ya un toujours un risque de décalage, après faut juste espérer que si les fps chutent, ils remontent après que ça se lisse, sinon on peut mettre un while à la place du if...

D'accord, merci ^-^

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Salut,

si tu cherches vraiment à avoir un temps 'réel' (en secondes), je te propose ca:

package com.grillecube.client;

public class Timer
{
	private static final double NANO_TO_SECOND = 1000000000;
	private double _time;
	private long _last_check;
	
	public Timer()
	{
		this._time = 0;
		this._last_check = System.nanoTime();
	}
	
	public void update()
	{
		long t = System.nanoTime();
		this._time += (t - this._last_check) / NANO_TO_SECOND;
		this._last_check = t;
	}
	
	public double getTime()
	{
		return (this._time);
	}
	
	@Override
	public String toString()
	{
		return ("Timer: " + this.getTime());
	}
	
	public static void main(String[] args)
	{
		Timer timer = new Timer();
		
		while (true)
		{
			timer.update();
			System.out.println(timer.toString());
			
			try
			{
				Thread.sleep(100);
			}
			catch (InterruptedException e)
			{
				break ;
			}
		}
	}
}

En gros: 'update()' met à jour le timer, getTimer()renvoit un double depuis l'instanciation du Timer qui correspond au temps ecoulé en seconde depuis le dernier 'update()'

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Le delta time correspond justement au temps en seconde depuis la dernière frame ^^

0

Partager ce message


Lien à poster
Partager sur d’autres sites

@Zetsyog ah oui sorry j'avais pas vu ton code ^^ oui je ne pensais pas libgx faisait ca :) nice!

0

Partager ce message


Lien à poster
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !


Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.


Connectez-vous maintenant