[C-Engine] n°4 : Déplacement du personnage
Posté le 01/03/2016 18:44
Bienvenue dans ce pour apprendre à déplacer un personnage et utiliser des scripts. Si vous n'avez pas encore créé de personnage c'est -ici-
Pour commencer, nous allons ajouter beaucoup plus de sprites. Ensuite nous allons mettre en place la gravité, et les collisions avec le décor. Et pour finir nous allons créer un script pour déplacer le personnage avec les flèches de droite, de gauche et de haut.
Etape 1 : Encore plus de sprites.
Pour que le jeu puisse être plus joli, nous allons créer plus d'animation.
Animation de déplacement sur le coté.
Animation de saut.
Nous allons utiliser les images suivantes:
Vous pouvez supprimer les anciennes images. Nous ne les utiliserons plus.
Voici le code correspondant aux images :
const unsigned char Perso_Normal[]={0xff, 0xff, 0xfc, 0x1f, 0xf0, 0x7, 0xe0, 0x7, 0xe0, 0x3, 0xc0, 0x53, 0x80, 0x51, 0x80, 0x51, 0x80, 0x1, 0x80, 0x1, 0xc8, 0x25, 0xf8, 0x7, 0xfc, 0xf, 0xe3, 0xf3, 0xc1, 0xe1, 0xff, 0xff, };
const unsigned char Perso_NormalN[]={0x3, 0xe0, 0xf, 0xf8, 0x1f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x3f, 0xfe, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff, 0x3e, 0x3e, };
const unsigned char Perso_Marche_1[]={0xff, 0xff, 0xf8, 0x3f, 0xe0, 0xf, 0xe0, 0xf, 0xc0, 0x17, 0xc0, 0x17, 0xc2, 0x17, 0xc1, 0x7, 0xc1, 0x7, 0xe2, 0x17, 0xfc, 0x7, 0x90, 0xf, 0x88, 0x1f, 0x8f, 0xe3, 0xff, 0xc3, 0xff, 0xff, };
const unsigned char Perso_Marche_1N[]={0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x3f, 0xf8, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0xff, 0xfc, 0xff, 0xf8, 0xff, 0xfc, 0xff, 0xfe, 0x70, 0x7e, 0x0, 0x3c, };
const unsigned char Perso_Marche_2[]={0xff, 0xff, 0xf8, 0x1f, 0xe0, 0xf, 0xc0, 0xf, 0xc0, 0x57, 0x80, 0x57, 0x80, 0x55, 0x80, 0x5, 0x88, 0x5, 0xc8, 0x25, 0xf8, 0x7, 0xfc, 0xf, 0xf3, 0xff, 0xf8, 0x5f, 0xff, 0xff, 0xff, 0xff, };
const unsigned char Perso_Marche_2N[]={0x7, 0xe0, 0x1f, 0xf0, 0x3f, 0xf8, 0x7f, 0xf8, 0x7f, 0xfc, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x3f, 0xfe, 0x1f, 0xf8, 0x1f, 0xf0, 0xf, 0xf0, 0x7, 0xe0, 0x0, 0x0, };
const unsigned char Perso_Marche_3[]={0xff, 0xff, 0xf8, 0x3f, 0xe0, 0xf, 0xf0, 0xf, 0x80, 0xa5, 0x80, 0xa5, 0x80, 0xa5, 0x80, 0x5, 0xe0, 0x7, 0xe0, 0x47, 0xe0, 0xb, 0xd0, 0xb, 0xcc, 0x33, 0xe3, 0xc7, 0xf1, 0xff, 0xff, 0xff, };
const unsigned char Perso_Marche_3N[]={0x7, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0x38, 0xe, 0x0, };
const unsigned char Perso_Saut[]={0xff, 0xff, 0xfe, 0x1f, 0xc8, 0x5, 0x80, 0x5, 0x80, 0x1, 0x80, 0x3, 0xc0, 0x53, 0xe0, 0x53, 0xe0, 0x53, 0xe6, 0x3, 0xe9, 0x5, 0xf1, 0x29, 0xf0, 0x91, 0xf0, 0xa3, 0xf9, 0xe7, 0xff, 0xff, };
const unsigned char Perso_SautN[]={0x1, 0xe0, 0x37, 0xfa, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe, 0x3f, 0xff, 0x3f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xfe, 0xf, 0xfc, 0x7, 0x38, };
Ensuite nous créons les sprites et les animations.
Sprite S_Perso_Marche_1(Perso_Marche_1 , Perso_Marche_1N , 16 , 16);S_Perso_Marche_1.CreateReverse();
Sprite S_Perso_Marche_2(Perso_Marche_2 , Perso_Marche_2N , 16 , 16);S_Perso_Marche_2.CreateReverse();
Sprite S_Perso_Marche_3(Perso_Marche_3 , Perso_Marche_3N , 16 , 16);S_Perso_Marche_3.CreateReverse();
Sprite S_Perso_Marche[]={ S_Perso_Marche_1 , S_Perso_Marche_2 , S_Perso_Marche_3};
Sprite S_Perso_Normal(Perso_Normal , Perso_NormalN , 16 , 16);S_Perso_Normal.CreateReverse();
Sprite S_Perso_Saut(Perso_Saut , Perso_SautN , 16 , 16);S_Perso_Saut.CreateReverse();
Animation A_Perso_Normal( S_Perso_Normal);
Animation A_Perso_Marche( S_Perso_Marche , 3 , 150 );
Animation A_Perso_Saut( S_Perso_Saut );
Animation A_Perso[]={ A_Perso_Normal , A_Perso_Marche , A_Perso_Saut};
La fonction "ReverseSprite" permet de créer un sprite correspondant à la symétrie du sprite de départ. Cela permet de diviser par 2 le temps de création de sprite.
Ici j'ai doublé le nombre de sprite car cela permet de gérérer le canal Alpha et donc permettre au personnage de ne pas se faire traverser pas le décor.
La méthode consiste à doubler l'image que l'on veut afficher comme ceci pour créer un canal alpha.
Normal :
Alpha :
Le tableau d'animation permet d'attribuer plusieurs animations à un objet.
Etape 2 : Mise en place des collisions et de la gravité.
Notre personnage, pour pouvoir entrer en collision avec le décor doit posséder un corps qui dans le C-Engine se créait avec les lignes suivantes.
Perso->AddRigibody();
Perso->GetRigibody()->SetMass(1);
On ajoute à l'objet le composant Rigibody.
Pour mettre en place la gravité, il suffit de spécifier au C-Engine que le jeu est un jeu de "Plateforme" avec la fonction du "Engine" SetType(int). 0 = Normal 1 = Plateforme ( avec gravité )
Game.SetType(1);
Il y aura peu être dans le futur d'autre type de jeu pré-configuré.
Etape 3 : Création d'un script et premier déplacement
Un script permet lorsqu'il est associé à un objet de lui faire exécuter des actions.
Tous nos scripts seront hérités de la class Script du C-Engine.
L'héritage est une notion avancée du language C++ et vous n'êtes pas obligé de l'apprendre pour l'utiliser.
Donc pour créer un script il faut écrire en dehors de toutes fonctions:
class Control: public Script
{
public:
void Update();
};
Nous venons de créer une class du nom de contrôl qui hérite de la class Script et qui possède comme fonction Update().
Pour lier un script à un objet il suffit de déclarer le Script puis de l'associé avec la fonction "AffectScript" de l'objet.
Control * ScriptPerso = new Control;
Perso->AffectScript(ScriptPerso);
La fonction Update() exécute le code qu'elle contient à chaque frame.
Il existe aussi la fonction Start() qui exécute le code au début du jeu.
Et la fonction UpdateEverySecond() qui est exécutée toutes les secondes.
Ce sera à vous de les utiliser avec précision pour créer un jeu.
Pour créer la fonction Update, il faut écrire en dehors de toutes fonctions:
void Control::Update()
{
}
Pour commencer, créons 2 variables dans la fonction Update() du type bool pour savoir si le personnage est au sol et s'il réalise une action.
bool isground = GetObject()->GetRigibody()->CollisionDecor( GetX() , GetY()-1);
bool isdo = false;
La fonction CollisionDecor renvoie true si l'objet, au positon X Y indiquée, touche un bloc solide.
Ici on vérifie juste en dessous pour savoir s'il touche le sol.
Isdo est initialisé à false car le joueur n'a encore rien fait.
Passons maintenant au déplacement.
if(input_press(K_RIGHT))
{
Move(1,0);
SetIt(1);
GetObject()->GetRender()->ReverseRender(false);
isdo = true;
}
else if(input_press(K_LEFT))
{
Move(-1,0);
SetIt(1);
GetObject()->GetRender()->ReverseRender(true);
isdo = true;
}
Pour vérifier les touches j'utilise la librairie de NineStars. input_press(K_RIGHT) est vraie lorsque le joueur appuie sur la touche Droite de la .
Move déplace l'objet de x et y pixel s'il ne rencontre pas d'obstacle.
ReverseRender( bool v) permet au C-Engine de savoir si il doit afficher le sprite ou son miroir.
False = le sprite
True = le miroir du sprite.
Et isdo = true car on réalise une action.
SetIt(int v ) permet de demander à l'objet d'afficher l'animation "v" du tableau d'animation A_Perso.
Ajouté ensuite ce code:
if(isdo == false)
{
SetIt(0);
}
GetEngine()->MiddleScreen(GetX() + 8 , GetY() + 8 );
Si le personnage ne fait rien alors on affiche l'animation de base.
MiddleScreen place la caméra qui filme la scène au centre du point donné, ici les coordonnées du personnage donné par GetX() et GetY() plus 8 pour la taille du personnage qui fait 16*16.
Vous pouvez compiler, le personnage peu se déplacer dans les 2 directions avec la caméra centrée sur lui.
Etape 4 : Le saut.
Cependant il manque le saut.
Pour cela, il suffit de remplacer:
if(isdo == false)
{
SetIt(0);
}
par
if(isground == true)
{
if(input_trigger(K_UP))
{
GetObject()->GetRigibody()->GetBody()->velocity.y = 25;
}
if(isdo == false)
{
SetIt(0);
}
}
else
{
SetIt(2);
}
Si le personnage touche le sol alors il peut sauter en appuyant sur "Up"
S'il saute alors on modifie sa vitesse en ordonnés à 25.
Sinon le personnage ne fait rien alors on affiche l'animation de base.
Et s'il ne touche pas le sol alors on affiche la 3 ème animation du tableau qui est le saut.
Dernière compilation et .... sa marche le personnage peut sauter.
Voici le code final que vous devriez avoir.
Voici le code final que vous devriez avoir.
class Control: public Script
{
public:
void Update();
};
void Control::Update()
{
bool isground = GetObject()[b]->[/b]GetRigibody()[b]->[/b]CollisionDecor( GetX() , GetY()-1);
bool isdo = false;
[b][blue]if[/blue][/b](input_press(K_RIGHT))
{
Move(1,[maroon]0[/maroon]);
SetIt(1);
GetObject()[b]->[/b]GetRender()[b]->[/b]ReverseRender(false);
isdo = true;
}
[b][blue]else[/blue][/b] if(input_press(K_LEFT))
{
Move(-1,[maroon]0[/maroon]);
SetIt(1);
GetObject()[b]->[/b]GetRender()[b]->[/b]ReverseRender(true);
isdo = true;
}
[b][blue]if[/blue][/b](isground == true)
{
[b][blue]if[/blue][/b](input_trigger(K_UP))
{
GetObject()[b]->[/b]GetRigibody()[b]->[/b]GetBody()->velocity.y = [maroon]25[/maroon];
}
[b][blue]if[/blue][/b](isdo == false)
{
SetIt(0);
}
}
[b][blue]else[/blue][/b]
{
SetIt(2);
}
GetEngine()[b]->[/b]MiddleScreen(GetX() + 8 , GetY() + 8 );
}
Merci d'avoir lu ce , et à la prochaine pour apprendre à éditer des maps.
Fichier joint
Citer : Posté le 01/03/2016 20:42 | #
Modifier la masse de l'objet modifie quoi physiquement ? Je suis curieux, c'est au niveau de l'inertie des objets lors des collisions ?
Citer : Posté le 02/03/2016 07:02 | #
C est surtout sur la gravité que sa agit.
a = Sommeforce / mass.
- Kirby's DreamLand : Gobe , Gobe , Gobe !!!
- L'invasion Seanchans : Détruit la flotte ennemis a bord du "Danseur des vagues".
Citer : Posté le 02/03/2016 13:47 | #
Tu sais que la masse n'intervient jamais dans l'accélération ?
Citer : Posté le 02/03/2016 14:15 | #
https://fr.wikipedia.org/wiki/Lois_du_mouvement_de_Newton
- Kirby's DreamLand : Gobe , Gobe , Gobe !!!
- L'invasion Seanchans : Détruit la flotte ennemis a bord du "Danseur des vagues".
Citer : Posté le 02/03/2016 14:22 | #
@Dark' : À force appliquée égale, deux objets de masse d'inertie différente n'auront à priori pas la même accélération...
(Après dans le cas de l'accélération gravitationnelle effectivement la masse va classiquement se simplifier donc elle ne rentre pas en compte pour cette accélération là, c'est ce que tu voulais dire je pense. )
Citer : Posté le 02/03/2016 14:34 | #
Disons que dans le cas d'autres forces que la gravité, ça rentre dans le cas de mon premier message
Ajouté le 02/03/2016 à 14:34 :
Mais oui j'ai pas été très précis
Citer : Posté le 30/03/2016 17:27 | # | Fichier joint
Voici le projet que vous devriez avoir.
- Kirby's DreamLand : Gobe , Gobe , Gobe !!!
- L'invasion Seanchans : Détruit la flotte ennemis a bord du "Danseur des vagues".
Citer : Posté le 13/04/2016 18:54 | # | Fichier joint
quelle est l'erreur?
Citer : Posté le 16/04/2016 21:48 | #
L'indentation ?
Citer : Posté le 18/04/2016 19:40 | #
Lors de la compilation le sdk me sort " C5265 (E) Member "Rigibody::R_body" is inaccessible" sur cette ligne :
Pourtant j'ai regardé dans Rigibody.cpp il y a bien
-Mon Fall Down
-Mon jeu de mains
-Mon starwars
-Mon dessinatout
-Mon niaiseux version 2.0
-Mon niaiseux version 3.0
-Inferno
-Mon super labyrinthe (en cours)
-Mon call of duty en 3D
-Casion (avec Az)
Citer : Posté le 18/04/2016 19:57 | #
Il faut écrire GetBody()->velocity.y
- Kirby's DreamLand : Gobe , Gobe , Gobe !!!
- L'invasion Seanchans : Détruit la flotte ennemis a bord du "Danseur des vagues".
Citer : Posté le 18/04/2016 19:59 | #
En effet merci ca marche du coup tu modifies le tuto ?
-Mon Fall Down
-Mon jeu de mains
-Mon starwars
-Mon dessinatout
-Mon niaiseux version 2.0
-Mon niaiseux version 3.0
-Inferno
-Mon super labyrinthe (en cours)
-Mon call of duty en 3D
-Casion (avec Az)
Citer : Posté le 18/04/2016 20:01 | #
Oui c'est fait j'avais oublié de mettre à jour la ligne, sinon il y a la doc avec toute les fonctions du C-Engine.
- Kirby's DreamLand : Gobe , Gobe , Gobe !!!
- L'invasion Seanchans : Détruit la flotte ennemis a bord du "Danseur des vagues".
Citer : Posté le 20/04/2016 15:05 | #
La j'ai un vrai problème :/ en gros je veux que mon perso se déplace tout seul vers la droite ( ca c'est bon) il se déplace bien par rapport à la map seuleument j'ai un problème :
Impossible de le faire sauter ! de même, il n'est pas affecté par la gravité :/
Tant que j'y suis j'aimerais faire ca mais je n'y suis pas arrivé :
-Arriver à faire sauter le personnage afin qu'il puisse sortir de l'écran (la fonction move(1,0) ne permet pas le déplacement lorsque le perso est en dehors de l'écran (ou bien de la map ?)
Voila si tu peux m'aider
class Control: public Script
{
public:
void Update();
};
void Control::Update()
{
bool isground = GetObject()->GetRigibody()->CollisionDecor( GetX() , GetY()-1);
bool isdo = false;
Move(1,0);
SetIt(0);
if(input_trigger(K_UP)){
GetObject()->GetRigibody()->GetBody()->velocity.y = 25;
isdo=true;
}
if(isdo == false){
SetIt(0);
}
else{
SetIt(1);
}
GetEngine()->MiddleScreen(GetX() + 8 , 32, false);
}
int Jeu(){
const unsigned char Perso_tombe[]={0x1, 0xe0, 0x36, 0x1a, 0x48, 0x5, 0x80, 0x5, 0x80, 0x1, 0x80, 0x3, 0x40, 0x52, 0x60, 0x52, 0x20, 0x52, 0x26, 0x3, 0x29, 0x5, 0x11, 0x29, 0x10, 0x91, 0x10, 0xa2, 0x9, 0xe4, 0x7, 0x38, };
const unsigned char Perso_saut[]={0x7, 0xe0, 0x18, 0x10, 0x20, 0x8, 0x40, 0x8, 0x40, 0x54, 0x80, 0x56, 0x80, 0x55, 0x80, 0x5, 0x88, 0x5, 0x48, 0x25, 0x38, 0x6, 0x1c, 0x8, 0x13, 0xf0, 0x8, 0x50, 0x7, 0xe0, 0x0, 0x0, };
Sprite S_Perso_1( Perso_saut , 16 , 16 );
Sprite S_Perso_2( Perso_tombe , 16 , 16 );
Sprite S_Perso[]={ S_Perso_1 , S_Perso_2 };
Animation A_Perso( S_Perso , 2 , 200 );
Object * Perso = new Object;
Perso->AddRigibody();
Perso->GetRigibody()->SetMass(0);
Perso->GetTransforms()->SetXY( 8 , 41 );
Perso->GetRender()->SetRender( A_Perso );
Control * ScriptPerso = new Control;
Perso->AffectScript(ScriptPerso);
//*************Map*************\\
const unsigned char tileset[]={0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0xff, 0xff, 0x0, 0x3f, 0xaa, 0xbf, 0x55, 0x7f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x81, 0x7f, 0x81, 0x7f, 0xff, 0xff, 0x88, 0x7f, 0x88, 0x7f, 0xff, 0xff, 0x81, 0x7f, 0x81, 0x7f, 0xff, 0xff, 0x7f, 0xbf, 0x80, 0x7f, 0x8c, 0x7f, 0x92, 0x7f, 0x82, 0x7f, 0x8c, 0x7f, 0x80, 0x7f, 0x88, 0x7f, 0x80, 0x7f, 0x7f, 0xbf};
bool tileprop[]= { false , true , true, true , true};
const unsigned char * map1[]={
"00000000000030000000",
"00000000000000000000",
"00300232020020020000",
"00000000000000000000",
"00000000000000000000",
"11111111111111111111",
};
Map Niveau;
Niveau.SetMap(tileset , map1 , tileprop , 10 , 10 , 20 ,6);
//*************Moteur*************\\
Engine Game;
Game.SetType(1);
Game.AddObject( Perso);
Game.AffectMap( &Niveau);
Niveau.AffectEngine( &Game);
Game.Game();
return 1;
}
extern "C"
{
int AddIn_main(int isAppli, unsigned short OptionNum){
Jeu();
return 1;
}
#pragma section _BR_Size
unsigned long BR_Size;
#pragma section
#pragma section _TOP
int InitializeSystem(int isAppli, unsigned short OptionNum){
return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
}
#pragma section
}
-Mon Fall Down
-Mon jeu de mains
-Mon starwars
-Mon dessinatout
-Mon niaiseux version 2.0
-Mon niaiseux version 3.0
-Inferno
-Mon super labyrinthe (en cours)
-Mon call of duty en 3D
-Casion (avec Az)
Citer : Posté le 20/04/2016 15:07 | #
SetMass doit être mis à 1.
Pour le déplacer en dehors de la map, tu peu utiliser SetXY(GetX() + 1, GetY());
Il y a aussi une variable dans la fenêtre à modifier.
MiddleScreen(GetX(),GetY(),false);
- Kirby's DreamLand : Gobe , Gobe , Gobe !!!
- L'invasion Seanchans : Détruit la flotte ennemis a bord du "Danseur des vagues".
Citer : Posté le 20/04/2016 15:10 | #
Merci
Seuleument mon bonhomme ne saute toujours pas x) (par contre il tombe )
-Mon Fall Down
-Mon jeu de mains
-Mon starwars
-Mon dessinatout
-Mon niaiseux version 2.0
-Mon niaiseux version 3.0
-Inferno
-Mon super labyrinthe (en cours)
-Mon call of duty en 3D
-Casion (avec Az)
Citer : Posté le 20/04/2016 18:09 | #
Ton script est mauvais il manque la condition qui vérifie que le joueur est bien au sol.
Regarde dans le spoiler en fin du tuto pour voir le code final que tu devrais avoir.
Peux tu me passer en .zip ton dossier qui contient ton projet ?
- Kirby's DreamLand : Gobe , Gobe , Gobe !!!
- L'invasion Seanchans : Détruit la flotte ennemis a bord du "Danseur des vagues".
Citer : Posté le 21/04/2016 17:24 | # | Fichier joint
@fife no ca c'est normal je veux faire un jeu du genre flappy bird donc je n'ai pas besoin que le perso soit au sol pour qu'il saute
voila je fichier joint
Ajouté le 08/05/2016 à 11:55 :
Petit up
-Mon Fall Down
-Mon jeu de mains
-Mon starwars
-Mon dessinatout
-Mon niaiseux version 2.0
-Mon niaiseux version 3.0
-Inferno
-Mon super labyrinthe (en cours)
-Mon call of duty en 3D
-Casion (avec Az)
Citer : Posté le 08/05/2016 12:12 | #
Essaye avec ça:
void Control::Update()
{
Move(1,0);
if(input_trigger(K_UP))GetObject()->GetRigibody()->GetBody()->velocity.y = 30;
GetEngine()->MiddleScreen(GetX() + 8 , 32, false);
}
Le code est entièrement épuré des choses inutiles.
- Kirby's DreamLand : Gobe , Gobe , Gobe !!!
- L'invasion Seanchans : Détruit la flotte ennemis a bord du "Danseur des vagues".
Citer : Posté le 08/05/2016 13:57 | #
Waow merci mec ca marche impec
-Mon Fall Down
-Mon jeu de mains
-Mon starwars
-Mon dessinatout
-Mon niaiseux version 2.0
-Mon niaiseux version 3.0
-Inferno
-Mon super labyrinthe (en cours)
-Mon call of duty en 3D
-Casion (avec Az)