1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-11-04 18:29:41 +01:00
Commit graph

66 commits

Author SHA1 Message Date
Misa
3699adec82 Fix, for in-GAMEMODE sprites, their colors updating too fast
Okay, so the problem here is that Graphics::setcol() is called right
before a sprite is drawn in a render function, but render functions are
done in deltatime, meaning that the color of a sprite keeps being
recalculated every time. This only affects sprites that use fRandom()
(the other thing that can dynamically determine a color is help.glow,
but that's only updated in the fixed-timestep loop), but is especially
noticeable for sprites that flash wildly, like the teleporter, trinket,
and elephant.

To fix this, we need to make the color be recalculated only in the
fixed-timestep loop. However, this means that we MUST store the color of
the sprite SOMEWHERE for the delta-timesteps to render it, otherwise the
color calculation will just be lost or something.

So each entity now has a new attribute, `realcol`, which is the actual
raw color used to render the sprite in render functions. This is not to
be confused with their `colour` attribute, which is more akin to a color
"ID" of sorts, but which isn't an actual color.

At the end of gamelogic(), as well as when an entity is first created,
the `colour` is given to Graphics::setcol() and then `realcol` gets set
to the actual color. Then when it comes time to render the entity,
`realcol` gets used instead.

Gravitron squares are a somewhat tricky case where there's technically
TWO colors for it - one is the actual sprite itself and the other is the
indicator. However, usually the indicator and the square aren't both
onscreen at the same time, so we can simply switch the realcol between
the two as needed.

However, we can't use this system for the sprite colors used on the
title and map screen, so we'll have to do something else for those.
2020-06-19 09:05:48 -04:00
Misa
2e17e872e4 Interpolate spikeleveltop and spikelevelbottom
This doesn't have much effect, except for when the spikes quickly move,
because the spikes only usually move at 1 pixel per frame anyway.
2020-06-19 09:05:48 -04:00
Misa
92c0f93a6f Move finalstretch animation code to gamelogic()
Otherwise, the tile animations will go too fast. However, the overall
color cycling hasn't been going fast, since it was never in gamerender()
in the first place.
2020-06-19 09:05:48 -04:00
Misa
fe1045b515 Interpolate tower scrolling
Now tower scrolling will look smooth ayy-eff.
2020-06-19 09:05:48 -04:00
Misa
880465c2e5 Fix credits position being 1 frame off w/ BG when press/release ACTION
When you pressed and released ACTION to speed up the credits, the
credits position would end up being 1 frame off from the background.

This is due to the fact that we update the tower background after we
update the credits position, so this commit moves the tower background
update before the credits position update.
2020-06-19 09:05:48 -04:00
Misa
b4142976f2 Move crewframedelay to titlelogic() and maplogic()
Incidentally enough, this de-duplicates the amount of times this code
has been copy-pasted from 4 times to 2.

Anyways, this makes it so the crew don't go lightning fast on the
summary screen, the NDM game-over screen, the NDM win screen, and the
pause screen in the main game. It was slightly hilarious seeing them go
really quickly, actually. It was like they were running away from a
giant monster or something.
2020-06-19 09:05:48 -04:00
Misa
1d669dffeb Interpolate "- Press ENTER to Teleport -" prompt
This is only really noticeable in slowmode, but if you're playing in
slowmode it'll be pretty smooth.
2020-06-19 09:05:48 -04:00
Misa
dcc9520d8f Interpolate trophy text
Just to make sure it's extra smooth. Not that it will be noticeable, and
you can't access the Secret Lab in slowmode without modifying the game,
but it's nice to have this.
2020-06-19 09:05:48 -04:00
Misa
118401f17e Move tower background update code to logic functions
Otherwise it'll go really really quickly, which is not good.
2020-06-19 09:05:48 -04:00
Misa
f53ed222d3 Interpolate activity zone prompt fading in and out
To make it real smooth, just in case it was noticeable that it only
updated at 1000/34 FPS before (well, except in slowmode, it's really
noticeable THERE).

Also this removes the re-typing out of (game.act_fade/10.0f) for every
single R, G, and B in gamerender().
2020-06-19 09:05:48 -04:00
Misa
4ba9954eb8 Move cursor delay update logic to maplogic()
Otherwise it'll go really really fast.

Incidentally this also basically de-duplicates it and results in less
copy-pasted code overall.
2020-06-19 09:05:48 -04:00
Misa
837ccfc735 Move gravity line color updating to gamelogic()
So it doesn't keep updating really quickly.
2020-06-19 09:05:48 -04:00
Misa
3b41721563 Interpolate bringing up and down quit/pause/teleporter screen
Now it's really, really smooth. Except for like the last frame when it
goes down, which I sometimes didn't notice (but maybe it didn't happen
every time due to being lucky on the delta timesteps or something,
whatevs.)
2020-06-19 09:05:48 -04:00
Misa
45c7292096 Simplify menu-off rendering/logic code
Since "if (graphics.resumegamemode)" and "if (menuoffset > 0)" both do
the same thing, they've been combined with an "or" conjunction.

