您的位置:首页 > 运维架构

openGL实现的2D人物移动、跳跃和攻击动画

2010-08-05 00:03 591 查看

openGL实现的2D人物移动、跳跃和攻击动画

键盘W, J键控制人物跳跃, A键往左走,D键往右走,空格键攻击,S键原地不动

如果用vector和sort()来管理每个源图片的ID,即可实现各个图片来回调用、切换的功能;在当前基础上,加进更多的逻辑判断,就能完成一个类似街机上超级玛丽类型的游戏。

以下是代码:

/******************************************/

/* INFR 2310 - Assignment 1

* Sprite Animation

*

* Part 1: Sprite Sheet Animation

* Part 2: Sprite Movement

* Part 3: Scrollers

*

* Author: Andrew Hogue

* Date: September, 2008

* Modified By: Sun, Jian/100285100

*

* Modification Description:Add a main character, background and foreground.

* 'w'and 'j' could make the character jump; 'a' could make the character walk left, and 'd' could make the character walk right

* 'space' could make the character attack; 's' could make the character stand

*

*/

#include <windows.h>

#include <stdio.h>

#include <stdlib.h>

#include <vector>

#include <algorithm>

#include <iostream>

#include <GL/gl.h>

#include <GL/glu.h>

#include "GL/glut.h"

#include "IL/il.h"

#include "IL/ilu.h"

#include "IL/ilut.h"

/******************************************/

/* GLOBAL VARIABLES */

/******************************************/

#define WINDOW_WIDTH 800

#define WINDOW_HEIGHT 432

/* anim types */

enum {ANIM_ACTION=0, ANIM_JUMP,ANIM_WALK_LEFT,ANIM_WALK_RIGHT,ANIM_IDLE}; //I change the original enum

/*********************************/

/* GLOBAL SPRITE INFO */

/*********************************/

#define FRAMES_PER_SECOND_SPRITE 10

const int FRAME_DELAY_SPRITE=1000/FRAMES_PER_SECOND_SPRITE;

char *spriteSheetName = "images/bleach_assignment1.gif";

char *spriteBackgroundName = "images/newbackground.gif";

char *spriteForegroundName = "images/newforeground.gif";

/* no animation can have more than 100 frames */

#define MAX_ANIM 100

typedef struct _UVcoords_t

{

// a single (u,v) texture coordinate

float u,v;

int currentFrames;

}UVcoords_t;

typedef struct _spriteSheet_t

{

int width,height;

unsigned int texId;

}spriteSheet_t;

typedef struct _spriteInfo_t

{

/* position info */

float x,y;

/* height of sprite in pixels on screen*/

float width,height;

// normalized width/height of sprite for texture

float texWidth,texHeight;

UVcoords_t anim[5]; //because I only have 5 anim in this assignment

int currentAnimState;

// the sprite comes from a sprite sheet

spriteSheet_t sheet;

}spriteInfo_t;

static spriteInfo_t the_sprite;

static spriteInfo_t background,foreground;

/*********************************/

/* function drawSprite()

* Description:

* - this function draws a 2D sprite at its internally defined location

*/

void drawSprite(spriteInfo_t *s)

{

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

glPushMatrix();

glTranslatef(s->x,s->y,0);

/* you will need to change this */

if (the_sprite.currentAnimState == ANIM_WALK_LEFT) //if the state is walk left

{

if(the_sprite.x<=400&&the_sprite.x>=10) //to make sure the main character will not out of the screen

the_sprite.x--;

background.anim[0].u -= 0.0005; //foreground move more fast than background

foreground.anim[0].u -= 0.002;

}

if (the_sprite.currentAnimState == ANIM_WALK_RIGHT)

{

if(the_sprite.x<400)

the_sprite.x++;

background.anim[0].u += 0.0005;

foreground.anim[0].u += 0.002;

}

int currentAnim = s->currentAnimState;

int currentFrame = s->anim[currentAnim].currentFrames;

UVcoords_t* UV = s->anim;

float u = UV->u+s->texWidth*currentFrame; //change the frame of different anim

float v = UV->v+s->texHeight*currentAnim;

glColor3f(1,1,1);

/* bind the appropriate texture frame */

glBindTexture(GL_TEXTURE_2D,s->sheet.texId);

/* draw the image as a quad the size of the first loaded image */

glBegin(GL_QUADS);

glTexCoord2f(u,v);

glVertex3f(0,0,0);

glTexCoord2f(u,v+s->texHeight);

glVertex3f(0,s->height,0);

glTexCoord2f(u+s->texWidth,v+s->texHeight);

glVertex3f(s->width,s->height,0);

glTexCoord2f(u+s->texWidth,v);

glVertex3f(s->width,0,0);

glEnd();

glPopMatrix();

glDisable(GL_BLEND);

if (the_sprite.currentAnimState == ANIM_JUMP&¤tFrame == 7)

the_sprite.currentAnimState = ANIM_IDLE; //this means the character can only jump once when 'j' or 'w' is pressed

if (the_sprite.currentAnimState == ANIM_ACTION&¤tFrame == 7)

the_sprite.currentAnimState = ANIM_IDLE; //this means the character can only attack once when 'space' is pressed

}

