Skip to content

Commit

Permalink
episode 12 - animated tiles
Browse files Browse the repository at this point in the history
  • Loading branch information
mark committed Oct 6, 2015
1 parent fd383de commit b12334d
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 24 deletions.
28 changes: 23 additions & 5 deletions maps/Map 1.tmx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@
<tileset firstgid="1" name="PrtCave" tilewidth="16" tileheight="16">
<image source="../content/tilesets/PrtCave.png" width="256" height="80"/>
</tileset>
<tileset firstgid="81" name="NpcSym" tilewidth="16" tileheight="16">
<image source="../content/tilesets/NpcSym.png" width="320" height="240"/>
<tile id="18">
<animation>
<frame tileid="18" duration="10"/>
<frame tileid="19" duration="10"/>
</animation>
</tile>
<tile id="26">
<animation>
<frame tileid="26" duration="100"/>
<frame tileid="27" duration="100"/>
<frame tileid="28" duration="100"/>
<frame tileid="29" duration="100"/>
<frame tileid="30" duration="100"/>
<frame tileid="31" duration="100"/>
<frame tileid="32" duration="100"/>
<frame tileid="33" duration="100"/>
</animation>
</tile>
</tileset>
<layer name="background" width="20" height="16">
<data>
<tile gid="34"/>
Expand Down Expand Up @@ -482,8 +503,8 @@
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="99"/>
<tile gid="107"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
Expand Down Expand Up @@ -687,9 +708,6 @@
<object id="21" x="82.2142" y="111.404">
<polyline points="0,0 31.1847,14.1749"/>
</object>
<object id="22" x="224.383" y="128.309">
<polyline points="0,0 13.6499,-6.29994"/>
</object>
<object id="23" x="159.913" y="65.0994">
<polyline points="0,0 14.1749,-6.61494"/>
</object>
Expand Down
49 changes: 49 additions & 0 deletions notes/episde 12 - animated tiles.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
=====================================================
Remaking Cavestory in C++
Episode 12 - Animated tiles
By: Limeoats
Website: www.limeoats.com
Twitter: @Limeoats
Github: https://github.com/Limeoats/cavestory-development
Reddit: http://www.reddit.com/r/Limeoats
=====================================================


=====================================================
Problem
=====================================================
-All of our tiles just sit still
-We want tiles that are animated on the screen
-We also want them animated in Tiled
-Our map isn't quite complete yet (heart container and save disk)

=====================================================
Details
=====================================================
-Npc/NpcSym.pbm
-Save disk duration: 100
-Health duration: 10

=====================================================
Solution
=====================================================
-Fix AnimatedSprite update
-Convert Npc/NpcSym.pbm to png and put it in tilesets folder
-Create the tiles in Tiled
-Fix the tile loading
-Create AnimatedTile class
-Parse the animation out of the .tmx file
-Modify the level class to use our new AnimatedTile


=====================================================
Next time
=====================================================
-Make Quote look up and down
-while walking
-while jumping
-Make Quote look behind him (interacting)




32 changes: 32 additions & 0 deletions source/headers/animatedtile.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef ANIMATED_TILE_H
#define ANIMATED_TILE_H

#include <vector>

#include "tile.h"
#include "globals.h"

class AnimatedTile : public Tile {
public:
AnimatedTile(std::vector<Vector2> tilesetPositions, int duration, SDL_Texture* tileset, Vector2 size, Vector2 position);
void update(int elapsedTime);
void draw(Graphics &graphics);
protected:
int _amountOfTime = 0;
bool _notDone = false;
private:
std::vector<Vector2> _tilesetPositions;
int _tileToDraw;
int _duration;
};

struct AnimatedTileInfo {
public:
int TilesetsFirstGid;
int StartTileId;
std::vector<int> TileIds;
int Duration;
};


#endif
6 changes: 6 additions & 0 deletions source/headers/level.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "tile.h"
#include "rectangle.h"
#include "slope.h"
#include "animatedtile.h"