As well, the map.extrarow check in maplogic() has been refactored to use
a variable instead of duplicating the entire code block. Not that it
matters anyway, because the difference between 240 and 230 is only 10
pixels, far short of the 25 pixel increment that bringing the menu up
and down uses, and both 240 and 230 integer-divided by 25 have the same
non-remainder value of 9.
2020-06-19 09:05:48 -04:00
Misa
a22a872886 Move menu offset logic to maplogic()
This is the logic that handles the timer that brings up and down the
teleporter, pause screen, and Esc screen. So now it doesn't go crazy
fast.
2020-06-19 09:05:48 -04:00
Misa
55ae3c73a9 Update left-moving star BG in fixed timestep loop
Otherwise they will move too fast.
2020-06-19 09:05:48 -04:00
Misa
495bea2e87 Update text boxes in the inner fixed-timestep loop
So they don't go really quickly.
2020-06-19 09:05:48 -04:00
Misa
905696c263 Update trophy text timer in fixed-timestep gamelogic()
Otherwise it, too, goes by too quickly.
2020-06-19 09:05:48 -04:00
Misa
92ee33043d Update activity prompt fade in fixed-timestep gamelogic()
Otherwise it goes by too quickly.
2020-06-19 09:05:48 -04:00
Misa
2510d3a6ba Interpolate cutscene bars position
Cutscene bars will now smoothly fade in and out at above 30 FPS instead
of at 30 FPS only.
2020-06-19 09:05:48 -04:00
Misa
a479c61141 Simplify "else if" indentation for right-side tower screen wrapping
No need to make an entire else-block and indent it when you can just do
"else if" instead.
2020-06-19 09:05:48 -04:00
Misa
a7b62d1098 Update oldxp/oldyp when screen wrapping
This is so it doesn't look like entities "zip" across the room.
2020-06-19 09:05:48 -04:00
Misa
298aa95259 Move onground/onroof/animateentities logic to start of gamelogic()
For some reason, it was put near the start of gamerender(), even though
since it handles edge-flipping it seems like it should be in the logic
function already.

This makes sure entity animations don't animate as fast as possible, and
also fixes edge-flipping on normal surfaces.
2020-06-19 09:05:48 -04:00
Misa
44bd4ec0b7 Fix custom assets not being unmounted when exiting from editor/credits
If you exited from the editor, custom assets would not be unmounted. But
I made sure to put the FILESYSTEM_unmountassets() before the
music.play(6) because otherwise the menu music wouldn't play.

You could also exit to the menu from a custom level using the
rollcredits() command, so I made sure to put a
FILESYSTEM_unmountassets() when returning to the menu from the credits
as well. I also made sure to put it before the music.playef(18) so
there's no risk of the sound effect not playing properly, or not playing
the non-level-specific one.

I added a comment to both FILESYSTEM_unmountasset()s to make sure anyone
reading the code is aware of the frame order dependency.
2020-06-17 06:02:26 -04:00
Misa
fdce412680 Guard all cases obj.getcompanion() is used unchecked
And this the function with the least amount of cases where its sentinel
value is used unchecked. Thankfully. obj.getplayer() was a bit of a slug
to get through.
2020-06-12 23:55:48 -04:00
Misa
beab344267 Guard all cases obj.getplayer() is used unchecked
obj.getplayer() can return -1, which can cause out-of-bounds indexing of
obj.entities, which is really bad. This was by far the most changes, as
obj.getplayer() is the most used entity-getting function that returns
-1, as well as the most-used function whose sentinel value goes
unchecked.

