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;
}
以下是上面代码所使用的素材:
相关文章推荐
- Unity2D - 2. 实现基本的人物移动控制和碰撞检测
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四)实现2D人物动画①
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四)实现2D人物动画①
- unity3d实现一个人物跟随鼠标点击地面那点就移动那点,实现点击特效加人物动画方向的切换。
- 时光煮雨 Unity3D实现2D人物动画② Unity2D 动画系统&资源效率
- 简单的实现人物的移动,跳跃,视角的转动等
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四)实现2D人物动画①
- C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(四)实现2D人物动画①
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(五)实现2D人物动画②
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(五)实现2D人物动画②
- Unity2D - 4. 实现android虚拟摇杆控制人物移动
- Unity3D实现2D人物动画① UGUI&Native2D序列帧动画
- 时光煮雨 Unity3D实现2D人物动画① UGUI&Native2D序列帧动画
- 时光煮雨 Unity3D实现2D人物移动-总结篇
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四)实现2D人物动画①
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(五)实现2D人物动画②
- Android 实现动画的2种方式(动画形式如:上下移动)
- cocos 2d 简单动画实现
- 属性动画实现控件类似贝塞尔曲线轨迹移动效果
- 属性动画实现控件类似贝塞尔曲线轨迹移动效果