class Graphics;
struct SDL_Texture;
Expand Down Expand Up @@ -41,11 +42,16 @@ class Level {
std::vector<Rectangle> _collisionRects;
std::vector<Slope> _slopes;

std::vector<AnimatedTile> _animatedTileList;
std::vector<AnimatedTileInfo> _animatedTileInfos;

/* void loadMap
* Loads a map
*/
void loadMap(std::string mapName, Graphics &graphics);

Vector2 getTilesetPosition(Tileset tls, int gid, int tileWidth, int tileHeight);

};

//Tileset structure
Expand Down
2 changes: 1 addition & 1 deletion source/headers/tile.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Tile {
Tile(SDL_Texture* tileset, Vector2 size, Vector2 tilesetPosition, Vector2 position);
void update(int elapsedTime);
void draw(Graphics &graphics);
private:
protected:
SDL_Texture* _tileset;
Vector2 _size;
Vector2 _tilesetPosition;
Expand Down
3 changes: 1 addition & 2 deletions source/src/animatedsprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ void AnimatedSprite::update(int elapsedTime) {
if (this->_currentAnimationOnce == true) {
this->setVisible(false);
}
this->_frameIndex = 0;
this->animationDone(this->_currentAnimation);
this->stopAnimation();
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions source/src/animatedtile.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "animatedtile.h"
#include "graphics.h"

AnimatedTile::AnimatedTile(std::vector<Vector2> tilesetPositions, int duration,
SDL_Texture* tileset, Vector2 size, Vector2 position) :
Tile(tileset, size, tilesetPositions.at(0), position),
_tilesetPositions(tilesetPositions),
_duration(duration),
_tileToDraw(0)
{}

void AnimatedTile::update(int elapsedTime) {
//Timer code
if (this->_amountOfTime <= 0) {
if (this->_tileToDraw == this->_tilesetPositions.size() -1) {
this->_tileToDraw = 0;
}
else {
this->_tileToDraw++;
}
this->_amountOfTime = this->_duration;
}
else {
this->_amountOfTime -= elapsedTime;
}

Tile::update(elapsedTime);
}

void AnimatedTile::draw(Graphics &graphics) {
SDL_Rect destRect = { this->_position.x, this->_position.y,
this->_size.x * globals::SPRITE_SCALE, this->_size.y * globals::SPRITE_SCALE };
SDL_Rect sourceRect = { this->_tilesetPositions.at(this->_tileToDraw).x, this->_tilesetPositions.at(this->_tileToDraw).y,
this->_size.x, this->_size.y };
graphics.blitSurface(this->_tileset, &sourceRect, &destRect);
}
89 changes: 73 additions & 16 deletions source/src/level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,31 @@ void Level::loadMap(std::string mapName, Graphics &graphics) {
SDL_Texture* tex = SDL_CreateTextureFromSurface(graphics.getRenderer(), graphics.loadImage(ss.str()));
this->_tilesets.push_back(Tileset(tex, firstgid));

//Get all of the animations for that tileset
XMLElement* pTileA = pTileset->FirstChildElement("tile");
if (pTileA != NULL) {
while (pTileA) {
AnimatedTileInfo ati;
ati.StartTileId = pTileA->IntAttribute("id") + firstgid;
ati.TilesetsFirstGid = firstgid;
XMLElement* pAnimation = pTileA->FirstChildElement("animation");
if (pAnimation != NULL) {
while (pAnimation) {
XMLElement* pFrame = pAnimation->FirstChildElement("frame");
if (pFrame != NULL) {
while (pFrame) {
ati.TileIds.push_back(pFrame->IntAttribute("tileid") + firstgid);
ati.Duration = pFrame->IntAttribute("duration");
pFrame = pFrame->NextSiblingElement("frame");
}
}
pAnimation = pAnimation->NextSiblingElement("animation");
}
}
this->_animatedTileInfos.push_back(ati);
pTileA = pTileA->NextSiblingElement("tile");
}
}
pTileset = pTileset->NextSiblingElement("tileset");
}
}
Expand Down Expand Up @@ -94,11 +119,13 @@ void Level::loadMap(std::string mapName, Graphics &graphics) {
//Get the tileset for this specific gid
int gid = pTile->IntAttribute("gid");
Tileset tls;
int closest = 0;
for (int i = 0; i < this->_tilesets.size(); i++) {
if (this->_tilesets[i].FirstGid <= gid) {
//This is the tileset we want
tls = this->_tilesets.at(i);
break;
if (this->_tilesets[i].FirstGid > closest) {
closest = this->_tilesets[i].FirstGid;
tls = this->_tilesets.at(i);
}
}
}

Expand All @@ -123,21 +150,34 @@ void Level::loadMap(std::string mapName, Graphics &graphics) {
Vector2 finalTilePosition = Vector2(xx, yy);

//Calculate the position of the tile in the tileset
int tilesetWidth, tilesetHeight;
SDL_QueryTexture(tls.Texture, NULL, NULL, &tilesetWidth, &tilesetHeight);
int tsxx = gid % (tilesetWidth / tileWidth) - 1;
tsxx *= tileWidth;
int tsyy = 0;
int amt = (gid / (tilesetWidth / tileWidth));
tsyy = tileHeight * amt;
Vector2 finalTilesetPosition = Vector2(tsxx, tsyy);
Vector2 finalTilesetPosition = this->getTilesetPosition(tls, gid, tileWidth, tileHeight);

//Build the actual tile and add it to the level's tile list
Tile tile(tls.Texture, Vector2(tileWidth, tileHeight),
finalTilesetPosition, finalTilePosition);
this->_tileList.push_back(tile);
bool isAnimatedTile = false;
AnimatedTileInfo ati;
for (int i = 0; i < this->_animatedTileInfos.size(); i++) {
if (this->_animatedTileInfos.at(i).StartTileId == gid) {
ati = this->_animatedTileInfos.at(i);
isAnimatedTile = true;
break;
}
}
if (isAnimatedTile == true) {
std::vector<Vector2> tilesetPositions;
for (int i = 0; i < ati.TileIds.size(); i++) {
tilesetPositions.push_back(this->getTilesetPosition(tls, ati.TileIds.at(i),
tileWidth, tileHeight));
}
AnimatedTile tile(tilesetPositions, ati.Duration,
tls.Texture, Vector2(tileWidth, tileHeight), finalTilePosition);
this->_animatedTileList.push_back(tile);
}
else {
Tile tile(tls.Texture, Vector2(tileWidth, tileHeight),
finalTilesetPosition, finalTilePosition);
this->_tileList.push_back(tile);
}
tileCounter++;

pTile = pTile->NextSiblingElement("tile");
}
}
Expand Down Expand Up @@ -241,13 +281,18 @@ void Level::loadMap(std::string mapName, Graphics &graphics) {
}

void Level::update(int elapsedTime) {

for (int i = 0; i < this->_animatedTileList.size(); i++) {
this->_animatedTileList.at(i).update(elapsedTime);
}
}

void Level::draw(Graphics &graphics) {
for (int i = 0; i < this->_tileList.size(); i++) {
this->_tileList.at(i).draw(graphics);
}
for (int i = 0; i < this->_animatedTileList.size(); i++) {
this->_animatedTileList.at(i).draw(graphics);
}
}

std::vector<Rectangle> Level::checkTileCollisions(const Rectangle &other) {
Expand All @@ -274,3 +319,15 @@ const Vector2 Level::getPlayerSpawnPoint() const {
return this->_spawnPoint;
}

Vector2 Level::getTilesetPosition(Tileset tls, int gid, int tileWidth, int tileHeight) {
int tilesetWidth, tilesetHeight;
SDL_QueryTexture(tls.Texture, NULL, NULL, &tilesetWidth, &tilesetHeight);
int tsxx = gid % (tilesetWidth / tileWidth) - 1;
tsxx *= tileWidth;
int tsyy = 0;
int amt = ((gid - tls.FirstGid) / (tilesetWidth / tileWidth));
tsyy = tileHeight * amt;
Vector2 finalTilesetPosition = Vector2(tsxx, tsyy);
return finalTilesetPosition;
}

0 comments on commit b12334d

Please sign in to comment.