To deal with the usage of obj.getplayer() in mapclass::warpto(), I just
added general bounds checks inside that function instead of changing all
the callers.
2020-06-12 23:55:48 -04:00
Misa
3a5dd5a616 Clean up all scriptclass externs into one location
I have the feeling that none of the devs understood what extern did, and
they kind of just sprinkled it everywhere until things started working.
But like all other classes, it should just be one line in the class's
respective header file, and shouldn't be so messy.
2020-05-22 09:46:12 -04:00
Misa
2d07090a6b Move returning to editor to end of frame
This fixes horizontal and vertical warp backgrounds not resetting, and
also a bunch of other 1-frame glitches, most noticeably cutscene bars
and fadeouts.

This adds a new variable shouldreturntoeditor to Game to signal whether
or not it should return to editor at the end of the frame.
2020-05-09 16:40:01 -04:00
Misa
269ad18b86 Call game.savestats() when setting new Super Gravitron record
This is to be extra safe and ensure that your hard-earned record isn't
lost at all.

In 2.2, the game didn't save your Super Gravitron record at all. It only
saved it if you closed the game by quitting to the title screen and
pressing ACTION on "quit game". You couldn't press Alt+F4, and you
couldn't press X, you had to do it that way, otherwise your record would
be lost.

In 2.3 right now, the game WILL save your unlock.vvv when you close the
game gracefully by any means, but this still means that if it doesn't
otherwise close gracefully (like, say, a crash), it won't save your
record. It feels like we shouldn't rely on this catch-all saving to save
Super Gravitron records.
2020-05-09 15:07:41 -04:00
Misa
f585d53955 Fix flag 67 turning on too early
Flag 67 seems to be a general-purpose Game Complete flag. It's used to
replace the CREW option with the SHIP option on the pause screen.

Unfortunately, it gets turned on too early during Game Complete. Right
when Viridian starts to teleport, you can bring up the pause screen and
select the SHIP option.

It will teleport you to the ship coordinates, but still keep you in
finalmode, and since the ship coordinates are at 102,111 (finalmode is
only around 46,54), you'll still be stuck in Outside Dimension VVVVVV,
and you've interrupted the Game Complete gamestate by switching to the
teleporting gamestate. Oh, and your checkpoint is set, too, so you can't
even press R. Oh and since there's no teleporter, and checkpoint setting
doesn't check the sentinel value, this results in Undefined Behavior,
too.

So this results in an in-game softlock. The only option you can do is
quit the game at this point.

To fix this issue, just move turning on flag 67 before the savetele() in
gamecompletelogic2().
2020-05-09 14:55:24 -04:00
Misa
ce1e212317 Prevent updating an entity if updateentities() removed it
Otherwise, this would result in the game updating an entity twice, which
isn't good. This is most noticeable in the Gravitron, where many
Gravitron squares are created and destroyed at a time, and it's
especially noticeable during the part near the end of the Gravitron
where the pattern is two Gravitron squares, one at the top and bottom,
and then two Gravitron squares in the middle afterwards. The timing is
just right such that the top one of the two middle ones would be
misaligned with the bottom one of the two when a Gravitron square gets
outside the screen.

To do this, I changed entityclass::updateentities() into a bool, and
made every single caller check its return value. I only needed to do
this for the ones preceding updateentitylogic() and
entitymapcollision(), but I wanted to play it safe and be defensive, so
I did it for the disappearing platform kludge, as well as the
updateentities() within the updateentities() function.
2020-05-05 17:22:47 -04:00
Misa
3c80d136e4 Add towermode checks to minitowermode screen transitions
Apparently, the game just leaves minitowermode on, which can cause
issues if you're in a horizontal warping room (and not any other room
type, due to how frame ordering works). This would manifest itself as a
wrong warp to (20,20) because the game is trying to apply the hardcoded
minitower screen transitions when it shouldn't be.
2020-05-05 14:39:02 -04:00
Misa
f78603ef87 Fix menu that you land on when you complete game or custom level
When you complete the game, you're now redirected to the play menu. This
is because your quicksave will have been deleted so you can't go back to
the summary menu.

