Path: blob/master/SonicMania/Objects/SPZ/FilmReel.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: FilmReel Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectFilmReel *FilmReel;1011void FilmReel_Update(void)12{13RSDK_THIS(FilmReel);1415self->velocity.x = (self->spinSpeed * RSDK.Cos256(self->angle)) >> 9;16self->velocity.y = (self->spinSpeed * RSDK.Sin256(self->angle)) >> 9;17self->lastPos.x += self->velocity.x;18self->lastPos.y += self->velocity.y;1920int32 prevPathFlags = self->pathFlags;21self->pathFlags = 0;22switch (self->pathDir) {23case 0:24if (self->drawPos.x != self->endPos.x) {25if (self->lastPos.x <= self->drawPos.x) {26self->lastPos.x = self->drawPos.x;27self->pathFlags = 1;28}2930if (self->lastPos.x >= self->endPos.x) {31self->pathFlags |= 2;32self->lastPos.x = self->endPos.x;33}34}3536if (self->drawPos.y != self->endPos.y) {37if (self->lastPos.y <= self->drawPos.y) {38self->pathFlags |= 1;39self->lastPos.y = self->drawPos.y;40}4142if (self->lastPos.y >= self->endPos.y) {43self->pathFlags |= 2;44self->lastPos.y = self->lastPos.y;45}46}47break;4849case 1:50if (self->drawPos.x != self->endPos.x) {51if (self->lastPos.x <= self->endPos.x) {52self->lastPos.x = self->endPos.x;53self->pathFlags = 2;54}5556if (self->lastPos.x >= self->endPos.x) {57self->pathFlags |= 1;58self->lastPos.x = self->drawPos.x;59}60}6162if (self->drawPos.y != self->endPos.y) {63if (self->lastPos.y <= self->drawPos.y) {64self->pathFlags |= 1;65self->lastPos.y = self->drawPos.y;66}6768if (self->lastPos.y >= self->endPos.y) {69self->pathFlags |= 2;70self->lastPos.y = self->lastPos.y;71}72}73break;7475case 2:76if (self->drawPos.x != self->endPos.x) {77if (self->lastPos.x <= self->endPos.x) {78self->lastPos.x = self->endPos.x;79self->pathFlags = 2;80}8182if (self->lastPos.x >= self->drawPos.x) {83self->pathFlags |= 1;84self->lastPos.x = self->drawPos.x;85}86}8788if (self->drawPos.y != self->endPos.y) {89if (self->lastPos.y <= self->endPos.y) {90self->pathFlags |= 2;91self->lastPos.y = self->endPos.y;92}9394if (self->lastPos.y >= self->drawPos.y) {95self->pathFlags |= 1;96self->lastPos.y = self->drawPos.y;97}98}99break;100101case 3:102if (self->drawPos.x != self->endPos.x) {103if (self->lastPos.x <= self->drawPos.x) {104self->lastPos.x = self->drawPos.x;105self->pathFlags = 1;106}107108if (self->lastPos.x >= self->endPos.x) {109self->pathFlags |= 2;110self->lastPos.x = self->endPos.x;111}112}113114if (self->drawPos.y != self->endPos.y) {115if (self->lastPos.y <= self->endPos.y) {116self->pathFlags |= 2;117self->lastPos.y = self->endPos.y;118}119120if (self->lastPos.y >= self->drawPos.y) {121self->pathFlags |= 1;122self->lastPos.y = self->drawPos.y;123}124}125break;126127default: break;128}129130if (self->pathFlags) {131if (!prevPathFlags) {132RSDK.PlaySfx(FilmReel->sfxLanding, false, 255);133RSDK.StopSfx(FilmReel->sfxUnravel);134135if (self->pathFlags == 1)136self->active = ACTIVE_BOUNDS;137}138}139else {140if (!(Zone->timer & 7))141RSDK.PlaySfx(FilmReel->sfxUnravel, false, 255);142143self->active = ACTIVE_NORMAL;144}145146self->spinSpeed -= 0x2000;147self->moveOffset.x = (self->lastPos.x & 0xFFFF0000) - (self->position.x & 0xFFFF0000);148self->moveOffset.y = (self->lastPos.y & 0xFFFF0000) - (self->position.y & 0xFFFF0000);149150if (!self->spinDirection)151FilmReel_SpinLeft();152else153FilmReel_SpinRight();154155self->spinSpeed = CLAMP(self->spinSpeed, -0x80000, 0x80000);156157self->position = self->lastPos;158if (!self->pathFlags) {159if (self->spinDirection)160self->spinAngle -= self->spinSpeed;161else162self->spinAngle += self->spinSpeed;163164self->rotation = (self->spinAngle >> 16) & 0x1FF;165}166167if (abs(self->pathSize.x) <= abs(self->pathSize.y)) {168int32 scale = MIN((abs(self->endPos.y - self->position.y) >> 8) / (abs(self->pathSize.x) >> 16) + 0x100, 0x200);169self->scale.x = scale;170self->scale.y = scale;171}172else {173int32 scale = MIN((abs(self->endPos.x - self->position.x) >> 8) / (abs(self->pathSize.x) >> 16) + 0x100, 0x200);174self->scale.x = scale;175self->scale.y = scale;176}177178self->lineDir = abs(self->position.x - self->drawPos.x) <= abs(self->pathSize.y - self->drawPos.y);179}180181void FilmReel_LateUpdate(void) {}182183void FilmReel_StaticUpdate(void) {}184185void FilmReel_Draw(void)186{187RSDK_THIS(FilmReel);188189int32 angle = (self->angle - 64) & 0xFF;190int32 x2 = (16 * self->scale.x * RSDK.Cos256(angle) + self->position.x) & 0xFFFF0000;191int32 y2 = (16 * self->scale.x * RSDK.Sin256(angle) + self->position.y) & 0xFFFF0000;192193self->celluoidAnimator.frameID = (self->rotation >> 4) & 1;194195color color1 = self->celluoidAnimator.frameID ? 0x204078 : 0x3868A8;196color color2 = self->celluoidAnimator.frameID ? 0x182850 : 0x204078;197198if (self->lineDir) {199RSDK.DrawLine(self->drawPos.x, self->drawPos.y, x2, y2, color1, 255, INK_NONE, false);200RSDK.DrawLine(self->drawPos.x, self->drawPos.y + 0x18000, x2, y2 + 0x18000, color2, 255, INK_NONE, false);201}202else {203RSDK.DrawLine(self->drawPos.x, self->drawPos.y, x2, y2, color1, 255, INK_NONE, false);204RSDK.DrawLine(self->drawPos.x - 0x18000, self->drawPos.y, x2 - 0x18000, y2, color2, 255, INK_NONE, false);205}206207RSDK.DrawSprite(&self->pinAnimator, &self->drawPos, false);208209self->drawFX = FX_SCALE;210RSDK.DrawSprite(&self->celluoidAnimator, NULL, false);211212self->drawFX = FX_ROTATE;213RSDK.DrawSprite(&self->reelAnimator, NULL, false);214215self->drawFX = FX_NONE;216RSDK.DrawSprite(&self->edgeAnimator, NULL, false);217}218219void FilmReel_Create(void *data)220{221RSDK_THIS(FilmReel);222223RSDK.SetSpriteAnimation(FilmReel->aniFrames, 0, &self->reelAnimator, true, 0);224RSDK.SetSpriteAnimation(FilmReel->aniFrames, 1, &self->celluoidAnimator, true, 0);225RSDK.SetSpriteAnimation(FilmReel->aniFrames, 2, &self->edgeAnimator, true, 0);226RSDK.SetSpriteAnimation(FilmReel->aniFrames, 3, &self->pinAnimator, true, 0);227228if (!SceneInfo->inEditor) {229self->lastPos = self->position;230self->drawPos = self->position;231self->endPos.x = self->drawPos.x + self->pathSize.x;232self->endPos.y = self->drawPos.y + self->pathSize.y;233234self->active = ACTIVE_BOUNDS;235self->updateRange.x = 0xC00000;236self->updateRange.y = 0xC00000;237self->scale.x = 0x200;238self->scale.y = 0x200;239240self->angle = RSDK.ATan2(self->pathSize.x, self->pathSize.y);241self->pathDir = self->angle >> 6;242self->pathFlags = 1;243self->visible = true;244self->drawGroup = Zone->objectDrawGroup[0];245}246}247248void FilmReel_StageLoad(void)249{250if (RSDK.CheckSceneFolder("SPZ1"))251FilmReel->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/FilmReel.bin", SCOPE_STAGE);252else253FilmReel->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/FilmReel.bin", SCOPE_STAGE);254255FilmReel->hitboxWheel.left = -64;256FilmReel->hitboxWheel.top = -64;257FilmReel->hitboxWheel.right = 64;258FilmReel->hitboxWheel.bottom = 64;259260FilmReel->offsetPos.x = 0x800000;261FilmReel->offsetPos.y = 0x800000;262263FilmReel->sfxUnravel = RSDK.GetSfx("Stage/Unravel.wav");264FilmReel->sfxLanding = RSDK.GetSfx("Stage/Landing.wav");265}266267void FilmReel_SpinLeft(void)268{269RSDK_THIS(FilmReel);270271foreach_active(Player, player)272{273if (Player_CheckCollisionTouch(player, self, &FilmReel->hitboxWheel)) {274player->collisionLayers |= Zone->moveLayerMask;275player->moveLayerPosition.x = FilmReel->offsetPos.x - self->lastPos.x;276player->moveLayerPosition.y = FilmReel->offsetPos.y - self->lastPos.y;277278if (!player->sidekick) {279if (player->onGround || RSDK.CheckObjectCollisionTouchCircle(self, 0x400000, player, 0x100000)) {280281bool32 controllingMovement = true;282switch (self->pathFlags) {283case 0:284if (player->collisionMode || (!player->left && !player->right && player->state != Player_State_Roll)) {285controllingMovement = false;286}287288if (abs(player->position.x - self->position.x) < 2 * abs(player->groundVel) && controllingMovement) {289if (player->groundVel < -0x60000)290player->groundVel = -0x60000;291292if (player->direction == FLIP_X) {293player->position.x = self->position.x;294self->spinSpeed -= player->groundVel;295}296}297else {298player->groundVel += self->spinSpeed >> 5;299if (player->groundVel < -0x60000)300player->groundVel = -0x60000;301}302break;303304case 1:305if (!player->collisionMode && (player->left || player->right || player->state == Player_State_Roll)306&& player->direction == FLIP_X) {307if (abs(player->position.x - self->position.x) < 2 * abs(player->groundVel)) {308if (player->groundVel < 0)309player->position.x = self->position.x;310self->spinSpeed -= player->groundVel;311}312}313break;314315case 2:316if (abs(player->position.x - self->position.x) >= 2 * abs(player->groundVel) || player->collisionMode317|| player->position.x <= self->position.x) {318if (player->left)319self->spinSpeed -= player->groundVel;320}321else {322if (player->groundVel > 0)323player->position.x = self->position.x;324self->spinSpeed -= player->groundVel;325}326break;327}328329if (player->camera && self->moveCamera) {330player->camera->state = StateMachine_None;331player->camera->position.x += self->moveOffset.x + ((self->position.x - player->camera->position.x) >> 3);332player->camera->position.y += self->moveOffset.y + ((self->position.y - player->camera->position.y - 0x200000) >> 3);333}334335player->position.x += self->moveOffset.x;336player->position.y += self->moveOffset.y;337}338else if (player->camera && self->moveCamera) {339player->camera->state = Camera_State_FollowXY;340}341}342}343}344}345346void FilmReel_SpinRight(void)347{348RSDK_THIS(FilmReel);349350foreach_active(Player, player)351{352if (Player_CheckCollisionTouch(player, self, &FilmReel->hitboxWheel)) {353player->collisionLayers |= Zone->moveLayerMask;354player->moveLayerPosition.x = FilmReel->offsetPos.x - self->lastPos.x;355player->moveLayerPosition.y = FilmReel->offsetPos.y - self->lastPos.y;356if (!player->sidekick) {357if (player->onGround || RSDK.CheckObjectCollisionTouchCircle(self, 0x400000, player, 0x100000)) {358359bool32 controllingMovement = true;360switch (self->pathFlags) {361case 0:362if (player->collisionMode || (!player->left && !player->right && player->state != Player_State_Roll)) {363controllingMovement = false;364}365366if (abs(player->position.x - self->position.x) < 2 * abs(player->groundVel) && controllingMovement) {367if (player->groundVel > 0x60000)368player->groundVel = 0x60000;369370if (player->direction == FLIP_NONE) {371player->position.x = self->position.x;372self->spinSpeed += player->groundVel;373}374}375else {376player->groundVel -= self->spinSpeed >> 5;377if (player->groundVel > 0x60000)378player->groundVel = 0x60000;379}380break;381382case 1:383if (player->collisionMode || (!player->left && !player->right && player->state != Player_State_Roll)384|| player->direction) {385controllingMovement = false;386}387388if (controllingMovement) {389if (abs(player->position.x - self->position.x) < 2 * abs(player->groundVel) && player->groundVel > 0) {390player->position.x = self->position.x;391}392self->spinSpeed += player->groundVel;393}394break;395396case 2:397if (abs(player->position.x - self->position.x) >= 2 * abs(player->groundVel) || player->collisionMode398|| player->position.x >= self->position.x) {399if (player->right)400self->spinSpeed += player->groundVel;401}402else {403if (player->groundVel < 0)404player->position.x = self->position.x;405self->spinSpeed += player->groundVel;406}407break;408}409410if (player->camera && self->moveCamera) {411player->camera->state = StateMachine_None;412player->camera->position.x += self->moveOffset.x + ((self->position.x - player->camera->position.x) >> 3);413player->camera->position.y += self->moveOffset.y + ((self->position.y - player->camera->position.y - 0x200000) >> 3);414}415}416else if (player->camera && self->moveCamera) {417player->camera->state = Camera_State_FollowXY;418}419}420}421}422}423424#if GAME_INCLUDE_EDITOR425void FilmReel_EditorDraw(void)426{427RSDK_THIS(FilmReel);428429self->lastPos = self->position;430self->drawPos = self->position;431self->endPos.x = self->position.x + self->pathSize.x;432self->endPos.y = self->position.y + self->pathSize.y;433self->active = ACTIVE_BOUNDS;434self->updateRange.x = 0xC00000;435self->updateRange.y = 0xC00000;436self->scale.x = 0x200;437self->scale.y = 0x200;438439self->angle = RSDK.ATan2(self->pathSize.x, self->pathSize.y);440self->pathDir = self->angle >> 6;441self->pathFlags = 1;442self->visible = true;443self->drawGroup = Zone->objectDrawGroup[0];444445FilmReel_Draw();446447if (showGizmos()) {448RSDK_DRAWING_OVERLAY(true);449450self->inkEffect = INK_BLEND;451self->drawPos = self->endPos;452FilmReel_Draw();453454self->drawFX = FX_SCALE;455RSDK.DrawSprite(&self->celluoidAnimator, &self->drawPos, false);456457self->drawFX = FX_ROTATE;458RSDK.DrawSprite(&self->reelAnimator, &self->drawPos, false);459460self->drawFX = FX_NONE;461RSDK.DrawSprite(&self->edgeAnimator, &self->drawPos, false);462463self->inkEffect = INK_NONE;464465RSDK_DRAWING_OVERLAY(false);466}467}468469void FilmReel_EditorLoad(void)470{471if (RSDK.CheckSceneFolder("SPZ1"))472FilmReel->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/FilmReel.bin", SCOPE_STAGE);473else474FilmReel->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/FilmReel.bin", SCOPE_STAGE);475476RSDK_ACTIVE_VAR(FilmReel, spinDirection);477RSDK_ENUM_VAR("Clockwise", FLIP_NONE);478RSDK_ENUM_VAR("Counter-Clockwise", FLIP_X);479}480#endif481482void FilmReel_Serialize(void)483{484RSDK_EDITABLE_VAR(FilmReel, VAR_VECTOR2, pathSize);485RSDK_EDITABLE_VAR(FilmReel, VAR_UINT8, spinDirection);486}487488489