blobwarsAttrition/src/world/radar.c

457 lines
9.6 KiB
C
Raw Normal View History

2018-02-12 09:09:03 +01:00
/*
2019-06-02 17:13:34 +02:00
Copyright (C) 2018-2019 Parallel Realities
2018-02-12 09:09:03 +01:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "radar.h"
2018-02-09 20:20:37 +01:00
static void logic(void);
static void draw(void);
2018-02-12 09:09:03 +01:00
static void getMapTileColor(int i, SDL_Color *c);
2018-02-09 20:20:37 +01:00
static void drawMap(void);
2018-02-12 09:09:03 +01:00
static void drawEntities(void);
static int isValidBlip(Entity *e);
static void getBlipColor(Entity *e, SDL_Color *c);
2018-02-12 23:40:15 +01:00
static void drawMarkers(void);
static void initMarker(int i, int x, int y, int angle, int type);
static void initBlips(void);
static void enableMarker(int type, int i);
2018-02-09 20:20:37 +01:00
static SDL_Rect viewRect;
2018-02-12 23:40:15 +01:00
static Texture *atlasTexture;
static Atlas *background;
static Atlas *arrow;
static int blinkTimer;
2018-12-22 22:53:19 +01:00
static SDL_Point offset;
static Marker marker[MAX_MARKERS];
static Entity *blips[MAX_BLIPS];
2018-02-09 20:20:37 +01:00
void initRadar(void)
{
2018-02-12 23:40:15 +01:00
SDL_Rect limits;
2018-12-22 22:53:19 +01:00
int renderWidth, renderHeight;
2019-06-02 17:13:34 +02:00
2018-12-22 22:53:19 +01:00
renderWidth = (app.config.winWidth / MAP_TILE_SIZE) + 1;
renderHeight = (app.config.winHeight / MAP_TILE_SIZE) + 1;
2019-06-02 17:13:34 +02:00
startSectionTransition();
2019-06-02 17:13:34 +02:00
memset(blips, 0, sizeof(Entity*) * MAX_BLIPS);
memset(marker, 0, sizeof(Marker) * MAX_MARKERS);
2019-06-02 17:13:34 +02:00
2018-03-15 09:01:04 +01:00
app.delegate.logic = &logic;
app.delegate.draw = &draw;
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
viewRect.x = (world.bob->x / MAP_TILE_SIZE) - (VIEW_SIZE_X / 2);
viewRect.y = (world.bob->y / MAP_TILE_SIZE) - (VIEW_SIZE_Y / 2);
viewRect.w = VIEW_SIZE_X;
viewRect.h = VIEW_SIZE_Y;
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
limits.x = world.map.bounds.x / MAP_TILE_SIZE;
limits.y = world.map.bounds.y / MAP_TILE_SIZE;
2018-12-22 22:53:19 +01:00
limits.w = (world.map.bounds.w / MAP_TILE_SIZE) - (VIEW_SIZE_X - renderWidth) - 1;
limits.h = (world.map.bounds.h / MAP_TILE_SIZE) - (VIEW_SIZE_Y - renderHeight);
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
viewRect.x = limit(viewRect.x, limits.x, limits.w);
viewRect.y = limit(viewRect.y, limits.y, limits.h);
2019-06-02 17:13:34 +02:00
2018-02-26 09:19:21 +01:00
if (viewRect.y > limits.h)
{
viewRect.y -= (viewRect.y - limits.h);
}
2018-02-12 23:40:15 +01:00
blinkTimer = 0;
atlasTexture = getTexture("gfx/atlas/atlas.png");
background = getImageFromAtlas("gfx/radar/background.png");
arrow = getImageFromAtlas("gfx/radar/arrow.png");
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
/* top */
2018-12-22 22:53:19 +01:00
initMarker(0, app.config.winWidth / 2 - 275, app.config.winHeight / 2 - 275, 0, M_MIA);
initMarker(1, app.config.winWidth / 2, app.config.winHeight / 2 - 275, 0, M_ITEM);
initMarker(2, app.config.winWidth / 2 + 275, app.config.winHeight / 2 - 275, 0, M_ENEMY);
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
/* bottom */
2018-12-22 22:53:19 +01:00
initMarker(3, app.config.winWidth / 2 - 275, app.config.winHeight / 2 + 275, 180, M_MIA);
initMarker(4, app.config.winWidth / 2, app.config.winHeight / 2 + 275, 180, M_ITEM);
initMarker(5, app.config.winWidth / 2 + 275, app.config.winHeight / 2 + 275, 180, M_ENEMY);
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
/* left */
2018-12-22 22:53:19 +01:00
initMarker(6, app.config.winWidth / 2 - 450, app.config.winHeight / 2 - 200, 270, M_MIA);
initMarker(7, app.config.winWidth / 2 - 450, app.config.winHeight / 2, 270, M_ITEM);
initMarker(8, app.config.winWidth / 2 - 450, app.config.winHeight / 2 + 200, 270, M_ENEMY);
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
/* right */
2018-12-22 22:53:19 +01:00
initMarker(9, app.config.winWidth / 2 + 450, app.config.winHeight / 2 - 200, 90, M_MIA);
initMarker(10, app.config.winWidth / 2 + 450, app.config.winHeight / 2, 90, M_ITEM);
initMarker(11, app.config.winWidth / 2 + 450, app.config.winHeight / 2 + 200, 90, M_ENEMY);
2019-06-02 17:13:34 +02:00
initBlips();
2019-06-02 17:13:34 +02:00
2018-12-22 22:53:19 +01:00
offset.x = ((app.config.winWidth - (RADAR_TILE_SIZE * VIEW_SIZE_X)) / 2);
offset.y = ((app.config.winHeight - (RADAR_TILE_SIZE * VIEW_SIZE_Y)) / 2);
2019-06-02 17:13:34 +02:00
endSectionTransition();
2018-02-09 20:20:37 +01:00
}
2018-02-12 23:40:15 +01:00
static void initMarker(int i, int x, int y, int angle, int type)
2018-02-09 20:20:37 +01:00
{
2018-02-12 23:40:15 +01:00
marker[i].x = x;
marker[i].y = y;
marker[i].angle = angle;
marker[i].type = type;
}
2018-02-09 20:20:37 +01:00
static void initBlips(void)
{
Entity *e;
int i, x, y;
2019-06-02 17:13:34 +02:00
i = 0;
2019-06-02 17:13:34 +02:00
for (e = world.entityHead.next ; e != NULL ; e = e->next)
{
if (isValidBlip(e))
{
x = (e->x / MAP_TILE_SIZE);
y = (e->y / MAP_TILE_SIZE);
2019-06-02 17:13:34 +02:00
if (y < viewRect.y)
{
enableMarker(e->type, M_MIA);
}
2019-06-02 17:13:34 +02:00
if (y > viewRect.y + viewRect.h)
{
enableMarker(e->type, M_MIA + (M_MAX));
}
2019-06-02 17:13:34 +02:00
if (x < viewRect.x)
{
enableMarker(e->type, M_MIA + (M_MAX * 2));
}
2019-06-02 17:13:34 +02:00
if (x > viewRect.x + viewRect.w)
{
enableMarker(e->type, M_MIA + (M_MAX * 3));
}
2019-06-02 17:13:34 +02:00
if (i < MAX_BLIPS)
{
blips[i++] = e;
}
}
}
}
static void enableMarker(int type, int i)
{
switch (type)
{
case ET_BOB:
case ET_MIA:
case ET_TEEKA:
marker[i].visible = 1;
break;
2019-06-02 17:13:34 +02:00
2018-03-01 23:30:33 +01:00
case ET_HEART:
case ET_CELL:
case ET_KEY:
case ET_ITEM:
marker[i + 1].visible = 1;
break;
2019-06-02 17:13:34 +02:00
case ET_ENEMY:
case ET_BOSS:
case ET_DESTRUCTABLE:
2018-03-05 09:39:54 +01:00
case ET_ITEM_PAD:
marker[i + 2].visible = 1;
break;
2019-06-02 17:13:34 +02:00
default:
break;
}
}
2018-02-12 23:40:15 +01:00
static void logic(void)
{
int i;
Marker *m;
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
blinkTimer++;
blinkTimer %= 60;
2019-06-02 17:13:34 +02:00
for (i = 0 ; i < MAX_MARKERS ; i++)
{
m = &marker[i];
2019-06-02 17:13:34 +02:00
if (i / 3 % 2 == 0)
{
m->value += 0.1;
}
else
{
m->value -= 0.1;
}
2019-06-02 17:13:34 +02:00
if (i < 6)
{
m->y += (float) sin(m->value);
}
else
{
m->x += (float) sin(m->value);
}
}
2019-06-02 17:13:34 +02:00
if (isControl(CONTROL_MAP))
{
pauseSound(0);
clearControl(CONTROL_MAP);
exitRadar();
}
2018-02-09 20:20:37 +01:00
}
static void draw(void)
{
2018-12-22 22:53:19 +01:00
blitRectScaled(atlasTexture->texture, 0, 0, app.config.winWidth, app.config.winHeight, &background->rect, 0);
2018-02-12 23:40:15 +01:00
2018-02-09 20:20:37 +01:00
drawMap();
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
drawEntities();
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
drawMarkers();
2019-06-02 17:13:34 +02:00
2018-12-22 22:53:19 +01:00
drawRect((app.config.winWidth / 2) - 230, app.config.winHeight - 58, 14, 14, 255, 255, 0, 255);
drawText((app.config.winWidth / 2) - 200, app.config.winHeight - 65, 20, TA_LEFT, colors.yellow, app.strings[ST_MIAS]);
2019-06-02 17:13:34 +02:00
2018-12-22 22:53:19 +01:00
drawRect((app.config.winWidth / 2) - 30, app.config.winHeight - 58, 14, 14, 0, 255, 255, 255);
drawText((app.config.winWidth / 2), app.config.winHeight - 65, 20, TA_LEFT, colors.cyan, app.strings[ST_ITEMS]);
2019-06-02 17:13:34 +02:00
2018-12-22 22:53:19 +01:00
drawRect((app.config.winWidth / 2) + 170, app.config.winHeight - 58, 14, 14, 255, 0, 0, 255);
drawText((app.config.winWidth / 2) + 200, app.config.winHeight - 65, 20, TA_LEFT, colors.red, app.strings[ST_TARGETS]);
2018-02-09 20:20:37 +01:00
}
static void drawMap(void)
{
2018-02-12 23:40:15 +01:00
int x, y, mx, my, i;
2018-02-12 09:09:03 +01:00
SDL_Color c;
2019-06-02 17:13:34 +02:00
2018-02-09 20:20:37 +01:00
for (x = 0 ; x < viewRect.w ; x++)
{
for (y = 0 ; y < viewRect.h ; y++)
{
mx = viewRect.x + x;
my = viewRect.y + y;
2019-06-02 17:13:34 +02:00
2018-12-22 22:53:19 +01:00
drawRect(offset.x + (x * RADAR_TILE_SIZE), offset.y + (y * RADAR_TILE_SIZE), RADAR_TILE_SIZE - 1, RADAR_TILE_SIZE - 1, 0, 0, 0, 255);
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
if (isWithinMap(mx, my))
2018-02-09 20:20:37 +01:00
{
2018-02-12 23:40:15 +01:00
i = world.map.data[mx][my];
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
if (i > MAP_TILE_AIR && i < MAP_TILE_NON_SOLID)
2018-02-12 09:09:03 +01:00
{
2018-02-12 23:40:15 +01:00
getMapTileColor(i, &c);
2019-06-02 17:13:34 +02:00
2018-12-22 22:53:19 +01:00
drawRect(offset.x + (x * RADAR_TILE_SIZE), offset.y + (y * RADAR_TILE_SIZE), RADAR_TILE_SIZE - 1, RADAR_TILE_SIZE - 1, c.r, c.g, c.b, 255);
2018-02-12 09:09:03 +01:00
}
2018-02-09 20:20:37 +01:00
}
2018-02-12 23:40:15 +01:00
}
2018-02-09 20:20:37 +01:00
}
2019-06-02 17:13:34 +02:00
2018-12-22 22:53:19 +01:00
drawOutlineRect(offset.x, offset.y, viewRect.w * RADAR_TILE_SIZE, viewRect.h * RADAR_TILE_SIZE, 0, 128, 0, 255);
2018-02-09 20:20:37 +01:00
}
2018-02-12 09:09:03 +01:00
static void getMapTileColor(int i, SDL_Color *c)
{
c->r = c->g = c->b = 0;
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
switch (i)
{
case MAP_TILE_WATER:
c->b = 255;
break;
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
case MAP_TILE_SLIME:
c->g = 255;
break;
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
case MAP_TILE_LAVA:
2018-02-12 23:40:15 +01:00
c->g = 128;
2018-02-12 09:09:03 +01:00
c->r = 255;
break;
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
default:
if (i < MAP_TILE_NON_SOLID)
{
c->r = c->g = c->b = 168;
}
break;
}
}
2018-02-09 20:20:37 +01:00
static void drawEntities(void)
{
Entity *e;
int i, x, y;
2018-02-12 09:09:03 +01:00
SDL_Color c;
2019-06-02 17:13:34 +02:00
for (i = 0 ; i < MAX_BLIPS ; i++)
2018-02-09 20:20:37 +01:00
{
e = blips[i];
2019-06-02 17:13:34 +02:00
if (e != NULL)
2018-02-12 09:09:03 +01:00
{
2018-02-12 09:32:21 +01:00
x = (e->x / MAP_TILE_SIZE);
y = (e->y / MAP_TILE_SIZE);
2019-06-02 17:13:34 +02:00
2018-02-12 09:32:21 +01:00
if (x >= viewRect.x && x < viewRect.x + viewRect.w && y >= viewRect.y && y < viewRect.y + viewRect.h)
{
x -= viewRect.x;
y -= viewRect.y;
2019-06-02 17:13:34 +02:00
2018-02-12 09:32:21 +01:00
getBlipColor(e, &c);
2018-02-09 20:20:37 +01:00
if (blinkTimer < 30)
{
2018-12-22 22:53:19 +01:00
drawRect(offset.x + (x * RADAR_TILE_SIZE), offset.y + (y * RADAR_TILE_SIZE), RADAR_TILE_SIZE - 1, RADAR_TILE_SIZE - 1, c.r, c.g, c.b, 255);
}
2018-02-12 09:32:21 +01:00
}
2018-02-12 09:09:03 +01:00
}
}
}
static int isValidBlip(Entity *e)
{
Item *i;
2019-06-02 17:13:34 +02:00
if (!(e->flags & (EF_GONE | EF_TELEPORTING)))
2018-02-12 09:09:03 +01:00
{
switch (e->type)
{
case ET_BOB:
case ET_MIA:
case ET_TEEKA:
case ET_BOSS:
2018-03-01 23:30:33 +01:00
case ET_HEART:
case ET_CELL:
case ET_KEY:
case ET_DESTRUCTABLE:
return 1;
2019-06-02 17:13:34 +02:00
case ET_ITEM:
i = (Item*)e;
return i->canBeCarried || i->canBePickedUp || i->isMissionTarget;
2019-06-02 17:13:34 +02:00
case ET_ENEMY:
return e->isMissionTarget || ((Unit*)e)->carriedItem != NULL || world.isEliminateAllEnemies;
2019-06-02 17:13:34 +02:00
2018-03-05 09:39:54 +01:00
case ET_ITEM_PAD:
return !e->active;
2019-06-02 17:13:34 +02:00
default:
return 0;
}
2018-02-12 09:09:03 +01:00
}
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
return 0;
}
static void getBlipColor(Entity *e, SDL_Color *c)
{
Unit *u;
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
c->r = c->g = c->b = 0;
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
switch (e->type)
{
case ET_BOB:
2018-02-12 23:40:15 +01:00
c->r = c->g = c->b = 255;
2018-02-12 09:09:03 +01:00
break;
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
case ET_ENEMY:
u = (Unit*)e;
if (u->carriedItem != NULL)
{
c->g = 168;
c->b = 255;
}
else
{
c->r = 255;
}
break;
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
case ET_BOSS:
case ET_DESTRUCTABLE:
2018-03-05 09:39:54 +01:00
case ET_ITEM_PAD:
2018-02-12 09:09:03 +01:00
c->r = 255;
break;
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
case ET_TEEKA:
2018-02-12 23:40:15 +01:00
case ET_MIA:
c->r = c->g = 255;
break;
2019-06-02 17:13:34 +02:00
2018-03-01 23:30:33 +01:00
case ET_HEART:
case ET_CELL:
2018-02-12 09:09:03 +01:00
case ET_KEY:
case ET_ITEM:
2018-02-12 23:40:15 +01:00
c->g = 168;
c->b = 255;
break;
2019-06-02 17:13:34 +02:00
2018-02-12 09:09:03 +01:00
default:
break;
2018-02-09 20:20:37 +01:00
}
}
2018-02-12 23:40:15 +01:00
static void drawMarkers(void)
{
int i;
2019-06-02 17:13:34 +02:00
for (i = 0 ; i < MAX_MARKERS ; i++)
2018-02-12 23:40:15 +01:00
{
if (marker[i].visible)
2018-02-12 23:40:15 +01:00
{
switch (i % M_MAX)
{
case M_MIA:
SDL_SetTextureColorMod(atlasTexture->texture, 255, 255, 0);
break;
2019-06-02 17:13:34 +02:00
case M_ITEM:
SDL_SetTextureColorMod(atlasTexture->texture, 0, 192, 255);
break;
2019-06-02 17:13:34 +02:00
case M_ENEMY:
SDL_SetTextureColorMod(atlasTexture->texture, 255, 0, 0);
break;
}
2019-06-02 17:13:34 +02:00
blitRectRotated(atlasTexture->texture, marker[i].x, marker[i].y, &arrow->rect, marker[i].angle);
2018-02-12 23:40:15 +01:00
}
}
2019-06-02 17:13:34 +02:00
2018-02-12 23:40:15 +01:00
SDL_SetTextureColorMod(atlasTexture->texture, 255, 255, 255);
}