Seuls les membres ayant 30 points peuvent parler sur le chat.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » A Switch To The Top C
Tituya En ligne Rédacteur Points: 959 Défis: 16 Message

A Switch To The Top C

Posté le 28/06/2020 22:33

Salut !

Voila le topic lié à l'annonce faite dans la RdP 185. Ici je vous poserai sûrement des questions pour que je puisse continuer le développement du jeu.

Mais avant toute chose, pour ceux n'ayant pas joué a A Switch To The Top, voici une petite présentation du projet :

Présentation :

Il s'agit d'un jeu de plateforme où vous incarnez un magnifique carré bleu ! Votre objectif est de finir le niveau qui se présente en face de vous. Mais vous ne pouvez pas sauter non, ça serai beaucoup trop simple ! Votre seul moyen de progresser en hauteur est d'inverser la gravité ! Ainsi lorsque vous êtes en bas, vous vous cognez la tête contre le premier bloc au dessus de vous si vous utilisez votre pouvoir

A force, vous allez pouvoir créer vos propres niveaux / textures afin de profiter pleinement du jeu !

Ce projet consiste à reproduire ce jeu en C pour 90+E. Permettant une meilleure gestion d'absolument tout pour encore plus de fun !

En cours :

- Gestion du temps
- Ajout de blocs

Done :

- Physique (collisions)
- Gestion des niveaux
- Changement gravité (ainsi que gravité par défaut par niveau)
- Bloc causant la mort
- Amélioration du calcul de gravité

Voila une image du 28/06 :

Voila une image du 04/07 :


Lien :

Sur Gitea : AST3_C

