f9e76d9dc0
During the final stretch, after Viridian turns off the Dimensional Stability Generator, the map goes all psychedelic and changes colors every 40 frames. Entities change their colors too, including conveyors, moving platforms, and disappearing platforms. But play around with the disappearing platforms for a bit and you'll notice they seem a bit glitchy. If you run on them at the right time, the tile they use while disappearing seems to abruptly change whenever the color of the room changes. If there's a color change while they're reappearing (when you die and respawn in the same room as them), they'll have the wrong tile and look like a conveyor. And even if you've never interacted with them at all, dying and respawning in the same room as them will change their tile to something wrong and also look like a conveyor. So, what's the problem? Well, first off, the tile of every untouched disappearing platform changing into a conveyor after you die and respawn in the same room is caused by a block of code in gamelogic() that gets run on each entity whenever you die. This block of code is the exact same block of code that gets ran on a disappearing platform if it's in the middle of disappearing. As a quick primer, every entity in the game has a state, which is just a number. You can view each entity's state in entityclass::updateentities(). State 0 of disappearing platforms is doing nothing, and they start with an onentity of 1, which means they turn to state 1 when they get touched. State 1 moves to state 2. State 2 does some decrementing, then moves to state 3 and sets the onentity to 4. State 3 also does nothing. After being touched, state 4 makes the platform reappear and move to state 5, but state 5 does the actual reappearing; state 5 then sets the state back to 0 and onentity back to 1. So, back to the copy-pasted block of code. The block of code was originally intended to fast-forward disappearing platforms if they were in the middle of disappearing, so the player respawn code would properly respawn the disappearing platform, instead of leaving it disappeared. What it does is keep updating the entity, while the state of the entity is 2, until it is no longer in state 2, then sets it to state 4. Crucially, the original block of code only ran if the disappearing platform was in state 2. But the other block of code, which was copy-pasted with slight modifications, runs on ALL disappearing platforms in final stretch, regardless of if they are in state 2 or not. Thus, all untouched platforms will be set to state 4, and state 4 will do the animation of the platform reappearing, which is invalid given that the platform never disappeared in the first place. So that's why dying and respawning in the same room as some disappearing platforms during final stretch will change their tiles to be conveyors. It seems to me that doing anything with death is wrong, here. The root cause is that map.changefinalcol() "resets" the tile of every disappearing platform, which is a function that gets called on every color change. The color change has nothing to do with dying, so why fiddle with the death code? Thus, I've deleted that entire block of code. What I've done to fix the issue is to make it so the tile of disappearing platforms aren't manually controlled. You see, unlike other entities in the game, the tile of disappearing platforms gets manually modified whenever it disappears or reappears. Other entities use the tile as a base and store their tile offset in the separate walkingframe attribute, which will be added to the tile attribute to produce the drawframe, which is the final thing that gets rendered - but for disappearing platforms, their tile gets directly incremented or decremented whenever they disappear or reappear, so when map.changefinalcol() gets ran to update the tile of every platform and conveyor, it basically discards the tile offset that was manually added in. Instead, what I've done is make it so disappearing platforms now use walkingframe, and thus their final drawframe will be their tile plus their walkingframe. Whenever map.changefinalcol() gets called, it is now free to modify the tile of disappearing platforms accordingly - after all, the tile offset is now stored in walkingframe, so no weird glitchiness can happen there. |
||
---|---|---|
.. | ||
src | ||
.dockerignore | ||
.gitignore | ||
CMakeLists.txt | ||
CONTRIBUTORS.txt | ||
Dockerfile | ||
README.md | ||
version.cmake |
How to Build
VVVVVV's official desktop versions are built with the following environments:
- Windows: Visual Studio 2010
- macOS: Xcode CLT, currently targeting 10.9 SDK
- GNU/Linux: CentOS 7
The engine depends solely on SDL2 2.0.14+ and SDL2_mixer. All other dependencies are statically linked into the engine. The development libraries for Windows can be downloaded from their respective websites, Linux developers can find the dev libraries from their respective repositories, and macOS developers should compile and install from source (including libogg/libvorbis/libvorbisfile).
Steamworks support is included and the DLL is loaded dynamically, you do not need the SDK headers and there is no special Steam or non-Steam version. The current implementation has been tested with Steamworks SDK v1.46.
To generate the projects on Windows:
# Put your SDL2/SDL2_mixer folders somewhere nice!
mkdir flibitBuild
cd flibitBuild
cmake -G "Visual Studio 10 2010" .. -DSDL2_INCLUDE_DIRS="C:\SDL2-2.0.10\include;C:\SDL2_mixer-2.0.4\include" -DSDL2_LIBRARIES="C:\SDL2-2.0.10\lib\x86\SDL2;C:\SDL2-2.0.10\lib\x86\SDL2main;C:\SDL2_mixer-2.0.4\lib\x86\SDL2_mixer"
Note that on some systems, the SDL2_LIBRARIES
list on Windows may need
SDL2/SDL2main/SDL2_mixer to have .lib
at the end of them. The reason for this
inconsistency is unknown.
To generate everywhere else:
mkdir flibitBuild
cd flibitBuild
cmake ..
macOS may be fussy about the SDK version. How to fix this is up to the whims of however Apple wants to make CMAKE_OSX_SYSROOT annoying to configure and retain each time Xcode updates.
Including data.zip
You'll need the data.zip file from VVVVVV to actually run the game! It's available to download separately for free in the Make and Play edition of the game. Put this file next to your executable and the game should run.
This is intended for personal use only - our license doesn't allow you to actually distribute this data.zip file with your own forks without getting permission from us first. See LICENSE.md for more details. (If you've got a project in mind that requires distributing this file, get in touch!)
A Word About Compiler Quirks
(Note: This section only applies to version 2.2 of the source code, which is the initial commit of this repository. Since then, much hard work has been put in to fix many undefined behaviors. If you're compiling the latest version of the source code, ignore this section.)
This engine is super fussy about optimization levels and runtime checks. In particular, the Windows version absolutely positively must be compiled in Debug mode, with /RTC enabled. If you build in Release mode, or have /RTC disabled, the game behaves dramatically different in ways that were never fully documented (bizarre softlocks, out-of-bounds issues that don't show up in tools like Valgrind, stuff like that). There are lots of things about this old code that could be cleaned up, polished, rewritten, and so on, but this is the one that will probably bite you the hardest when setting up your own build, regardless of platform.
We hope you'll enjoy messing with the source anyway!
Love, flibit