When you complete a custom level, you'll go back to the levels list, in
case you started the level from a quicksave.
2020-05-02 23:47:37 -04:00
Misa
192b2f2dba Don't re-draw credits scroll background every frame
While I was working on my over-30-FPS patch, I found out that the tower
background in the credits scroll was being completely re-drawn every
single frame, which was a bit wasteful and expensive. It's also harder
to interpolate for my over-30-FPS patch. I'm guessing this constant
re-draw was done because the math to get the surface scroll properly
working is a bit subtle, but I've figured the precise math out!

The first changes of this patch is just removing the unconditional
`map.tdrawback = true;`, and having to set `map.scrolldir` everywhere to
get the credits scrolling in the right direction but make sure the title
screen doesn't start scrolling like a descending tower, too.

After that, the first problem is that it looks like the ACTION press to
speed up the credits scrolling doesn't speed up the background, too. No
problem, just shove a `!game.press_action` check in
`gamecompletelogic()`.

However, this introduces a mini-problem, which is that NOW when you hold
down ACTION, the background appears to be slowly getting out of sync
with the credits text by a one-pixel-per-second difference. This is
actually due to the fact that, as a result of me adding the conditional,
`map.bscroll` is no longer always unconditionally getting set to 1,
while `game.creditposition` IS always unconditionally getting
decremented by 1. And when you hold down ACTION, `game.creditposition`
gets decremented by 6.

Thus, I need to set `map.bscroll` when holding down ACTION to be 7,
which is 6 plus 1.

Then we have another problem, which is that the incoming textures desync
when you press ACTION, and when you release ACTION. They desync by
precisely 6 pixels, which should be a familiar number. I (eventually)
tracked this down to `map.bypos` being updated at the same time
`map.bscroll` is, even though `map.bypos` should be updated a frame
later AFTER updating `map.bscroll`.

So I had to change the `map.bypos` update in `gamecompleteinput()` and
`gamecompletelogic()` to be `map.bypos += map.bscroll;` and then place
it before any `map.bscroll` update, thus ensuring that `map.bscroll`
updates exactly one frame before `map.ypos` does. I had to move the
`map.bypos += map.bscroll;` to be in `gamecompleteinput()`, because
`gamecompleteinput()` comes first before `gamecompletelogic()` in the
`main.cpp` game loop, otherwise the `map.bypos` update won't be delayed
by one frame for when you press ACTION to make it go faster, and thus
cause a desync when you press ACTION.

Oh and then after that, I had to make the descending tower background
draw a THIRD row of incoming tiles, otherwise you could see some black
flickering at the bottom of the screen when you held down ACTION.

All of this took me way too long to figure out, but now the credits
scroll works perfectly while being more optimized.
2020-04-30 05:04:13 -04:00
Misa
c040ceda29 Merge towerlogic() into gamelogic()
This doesn't change anything functionality-wise, but it does remove a
lot of duplicate code, which makes it easier to work on.
2020-04-26 19:07:40 -04:00
Misa
e909515f3d Don't go to main menu when exiting to menu
This also replaces some createmenu()s with returnmenu()s as needed even
when said createmenu()s already didn't go to the main menu.

Now when you exit the level editor, you'll be selecting the "level
editor" option in "play levels", and if you exit from a level you'll
still be selecting that level in the levels list.

Furthermore, regardless of what you're exiting, your cursor position
will be remembered.
2020-04-17 15:41:48 -04:00
Misa
4d9c834a13 Change gamestate ints to their enum names
This is to make it easier to read, so I don't have to reference Enums.h
if I want to know what they are referring to.
2020-04-17 15:41:48 -04:00
Misa
e8a07f9c3d Convert menu names to be an enum instead of being stringly-typed
Stringly-typed things are bad, because if you make a typo when typing
out a string, it's not caught at compile-time. And in the case of this
menu system, you'd have to do an excessive amount of testing to uncover
any bugs caused by a typo. Why do that when you can just use an enum and
catch compile-time errors instead?

Also, you can't use switch-case statements on stringly-typed variables.

So every menu name is now in the enum Menu::MenuName, but you can simply
refer to a menu name by just prefixing it with Menu::.

Unfortunately, I've had to change the "continue" menu name to be
"continuemenu", because "continue" is a keyword in C and C++. Also, it
looks like "timetrialcomplete4" is an unused menu name, even though it
was referenced in Render.cpp.
2020-04-17 15:41:48 -04:00
Misa
abfae6b4d7 Declare obj.flags a vector of bools instead of ints
It's treated like a bool anyway, so might as well make it one.