Bon, je précise, il s'agit de mon premier projet de programmation d'add-in (sauf si l'on compte Dumb Clicker ). Donc je vais surement poser pleiiiiin de questions !


FlamingKite Hors ligne Membre Points: 92 Défis: 3 Message

Citer : Posté le 28/06/2020 22:35 | #


Bonne chance Tituya !
(ceci est un message du Comité de Soutien envers les développeurs courageux qui se lancent dans des projets sympas mais pas si simples. Attention le comité de soutien est totalement incompétent en programmation, sauf un peu en Basic mais c'est tout )
"Un pessimiste voit la difficulté dans chaque opportunité, un optimiste voit l'opportunité dans chaque difficulté"
Winston Churchill


J'ai bien envie aussi de mettre mes programmes en signature, après j'en ai que 2 donc c'est pas génial Bon allez, je les met quand même :
les 2 smileys c'est pour garder la bonne humeur
Lephenixnoir En ligne Administrateur Points: 18145 Défis: 142 Message

Citer : Posté le 28/06/2020 22:38 | #


Autre suggestions rapide : pourquoi deux touches différentes pour changer la gravité ? Si une seule est acceptable compte tenu du gameplay, c'est probablement plus dynamique puisque ça évite au joueur de bouger son doigt sans cesse.
Tituya En ligne Rédacteur Points: 959 Défis: 16 Message

Citer : Posté le 28/06/2020 22:41 | #


C'est prévu mais pas encore implémenté dans le jeu
Pour l'instant j'ai fais ça pour mes tests, c'est vraiment le début du projet (ce qui explique les valeurs de tests à l'écran).

Ajouté le 28/06/2020 à 23:21 :
Bon du coup je commence avec mes questions : Le timer

Pour le moment je souhaite faire une version similaire à ce que KikooDX a fait. Cela me semble plus simple pour le moment. Si je ne suis pas satisfait après ça, je ferai l'autre version que Lephe' a énoncé dans un commentaire de la RdP.

Si j'ai bien compris il faut que j'actualise mon écran en fonction des FPS. C'est logique ça. Mais par contre je n'ai pas bien compris le principe du callback.

Il faut donc que je lance ce script en fonction des FPS.
draw_level(level);
draw_player(player_x,player_y);
dupdate();


Pour ça il faut donc que je déclare le timer avant, mais je ne sais absolument pas quoi mettre pour le délai et le callback... J'ai bien lu le header concernant les timers mais sans voir une application concrète je ne vois pas vraiment comment faire. J'ai essayé de comprendre le code de JTMM mais vu qu'il s'agit d'une autre version de gint, ça ne correspond pas vraiment.
Bref : Je sais pas utiliser les timers donc je vous demande comment faire.

Après ça je peux me débrouiller pour la vitesse du joueur. C'est juste de la physique ça

Merci !

[EDIT]

-J'ai rajouté la touche unique (SHIFT) pour changer la gravité, et je n'autorise cela que lorsque le joueur est sur un bloc solide.
Bretagne > Reste du globe
(Et de toute façon, vous pouvez pas dire l'inverse grâce à Bzh)



Kikoodx Hors ligne Membre Points: 2146 Défis: 11 Message

Citer : Posté le 29/06/2020 11:09 | #


Salut, je vais répondre au message de Lephé sur ce topic.

Lephenixnoir a écrit :
Il y a différents niveaux de ça. D'un côté tu as la méthode de KikooDX où il fixe juste 30 FPS (je crois) et applique une gravité dont l'unité est en gros en m·frame⁻². Je suis pas d'accord que "c'est le mieux dans cette situation" (encore moins de juste appliquer une vitesse constante) mais ça marche.

L'autre côté c'est de mesurer vraiment le temps qui s'écoule entre deux frames (ou de le fixer, par exemple à 1/30s) et ensuite de calculer l'évolution de la position/vitesse/etc des objets en fonction du temps écoulé et de leur vitesse/accélération/etc.

Avoir une vraie simulation est un peu plus cher à calculer, mais sur la Graph 90+E tu ne le sentiras même pas parce que c'est le dessin qui pompe tout le temps CPU. Tu peux pas contrôler non plus les choses au pixel près. Mais le rendu est beaucoup plus naturel.

60 UPS et 30 FPS. Ce n'est pas le mieux mais je tiens beaucoup à avoir des timings/vitesses consistantes. Pour le prochain jeu ce sera mieux fait, j'ai eu des problèmes avec ça.
La seconde méthode proposée a quelques avantages, comme le slowmo qui peut être intégré très facilement. Si le temps est fixe, c'est juste équivalent à ce que j'avais fait pour JTMM.
Je ne pense pas qu'un jeu se doit d'avoir une gravité réaliste, c'est rare que ce soit le cas. (Tiens je peux caser Celeste )
Et dans cette situation spécifique, je pense vraiment que rester sur une vitesse constante est le bon choix.
VVVVVV, Gravity Duck et bien d'autres jeux ont une vitesse constante et à raison. Le ressenti est plus "naturel" que la méthode classique.

Sidenote : évitez de considérer que JTMM est mon standard en terme de platformer. J'ai fait énormément d'erreurs sur ce projet sur tous les plans (notamment le système de saut qui est hyper mal foutu).
2+2=5
Perdu
Lephenixnoir En ligne Administrateur Points: 18145 Défis: 142 Message

Citer : Posté le 29/06/2020 11:19 | #


Donc un timer ça sert à exécuter du code de façon périodique. Le code qu'on exécute dans un timer est appelé "callback" ou "handler". Le but d'un callback c'est toujours d'être le plus court possible. Ici, on peut juste s'en servir pour compter chaque fois que 1/30s s'écoule (par exemple).

L'idée c'est d'avoir une variable par exemple frame_elapsed qui te dit quand 1/30s s'est écoulé. Toutes les 1/30s on met cette variable à 1 et quand on dessine un frame on la met à 0. Si au moment de dessiner un frame elle vaut toujours 0 on attend qu'elle vale 1.

Ça ressemble à ça.

#include <gint/clock.h> /* sleep() */

/* La valeur va changer dans le callback, ce que le compilateur ne sait pas, donc
   on met "volatile" pour lui dire "attention la valeur change dans ton dos" */
volatile int frame_elapsed = 1;

/* Du code pour lancer le timer ... */

while(game_loop)
{
    /* On attend que la variable passe à 1 */
    while(frame_elasped == 0) sleep();

    read_inputs();
    do_physics();
    draw_frame();
    dupdate();

    frame_elapsed = 0;
}

/* Du code pour arrêter le timer... */

Et donc ensuite la question c'est comment on fait marcher un timer. Ici c'est pas bien difficile : on va écrire une fonction qui prend en argument l'adresse de la variable et la met à 1. Ce sera notre callback. Un callback de timer doit renvoyer TIMER_STOP ou TIMER_CONTINUE pour décider si le timer doit continuer de tourner. Ici on veut que le timer continue jusqu'à la fin du programme donc on renvoie TIMER_CONTINUE à chaque fois.

#include <gint/timer.h>

int callback(volatile int *frame_elasped)
{
    *frame_elapsed = 1;
    return TIMER_CONTINUE;
}

Ensuite, au début de la fonction principale, tu lances le timer. La fonction timer_setup() te demande quel timer tu veux mais ici on s'en fout un peu donc on va la laisser choisir. Le délai à indiquer est en µs, je vais mettre 33'000 pour avoir environ 30 FPS. Ensuite il y a le callback à appeler et son argument s'il y en a un (ici il y en a un).

int t = timer_setup(TIMER_ANY, 33000, callback, &frame_elapsed);
timer_start(t);

La fonction renvoie un entier qui représente le timer qui t'as été attribué. Cet entier permet de manipuler le timer, ici je m'en sers pour le démarrer immédiatement. Tu ne dois surtout pas perdre l'entier sinon tu perds le contrôle du timer !

Bien sûr une fois que la boucle du jeu s'arrête il faut couper le timer puisqu'il ne se coupe jamais tout seul (il ne renvoie jamais TIMER_STOP). Et donc à la fin on appelle timer_stop().

timer_stop(t);
/* Et là le timer est arrêté et libéré donc tu n'as plus besoin de l'entier t */

Voilà voilà pour une intro rapide aux timers.
Tituya En ligne Rédacteur Points: 959 Défis: 16 Message

Citer : Posté le 02/07/2020 01:11 | #


J'étais en train d'essayer mais visiblement ça ne semble pas marcher ici. J'obtiens une erreur :
incompatible type for argument 3 of 'timer_setup expected 'timer_callback_t' {aka 'union <anonymous>'} but argument is of type 'int (*)(volatile int *)'

Pourtant il ne me semble pas avoir fais d'erreur en prenant exemple sur ce que tu as marqué plus haut, voila mon script :

#include <gint/clock.h>
#include <gint/timer.h>

int callback(volatile int *frame_elapsed)
{
    *frame_elapsed = 1;
    return TIMER_CONTINUE;
}

int main(void)
{
    volatile int frame_elapsed = 1;
    int timer = timer_setup(TIMER_ANY, 100000/FPS, callback, &frame_elapsed);
    timer_start(timer);
while(1)
    {
        while(!frame_elapsed) sleep();
        frame_elapsed = 0;
    }
}
timer_stop(timer);
return 0;


J'ai par ailleurs corrigé pas mal de chose notamment les collisions grâce à KikooDX ainsi que rajouté la mort dans le jeu. J'ai aussi rajouté un vrai niveau mettant bien en profit la physique actuelle. Si tu veux tester le moteur, le gitea est à jour

merci !
Bretagne > Reste du globe
(Et de toute façon, vous pouvez pas dire l'inverse grâce à Bzh)



Lephenixnoir En ligne Administrateur Points: 18145 Défis: 142 Message

Citer : Posté le 02/07/2020 08:54 | #


Ah oui, c'est exact. timer_callback_t est une liste de tous les prototypes autorisés pour le callback et pour une raison obscure j'avais oublié de mettre les pointeurs sur int dans les arguments autorisés. Désolé pour ça !

J'ai poussé un commit sur gint qui les autorise, AST3_C compile maintenant.

Attention, tu as poussé build-cg sur le dépôt ! Supprime-le au plus vite et mets-le entièrement dans ton .gitignore !
Tituya En ligne Rédacteur Points: 959 Défis: 16 Message

Citer : Posté le 02/07/2020 12:31 | #


OK très bien merci ! J'irais voir ça tout à l'heure.

J'ai remarqué que j'avais poussé build-cg. J'ai corrigé ça il y a 2 jours maintenant
Par contre si on regarde les anciens commit, il est présent

Ajouté le 02/07/2020 à 19:00 :
Bon, je sais pas vraiment si c'est comme ça que tu le pensais mais j'ai rajouté une pseudo gravité avec une accélération constante mais n'ayant aucun lien avec nos mesures physiques.
Cependant je n'ai pas utilisé la seconde loi de Newton pour faire ça en fonction du temps. Et à vrai dire je ne définie même pas une unité, mon code ressemble simplement à ça :

#define ACCELERATION 0.4

int main(void)
{
float vspd = 1.0;
    if(!collide_solid(player_x, player_y+(ACCELERATION+vspd), level, gravity))
    {
        vspd+=ACCELERATION;
        player_y+=vspd;
    }
    else if(!collide_solid(player_x, player_y+1, level, gravity))
    {
        vspd = 1;
        player_y+=1;
    }
}


Ça reste en effet plus agréable de jouer comme ça. Mais je doute fortement que c'est ce que tu voulais que je fasse

Au passage, j'ai bien réussi à faire fonctionner le timer
Bretagne > Reste du globe
(Et de toute façon, vous pouvez pas dire l'inverse grâce à Bzh)



Lephenixnoir En ligne Administrateur Points: 18145 Défis: 142 Message

Citer : Posté le 02/07/2020 19:32 | #


Oui voilà, c'est l'idée pour une simulation avec accélération. Ce que je proposais c'était d'introduire un delta temps dans le paquet. Si tu m'excuses les notations un peu plus à la physicienne, ça ressemble à ça :

/* Peu importe la valeur, mais si tes distances correspondent c'est -9.81 */
float y, vy=0, ay=-9.81;


void udpate(float dt)
{
    vy += ay * dt;
    y += vy * dt;

    if(collide_solid(player_x, player_y, level, gravity))
    {
        /* Appliquer une force dans l'autre sens ou annuler le mouvement */
    }
}

L'avantage c'est que si tu modifies le nombre de FPS normal tu peux modifier le dt correspondant et le jeu ira toujours aussi vite. Avec ton exemple si t'augmente les FPS le jeu va plus vite.
Tituya En ligne Rédacteur Points: 959 Défis: 16 Message

Citer : Posté le 02/07/2020 19:46 | #


En effet j'ai remarqué qu'avec un FPS plus élevé le jeu tournait plus vite.

En soit ce n'est pas si dérangeant compte tenu du FPS constant pour la sortie du jeu, je peux très bien continuer à utiliser cette méthode si je définis dès maintenant un FPS qui ne changera plus avec le temps

Mais bon, ça c'est un peu faignant de faire ça comme ça. Je vais me pencher sur ta méthode plus orthodoxe. En attendant j'ai un petit bug à régler à cause de tout ça !
Bretagne > Reste du globe
(Et de toute façon, vous pouvez pas dire l'inverse grâce à Bzh)




LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
Pour coloriser votre code, cliquez ici.
Sinon cliquez sur le bouton ci-dessous.
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2020 | Il y a 38 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd