Je rencontre des problèmes pour implémenter l'animation de sprite dans openGL ES. Je l'ai googlé et la seule chose que je reçois est le tutoriel implémentant via Canvas.
Je connais le chemin mais j'ai du mal à le mettre en œuvre.
Ce dont j'ai besoin: une animation de sprite sur la détection de collision.
Ce que j'ai fait: la fonction de détection de collision fonctionne correctement.
PS: Tout fonctionne bien mais je veux implémenter l'animation dans OPENGL UNIQUEMENT. La toile ne fonctionnera pas dans mon cas.
------------------------ ÉDITER-----------------------
J'ai maintenant une feuille de sprite, disons celle ci-dessous ayant certaines coordonnées, mais d'où commenceront les coordonnées (u, v)? Dois-je considérer mes coordonnées u, v de (0,0) ou de (0,5) et dans quel motif dois-je les stocker dans ma liste ..? ----> De gauche à droite OU ----> de haut en bas
Dois-je avoir un tableau 2D dans ma classe de sprites? voici l'image pour une meilleure compréhension.
Je suppose que j'ai une feuille de sprite NxN, où N = 3,4,5,6, .... et ainsi de suite.
.
.
class FragileSquare{
FloatBuffer fVertexBuffer, mTextureBuffer;
ByteBuffer mColorBuff;
ByteBuffer mIndexBuff;
int[] textures = new int[1];
public boolean beingHitFromBall = false;
int numberSprites = 49;
int columnInt = 7; //number of columns as int
float columnFloat = 7.0f; //number of columns as float
float rowFloat = 7.0f;
public FragileSquare() {
// TODO Auto-generated constructor stub
float vertices [] = {-1.0f,1.0f, //byte index 0
1.0f, 1.0f, //byte index 1
//byte index 2
-1.0f, -1.0f,
1.0f,-1.0f}; //byte index 3
float textureCoord[] = {
0.0f,0.0f,
0.142f,0.0f,
0.0f,0.142f,
0.142f,0.142f
};
byte indices[] = {0, 1, 2,
1, 2, 3 };
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4*2 * 4); // 4 vertices, 2 co-ordinates(x,y) 4 for converting in float
byteBuffer.order(ByteOrder.nativeOrder());
fVertexBuffer = byteBuffer.asFloatBuffer();
fVertexBuffer.put(vertices);
fVertexBuffer.position(0);
ByteBuffer byteBuffer2 = ByteBuffer.allocateDirect(textureCoord.length * 4);
byteBuffer2.order(ByteOrder.nativeOrder());
mTextureBuffer = byteBuffer2.asFloatBuffer();
mTextureBuffer.put(textureCoord);
mTextureBuffer.position(0);
}
public void draw(GL10 gl){
gl.glFrontFace(GL11.GL_CW);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(1,GL10.GL_FLOAT, 0, fVertexBuffer);
gl.glEnable(GL10.GL_TEXTURE_2D);
int idx = (int) ((System.currentTimeMillis()%(200*4))/200);
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glTranslatef((idx%columnInt)/columnFloat, (idx/columnInt)/rowFloat, 0);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); //4
gl.glTexCoordPointer(2, GL10.GL_FLOAT,0, mTextureBuffer); //5
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); //7
gl.glFrontFace(GL11.GL_CCW);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glLoadIdentity();
gl.glMatrixMode(GL10.GL_MODELVIEW);
}
public void loadFragileTexture(GL10 gl, Context context, int resource)
{
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resource);
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
}
Réponses:
Il s'agit d'un extrait de code que j'utilise dans mon application Android.
L'astuce consiste à utiliser glMatrixMode suivi de glTranslatef. Cela vous permettra de traduire l'espace uv.
les coordonnées uv vont de (0,0) à (1,1)
Supposons que vous ayez une texture carrée avec 4 images et que vous souhaitiez texturer un quad. Je vais utiliser les coordonnées suivantes pour définir des cadres dans l'espace uv (le choix vous appartient)
1er (0, 0) (0,5, 0,5)
2e (0,5, 0) (1, 0,5)
3e (0, 0,5) (0,5, 1)
4e (0,5, 0,5) (1, 1)
Avec glTexCoordPointer, vous devez mapper la 1ère image sur votre quad puis lorsque vous souhaitez afficher la 2ème image que vous appelez glTranslatef (0,5, 0, 0), glTranslatef (0, 0,5, 0) pour la 3ème et glTranslatef (0,5, 0,5, 0 ) pour le 4.
Le code ci-dessus est testé et fonctionne très bien, j'espère que l'exemple est assez clair.
ÉDITER:
à la fin de votre fonction de dessin, vous devez réinitialiser votre matrice de texture avec ce code.
ok, prenons 5 lignes et 4 colonnes comme exemple. Il y a au maximum 20 sprites dans votre spriteet, utilisez donc int idx = (int) ((System.currentTimeMillis ()% 200 * number_of_sprites))) / 200);
idx passe maintenant de 0 à number_of_sprites-1 (peut être <20 si vous avez par exemple 5 lignes, 4 colonnes mais seulement 18 sprite) en changeant sa valeur toutes les 200 ms. En supposant que vous avez votre sprite de gauche à droite et de haut en bas, vous pouvez trouver vos coordonnées de cadre dans l'espace uv en faisant cela.
quand vous faites idx% c vous trouvez votre index de colonne, le résultat est toujours entre 0 et c-1
idx% c est un entier, vous devez le mettre à l'échelle à une valeur comprise entre 0,0 et 1,0 pour que vous divisiez par cf, cf est un flottant donc il y a un transtypage implicite ici
idx / c est la même chose mais pour les lignes, idx et c sont tous les deux des nombres entiers donc le résultat est toujours entier, et c'est l'index des lignes, en divisant par rf vous obtenez une valeur entre 0.0 et 1.0
la source
int oldIdx;
avant celapublic FragileSquare()
dans la méthode draw, procédez comme suit:int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx;
À propos, je pense que nous allons OT, la question d'origine a été répondue, vous devriez peut-être fermer celle-ci et en ouvrir une nouvelle si nécessaire.Ma suggestion: créer une texture contenant toutes vos images de votre animation (côte à côte). Modifiez les coordonnées de la texture en fonction du cadre que vous souhaitez afficher.
la source
Vous devez utiliser quelque chose appelé une feuille de sprites .
Une feuille de sprites est juste une image unique avec tous les différents "cadres" qui montrent les poses que le personnage peut prendre. Vous sélectionnez le "cadre" de la feuille de sprite à afficher en fonction du temps (comme pour une animation d'explosion) ou de l'entrée du joueur (comme face à gauche, à droite ou dessiner un pistolet)
La façon la plus simple de faire quelque chose comme ça est d'avoir tous les sprites associés de la même taille (même largeur et hauteur), et donc obtenir la coordonnée (u) du 4ème sprite à partir de la gauche est juste
(sprite_width*4.0 / sprite_sheet_width)
.Si vous essayez d'optimiser et d'être économe en espace, vous pouvez utiliser un outil comme TexturePacker pour emballer vos sprites sur une seule feuille. TexturePacker émet également des données json ou xml qui décrivent les emplacements xy de chacun des sprites dans lesquels vous chargez.
la source
Sprite
classe. À l'intérieur duSprite
parc de classe, une liste de paires (u, v) qui décrivent les coordonnées (u, v) de chaque "encore" dans la texture. Vous avez besoin de 2 variables supplémentaires pour suivre le temps: un flottant pour stocker "secondes par image" (# secondes à consacrer à chaque image d'animation), et un autre flottant appelé "horloge", qui stocke "l'heure actuelle" dans le cycle d'animation. Lorsque vous allez dessiner, vous devez mettre à jour l'heure actuelle. Lorsque "secondes par image" est dépassé, vous passez à l'image suivante de l'animation, de sorte que l'animation continue.Vous pouvez utiliser I_COLLIDE avec OpenGL.
Faites de chaque entité du monde une boîte, puis vérifiez si chacun des axes de la boîte entre en collision avec d'autres entités.
Avec de grandes quantités d'entités pour tester les collisions, vous voudrez peut-être vérifier dans un octree. Vous diviseriez simplement le monde en secteurs, puis vous ne vérifieriez que les collisions entre les objets des mêmes secteurs.
Utilisez également le moteur dynamique Bullet qui est un moteur open source de détection de collision et de physique.
la source