Skip to content

Instantly share code, notes, and snippets.

@gwx
Created August 18, 2013 19:32
Show Gist options
  • Save gwx/6263523 to your computer and use it in GitHub Desktop.
Save gwx/6263523 to your computer and use it in GitHub Desktop.
// The weapon id used for animations.
const int LW_ANIMATION = 31;
// The weapon id used for animations that you don't want to be updated.
const int LW_ANIMATION2 = 32;
// The weapon->Misc index used to store the assigned sprite id.
// If you don't want to use this, set this to -1.
const int ANIMATION_SPRITE_INDEX = 1;
// weapon->Misc index for storing fine X movement.
const int ANIMATION_X_INDEX = 2;
// weapon->Misc index for storing fine Y movement.
const int ANIMATION_Y_INDEX = 3;
// Get the id of the sprite an animation is running.
int Animation_GetSpriteId(lweapon animation) {
return animation->Misc[MISC_ANI_SPRITE];}
// Get the id of the sprite an animation is running.
int Animation_GetSpriteId(int animationId) {
lweapon animation = FindLWeapon(animationId);
return animation->Misc[MISC_ANI_SPRITE];}
// Creates an animation. Once you create an animation, call
// Animation_GetId(animation) to get the unique id for that animation.
// With that id you can call AnimationGet(id) in subsequent frames to
// retrieve that specific animation.
// INPUT
// spriteId - The id number of the sprite to use for the animation.
// x, y - The location on the screen, in pixels, to display the animation.
// loop - If false, after the animation has completed one full cycle,
// it will remove itself.
// OUTPUT
// Returns the created animation.
lweapon Animation_Create(int spriteId, int x, int y, bool loop) {
return Animation_Create(spriteId, x, y, Cond(loop, 0, 1));}
// Creates an animation. Once you create an animation, call
// Animation_GetId(animation) to get the unique id for that animation.
// With that id you can call AnimationGet(id) in subsequent frames to
// retrieve that specific animation.
// INPUT
// spriteId - The id number of the sprite to use for the animation.
// Can also be negative, meaning a static animation of the positive
// tile number.
// x, y - The location on the screen, in pixels, to display the animation.
// loops - The number of times to loop through the animation before
// destroying itself, or 0 for infinite times.
// OUTPUT
// Returns the created animation.
lweapon Animation_Create(int spriteId, int x, int y, int loops) {
// Make a new lweapon of type animation.
lweapon animation = Screen->CreateLWeapon(LW_ANIMATION);
if (spriteId < 0) {
// Set to a static tile.
Animation_SetStatic(animation, -spriteId);}
else {
// Make it use the provided sprite.
animation->UseSprite(spriteId);}
// Remember which sprite was assigned in a misc. variable.
// This will be turned off if the constant is set to -1.
animation->Misc[MISC_ANI_SPRITE] = spriteId;
// Turn off collision detection so it doesn't hit any enemies by accident.
animation->CollDetection = false;
// Set its drawing location. If we keep it at (0,0) and only move its draw
// location, we don't have to worry about it falling off the edge of the
// screen and dying.
animation->DrawXOffset = x;
animation->DrawYOffset = y;
// Save location in misc variables, because they have higher precision.
animation->Misc[MISC_ANI_X] = x;
animation->Misc[MISC_ANI_Y] = y;
// If it's not stopping itself, then set the DeadState to -2.
// We don't want to use -1, since that would make it update its
// position, and we're solely using the drawing offsets to make it
// move and keeping the actual weapon at (0,0).
if (loops == 0) {
animation->DeadState = -2;}
// Otherwise, use the DeadState as a timer to run through the sprite once.
else {
animation->DeadState = loops * animation->NumFrames * animation->ASpeed;}
return animation;}
// Create an one-time running animation at x, y.
// See the first AnimationCreate for the full description.
lweapon Animation_Create(int spriteId, int x, int y) {
return Animation_Create(spriteId, x, y, false);}
// Create an animation at the given tile.
// See the first AnimationCreate for the full description.
lweapon Animation_Create(int spriteId, int location, bool loop) {
return Animation_Create(spriteId, ComboX(location), ComboY(location), loop);}
// Create a one-time running animation at the given tile.
// See the first AnimationCreate for the full description.
lweapon Animation_Create(int spriteId, int location) {
return Animation_Create(spriteId, ComboX(location), ComboY(location), false);}
// Set an animation to use a static tile.
void Animation_SetStatic(lweapon animation, int tile) {
animation->OriginalTile = tile;
animation->Tile = tile;
animation->NumFrames = 1;
animation->Frame = 0;
animation->ASpeed = 1;}
// If you want to use the built-in movement values of a weapon
// for an animation, set them and then call this function on
// that weapon every frame. This will move the draw offsets instead.
void Animation_Update(lweapon animation) {
float step = animation->Step * 0.01;
int x = animation->Misc[MISC_ANI_X];
int y = animation->Misc[MISC_ANI_Y];
// Angular Movement
if (animation->Angular) {
x += step * RadianCos(animation->Angle);
y += step * RadianSin(animation->Angle);}
// Directional Movement
else {
x += step * DirX(animation->Dir);
y += step * DirY(animation->Dir);}
// Store values.
animation->Misc[MISC_ANI_X] = x;
animation->Misc[MISC_ANI_Y] = y;
animation->DrawXOffset = x;
animation->DrawYOffset = y;}
// Use this version of AnimationUpdate to update every animation.
void Animation_Update() {
// Loop through every lweapon on the screen.
for (int i = 1; i <= Screen->NumLWeapons(); i++) {
lweapon lw = Screen->LoadLWeapon(i);
// If lw is an animation, update it.
if (lw->ID == LW_ANIMATION) {
Animation_Update(lw);}}}
// Move the animation to the given location.
void Animation_Move(lweapon animation, int x, int y) {
animation->Misc[ANIMATION_X_INDEX] = x;
animation->Misc[ANIMATION_Y_INDEX] = y;}
// Destroys all animations.
void Animation_Destroy() {
// Loop through every lweapon on the screen.
for (int i = 1; i <= Screen->NumLWeapons(); i++) {
lweapon lw = Screen->LoadLWeapon(i);
// If lw is an animation, destroy it.
if (lw->ID == LW_ANIMATION) {
Remove(lw);}}}
// Assign Unique IDs to everything.
// Misc Indices. Mess with these to avoid collisions with other scripts.
const int FFC_ID_INDEX = 0;
const int NPC_ID_INDEX = 0;
const int LWEAPON_ID_INDEX = 0;
const int EWEAPON_ID_INDEX = 0;
const int ITEM_ID_INDEX = 0;
// Values indicating unassigned ids. Assign this to whatever the
// default value for your selected index is.
const int FFC_ID_NULL = 0;
const int NPC_ID_NULL = 0;
const int LWEAPON_ID_NULL = 0;
const int EWEAPON_ID_NULL = 0;
const int ITEM_ID_NULL = 0;
// Value indicating next id.
int NextFFCId = FFC_ID_NULL + 1;
int NextNPCId = NPC_ID_NULL + 1;
int NextLWeaponId = LWEAPON_ID_NULL + 1;
int NextEWeaponId = EWEAPON_ID_NULL + 1;
int NextItemId = ITEM_ID_NULL + 1;
// Get the id of an ffc, first assigning one if needed.
int GetId(ffc _ffc) {
if (_ffc->Misc[FFC_ID_INDEX] == FFC_ID_NULL) {
_ffc->Misc[FFC_ID_INDEX] = NextFFCId;
NextFFCId++;
if (NextFFCId == FFC_ID_NULL) {
NextFFCId++;}}
return _ffc->Misc[FFC_ID_INDEX];}
// Get the id of an npc, first assigning one if needed.
int GetId(npc _npc) {
if (_npc->Misc[NPC_ID_INDEX] == NPC_ID_NULL) {
_npc->Misc[NPC_ID_INDEX] = NextNPCId;
NextNPCId++;
if (NextNPCId == NPC_ID_NULL) {
NextNPCId++;}}
return _npc->Misc[NPC_ID_INDEX];}
// Get the id of an lweapon, first assigning one if needed.
int GetId(lweapon _lweapon) {
if (_lweapon->Misc[LWEAPON_ID_INDEX] == LWEAPON_ID_NULL) {
_lweapon->Misc[LWEAPON_ID_INDEX] = NextLWeaponId;
NextLWeaponId++;
if (NextLWeaponId == LWEAPON_ID_NULL) {
NextLWeaponId++;}}
return _lweapon->Misc[LWEAPON_ID_INDEX];}
// Get the id of an eweapon, first assigning one if needed.
int GetId(eweapon _eweapon) {
if (_eweapon->Misc[EWEAPON_ID_INDEX] == EWEAPON_ID_NULL) {
_eweapon->Misc[EWEAPON_ID_INDEX] = NextEWeaponId;
NextEWeaponId++;
if (NextEWeaponId == EWEAPON_ID_NULL) {
NextEWeaponId++;}}
return _eweapon->Misc[EWEAPON_ID_INDEX];}
// Get the id of an item, first assigning one if needed.
int GetId(item _item) {
if (_item->Misc[ITEM_ID_INDEX] == ITEM_ID_NULL) {
_item->Misc[ITEM_ID_INDEX] = NextItemId;
NextItemId++;
if (NextItemId == ITEM_ID_NULL) {
NextItemId++;}}
return _item->Misc[ITEM_ID_INDEX];}
// Return the ffc with the given id.
ffc FindFFC(int id) {
for (int i = 1; i <= 32; i++) {
ffc _ffc = Screen->LoadFFC(i);
if (GetId(_ffc) == id) {
return _ffc;}}}
// Return the npc with the given id.
npc FindNPC(int id) {
for (int i = 1; i <= Screen->NumNPCs(); i++) {
npc _npc = Screen->LoadNPC(i);
if (GetId(_npc) == id) {
return _npc;}}}
// Return the lweapon with the given id.
lweapon FindLWeapon(int id) {
for (int i = 1; i <= Screen->NumLWeapons(); i++) {
lweapon _lweapon = Screen->LoadLWeapon(i);
if (GetId(_lweapon) == id) {
return _lweapon;}}}
// Return the eweapon with the given id.
eweapon FindEWeapon(int id) {
for (int i = 1; i <= Screen->NumEWeapons(); i++) {
eweapon _eweapon = Screen->LoadEWeapon(i);
if (GetId(_eweapon) == id) {
return _eweapon;}}}
// Return the item with the given id.
item FindItem(int id) {
for (int i = 1; i <= Screen->NumItems(); i++) {
item _item = Screen->LoadItem(i);
if (GetId(_item) == id) {
return _item;}}}
// Misc indices.
//// LWeapon
const int MISC_LW_ID = 0;
const int MISC_ANI_SPRITE = 1;
const int MISC_ANI_X = 2;
const int MISC_ANI_Y = 3;
const int SF_CAN = 1;
const int SF_ITEM = 2;
const int SF_NEXT = 4;
const int SF_CONTINUOUS = 8;
const int SF_BUSH = 16;
const int SF_FLOWER = 32;
const int SF_GRASS = 64;
// How many cycles the animation will last.
const int SLASH_ANIM_DURATION = 1;
// How many animations to create.
const int SLASH_ANIM_COUNT = 10;
// Maximum amount the animation will be randomly offset.
const int SLASH_ANIM_MAX_OFFSET = 8;
// Minimum animation step.
const int SLASH_ANIM_STEP_MIN = 30;
// Maximum animation step.
const int SLASH_ANIM_STEP_MAX = 80;
int Slash_InterpretType(int comboType) {
if (comboType == CT_BUSH) {
return SF_CAN | SF_BUSH;}
else if (comboType == CT_BUSHC) {
return SF_CAN | SF_ITEM | SF_CONTINUOUS | SF_BUSH;}
else if (comboType == CT_BUSHNEXT) {
return SF_CAN | SF_ITEM | SF_NEXT | SF_BUSH;}
else if (comboType == CT_BUSHNEXTC) {
return SF_CAN | SF_ITEM | SF_NEXT | SF_CONTINUOUS | SF_BUSH;}
else if (comboType == CT_FLOWERS) {
return SF_CAN | SF_ITEM | SF_FLOWER;}
else if (comboType == CT_FLOWERSC) {
return SF_CAN | SF_ITEM | SF_CONTINUOUS | SF_FLOWER;}
else if (comboType == CT_SLASH) {
return SF_CAN;}
else if (comboType == CT_SLASHC) {
return SF_CAN | SF_CONTINUOUS;}
else if (comboType == CT_SLASHITEM) {
return SF_CAN | SF_ITEM;}
else if (comboType == CT_SLASHITEMC) {
return SF_CAN | SF_ITEM | SF_CONTINUOUS;}
else if (comboType == CT_SLASHNEXT) {
return SF_CAN | SF_NEXT;}
else if (comboType == CT_SLASHNEXTC) {
return SF_CAN | SF_NEXT | SF_CONTINUOUS;}
else if (comboType == CT_SLASHNEXTITEM) {
return SF_CAN | SF_ITEM | SF_NEXT;}
else if (comboType == CT_SLASHNEXTITEMC) {
return SF_CAN | SF_ITEM | SF_NEXT | SF_CONTINUOUS;}
else if (comboType == CT_TALLGRASS) {
return SF_CAN | SF_ITEM | SF_GRASS;}
else if (comboType == CT_TALLGRASSC) {
return SF_CAN | SF_ITEM | SF_CONTINUOUS | SF_GRASS;}
else if (comboType == CT_TALLGRASSNEXT) {
return SF_CAN | SF_ITEM | SF_NEXT | SF_GRASS;}
else {
return 0;}}
// Slash a given combo.
// Dosen't support continuous.
bool Slash_Slash(int loc) {
Slash_Slash(loc, true);}
// Slash a given combo.
// Dosen't support continuous.
bool Slash_Slash(int loc, bool fullSlash) {
int type = Slash_InterpretType(Screen->ComboT[loc]);
if (type & SF_CAN && (fullSlash || Screen->ComboS[loc] != 0)) {
// Change combo.
if (type & SF_NEXT) {
Screen->ComboD[loc]++;}
else {
Screen->ComboD[loc] = Screen->UnderCombo;}
// Drop item.
if (type & SF_ITEM) {
DropItem(DROP_GRASS, loc);}
// Animation
if (type & SF_BUSH) {
Slash_CreateEffects(loc, SPR_LEAF, 1, 1, true);}
else if (type & SF_GRASS) {
Slash_CreateEffects(loc, SPR_GRASS, 1, 1, true);}
else if (type & SF_FLOWER) {
Slash_CreateEffects(loc, SPR_LEAF, 1, 1, true);}
else {
// Looks ugly right now.
// Slash_CreateEffects(loc, SPR_POT, 1.5, 1, false);
}
// Play sound.
if (type & (SF_BUSH | SF_GRASS | SF_FLOWER)) {
Game->PlaySound(SFX_GRASSCUT);}
else {
Game->PlaySound(SFX_POT_SMASH);}
return true;}
// Also cut layer 1 (full slash only).
type = Slash_InterpretType(GetLayerComboT(1, loc));
if (type & SF_CAN && fullSlash) {
SetLayerComboD(1, loc, GetLayerComboD(1, loc) + 1);
Slash_CreateEffects(loc, SPR_GRASS, 1, 1, true);
Game->PlaySound(SFX_GRASSCUT);}
return false;}
// Slash a given combo.
bool Slash_Slash(int x, int y) {
return Slash_Slash(ComboAt(x, y));}
// Slash a given region.
bool Slash_Slash(int x, int y, int w, int h) {
bool slash = false;
for (int x1 = x; x1 < x + w; x1 += 16) {
for (int y1 = y; y1 < y + h; y1 += 16) {
slash ||= Slash_Slash(ComboAt(x1, y1));}
slash ||= Slash_Slash(ComboAt(x1, y + h));}
x += w;
for (int y1 = y; y1 < y + h; y1 += 16) {
slash ||= Slash_Slash(ComboAt(x, y1));}
slash ||= Slash_Slash(ComboAt(x, y + h));
return slash;}
// Slash what a given weapon hits.
bool Slash_Slash(lweapon lw) {
return Slash_Slash(lw->X + lw->HitXOffset,
lw->Y + lw->HitYOffset,
lw->HitWidth,
lw->HitHeight);}
// Slash a given tile only if it is solid.
bool Slash_SlashSolid(int loc) {
return Slash_Slash(loc, false);}
// Slash a given solid combo.
bool Slash_SlashSolid(int x, int y) {
return Slash_SlashSolid(ComboAt(x, y));}
// Slash solid tiles in a given region.
bool Slash_SlashSolid(int x, int y, int w, int h) {
bool slash = false;
for (int x1 = x; x1 < x + w; x1 += 16) {
for (int y1 = y; y1 < y + h; y1 += 16) {
slash ||= Slash_SlashSolid(ComboAt(x1, y1));}
slash ||= Slash_SlashSolid(ComboAt(x1, y + h));}
x += w;
for (int y1 = y; y1 < y + h; y1 += 16) {
slash ||= Slash_SlashSolid(ComboAt(x, y1));}
slash ||= Slash_SlashSolid(ComboAt(x, y + h));
return slash;}
// Slash solid tiles a given weapon hits.
bool Slash_SlashSolid(lweapon lw) {
return Slash_SlashSolid(lw->X + lw->HitXOffset,
lw->Y + lw->HitYOffset,
lw->HitWidth,
lw->HitHeight);}
void Slash_CreateEffects(int loc, int animId, int stepMult, int durMult, bool flip) {
int x = ComboX(loc);
int y = ComboY(loc);
int cset = Screen->ComboC[loc];
for (int i = 0; i < SLASH_ANIM_COUNT; i++) {
int x1 = x + Rand(2 * SLASH_ANIM_MAX_OFFSET + 1) - SLASH_ANIM_MAX_OFFSET;
int y1 = y + Rand(2 * SLASH_ANIM_MAX_OFFSET + 1) - SLASH_ANIM_MAX_OFFSET;
lweapon animation = Animation_Create(animId, x1, y1, SLASH_ANIM_DURATION * durMult);
animation->CSet = cset;
animation->Step =
stepMult *
(Rand(SLASH_ANIM_STEP_MAX - SLASH_ANIM_STEP_MIN) + SLASH_ANIM_STEP_MIN);
animation->Behind = false;
animation->Angular = true;
animation->Angle = Rand(PI2);
if (flip) {animation->Flip = Rand(4);}
else {animation->Flip = 0;}}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment