Sauve le hérisson !

Un pauvre hérisson s’est perdu dans une série de jardins enchantés… À vous de le retrouver !

Incarnez un jardinier courageux et partez à l’aventure à travers des cartes pleines de surprises. Ramassez les carottes pour ouvrir les portes, évitez les guêpes (elles piquent fort mais ne survivent pas) et méfiez-vous des frelons (plus résistants et encore plus redoutables).

Chaque pas vous coûte de l’énergie selon le terrain. Restez immobile quelques instants et vous récupérerez un peu de jus. Mais attention : si vous vous faites piquer sans avoir assez d’énergie pour encaisser le coup, c’est la fin.

Alors, prêt·e à braver les jardins et sauver votre ami à piquants ?

UBGarden

Principes du jeu

Chaque jardin est une carte rectangulaire composée de cellules.

Certaines cellules sont traversables, d’autres non. Le jardinier, les guêpes et les frelons se déplacent sur cette grille. Les portes permettent de passer d’un jardin à l’autre — à condition qu’elles soient ouvertes. Les guêpes et les frelons, eux, n’empruntent jamais les portes : ils ont une peur panique des courants d’air et refusent d’y poser les pattes, qu’elles soient ouvertes ou fermées.

Pour ouvrir les portes, il faut ramasser toutes les carottes. Mais attention : les jardins sont peuplés de guêpes et de frelons… et vous êtes allergique aux piqûres !

Les guêpes meurent après vous avoir piqué. Les frelons, eux, peuvent piquer deux fois avant de rendre l’âme. Les piqûres coûtent cher : -20 d’énergie pour une guêpe, -30 pour un frelon. Si vous n’avez plus d’énergie au moment d’une piqûre, la partie est perdue.

Heureusement, des bombes insecticides sont là pour vous aider. Chaque bombe tue une guêpe ; deux bombes sont nécessaires pour un frelon. Les insectes peuvent aussi marcher sur les bombes — ce n’est pas bon pour leur santé.

Côté terrain :

Ramassez automatiquement les bonus sur votre route :

Le niveau d’énergie, le degré de fatigue (diseaseLevel) et le nombre de bombes sont affichés en permanence dans la barre d’état.

Environnement

Voici les éléments que vous rencontrerez dans le jeu :

Image Nom Description
Herbe Coût de déplacement du jardinier : 1 x diseaseLevel
Terre Coût de déplacement du jardinier : 2 x diseaseLevel
Bosquet de fleurs Franchissable uniquement par les guêpes et frelons
Nid de guêpes Génère une guêpe + une bombe insecticide toutes les 5 secondes
Nid de frelons Génère un frelon + deux bombes insecticides toutes les 10 secondes
Hérisson Hérisson apeuré à retrouver de toute urgence
Porte fermée Infranchissable tant que toutes les carottes ne sont pas ramassées
Porte ouverte Permet de passer dans un autre jardin
Carottes Toutes les ramasser pour ouvrir les portes
Pomme empoisonnée Maladie temporaire, fatigue augmentée
Pomme Guérison + regain d’énergie
Bombe insecticide Tue une guêpe ou blesse un frelon
Guêpe Meurt après une piqûre ou en touchant une bombe
Frelon Peut piquer deux fois; blesse sévèrement et nécessite deux bombes insecticide
Jardinier C’est vous !

Nous pouvons classer les éléments de la manière suivante :

Prise en main

Nous vous fournissons une première ébauche du jeu.

Au lancement, une carte simple (MapLevelDefaultStart) est chargée : le jardinier peut s’y déplacer librement, quelle que soit la nature des cellules.
Les paramètres du jeu sont stockés dans un fichier .properties, très simple à modifier.

Les fichiers properties en Java permettent de stocker facilement des couples clé/valeur.

Paramètres   Valeur par défaut Commentaire
waspMoveFrequency   1 / s Vitesse de déplacement des guêpes
hornetMoveFrequency   2 / s Vitesse de déplacement des frelons
gardenerEnergy   100 Énergie max du jardinier
energyBoost   50 Gain d’énergie avec une pomme
energyRecoverDuration   1000 ms Temps d’inactivité pour regagner 1 point d’énergie
diseaseDuration   5000 ms Durée de la maladie après un avoir mangé un trognon

Travail à fournir

Archive du jeu de base : UBGarden-student-2025.zip

1. Premiers pas

2. Gestion des mondes

3. Donnons vie aux guêpes

4. Bombes insecticides

6. Ajoutons des frelons

Gestion des bonus

Lorsque le jardinier marche sur un bonus, il doit pouvoir le ramasser. Imaginons que les classes Apple et PoisonedApple soient des sous-classes de la classe Bonus. On aimerait pouvoir écrire dans le code de la classe Gardener quelque chose comme ceci :

class Gardener {
    void pickUp(Apple apple) { ... }
    void pickUp(PoisonedApple poisonedApple) { ... }

    void doMove(Direction direction) {
        Position nextPos = direction.nextPosition(getPosition());
        Decor next = game.world().getGrid().get(nextPos);
        setPosition(nextPos);
        if (next != null)
            pickUp(next);
    }
}

Mais en Java, il n’est pas possible de faire un dispatch dynamique en fonction du type du paramètre passé à une méthode (ici, le type du bonus). Java ne fait qu’un dispatch dynamique sur l’objet appelant, pas sur les arguments.

Pour contourner cela, on inverse la dépendance : au lieu que ce soit le jardinier qui “ramasse” le bonus, c’est le bonus qui “se fait ramasser” par le jardinier. Avec ce mécanisme, on bénéficie du dispatch dynamique sur le type réel du bonus, puis du dispatch statique sur la méthode pickUp(...) côté jardinier.

class Gardener {
    void pickUp(Apple apple) { ... }
    void pickUp(PoisonedApple poisonedApple) { ... }

    void doMove(Direction direction) {
        // ... 
        if (next != null)
            next.pickUpBy(this);
    }
}

public interface Pickupabke {
    default void pickUpBy(Gardener gardener) {}
}

public abstract class Bonus implements Pickupabke {}

public class Apple extends Bonus { 
    @Override
    public void pickUpBy(Gardener gardener) {
        gardener.pickUp(this);
    }
}

public class PoisonedApple extends Bonus { 
    @Override
    public void pickUpByBy(Gardener gardener) {
        gardener.pickUp(this);
    }
 }

Dans ce cas, c’est bien la bonne méthode pickUp(Apple) ou pickUp(PoisonedApple) du jardinier qui sera appelée, grâce au double dispatch :