/* function DisplayCallbackFunction(void)

* Description:

* - this is the openGL display routine

* - this draws the sprites appropriately

*/

void DisplayCallbackFunction(void)

{

/* clear the screen */

glClearColor(0,0.5,0,0);

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

/* enable texturing */

glEnable(GL_TEXTURE_2D);

drawSprite(&background); //draw background first, and then the foreground, and finally the character

drawSprite(&foreground);

drawSprite(&the_sprite);

/* display the drawn frame */

glutSwapBuffers();

}

/* function void KeyboardCallbackFunction(unsigned char, int,int)

* Description:

* - this handles keyboard input when a button is pressed

*/

void KeyboardCallbackFunction(unsigned char key, int x, int y)

{

std::cout << "Keycode:"<<(int)key<<std::endl;

switch(key)

{

case 32: // the space bar

the_sprite.currentAnimState = ANIM_ACTION;

break;

case 27: // the escape key

case 'q':

case 'Q':

exit(1);

break;

}

}

/* function void KeyboardUpCallbackFunction(unsigned char, int,int)

* Description:

* - this handles keyboard input when a button is lifted

*/

void KeyboardUpCallbackFunction(unsigned char key, int x, int y)

{

switch(key)

{

case 'w':

case 'W':

case 'j':

case 'J':

the_sprite.currentAnimState = ANIM_JUMP;

break;

case 'a':

case 'A':

the_sprite.currentAnimState = ANIM_WALK_LEFT;

break;

case 's':

case 'S':

the_sprite.currentAnimState = ANIM_IDLE; //I change the 's' to the state of idle

break;

case 'd':

case 'D':

the_sprite.currentAnimState = ANIM_WALK_RIGHT;

break;

}

}

/* function resetSprite()

* Description:

* - reset's the sprite position

*/

void resetSprite()

{

the_sprite.x = 90; //set the initial position of character

the_sprite.y = 60;

background.x = 0;

foreground.x = 0;

}

/* function UpdateSpriteAnimation()

* Description:

* - routine for moving sprite and updating animations

*/

void UpdateSpriteAnimation()

{

int currentAnim = the_sprite.currentAnimState;

the_sprite.anim[currentAnim].currentFrames = (the_sprite.anim[currentAnim].currentFrames++)%8;

}

/* function initSprite()

* Description:

* - this initializes a sprite to default values

*/

void initSprite(spriteInfo_t *s, int w, int h, char *name)

{

s->width = w;

s->height = h;

s->sheet.texId = ilutGLLoadImage(name);

s->sheet.height = ilGetInteger(IL_IMAGE_HEIGHT);

s->sheet.width = ilGetInteger(IL_IMAGE_WIDTH);

s->texHeight = s->height/(float)s->sheet.height;

s->texWidth = s->width/(float)s->sheet.width;

s->currentAnimState = ANIM_IDLE; //initializes the character's initial state

}

/* function loadSprite()

* - this loads the character sprite

*/

void loadSprite()

{

initSprite(&the_sprite, 193,193, spriteSheetName);

initSprite(&background, 1280,432,spriteBackgroundName);

initSprite(&foreground, 1014,432,spriteForegroundName);

/* set up the initial position */

resetSprite();

}

/* function initImageLibrary()

* Description:

* - initialize the DevIL library properly

*/

void initImageLibrary()

{

glEnable(GL_TEXTURE_2D);

ilInit();

iluInit();

ilutRenderer(ILUT_OPENGL);

loadSprite();

}

/* function TimerCallbackFunction(int value)

* Description:

* - this is called many times per second

* - this enables you to animate things

* - no drawing, just changing the state

* - changes the frame number and calls for a redisplay

* - FRAME_DELAY_SPRITE is the number of milliseconds to wait before calling the timer again

*/

void TimerCallbackFunction(int value)

{

UpdateSpriteAnimation();

glutPostRedisplay();

glutTimerFunc(FRAME_DELAY_SPRITE,TimerCallbackFunction,0);

}

/* function WindowReshapeCallbackFunction()

* Description:

* - this is called whenever the window is resized

* - and sets up the projection matrix properly

* - currently set up for an orthographic view (2D only)

*/

void WindowReshapeCallbackFunction(int w,int h)

{

float asp = (float)w/(float)h;

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0,w,0,h);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

/* function main()

* Description:

* - this is the main function

* - does initialization and then calls glutMainLoop() to start the event handler

*/

int main(int argc, char **argv)

{

/* initialize the window and OpenGL properly */

glutInit(&argc,argv);

glutInitWindowSize(WINDOW_WIDTH,WINDOW_HEIGHT);

glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE);

glutCreateWindow("Sprite Anim, Modified By: Sun, Jian/100285100");//also add myself information
on the screen

/* set up our function callbacks */

glutDisplayFunc(DisplayCallbackFunction);

glutKeyboardFunc(KeyboardCallbackFunction);

glutKeyboardUpFunc(KeyboardUpCallbackFunction);

glutReshapeFunc(WindowReshapeCallbackFunction);

glutTimerFunc(1,TimerCallbackFunction,0);

/* enable texturing */

glEnable(GL_TEXTURE_2D);

/* initialize the image library engine */

initImageLibrary();

/* start the event handler */

glutMainLoop();

return 0;

}

以下是上面代码所使用的素材:





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