The Game Engine  1
Animation.cpp
Go to the documentation of this file.
1 #include <string>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <SDL/SDL.h>
5 #include <SDL/SDL_image.h>
6 #include <vector>
7 #include <fstream>
8 #include <sstream>
9 #include <iostream>
10 #include "Game.h"
11 #include "Animation.h"
12 #include "fns.h"
13 #include <GL/gl.h>
14 #include <yaml-cpp/yaml.h>
15 using namespace std;
16 
17 Animation::Animation():Name(),Built(false)
18 {}
19 
20 Animation::Animation(string animFile):Name(animFile),Built(false)
21 {
22  loadAnimation(animFile);
23  Built = true;
24 }
25 
26 Animation::Animation(string animFile, string name):Name(name),Built(false)
27 {
28  loadAnimation(animFile);
29  Built = true;
30 }
31 
33  for(unsigned int i=0; i< NumFrames; ++i){
34  SpriteFrame* frame = Frames[i];
35 
36  //remove the frame's image
37  Game::game()->removeTexture(&frame->tex);
38 
39  //remove collision data
40  for(unsigned int j=0, end = frame->collisionData.size(); j < end; ++j)
41  delete (frame->collisionData[j]);
43 
44  //remove frame
45  delete frame;
46  }
47 }
48 
49 bool Animation::loadAnimation(string animFile)
50 {
51  //variables
52  string buffer,file, filename;
53  Uint8 transparency[3];
54  unsigned int pause;
55  animFile="ArtAssets/Sprites/"+animFile;
56 
57  //file
58  ifstream fin(animFile.c_str());
59 
60  if(!fin)
61  {
62  printf("Error opening %s\n\n",animFile.c_str());
63  return Built;
64  }
65 
66  try{
67  YAML::Parser parser(fin);
68 
69  YAML::Node doc;
70  while(parser.GetNextDocument(doc)) {
71  NumFrames = doc.size();
72  Frames = vector<SpriteFrame*>();
73  Built = true;
74  //read out frames
75  for(unsigned int i=0, count = doc.size(); i<count; i++) {
76  SpriteFrame* frame = new SpriteFrame();
77 
79  file=doc[i]["file"].to<string>();
80  filename = "Textures/"+file;
81 
83  pause=doc[i]["pause"].to<unsigned int>();
84 
86  transparency[0]=doc[i]["transparency"]["r"].to<unsigned int>();
87  transparency[1]=doc[i]["transparency"]["g"].to<unsigned int>();
88  transparency[2]=doc[i]["transparency"]["b"].to<unsigned int>();
89 
91  double x=doc[i]["offset"]["x"].to<double>();
92  double y=doc[i]["offset"]["y"].to<double>();
94  for(unsigned int j=0; j<doc[i]["collision"].size();j++) {
95  if(doc[i]["collision"][j]["type"].to<string>()=="circle") {
96  double xOffset = doc[i]["collision"][j]["offset"]["x"].to<double>();
97  double yOffset = doc[i]["collision"][j]["offset"]["y"].to<double>();
98  double radius = doc[i]["collision"][j]["radius"].to<double>();
99  string name = doc[i]["collision"][j]["name"].to<string>();
100  frame->collisionData.push_back(new CollisionCircle(name, Point2D(xOffset, yOffset), radius));
101  }
102  else if(doc[i]["collision"][j]["type"].to<string>()=="rectangle") {
103  double xOffset = doc[i]["collision"][j]["offset"]["x"].to<double>();
104  double yOffset = doc[i]["collision"][j]["offset"]["y"].to<double>();
105  double width = doc[i]["collision"][j]["width"].to<double>();
106  double height = doc[i]["collision"][j]["height"].to<double>();
107  string name = doc[i]["collision"][j]["name"].to<string>();
108  frame->collisionData.push_back(new CollisionRectangle(name, Point2D(xOffset, yOffset), width, height));
109  }
110  }
112  SDL_Surface *temp=NULL;
113  if((temp = LoadImage(filename)) == NULL) return false;//Load image for Frame
114 
116  SDL_SetColorKey(temp, SDL_SRCCOLORKEY, SDL_MapRGB(temp->format, transparency[0], transparency[1], transparency[2]));
117 
119  SDL_Surface* surface = SDL_DisplayFormatAlpha(temp);
120  SDL_FreeSurface(temp);
121  frame->width=surface->w;
122  frame->height=surface->h;
123 
124  //make sure it loaded
125  if(surface->w <= 0 || surface->h <= 0 ){
126  cout<<"Error, "+file+" loaded improperly"<<endl;
127  }
128  else {
129  // Check that the image’s width is a power of 2
130 
131  if ( (surface->w & (surface->w - 1)) != 0 ) {
132  cout<<"warning: "<<file<<"'s width is not a power of 2"<<endl;
133  }
134 
135  // Also check if the height is a power of 2
136  if ( (surface->h & (surface->h - 1)) != 0 ) {
137  cout<<"warning: "<<file<<"'s height is not a power of 2"<<endl;
138  }
139  }
140 
141  //get number of channels in the SDL surface
142  GLint nofcolors=surface->format->BytesPerPixel;
143 
144  GLenum texture_format=0;
145 
146  //contains an alpha channel
147  if(surface->format->Rmask==0x000000ff)
148  texture_format=GL_RGBA;
149  else
150  texture_format=GL_BGRA;
151  if(!(nofcolors==4 || nofcolors==3))
152  {
153  cout<<"warning: the image is not truecolor...this will break "<<endl;
154  }
155 
156  // allocate a texture name if it's not already
157  Game::game()->getTexture(filename, &frame->tex);
158 
159  // select our current texture
160  glBindTexture( GL_TEXTURE_2D, frame->tex.image );
161 
162  // select modulate to mix texture with color for shading
163  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
164 
165  // when texture area is small, bilinear filter the closest mipmap
166  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
167  // when texture area is large, bilinear filter the original
168  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
169 
170  // the texture wraps over at the edges (repeat)
171  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
172  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
173 
174  glTexImage2D( GL_TEXTURE_2D, 0, nofcolors, surface->w, surface->h, 0,
175  texture_format, GL_UNSIGNED_BYTE, surface->pixels );
176 
177  SDL_FreeSurface(surface);
178 
180  frame->pause = pause;
181  unsigned int mW = frame->width;
182  unsigned int mH = frame->height;
183 
185  frame->animationPeg = Point2D(x + double(mW)/2, y + double(mH)/2);
186 
188  //do default hotspot of centerpos [0] and footpos [1]
189 
190  //add the rest of the hotspots
191 
192  Frames.push_back(frame);
193  }
194  }
195  fin.close();
196  } catch(YAML::ParserException& e) {
197  std::cout << e.what() << "\n";
198  Built = false;
199  return Built;
200  }
201  return Built;
202 }