2020-09-28 04:15:06 +02:00
|
|
|
#define GRAPHICS_DEFINITION
|
2020-01-01 21:29:24 +01:00
|
|
|
#include "Graphics.h"
|
2020-07-19 21:43:29 +02:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <utf8/unchecked.h>
|
|
|
|
|
2020-07-19 21:05:41 +02:00
|
|
|
#include "editor.h"
|
2020-01-01 21:29:24 +01:00
|
|
|
#include "Entity.h"
|
2021-02-16 03:53:17 +01:00
|
|
|
#include "Exit.h"
|
2020-07-19 21:43:29 +02:00
|
|
|
#include "FileSystemUtils.h"
|
2020-01-01 21:29:24 +01:00
|
|
|
#include "Map.h"
|
2020-07-19 21:05:41 +02:00
|
|
|
#include "Music.h"
|
2020-01-01 21:29:24 +01:00
|
|
|
#include "Screen.h"
|
2020-07-19 21:05:41 +02:00
|
|
|
#include "UtilityClass.h"
|
2020-01-01 21:29:24 +01:00
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::init(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
flipmode = false;
|
|
|
|
setRect(tiles_rect, 0,0,8,8);
|
|
|
|
setRect(sprites_rect, 0,0,32,32);
|
|
|
|
setRect(bfont_rect, 0,0,8,8);
|
|
|
|
setRect(bg_rect, 0,0,320,240);
|
|
|
|
setRect(footerrect, 0, 230, 320, 10);
|
|
|
|
setRect(prect, 0, 0, 4, 4);
|
|
|
|
setRect(line_rect, 0,0,0,0);
|
|
|
|
setRect(tele_rect,0,0,96,96);
|
2020-11-02 19:44:53 +01:00
|
|
|
setRect(towerbuffer_rect, 8, 8, 320, 240);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
//We initialise a few things
|
|
|
|
|
2020-04-02 22:05:48 +02:00
|
|
|
linestate = 0;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
trinketcolset = false;
|
|
|
|
|
|
|
|
showcutscenebars = false;
|
2021-03-20 07:08:35 +01:00
|
|
|
setbars(0);
|
2020-01-17 18:37:53 +01:00
|
|
|
notextoutline = false;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
flipmode = false;
|
|
|
|
setflipmode = false;
|
|
|
|
|
|
|
|
//Background inits
|
2020-07-03 11:31:13 +02:00
|
|
|
for (int i = 0; i < numstars; i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
SDL_Rect s = {Sint16(fRandom() * 320), Sint16(fRandom() * 240), 2, 2};
|
|
|
|
int s2 = 4+(fRandom()*4);
|
2020-07-03 11:31:13 +02:00
|
|
|
stars[i] = s;
|
|
|
|
starsspeed[i] = s2;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-07-03 11:31:13 +02:00
|
|
|
for (int i = 0; i < numbackboxes; i++)
|
|
|
|
{
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect bb;
|
|
|
|
int bvx = 0;
|
|
|
|
int bvy = 0;
|
|
|
|
if(fRandom()*100 > 50)
|
|
|
|
{
|
|
|
|
bvx = 9 - (fRandom() * 19);
|
|
|
|
if (bvx > -6 && bvx < 6) bvx = 6;
|
|
|
|
bvx = bvx * 1.5;
|
|
|
|
setRect(bb, fRandom() * 320, fRandom() * 240, 32, 12);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bvy = 9 - (fRandom() * 19);
|
|
|
|
if (bvy > -6 && bvy < 6) bvy = 6;
|
|
|
|
bvy = bvy * 1.5;
|
|
|
|
setRect(bb, fRandom() * 320, fRandom() * 240, 12, 32) ;
|
|
|
|
}
|
|
|
|
float bint = 0.5 + ((fRandom() * 100) / 200);
|
2020-07-03 11:31:13 +02:00
|
|
|
backboxes[i] = bb;
|
|
|
|
backboxvx[i] = bvx;
|
|
|
|
backboxvy[i] = bvy;
|
|
|
|
backboxint[i] = bint;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
backoffset = 0;
|
|
|
|
backgrounddrawn = false;
|
|
|
|
|
|
|
|
warpskip = 0;
|
|
|
|
warpfcol = 0x000000;
|
|
|
|
warpbcol = 0x000000;
|
|
|
|
|
|
|
|
spcol = 0;
|
|
|
|
spcoldel = 0;
|
2020-04-02 22:05:48 +02:00
|
|
|
rcol = 0;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
crewframe = 0;
|
|
|
|
crewframedelay = 4;
|
|
|
|
menuoffset = 0;
|
2020-04-29 05:46:33 +02:00
|
|
|
oldmenuoffset = 0;
|
2020-01-01 21:29:24 +01:00
|
|
|
resumegamemode = false;
|
|
|
|
|
|
|
|
//Fading stuff
|
2020-07-03 11:40:57 +02:00
|
|
|
SDL_memset(fadebars, 0, sizeof(fadebars));
|
2020-01-12 18:26:00 +01:00
|
|
|
|
2021-03-20 07:09:11 +01:00
|
|
|
setfade(0);
|
2020-01-01 21:29:24 +01:00
|
|
|
fademode = 0;
|
|
|
|
|
2020-01-11 01:37:23 +01:00
|
|
|
// initialize everything else to zero
|
2020-01-11 17:33:36 +01:00
|
|
|
backBuffer = NULL;
|
2020-01-12 18:26:00 +01:00
|
|
|
ct = colourTransform();
|
|
|
|
foot_rect = SDL_Rect();
|
2020-01-11 01:37:23 +01:00
|
|
|
foregrounddrawn = false;
|
2020-01-11 17:33:36 +01:00
|
|
|
foregroundBuffer = NULL;
|
2020-01-11 01:37:23 +01:00
|
|
|
backgrounddrawn = false;
|
2020-01-12 18:26:00 +01:00
|
|
|
images_rect = SDL_Rect();
|
2020-01-11 01:37:23 +01:00
|
|
|
m = 0;
|
|
|
|
linedelay = 0;
|
2020-01-11 17:33:36 +01:00
|
|
|
menubuffer = NULL;
|
|
|
|
screenbuffer = NULL;
|
|
|
|
tempBuffer = NULL;
|
2020-11-03 01:54:17 +01:00
|
|
|
warpbuffer = NULL;
|
|
|
|
warpbuffer_lerp = NULL;
|
2020-07-06 22:04:34 +02:00
|
|
|
footerbuffer = NULL;
|
|
|
|
ghostbuffer = NULL;
|
2020-11-03 00:05:24 +01:00
|
|
|
towerbg = TowerBG();
|
2020-11-03 00:23:53 +01:00
|
|
|
titlebg = TowerBG();
|
2020-01-11 01:37:23 +01:00
|
|
|
trinketr = 0;
|
|
|
|
trinketg = 0;
|
|
|
|
trinketb = 0;
|
2020-01-12 18:26:00 +01:00
|
|
|
warprect = SDL_Rect();
|
2020-01-25 05:43:04 +01:00
|
|
|
|
|
|
|
translucentroomname = false;
|
2020-01-29 08:17:13 +01:00
|
|
|
showmousecursor = true;
|
2020-04-29 01:02:55 +02:00
|
|
|
|
|
|
|
alpha = 1.0f;
|
2020-04-29 02:29:59 +02:00
|
|
|
|
|
|
|
screenshake_x = 0;
|
|
|
|
screenshake_y = 0;
|
2020-05-02 01:40:35 +02:00
|
|
|
|
|
|
|
col_crewred = 0x00000000;
|
|
|
|
col_crewyellow = 0x00000000;
|
|
|
|
col_crewgreen = 0x00000000;
|
|
|
|
col_crewcyan = 0x00000000;
|
|
|
|
col_crewblue = 0x00000000;
|
|
|
|
col_crewpurple = 0x00000000;
|
|
|
|
col_crewinactive = 0x00000000;
|
|
|
|
col_clock = 0x00000000;
|
|
|
|
col_trinket = 0x00000000;
|
|
|
|
col_tr = 0;
|
|
|
|
col_tg = 0;
|
|
|
|
col_tb = 0;
|
2020-05-02 21:06:40 +02:00
|
|
|
|
|
|
|
kludgeswnlinewidth = false;
|
Make one-way recolors check for specific files
So, 2.3 added recoloring one-way tiles to no longer make them be always
yellow. However, custom levels that retexture the one-way tiles might
not want them to be recolored. So, if there are ANY custom assets
mounted, then the one-ways will not be recolored. However, if the XML
has a <onewaycol_override>1</onewaycol_override> tag, then the one-way
will be recolored again anyways.
When I added one-way recoloring, I didn't intend for any custom asset to
disable the recoloring; I only did it because I couldn't find a way to
check if a specific file was customized by the custom level or not.
However, I have figured out how to do so, and so now tiles.png one-way
recolors will only be disabled if there's a custom tiles.png, and
tiles2.png one-way recolors will only be disabled if there's a custom
tiles2.png.
In order to make sure we're not calling PhysFS functions on every single
deltaframe, I've added caching variables, tiles1_mounted and
tiles2_mounted, to Graphics; these get assigned every time
reloadresources() is called.
2021-03-06 19:52:11 +01:00
|
|
|
|
|
|
|
#ifndef NO_CUSTOM_LEVELS
|
|
|
|
tiles1_mounted = false;
|
|
|
|
tiles2_mounted = false;
|
|
|
|
#endif
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::destroy(void)
|
2021-02-16 01:13:18 +01:00
|
|
|
{
|
|
|
|
#define CLEAR_ARRAY(name) \
|
|
|
|
for (size_t i = 0; i < name.size(); i += 1) \
|
|
|
|
{ \
|
|
|
|
SDL_FreeSurface(name[i]); \
|
|
|
|
} \
|
|
|
|
name.clear();
|
|
|
|
|
|
|
|
CLEAR_ARRAY(tiles)
|
|
|
|
CLEAR_ARRAY(tiles2)
|
|
|
|
CLEAR_ARRAY(tiles3)
|
|
|
|
CLEAR_ARRAY(entcolours)
|
|
|
|
CLEAR_ARRAY(sprites)
|
|
|
|
CLEAR_ARRAY(flipsprites)
|
|
|
|
CLEAR_ARRAY(tele)
|
|
|
|
CLEAR_ARRAY(bfont)
|
|
|
|
CLEAR_ARRAY(flipbfont)
|
|
|
|
|
|
|
|
#undef CLEAR_ARRAY
|
|
|
|
}
|
|
|
|
|
2021-02-16 01:18:45 +01:00
|
|
|
void Graphics::create_buffers(const SDL_PixelFormat* fmt)
|
|
|
|
{
|
|
|
|
#define CREATE_SURFACE(w, h) \
|
|
|
|
SDL_CreateRGBSurface( \
|
|
|
|
SDL_SWSURFACE, \
|
|
|
|
w, h, \
|
|
|
|
fmt->BitsPerPixel, \
|
|
|
|
fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask \
|
|
|
|
)
|
|
|
|
backBuffer = CREATE_SURFACE(320, 240);
|
|
|
|
SDL_SetSurfaceBlendMode(backBuffer, SDL_BLENDMODE_NONE);
|
|
|
|
|
|
|
|
footerbuffer = CREATE_SURFACE(320, 10);
|
|
|
|
SDL_SetSurfaceBlendMode(footerbuffer, SDL_BLENDMODE_BLEND);
|
|
|
|
SDL_SetSurfaceAlphaMod(footerbuffer, 127);
|
|
|
|
FillRect(footerbuffer, SDL_MapRGB(fmt, 0, 0, 0));
|
|
|
|
|
|
|
|
ghostbuffer = CREATE_SURFACE(320, 240);
|
|
|
|
SDL_SetSurfaceBlendMode(ghostbuffer, SDL_BLENDMODE_BLEND);
|
|
|
|
SDL_SetSurfaceAlphaMod(ghostbuffer, 127);
|
|
|
|
|
|
|
|
foregroundBuffer = CREATE_SURFACE(320, 240);
|
|
|
|
SDL_SetSurfaceBlendMode(foregroundBuffer, SDL_BLENDMODE_BLEND);
|
|
|
|
|
|
|
|
menubuffer = CREATE_SURFACE(320, 240);
|
|
|
|
SDL_SetSurfaceBlendMode(menubuffer, SDL_BLENDMODE_NONE);
|
|
|
|
|
|
|
|
warpbuffer = CREATE_SURFACE(320 + 16, 240 + 16);
|
|
|
|
SDL_SetSurfaceBlendMode(warpbuffer, SDL_BLENDMODE_NONE);
|
|
|
|
|
|
|
|
warpbuffer_lerp = CREATE_SURFACE(320 + 16, 240 + 16);
|
|
|
|
SDL_SetSurfaceBlendMode(warpbuffer_lerp, SDL_BLENDMODE_NONE);
|
|
|
|
|
|
|
|
towerbg.buffer = CREATE_SURFACE(320 + 16, 240 + 16);
|
|
|
|
SDL_SetSurfaceBlendMode(towerbg.buffer, SDL_BLENDMODE_NONE);
|
|
|
|
|
|
|
|
towerbg.buffer_lerp = CREATE_SURFACE(320 + 16, 240 + 16);
|
|
|
|
SDL_SetSurfaceBlendMode(towerbg.buffer_lerp, SDL_BLENDMODE_NONE);
|
|
|
|
|
|
|
|
titlebg.buffer = CREATE_SURFACE(320 + 16, 240 + 16);
|
|
|
|
SDL_SetSurfaceBlendMode(titlebg.buffer, SDL_BLENDMODE_NONE);
|
|
|
|
|
|
|
|
titlebg.buffer_lerp = CREATE_SURFACE(320 + 16, 240 + 16);
|
|
|
|
SDL_SetSurfaceBlendMode(titlebg.buffer_lerp, SDL_BLENDMODE_NONE);
|
|
|
|
|
|
|
|
tempBuffer = CREATE_SURFACE(320, 240);
|
|
|
|
SDL_SetSurfaceBlendMode(tempBuffer, SDL_BLENDMODE_NONE);
|
|
|
|
|
|
|
|
#undef CREATE_SURFACE
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::destroy_buffers(void)
|
2021-02-16 01:16:52 +01:00
|
|
|
{
|
|
|
|
#define FREE_SURFACE(SURFACE) \
|
|
|
|
SDL_FreeSurface(SURFACE); \
|
|
|
|
SURFACE = NULL;
|
|
|
|
|
|
|
|
FREE_SURFACE(backBuffer)
|
|
|
|
FREE_SURFACE(footerbuffer)
|
|
|
|
FREE_SURFACE(ghostbuffer)
|
|
|
|
FREE_SURFACE(foregroundBuffer)
|
|
|
|
FREE_SURFACE(menubuffer)
|
|
|
|
FREE_SURFACE(warpbuffer)
|
|
|
|
FREE_SURFACE(warpbuffer_lerp)
|
|
|
|
FREE_SURFACE(towerbg.buffer)
|
|
|
|
FREE_SURFACE(towerbg.buffer_lerp)
|
|
|
|
FREE_SURFACE(titlebg.buffer)
|
|
|
|
FREE_SURFACE(titlebg.buffer_lerp)
|
|
|
|
FREE_SURFACE(tempBuffer)
|
|
|
|
|
|
|
|
#undef FREE_SURFACE
|
|
|
|
}
|
|
|
|
|
2021-02-16 01:21:27 +01:00
|
|
|
int Graphics::font_idx(uint32_t ch)
|
|
|
|
{
|
|
|
|
if (font_positions.size() > 0)
|
|
|
|
{
|
2020-01-31 19:25:37 +01:00
|
|
|
std::map<int, int>::iterator iter = font_positions.find(ch);
|
2021-02-16 01:21:27 +01:00
|
|
|
if (iter == font_positions.end())
|
|
|
|
{
|
2020-01-31 19:25:37 +01:00
|
|
|
iter = font_positions.find('?');
|
2021-02-16 01:21:27 +01:00
|
|
|
if (iter == font_positions.end())
|
|
|
|
{
|
2020-01-31 19:25:37 +01:00
|
|
|
puts("font.txt missing fallback character!");
|
2021-02-16 03:53:17 +01:00
|
|
|
VVV_exit(1);
|
2020-01-31 19:25:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return iter->second;
|
2021-02-16 01:21:27 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-01-31 19:25:37 +01:00
|
|
|
return ch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-31 21:26:11 +02:00
|
|
|
void Graphics::drawspritesetcol(int x, int y, int t, int c)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, sprites))
|
2020-06-14 03:35:12 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect;
|
|
|
|
setRect(rect,x,y,sprites_rect.w,sprites_rect.h);
|
2020-03-31 21:26:11 +02:00
|
|
|
setcol(c);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
BlitSurfaceColoured(sprites[t],NULL,backBuffer, &rect, ct);
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::updatetitlecolours(void)
|
2020-05-02 01:40:35 +02:00
|
|
|
{
|
|
|
|
setcol(15);
|
|
|
|
col_crewred = ct.colour;
|
|
|
|
setcol(14);
|
|
|
|
col_crewyellow = ct.colour;
|
|
|
|
setcol(13);
|
|
|
|
col_crewgreen = ct.colour;
|
|
|
|
setcol(0);
|
|
|
|
col_crewcyan = ct.colour;
|
|
|
|
setcol(16);
|
|
|
|
col_crewblue = ct.colour;
|
|
|
|
setcol(20);
|
|
|
|
col_crewpurple = ct.colour;
|
|
|
|
setcol(19);
|
|
|
|
col_crewinactive = ct.colour;
|
|
|
|
|
|
|
|
setcol(18);
|
|
|
|
col_clock = ct.colour;
|
|
|
|
setcol(18);
|
|
|
|
col_trinket = ct.colour;
|
|
|
|
}
|
|
|
|
|
Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.
This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)
Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:59:47 +02:00
|
|
|
#define PROCESS_TILESHEET_CHECK_ERROR(tilesheet, tile_square) \
|
|
|
|
if (grphx.im_##tilesheet->w % tile_square != 0 \
|
|
|
|
|| grphx.im_##tilesheet->h % tile_square != 0) \
|
|
|
|
{ \
|
|
|
|
const char* error = "Error: %s.png dimensions not exact multiples of %i!"; \
|
|
|
|
char message[128]; \
|
|
|
|
SDL_snprintf(message, sizeof(message), error, #tilesheet, tile_square); \
|
|
|
|
\
|
|
|
|
const char* error_title = "Error with %s.png"; \
|
|
|
|
char message_title[128]; \
|
|
|
|
SDL_snprintf(message_title, sizeof(message_title), error_title, #tilesheet); \
|
|
|
|
\
|
|
|
|
puts(message); \
|
|
|
|
\
|
|
|
|
SDL_ShowSimpleMessageBox( \
|
|
|
|
SDL_MESSAGEBOX_ERROR, \
|
|
|
|
message_title, \
|
|
|
|
message, \
|
|
|
|
NULL \
|
|
|
|
); \
|
|
|
|
\
|
2021-02-16 03:53:17 +01:00
|
|
|
VVV_exit(1); \
|
Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.
This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)
Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:59:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#define PROCESS_TILESHEET_RENAME(tilesheet, vector, tile_square, extra_code) \
|
|
|
|
PROCESS_TILESHEET_CHECK_ERROR(tilesheet, tile_square) \
|
|
|
|
\
|
|
|
|
for (int j = 0; j < grphx.im_##tilesheet->h / tile_square; j++) \
|
|
|
|
{ \
|
|
|
|
for (int i = 0; i < grphx.im_##tilesheet->w / tile_square; i++) \
|
|
|
|
{ \
|
|
|
|
SDL_Surface* temp = GetSubSurface( \
|
|
|
|
grphx.im_##tilesheet, \
|
|
|
|
i * tile_square, j * tile_square, \
|
|
|
|
tile_square, tile_square \
|
|
|
|
); \
|
|
|
|
vector.push_back(temp); \
|
|
|
|
\
|
|
|
|
extra_code \
|
|
|
|
} \
|
Free base tilesheet image after processing it
This isn't a memory leak (not even Valgrind complains), because it gets
properly cleaned up in GraphicsResources::destroy(). Still, it's memory
that is just laying around not being used, and in the name of
deallocating things as soon as you no longer need them, we should
deallocate the base tilesheet images after we split all of them into
tiles.
This reduces the memory cost of all tilesheet images by half, since we
were essentially keeping around duplicates for nothing; this doesn't
really have much of an impact with conventional tilesheet sizes, since
they're usually small enough, but since 2.3 allowed for tilesheet images
of any size, this is a pretty big deal for really big tilesheet images.
It's okay to do this, even though they also get freed in
GraphicsResources::destroy(), because SDL_FreeSurface() does a NULL
check on the pointer passed to it, and we set the pointer to NULL after
freeing the surfaces.
2021-02-16 03:07:33 +01:00
|
|
|
} \
|
|
|
|
\
|
|
|
|
SDL_FreeSurface(grphx.im_##tilesheet); \
|
|
|
|
grphx.im_##tilesheet = NULL;
|
Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.
This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)
Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:59:47 +02:00
|
|
|
|
|
|
|
#define PROCESS_TILESHEET(tilesheet, tile_square, extra_code) \
|
|
|
|
PROCESS_TILESHEET_RENAME(tilesheet, tilesheet, tile_square, extra_code)
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::Makebfont(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.
This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)
Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:59:47 +02:00
|
|
|
PROCESS_TILESHEET(bfont, 8,
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.
This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)
Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:59:47 +02:00
|
|
|
SDL_Surface* TempFlipped = FlipSurfaceVerticle(temp);
|
|
|
|
flipbfont.push_back(TempFlipped);
|
|
|
|
})
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-01-31 19:25:37 +01:00
|
|
|
unsigned char* charmap = NULL;
|
|
|
|
size_t length;
|
|
|
|
FILESYSTEM_loadFileToMemory("graphics/font.txt", &charmap, &length);
|
2020-09-25 21:55:12 +02:00
|
|
|
if (charmap != NULL)
|
|
|
|
{
|
2020-01-31 19:25:37 +01:00
|
|
|
unsigned char* current = charmap;
|
|
|
|
unsigned char* end = charmap + length;
|
|
|
|
int pos = 0;
|
2020-09-25 21:55:12 +02:00
|
|
|
while (current != end)
|
|
|
|
{
|
2020-01-31 19:25:37 +01:00
|
|
|
int codepoint = utf8::unchecked::next(current);
|
|
|
|
font_positions[codepoint] = pos;
|
|
|
|
++pos;
|
|
|
|
}
|
2020-06-07 22:29:48 +02:00
|
|
|
FILESYSTEM_freeMemory(&charmap);
|
2020-09-25 21:55:12 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-09-25 21:52:34 +02:00
|
|
|
font_positions.clear();
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-01-31 19:25:37 +01:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-09-25 21:55:12 +02:00
|
|
|
int Graphics::bfontlen(uint32_t ch)
|
|
|
|
{
|
|
|
|
if (ch < 32)
|
|
|
|
{
|
2020-01-31 19:25:37 +01:00
|
|
|
return 6;
|
2020-09-25 21:55:12 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-01-31 19:25:37 +01:00
|
|
|
return 8;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::MakeTileArray(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.
This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)
Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:59:47 +02:00
|
|
|
PROCESS_TILESHEET(tiles, 8, )
|
|
|
|
PROCESS_TILESHEET(tiles2, 8, )
|
|
|
|
PROCESS_TILESHEET(tiles3, 8, )
|
|
|
|
PROCESS_TILESHEET(entcolours, 8, )
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::maketelearray(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.
This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)
Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:59:47 +02:00
|
|
|
PROCESS_TILESHEET_RENAME(teleporter, tele, 96, )
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::MakeSpriteArray(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.
This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)
Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:59:47 +02:00
|
|
|
PROCESS_TILESHEET(sprites, 32, )
|
|
|
|
PROCESS_TILESHEET(flipsprites, 32, )
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Refactor, de-duplicate, and clean up tilesheet processing
The tilesheets in question are font.png, tiles.png, tiles2.png,
tiles3.png, entcolours.png, teleporter.png, sprites.png, and
flipsprites.png.
This patch removes the hardcoded dimensions when scanning the
tilesheets, because it's simpler that way. It also de-duplicates it so
it isn't a bunch of copy-paste, by using macros. (I had to use macros
because it was the easiest way to optionally pass in some extra code in
the innermost for-loop.)
Also, if the dimensions of a scanned tilesheet aren't exactly multiples
of the dimensions of the tile unit for that given tilesheet (e.g. if the
dimensions of a scanned tiles.png are not exact multiples of 8), then an
SDL_SimpleMessageBox will show up with the error message, a puts() of
the error message will be called, and the program will exit.
2020-06-28 08:59:47 +02:00
|
|
|
#undef PROCESS_TILESHEET
|
|
|
|
#undef PROCESS_TILESHEET_RENAME
|
|
|
|
#undef PROCESS_TILESHEET_CHECK_ERROR
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-06-21 03:33:55 +02:00
|
|
|
void Graphics::map_tab(int opt, const std::string& text, bool selected /*= false*/)
|
|
|
|
{
|
|
|
|
int x = opt*80 + 40 - len(text)/2;
|
|
|
|
if (selected)
|
|
|
|
{
|
|
|
|
Print(x-8, 220, "[" + text + "]", 196, 196, 255 - help.glow);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Print(x, 220, text, 64, 64, 64);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-23 00:23:15 +02:00
|
|
|
void Graphics::map_option(int opt, int num_opts, const std::string& text, bool selected /*= false*/)
|
|
|
|
{
|
|
|
|
int x = 80 + opt*32;
|
|
|
|
int y = 136; // start from middle of menu
|
|
|
|
|
|
|
|
int yoff = -(num_opts * 12) / 2; // could be simplified to -num_opts * 6, this conveys my intent better though
|
|
|
|
yoff += opt * 12;
|
|
|
|
|
|
|
|
if (flipmode)
|
|
|
|
{
|
|
|
|
y -= yoff; // going down, which in Flip Mode means going up
|
|
|
|
y -= 40;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y += yoff; // going up
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selected)
|
|
|
|
{
|
2020-06-23 03:29:52 +02:00
|
|
|
std::string text_upper(text);
|
2020-07-03 23:54:23 +02:00
|
|
|
for (size_t i = 0; i < text_upper.length(); i++)
|
|
|
|
{
|
|
|
|
text_upper[i] = SDL_toupper(text_upper[i]);
|
|
|
|
}
|
2020-06-23 03:29:52 +02:00
|
|
|
Print(x - 16, y, "[ " + text_upper + " ]", 196, 196, 255 - help.glow);
|
2020-06-23 00:23:15 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Print(x, y, text, 96, 96, 96);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 03:23:12 +01:00
|
|
|
void Graphics::Print( int _x, int _y, std::string _s, int r, int g, int b, bool cen /*= false*/ ) {
|
|
|
|
return PrintAlpha(_x,_y,_s,r,g,b,255,cen);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::PrintAlpha( int _x, int _y, std::string _s, int r, int g, int b, int a, bool cen /*= false*/ )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-06-14 03:46:32 +02:00
|
|
|
std::vector<SDL_Surface*>& font = flipmode ? flipbfont : bfont;
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
r = clamp(r,0,255);
|
|
|
|
g = clamp(g,0,255);
|
|
|
|
b = clamp(b,0,255);
|
2020-02-10 03:23:12 +01:00
|
|
|
a = clamp(a,0,255);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-02-10 03:23:12 +01:00
|
|
|
ct.colour = getRGBA(r, g, b, a);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
if (cen)
|
|
|
|
_x = ((160 ) - ((len(_s)) / 2));
|
|
|
|
int bfontpos = 0;
|
|
|
|
int curr;
|
2020-06-14 03:56:59 +02:00
|
|
|
int idx;
|
2020-01-31 19:25:37 +01:00
|
|
|
std::string::iterator iter = _s.begin();
|
|
|
|
while (iter != _s.end()) {
|
|
|
|
curr = utf8::unchecked::next(iter);
|
2020-01-01 21:29:24 +01:00
|
|
|
point tpoint;
|
|
|
|
tpoint.x = _x + bfontpos;
|
|
|
|
tpoint.y = _y;
|
|
|
|
|
|
|
|
SDL_Rect fontRect = bfont_rect;
|
|
|
|
fontRect.x = tpoint.x ;
|
|
|
|
fontRect.y = tpoint.y ;
|
|
|
|
|
2020-06-14 03:56:59 +02:00
|
|
|
idx = font_idx(curr);
|
2020-09-08 09:31:44 +02:00
|
|
|
if (INBOUNDS_VEC(idx, font))
|
2020-06-14 03:56:59 +02:00
|
|
|
{
|
|
|
|
BlitSurfaceColoured( font[idx], NULL, backBuffer, &fontRect , ct);
|
|
|
|
}
|
2020-01-31 19:25:37 +01:00
|
|
|
bfontpos+=bfontlen(curr) ;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Graphics::bigprint( int _x, int _y, std::string _s, int r, int g, int b, bool cen, int sc )
|
|
|
|
{
|
2020-06-14 03:46:32 +02:00
|
|
|
std::vector<SDL_Surface*>& font = flipmode ? flipbfont : bfont;
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
r = clamp(r,0,255);
|
|
|
|
g = clamp(g,0,255);
|
|
|
|
b = clamp(b,0,255);
|
|
|
|
|
|
|
|
ct.colour = getRGB(r, g, b);
|
|
|
|
|
2020-04-02 22:05:48 +02:00
|
|
|
if (cen)
|
|
|
|
{
|
Reduce dependency on libc functions
During 2.3 development, there's been a gradual shift to using SDL stdlib
functions instead of libc functions, but there are still some libc
functions (or the same libc function but from the STL) in the code.
Well, this patch replaces all the rest of them in one fell swoop.
SDL's stdlib can replace most of these, but its SDL_min() and SDL_max()
are inadequate - they aren't really functions, they're more like macros
with a nasty penchant for double-evaluation. So I just made my own
VVV_min() and VVV_max() functions and placed them in Maths.h instead,
then replaced all the previous usages of min(), max(), std::min(),
std::max(), SDL_min(), and SDL_max() with VVV_min() and VVV_max().
Additionally, there's no SDL_isxdigit(), so I just implemented my own
VVV_isxdigit().
SDL has SDL_malloc() and SDL_free(), but they have some refcounting
built in to them, so in order to use them with LodePNG, I have to
replace the malloc() and free() that LodePNG uses. Which isn't too hard,
I did it in a new file called ThirdPartyDeps.c, and LodePNG is now
compiled with the LODEPNG_NO_COMPILE_ALLOCATORS definition.
Lastly, I also refactored the awful strcpy() and strcat() usages in
PLATFORM_migrateSaveData() to use SDL_snprintf() instead. I know save
migration is getting axed in 2.4, but it still bothers me to have
something like that in the codebase otherwise.
Without further ado, here is the full list of functions that the
codebase now uses:
- SDL_strlcpy() instead of strcpy()
- SDL_strlcat() instead of strcat()
- SDL_snprintf() instead of sprintf(), strcpy(), or strcat() (see above)
- VVV_min() instead of min(), std::min(), or SDL_min()
- VVV_max() instead of max(), std::max(), or SDL_max()
- VVV_isxdigit() instead of isxdigit()
- SDL_strcmp() instead of strcmp()
- SDL_strcasecmp() instead of strcasecmp() or Win32 strcmpi()
- SDL_strstr() instead of strstr()
- SDL_strlen() instead of strlen()
- SDL_sscanf() instead of sscanf()
- SDL_getenv() instead of getenv()
- SDL_malloc() instead of malloc() (replacing in LodePNG as well)
- SDL_free() instead of free() (replacing in LodePNG as well)
2021-01-12 01:17:45 +01:00
|
|
|
_x = VVV_max(160 - (int((len(_s)/ 2.0)*sc)), 0 );
|
2020-04-02 22:05:48 +02:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
int bfontpos = 0;
|
|
|
|
int curr;
|
2020-06-14 03:56:59 +02:00
|
|
|
int idx;
|
2020-01-31 19:25:37 +01:00
|
|
|
std::string::iterator iter = _s.begin();
|
|
|
|
while (iter != _s.end()) {
|
|
|
|
curr = utf8::unchecked::next(iter);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-06-14 03:56:59 +02:00
|
|
|
idx = font_idx(curr);
|
2020-09-08 09:31:44 +02:00
|
|
|
if (INBOUNDS_VEC(idx, font))
|
2020-06-14 03:56:59 +02:00
|
|
|
{
|
2020-08-04 22:09:13 +02:00
|
|
|
SDL_Surface* tempPrint = ScaleSurface(font[idx], font[idx]->w *sc,font[idx]->h *sc);
|
2020-06-14 03:56:59 +02:00
|
|
|
SDL_Rect printrect = { static_cast<Sint16>((_x) + bfontpos), static_cast<Sint16>(_y) , static_cast<Sint16>((bfont_rect.w*sc)+1), static_cast<Sint16>((bfont_rect.h * sc)+1)};
|
|
|
|
BlitSurfaceColoured(tempPrint, NULL, backBuffer, &printrect, ct);
|
|
|
|
SDL_FreeSurface(tempPrint);
|
|
|
|
}
|
2020-01-31 19:25:37 +01:00
|
|
|
bfontpos+=bfontlen(curr) *sc;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Graphics::len(std::string t)
|
|
|
|
{
|
|
|
|
int bfontpos = 0;
|
2020-01-31 19:25:37 +01:00
|
|
|
std::string::iterator iter = t.begin();
|
|
|
|
while (iter != t.end()) {
|
|
|
|
int cur = utf8::unchecked::next(iter);
|
|
|
|
bfontpos += bfontlen(cur);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
return bfontpos;
|
|
|
|
}
|
|
|
|
|
2020-02-10 03:23:12 +01:00
|
|
|
void Graphics::PrintOffAlpha( int _x, int _y, std::string _s, int r, int g, int b, int a, bool cen /*= false*/ )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-06-14 03:46:32 +02:00
|
|
|
std::vector<SDL_Surface*>& font = flipmode ? flipbfont : bfont;
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
r = clamp(r,0,255);
|
|
|
|
g = clamp(g,0,255);
|
|
|
|
b = clamp(b,0,255);
|
2020-02-10 03:23:12 +01:00
|
|
|
a = clamp(a,0,255);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
ct.colour = getRGB(r, g, b);
|
|
|
|
|
|
|
|
if (cen)
|
|
|
|
_x = ((160) - (len(_s) / 2))+_x;
|
|
|
|
int bfontpos = 0;
|
2020-06-14 03:56:59 +02:00
|
|
|
int idx;
|
2020-01-31 19:25:37 +01:00
|
|
|
std::string::iterator iter = _s.begin();
|
|
|
|
while (iter != _s.end()) {
|
|
|
|
int curr = utf8::unchecked::next(iter);
|
2020-01-01 21:29:24 +01:00
|
|
|
point tpoint;
|
|
|
|
tpoint.x = _x + bfontpos;
|
|
|
|
tpoint.y = _y;
|
|
|
|
|
|
|
|
SDL_Rect fontRect = bfont_rect;
|
|
|
|
fontRect.x = tpoint.x ;
|
|
|
|
fontRect.y = tpoint.y ;
|
|
|
|
|
2020-06-14 03:56:59 +02:00
|
|
|
idx = font_idx(curr);
|
2020-09-08 09:31:44 +02:00
|
|
|
if (INBOUNDS_VEC(idx, font))
|
2020-06-14 03:56:59 +02:00
|
|
|
{
|
|
|
|
BlitSurfaceColoured( font[idx], NULL, backBuffer, &fontRect , ct);
|
|
|
|
}
|
2020-01-31 19:25:37 +01:00
|
|
|
bfontpos+=bfontlen(curr) ;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 03:23:12 +01:00
|
|
|
void Graphics::bprint( int x, int y, std::string t, int r, int g, int b, bool cen /*= false*/ ) {
|
|
|
|
bprintalpha(x,y,t,r,g,b,255,cen);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::bprintalpha( int x, int y, std::string t, int r, int g, int b, int a, bool cen /*= false*/ )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-01-17 18:37:53 +01:00
|
|
|
if (!notextoutline)
|
2020-01-14 01:22:26 +01:00
|
|
|
{
|
2020-02-10 03:23:12 +01:00
|
|
|
PrintAlpha(x, y - 1, t, 0, 0, 0, a, cen);
|
2020-01-17 18:37:53 +01:00
|
|
|
if (cen)
|
|
|
|
{
|
2020-02-10 03:23:12 +01:00
|
|
|
PrintOffAlpha(-1, y, t, 0, 0, 0, a, cen);
|
|
|
|
PrintOffAlpha(1, y, t, 0, 0, 0, a, cen);
|
2020-01-17 18:37:53 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-02-10 03:23:12 +01:00
|
|
|
PrintAlpha(x -1, y, t, 0, 0, 0, a, cen);
|
|
|
|
PrintAlpha(x +1, y, t, 0, 0, 0, a, cen);
|
2020-01-17 18:37:53 +01:00
|
|
|
}
|
2020-02-10 03:23:12 +01:00
|
|
|
PrintAlpha(x, y+1, t, 0, 0, 0, a, cen);
|
2020-01-14 01:22:26 +01:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-02-10 03:23:12 +01:00
|
|
|
PrintAlpha(x, y, t, r, g, b, a, cen);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::printcrewname( int x, int y, int t )
|
|
|
|
{
|
|
|
|
//Print the name of crew member t in the right colour
|
|
|
|
switch(t)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
Print(x, y, "Viridian", 16, 240, 240,false );
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
Print(x, y, "Violet", 240, 16, 240,false);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
Print(x, y, "Vitellary", 240, 240, 16,false);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
Print(x, y, "Vermilion", 240, 16, 16,false);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
Print(x, y, "Verdigris", 16, 240, 16,false);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
Print(x, y, "Victoria", 16, 16, 240,false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::printcrewnamedark( int x, int y, int t )
|
|
|
|
{
|
|
|
|
//Print the name of crew member t as above, but in black and white
|
|
|
|
switch(t)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
Print(x, y, "Viridian", 128,128,128,false);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
Print(x, y, "Violet", 128,128,128,false);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
Print(x, y, "Vitellary", 128,128,128,false);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
Print(x, y, "Vermilion", 128,128,128,false);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
Print(x, y, "Verdigris", 128,128,128,false);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
Print(x, y, "Victoria", 128,128,128,false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::printcrewnamestatus( int x, int y, int t )
|
|
|
|
{
|
|
|
|
//Print the status of crew member t in the right colour
|
|
|
|
switch(t)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
Print(x, y, "(that's you!)", 12, 140, 140,false);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
Print(x, y, "Rescued!", 140, 12, 140,false);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
Print(x, y, "Rescued!", 140, 140, 12,false);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
Print(x, y, "Rescued!", 140, 12, 12,false);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
Print(x, y, "Rescued!", 12, 140, 12,false);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
Print(x, y, "Rescued!", 12, 12, 140,false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawsprite( int x, int y, int t, int r, int g, int b )
|
|
|
|
{
|
2020-09-10 07:35:35 +02:00
|
|
|
if (!INBOUNDS_VEC(t, sprites))
|
|
|
|
{
|
|
|
|
WHINE_ONCE("drawsprite() out-of-bounds!");
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect = { Sint16(x), Sint16(y), sprites_rect.w, sprites_rect.h };
|
|
|
|
setcolreal(getRGB(r,g,b));
|
|
|
|
BlitSurfaceColoured(sprites[t], NULL, backBuffer, &rect, ct);
|
|
|
|
}
|
|
|
|
|
2020-05-02 01:40:35 +02:00
|
|
|
void Graphics::drawsprite(int x, int y, int t, Uint32 c)
|
|
|
|
{
|
2020-09-10 07:35:35 +02:00
|
|
|
if (!INBOUNDS_VEC(t, sprites))
|
|
|
|
{
|
|
|
|
WHINE_ONCE("drawsprite() out-of-bounds!");
|
|
|
|
}
|
|
|
|
|
2020-05-02 01:40:35 +02:00
|
|
|
SDL_Rect rect = { Sint16(x), Sint16(y), sprites_rect.w, sprites_rect.h };
|
|
|
|
setcolreal(c);
|
|
|
|
BlitSurfaceColoured(sprites[t], NULL, backBuffer, &rect, ct);
|
|
|
|
}
|
|
|
|
|
2021-03-06 08:55:35 +01:00
|
|
|
#ifndef NO_CUSTOM_LEVELS
|
Make one-way recolors check for specific files
So, 2.3 added recoloring one-way tiles to no longer make them be always
yellow. However, custom levels that retexture the one-way tiles might
not want them to be recolored. So, if there are ANY custom assets
mounted, then the one-ways will not be recolored. However, if the XML
has a <onewaycol_override>1</onewaycol_override> tag, then the one-way
will be recolored again anyways.
When I added one-way recoloring, I didn't intend for any custom asset to
disable the recoloring; I only did it because I couldn't find a way to
check if a specific file was customized by the custom level or not.
However, I have figured out how to do so, and so now tiles.png one-way
recolors will only be disabled if there's a custom tiles.png, and
tiles2.png one-way recolors will only be disabled if there's a custom
tiles2.png.
In order to make sure we're not calling PhysFS functions on every single
deltaframe, I've added caching variables, tiles1_mounted and
tiles2_mounted, to Graphics; these get assigned every time
reloadresources() is called.
2021-03-06 19:52:11 +01:00
|
|
|
bool Graphics::shouldrecoloroneway(const int tilenum, const bool mounted)
|
2021-03-06 08:55:35 +01:00
|
|
|
{
|
|
|
|
return (tilenum >= 14 && tilenum <= 17
|
Make one-way recolors check for specific files
So, 2.3 added recoloring one-way tiles to no longer make them be always
yellow. However, custom levels that retexture the one-way tiles might
not want them to be recolored. So, if there are ANY custom assets
mounted, then the one-ways will not be recolored. However, if the XML
has a <onewaycol_override>1</onewaycol_override> tag, then the one-way
will be recolored again anyways.
When I added one-way recoloring, I didn't intend for any custom asset to
disable the recoloring; I only did it because I couldn't find a way to
check if a specific file was customized by the custom level or not.
However, I have figured out how to do so, and so now tiles.png one-way
recolors will only be disabled if there's a custom tiles.png, and
tiles2.png one-way recolors will only be disabled if there's a custom
tiles2.png.
In order to make sure we're not calling PhysFS functions on every single
deltaframe, I've added caching variables, tiles1_mounted and
tiles2_mounted, to Graphics; these get assigned every time
reloadresources() is called.
2021-03-06 19:52:11 +01:00
|
|
|
&& (!mounted
|
2021-03-06 08:55:35 +01:00
|
|
|
|| ed.onewaycol_override));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-04-02 00:42:22 +02:00
|
|
|
void Graphics::drawtile( int x, int y, int t )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles))
|
2020-06-14 03:37:18 +02:00
|
|
|
{
|
2020-07-01 00:01:30 +02:00
|
|
|
WHINE_ONCE("drawtile() out-of-bounds!")
|
2020-06-14 03:37:18 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-06-30 20:47:22 +02:00
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect = { Sint16(x), Sint16(y), tiles_rect.w, tiles_rect.h };
|
2020-06-30 20:47:22 +02:00
|
|
|
|
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
Make one-way recolors check for specific files
So, 2.3 added recoloring one-way tiles to no longer make them be always
yellow. However, custom levels that retexture the one-way tiles might
not want them to be recolored. So, if there are ANY custom assets
mounted, then the one-ways will not be recolored. However, if the XML
has a <onewaycol_override>1</onewaycol_override> tag, then the one-way
will be recolored again anyways.
When I added one-way recoloring, I didn't intend for any custom asset to
disable the recoloring; I only did it because I couldn't find a way to
check if a specific file was customized by the custom level or not.
However, I have figured out how to do so, and so now tiles.png one-way
recolors will only be disabled if there's a custom tiles.png, and
tiles2.png one-way recolors will only be disabled if there's a custom
tiles2.png.
In order to make sure we're not calling PhysFS functions on every single
deltaframe, I've added caching variables, tiles1_mounted and
tiles2_mounted, to Graphics; these get assigned every time
reloadresources() is called.
2021-03-06 19:52:11 +01:00
|
|
|
if (shouldrecoloroneway(t, tiles1_mounted))
|
2020-06-30 20:47:22 +02:00
|
|
|
{
|
|
|
|
colourTransform thect = {ed.getonewaycol()};
|
|
|
|
BlitSurfaceTinted(tiles[t], NULL, backBuffer, &rect, thect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
BlitSurfaceStandard(tiles[t], NULL, backBuffer, &rect);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-02 00:47:35 +02:00
|
|
|
void Graphics::drawtile2( int x, int y, int t )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles2))
|
2020-06-14 03:37:18 +02:00
|
|
|
{
|
2020-07-01 00:01:30 +02:00
|
|
|
WHINE_ONCE("drawtile2() out-of-bounds!")
|
2020-06-14 03:37:18 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-06-30 20:47:22 +02:00
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect = { Sint16(x), Sint16(y), tiles_rect.w, tiles_rect.h };
|
2020-06-30 20:47:22 +02:00
|
|
|
|
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
Make one-way recolors check for specific files
So, 2.3 added recoloring one-way tiles to no longer make them be always
yellow. However, custom levels that retexture the one-way tiles might
not want them to be recolored. So, if there are ANY custom assets
mounted, then the one-ways will not be recolored. However, if the XML
has a <onewaycol_override>1</onewaycol_override> tag, then the one-way
will be recolored again anyways.
When I added one-way recoloring, I didn't intend for any custom asset to
disable the recoloring; I only did it because I couldn't find a way to
check if a specific file was customized by the custom level or not.
However, I have figured out how to do so, and so now tiles.png one-way
recolors will only be disabled if there's a custom tiles.png, and
tiles2.png one-way recolors will only be disabled if there's a custom
tiles2.png.
In order to make sure we're not calling PhysFS functions on every single
deltaframe, I've added caching variables, tiles1_mounted and
tiles2_mounted, to Graphics; these get assigned every time
reloadresources() is called.
2021-03-06 19:52:11 +01:00
|
|
|
if (shouldrecoloroneway(t, tiles2_mounted))
|
2020-06-30 20:47:22 +02:00
|
|
|
{
|
|
|
|
colourTransform thect = {ed.getonewaycol()};
|
|
|
|
BlitSurfaceTinted(tiles2[t], NULL, backBuffer, &rect, thect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
BlitSurfaceStandard(tiles2[t], NULL, backBuffer, &rect);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-04 04:13:08 +02:00
|
|
|
void Graphics::drawtile3( int x, int y, int t, int off, int height_subtract /*= 0*/ )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-08-04 03:58:53 +02:00
|
|
|
t += off * 30;
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles3))
|
2020-06-14 03:37:18 +02:00
|
|
|
{
|
2020-07-01 00:01:30 +02:00
|
|
|
WHINE_ONCE("drawtile3() out-of-bounds!")
|
2020-06-14 03:37:18 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-08-04 04:13:08 +02:00
|
|
|
SDL_Rect src_rect = { 0, 0, tiles_rect.w, tiles_rect.h - height_subtract };
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect = { Sint16(x), Sint16(y), tiles_rect.w, tiles_rect.h };
|
2020-08-04 04:13:08 +02:00
|
|
|
BlitSurfaceStandard(tiles3[t], &src_rect, backBuffer, &rect);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawtowertile( int x, int y, int t )
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles2))
|
2020-06-14 03:37:18 +02:00
|
|
|
{
|
2020-07-01 00:01:30 +02:00
|
|
|
WHINE_ONCE("drawtowertile() out-of-bounds!")
|
2020-06-14 03:37:18 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-11-02 19:44:53 +01:00
|
|
|
x += 8;
|
|
|
|
y += 8;
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect = { Sint16(x), Sint16(y), tiles_rect.w, tiles_rect.h };
|
2020-11-03 01:54:17 +01:00
|
|
|
BlitSurfaceStandard(tiles2[t], NULL, warpbuffer, &rect);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-03 00:05:24 +01:00
|
|
|
void Graphics::drawtowertile3( int x, int y, int t, TowerBG& bg_obj )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-11-03 00:05:24 +01:00
|
|
|
t += bg_obj.colstate*30;
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles3))
|
2020-06-14 03:37:18 +02:00
|
|
|
{
|
2020-07-01 00:01:30 +02:00
|
|
|
WHINE_ONCE("drawtowertile3() out-of-bounds!")
|
2020-06-14 03:37:18 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-11-02 19:44:53 +01:00
|
|
|
x += 8;
|
|
|
|
y += 8;
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect = { Sint16(x), Sint16(y), tiles_rect.w, tiles_rect.h };
|
2020-11-03 00:05:24 +01:00
|
|
|
BlitSurfaceStandard(tiles3[t], NULL, bg_obj.buffer, &rect);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::drawgui(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-03-19 21:31:53 +01:00
|
|
|
int text_sign;
|
2021-03-19 21:34:13 +01:00
|
|
|
int crew_yp;
|
|
|
|
int crew_sprite;
|
2021-03-19 21:31:53 +01:00
|
|
|
if (flipmode)
|
|
|
|
{
|
|
|
|
text_sign = -1;
|
2021-03-19 21:34:13 +01:00
|
|
|
crew_yp = 64 + 48 + 4;
|
|
|
|
crew_sprite = 6;
|
2021-03-19 21:31:53 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
text_sign = 1;
|
2021-03-19 21:34:13 +01:00
|
|
|
crew_yp = 64 + 32 + 4;
|
|
|
|
crew_sprite = 0;
|
2021-03-19 21:31:53 +01:00
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
//Draw all the textboxes to the screen
|
2020-04-04 02:25:17 +02:00
|
|
|
for (size_t i = 0; i<textbox.size(); i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-03-19 21:31:53 +01:00
|
|
|
int text_yoff;
|
2021-03-20 03:51:36 +01:00
|
|
|
int yp;
|
2021-03-19 21:31:53 +01:00
|
|
|
if (flipmode)
|
|
|
|
{
|
|
|
|
text_yoff = textbox[i].line.size() * 8;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
text_yoff = 8;
|
|
|
|
}
|
|
|
|
|
2021-03-20 03:51:36 +01:00
|
|
|
yp = textbox[i].yp;
|
|
|
|
if (flipmode && textbox[i].flipme)
|
|
|
|
{
|
|
|
|
yp += 2 * (120 - yp) - 8 * (textbox[i].line.size() + 2);
|
|
|
|
}
|
|
|
|
|
2020-04-29 06:49:15 +02:00
|
|
|
//This routine also updates textbox colors
|
|
|
|
float tl_lerp = lerp(textbox[i].prev_tl, textbox[i].tl);
|
|
|
|
textbox[i].setcol(textbox[i].tr * tl_lerp, textbox[i].tg * tl_lerp, textbox[i].tb * tl_lerp);
|
|
|
|
|
2020-04-04 02:26:29 +02:00
|
|
|
if (textbox[i].r == 0 && textbox[i].g == 0 && textbox[i].b == 0)
|
|
|
|
{
|
2021-03-19 21:31:53 +01:00
|
|
|
for (size_t j = 0; j < textbox[i].line.size(); j++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-03-20 03:51:36 +01:00
|
|
|
Print(textbox[i].xp + 8, yp + text_yoff + text_sign * (j * 8), textbox[i].line[j], 196, 196, 255 - help.glow);
|
2020-04-04 02:26:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-03-20 03:51:36 +01:00
|
|
|
SDL_Rect textrect = {textbox[i].xp, yp, textbox[i].w, textbox[i].h};
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2021-03-20 03:47:37 +01:00
|
|
|
FillRect(backBuffer, textrect, textbox[i].r/6, textbox[i].g/6, textbox[i].b / 6 );
|
2020-04-04 02:26:29 +02:00
|
|
|
|
2021-03-20 03:51:36 +01:00
|
|
|
drawcoloredtile(textbox[i].xp, yp, 40, textbox[i].r, textbox[i].g, textbox[i].b);
|
|
|
|
drawcoloredtile(textbox[i].xp+textbox[i].w-8, yp, 42, textbox[i].r, textbox[i].g, textbox[i].b);
|
|
|
|
drawcoloredtile(textbox[i].xp, yp+textbox[i].h-8, 45, textbox[i].r, textbox[i].g, textbox[i].b);
|
|
|
|
drawcoloredtile(textbox[i].xp+textbox[i].w-8, yp+textbox[i].h-8, 47, textbox[i].r, textbox[i].g, textbox[i].b);
|
2020-04-04 02:26:29 +02:00
|
|
|
for (int k = 0; k < textbox[i].lw; k++)
|
|
|
|
{
|
2021-03-20 03:51:36 +01:00
|
|
|
drawcoloredtile(textbox[i].xp + 8 + (k * 8), yp, 41, textbox[i].r, textbox[i].g, textbox[i].b);
|
|
|
|
drawcoloredtile(textbox[i].xp + 8 + (k * 8), yp+textbox[i].h-8, 46, textbox[i].r, textbox[i].g, textbox[i].b);
|
2020-04-04 02:26:29 +02:00
|
|
|
}
|
2020-04-04 02:41:01 +02:00
|
|
|
for (size_t k = 0; k < textbox[i].line.size(); k++)
|
2020-04-04 02:26:29 +02:00
|
|
|
{
|
2021-03-20 03:51:36 +01:00
|
|
|
drawcoloredtile(textbox[i].xp, yp + 8 + (k * 8), 43, textbox[i].r, textbox[i].g, textbox[i].b);
|
|
|
|
drawcoloredtile(textbox[i].xp + textbox[i].w-8, yp + 8 + (k * 8), 44, textbox[i].r, textbox[i].g, textbox[i].b);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2021-03-19 21:31:53 +01:00
|
|
|
for (size_t j = 0; j < textbox[i].line.size(); j++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2021-03-20 03:51:36 +01:00
|
|
|
Print(textbox[i].xp + 8, yp + text_yoff + text_sign * (j * 8), textbox[i].line[j], textbox[i].r, textbox[i].g, textbox[i].b);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-04-04 02:26:29 +02:00
|
|
|
}
|
|
|
|
|
Remove allowspecial, replace with opaqueness check
When I added the over-30-FPS mode, I kept running into this problem
where the special images of text boxes would render during the
deltaframes of fade-in/fade-out animations, even though they shouldn't
be. So I simply added a flag to the text box that enables drawing these
special images.
However, this doesn't solve the problem fully, and there's still a small
chance that a special-image text box could draw another special image
during its deltaframes. It's really rare and you have to have your
deltaframe luck juuuuuust right (or you could use libTAS, probably), but
it helps to be in 40% slowmode and have a high refresh rate (which, if
it isn't a multiple of 30, you should disable VSync, too, in order to
not have a low framerate).
So instead, special images will only be drawn if the text box has fully
faded in completely. That solves the issue completely.
2020-08-05 05:42:43 +02:00
|
|
|
// Only draw special images when fully opaque
|
|
|
|
// This prevents flashes of special images during delta frames
|
|
|
|
bool drawspecial = textbox[i].tl >= 1.0;
|
|
|
|
|
|
|
|
if ((textbox[i].yp == 12 || textbox[i].yp == 180) && textbox[i].r == 165 && drawspecial)
|
2020-04-04 02:26:29 +02:00
|
|
|
{
|
2020-01-01 21:29:24 +01:00
|
|
|
if (flipmode)
|
|
|
|
{
|
2020-04-04 02:26:29 +02:00
|
|
|
drawimage(5, 0, 180, true);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-04 02:26:29 +02:00
|
|
|
drawimage(0, 0, 12, true);
|
|
|
|
}
|
|
|
|
}
|
Remove allowspecial, replace with opaqueness check
When I added the over-30-FPS mode, I kept running into this problem
where the special images of text boxes would render during the
deltaframes of fade-in/fade-out animations, even though they shouldn't
be. So I simply added a flag to the text box that enables drawing these
special images.
However, this doesn't solve the problem fully, and there's still a small
chance that a special-image text box could draw another special image
during its deltaframes. It's really rare and you have to have your
deltaframe luck juuuuuust right (or you could use libTAS, probably), but
it helps to be in 40% slowmode and have a high refresh rate (which, if
it isn't a multiple of 30, you should disable VSync, too, in order to
not have a low framerate).
So instead, special images will only be drawn if the text box has fully
faded in completely. That solves the issue completely.
2020-08-05 05:42:43 +02:00
|
|
|
else if ((textbox[i].yp == 12 || textbox[i].yp == 180) && textbox[i].g == 165 && drawspecial)
|
2020-04-04 02:26:29 +02:00
|
|
|
{
|
|
|
|
if (flipmode)
|
|
|
|
{
|
|
|
|
drawimage(6, 0, 180, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
drawimage(4, 0, 12, true);
|
|
|
|
}
|
|
|
|
}
|
2021-03-19 21:34:13 +01:00
|
|
|
if (textbox[i].r == 175 && textbox[i].g == 175 && drawspecial)
|
2020-04-04 02:26:29 +02:00
|
|
|
{
|
2021-03-19 21:34:13 +01:00
|
|
|
//purple guy
|
|
|
|
drawsprite(80 - 6, crew_yp, crew_sprite, 220- help.glow/4 - int(fRandom()*20), 120- help.glow/4, 210 - help.glow/4);
|
2020-04-04 02:26:29 +02:00
|
|
|
}
|
2021-03-19 21:34:13 +01:00
|
|
|
else if (textbox[i].r == 175 && textbox[i].b == 175 && drawspecial)
|
2020-04-04 02:26:29 +02:00
|
|
|
{
|
2021-03-19 21:34:13 +01:00
|
|
|
//red guy
|
|
|
|
drawsprite(80 - 6, crew_yp, crew_sprite, 255 - help.glow/8, 70 - help.glow/4, 70 - help.glow / 4);
|
|
|
|
}
|
|
|
|
else if (textbox[i].r == 175 && drawspecial)
|
|
|
|
{
|
|
|
|
//green guy
|
|
|
|
drawsprite(80 - 6, crew_yp, crew_sprite, 120 - help.glow / 4 - int(fRandom() * 20), 220 - help.glow / 4, 120 - help.glow / 4);
|
|
|
|
}
|
|
|
|
else if (textbox[i].g == 175 && drawspecial)
|
|
|
|
{
|
|
|
|
//yellow guy
|
|
|
|
drawsprite(80 - 6, crew_yp, crew_sprite, 220- help.glow/4 - int(fRandom()*20), 210 - help.glow/4, 120- help.glow/4);
|
|
|
|
}
|
|
|
|
else if (textbox[i].b == 175 && drawspecial)
|
|
|
|
{
|
|
|
|
//blue guy
|
|
|
|
drawsprite(80 - 6, crew_yp, crew_sprite, 75, 75, 255- help.glow/4 - int(fRandom()*20));
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::updatetextboxes(void)
|
2020-04-29 03:38:43 +02:00
|
|
|
{
|
|
|
|
for (size_t i = 0; i < textbox.size(); i++)
|
|
|
|
{
|
|
|
|
textbox[i].update();
|
|
|
|
|
|
|
|
if (textbox[i].tm == 2 && textbox[i].tl <= 0.5)
|
|
|
|
{
|
|
|
|
textbox.erase(textbox.begin() + i);
|
|
|
|
i--;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
void Graphics::drawimagecol( int t, int xp, int yp, int r = 0, int g = 0, int b = 0, bool cent/*= false*/ )
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, images))
|
2020-06-14 03:37:53 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect trect;
|
2020-04-02 22:05:48 +02:00
|
|
|
if(r+g+b != 0)
|
|
|
|
{
|
|
|
|
RGBf(r,g,b);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
point tpoint;
|
|
|
|
if (cent)
|
|
|
|
{
|
|
|
|
tpoint.x = 160 - int(images[t]->w / 2);
|
|
|
|
tpoint.y = yp;
|
|
|
|
trect.x = tpoint.x ;
|
|
|
|
trect.y = tpoint.y;
|
|
|
|
trect.w = images[t]->w;
|
|
|
|
trect.h= images[t]->h;
|
|
|
|
BlitSurfaceColoured(images[t], NULL, backBuffer, &trect, ct);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
trect.x = xp;
|
|
|
|
trect.y = yp;
|
|
|
|
trect.w = images[t]->w;
|
|
|
|
trect.h = images[t]->h;
|
|
|
|
BlitSurfaceColoured(images[t], NULL, backBuffer, &trect, ct);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawimage( int t, int xp, int yp, bool cent/*=false*/ )
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, images))
|
2020-06-14 03:37:53 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
SDL_Rect trect;
|
|
|
|
if (cent)
|
|
|
|
{
|
|
|
|
trect.x = 160 - int(images[t]->w / 2);
|
|
|
|
trect.y = yp;
|
|
|
|
trect.w = images[t]->w;
|
|
|
|
trect.h = images[t]->h;
|
|
|
|
BlitSurfaceStandard(images[t], NULL, backBuffer, &trect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
trect.x = xp;
|
|
|
|
trect.y = yp;
|
|
|
|
trect.w = images[t]->w;
|
|
|
|
trect.h= images[t]->h;
|
|
|
|
|
|
|
|
BlitSurfaceStandard(images[t], NULL, backBuffer, &trect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawpartimage( int t, int xp, int yp, int wp, int hp)
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, images))
|
2020-06-14 03:37:53 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect trect;
|
|
|
|
|
|
|
|
trect.x = xp;
|
|
|
|
trect.y = yp;
|
|
|
|
trect.w = wp;
|
|
|
|
trect.h= hp;
|
|
|
|
|
|
|
|
SDL_Rect trect2;
|
|
|
|
|
|
|
|
trect2.x = 0;
|
|
|
|
trect2.y = 0;
|
|
|
|
trect2.w = wp;
|
|
|
|
trect2.h= hp;
|
|
|
|
|
|
|
|
BlitSurfaceStandard(images[t], &trect2, backBuffer, &trect);
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::cutscenebars(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-29 02:16:24 +02:00
|
|
|
int usethispos = lerp(oldcutscenebarspos, cutscenebarspos);
|
2020-01-01 21:29:24 +01:00
|
|
|
if (showcutscenebars)
|
|
|
|
{
|
2020-04-29 02:16:24 +02:00
|
|
|
FillRect(backBuffer, 0, 0, usethispos, 16, 0x000000);
|
|
|
|
FillRect(backBuffer, 360-usethispos, 224, usethispos, 16, 0x000000);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-04-29 02:17:13 +02:00
|
|
|
else if (cutscenebarspos > 0) //disappearing
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-29 02:17:13 +02:00
|
|
|
//draw
|
|
|
|
FillRect(backBuffer, 0, 0, usethispos, 16, 0x000000);
|
|
|
|
FillRect(backBuffer, 360-usethispos, 224, usethispos, 16, 0x000000);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::cutscenebarstimer(void)
|
2020-04-29 02:11:02 +02:00
|
|
|
{
|
2020-04-29 02:16:24 +02:00
|
|
|
oldcutscenebarspos = cutscenebarspos;
|
2020-04-29 02:11:02 +02:00
|
|
|
if (showcutscenebars)
|
|
|
|
{
|
|
|
|
cutscenebarspos += 25;
|
Reduce dependency on libc functions
During 2.3 development, there's been a gradual shift to using SDL stdlib
functions instead of libc functions, but there are still some libc
functions (or the same libc function but from the STL) in the code.
Well, this patch replaces all the rest of them in one fell swoop.
SDL's stdlib can replace most of these, but its SDL_min() and SDL_max()
are inadequate - they aren't really functions, they're more like macros
with a nasty penchant for double-evaluation. So I just made my own
VVV_min() and VVV_max() functions and placed them in Maths.h instead,
then replaced all the previous usages of min(), max(), std::min(),
std::max(), SDL_min(), and SDL_max() with VVV_min() and VVV_max().
Additionally, there's no SDL_isxdigit(), so I just implemented my own
VVV_isxdigit().
SDL has SDL_malloc() and SDL_free(), but they have some refcounting
built in to them, so in order to use them with LodePNG, I have to
replace the malloc() and free() that LodePNG uses. Which isn't too hard,
I did it in a new file called ThirdPartyDeps.c, and LodePNG is now
compiled with the LODEPNG_NO_COMPILE_ALLOCATORS definition.
Lastly, I also refactored the awful strcpy() and strcat() usages in
PLATFORM_migrateSaveData() to use SDL_snprintf() instead. I know save
migration is getting axed in 2.4, but it still bothers me to have
something like that in the codebase otherwise.
Without further ado, here is the full list of functions that the
codebase now uses:
- SDL_strlcpy() instead of strcpy()
- SDL_strlcat() instead of strcat()
- SDL_snprintf() instead of sprintf(), strcpy(), or strcat() (see above)
- VVV_min() instead of min(), std::min(), or SDL_min()
- VVV_max() instead of max(), std::max(), or SDL_max()
- VVV_isxdigit() instead of isxdigit()
- SDL_strcmp() instead of strcmp()
- SDL_strcasecmp() instead of strcasecmp() or Win32 strcmpi()
- SDL_strstr() instead of strstr()
- SDL_strlen() instead of strlen()
- SDL_sscanf() instead of sscanf()
- SDL_getenv() instead of getenv()
- SDL_malloc() instead of malloc() (replacing in LodePNG as well)
- SDL_free() instead of free() (replacing in LodePNG as well)
2021-01-12 01:17:45 +01:00
|
|
|
cutscenebarspos = VVV_min(cutscenebarspos, 361);
|
2020-04-29 02:11:02 +02:00
|
|
|
}
|
|
|
|
else if (cutscenebarspos > 0)
|
|
|
|
{
|
|
|
|
//disappearing
|
|
|
|
cutscenebarspos -= 25;
|
Reduce dependency on libc functions
During 2.3 development, there's been a gradual shift to using SDL stdlib
functions instead of libc functions, but there are still some libc
functions (or the same libc function but from the STL) in the code.
Well, this patch replaces all the rest of them in one fell swoop.
SDL's stdlib can replace most of these, but its SDL_min() and SDL_max()
are inadequate - they aren't really functions, they're more like macros
with a nasty penchant for double-evaluation. So I just made my own
VVV_min() and VVV_max() functions and placed them in Maths.h instead,
then replaced all the previous usages of min(), max(), std::min(),
std::max(), SDL_min(), and SDL_max() with VVV_min() and VVV_max().
Additionally, there's no SDL_isxdigit(), so I just implemented my own
VVV_isxdigit().
SDL has SDL_malloc() and SDL_free(), but they have some refcounting
built in to them, so in order to use them with LodePNG, I have to
replace the malloc() and free() that LodePNG uses. Which isn't too hard,
I did it in a new file called ThirdPartyDeps.c, and LodePNG is now
compiled with the LODEPNG_NO_COMPILE_ALLOCATORS definition.
Lastly, I also refactored the awful strcpy() and strcat() usages in
PLATFORM_migrateSaveData() to use SDL_snprintf() instead. I know save
migration is getting axed in 2.4, but it still bothers me to have
something like that in the codebase otherwise.
Without further ado, here is the full list of functions that the
codebase now uses:
- SDL_strlcpy() instead of strcpy()
- SDL_strlcat() instead of strcat()
- SDL_snprintf() instead of sprintf(), strcpy(), or strcat() (see above)
- VVV_min() instead of min(), std::min(), or SDL_min()
- VVV_max() instead of max(), std::max(), or SDL_max()
- VVV_isxdigit() instead of isxdigit()
- SDL_strcmp() instead of strcmp()
- SDL_strcasecmp() instead of strcasecmp() or Win32 strcmpi()
- SDL_strstr() instead of strstr()
- SDL_strlen() instead of strlen()
- SDL_sscanf() instead of sscanf()
- SDL_getenv() instead of getenv()
- SDL_malloc() instead of malloc() (replacing in LodePNG as well)
- SDL_free() instead of free() (replacing in LodePNG as well)
2021-01-12 01:17:45 +01:00
|
|
|
cutscenebarspos = VVV_max(cutscenebarspos, 0);
|
2020-04-29 02:11:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-20 07:08:35 +01:00
|
|
|
void Graphics::setbars(const int position)
|
|
|
|
{
|
|
|
|
cutscenebarspos = position;
|
|
|
|
oldcutscenebarspos = position;
|
|
|
|
}
|
|
|
|
|
2020-03-31 21:26:11 +02:00
|
|
|
void Graphics::drawcrewman( int x, int y, int t, bool act, bool noshift /*=false*/ )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
if (!act)
|
|
|
|
{
|
|
|
|
if (noshift)
|
|
|
|
{
|
|
|
|
if (flipmode)
|
|
|
|
{
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x, y, 14, col_crewinactive);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x, y, 12, col_crewinactive);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (flipmode)
|
|
|
|
{
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x - 8, y, 14, col_crewinactive);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x - 8, y, 12, col_crewinactive);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (flipmode) crewframe += 6;
|
|
|
|
|
|
|
|
switch(t)
|
|
|
|
{
|
|
|
|
case 0:
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x, y, crewframe, col_crewcyan);
|
2020-01-01 21:29:24 +01:00
|
|
|
break;
|
|
|
|
case 1:
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x, y, crewframe, col_crewpurple);
|
2020-01-01 21:29:24 +01:00
|
|
|
break;
|
|
|
|
case 2:
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x, y, crewframe, col_crewyellow);
|
2020-01-01 21:29:24 +01:00
|
|
|
break;
|
|
|
|
case 3:
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x, y, crewframe, col_crewred);
|
2020-01-01 21:29:24 +01:00
|
|
|
break;
|
|
|
|
case 4:
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x, y, crewframe, col_crewgreen);
|
2020-01-01 21:29:24 +01:00
|
|
|
break;
|
|
|
|
case 5:
|
2020-05-02 01:40:35 +02:00
|
|
|
drawsprite(x, y, crewframe, col_crewblue);
|
2020-01-01 21:29:24 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flipmode) crewframe -= 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawpixeltextbox( int x, int y, int w, int h, int w2, int h2, int r, int g, int b, int xo, int yo )
|
|
|
|
{
|
|
|
|
//given these parameters, draw a textbox with a pixel width
|
|
|
|
|
|
|
|
//madrect.x = x; madrect.y = y; madrect.w = w; madrect.h = h;
|
|
|
|
FillRect(backBuffer,x,y,w,h, r/6, g/6, b/6 );
|
|
|
|
|
2020-06-14 20:21:32 +02:00
|
|
|
for (int k = 0; k < w2-2; k++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
drawcoloredtile(x + 8-xo + (k * 8), y, 41, r, g, b);
|
|
|
|
drawcoloredtile(x + 8-xo + (k * 8), y + (h) - 8, 46, r, g, b);
|
|
|
|
}
|
|
|
|
|
2020-06-14 20:21:32 +02:00
|
|
|
for (int k = 0; k < h2-2; k++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
drawcoloredtile(x, y + 8-yo + (k * 8), 43, r, g, b);
|
|
|
|
drawcoloredtile(x + (w) - 8, y + 8-yo + (k * 8), 44, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
drawcoloredtile(x, y, 40, r, g, b);
|
|
|
|
drawcoloredtile(x + (w) - 8, y, 42, r, g, b);
|
|
|
|
drawcoloredtile(x, y + (h) - 8, 45, r, g, b);
|
|
|
|
drawcoloredtile(x + (w) - 8, y + (h) - 8, 47, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawcustompixeltextbox( int x, int y, int w, int h, int w2, int h2, int r, int g, int b, int xo, int yo )
|
|
|
|
{
|
|
|
|
//given these parameters, draw a textbox with a pixel width
|
|
|
|
|
|
|
|
FillRect(backBuffer,x,y,w,h, r/6, g/6, b/6 );
|
|
|
|
|
2020-06-14 20:21:32 +02:00
|
|
|
for (int k = 0; k < w2-2; k++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
drawcoloredtile(x + 8-xo + (k * 8), y, 41, r, g, b);
|
|
|
|
drawcoloredtile(x + 8-xo + (k * 8), y + (h) - 8, 46, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
drawcoloredtile(x+ (w) - 16, y, 41, r, g, b);
|
|
|
|
drawcoloredtile(x+ (w) - 16, y + (h) - 8, 46, r, g, b);
|
|
|
|
drawcoloredtile(x+ (w) - 24, y, 41, r, g, b);
|
|
|
|
drawcoloredtile(x+ (w) - 24, y + (h) - 8, 46, r, g, b);
|
|
|
|
|
2020-06-14 20:21:32 +02:00
|
|
|
for (int k = 0; k < h2-2; k++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
drawcoloredtile(x, y + 8-yo + (k * 8), 43, r, g, b);
|
|
|
|
drawcoloredtile(x + (w) - 8, y + 8-yo + (k * 8), 44, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
drawcoloredtile(x, y + (h) - 16, 43, r, g, b);
|
|
|
|
drawcoloredtile(x + (w) - 8, y + (h) - 16, 44, r, g, b);
|
|
|
|
drawcoloredtile(x, y + (h) - 24, 43, r, g, b);
|
|
|
|
drawcoloredtile(x + (w) - 8, y + (h) - 24, 44, r, g, b);
|
|
|
|
|
|
|
|
drawcoloredtile(x, y, 40, r, g, b);
|
|
|
|
drawcoloredtile(x + (w) - 8, y, 42, r, g, b);
|
|
|
|
drawcoloredtile(x, y + (h) - 8, 45, r, g, b);
|
|
|
|
drawcoloredtile(x + (w) - 8, y + (h) - 8, 47, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawtextbox( int x, int y, int w, int h, int r, int g, int b )
|
|
|
|
{
|
|
|
|
//given these parameters, draw a textbox
|
|
|
|
FillRect(backBuffer,x,y,w*8,h*8, r/6, g/6, b/6 );
|
|
|
|
|
|
|
|
drawcoloredtile(x, y, 40, r, g, b);
|
|
|
|
drawcoloredtile(x + (w*8) - 8, y, 42, r, g, b);
|
|
|
|
drawcoloredtile(x, y + (h*8) - 8, 45, r, g, b);
|
|
|
|
drawcoloredtile(x + (w*8) - 8, y + (h*8) - 8, 47, r, g, b);
|
|
|
|
|
|
|
|
for (int k = 0; k < w-2; k++)
|
|
|
|
{
|
|
|
|
drawcoloredtile(x + 8 + (k * 8), y, 41, r, g, b);
|
|
|
|
drawcoloredtile(x + 8 + (k * 8), y + (h * 8) - 8, 46, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int k = 0; k < h-2; k++)
|
|
|
|
{
|
|
|
|
drawcoloredtile(x, y + 8 + (k * 8), 43, r, g, b);
|
|
|
|
drawcoloredtile(x + (w * 8) - 8, y + 8 + (k * 8), 44, r, g, b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::textboxactive(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
//Remove all but the most recent textbox
|
2020-04-04 02:25:17 +02:00
|
|
|
for (int i = 0; i < (int) textbox.size(); i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
if (m != i) textbox[i].remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::textboxremovefast(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
//Remove all textboxes
|
2020-04-04 02:25:17 +02:00
|
|
|
for (size_t i = 0; i < textbox.size(); i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
textbox[i].removefast();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::textboxremove(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
//Remove all textboxes
|
2020-04-04 02:25:17 +02:00
|
|
|
for (size_t i = 0; i < textbox.size(); i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
textbox[i].remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::textboxtimer( int t )
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(m, textbox))
|
2020-06-28 19:40:58 +02:00
|
|
|
{
|
2020-06-28 21:43:12 +02:00
|
|
|
puts("textboxtimer() out-of-bounds!");
|
2020-06-28 19:40:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
textbox[m].timer=t;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::addline( std::string t )
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(m, textbox))
|
2020-06-28 19:40:58 +02:00
|
|
|
{
|
2020-06-28 21:43:12 +02:00
|
|
|
puts("addline() out-of-bounds!");
|
2020-06-28 19:40:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
textbox[m].addline(t);
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::textboxadjust(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(m, textbox))
|
2020-06-28 19:40:58 +02:00
|
|
|
{
|
2020-06-28 21:43:12 +02:00
|
|
|
puts("textboxadjust() out-of-bounds!");
|
2020-06-28 19:40:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
textbox[m].adjust();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-20 00:41:41 +01:00
|
|
|
void Graphics::createtextbox( std::string t, int xp, int yp, int r, int g, int b)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-04 02:25:17 +02:00
|
|
|
m = textbox.size();
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
if(m<20)
|
|
|
|
{
|
2020-04-04 02:25:17 +02:00
|
|
|
textboxclass text;
|
2020-04-04 02:41:01 +02:00
|
|
|
text.line.push_back(t);
|
2020-04-04 02:25:17 +02:00
|
|
|
text.xp = xp;
|
2020-01-31 19:25:37 +01:00
|
|
|
int length = utf8::unchecked::distance(t.begin(), t.end());
|
2020-04-04 02:25:17 +02:00
|
|
|
if (xp == -1) text.xp = 160 - (((length / 2) + 1) * 8);
|
|
|
|
text.yp = yp;
|
|
|
|
text.initcol(r, g, b);
|
|
|
|
text.resize();
|
|
|
|
textbox.push_back(text);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::drawfade(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-29 03:10:40 +02:00
|
|
|
int usethisamount = lerp(oldfadeamount, fadeamount);
|
2020-01-01 21:29:24 +01:00
|
|
|
if ((fademode == 1)||(fademode == 4))
|
|
|
|
{
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else if(fademode==3)
|
|
|
|
{
|
2020-07-03 11:40:57 +02:00
|
|
|
for (size_t i = 0; i < SDL_arraysize(fadebars); i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-29 03:10:40 +02:00
|
|
|
FillRect(backBuffer, fadebars[i], i * 16, usethisamount, 16, 0x000000 );
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(fademode==5 )
|
|
|
|
{
|
2020-07-03 11:40:57 +02:00
|
|
|
for (size_t i = 0; i < SDL_arraysize(fadebars); i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-29 03:10:40 +02:00
|
|
|
FillRect(backBuffer, fadebars[i]-usethisamount, i * 16, 500, 16, 0x000000 );
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::processfade(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-29 03:10:40 +02:00
|
|
|
oldfadeamount = fadeamount;
|
2020-01-01 21:29:24 +01:00
|
|
|
if (fademode > 1)
|
|
|
|
{
|
|
|
|
if (fademode == 2)
|
|
|
|
{
|
|
|
|
//prepare fade out
|
2020-07-03 11:40:57 +02:00
|
|
|
for (size_t i = 0; i < SDL_arraysize(fadebars); i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
fadebars[i] = -int(fRandom() * 12) * 8;
|
|
|
|
}
|
2021-03-20 07:09:11 +01:00
|
|
|
setfade(0);
|
2020-01-01 21:29:24 +01:00
|
|
|
fademode = 3;
|
|
|
|
}
|
|
|
|
else if (fademode == 3)
|
|
|
|
{
|
|
|
|
fadeamount += 24;
|
|
|
|
if (fadeamount > 416)
|
|
|
|
{
|
|
|
|
fademode = 1; //faded
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (fademode == 4)
|
|
|
|
{
|
|
|
|
//prepare fade in
|
2020-07-03 11:40:57 +02:00
|
|
|
for (size_t i = 0; i < SDL_arraysize(fadebars); i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
fadebars[i] = 320 + int(fRandom() * 12) * 8;
|
|
|
|
}
|
2021-03-20 07:09:11 +01:00
|
|
|
setfade(416);
|
2020-01-01 21:29:24 +01:00
|
|
|
fademode = 5;
|
|
|
|
}
|
|
|
|
else if (fademode == 5)
|
|
|
|
{
|
|
|
|
fadeamount -= 24;
|
|
|
|
if (fadeamount <= 0)
|
|
|
|
{
|
|
|
|
fademode = 0; //normal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-20 07:09:11 +01:00
|
|
|
void Graphics::setfade(const int amount)
|
|
|
|
{
|
|
|
|
fadeamount = amount;
|
|
|
|
oldfadeamount = amount;
|
|
|
|
}
|
|
|
|
|
2020-07-04 23:53:05 +02:00
|
|
|
void Graphics::drawmenu( int cr, int cg, int cb, bool levelmenu /*= false*/ )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
Refactor menu creation code
Firstly, menu options are no longer ad-hoc objects, and are added by
using Game::option() (this is the biggest change). This removes the
vector Game::menuoptionsactive, and Game::menuoptions is now a vector of
MenuOption instead of std::string.
Secondly, the manual tracker variable of the amount of menu options,
Game::nummenuoptions, has been removed, in favor of using vectors
properly and using Game::menuoptions::size().
As a result, a lot of copy-pasted code has been removed from
Game::createmenu(), mostly due to having to have different versions of
menus depending on whether or not we have certain defines, or having an
mmmmmm.vvv file inside the VVVVVV directory. In the old days, you
couldn't just add or remove a menu option conveniently, you had to
shuffle around the position of every other menu option too, which
resulted in lots of copy-pasted code. But now this copy-pasted code has
been de-duplicated, at least in Game::createmenu().
2020-04-15 06:50:17 +02:00
|
|
|
for (size_t i = 0; i < game.menuoptions.size(); i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-07-04 23:53:05 +02:00
|
|
|
MenuOption& opt = game.menuoptions[i];
|
|
|
|
|
|
|
|
int fr, fg, fb;
|
|
|
|
if (opt.active)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-07-04 23:53:05 +02:00
|
|
|
// Color it normally
|
|
|
|
fr = cr;
|
|
|
|
fg = cg;
|
|
|
|
fb = cb;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-04 23:53:05 +02:00
|
|
|
// Color it gray
|
|
|
|
fr = 128;
|
|
|
|
fg = 128;
|
|
|
|
fb = 128;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = i*game.menuspacing + game.menuxoff;
|
|
|
|
int y = 140 + i*12 + game.menuyoff;
|
|
|
|
|
|
|
|
if (levelmenu)
|
|
|
|
{
|
|
|
|
if (game.menuoptions.size() - i <= 3)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-07-04 23:53:05 +02:00
|
|
|
// We're on "next page", "previous page", or "return to menu". Draw them separated by a bit
|
|
|
|
y += 8;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-04 23:53:05 +02:00
|
|
|
// Get out of the way of the level descriptions
|
|
|
|
y += 4;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-07 03:14:44 +01:00
|
|
|
char tempstring[MENU_TEXT_BYTES];
|
2020-07-04 23:53:05 +02:00
|
|
|
SDL_strlcpy(tempstring, opt.text, sizeof(tempstring));
|
|
|
|
|
2021-03-07 03:14:44 +01:00
|
|
|
char buffer[MENU_TEXT_BYTES];
|
Refactor menu creation code
Firstly, menu options are no longer ad-hoc objects, and are added by
using Game::option() (this is the biggest change). This removes the
vector Game::menuoptionsactive, and Game::menuoptions is now a vector of
MenuOption instead of std::string.
Secondly, the manual tracker variable of the amount of menu options,
Game::nummenuoptions, has been removed, in favor of using vectors
properly and using Game::menuoptions::size().
As a result, a lot of copy-pasted code has been removed from
Game::createmenu(), mostly due to having to have different versions of
menus depending on whether or not we have certain defines, or having an
mmmmmm.vvv file inside the VVVVVV directory. In the old days, you
couldn't just add or remove a menu option conveniently, you had to
shuffle around the position of every other menu option too, which
resulted in lots of copy-pasted code. But now this copy-pasted code has
been de-duplicated, at least in Game::createmenu().
2020-04-15 06:50:17 +02:00
|
|
|
if ((int) i == game.currentmenuoption)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-07-04 23:53:05 +02:00
|
|
|
if (opt.active)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-07-04 23:53:05 +02:00
|
|
|
// Uppercase the text
|
|
|
|
// FIXME: This isn't UTF-8 aware!
|
2020-07-15 18:09:24 +02:00
|
|
|
size_t templen = SDL_strlen(tempstring);
|
|
|
|
for (size_t ii = 0; ii < templen; ii++)
|
2020-07-03 23:54:23 +02:00
|
|
|
{
|
|
|
|
tempstring[ii] = SDL_toupper(tempstring[ii]);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-07-04 23:53:05 +02:00
|
|
|
|
|
|
|
// Add brackets
|
|
|
|
SDL_snprintf(buffer, sizeof(buffer), "[ %s ]", tempstring);
|
|
|
|
// Account for brackets
|
|
|
|
x -= 16;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-04 23:53:05 +02:00
|
|
|
SDL_strlcpy(buffer, tempstring, sizeof(buffer));
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-07-04 23:53:05 +02:00
|
|
|
|
|
|
|
Print(x, y, buffer, fr, fg, fb);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Graphics::drawcoloredtile( int x, int y, int t, int r, int g, int b )
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles))
|
2020-06-14 03:37:18 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
setcolreal(getRGB(r,g,b));
|
|
|
|
|
|
|
|
SDL_Rect rect;
|
|
|
|
setRect(rect,x,y,tiles_rect.w,tiles_rect.h);
|
|
|
|
BlitSurfaceColoured(tiles[t],NULL, backBuffer, &rect, ct );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-02 00:35:27 +02:00
|
|
|
bool Graphics::Hitest(SDL_Surface* surface1, point p1, SDL_Surface* surface2, point p2)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
//find rectangle where they intersect:
|
|
|
|
|
|
|
|
int r1_left = p1.x;
|
|
|
|
int r1_right = r1_left + surface1->w;
|
|
|
|
int r2_left = p2.x;
|
|
|
|
int r2_right = r2_left + surface2->w;
|
|
|
|
|
|
|
|
int r1_bottom = p1.y;
|
|
|
|
int r1_top = p1.y + surface1->h;
|
|
|
|
int r2_bottom = p2.y;
|
|
|
|
int r2_top = p2.y + surface2->h;
|
|
|
|
|
2020-08-04 09:55:18 +02:00
|
|
|
SDL_Rect rect1 = {p1.x, p1.y, surface1->w, surface1->h};
|
|
|
|
SDL_Rect rect2 = {p2.x, p2.y, surface2->w, surface2->h};
|
|
|
|
bool intersection = help.intersects(rect1, rect2);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
if(intersection)
|
|
|
|
{
|
Reduce dependency on libc functions
During 2.3 development, there's been a gradual shift to using SDL stdlib
functions instead of libc functions, but there are still some libc
functions (or the same libc function but from the STL) in the code.
Well, this patch replaces all the rest of them in one fell swoop.
SDL's stdlib can replace most of these, but its SDL_min() and SDL_max()
are inadequate - they aren't really functions, they're more like macros
with a nasty penchant for double-evaluation. So I just made my own
VVV_min() and VVV_max() functions and placed them in Maths.h instead,
then replaced all the previous usages of min(), max(), std::min(),
std::max(), SDL_min(), and SDL_max() with VVV_min() and VVV_max().
Additionally, there's no SDL_isxdigit(), so I just implemented my own
VVV_isxdigit().
SDL has SDL_malloc() and SDL_free(), but they have some refcounting
built in to them, so in order to use them with LodePNG, I have to
replace the malloc() and free() that LodePNG uses. Which isn't too hard,
I did it in a new file called ThirdPartyDeps.c, and LodePNG is now
compiled with the LODEPNG_NO_COMPILE_ALLOCATORS definition.
Lastly, I also refactored the awful strcpy() and strcat() usages in
PLATFORM_migrateSaveData() to use SDL_snprintf() instead. I know save
migration is getting axed in 2.4, but it still bothers me to have
something like that in the codebase otherwise.
Without further ado, here is the full list of functions that the
codebase now uses:
- SDL_strlcpy() instead of strcpy()
- SDL_strlcat() instead of strcat()
- SDL_snprintf() instead of sprintf(), strcpy(), or strcat() (see above)
- VVV_min() instead of min(), std::min(), or SDL_min()
- VVV_max() instead of max(), std::max(), or SDL_max()
- VVV_isxdigit() instead of isxdigit()
- SDL_strcmp() instead of strcmp()
- SDL_strcasecmp() instead of strcasecmp() or Win32 strcmpi()
- SDL_strstr() instead of strstr()
- SDL_strlen() instead of strlen()
- SDL_sscanf() instead of sscanf()
- SDL_getenv() instead of getenv()
- SDL_malloc() instead of malloc() (replacing in LodePNG as well)
- SDL_free() instead of free() (replacing in LodePNG as well)
2021-01-12 01:17:45 +01:00
|
|
|
int r3_left = VVV_max(r1_left, r2_left);
|
|
|
|
int r3_top = VVV_min(r1_top, r2_top);
|
|
|
|
int r3_right = VVV_min(r1_right, r2_right);
|
|
|
|
int r3_bottom= VVV_max(r1_bottom, r2_bottom);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
//for every pixel inside rectangle
|
|
|
|
for(int x = r3_left; x < r3_right; x++)
|
|
|
|
{
|
|
|
|
for(int y = r3_bottom; y < r3_top; y++)
|
|
|
|
{
|
|
|
|
Uint32 pixel1 = ReadPixel(surface1 , x - p1.x, y - p1.y);
|
|
|
|
Uint32 pixel2 = ReadPixel(surface2 , x - p2.x, y - p2.y);
|
|
|
|
if ((pixel1 & 0x000000FF) && (pixel2 & 0x000000FF))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-08-04 09:56:45 +02:00
|
|
|
return false;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-03-31 21:26:11 +02:00
|
|
|
void Graphics::drawgravityline( int t )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-11-01 05:23:59 +01:00
|
|
|
if (!INBOUNDS_VEC(t, obj.entities))
|
|
|
|
{
|
|
|
|
WHINE_ONCE("drawgravityline() out-of-bounds!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-25 19:13:00 +02:00
|
|
|
if (obj.entities[t].life == 0 || obj.entities[t].onentity == 1) // FIXME: Remove 'onentity == 1' when game loop order is fixed!
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
switch(linestate)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(200-20, 200-20, 200-20));
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(225-30, 245-30, 245-30));
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(245-30, 245-30, 225-30));
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(164-10, 200-20, 200-20));
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(224-20, 255-30, 196-20));
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(205-20, 235-30, 196-20));
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(164-10, 164-10, 164-10));
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(225-30, 245-30, 205-20));
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(205-20, 255-30, 225-30));
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(245-30, 245-30, 245-30));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FillRect(backBuffer,line_rect, getRGB(96, 96, 96));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::drawtrophytext(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
int temp, temp2, temp3;
|
|
|
|
|
|
|
|
if (obj.trophytext < 15)
|
|
|
|
{
|
2020-04-30 01:54:36 +02:00
|
|
|
int usethismult = lerp(obj.oldtrophytext, obj.trophytext);
|
|
|
|
temp = (196 * usethismult) / 15;
|
|
|
|
temp2 = (196 * usethismult) / 15;
|
|
|
|
temp3 = ((255 - help.glow) * usethismult) / 15;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
temp = 196;
|
|
|
|
temp2 = 196;
|
|
|
|
temp3 = 255 - help.glow;
|
|
|
|
}
|
|
|
|
switch(obj.trophytype)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
Print( -1, 6, "SPACE STATION 1 MASTERED", temp, temp2, temp3, true);
|
|
|
|
Print( -1, 16, "Obtain a V Rank in this Time Trial", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
Print( -1, 6, "LABORATORY MASTERED", temp, temp2, temp3, true);
|
|
|
|
Print( -1, 16, "Obtain a V Rank in this Time Trial", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
Print( -1, 6, "THE TOWER MASTERED", temp, temp2, temp3, true);
|
|
|
|
Print( -1, 16, "Obtain a V Rank in this Time Trial", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
Print( -1, 6, "SPACE STATION 2 MASTERED", temp, temp2, temp3, true);
|
|
|
|
Print( -1, 16, "Obtain a V Rank in this Time Trial", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
Print( -1, 6, "WARP ZONE MASTERED", temp, temp2, temp3, true);
|
|
|
|
Print( -1, 16, "Obtain a V Rank in this Time Trial", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
Print( -1, 6, "FINAL LEVEL MASTERED", temp, temp2, temp3, true);
|
|
|
|
Print( -1, 16, "Obtain a V Rank in this Time Trial", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
Print( -1, 6, "GAME COMPLETE", temp, temp2, temp3, true);
|
|
|
|
Print( -1, 16, "Complete the game", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
Print( -1, 6, "FLIP MODE COMPLETE", temp, temp2, temp3, true);
|
|
|
|
Print( -1, 16, "Complete the game in flip mode", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
Print( -1, 11, "Win with less than 50 deaths", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
Print( -1, 11, "Win with less than 100 deaths", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
Print( -1, 11, "Win with less than 250 deaths", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
Print( -1, 11, "Win with less than 500 deaths", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
Print( -1, 11, "Last 5 seconds on the Super Gravitron", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
Print( -1, 11, "Last 10 seconds on the Super Gravitron", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
Print( -1, 11, "Last 15 seconds on the Super Gravitron", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
Print( -1, 11, "Last 20 seconds on the Super Gravitron", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 17:
|
|
|
|
Print( -1, 11, "Last 30 seconds on the Super Gravitron", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 18:
|
|
|
|
Print( -1, 11, "Last 1 minute on the Super Gravitron", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
case 20:
|
|
|
|
Print( -1, 6, "MASTER OF THE UNIVERSE", temp, temp2, temp3, true);
|
|
|
|
Print( -1, 16, "Complete the game in no death mode", temp, temp2, temp3, true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::drawentities(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-11-01 05:38:15 +01:00
|
|
|
const int yoff = map.towermode ? lerp(map.oldypos, map.ypos) : 0;
|
|
|
|
|
Fix crewmates being drawn behind other entities
This fixes the draw order by drawing all other entities first, before
then drawing all humanoids[1] after, including the player afterwards.
This is actually a regression fix from #191. When I was testing this, I
was thinking about where get a crewmate in front of another entity in
the main game, other than the checkpoints in Intermission 1. And then I
thought about the teleporters, because I remember the pre-Deep Space
cutscene in Dimension Open looking funny because Vita ended up being
behind the teleporter. (Actually, a lot of the cutscenes of Dimension
Open look funny because of crewmates standing behind terminals.)
So then I tried to get crewmates in front of teleporters. It actually
turns out that you can't do it for most of them... except for Verdigris.
And then that's what I realized why there was an oddity in WarpClass.cpp
when I was removing the `active` system from the game - for some reason,
the game put a hole in `obj.entities` between the teleporter and the
player when loading the room Murdering Twinmaker. In a violation of
Chesterton's Fence (the principle that you should understand something
before removing it), I shrugged it off and decided "there's no way to
support having holes with my new system, and having holes is probably
bad anyway, so I'm going to remove this and move on". The fact that
there wasn't any comments clarifying the mysterious code didn't help
(but, this *was* 2.2 code after all; have you *seen* 2.2 code?!).
And it turns out that this maneuver was done so Verdigris would fill
that hole when he got created, and Verdigris being first before the
teleporter would mean he would be drawn in front of the teleporter,
instead of being behind it. So ever since
b1b1474b7bbc3ceddea24f689a7ddb050cfe4490 got merged, there has actually
been a regression from 2.2 where Verdigris got drawn behind the
teleporter in Murdering Twinmaker, instead of properly being in front of
it like in 2.2 and previous.
This patch fixes that regression, but it actually properly fixes it
instead of hacking around with the `active` system.
Closes #426.
[1]: I'm going to go on a rant here, so hear me out. It's not explicitly
stated that the characters in VVVVVV are human. So, given this
information, what do we call them? Well, the VVVVVV community (at least
the custom levels one, I don't think the speedrunning community does
this or is preoccupied with lore in the first place) decided to call
them "villis", because of the roomname "The Villi People" - which is
only one blunder in a series of awful headcanons based off of the
assumption that the intent of Bennett Foddy (who named the roomnames)
was to decree some sort of lore to the game. Another one being
"Verdigris can't flip" because of "Green Dudes Can't Flip". Then an OC
(original character) got named based off of "The Voon Show" too. And so
on and so forth.
2020-11-01 07:23:40 +01:00
|
|
|
if (!map.custommode)
|
2020-11-01 05:38:15 +01:00
|
|
|
{
|
Fix crewmates being drawn behind other entities
This fixes the draw order by drawing all other entities first, before
then drawing all humanoids[1] after, including the player afterwards.
This is actually a regression fix from #191. When I was testing this, I
was thinking about where get a crewmate in front of another entity in
the main game, other than the checkpoints in Intermission 1. And then I
thought about the teleporters, because I remember the pre-Deep Space
cutscene in Dimension Open looking funny because Vita ended up being
behind the teleporter. (Actually, a lot of the cutscenes of Dimension
Open look funny because of crewmates standing behind terminals.)
So then I tried to get crewmates in front of teleporters. It actually
turns out that you can't do it for most of them... except for Verdigris.
And then that's what I realized why there was an oddity in WarpClass.cpp
when I was removing the `active` system from the game - for some reason,
the game put a hole in `obj.entities` between the teleporter and the
player when loading the room Murdering Twinmaker. In a violation of
Chesterton's Fence (the principle that you should understand something
before removing it), I shrugged it off and decided "there's no way to
support having holes with my new system, and having holes is probably
bad anyway, so I'm going to remove this and move on". The fact that
there wasn't any comments clarifying the mysterious code didn't help
(but, this *was* 2.2 code after all; have you *seen* 2.2 code?!).
And it turns out that this maneuver was done so Verdigris would fill
that hole when he got created, and Verdigris being first before the
teleporter would mean he would be drawn in front of the teleporter,
instead of being behind it. So ever since
b1b1474b7bbc3ceddea24f689a7ddb050cfe4490 got merged, there has actually
been a regression from 2.2 where Verdigris got drawn behind the
teleporter in Murdering Twinmaker, instead of properly being in front of
it like in 2.2 and previous.
This patch fixes that regression, but it actually properly fixes it
instead of hacking around with the `active` system.
Closes #426.
[1]: I'm going to go on a rant here, so hear me out. It's not explicitly
stated that the characters in VVVVVV are human. So, given this
information, what do we call them? Well, the VVVVVV community (at least
the custom levels one, I don't think the speedrunning community does
this or is preoccupied with lore in the first place) decided to call
them "villis", because of the roomname "The Villi People" - which is
only one blunder in a series of awful headcanons based off of the
assumption that the intent of Bennett Foddy (who named the roomnames)
was to decree some sort of lore to the game. Another one being
"Verdigris can't flip" because of "Green Dudes Can't Flip". Then an OC
(original character) got named based off of "The Voon Show" too. And so
on and so forth.
2020-11-01 07:23:40 +01:00
|
|
|
for (int i = obj.entities.size() - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (!obj.entities[i].ishumanoid())
|
|
|
|
{
|
|
|
|
drawentity(i, yoff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = obj.entities.size() - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (obj.entities[i].ishumanoid())
|
|
|
|
{
|
|
|
|
drawentity(i, yoff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = obj.entities.size() - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
drawentity(i, yoff);
|
|
|
|
}
|
2020-11-01 05:38:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawentity(const int i, const int yoff)
|
|
|
|
{
|
|
|
|
if (!INBOUNDS_VEC(i, obj.entities))
|
|
|
|
{
|
|
|
|
WHINE_ONCE("drawentity() out-of-bounds!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-11-01 05:39:19 +01:00
|
|
|
if (obj.entities[i].invis)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-11-01 05:38:15 +01:00
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
point tpoint;
|
|
|
|
|
|
|
|
SDL_Rect drawRect;
|
|
|
|
|
2020-06-30 00:27:23 +02:00
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
|
|
|
// Special case for gray Warp Zone tileset!
|
2020-10-20 08:57:23 +02:00
|
|
|
const int room = game.roomx-100 + (game.roomy-100) * ed.maxwidth;
|
|
|
|
const bool custom_gray = INBOUNDS_ARR(room, ed.level)
|
2020-06-30 00:27:23 +02:00
|
|
|
&& ed.level[room].tileset == 3 && ed.level[room].tilecol == 6;
|
|
|
|
#else
|
2020-10-20 08:57:23 +02:00
|
|
|
const bool custom_gray = false;
|
2020-06-30 00:27:23 +02:00
|
|
|
#endif
|
|
|
|
|
2020-10-20 08:55:49 +02:00
|
|
|
std::vector<SDL_Surface*>& tilesvec = (map.custommode && !map.finalmode) ? entcolours : tiles;
|
2020-04-25 23:29:26 +02:00
|
|
|
|
2020-10-20 08:55:49 +02:00
|
|
|
std::vector<SDL_Surface*>& spritesvec = flipmode ? flipsprites : sprites;
|
2020-04-26 04:47:09 +02:00
|
|
|
|
2020-11-01 05:39:19 +01:00
|
|
|
const int xp = lerp(obj.entities[i].lerpoldxp, obj.entities[i].xp);
|
|
|
|
const int yp = lerp(obj.entities[i].lerpoldyp, obj.entities[i].yp);
|
2020-04-29 01:02:55 +02:00
|
|
|
|
2020-11-01 05:39:19 +01:00
|
|
|
switch (obj.entities[i].size)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
{
|
|
|
|
// Sprites
|
|
|
|
if (!INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec))
|
2020-04-26 20:13:47 +02:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
tpoint.x = xp;
|
|
|
|
tpoint.y = yp - yoff;
|
|
|
|
setcolreal(obj.entities[i].realcol);
|
|
|
|
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe], NULL, backBuffer, &drawRect, ct);
|
|
|
|
|
|
|
|
//screenwrapping!
|
|
|
|
point wrappedPoint;
|
|
|
|
bool wrapX = false;
|
|
|
|
bool wrapY = false;
|
|
|
|
|
|
|
|
wrappedPoint.x = tpoint.x;
|
|
|
|
if (tpoint.x < 0)
|
2020-07-29 18:17:28 +02:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
wrapX = true;
|
|
|
|
wrappedPoint.x += 320;
|
|
|
|
}
|
|
|
|
else if (tpoint.x > 300)
|
|
|
|
{
|
|
|
|
wrapX = true;
|
|
|
|
wrappedPoint.x -= 320;
|
|
|
|
}
|
|
|
|
|
|
|
|
wrappedPoint.y = tpoint.y;
|
|
|
|
if (tpoint.y < 0)
|
|
|
|
{
|
|
|
|
wrapY = true;
|
|
|
|
wrappedPoint.y += 230;
|
|
|
|
}
|
|
|
|
else if (tpoint.y > 210)
|
|
|
|
{
|
|
|
|
wrapY = true;
|
|
|
|
wrappedPoint.y -= 230;
|
|
|
|
}
|
2020-04-26 20:13:47 +02:00
|
|
|
|
2020-11-01 05:39:19 +01:00
|
|
|
const bool isInWrappingAreaOfTower = map.towermode && !map.minitowermode && map.ypos >= 500 && map.ypos <= 5000;
|
|
|
|
if (wrapX && (map.warpx || isInWrappingAreaOfTower))
|
|
|
|
{
|
2020-04-26 20:13:47 +02:00
|
|
|
drawRect = sprites_rect;
|
2020-11-01 05:39:19 +01:00
|
|
|
drawRect.x += wrappedPoint.x;
|
2020-04-26 20:13:47 +02:00
|
|
|
drawRect.y += tpoint.y;
|
2020-10-20 08:55:49 +02:00
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe], NULL, backBuffer, &drawRect, ct);
|
2020-07-29 18:17:28 +02:00
|
|
|
}
|
2020-11-01 05:39:19 +01:00
|
|
|
if (wrapY && map.warpy)
|
|
|
|
{
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += wrappedPoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe], NULL, backBuffer, &drawRect, ct);
|
|
|
|
}
|
|
|
|
if (wrapX && wrapY && map.warpx && map.warpy)
|
|
|
|
{
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += wrappedPoint.x;
|
|
|
|
drawRect.y += wrappedPoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe], NULL, backBuffer, &drawRect, ct);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1:
|
|
|
|
// Tiles
|
|
|
|
if (!INBOUNDS_VEC(obj.entities[i].drawframe, tiles))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
tpoint.x = xp;
|
|
|
|
tpoint.y = yp - yoff;
|
|
|
|
drawRect = tiles_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
|
|
|
BlitSurfaceStandard(tiles[obj.entities[i].drawframe],NULL, backBuffer, &drawRect);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
case 8:
|
|
|
|
{
|
|
|
|
// Special: Moving platform, 4 tiles or 8 tiles
|
|
|
|
if (!INBOUNDS_VEC(obj.entities[i].drawframe, tilesvec))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
tpoint.x = xp;
|
|
|
|
tpoint.y = yp - yoff;
|
|
|
|
int thiswidth = 4;
|
|
|
|
if (obj.entities[i].size == 8)
|
|
|
|
{
|
|
|
|
thiswidth = 8;
|
|
|
|
}
|
|
|
|
for (int ii = 0; ii < thiswidth; ii++)
|
|
|
|
{
|
2020-04-26 20:13:47 +02:00
|
|
|
drawRect = tiles_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
2020-11-01 05:39:19 +01:00
|
|
|
drawRect.x += 8 * ii;
|
|
|
|
if (custom_gray)
|
2020-06-14 03:35:12 +02:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
colourTransform temp_ct;
|
|
|
|
temp_ct.colour = 0xFFFFFFFF;
|
|
|
|
BlitSurfaceTinted(tilesvec[obj.entities[i].drawframe],NULL, backBuffer, &drawRect, temp_ct);
|
2020-06-14 03:35:12 +02:00
|
|
|
}
|
2020-11-01 05:39:19 +01:00
|
|
|
else
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
BlitSurfaceStandard(tilesvec[obj.entities[i].drawframe],NULL, backBuffer, &drawRect);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
2020-04-26 20:13:47 +02:00
|
|
|
}
|
2020-11-01 05:39:19 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 3: // Big chunky pixels!
|
|
|
|
prect.x = xp;
|
|
|
|
prect.y = yp - yoff;
|
|
|
|
FillRect(backBuffer, prect, obj.entities[i].realcol);
|
|
|
|
break;
|
|
|
|
case 4: // Small pickups
|
|
|
|
setcolreal(obj.entities[i].realcol);
|
|
|
|
drawhuetile(xp, yp - yoff, obj.entities[i].tile);
|
|
|
|
break;
|
|
|
|
case 5: //Horizontal Line
|
|
|
|
{
|
|
|
|
int oldw = obj.entities[i].w;
|
|
|
|
if ((game.swngame == 3 || kludgeswnlinewidth) && obj.getlineat(84 - 32) == i)
|
2020-05-02 02:57:07 +02:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
oldw -= 24;
|
|
|
|
}
|
|
|
|
line_rect.x = xp;
|
|
|
|
line_rect.y = yp - yoff;
|
|
|
|
line_rect.w = lerp(oldw, obj.entities[i].w);
|
|
|
|
line_rect.h = 1;
|
|
|
|
drawgravityline(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 6: //Vertical Line
|
|
|
|
line_rect.x = xp;
|
|
|
|
line_rect.y = yp - yoff;
|
|
|
|
line_rect.w = 1;
|
|
|
|
line_rect.h = obj.entities[i].h;
|
|
|
|
drawgravityline(i);
|
|
|
|
break;
|
|
|
|
case 7: //Teleporter
|
|
|
|
drawtele(xp, yp - yoff, obj.entities[i].drawframe, obj.entities[i].realcol);
|
|
|
|
break;
|
|
|
|
//case 8: // Special: Moving platform, 8 tiles
|
|
|
|
// Note: This code is in the 4-tile code
|
|
|
|
break;
|
|
|
|
case 9: // Really Big Sprite! (2x2)
|
|
|
|
if (!INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setcolreal(obj.entities[i].realcol);
|
|
|
|
|
|
|
|
tpoint.x = xp;
|
|
|
|
tpoint.y = yp - yoff;
|
|
|
|
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe],NULL, backBuffer, &drawRect, ct);
|
|
|
|
|
|
|
|
tpoint.x = xp+32;
|
|
|
|
tpoint.y = yp - yoff;
|
|
|
|
//
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe+1],NULL, backBuffer, &drawRect, ct);
|
|
|
|
|
|
|
|
tpoint.x = xp;
|
|
|
|
tpoint.y = yp+32 - yoff;
|
|
|
|
//
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe+12],NULL, backBuffer, &drawRect, ct);
|
|
|
|
|
|
|
|
tpoint.x = xp+32;
|
|
|
|
tpoint.y = yp+32 - yoff;
|
|
|
|
//
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe + 13],NULL, backBuffer, &drawRect, ct);
|
|
|
|
break;
|
|
|
|
case 10: // 2x1 Sprite
|
|
|
|
if (!INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setcolreal(obj.entities[i].realcol);
|
|
|
|
|
|
|
|
tpoint.x = xp;
|
|
|
|
tpoint.y = yp - yoff;
|
|
|
|
//
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe],NULL, backBuffer, &drawRect, ct);
|
|
|
|
|
|
|
|
tpoint.x = xp+32;
|
|
|
|
tpoint.y = yp - yoff;
|
|
|
|
//
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe+1],NULL, backBuffer, &drawRect, ct);
|
|
|
|
break;
|
|
|
|
case 11: //The fucking elephant
|
|
|
|
setcolreal(obj.entities[i].realcol);
|
|
|
|
drawimagecol(3, xp, yp - yoff);
|
|
|
|
break;
|
|
|
|
case 12: // Regular sprites that don't wrap
|
|
|
|
if (!INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
tpoint.x = xp;
|
|
|
|
tpoint.y = yp - yoff;
|
|
|
|
setcolreal(obj.entities[i].realcol);
|
|
|
|
//
|
|
|
|
drawRect = sprites_rect;
|
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
|
|
|
BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe],NULL, backBuffer, &drawRect, ct);
|
|
|
|
|
|
|
|
|
|
|
|
//if we're outside the screen, we need to draw indicators
|
|
|
|
|
|
|
|
if (obj.entities[i].xp < -20 && obj.entities[i].vx > 0)
|
|
|
|
{
|
|
|
|
if (obj.entities[i].xp < -100)
|
2020-05-02 02:57:07 +02:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
tpoint.x = -5 + (int(( -obj.entities[i].xp) / 10));
|
2020-05-02 02:57:07 +02:00
|
|
|
}
|
2020-11-01 05:39:19 +01:00
|
|
|
else
|
2020-06-14 03:35:12 +02:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
tpoint.x = 5;
|
2020-06-14 03:35:12 +02:00
|
|
|
}
|
2020-04-26 20:13:47 +02:00
|
|
|
|
2020-11-01 05:39:19 +01:00
|
|
|
tpoint.y = tpoint.y+4;
|
2020-04-26 20:13:47 +02:00
|
|
|
|
|
|
|
|
2020-11-01 05:39:19 +01:00
|
|
|
drawRect = tiles_rect;
|
2020-04-26 20:13:47 +02:00
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
2020-11-01 05:39:19 +01:00
|
|
|
BlitSurfaceColoured(tiles[1167],NULL, backBuffer, &drawRect, ct);
|
2020-04-26 20:13:47 +02:00
|
|
|
|
2020-11-01 05:39:19 +01:00
|
|
|
}
|
|
|
|
else if (obj.entities[i].xp > 340 && obj.entities[i].vx < 0)
|
|
|
|
{
|
|
|
|
if (obj.entities[i].xp > 420)
|
2020-06-14 03:35:12 +02:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
tpoint.x = 320 - (int(( obj.entities[i].xp-320) / 10));
|
2020-06-14 03:35:12 +02:00
|
|
|
}
|
2020-11-01 05:39:19 +01:00
|
|
|
else
|
2020-06-14 03:35:12 +02:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
tpoint.x = 310;
|
2020-06-14 03:35:12 +02:00
|
|
|
}
|
2020-11-01 05:39:19 +01:00
|
|
|
|
|
|
|
tpoint.y = tpoint.y+4;
|
2020-04-26 20:13:47 +02:00
|
|
|
//
|
2020-11-01 05:39:19 +01:00
|
|
|
|
|
|
|
drawRect = tiles_rect;
|
2020-04-26 20:13:47 +02:00
|
|
|
drawRect.x += tpoint.x;
|
|
|
|
drawRect.y += tpoint.y;
|
2020-11-01 05:39:19 +01:00
|
|
|
BlitSurfaceColoured(tiles[1166],NULL, backBuffer, &drawRect, ct);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
{
|
|
|
|
//Special for epilogue: huge hero!
|
|
|
|
if (!INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec))
|
2020-04-26 20:13:47 +02:00
|
|
|
{
|
2020-11-01 05:39:19 +01:00
|
|
|
return;
|
|
|
|
}
|
2020-04-26 04:50:09 +02:00
|
|
|
|
2020-11-01 05:39:19 +01:00
|
|
|
tpoint.x = xp; tpoint.y = yp - yoff;
|
|
|
|
setcolreal(obj.entities[i].realcol);
|
2021-03-18 22:10:55 +01:00
|
|
|
setRect(drawRect, Sint16(xp), Sint16(yp - yoff), Sint16(sprites_rect.x * 6), Sint16(sprites_rect.y * 6 ) );
|
2020-11-01 05:39:19 +01:00
|
|
|
SDL_Surface* TempSurface = ScaleSurface( spritesvec[obj.entities[i].drawframe], 6 * sprites_rect.w,6* sprites_rect.h );
|
|
|
|
BlitSurfaceColoured(TempSurface, NULL , backBuffer, &drawRect, ct );
|
|
|
|
SDL_FreeSurface(TempSurface);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-11-01 05:39:19 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2020-03-31 21:26:11 +02:00
|
|
|
void Graphics::drawbackground( int t )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
int temp = 0;
|
|
|
|
|
|
|
|
switch(t)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
//Starfield
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-07-03 11:31:13 +02:00
|
|
|
for (int i = 0; i < numstars; i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
stars[i].w = 2;
|
|
|
|
stars[i].h = 2;
|
2020-04-29 04:30:37 +02:00
|
|
|
SDL_Rect star_rect = stars[i];
|
|
|
|
star_rect.x = lerp(star_rect.x + starsspeed[i], star_rect.x);
|
2020-01-01 21:29:24 +01:00
|
|
|
if (starsspeed[i] <= 6)
|
|
|
|
{
|
2020-04-29 04:30:37 +02:00
|
|
|
FillRect(backBuffer,star_rect, getRGB(0x22,0x22,0x22));
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-29 04:30:37 +02:00
|
|
|
FillRect(backBuffer,star_rect, getRGB(0x55,0x55,0x55));
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
2020-11-02 22:02:51 +01:00
|
|
|
{
|
2021-01-14 04:39:50 +01:00
|
|
|
int bcol = 0, bcol2 = 0;
|
2020-11-02 22:02:51 +01:00
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
//Lab
|
|
|
|
switch(rcol)
|
|
|
|
{
|
|
|
|
//Akward ordering to match tileset
|
|
|
|
case 0:
|
|
|
|
bcol2 = RGBflip(0, 16*backboxint[0], 16*backboxint[0]);
|
|
|
|
break; //Cyan
|
|
|
|
case 1:
|
|
|
|
bcol2 = RGBflip(16*backboxint[0], 0, 0);
|
|
|
|
break; //Red
|
|
|
|
case 2:
|
|
|
|
bcol2 = RGBflip(16*backboxint[0], 0, 16*backboxint[0]);
|
|
|
|
break; //Purple
|
|
|
|
case 3:
|
|
|
|
bcol2 = RGBflip(0, 0, 16*backboxint[0]);
|
|
|
|
break; //Blue
|
|
|
|
case 4:
|
|
|
|
bcol2 = RGBflip(16*backboxint[0], 16*backboxint[0], 0);
|
|
|
|
break; //Yellow
|
|
|
|
case 5:
|
|
|
|
bcol2 = RGBflip(0, 16 * backboxint[0], 0);
|
|
|
|
break; //Green
|
|
|
|
case 6:
|
|
|
|
//crazy case
|
|
|
|
switch(spcol)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
bcol2 = RGBflip(0, 16*backboxint[0], 16*backboxint[0]);
|
|
|
|
break; //Cyan
|
|
|
|
case 1:
|
|
|
|
bcol2 = RGBflip(0, (spcoldel+1)*backboxint[0], 16*backboxint[0]);
|
|
|
|
break; //Cyan
|
|
|
|
case 2:
|
|
|
|
bcol2 = RGBflip(0, 0, 16*backboxint[0]);
|
|
|
|
break; //Blue
|
|
|
|
case 3:
|
|
|
|
bcol2 = RGBflip((16-spcoldel)*backboxint[0], 0, 16*backboxint[0]);
|
|
|
|
break; //Blue
|
|
|
|
case 4:
|
|
|
|
bcol2 = RGBflip(16*backboxint[0], 0, 16*backboxint[0]);
|
|
|
|
break; //Purple
|
|
|
|
case 5:
|
|
|
|
bcol2 = RGBflip(16*backboxint[0], 0, (spcoldel+1)*backboxint[0]);
|
|
|
|
break; //Purple
|
|
|
|
case 6:
|
|
|
|
bcol2 = RGBflip(16*backboxint[0], 0, 0);
|
|
|
|
break; //Red
|
|
|
|
case 7:
|
|
|
|
bcol2 = RGBflip(16*backboxint[0], (16-spcoldel)*backboxint[0], 0);
|
|
|
|
break; //Red
|
|
|
|
case 8:
|
|
|
|
bcol2 = RGBflip(16*backboxint[0], 16*backboxint[0], 0);
|
|
|
|
break; //Yellow
|
|
|
|
case 9:
|
|
|
|
bcol2 = RGBflip((spcoldel+1)*backboxint[0], 16*backboxint[0], 0);
|
|
|
|
break; //Yellow
|
|
|
|
case 10:
|
|
|
|
bcol2 = RGBflip(0, 16 * backboxint[0], 0);
|
|
|
|
break; //Green
|
|
|
|
case 11:
|
|
|
|
bcol2 = RGBflip(0, 16 * backboxint[0], (16-spcoldel)*backboxint[0]);
|
|
|
|
break; //Green
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FillRect(backBuffer,bcol2);
|
|
|
|
|
2020-07-03 11:31:13 +02:00
|
|
|
for (int i = 0; i < numbackboxes; i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
switch(rcol)
|
|
|
|
{
|
|
|
|
//Akward ordering to match tileset
|
|
|
|
case 0:
|
|
|
|
bcol = RGBflip(16, 128*backboxint[0], 128*backboxint[0]);
|
|
|
|
break; //Cyan
|
|
|
|
case 1:
|
|
|
|
bcol = RGBflip(128*backboxint[0], 16, 16);
|
|
|
|
break; //Red
|
|
|
|
case 2:
|
|
|
|
bcol = RGBflip(128*backboxint[0], 16, 128*backboxint[0]);
|
|
|
|
break; //Purple
|
|
|
|
case 3:
|
|
|
|
bcol = RGBflip(16, 16, 128*backboxint[0]);
|
|
|
|
break; //Blue
|
|
|
|
case 4:
|
|
|
|
bcol = RGBflip(128*backboxint[0], 128*backboxint[0], 16);
|
|
|
|
break; //Yellow
|
|
|
|
case 5:
|
|
|
|
bcol = RGBflip(16, 128 * backboxint[0], 16);
|
|
|
|
break; //Green
|
|
|
|
case 6:
|
|
|
|
//crazy case
|
|
|
|
switch(spcol)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
bcol = RGBflip(16, 128*backboxint[0], 128*backboxint[0]);
|
|
|
|
break; //Cyan
|
|
|
|
case 1:
|
|
|
|
bcol = RGBflip(16, ((spcoldel+1)*8)*backboxint[0], 128*backboxint[0]);
|
|
|
|
break; //Cyan
|
|
|
|
case 2:
|
|
|
|
bcol = RGBflip(16, 16, 128*backboxint[0]);
|
|
|
|
break; //Blue
|
|
|
|
case 3:
|
|
|
|
bcol = RGBflip((128-(spcoldel*8))*backboxint[0], 16, 128*backboxint[0]);
|
|
|
|
break; //Blue
|
|
|
|
case 4:
|
|
|
|
bcol = RGBflip(128*backboxint[0], 16, 128*backboxint[0]);
|
|
|
|
break; //Purple
|
|
|
|
case 5:
|
|
|
|
bcol = RGBflip(128*backboxint[0], 16, ((spcoldel+1)*8)*backboxint[0]);
|
|
|
|
break; //Purple
|
|
|
|
case 6:
|
|
|
|
bcol = RGBflip(128*backboxint[0], 16, 16);
|
|
|
|
break; //Red
|
|
|
|
case 7:
|
|
|
|
bcol = RGBflip(128*backboxint[0], (128-(spcoldel*8))*backboxint[0], 16);
|
|
|
|
break; //Red
|
|
|
|
case 8:
|
|
|
|
bcol = RGBflip(128*backboxint[0], 128*backboxint[0], 16);
|
|
|
|
break; //Yellow
|
|
|
|
case 9:
|
|
|
|
bcol = RGBflip(((spcoldel+1)*8)*backboxint[0], 128*backboxint[0], 16);
|
|
|
|
break; //Yellow
|
|
|
|
case 10:
|
|
|
|
bcol = RGBflip(16, 128 * backboxint[0], 16);
|
|
|
|
break; //Green
|
|
|
|
case 11:
|
|
|
|
bcol = RGBflip(16, 128 * backboxint[0], (128-(spcoldel*8))*backboxint[0]);
|
|
|
|
break; //Green
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2020-04-29 04:45:18 +02:00
|
|
|
|
2020-04-29 04:54:53 +02:00
|
|
|
SDL_Rect backboxrect = backboxes[i];
|
2020-04-29 04:45:18 +02:00
|
|
|
backboxrect.x = lerp(backboxes[i].x - backboxvx[i], backboxes[i].x);
|
|
|
|
backboxrect.y = lerp(backboxes[i].y - backboxvy[i], backboxes[i].y);
|
|
|
|
|
|
|
|
FillRect(backBuffer, backboxrect, bcol);
|
|
|
|
backboxrect.x += 1;
|
|
|
|
backboxrect.y += 1;
|
|
|
|
backboxrect.w -= 2;
|
|
|
|
backboxrect.h -= 2;
|
2020-01-01 21:29:24 +01:00
|
|
|
FillRect(backBuffer,backboxrect, bcol2);
|
|
|
|
}
|
|
|
|
break;
|
2020-11-02 22:02:51 +01:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
case 3: //Warp zone (horizontal)
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-11-03 01:54:17 +01:00
|
|
|
BlitSurfaceStandard(warpbuffer, NULL, warpbuffer_lerp, NULL);
|
|
|
|
ScrollSurface(warpbuffer_lerp, lerp(0, -3), 0);
|
|
|
|
BlitSurfaceStandard(warpbuffer_lerp, &towerbuffer_rect, backBuffer, NULL);
|
2020-01-01 21:29:24 +01:00
|
|
|
break;
|
|
|
|
case 4: //Warp zone (vertical)
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-11-03 01:54:17 +01:00
|
|
|
SDL_BlitSurface(warpbuffer, NULL, warpbuffer_lerp, NULL);
|
|
|
|
ScrollSurface(warpbuffer_lerp, 0, lerp(0, -3));
|
|
|
|
SDL_BlitSurface(warpbuffer_lerp, &towerbuffer_rect, backBuffer, NULL);
|
2020-01-01 21:29:24 +01:00
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
//Warp zone, central
|
|
|
|
switch(rcol)
|
|
|
|
{
|
|
|
|
//Akward ordering to match tileset
|
|
|
|
case 0:
|
|
|
|
warpbcol = RGBflip(0x0A, 0x10, 0x0E);
|
|
|
|
warpfcol = RGBflip(0x10, 0x22, 0x21);
|
|
|
|
break; //Cyan
|
|
|
|
case 1:
|
|
|
|
warpbcol = RGBflip(0x11, 0x09, 0x0B);
|
|
|
|
warpfcol = RGBflip(0x22, 0x10, 0x11);
|
|
|
|
break; //Red
|
|
|
|
case 2:
|
|
|
|
warpbcol = RGBflip(0x0F, 0x0A, 0x10);
|
|
|
|
warpfcol = RGBflip(0x22,0x10,0x22);
|
|
|
|
break; //Purple
|
|
|
|
case 3:
|
|
|
|
warpbcol = RGBflip(0x0A, 0x0B, 0x10);
|
|
|
|
warpfcol = RGBflip(0x10, 0x10, 0x22);
|
|
|
|
break; //Blue
|
|
|
|
case 4:
|
|
|
|
warpbcol = RGBflip(0x10, 0x0D, 0x0A);
|
|
|
|
warpfcol = RGBflip(0x22, 0x1E, 0x10);
|
|
|
|
break; //Yellow
|
|
|
|
case 5:
|
|
|
|
warpbcol = RGBflip(0x0D, 0x10, 0x0A);
|
|
|
|
warpfcol = RGBflip(0x14, 0x22, 0x10);
|
|
|
|
break; //Green
|
|
|
|
case 6:
|
|
|
|
warpbcol = RGBflip(0x0A, 0x0A, 0x0A);
|
|
|
|
warpfcol = RGBflip(0x12, 0x12, 0x12);
|
|
|
|
break; //Gray
|
2020-04-02 22:05:48 +02:00
|
|
|
default:
|
|
|
|
warpbcol = RGBflip(0xFF, 0xFF, 0xFF);
|
|
|
|
warpfcol = RGBflip(0xFF, 0xFF, 0xFF);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 10 ; i >= 0; i--)
|
|
|
|
{
|
2020-04-30 00:44:07 +02:00
|
|
|
temp = (i << 4) + lerp(backoffset - 1, backoffset);
|
2020-01-01 21:29:24 +01:00
|
|
|
setwarprect(160 - temp, 120 - temp, temp * 2, temp * 2);
|
|
|
|
if (i % 2 == warpskip)
|
|
|
|
{
|
|
|
|
FillRect(backBuffer, warprect, warpbcol);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FillRect(backBuffer,warprect, warpfcol);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
//Final Starfield
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-07-03 11:31:13 +02:00
|
|
|
for (int i = 0; i < numstars; i++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-29 04:52:59 +02:00
|
|
|
stars[i].w = 2;
|
|
|
|
stars[i].h = 2;
|
|
|
|
SDL_Rect star_rect = stars[i];
|
|
|
|
star_rect.y = lerp(star_rect.y + starsspeed[i], star_rect.y);
|
2020-01-01 21:29:24 +01:00
|
|
|
if (starsspeed[i] <= 8)
|
|
|
|
{
|
2020-04-29 04:52:59 +02:00
|
|
|
FillRect(backBuffer, star_rect, getRGB(0x22, 0x22, 0x22));
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-29 04:52:59 +02:00
|
|
|
FillRect(backBuffer, star_rect, getRGB(0x55, 0x55, 0x55));
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
//Static, unscrolling section of the tower
|
|
|
|
for (int j = 0; j < 30; j++)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 40; i++)
|
|
|
|
{
|
|
|
|
drawtile3(i * 8, j * 8, map.tower.backat(i, j, 200), 15);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
//Static, unscrolling section of the tower
|
|
|
|
for (int j = 0; j < 30; j++)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 40; i++)
|
|
|
|
{
|
|
|
|
drawtile3(i * 8, j * 8, map.tower.backat(i, j, 200), 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
//Static, unscrolling section of the tower
|
|
|
|
for (int j = 0; j < 30; j++)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 40; i++)
|
|
|
|
{
|
|
|
|
drawtile3(i * 8, j * 8, map.tower.backat(i, j, 600), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-29 04:28:16 +02:00
|
|
|
void Graphics::updatebackground(int t)
|
|
|
|
{
|
|
|
|
switch (t)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
//Starfield
|
2020-07-03 11:31:13 +02:00
|
|
|
for (int i = 0; i < numstars; i++)
|
2020-04-29 04:28:16 +02:00
|
|
|
{
|
|
|
|
stars[i].w = 2;
|
|
|
|
stars[i].h = 2;
|
|
|
|
stars[i].x -= Sint16(starsspeed[i]);
|
|
|
|
if (stars[i].x < -10)
|
|
|
|
{
|
|
|
|
stars[i].x += 340;
|
|
|
|
stars[i].y = int(fRandom() * 240);
|
|
|
|
stars[i].w = 2;
|
|
|
|
starsspeed[i] = 4+int(fRandom()*4);
|
|
|
|
}
|
|
|
|
}
|
2020-04-29 04:33:33 +02:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
//Lab
|
2020-04-29 04:47:37 +02:00
|
|
|
if (rcol == 6)
|
|
|
|
{
|
|
|
|
//crazy caze
|
|
|
|
spcoldel--;
|
|
|
|
if (spcoldel <= 0)
|
|
|
|
{
|
|
|
|
spcoldel = 15;
|
|
|
|
spcol++;
|
|
|
|
if (spcol >= 12) spcol = 0;
|
|
|
|
}
|
|
|
|
}
|
2020-07-03 11:31:13 +02:00
|
|
|
for (int i = 0; i < numbackboxes; i++)
|
2020-04-29 04:33:33 +02:00
|
|
|
{
|
|
|
|
backboxes[i].x += backboxvx[i];
|
|
|
|
backboxes[i].y += backboxvy[i];
|
|
|
|
if (backboxes[i].x < -40)
|
|
|
|
{
|
|
|
|
backboxes[i].x = 320;
|
|
|
|
backboxes[i].y = fRandom() * 240;
|
|
|
|
}
|
|
|
|
if (backboxes[i].x > 320)
|
|
|
|
{
|
|
|
|
backboxes[i].x = -32;
|
|
|
|
backboxes[i].y = fRandom() * 240;
|
|
|
|
}
|
|
|
|
if (backboxes[i].y < -40)
|
|
|
|
{
|
|
|
|
backboxes[i].y = 240;
|
|
|
|
backboxes[i].x = fRandom() * 320;
|
|
|
|
}
|
|
|
|
if (backboxes[i].y > 260)
|
|
|
|
{
|
|
|
|
backboxes[i].y = -32;
|
|
|
|
backboxes[i].x = fRandom() * 320;
|
|
|
|
}
|
|
|
|
}
|
2020-04-29 04:50:03 +02:00
|
|
|
break;
|
2020-04-29 19:37:56 +02:00
|
|
|
case 3: //Warp zone (horizontal)
|
2020-05-02 22:11:36 +02:00
|
|
|
{
|
|
|
|
int temp = 680 + (rcol * 3);
|
2020-04-29 19:37:56 +02:00
|
|
|
backoffset+=3;
|
|
|
|
if (backoffset >= 16) backoffset -= 16;
|
|
|
|
|
|
|
|
if (backgrounddrawn)
|
|
|
|
{
|
2020-11-03 01:54:17 +01:00
|
|
|
ScrollSurface(warpbuffer, -3, 0 );
|
2020-04-29 19:37:56 +02:00
|
|
|
for (int j = 0; j < 15; j++)
|
|
|
|
{
|
2020-05-02 22:11:36 +02:00
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
drawtowertile(317 - backoffset + (i * 16), (j * 16), temp+40); //20*16 = 320
|
|
|
|
drawtowertile(317 - backoffset + (i * 16) + 8, (j * 16), temp + 41);
|
|
|
|
drawtowertile(317 - backoffset + (i * 16), (j * 16) + 8, temp + 80);
|
|
|
|
drawtowertile(317 - backoffset + (i * 16) + 8, (j * 16) + 8, temp + 81);
|
|
|
|
}
|
2020-04-29 19:37:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//draw the whole thing for the first time!
|
|
|
|
backoffset = 0;
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(warpbuffer);
|
2020-04-29 19:37:56 +02:00
|
|
|
for (int j = 0; j < 15; j++)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 21; i++)
|
|
|
|
{
|
|
|
|
drawtowertile((i * 16) - backoffset - 3, (j * 16), temp+40);
|
|
|
|
drawtowertile((i * 16) - backoffset + 8 - 3, (j * 16), temp + 41);
|
|
|
|
drawtowertile((i * 16) - backoffset - 3, (j * 16) + 8, temp + 80);
|
|
|
|
drawtowertile((i * 16) - backoffset + 8 - 3, (j * 16) + 8, temp + 81);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
backgrounddrawn = true;
|
|
|
|
}
|
|
|
|
break;
|
2020-05-02 22:11:36 +02:00
|
|
|
}
|
2020-04-29 20:06:03 +02:00
|
|
|
case 4: //Warp zone (vertical)
|
2020-05-02 22:11:36 +02:00
|
|
|
{
|
|
|
|
int temp = 760 + (rcol * 3);
|
2020-04-29 20:06:03 +02:00
|
|
|
backoffset+=3;
|
|
|
|
if (backoffset >= 16) backoffset -= 16;
|
|
|
|
|
|
|
|
if (backgrounddrawn)
|
|
|
|
{
|
2020-11-03 01:54:17 +01:00
|
|
|
ScrollSurface(warpbuffer,0,-3);
|
2020-05-02 22:11:36 +02:00
|
|
|
for (int j = 0; j < 2; j++)
|
2020-04-29 20:06:03 +02:00
|
|
|
{
|
2020-05-02 22:11:36 +02:00
|
|
|
for (int i = 0; i < 21; i++)
|
|
|
|
{
|
|
|
|
drawtowertile((i * 16), 237 - backoffset + (j * 16), temp + 40); //14*17=240 - 3
|
|
|
|
drawtowertile((i * 16) + 8, 237 - backoffset + (j * 16), temp + 41);
|
|
|
|
drawtowertile((i * 16), 237 - backoffset + (j * 16) + 8, temp + 80);
|
|
|
|
drawtowertile((i * 16) + 8, 237 - backoffset + (j * 16) + 8, temp + 81);
|
|
|
|
}
|
2020-04-29 20:06:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//draw the whole thing for the first time!
|
|
|
|
backoffset = 0;
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(warpbuffer);
|
2020-05-02 22:11:36 +02:00
|
|
|
for (int j = 0; j < 16; j++)
|
2020-04-29 20:06:03 +02:00
|
|
|
{
|
|
|
|
for (int i = 0; i < 21; i++)
|
|
|
|
{
|
|
|
|
drawtowertile((i * 16), (j * 16)- backoffset - 3, temp+40);
|
|
|
|
drawtowertile((i * 16)+ 8, (j * 16)- backoffset - 3, temp + 41);
|
|
|
|
drawtowertile((i * 16), (j * 16)- backoffset + 8 - 3, temp + 80);
|
|
|
|
drawtowertile((i * 16)+ 8, (j * 16)- backoffset + 8 - 3, temp + 81);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
backgrounddrawn = true;
|
|
|
|
}
|
|
|
|
break;
|
2020-05-02 22:11:36 +02:00
|
|
|
}
|
2020-04-30 00:37:39 +02:00
|
|
|
case 5:
|
|
|
|
//Warp zone, central
|
|
|
|
|
|
|
|
backoffset += 1;
|
|
|
|
if (backoffset >= 16)
|
|
|
|
{
|
|
|
|
backoffset -= 16;
|
|
|
|
warpskip = (warpskip + 1) % 2;
|
|
|
|
}
|
|
|
|
break;
|
2020-04-29 04:50:03 +02:00
|
|
|
case 6:
|
|
|
|
//Final Starfield
|
2020-07-03 11:31:13 +02:00
|
|
|
for (int i = 0; i < numstars; i++)
|
2020-04-29 04:50:03 +02:00
|
|
|
{
|
|
|
|
stars[i].w = 2;
|
|
|
|
stars[i].h = 2;
|
|
|
|
stars[i].y -= starsspeed[i];
|
|
|
|
if (stars[i].y < -10)
|
|
|
|
{
|
|
|
|
stars[i].y += 260;
|
|
|
|
stars[i].x = fRandom() * 320;
|
|
|
|
starsspeed[i] = 5+(fRandom()*5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2020-04-29 04:28:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::drawmap(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
if (!foregrounddrawn)
|
|
|
|
{
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(foregroundBuffer);
|
2020-01-01 21:29:24 +01:00
|
|
|
if(map.tileset==0)
|
|
|
|
{
|
2020-06-14 20:21:32 +02:00
|
|
|
for (int j = 0; j < 30; j++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
for (int i = 0; i < 40; i++)
|
|
|
|
{
|
|
|
|
if(map.contents[i + map.vmult[j]]>0) drawforetile(i * 8, j * 8, map.contents[i + map.vmult[j]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (map.tileset == 1)
|
|
|
|
{
|
Add and draw one more row to all rooms with roomnames
Since translucent roomname backgrounds were introduced in
TerryCavanagh/VVVVVV#122, it exposes one glaring flaw with the game that
until now has been kept hidden: in rooms with room names, the game
cheapens out with the tile data and doesn't have a 30th row, because the
room name would hide the missing row. As a result, rooms with room names
have 29 rows instead of 30 to fill up the entire screen. And it looks
really weird when there's nothing but empty space behind the translucent
room name background.
To remedy this, I added one row to each room with a room name in the level.
First, I had to filter out all the rooms with no room names. However, that's
actually all contained in Otherlevel.cpp, the Overworld, which contains 221
rooms (8 of which are the Secret Lab, 6 more of which are the Ship, so 207 are
the actual Overworld, right? Wrong, 2 of those Overworld no-roomname rooms are
in the Lab, so there are actually 205 Overworld rooms). The remaining level
data files all contain rooms with room names.
But the process wasn't that easy. I noticed a while ago that each room
contains 29 `tmap.push_back()`s, one for each row of the room, and each row is
simply a string containing the 40 tiles for that row, concatenated with
commas.
However, I decided to actually check my intuition by doing a grep on each
level file and counting the number of results, for example `grep 'push_back'
Labclass.cpp | wc -l`. Whatever number comes out should be divisible by 29.
That particular grep on Labclass.cpp returns 1306, which divided by 29 is 45
with a remainder of 1.
So what does that mean? Does that mean there's 45 rooms each, and 1 leftover
row? Well, not exactly. The extra row comes from the fact that Outer Space has
30 rows instead of 29. Outer Space is the room that comes up when the game
finds a room is non-existent, which shouldn't happen with a properly-working
game, except in Outside Dimension VVVVVV. In fact, each level file has their
own Outer Space, and every single Outer Space also has 30 rooms. So really,
this means there are 44 rooms in the Lab and one Outer Space room. (Well, in
reality, there are 46 rooms in the Lab, because 2 of them use the Outside
tileset but have no room names, so they're stored in Otherlevel.cpp instead.)
We find the same result for the Warp Zone. `grep 'push_back' WarpClass.cpp |
wc -l` returns 697, which is 24 remainder 1, meaning 23 rooms of 29 rows and 1
room of 30 rows, which corresponds with 23 rooms in the Warp Zone and one
Outer Space room.
However, Outside Dimension VVVVVV + Tower Hallways and Space Station 1 and 2
are both odd curiosities. Finalclass.cpp contains Outside Dimension VVVVVV,
(which is Intermission 1 and 2 and the Final Level), but also the Tower
Hallway rooms, i.e. the auxiliary Tower rooms that are not a part of the main
tower. Spacestation2.cpp contains both Space Station 1 and 2, so don't be
deceived by the name.
`grep 'push_back' Finalclass.cpp | wc -l` returns 1597, which is actually 55
remainder 2. So... are there two rooms with 30 rows? Yes, in fact, The
Gravitron and Outer Space both contain 30 rows. So there are actually 55 rooms
stored in Finalclass.cpp (not including the minitowers Panic Room and The
Final Challenge), 54 rooms of actual level data and one Outer Space room, and
breaking down the 54 rooms even further, 51 of them are actually in Outside
Dimension VVVVVV and 3 of them are Tower Hallways. Of the 51 Outside Dimension
VVVVVV rooms, 14 of those are Intermission 1, 4 of them are Intermission 2,
and the rest of the 33 rooms are the Final Level (again, not including the
minitowers).
`grep 'push_back' Spacestation2.cpp | wc -l` returns 2148, which is 74
remainder 2. Are there two rooms with 30 rows again? No; one of those counted
2148 rows is a false-positive, because there's an if-else in Prize for the
Reckless that replaces the row with spikes with a row without spikes if you
are in a time trial or in No Death Mode. So there's 73 rooms in Space Station
1 and 2, and one Outer Space room.
With all this in mind, I decided to duplicate the current last row of each
room, the 29th row, to add a 30th row. However, I wasn't going to do this
automatically! But neither was I going to write some kludge-y code to parse
each nightmare of a level file and duplicate the rows that way.
Enter: Vim macros! (Er, well, actually, I use Neovim.) I first did
`/push_back`, so that pressing `n` would keep going to the next `push_back` in
the file. Then I went to the 29th row of the first room in the file, did a
`Yp`, and then started my macro with `qq`. The macro went like this: `30nYp`,
which is simply going to the 29th row of the next room over and duplicating
it. And that's all there was to it. However, I had to make sure that (1) my
cursor was before the `push_back` on the line of the 29th row of the room, and
(2) that I didn't skip rooms, both of which were problems I encountered when
pressing Ctrl+Z a given invocation of the macro (the Ctrl+Z is just a
metaphor, you actually undo by typing `u` in Vim). And also I had to make sure
to be careful around the extra lines of `push_back`s in Prize for the Reckless
and The Gravitron, and make sure I didn't run past the end of the file and
loop back around. Thankfully, all Outer Space rooms are at the end of each
file.
But first, I had to increase the number of rows drawn in Graphics.cpp by 1 in
order to compensate for this, and do the same when reading the tile data in
Map.cpp. I had to change fillcontent(), drawmap(), drawfinalmap(),
drawtowermap(), and drawtowermap_nobackground(). Funnily enough, the tower
functions already used 30 rows, but I guess it's an off-by-one due to the
camera scrolling, so they now draw 31 rows each.
Then, I went in-game to make sure that the row behind each room name looked
fine. I checked EVERY single room with a room name. I turned on invincibility
mode and added a temporary line to hardreset() that always turned on
game.nocutscenes for a smoother playtesting experience. And to make sure that
rooms which have entirely empty bottom rows actually still have 30 rows,
instead of having 29 and the game assuming that the 30th row was empty
(because that sounds like it could lead to Undefined Behavior), I added this
temporary debugging line to the start of mapclass::fillcontent():
printf("(%i,%i) has %i rows\n", game.roomx, game.roomy, (int) tmap.size());
Everywhere I checked - and I made sure to check all rooms - every room had 30
rows and not 29 rows.
Unfortunately, some rooms simply couldn't be left alone with their 29th row
duplicated and had to be manually edited. This was because the 29th row would
contain some edge tiles because the player would be able to walk somewhere on
the 28th, 27th, and 26th rows, and if you duplicated said edge tiles behind
the room name, it would look bad.
Here's a list of rooms whose 30th rows I had to manually edit:
- Comms Relay
- The Yes Men
- Stop and Reflect
- They Call Him Flipper
- Double-slit Experiment
- Square Root
- Brought to you by the letter G
- The Bernoulli Principle
- Purest Unobtainium
- I Smell Ozone
- Conveying a New Idea
- Upstream Downstream
- Give Me A V
- $eeing Dollar $ign$
- Doing Things The Hard Way
- Very Good
- Must I Do Everything For You?
- Now Stay Close To Me...
- ...But Not Too Close
- ...Not as I Do
- Do Try To Keep Up
- Whee Sports
- As you like it
This is actually a strange case where it looked bad because of the 29th
row, instead of the 30th row, and I had to change the 29th row instead of
the 30th row to fix it.
- Maze With No Entrance
- Ascending and Descending
- Mind The Gap
Same strange case as "As you like it" (it's the 29th row I had to change
that was the problem, not the 30th).
- 1950 Silverstone Grand V
- The Villi People
I found that Panic Room and The Final Challenge also looked strange behind the
roomname background, but I can't do much about either because towers' tile
data wrap around at the top and bottom, and if I added another row to either
it would be visible above the room name.
I've considered updating the development editors with these new level tiles,
but I decided against it as the development editors are already pretty
outdated anyway.
2020-02-03 22:24:30 +01:00
|
|
|
for (int jt = 0; jt < 30; jt++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
for (int it = 0; it < 40; it++)
|
|
|
|
{
|
|
|
|
if(map.contents[it + map.vmult[jt]]>0) drawforetile2(it * 8, jt * 8, map.contents[it + map.vmult[jt]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (map.tileset == 2)
|
|
|
|
{
|
2020-06-14 20:21:32 +02:00
|
|
|
for (int j = 0; j < 30; j++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
for (int i = 0; i < 40; i++)
|
|
|
|
{
|
|
|
|
if(map.contents[i + map.vmult[j]]>0) drawforetile3(i * 8, j * 8, map.contents[i + map.vmult[j]],map.rcol);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foregrounddrawn = true;
|
|
|
|
}
|
Ax OverlaySurfaceKeyed(), set proper foregroundBuffer blend mode
So, earlier in the development of 2.0, Simon Roth (I presume)
encountered a problem: Oh no, all my backgrounds aren't appearing! And
this is because my foregroundBuffer, which contains all the drawn tiles,
is drawing complete black over it!
So he had a solution that seems ingenius, but is actually really really
hacky and super 100% NOT the proper solution. Just, take the
foregroundBuffer, iterate over each pixel, and DON'T draw any pixel
that's 0xDEADBEEF. 0xDEADBEEF is a special signal meaning "don't draw
this pixel". It is called a 'key'.
Unfortunately, this causes a bug where translucent pixels on tiles
(pixels between 0% and 100% opacity) didn't get drawn correctly. They
would be drawn against this weird blue color.
Now, in #103, I came across this weird constant and decided "hey, this
looks awfully like that weird blue color I came across, maybe if I set
it to 0x00000000, i.e. complete and transparent black, the issue will be
fixed". And it DID appear to be fixed. However, I didn't look too
closely, nor did I test it that much, and all that ended up doing was
drawing the pixels against black, which more subtly disguised the
problem with translucent pixels.
So, after some investigation, I noticed that BlitSurfaceColoured() was
drawing translucent pixels just fine. And I thought at the time that
there was something wrong with BlitSurfaceStandard(), or something.
Further along later I realized that all drawn tiles were passing through
this weird OverlaySurfaceKeyed() function. And removing it in favor of a
straight SDL_BlitSurface() produced the bug I mentioned above: Oh no,
all the backgrounds don't show up, because my foregroundBuffer is
drawing pure black over them!
Well... just... set the proper blend mode for foregroundBuffer. It
should be SDL_BLENDMODE_BLEND instead of SDL_BLENDMODE_NONE.
Then you don't have to worry about your transparency at all. If you did
it right, you won't have to resort this hacky color-keying business.
*sigh*
2020-08-04 09:24:04 +02:00
|
|
|
SDL_BlitSurface(foregroundBuffer, NULL, backBuffer, NULL);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::drawfinalmap(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-02 22:05:48 +02:00
|
|
|
if (!foregrounddrawn) {
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(foregroundBuffer);
|
2020-04-02 22:05:48 +02:00
|
|
|
if(map.tileset==0){
|
Add and draw one more row to all rooms with roomnames
Since translucent roomname backgrounds were introduced in
TerryCavanagh/VVVVVV#122, it exposes one glaring flaw with the game that
until now has been kept hidden: in rooms with room names, the game
cheapens out with the tile data and doesn't have a 30th row, because the
room name would hide the missing row. As a result, rooms with room names
have 29 rows instead of 30 to fill up the entire screen. And it looks
really weird when there's nothing but empty space behind the translucent
room name background.
To remedy this, I added one row to each room with a room name in the level.
First, I had to filter out all the rooms with no room names. However, that's
actually all contained in Otherlevel.cpp, the Overworld, which contains 221
rooms (8 of which are the Secret Lab, 6 more of which are the Ship, so 207 are
the actual Overworld, right? Wrong, 2 of those Overworld no-roomname rooms are
in the Lab, so there are actually 205 Overworld rooms). The remaining level
data files all contain rooms with room names.
But the process wasn't that easy. I noticed a while ago that each room
contains 29 `tmap.push_back()`s, one for each row of the room, and each row is
simply a string containing the 40 tiles for that row, concatenated with
commas.
However, I decided to actually check my intuition by doing a grep on each
level file and counting the number of results, for example `grep 'push_back'
Labclass.cpp | wc -l`. Whatever number comes out should be divisible by 29.
That particular grep on Labclass.cpp returns 1306, which divided by 29 is 45
with a remainder of 1.
So what does that mean? Does that mean there's 45 rooms each, and 1 leftover
row? Well, not exactly. The extra row comes from the fact that Outer Space has
30 rows instead of 29. Outer Space is the room that comes up when the game
finds a room is non-existent, which shouldn't happen with a properly-working
game, except in Outside Dimension VVVVVV. In fact, each level file has their
own Outer Space, and every single Outer Space also has 30 rooms. So really,
this means there are 44 rooms in the Lab and one Outer Space room. (Well, in
reality, there are 46 rooms in the Lab, because 2 of them use the Outside
tileset but have no room names, so they're stored in Otherlevel.cpp instead.)
We find the same result for the Warp Zone. `grep 'push_back' WarpClass.cpp |
wc -l` returns 697, which is 24 remainder 1, meaning 23 rooms of 29 rows and 1
room of 30 rows, which corresponds with 23 rooms in the Warp Zone and one
Outer Space room.
However, Outside Dimension VVVVVV + Tower Hallways and Space Station 1 and 2
are both odd curiosities. Finalclass.cpp contains Outside Dimension VVVVVV,
(which is Intermission 1 and 2 and the Final Level), but also the Tower
Hallway rooms, i.e. the auxiliary Tower rooms that are not a part of the main
tower. Spacestation2.cpp contains both Space Station 1 and 2, so don't be
deceived by the name.
`grep 'push_back' Finalclass.cpp | wc -l` returns 1597, which is actually 55
remainder 2. So... are there two rooms with 30 rows? Yes, in fact, The
Gravitron and Outer Space both contain 30 rows. So there are actually 55 rooms
stored in Finalclass.cpp (not including the minitowers Panic Room and The
Final Challenge), 54 rooms of actual level data and one Outer Space room, and
breaking down the 54 rooms even further, 51 of them are actually in Outside
Dimension VVVVVV and 3 of them are Tower Hallways. Of the 51 Outside Dimension
VVVVVV rooms, 14 of those are Intermission 1, 4 of them are Intermission 2,
and the rest of the 33 rooms are the Final Level (again, not including the
minitowers).
`grep 'push_back' Spacestation2.cpp | wc -l` returns 2148, which is 74
remainder 2. Are there two rooms with 30 rows again? No; one of those counted
2148 rows is a false-positive, because there's an if-else in Prize for the
Reckless that replaces the row with spikes with a row without spikes if you
are in a time trial or in No Death Mode. So there's 73 rooms in Space Station
1 and 2, and one Outer Space room.
With all this in mind, I decided to duplicate the current last row of each
room, the 29th row, to add a 30th row. However, I wasn't going to do this
automatically! But neither was I going to write some kludge-y code to parse
each nightmare of a level file and duplicate the rows that way.
Enter: Vim macros! (Er, well, actually, I use Neovim.) I first did
`/push_back`, so that pressing `n` would keep going to the next `push_back` in
the file. Then I went to the 29th row of the first room in the file, did a
`Yp`, and then started my macro with `qq`. The macro went like this: `30nYp`,
which is simply going to the 29th row of the next room over and duplicating
it. And that's all there was to it. However, I had to make sure that (1) my
cursor was before the `push_back` on the line of the 29th row of the room, and
(2) that I didn't skip rooms, both of which were problems I encountered when
pressing Ctrl+Z a given invocation of the macro (the Ctrl+Z is just a
metaphor, you actually undo by typing `u` in Vim). And also I had to make sure
to be careful around the extra lines of `push_back`s in Prize for the Reckless
and The Gravitron, and make sure I didn't run past the end of the file and
loop back around. Thankfully, all Outer Space rooms are at the end of each
file.
But first, I had to increase the number of rows drawn in Graphics.cpp by 1 in
order to compensate for this, and do the same when reading the tile data in
Map.cpp. I had to change fillcontent(), drawmap(), drawfinalmap(),
drawtowermap(), and drawtowermap_nobackground(). Funnily enough, the tower
functions already used 30 rows, but I guess it's an off-by-one due to the
camera scrolling, so they now draw 31 rows each.
Then, I went in-game to make sure that the row behind each room name looked
fine. I checked EVERY single room with a room name. I turned on invincibility
mode and added a temporary line to hardreset() that always turned on
game.nocutscenes for a smoother playtesting experience. And to make sure that
rooms which have entirely empty bottom rows actually still have 30 rows,
instead of having 29 and the game assuming that the 30th row was empty
(because that sounds like it could lead to Undefined Behavior), I added this
temporary debugging line to the start of mapclass::fillcontent():
printf("(%i,%i) has %i rows\n", game.roomx, game.roomy, (int) tmap.size());
Everywhere I checked - and I made sure to check all rooms - every room had 30
rows and not 29 rows.
Unfortunately, some rooms simply couldn't be left alone with their 29th row
duplicated and had to be manually edited. This was because the 29th row would
contain some edge tiles because the player would be able to walk somewhere on
the 28th, 27th, and 26th rows, and if you duplicated said edge tiles behind
the room name, it would look bad.
Here's a list of rooms whose 30th rows I had to manually edit:
- Comms Relay
- The Yes Men
- Stop and Reflect
- They Call Him Flipper
- Double-slit Experiment
- Square Root
- Brought to you by the letter G
- The Bernoulli Principle
- Purest Unobtainium
- I Smell Ozone
- Conveying a New Idea
- Upstream Downstream
- Give Me A V
- $eeing Dollar $ign$
- Doing Things The Hard Way
- Very Good
- Must I Do Everything For You?
- Now Stay Close To Me...
- ...But Not Too Close
- ...Not as I Do
- Do Try To Keep Up
- Whee Sports
- As you like it
This is actually a strange case where it looked bad because of the 29th
row, instead of the 30th row, and I had to change the 29th row instead of
the 30th row to fix it.
- Maze With No Entrance
- Ascending and Descending
- Mind The Gap
Same strange case as "As you like it" (it's the 29th row I had to change
that was the problem, not the 30th).
- 1950 Silverstone Grand V
- The Villi People
I found that Panic Room and The Final Challenge also looked strange behind the
roomname background, but I can't do much about either because towers' tile
data wrap around at the top and bottom, and if I added another row to either
it would be visible above the room name.
I've considered updating the development editors with these new level tiles,
but I decided against it as the development editors are already pretty
outdated anyway.
2020-02-03 22:24:30 +01:00
|
|
|
for (int j = 0; j < 30; j++) {
|
2020-04-02 22:05:48 +02:00
|
|
|
for (int i = 0; i < 40; i++) {
|
|
|
|
if((map.contents[i + map.vmult[j]])>0)
|
|
|
|
drawforetile(i * 8, j * 8, map.finalat(i,j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else if (map.tileset == 1) {
|
Add and draw one more row to all rooms with roomnames
Since translucent roomname backgrounds were introduced in
TerryCavanagh/VVVVVV#122, it exposes one glaring flaw with the game that
until now has been kept hidden: in rooms with room names, the game
cheapens out with the tile data and doesn't have a 30th row, because the
room name would hide the missing row. As a result, rooms with room names
have 29 rows instead of 30 to fill up the entire screen. And it looks
really weird when there's nothing but empty space behind the translucent
room name background.
To remedy this, I added one row to each room with a room name in the level.
First, I had to filter out all the rooms with no room names. However, that's
actually all contained in Otherlevel.cpp, the Overworld, which contains 221
rooms (8 of which are the Secret Lab, 6 more of which are the Ship, so 207 are
the actual Overworld, right? Wrong, 2 of those Overworld no-roomname rooms are
in the Lab, so there are actually 205 Overworld rooms). The remaining level
data files all contain rooms with room names.
But the process wasn't that easy. I noticed a while ago that each room
contains 29 `tmap.push_back()`s, one for each row of the room, and each row is
simply a string containing the 40 tiles for that row, concatenated with
commas.
However, I decided to actually check my intuition by doing a grep on each
level file and counting the number of results, for example `grep 'push_back'
Labclass.cpp | wc -l`. Whatever number comes out should be divisible by 29.
That particular grep on Labclass.cpp returns 1306, which divided by 29 is 45
with a remainder of 1.
So what does that mean? Does that mean there's 45 rooms each, and 1 leftover
row? Well, not exactly. The extra row comes from the fact that Outer Space has
30 rows instead of 29. Outer Space is the room that comes up when the game
finds a room is non-existent, which shouldn't happen with a properly-working
game, except in Outside Dimension VVVVVV. In fact, each level file has their
own Outer Space, and every single Outer Space also has 30 rooms. So really,
this means there are 44 rooms in the Lab and one Outer Space room. (Well, in
reality, there are 46 rooms in the Lab, because 2 of them use the Outside
tileset but have no room names, so they're stored in Otherlevel.cpp instead.)
We find the same result for the Warp Zone. `grep 'push_back' WarpClass.cpp |
wc -l` returns 697, which is 24 remainder 1, meaning 23 rooms of 29 rows and 1
room of 30 rows, which corresponds with 23 rooms in the Warp Zone and one
Outer Space room.
However, Outside Dimension VVVVVV + Tower Hallways and Space Station 1 and 2
are both odd curiosities. Finalclass.cpp contains Outside Dimension VVVVVV,
(which is Intermission 1 and 2 and the Final Level), but also the Tower
Hallway rooms, i.e. the auxiliary Tower rooms that are not a part of the main
tower. Spacestation2.cpp contains both Space Station 1 and 2, so don't be
deceived by the name.
`grep 'push_back' Finalclass.cpp | wc -l` returns 1597, which is actually 55
remainder 2. So... are there two rooms with 30 rows? Yes, in fact, The
Gravitron and Outer Space both contain 30 rows. So there are actually 55 rooms
stored in Finalclass.cpp (not including the minitowers Panic Room and The
Final Challenge), 54 rooms of actual level data and one Outer Space room, and
breaking down the 54 rooms even further, 51 of them are actually in Outside
Dimension VVVVVV and 3 of them are Tower Hallways. Of the 51 Outside Dimension
VVVVVV rooms, 14 of those are Intermission 1, 4 of them are Intermission 2,
and the rest of the 33 rooms are the Final Level (again, not including the
minitowers).
`grep 'push_back' Spacestation2.cpp | wc -l` returns 2148, which is 74
remainder 2. Are there two rooms with 30 rows again? No; one of those counted
2148 rows is a false-positive, because there's an if-else in Prize for the
Reckless that replaces the row with spikes with a row without spikes if you
are in a time trial or in No Death Mode. So there's 73 rooms in Space Station
1 and 2, and one Outer Space room.
With all this in mind, I decided to duplicate the current last row of each
room, the 29th row, to add a 30th row. However, I wasn't going to do this
automatically! But neither was I going to write some kludge-y code to parse
each nightmare of a level file and duplicate the rows that way.
Enter: Vim macros! (Er, well, actually, I use Neovim.) I first did
`/push_back`, so that pressing `n` would keep going to the next `push_back` in
the file. Then I went to the 29th row of the first room in the file, did a
`Yp`, and then started my macro with `qq`. The macro went like this: `30nYp`,
which is simply going to the 29th row of the next room over and duplicating
it. And that's all there was to it. However, I had to make sure that (1) my
cursor was before the `push_back` on the line of the 29th row of the room, and
(2) that I didn't skip rooms, both of which were problems I encountered when
pressing Ctrl+Z a given invocation of the macro (the Ctrl+Z is just a
metaphor, you actually undo by typing `u` in Vim). And also I had to make sure
to be careful around the extra lines of `push_back`s in Prize for the Reckless
and The Gravitron, and make sure I didn't run past the end of the file and
loop back around. Thankfully, all Outer Space rooms are at the end of each
file.
But first, I had to increase the number of rows drawn in Graphics.cpp by 1 in
order to compensate for this, and do the same when reading the tile data in
Map.cpp. I had to change fillcontent(), drawmap(), drawfinalmap(),
drawtowermap(), and drawtowermap_nobackground(). Funnily enough, the tower
functions already used 30 rows, but I guess it's an off-by-one due to the
camera scrolling, so they now draw 31 rows each.
Then, I went in-game to make sure that the row behind each room name looked
fine. I checked EVERY single room with a room name. I turned on invincibility
mode and added a temporary line to hardreset() that always turned on
game.nocutscenes for a smoother playtesting experience. And to make sure that
rooms which have entirely empty bottom rows actually still have 30 rows,
instead of having 29 and the game assuming that the 30th row was empty
(because that sounds like it could lead to Undefined Behavior), I added this
temporary debugging line to the start of mapclass::fillcontent():
printf("(%i,%i) has %i rows\n", game.roomx, game.roomy, (int) tmap.size());
Everywhere I checked - and I made sure to check all rooms - every room had 30
rows and not 29 rows.
Unfortunately, some rooms simply couldn't be left alone with their 29th row
duplicated and had to be manually edited. This was because the 29th row would
contain some edge tiles because the player would be able to walk somewhere on
the 28th, 27th, and 26th rows, and if you duplicated said edge tiles behind
the room name, it would look bad.
Here's a list of rooms whose 30th rows I had to manually edit:
- Comms Relay
- The Yes Men
- Stop and Reflect
- They Call Him Flipper
- Double-slit Experiment
- Square Root
- Brought to you by the letter G
- The Bernoulli Principle
- Purest Unobtainium
- I Smell Ozone
- Conveying a New Idea
- Upstream Downstream
- Give Me A V
- $eeing Dollar $ign$
- Doing Things The Hard Way
- Very Good
- Must I Do Everything For You?
- Now Stay Close To Me...
- ...But Not Too Close
- ...Not as I Do
- Do Try To Keep Up
- Whee Sports
- As you like it
This is actually a strange case where it looked bad because of the 29th
row, instead of the 30th row, and I had to change the 29th row instead of
the 30th row to fix it.
- Maze With No Entrance
- Ascending and Descending
- Mind The Gap
Same strange case as "As you like it" (it's the 29th row I had to change
that was the problem, not the 30th).
- 1950 Silverstone Grand V
- The Villi People
I found that Panic Room and The Final Challenge also looked strange behind the
roomname background, but I can't do much about either because towers' tile
data wrap around at the top and bottom, and if I added another row to either
it would be visible above the room name.
I've considered updating the development editors with these new level tiles,
but I decided against it as the development editors are already pretty
outdated anyway.
2020-02-03 22:24:30 +01:00
|
|
|
for (int j = 0; j < 30; j++) {
|
2020-04-02 22:05:48 +02:00
|
|
|
for (int i = 0; i < 40; i++) {
|
|
|
|
if((map.contents[i + map.vmult[j]])>0)
|
|
|
|
drawforetile2(i * 8, j * 8, map.finalat(i,j));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foregrounddrawn=true;
|
|
|
|
}
|
|
|
|
|
Ax OverlaySurfaceKeyed(), set proper foregroundBuffer blend mode
So, earlier in the development of 2.0, Simon Roth (I presume)
encountered a problem: Oh no, all my backgrounds aren't appearing! And
this is because my foregroundBuffer, which contains all the drawn tiles,
is drawing complete black over it!
So he had a solution that seems ingenius, but is actually really really
hacky and super 100% NOT the proper solution. Just, take the
foregroundBuffer, iterate over each pixel, and DON'T draw any pixel
that's 0xDEADBEEF. 0xDEADBEEF is a special signal meaning "don't draw
this pixel". It is called a 'key'.
Unfortunately, this causes a bug where translucent pixels on tiles
(pixels between 0% and 100% opacity) didn't get drawn correctly. They
would be drawn against this weird blue color.
Now, in #103, I came across this weird constant and decided "hey, this
looks awfully like that weird blue color I came across, maybe if I set
it to 0x00000000, i.e. complete and transparent black, the issue will be
fixed". And it DID appear to be fixed. However, I didn't look too
closely, nor did I test it that much, and all that ended up doing was
drawing the pixels against black, which more subtly disguised the
problem with translucent pixels.
So, after some investigation, I noticed that BlitSurfaceColoured() was
drawing translucent pixels just fine. And I thought at the time that
there was something wrong with BlitSurfaceStandard(), or something.
Further along later I realized that all drawn tiles were passing through
this weird OverlaySurfaceKeyed() function. And removing it in favor of a
straight SDL_BlitSurface() produced the bug I mentioned above: Oh no,
all the backgrounds don't show up, because my foregroundBuffer is
drawing pure black over them!
Well... just... set the proper blend mode for foregroundBuffer. It
should be SDL_BLENDMODE_BLEND instead of SDL_BLENDMODE_NONE.
Then you don't have to worry about your transparency at all. If you did
it right, you won't have to resort this hacky color-keying business.
*sigh*
2020-08-04 09:24:04 +02:00
|
|
|
SDL_BlitSurface(foregroundBuffer, NULL, backBuffer, NULL);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::drawtowermap(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
int temp;
|
2020-04-30 20:52:21 +02:00
|
|
|
int yoff = lerp(map.oldypos, map.ypos);
|
Add and draw one more row to all rooms with roomnames
Since translucent roomname backgrounds were introduced in
TerryCavanagh/VVVVVV#122, it exposes one glaring flaw with the game that
until now has been kept hidden: in rooms with room names, the game
cheapens out with the tile data and doesn't have a 30th row, because the
room name would hide the missing row. As a result, rooms with room names
have 29 rows instead of 30 to fill up the entire screen. And it looks
really weird when there's nothing but empty space behind the translucent
room name background.
To remedy this, I added one row to each room with a room name in the level.
First, I had to filter out all the rooms with no room names. However, that's
actually all contained in Otherlevel.cpp, the Overworld, which contains 221
rooms (8 of which are the Secret Lab, 6 more of which are the Ship, so 207 are
the actual Overworld, right? Wrong, 2 of those Overworld no-roomname rooms are
in the Lab, so there are actually 205 Overworld rooms). The remaining level
data files all contain rooms with room names.
But the process wasn't that easy. I noticed a while ago that each room
contains 29 `tmap.push_back()`s, one for each row of the room, and each row is
simply a string containing the 40 tiles for that row, concatenated with
commas.
However, I decided to actually check my intuition by doing a grep on each
level file and counting the number of results, for example `grep 'push_back'
Labclass.cpp | wc -l`. Whatever number comes out should be divisible by 29.
That particular grep on Labclass.cpp returns 1306, which divided by 29 is 45
with a remainder of 1.
So what does that mean? Does that mean there's 45 rooms each, and 1 leftover
row? Well, not exactly. The extra row comes from the fact that Outer Space has
30 rows instead of 29. Outer Space is the room that comes up when the game
finds a room is non-existent, which shouldn't happen with a properly-working
game, except in Outside Dimension VVVVVV. In fact, each level file has their
own Outer Space, and every single Outer Space also has 30 rooms. So really,
this means there are 44 rooms in the Lab and one Outer Space room. (Well, in
reality, there are 46 rooms in the Lab, because 2 of them use the Outside
tileset but have no room names, so they're stored in Otherlevel.cpp instead.)
We find the same result for the Warp Zone. `grep 'push_back' WarpClass.cpp |
wc -l` returns 697, which is 24 remainder 1, meaning 23 rooms of 29 rows and 1
room of 30 rows, which corresponds with 23 rooms in the Warp Zone and one
Outer Space room.
However, Outside Dimension VVVVVV + Tower Hallways and Space Station 1 and 2
are both odd curiosities. Finalclass.cpp contains Outside Dimension VVVVVV,
(which is Intermission 1 and 2 and the Final Level), but also the Tower
Hallway rooms, i.e. the auxiliary Tower rooms that are not a part of the main
tower. Spacestation2.cpp contains both Space Station 1 and 2, so don't be
deceived by the name.
`grep 'push_back' Finalclass.cpp | wc -l` returns 1597, which is actually 55
remainder 2. So... are there two rooms with 30 rows? Yes, in fact, The
Gravitron and Outer Space both contain 30 rows. So there are actually 55 rooms
stored in Finalclass.cpp (not including the minitowers Panic Room and The
Final Challenge), 54 rooms of actual level data and one Outer Space room, and
breaking down the 54 rooms even further, 51 of them are actually in Outside
Dimension VVVVVV and 3 of them are Tower Hallways. Of the 51 Outside Dimension
VVVVVV rooms, 14 of those are Intermission 1, 4 of them are Intermission 2,
and the rest of the 33 rooms are the Final Level (again, not including the
minitowers).
`grep 'push_back' Spacestation2.cpp | wc -l` returns 2148, which is 74
remainder 2. Are there two rooms with 30 rows again? No; one of those counted
2148 rows is a false-positive, because there's an if-else in Prize for the
Reckless that replaces the row with spikes with a row without spikes if you
are in a time trial or in No Death Mode. So there's 73 rooms in Space Station
1 and 2, and one Outer Space room.
With all this in mind, I decided to duplicate the current last row of each
room, the 29th row, to add a 30th row. However, I wasn't going to do this
automatically! But neither was I going to write some kludge-y code to parse
each nightmare of a level file and duplicate the rows that way.
Enter: Vim macros! (Er, well, actually, I use Neovim.) I first did
`/push_back`, so that pressing `n` would keep going to the next `push_back` in
the file. Then I went to the 29th row of the first room in the file, did a
`Yp`, and then started my macro with `qq`. The macro went like this: `30nYp`,
which is simply going to the 29th row of the next room over and duplicating
it. And that's all there was to it. However, I had to make sure that (1) my
cursor was before the `push_back` on the line of the 29th row of the room, and
(2) that I didn't skip rooms, both of which were problems I encountered when
pressing Ctrl+Z a given invocation of the macro (the Ctrl+Z is just a
metaphor, you actually undo by typing `u` in Vim). And also I had to make sure
to be careful around the extra lines of `push_back`s in Prize for the Reckless
and The Gravitron, and make sure I didn't run past the end of the file and
loop back around. Thankfully, all Outer Space rooms are at the end of each
file.
But first, I had to increase the number of rows drawn in Graphics.cpp by 1 in
order to compensate for this, and do the same when reading the tile data in
Map.cpp. I had to change fillcontent(), drawmap(), drawfinalmap(),
drawtowermap(), and drawtowermap_nobackground(). Funnily enough, the tower
functions already used 30 rows, but I guess it's an off-by-one due to the
camera scrolling, so they now draw 31 rows each.
Then, I went in-game to make sure that the row behind each room name looked
fine. I checked EVERY single room with a room name. I turned on invincibility
mode and added a temporary line to hardreset() that always turned on
game.nocutscenes for a smoother playtesting experience. And to make sure that
rooms which have entirely empty bottom rows actually still have 30 rows,
instead of having 29 and the game assuming that the 30th row was empty
(because that sounds like it could lead to Undefined Behavior), I added this
temporary debugging line to the start of mapclass::fillcontent():
printf("(%i,%i) has %i rows\n", game.roomx, game.roomy, (int) tmap.size());
Everywhere I checked - and I made sure to check all rooms - every room had 30
rows and not 29 rows.
Unfortunately, some rooms simply couldn't be left alone with their 29th row
duplicated and had to be manually edited. This was because the 29th row would
contain some edge tiles because the player would be able to walk somewhere on
the 28th, 27th, and 26th rows, and if you duplicated said edge tiles behind
the room name, it would look bad.
Here's a list of rooms whose 30th rows I had to manually edit:
- Comms Relay
- The Yes Men
- Stop and Reflect
- They Call Him Flipper
- Double-slit Experiment
- Square Root
- Brought to you by the letter G
- The Bernoulli Principle
- Purest Unobtainium
- I Smell Ozone
- Conveying a New Idea
- Upstream Downstream
- Give Me A V
- $eeing Dollar $ign$
- Doing Things The Hard Way
- Very Good
- Must I Do Everything For You?
- Now Stay Close To Me...
- ...But Not Too Close
- ...Not as I Do
- Do Try To Keep Up
- Whee Sports
- As you like it
This is actually a strange case where it looked bad because of the 29th
row, instead of the 30th row, and I had to change the 29th row instead of
the 30th row to fix it.
- Maze With No Entrance
- Ascending and Descending
- Mind The Gap
Same strange case as "As you like it" (it's the 29th row I had to change
that was the problem, not the 30th).
- 1950 Silverstone Grand V
- The Villi People
I found that Panic Room and The Final Challenge also looked strange behind the
roomname background, but I can't do much about either because towers' tile
data wrap around at the top and bottom, and if I added another row to either
it would be visible above the room name.
I've considered updating the development editors with these new level tiles,
but I decided against it as the development editors are already pretty
outdated anyway.
2020-02-03 22:24:30 +01:00
|
|
|
for (int j = 0; j < 31; j++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
for (int i = 0; i < 40; i++)
|
|
|
|
{
|
2020-04-30 20:52:21 +02:00
|
|
|
temp = map.tower.at(i, j, yoff);
|
2020-11-03 00:05:24 +01:00
|
|
|
if (temp > 0) drawtile3(i * 8, (j * 8) - (yoff % 8), temp, towerbg.colstate);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::drawtowerspikes(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-30 21:58:08 +02:00
|
|
|
int spikeleveltop = lerp(map.oldspikeleveltop, map.spikeleveltop);
|
|
|
|
int spikelevelbottom = lerp(map.oldspikelevelbottom, map.spikelevelbottom);
|
2020-01-01 21:29:24 +01:00
|
|
|
for (int i = 0; i < 40; i++)
|
|
|
|
{
|
2020-11-03 00:05:24 +01:00
|
|
|
drawtile3(i * 8, -8+spikeleveltop, 9, towerbg.colstate);
|
|
|
|
drawtile3(i * 8, 230-spikelevelbottom, 8, towerbg.colstate, 8 - spikelevelbottom);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-03 00:05:24 +01:00
|
|
|
void Graphics::drawtowerbackground(const TowerBG& bg_obj)
|
2020-04-30 00:25:01 +02:00
|
|
|
{
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-11-03 00:05:24 +01:00
|
|
|
SDL_BlitSurface(bg_obj.buffer, NULL, bg_obj.buffer_lerp, NULL);
|
|
|
|
ScrollSurface(bg_obj.buffer_lerp, 0, lerp(0, -bg_obj.bscroll));
|
|
|
|
SDL_BlitSurface(bg_obj.buffer_lerp, &towerbuffer_rect, backBuffer, NULL);
|
2020-04-30 00:25:01 +02:00
|
|
|
}
|
|
|
|
|
2020-11-03 00:05:24 +01:00
|
|
|
void Graphics::updatetowerbackground(TowerBG& bg_obj)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
int temp;
|
|
|
|
|
2020-11-03 00:05:24 +01:00
|
|
|
if (bg_obj.bypos < 0) bg_obj.bypos += 120 * 8;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-11-03 00:05:24 +01:00
|
|
|
if (bg_obj.tdrawback)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-11-03 00:05:24 +01:00
|
|
|
int off = bg_obj.scrolldir == 0 ? 0 : bg_obj.bscroll;
|
2020-01-01 21:29:24 +01:00
|
|
|
//Draw the whole thing; needed for every colour cycle!
|
2020-11-02 19:49:54 +01:00
|
|
|
for (int j = -1; j < 32; j++)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
for (int i = 0; i < 40; i++)
|
|
|
|
{
|
2020-11-03 00:05:24 +01:00
|
|
|
temp = map.tower.backat(i, j, bg_obj.bypos);
|
|
|
|
drawtowertile3(i * 8, (j * 8) - (bg_obj.bypos % 8) - off, temp, bg_obj);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-03 00:05:24 +01:00
|
|
|
bg_obj.tdrawback = false;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//just update the bottom
|
2020-11-03 00:05:24 +01:00
|
|
|
ScrollSurface(bg_obj.buffer, 0, -bg_obj.bscroll);
|
|
|
|
if (bg_obj.scrolldir == 0)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-04-29 23:28:11 +02:00
|
|
|
for (int i = 0; i < 40; i++)
|
2020-04-29 22:44:28 +02:00
|
|
|
{
|
2020-11-03 00:05:24 +01:00
|
|
|
temp = map.tower.backat(i, -1, bg_obj.bypos);
|
|
|
|
drawtowertile3(i * 8, -1*8 - (bg_obj.bypos % 8), temp, bg_obj);
|
|
|
|
temp = map.tower.backat(i, 0, bg_obj.bypos);
|
|
|
|
drawtowertile3(i * 8, -(bg_obj.bypos % 8), temp, bg_obj);
|
2020-04-29 22:44:28 +02:00
|
|
|
}
|
2020-04-29 23:28:11 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 40; i++)
|
2020-04-29 22:44:28 +02:00
|
|
|
{
|
2020-11-03 00:05:24 +01:00
|
|
|
temp = map.tower.backat(i, 29, bg_obj.bypos);
|
|
|
|
drawtowertile3(i * 8, 29*8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj);
|
|
|
|
temp = map.tower.backat(i, 30, bg_obj.bypos);
|
|
|
|
drawtowertile3(i * 8, 30*8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj);
|
|
|
|
temp = map.tower.backat(i, 31, bg_obj.bypos);
|
|
|
|
drawtowertile3(i * 8, 31*8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj);
|
|
|
|
temp = map.tower.backat(i, 32, bg_obj.bypos);
|
|
|
|
drawtowertile3(i * 8, 32*8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj);
|
2020-04-29 22:44:28 +02:00
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-31 21:26:11 +02:00
|
|
|
void Graphics::setcol( int t )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
int temp;
|
|
|
|
|
|
|
|
//Setup predefinied colours as per our zany palette
|
|
|
|
switch(t)
|
|
|
|
{
|
|
|
|
//Player Normal
|
|
|
|
case 0:
|
|
|
|
ct.colour = getRGB(160- help.glow/2 - (fRandom()*20), 200- help.glow/2, 220 - help.glow);
|
|
|
|
break;
|
|
|
|
//Player Hurt
|
|
|
|
case 1:
|
|
|
|
ct.colour = getRGB(196 - (fRandom() * 64), 10, 10);
|
|
|
|
break;
|
|
|
|
//Enemies and stuff
|
|
|
|
case 2:
|
|
|
|
ct.colour = getRGB(225-(help.glow/2), 75, 30);
|
|
|
|
break;
|
|
|
|
case 3: //Trinket
|
|
|
|
if (!trinketcolset)
|
|
|
|
{
|
|
|
|
trinketr = 200 - (fRandom() * 64);
|
|
|
|
trinketg = 200 - (fRandom() * 128);
|
|
|
|
trinketb = 164 + (fRandom() * 60);
|
|
|
|
trinketcolset = true;
|
|
|
|
}
|
|
|
|
ct.colour = getRGB(trinketr, trinketg, trinketb);
|
|
|
|
break;
|
|
|
|
case 4: //Inactive savepoint
|
|
|
|
temp = (help.glow/2) + (fRandom() * 8);
|
|
|
|
ct.colour = getRGB(80 + temp, 80 + temp, 80 + temp);
|
|
|
|
break;
|
|
|
|
case 5: //Active savepoint
|
|
|
|
ct.colour = getRGB(164+(fRandom()*64),164+(fRandom()*64), 255-(fRandom()*64));
|
|
|
|
break;
|
|
|
|
case 6: //Enemy : Red
|
|
|
|
ct.colour = getRGB(250 - help.glow/2, 60- help.glow/2, 60 - help.glow/2);
|
|
|
|
break;
|
|
|
|
case 7: //Enemy : Green
|
|
|
|
ct.colour = getRGB(100 - help.glow/2 - (fRandom()*30), 250 - help.glow/2, 100 - help.glow/2 - (fRandom()*30));
|
|
|
|
break;
|
|
|
|
case 8: //Enemy : Purple
|
|
|
|
ct.colour = getRGB(250 - help.glow/2, 20, 128 - help.glow/2 + (fRandom()*30));
|
|
|
|
break;
|
|
|
|
case 9: //Enemy : Yellow
|
|
|
|
ct.colour = getRGB(250 - help.glow/2, 250 - help.glow/2, 20);
|
|
|
|
break;
|
|
|
|
case 10: //Warp point (white)
|
|
|
|
ct.colour = getRGB(255 - (fRandom() * 64), 255 - (fRandom() * 64), 255 - (fRandom() * 64));
|
|
|
|
break;
|
|
|
|
case 11: //Enemy : Cyan
|
|
|
|
ct.colour = getRGB(20, 250 - help.glow/2, 250 - help.glow/2);
|
|
|
|
break;
|
|
|
|
case 12: //Enemy : Blue
|
|
|
|
ct.colour = getRGB(90- help.glow/2, 90 - help.glow/2, 250 - help.glow/2);
|
|
|
|
break;
|
|
|
|
//Crew Members
|
|
|
|
//green
|
|
|
|
case 13:
|
|
|
|
ct.colour = getRGB(120- help.glow/4 - (fRandom()*20), 220 - help.glow/4, 120- help.glow/4);
|
|
|
|
break;
|
|
|
|
//Yellow
|
|
|
|
case 14:
|
|
|
|
ct.colour = getRGB(220- help.glow/4 - (fRandom()*20), 210 - help.glow/4, 120- help.glow/4);
|
|
|
|
break;
|
|
|
|
//pink
|
|
|
|
case 15:
|
|
|
|
ct.colour = getRGB(255 - help.glow/8, 70 - help.glow/4, 70 - help.glow / 4);
|
|
|
|
break;
|
|
|
|
//Blue
|
|
|
|
case 16:
|
|
|
|
ct.colour = getRGB(75, 75, 255- help.glow/4 - (fRandom()*20));
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 17: //Enemy : Orange
|
|
|
|
ct.colour = getRGB(250 - help.glow/2, 130 - help.glow/2, 20);
|
|
|
|
break;
|
|
|
|
case 18: //Enemy : Gray
|
|
|
|
ct.colour = getRGB(130- help.glow/2, 130 - help.glow/2, 130 - help.glow/2);
|
|
|
|
break;
|
|
|
|
case 19: //Enemy : Dark gray
|
|
|
|
ct.colour = getRGB(60- help.glow/8, 60 - help.glow/8, 60 - help.glow/8);
|
|
|
|
break;
|
|
|
|
//Purple
|
|
|
|
case 20:
|
|
|
|
ct.colour = getRGB(220 - help.glow / 4 - (fRandom() * 20), 120 - help.glow / 4, 210 - help.glow / 4);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 21: //Enemy : Light Gray
|
|
|
|
ct.colour = getRGB(180- help.glow/2, 180 - help.glow/2, 180 - help.glow/2);
|
|
|
|
break;
|
|
|
|
case 22: //Enemy : Indicator Gray
|
|
|
|
ct.colour = getRGB(230- help.glow/2, 230- help.glow/2, 230- help.glow/2);
|
|
|
|
break;
|
|
|
|
case 23: //Enemy : Indicator Gray
|
|
|
|
ct.colour = getRGB(255- help.glow/2 - (fRandom() * 40) , 255- help.glow/2 - (fRandom() * 40), 255- help.glow/2 - (fRandom() * 40));
|
|
|
|
break;
|
|
|
|
|
|
|
|
//Trophies
|
Fix Secret Lab Time Trial trophies having wrong colors
Ever since 2.0, the colors of some of the Time Trial trophies in the
Secret Lab don't correspond to the crewmate of the given level. The
trophy for the Tower uses Victoria's color, and the Lab trophy uses
Vermilion's color. The Space Station 2 trophy uses Viridian's color, and
the Final Level trophy uses Vitellary's color.
This doesn't appear to be intentional, and it would be odd if it was,
since this game matches the colors everywhere else (each zone on the map
is colored with their respective crewmate in mind, for instance). Also,
the Lab trophy has the sad expression, which is Victoria's trait - it
would be weird if this was intended for Vermilion instead.
But the biggest piece of evidence that this was unintentional is the
corresponding comment for each color in Graphics::setcol(). It mislabels
yellow as cyan, cyan as yellow, blue as red, and red as blue.
To fix this, I simply have to set the correct color for each trophy in
case 25 of entityclass::createentity(). I could fix it in
Graphics::setcol() itself, but custom levels might depend on those
certain colors being the way they are, so it's a safer bet to just fix
it in the trophy creation case itself.
The diff of this might look weird. Even though all I'm doing is changing
some value assignments around, it looks like the "patience" algorithm
thinks I'm moving a whole case of the trophy switch-case around.
2020-11-15 00:43:22 +01:00
|
|
|
//Yellow
|
2020-01-01 21:29:24 +01:00
|
|
|
case 30:
|
|
|
|
ct.colour = RGBf(160, 200, 220);
|
|
|
|
break;
|
|
|
|
//Purple
|
|
|
|
case 31:
|
|
|
|
ct.colour = RGBf(220, 120, 210);
|
|
|
|
break;
|
Fix Secret Lab Time Trial trophies having wrong colors
Ever since 2.0, the colors of some of the Time Trial trophies in the
Secret Lab don't correspond to the crewmate of the given level. The
trophy for the Tower uses Victoria's color, and the Lab trophy uses
Vermilion's color. The Space Station 2 trophy uses Viridian's color, and
the Final Level trophy uses Vitellary's color.
This doesn't appear to be intentional, and it would be odd if it was,
since this game matches the colors everywhere else (each zone on the map
is colored with their respective crewmate in mind, for instance). Also,
the Lab trophy has the sad expression, which is Victoria's trait - it
would be weird if this was intended for Vermilion instead.
But the biggest piece of evidence that this was unintentional is the
corresponding comment for each color in Graphics::setcol(). It mislabels
yellow as cyan, cyan as yellow, blue as red, and red as blue.
To fix this, I simply have to set the correct color for each trophy in
case 25 of entityclass::createentity(). I could fix it in
Graphics::setcol() itself, but custom levels might depend on those
certain colors being the way they are, so it's a safer bet to just fix
it in the trophy creation case itself.
The diff of this might look weird. Even though all I'm doing is changing
some value assignments around, it looks like the "patience" algorithm
thinks I'm moving a whole case of the trophy switch-case around.
2020-11-15 00:43:22 +01:00
|
|
|
//cyan
|
2020-01-01 21:29:24 +01:00
|
|
|
case 32:
|
|
|
|
ct.colour = RGBf(220, 210, 120);
|
|
|
|
break;
|
Fix Secret Lab Time Trial trophies having wrong colors
Ever since 2.0, the colors of some of the Time Trial trophies in the
Secret Lab don't correspond to the crewmate of the given level. The
trophy for the Tower uses Victoria's color, and the Lab trophy uses
Vermilion's color. The Space Station 2 trophy uses Viridian's color, and
the Final Level trophy uses Vitellary's color.
This doesn't appear to be intentional, and it would be odd if it was,
since this game matches the colors everywhere else (each zone on the map
is colored with their respective crewmate in mind, for instance). Also,
the Lab trophy has the sad expression, which is Victoria's trait - it
would be weird if this was intended for Vermilion instead.
But the biggest piece of evidence that this was unintentional is the
corresponding comment for each color in Graphics::setcol(). It mislabels
yellow as cyan, cyan as yellow, blue as red, and red as blue.
To fix this, I simply have to set the correct color for each trophy in
case 25 of entityclass::createentity(). I could fix it in
Graphics::setcol() itself, but custom levels might depend on those
certain colors being the way they are, so it's a safer bet to just fix
it in the trophy creation case itself.
The diff of this might look weird. Even though all I'm doing is changing
some value assignments around, it looks like the "patience" algorithm
thinks I'm moving a whole case of the trophy switch-case around.
2020-11-15 00:43:22 +01:00
|
|
|
//Blue
|
2020-01-01 21:29:24 +01:00
|
|
|
case 33:
|
|
|
|
ct.colour = RGBf(255, 70, 70);
|
|
|
|
break;
|
|
|
|
//green
|
|
|
|
case 34:
|
|
|
|
ct.colour = RGBf(120, 220, 120);
|
|
|
|
break;
|
Fix Secret Lab Time Trial trophies having wrong colors
Ever since 2.0, the colors of some of the Time Trial trophies in the
Secret Lab don't correspond to the crewmate of the given level. The
trophy for the Tower uses Victoria's color, and the Lab trophy uses
Vermilion's color. The Space Station 2 trophy uses Viridian's color, and
the Final Level trophy uses Vitellary's color.
This doesn't appear to be intentional, and it would be odd if it was,
since this game matches the colors everywhere else (each zone on the map
is colored with their respective crewmate in mind, for instance). Also,
the Lab trophy has the sad expression, which is Victoria's trait - it
would be weird if this was intended for Vermilion instead.
But the biggest piece of evidence that this was unintentional is the
corresponding comment for each color in Graphics::setcol(). It mislabels
yellow as cyan, cyan as yellow, blue as red, and red as blue.
To fix this, I simply have to set the correct color for each trophy in
case 25 of entityclass::createentity(). I could fix it in
Graphics::setcol() itself, but custom levels might depend on those
certain colors being the way they are, so it's a safer bet to just fix
it in the trophy creation case itself.
The diff of this might look weird. Even though all I'm doing is changing
some value assignments around, it looks like the "patience" algorithm
thinks I'm moving a whole case of the trophy switch-case around.
2020-11-15 00:43:22 +01:00
|
|
|
//red
|
2020-01-01 21:29:24 +01:00
|
|
|
case 35:
|
|
|
|
ct.colour = RGBf(75, 75, 255);
|
|
|
|
break;
|
|
|
|
//Gold
|
|
|
|
case 36:
|
|
|
|
ct.colour = getRGB(180, 120, 20);
|
|
|
|
break;
|
|
|
|
case 37: //Trinket
|
|
|
|
if (!trinketcolset)
|
|
|
|
{
|
|
|
|
trinketr = 200 - (fRandom() * 64);
|
|
|
|
trinketg = 200 - (fRandom() * 128);
|
|
|
|
trinketb = 164 + (fRandom() * 60);
|
|
|
|
trinketcolset = true;
|
|
|
|
}
|
|
|
|
ct.colour = RGBf(trinketr, trinketg, trinketb);
|
|
|
|
break;
|
|
|
|
//Silver
|
|
|
|
case 38:
|
|
|
|
ct.colour = RGBf(196, 196, 196);
|
|
|
|
break;
|
|
|
|
//Bronze
|
|
|
|
case 39:
|
|
|
|
ct.colour = RGBf(128, 64, 10);
|
|
|
|
break;
|
|
|
|
//Awesome
|
|
|
|
case 40: //Teleporter in action!
|
|
|
|
temp = fRandom() * 150;
|
|
|
|
if(temp<33)
|
|
|
|
{
|
|
|
|
ct.colour = RGBf(255 - (fRandom() * 64), 64 + (fRandom() * 64), 64 + (fRandom() * 64));
|
|
|
|
}
|
|
|
|
else if (temp < 66)
|
|
|
|
{
|
|
|
|
ct.colour = RGBf(64 + (fRandom() * 64), 255 - (fRandom() * 64), 64 + (fRandom() * 64));
|
|
|
|
}
|
|
|
|
else if (temp < 100)
|
|
|
|
{
|
|
|
|
ct.colour = RGBf(64 + (fRandom() * 64), 64 + (fRandom() * 64), 255 - (fRandom() * 64));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ct.colour = RGBf(164+(fRandom()*64),164+(fRandom()*64), 255-(fRandom()*64));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 100: //Inactive Teleporter
|
|
|
|
temp = (help.glow/2) + (fRandom() * 8);
|
|
|
|
ct.colour = getRGB(42 + temp, 42 + temp, 42 + temp);
|
|
|
|
break;
|
|
|
|
case 101: //Active Teleporter
|
|
|
|
ct.colour = getRGB(164+(fRandom()*64),164+(fRandom()*64), 255-(fRandom()*64));
|
|
|
|
break;
|
|
|
|
case 102: //Teleporter in action!
|
|
|
|
temp = fRandom() * 150;
|
|
|
|
if(temp<33)
|
|
|
|
{
|
|
|
|
ct.colour = getRGB(255 - (fRandom() * 64), 64 + (fRandom() * 64), 64 + (fRandom() * 64));
|
|
|
|
}
|
|
|
|
else if (temp < 66)
|
|
|
|
{
|
|
|
|
ct.colour = getRGB(64 + (fRandom() * 64), 255 - (fRandom() * 64), 64 + (fRandom() * 64));
|
|
|
|
}
|
|
|
|
else if (temp < 100)
|
|
|
|
{
|
|
|
|
ct.colour = getRGB(64 + (fRandom() * 64), 64 + (fRandom() * 64), 255 - (fRandom() * 64));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ct.colour = getRGB(164+(fRandom()*64),164+(fRandom()*64), 255-(fRandom()*64));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
Fix default Graphics::setcol() value having no alpha
This patch fixes a regression caused by commit
6b1a7ebce6fa77ec54c881bec95081b1a2826646.
When you spawn a crewmate with an invalid color, by doing something like
`createentity(100,100,18,-1,0)` (here the color is -1, which is
invalid), a white crewmate with the color of solid white (255, 255, 255)
would appear.
That is, until AllyTally came along and committed commit
6b1a7ebce6fa77ec54c881bec95081b1a2826646 (Make "[Press ENTER to
return to editor]" fade out after a bit) (PR #158). Then after that
commit, it would seem like the crewmate didn't appear, but in reality
they were just invisible, because they had an invisible color.
As part of Ally's changes, to properly support drawing text with a
certain amount of alpha, she made BlitSurfaceColoured() account for the
alpha of the color given instead of only caring about the RGB of the
color, discarding the alpha, and using the alpha of the surface it was
drawing instead. This effectively made it so the alpha of whatever it
was drawing would be 255 all the time, except for if you had custom
textures and your custom textures had translucent pixels.
However, the default color set by Graphics::setcol() if you didn't
provide a valid color index was 0xFFFFFF. Which is only (255, 255, 255)
but ends up having an alpha value of 0 (because it's actually
0x00FFFFFF). And all colors drawn with alpha 0 end up being drawn with
alpha 0 after 6b1a7ebce6fa77ec54c881bec95081b1a2826646. So
invalid-colored entities will end up being invisible.
To fix this, I just decided to add alpha to the default value instead.
In addition, I used getRGB() to be consistent with all the other colors
in the function.
2020-09-17 12:38:56 +02:00
|
|
|
ct.colour = getRGB(255, 255, 255);
|
2020-01-01 21:29:24 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::menuoffrender(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
SDL_Rect offsetRect1;
|
|
|
|
setRect (offsetRect1, 0, 0, backBuffer->w ,backBuffer->h);
|
|
|
|
|
|
|
|
//put the back buffer in the menubuffer
|
|
|
|
BlitSurfaceStandard(backBuffer, NULL, menubuffer, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-29 05:46:33 +02:00
|
|
|
int usethisoffset = lerp(oldmenuoffset, menuoffset);
|
2020-01-01 21:29:24 +01:00
|
|
|
if(flipmode)
|
|
|
|
{
|
|
|
|
SDL_Surface* tempbufferFlipped = FlipSurfaceVerticle(tempBuffer);
|
|
|
|
//put the stored backbuffer in the backbuffer.
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-01-01 21:29:24 +01:00
|
|
|
BlitSurfaceStandard(tempbufferFlipped, NULL, backBuffer, NULL);
|
|
|
|
SDL_FreeSurface(tempbufferFlipped);
|
|
|
|
SDL_Rect offsetRect;
|
Reverse menu animation direction in Flip Mode
In normal mode, the room name is at the bottom of the screen. When you
bring up the map screen, it appears as if the room name is moving up
from the bottom of the screen, and the map screen is "pushing" it up.
The effect is pretty seamless, and when I first played the game (back in
2014), I thought it was pretty cool.
However, in Flip Mode, the room name is at the top of the screen. So one
would expect the menu animation to come from above the screen. Well, no,
it still goes from the bottom of screen; ruining the effect because it
seems like there are two room names on the screen, when there ought to
be only one.
To be fair, I only noticed this while fixing another bug now, but it's
one of those things you can't unsee (I have cursed you with knowledge!);
not to mention that I probably only didn't notice this because I don't
play in Flip Mode that often (and I'd wager almost no one does; Flip
Mode previous to 2.3 seems to have been really untested, like I said
in #165). It feels like a bit of an oversight that the direction of the
animation is the same direction as in unflipped mode. So I'm fixing
this.
2021-03-06 04:24:54 +01:00
|
|
|
setRect (offsetRect, 0, -usethisoffset, backBuffer->w ,backBuffer->h);
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Surface* temp = FlipSurfaceVerticle(menubuffer);
|
|
|
|
BlitSurfaceStandard(temp,NULL,backBuffer,&offsetRect);
|
|
|
|
SDL_FreeSurface(temp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//put the stored backbuffer in the backbuffer.
|
|
|
|
BlitSurfaceStandard(tempBuffer, NULL, backBuffer, NULL);
|
|
|
|
|
|
|
|
SDL_Rect offsetRect;
|
2020-04-29 05:46:33 +02:00
|
|
|
setRect (offsetRect, 0, usethisoffset, backBuffer->w ,backBuffer->h);
|
2020-01-01 21:29:24 +01:00
|
|
|
BlitSurfaceStandard(menubuffer,NULL,backBuffer,&offsetRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_Rect rect;
|
|
|
|
setRect(rect, 0, 0, backBuffer->w, backBuffer->h);
|
|
|
|
screenbuffer->UpdateScreen(backBuffer,&rect);
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2020-04-30 23:42:08 +02:00
|
|
|
void Graphics::drawhuetile( int x, int y, int t )
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles))
|
2020-06-14 03:37:18 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
point tpoint;
|
|
|
|
tpoint.x = x;
|
|
|
|
tpoint.y = y;
|
2020-04-30 23:42:08 +02:00
|
|
|
|
|
|
|
|
|
|
|
SDL_Rect rect;
|
|
|
|
setRect(rect,tpoint.x,tpoint.y,tiles_rect.w, tiles_rect.h);
|
|
|
|
BlitSurfaceColoured(tiles[t],NULL,backBuffer, &rect, ct);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::huetilesetcol(int t)
|
|
|
|
{
|
|
|
|
switch (t)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
setcolreal(getRGB(250-int(fRandom()*32), 250-int(fRandom()*32), 10));
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
setcolreal(getRGB(250-int(fRandom()*32), 250-int(fRandom()*32), 10));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
setcolreal(getRGB(250-int(fRandom()*32), 250-int(fRandom()*32), 10));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-30 23:57:21 +02:00
|
|
|
Uint32 Graphics::bigchunkygetcol(int t)
|
|
|
|
{
|
|
|
|
//A seperate index of colours, for simplicity
|
|
|
|
switch (t)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
return getRGB((fRandom() * 64), 10, 10);
|
|
|
|
case 2:
|
|
|
|
return getRGB(int(160- help.glow/2 - (fRandom()*20)), 200- help.glow/2, 220 - help.glow);
|
|
|
|
}
|
|
|
|
return 0x00000000;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
void Graphics::setwarprect( int a, int b, int c, int d )
|
|
|
|
{
|
|
|
|
warprect.x = a;
|
|
|
|
warprect.y = b;
|
|
|
|
warprect.w = c;
|
|
|
|
warprect.h = d;
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::textboxcenterx(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(m, textbox))
|
2020-06-28 19:40:58 +02:00
|
|
|
{
|
2020-06-28 21:43:12 +02:00
|
|
|
puts("textboxcenterx() out-of-bounds!");
|
2020-06-28 19:40:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
textbox[m].centerx();
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
int Graphics::textboxwidth(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(m, textbox))
|
2020-06-28 19:40:58 +02:00
|
|
|
{
|
2020-06-28 21:43:12 +02:00
|
|
|
puts("textboxwidth() out-of-bounds!");
|
2020-06-28 19:40:58 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
return textbox[m].w;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::textboxmoveto(int xo)
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(m, textbox))
|
2020-06-28 19:40:58 +02:00
|
|
|
{
|
2020-06-28 21:43:12 +02:00
|
|
|
puts("textboxmoveto() out-of-bounds!");
|
2020-06-28 19:40:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
textbox[m].xp = xo;
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::textboxcentery(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(m, textbox))
|
2020-06-28 19:40:58 +02:00
|
|
|
{
|
2020-06-28 21:43:12 +02:00
|
|
|
puts("textboxcentery() out-of-bounds!");
|
2020-06-28 19:40:58 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
textbox[m].centery();
|
|
|
|
}
|
|
|
|
|
|
|
|
int Graphics::crewcolour(const int t)
|
|
|
|
{
|
|
|
|
//given crewmate t, return colour in setcol
|
|
|
|
if (t == 0) return 0;
|
|
|
|
if (t == 1) return 20;
|
|
|
|
if (t == 2) return 14;
|
|
|
|
if (t == 3) return 15;
|
|
|
|
if (t == 4) return 13;
|
|
|
|
if (t == 5) return 16;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::flashlight(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
FillRect(backBuffer, 0xBBBBBBBB);
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::screenshake(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
if(flipmode)
|
|
|
|
{
|
|
|
|
SDL_Rect shakeRect;
|
2020-04-29 02:29:59 +02:00
|
|
|
setRect(shakeRect,screenshake_x, screenshake_y, backBuffer->w, backBuffer->h);
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Surface* flipBackBuffer = FlipSurfaceVerticle(backBuffer);
|
|
|
|
screenbuffer->UpdateScreen( flipBackBuffer, &shakeRect);
|
|
|
|
SDL_FreeSurface(flipBackBuffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SDL_Rect shakeRect;
|
2020-04-29 02:29:59 +02:00
|
|
|
setRect(shakeRect,screenshake_x, screenshake_y, backBuffer->w, backBuffer->h);
|
2020-01-01 21:29:24 +01:00
|
|
|
screenbuffer->UpdateScreen( backBuffer, &shakeRect);
|
|
|
|
}
|
|
|
|
|
2021-02-26 00:37:03 +01:00
|
|
|
ClearSurface(backBuffer);
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::updatescreenshake(void)
|
2020-04-29 02:29:59 +02:00
|
|
|
{
|
|
|
|
screenshake_x = static_cast<Sint32>((fRandom() * 7) - 4);
|
|
|
|
screenshake_y = static_cast<Sint32>((fRandom() * 7) - 4);
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::render(void)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
if(screenbuffer == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(flipmode)
|
|
|
|
{
|
|
|
|
SDL_Rect rect;
|
|
|
|
setRect(rect, 0, 0, backBuffer->w, backBuffer->h);
|
|
|
|
SDL_Surface* tempsurface = FlipSurfaceVerticle(backBuffer);
|
|
|
|
if(tempsurface != NULL)
|
|
|
|
{
|
|
|
|
screenbuffer->UpdateScreen( tempsurface, &rect);
|
|
|
|
SDL_FreeSurface(tempsurface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SDL_Rect rect;
|
|
|
|
setRect(rect, 0, 0, backBuffer->w, backBuffer->h);
|
|
|
|
screenbuffer->UpdateScreen( backBuffer, &rect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Explicitly declare void for all void parameter functions (#628)
Apparently in C, if you have `void test();`, it's completely okay to do
`test(2);`. The function will take in the argument, but just discard it
and throw it away. It's like a trash can, and a rude one at that. If you
declare it like `void test(void);`, this is prevented.
This is not a problem in C++ - doing `void test();` and `test(2);` is
guaranteed to result in a compile error (this also means that right now,
at least in all `.cpp` files, nobody is ever calling a void parameter
function with arguments and having their arguments be thrown away).
However, we may not be using C++ in the future, so I just want to lay
down the precedent that if a function takes in no arguments, you must
explicitly declare it as such.
I would've added `-Wstrict-prototypes`, but it produces an annoying
warning message saying it doesn't work in C++ mode if you're compiling
in C++ mode. So it can be added later.
2021-02-25 23:23:59 +01:00
|
|
|
void Graphics::renderwithscreeneffects(void)
|
2020-04-27 04:24:50 +02:00
|
|
|
{
|
|
|
|
if (game.flashlight > 0 && !game.noflashingmode)
|
|
|
|
{
|
2020-09-28 04:15:06 +02:00
|
|
|
flashlight();
|
2020-04-27 04:24:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (game.screenshake > 0 && !game.noflashingmode)
|
|
|
|
{
|
2020-09-28 04:15:06 +02:00
|
|
|
screenshake();
|
2020-04-27 04:24:50 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-09-28 04:15:06 +02:00
|
|
|
render();
|
2020-04-27 04:24:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
void Graphics::bigrprint(int x, int y, std::string& t, int r, int g, int b, bool cen, float sc)
|
|
|
|
{
|
2020-06-14 03:46:32 +02:00
|
|
|
std::vector<SDL_Surface*>& font = flipmode ? flipbfont : bfont;
|
|
|
|
|
2020-09-08 22:12:07 +02:00
|
|
|
r = clamp(r, 0, 255);
|
|
|
|
g = clamp(g, 0, 255);
|
|
|
|
b = clamp(b, 0, 255);
|
2020-01-01 21:29:24 +01:00
|
|
|
ct.colour = getRGB(r, g, b);
|
|
|
|
|
|
|
|
x = x / (sc);
|
|
|
|
|
|
|
|
x -= (len(t));
|
|
|
|
|
|
|
|
if (cen)
|
|
|
|
{
|
Reduce dependency on libc functions
During 2.3 development, there's been a gradual shift to using SDL stdlib
functions instead of libc functions, but there are still some libc
functions (or the same libc function but from the STL) in the code.
Well, this patch replaces all the rest of them in one fell swoop.
SDL's stdlib can replace most of these, but its SDL_min() and SDL_max()
are inadequate - they aren't really functions, they're more like macros
with a nasty penchant for double-evaluation. So I just made my own
VVV_min() and VVV_max() functions and placed them in Maths.h instead,
then replaced all the previous usages of min(), max(), std::min(),
std::max(), SDL_min(), and SDL_max() with VVV_min() and VVV_max().
Additionally, there's no SDL_isxdigit(), so I just implemented my own
VVV_isxdigit().
SDL has SDL_malloc() and SDL_free(), but they have some refcounting
built in to them, so in order to use them with LodePNG, I have to
replace the malloc() and free() that LodePNG uses. Which isn't too hard,
I did it in a new file called ThirdPartyDeps.c, and LodePNG is now
compiled with the LODEPNG_NO_COMPILE_ALLOCATORS definition.
Lastly, I also refactored the awful strcpy() and strcat() usages in
PLATFORM_migrateSaveData() to use SDL_snprintf() instead. I know save
migration is getting axed in 2.4, but it still bothers me to have
something like that in the codebase otherwise.
Without further ado, here is the full list of functions that the
codebase now uses:
- SDL_strlcpy() instead of strcpy()
- SDL_strlcat() instead of strcat()
- SDL_snprintf() instead of sprintf(), strcpy(), or strcat() (see above)
- VVV_min() instead of min(), std::min(), or SDL_min()
- VVV_max() instead of max(), std::max(), or SDL_max()
- VVV_isxdigit() instead of isxdigit()
- SDL_strcmp() instead of strcmp()
- SDL_strcasecmp() instead of strcasecmp() or Win32 strcmpi()
- SDL_strstr() instead of strstr()
- SDL_strlen() instead of strlen()
- SDL_sscanf() instead of sscanf()
- SDL_getenv() instead of getenv()
- SDL_malloc() instead of malloc() (replacing in LodePNG as well)
- SDL_free() instead of free() (replacing in LodePNG as well)
2021-01-12 01:17:45 +01:00
|
|
|
x = VVV_max(160 - (int((len(t)/ 2.0)*sc)), 0 );
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x *= (sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
int bfontpos = 0;
|
|
|
|
int cur;
|
2020-06-14 03:56:59 +02:00
|
|
|
int idx;
|
2020-01-31 19:25:37 +01:00
|
|
|
std::string::iterator iter = t.begin();
|
|
|
|
while (iter != t.end()) {
|
|
|
|
cur = utf8::unchecked::next(iter);
|
2020-06-14 03:56:59 +02:00
|
|
|
idx = font_idx(cur);
|
2020-09-08 09:31:44 +02:00
|
|
|
if (INBOUNDS_VEC(idx, font))
|
2020-06-14 03:56:59 +02:00
|
|
|
{
|
2020-08-04 22:09:13 +02:00
|
|
|
SDL_Surface* tempPrint = ScaleSurface(font[idx], font[idx]->w *sc,font[idx]->h *sc);
|
2020-06-14 03:56:59 +02:00
|
|
|
SDL_Rect printrect = { Sint16((x) + bfontpos), Sint16(y) , Sint16(bfont_rect.w*sc), Sint16(bfont_rect.h * sc)};
|
|
|
|
BlitSurfaceColoured(tempPrint, NULL, backBuffer, &printrect, ct);
|
|
|
|
SDL_FreeSurface(tempPrint);
|
|
|
|
}
|
2020-01-31 19:25:37 +01:00
|
|
|
bfontpos+=bfontlen(cur)* sc;
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-05-01 02:34:37 +02:00
|
|
|
void Graphics::drawtele(int x, int y, int t, Uint32 c)
|
2020-01-01 21:29:24 +01:00
|
|
|
{
|
|
|
|
setcolreal(getRGB(16,16,16));
|
|
|
|
|
|
|
|
SDL_Rect telerect;
|
|
|
|
setRect(telerect, x , y, tele_rect.w, tele_rect.h );
|
2020-09-08 09:31:44 +02:00
|
|
|
if (INBOUNDS_VEC(0, tele))
|
2020-06-14 03:37:53 +02:00
|
|
|
{
|
|
|
|
BlitSurfaceColoured(tele[0], NULL, backBuffer, &telerect, ct);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
|
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-05-01 02:34:37 +02:00
|
|
|
setcolreal(c);
|
2020-01-01 21:29:24 +01:00
|
|
|
if (t > 9) t = 8;
|
Fix teleporter sprites sometimes being solid colors
This commit fixes a bug that also sometimes occurred in 2.2, where the
teleporter sprite would randomly turn into a solid color and just be a
solid circle with no detail.
Why did this happen? The short answer is an incorrect lower bound when
clamping the teleporter sprite index in `Graphics::drawtele()`. The long
answer is bad RNG with the teleporter animation code. This commit fixes
the short answer, because I do not want to mess with the long answer.
So, here is what would happen: the teleporter's `tile` would be 6. The
teleporter code decrements its `framedelay` each frame. Then when it
reached a `framedelay` of 0, it would call `fRandom()` and essentially
ask for a random number between 0 and 6. If the RNG ended up being
greater than or equal to 4, then it would set its `walkingframe` to -5.
At the end of the routine, the teleporter's `drawframe` ends up being
its `tile` plus its `walkingframe`. So having a `walkingframe` of -5
here is fine, because its `tile` is 6.
Until it isn't. When its `tile` becomes 2, it still keeps its
`walkingframe` around. The code that runs when its `tile` is 2 does have
the possibility of completely resetting its `walkingframe` to be in
bounds (in bounds after its `tile` is added), but that only runs when
its `framedelay` is 0, and in the meantime it'll just use the previous
`walkingframe`.
So you could have a `walkingframe` of -5, plus a `tile` of 2, which
produces a `drawframe` of -3. Then `Graphics::drawtele()` will clamp
that to 0, which just means it'll draw the teleporter backing, and the
teleporter backing is a simple solid color, so the teleporter will end
up being completely and fully solid.
To fix this, I just made `Graphics::drawtele()` clamp to 1 on the lower
bound, instead of 0. So if it ever gets passed a negative teleporter
index, it'll just draw the normal teleporter sprite instead, which is
better.
2020-11-04 00:51:17 +01:00
|
|
|
if (t < 1) t = 1;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2020-04-26 20:42:06 +02:00
|
|
|
setRect(telerect, x , y, tele_rect.w, tele_rect.h );
|
2020-09-08 09:31:44 +02:00
|
|
|
if (INBOUNDS_VEC(t, tele))
|
2020-06-14 03:37:53 +02:00
|
|
|
{
|
|
|
|
BlitSurfaceColoured(tele[t], NULL, backBuffer, &telerect, ct);
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
2020-02-10 03:23:12 +01:00
|
|
|
Uint32 Graphics::getRGBA(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
|
|
|
|
{
|
|
|
|
return SDL_MapRGBA(backBuffer->format, b, g, r, a);
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
Uint32 Graphics::getRGB(Uint8 r, Uint8 g, Uint8 b)
|
|
|
|
{
|
|
|
|
return SDL_MapRGB(backBuffer->format, b, g, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint32 Graphics::getBGR(Uint8 r, Uint8 g, Uint8 b)
|
|
|
|
{
|
|
|
|
return SDL_MapRGB(backBuffer->format, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint32 Graphics::getRGB(Uint32 _col)
|
|
|
|
{
|
|
|
|
return ( _col);
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint32 Graphics::RGBflip(Uint8 r, Uint8 g, Uint8 b)
|
|
|
|
{
|
|
|
|
return SDL_MapRGB(backBuffer->format, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint32 Graphics::RGBf(int r, int g, int b)
|
|
|
|
{
|
|
|
|
r = (r+128) / 3;
|
|
|
|
g = (g+128) / 3;
|
|
|
|
b = (b+128) / 3;
|
|
|
|
return SDL_MapRGB(backBuffer->format, r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::setcolreal(Uint32 t)
|
|
|
|
{
|
|
|
|
ct.colour = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawforetile(int x, int y, int t)
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles))
|
2020-06-30 20:51:01 +02:00
|
|
|
{
|
2020-07-01 00:01:30 +02:00
|
|
|
WHINE_ONCE("drawforetile() out-of-bounds!")
|
2020-06-30 20:51:01 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect;
|
|
|
|
setRect(rect, x,y,tiles_rect.w, tiles_rect.h);
|
2020-06-30 20:47:22 +02:00
|
|
|
|
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
Make one-way recolors check for specific files
So, 2.3 added recoloring one-way tiles to no longer make them be always
yellow. However, custom levels that retexture the one-way tiles might
not want them to be recolored. So, if there are ANY custom assets
mounted, then the one-ways will not be recolored. However, if the XML
has a <onewaycol_override>1</onewaycol_override> tag, then the one-way
will be recolored again anyways.
When I added one-way recoloring, I didn't intend for any custom asset to
disable the recoloring; I only did it because I couldn't find a way to
check if a specific file was customized by the custom level or not.
However, I have figured out how to do so, and so now tiles.png one-way
recolors will only be disabled if there's a custom tiles.png, and
tiles2.png one-way recolors will only be disabled if there's a custom
tiles2.png.
In order to make sure we're not calling PhysFS functions on every single
deltaframe, I've added caching variables, tiles1_mounted and
tiles2_mounted, to Graphics; these get assigned every time
reloadresources() is called.
2021-03-06 19:52:11 +01:00
|
|
|
if (shouldrecoloroneway(t, tiles1_mounted))
|
2020-06-30 20:47:22 +02:00
|
|
|
{
|
|
|
|
colourTransform thect = {ed.getonewaycol()};
|
|
|
|
BlitSurfaceTinted(tiles[t], NULL, foregroundBuffer, &rect, thect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
BlitSurfaceStandard(tiles[t],NULL, foregroundBuffer, &rect );
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawforetile2(int x, int y, int t)
|
|
|
|
{
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles2))
|
2020-06-30 20:51:01 +02:00
|
|
|
{
|
2020-07-01 00:01:30 +02:00
|
|
|
WHINE_ONCE("drawforetile2() out-of-bounds!")
|
2020-06-30 20:51:01 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect;
|
|
|
|
setRect(rect, x,y,tiles_rect.w, tiles_rect.h);
|
2020-06-30 20:47:22 +02:00
|
|
|
|
|
|
|
#if !defined(NO_CUSTOM_LEVELS)
|
Make one-way recolors check for specific files
So, 2.3 added recoloring one-way tiles to no longer make them be always
yellow. However, custom levels that retexture the one-way tiles might
not want them to be recolored. So, if there are ANY custom assets
mounted, then the one-ways will not be recolored. However, if the XML
has a <onewaycol_override>1</onewaycol_override> tag, then the one-way
will be recolored again anyways.
When I added one-way recoloring, I didn't intend for any custom asset to
disable the recoloring; I only did it because I couldn't find a way to
check if a specific file was customized by the custom level or not.
However, I have figured out how to do so, and so now tiles.png one-way
recolors will only be disabled if there's a custom tiles.png, and
tiles2.png one-way recolors will only be disabled if there's a custom
tiles2.png.
In order to make sure we're not calling PhysFS functions on every single
deltaframe, I've added caching variables, tiles1_mounted and
tiles2_mounted, to Graphics; these get assigned every time
reloadresources() is called.
2021-03-06 19:52:11 +01:00
|
|
|
if (shouldrecoloroneway(t, tiles2_mounted))
|
2020-06-30 20:47:22 +02:00
|
|
|
{
|
|
|
|
colourTransform thect = {ed.getonewaycol()};
|
|
|
|
BlitSurfaceTinted(tiles2[t], NULL, foregroundBuffer, &rect, thect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
BlitSurfaceStandard(tiles2[t],NULL, foregroundBuffer, &rect );
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawforetile3(int x, int y, int t, int off)
|
|
|
|
{
|
2020-06-30 20:51:01 +02:00
|
|
|
t += off * 30;
|
2020-09-08 09:31:44 +02:00
|
|
|
if (!INBOUNDS_VEC(t, tiles3))
|
2020-06-30 20:51:01 +02:00
|
|
|
{
|
2020-07-01 00:01:30 +02:00
|
|
|
WHINE_ONCE("drawforetile3() out-of-bounds!")
|
2020-06-30 20:51:01 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-01-01 21:29:24 +01:00
|
|
|
SDL_Rect rect;
|
|
|
|
setRect(rect, x,y,tiles_rect.w, tiles_rect.h);
|
2020-06-30 20:51:01 +02:00
|
|
|
BlitSurfaceStandard(tiles3[t],NULL, foregroundBuffer, &rect );
|
2020-01-01 21:29:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Graphics::drawrect(int x, int y, int w, int h, int r, int g, int b)
|
|
|
|
{
|
|
|
|
SDL_Rect madrect;
|
|
|
|
//Draw the retangle indicated by that object
|
|
|
|
madrect.x = x;
|
|
|
|
madrect.y = y;
|
|
|
|
madrect.w = w;
|
|
|
|
madrect.h = 1;
|
|
|
|
FillRect(backBuffer, madrect, getRGB(b,g,r));
|
|
|
|
|
|
|
|
madrect.w = 1;
|
|
|
|
madrect.h = h;
|
|
|
|
FillRect(backBuffer, madrect, getRGB(b,g,r));
|
|
|
|
|
|
|
|
madrect.x = x + w - 1;
|
|
|
|
madrect.w = 1;
|
|
|
|
madrect.h = h;
|
|
|
|
FillRect(backBuffer, madrect, getRGB(b,g,r));
|
|
|
|
madrect.x = x;
|
|
|
|
madrect.y = y + h - 1;
|
|
|
|
madrect.w = w;
|
|
|
|
madrect.h = 1;
|
|
|
|
FillRect(backBuffer, madrect, getRGB(b,g,r));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Graphics::onscreen(int t)
|
|
|
|
{
|
|
|
|
return (t >= -40 && t <= 280);
|
|
|
|
}
|
2020-06-01 01:31:02 +02:00
|
|
|
|
2021-03-19 05:20:05 +01:00
|
|
|
void Graphics::reloadresources(void)
|
2021-02-16 00:38:41 +01:00
|
|
|
{
|
2020-06-12 02:55:27 +02:00
|
|
|
grphx.destroy();
|
|
|
|
grphx.init();
|
|
|
|
|
2021-02-16 01:13:18 +01:00
|
|
|
destroy();
|
2020-06-12 02:55:27 +02:00
|
|
|
|
|
|
|
MakeTileArray();
|
|
|
|
MakeSpriteArray();
|
|
|
|
maketelearray();
|
|
|
|
Makebfont();
|
|
|
|
|
|
|
|
images.clear();
|
|
|
|
|
|
|
|
images.push_back(grphx.im_image0);
|
|
|
|
images.push_back(grphx.im_image1);
|
|
|
|
images.push_back(grphx.im_image2);
|
|
|
|
images.push_back(grphx.im_image3);
|
|
|
|
images.push_back(grphx.im_image4);
|
|
|
|
images.push_back(grphx.im_image5);
|
|
|
|
images.push_back(grphx.im_image6);
|
|
|
|
|
|
|
|
images.push_back(grphx.im_image7);
|
|
|
|
images.push_back(grphx.im_image8);
|
|
|
|
images.push_back(grphx.im_image9);
|
|
|
|
images.push_back(grphx.im_image10);
|
|
|
|
images.push_back(grphx.im_image11);
|
|
|
|
images.push_back(grphx.im_image12);
|
|
|
|
|
2020-11-01 04:30:24 +01:00
|
|
|
if (screenbuffer != NULL)
|
|
|
|
{
|
|
|
|
screenbuffer->LoadIcon();
|
|
|
|
}
|
|
|
|
|
2021-02-16 01:24:21 +01:00
|
|
|
music.destroy();
|
2020-06-12 02:55:27 +02:00
|
|
|
music.init();
|
Make one-way recolors check for specific files
So, 2.3 added recoloring one-way tiles to no longer make them be always
yellow. However, custom levels that retexture the one-way tiles might
not want them to be recolored. So, if there are ANY custom assets
mounted, then the one-ways will not be recolored. However, if the XML
has a <onewaycol_override>1</onewaycol_override> tag, then the one-way
will be recolored again anyways.
When I added one-way recoloring, I didn't intend for any custom asset to
disable the recoloring; I only did it because I couldn't find a way to
check if a specific file was customized by the custom level or not.
However, I have figured out how to do so, and so now tiles.png one-way
recolors will only be disabled if there's a custom tiles.png, and
tiles2.png one-way recolors will only be disabled if there's a custom
tiles2.png.
In order to make sure we're not calling PhysFS functions on every single
deltaframe, I've added caching variables, tiles1_mounted and
tiles2_mounted, to Graphics; these get assigned every time
reloadresources() is called.
2021-03-06 19:52:11 +01:00
|
|
|
|
|
|
|
#ifndef NO_CUSTOM_LEVELS
|
|
|
|
tiles1_mounted = FILESYSTEM_isAssetMounted("graphics/tiles.png");
|
|
|
|
tiles2_mounted = FILESYSTEM_isAssetMounted("graphics/tiles2.png");
|
|
|
|
#endif
|
2020-06-01 01:31:02 +02:00
|
|
|
}
|
2020-05-02 22:53:19 +02:00
|
|
|
|
|
|
|
Uint32 Graphics::crewcolourreal(int t)
|
|
|
|
{
|
|
|
|
switch (t)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
return col_crewcyan;
|
|
|
|
case 1:
|
|
|
|
return col_crewpurple;
|
|
|
|
case 2:
|
|
|
|
return col_crewyellow;
|
|
|
|
case 3:
|
|
|
|
return col_crewred;
|
|
|
|
case 4:
|
|
|
|
return col_crewgreen;
|
|
|
|
case 5:
|
|
|
|
return col_crewblue;
|
|
|
|
}
|
|
|
|
return col_crewcyan;
|
|
|
|
}
|