This also necessitates updating every single instance where it or an
element inside it is used, too.
2020-04-09 19:20:31 -04:00
Misa
7f0db19abd Fix memory leak from warping moving platforms
It turns out that when the game warps moving platforms, it won't remove
the block from the position before they warped. Eventually, these blocks
will pile up and will never be removed, causing a memory leak.
2020-04-04 16:26:15 -04:00
Misa
79a54f23e6 De-dupe screen transition / warping logic
I noticed that the code for going to the adjacent room when offscreen
and for warping instead if the room is warping was a bit
copy-and-pasted. To clean up the code a bit, there's now 5 separate
checks in gamelogic():

if (map.warpx)
if (map.warpy)
if (map.warpy && !map.warpx)
if (!map.warpy)
if (!map.warpx)

I made sure to preserve the previous weird horizontal warping behavior
that happens with vertical warping (thus the middle one), and to
preserve the frame ordering just in case there's something dependent on
the frame ordering.

The frame ordering is that first it will warp you horizontally, if
applicable, then it will warp you vertically, if applicable. Then if you
have vertical warping only, that weird horizontal warp. Then it will
screen transition you vertically, if applicable. Then it will screen
transition you horizontally, if applicable.

To explain the weird horizontal warp with the vertical warp: apparently
if an entity is far offscreen enough, and if that entity is not the
player, it will be warped horizontally during a vertical warp. The
points at which it will warp is 30 pixels farther out than normal
horizontal warping.

I think someone ran into this before, but my memory is fuzzy. The best I
can recall is that they were probably createentity()ing a high-speed
horizontally-moving enemy in a vertically warping room, only to discover
that said enemy kept warping horizontally.
2020-04-04 16:26:15 -04:00
Misa
7899cb8088 Condense some nested else-if statements
It's better to write 'else if' than 'else { if }'.
2020-04-04 16:26:15 -04:00
Misa
e6c6c7cf60 Condense some nested if-statements in gamelogic()
It's better to write if (cond1 && cond2) than it is to write if (cond1)
{ if (cond2) }.
2020-04-04 16:26:15 -04:00
Misa
3818340011 Clean up some indentation in gamelogic()
This is just a miscellaneous indentation cleanup to fix some places
where it is indented with 2 spaces instead of 4.
2020-04-04 16:26:15 -04:00
Misa
744c685614 Remove entityclass::cleanup()
This function's sole purpose was to make sure obj.nentity was in sync,
and that obj.nentity-1 pointed to the last 'active' entity in
obj.entities. But now that obj.nentity is removed and we use
obj.entities.size() instead, it is no longer necessary.
2020-04-03 23:28:47 -04:00
Misa
b1b1474b7b Refactor entities and linecrosskludge to not use the 'active' system
This removes the variables obj.nentity and obj.nlinecrosskludge, as well
as removing the 'active' attribute from the entity class object. Now
every entity you access is guaranteed to be real and you don't have to
check the 'active' variable.

The biggest part of this is changing createentity() to modify a
newly-created entity object and push it back instead of already
modifying an indice in obj.entities.

As well, removing an entity now uses the new obj.removeentity() function
and removeentity_iter() macro.
2020-04-03 23:28:47 -04:00
Misa
04d14000ec Remove global 'temp' variable from titlerender.cpp
Just a miscellaneous code cleanup.

There's no glitches that take advantage of the previous situation,
namely that 'temp' was a global variable in Logic.cpp and editor.cpp.
Even if there were, it seems like it would easily lead to some undefined
behavior. So it's good to clean this up.
2020-04-03 10:40:50 -04:00
Misa
d13c24b9b0 Realign logic update trio comments
This is the "Behavioral logic", "Basic Physics", and "Collisions with
walls" trio.

They were originally aligned but then I removed global args, thus
misaligning them. So now I'm re-aligning them back again.
2020-04-03 10:40:50 -04:00
Misa
07573ad738 Remove outdated comments from Logic.cpp
Earlier design decisions that have been commented out and are now
obselete.
2020-04-03 10:40:50 -04:00
Misa
e56b0d9f39 Fix mixed indentation in Logic.cpp
It's clear that there was another person who added achievements and did
some warp line stuff.
2020-04-03 10:40:50 -04:00