starfighter/src/player.cpp

589 lines
14 KiB
C++
Raw Normal View History

/*
Copyright (C) 2003 Parallel Realities
Copyright (C) 2011, 2012, 2013 Guus Sliepen
Copyright (C) 2012, 2015 Julian Marchant
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
2015-02-26 17:20:36 +01:00
as published by the Free Software Foundation; either version 3
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
2015-02-26 17:20:36 +01:00
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
2015-02-26 17:20:36 +01:00
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Starfighter.h"
object player;
static bool charger_fired = false;
/*
Initialises the player for a new game.
*/
void initPlayer()
{
player.active = true;
player.x = screen->w / 2;
player.y = screen->h / 2;
player.speed = 2;
player.systemPower = player.maxShield;
player.face = 0;
player.image[0] = shipShape[0];
player.image[1] = shipShape[1];
player.engineX = player.image[0]->w;
player.engineY = (player.image[0]->h / 2);
player.owner = &player;
player.flags = FL_FRIEND;
player.weaponType[0] = W_PLAYER_WEAPON;
if(weapon[W_PLAYER_WEAPON].ammo[0] < currentGame.minPlasmaOutput)
weapon[W_PLAYER_WEAPON].ammo[0] = currentGame.minPlasmaOutput;
if(weapon[W_PLAYER_WEAPON].damage < currentGame.minPlasmaDamage)
weapon[W_PLAYER_WEAPON].damage = currentGame.minPlasmaDamage;
if(weapon[W_PLAYER_WEAPON].reload[0] > rate2reload[currentGame.minPlasmaRate])
weapon[W_PLAYER_WEAPON].reload[0] = rate2reload[currentGame.minPlasmaRate];
player.hit = 0;
engine.lowShield = (player.maxShield >= 3) ? (player.maxShield / 3) : 1;
engine.averageShield = engine.lowShield + engine.lowShield;
if ((player.weaponType[1] == W_CHARGER) || (player.weaponType[1] == W_LASER))
player.ammo[1] = 0;
}
2015-03-07 05:18:31 +01:00
void player_setTarget(int index)
{
engine.targetIndex = index;
engine.targetShield = 85;
engine.targetShield /= aliens[index].shield;
2015-03-07 05:18:31 +01:00
}
void exitPlayer()
{
charger_fired = false;
if ((player.weaponType[1] == W_CHARGER) || (player.weaponType[1] == W_LASER))
player.ammo[1] = 0;
}
void doPlayer()
{
// This causes the motion to slow
engine.ssx *= 0.99;
engine.ssy *= 0.99;
engine.smx = 0;
engine.smy = 0;
int shapeToUse;
float cd;
float cc;
bool xmoved = false;
bool ymoved = false;
if (player.shield > -100)
{
if (player.shield > 0)
{
2013-09-30 16:52:43 +02:00
if ((engine.keyState[KEY_FIRE]))
ship_fireBullet(&player, 0);
2013-09-30 16:52:43 +02:00
if ((engine.keyState[KEY_ALTFIRE]) && (player.weaponType[1] != W_NONE))
{
if ((player.weaponType[1] != W_CHARGER) &&
(player.weaponType[1] != W_LASER) && (player.ammo[1] > 0))
{
ship_fireBullet(&player, 1);
}
if (player.weaponType[1] == W_LASER)
{
if (player.ammo[1] < 100)
{
ship_fireBullet(&player, 1);
player.ammo[1] += 2;
if (player.ammo[1] >= 100)
{
player.ammo[1] = 200;
setInfoLine("Laser Overheat!!", FONT_WHITE);
}
}
}
}
if (player.weaponType[1] == W_CHARGER)
{
if (engine.keyState[KEY_ALTFIRE] &&
((currentGame.difficulty == DIFFICULTY_ORIGINAL) ||
!(engine.keyState[KEY_FIRE])))
{
if (!charger_fired)
{
if (currentGame.difficulty == DIFFICULTY_ORIGINAL)
{
LIMIT_ADD(player.ammo[1], 1, 0, 200);
}
else
{
LIMIT_ADD(player.ammo[1], 1, 0, 150);
if (player.ammo[1] >= 150)
{
ship_fireBullet(&player, 1);
player.ammo[1] = 0;
charger_fired = true;
}
}
}
}
else
{
if (player.ammo[1] > 0)
ship_fireBullet(&player, 1);
player.ammo[1] = 0;
charger_fired = false;
}
}
2013-09-30 16:52:43 +02:00
if ((engine.keyState[KEY_SWITCH]))
{
if ((weapon[W_PLAYER_WEAPON].ammo[0] >= 3) &&
(weapon[W_PLAYER_WEAPON].ammo[0] <= currentGame.maxPlasmaOutput))
{
weapon[W_PLAYER_WEAPON].flags ^= WF_SPREAD;
if (weapon[W_PLAYER_WEAPON].flags & WF_SPREAD)
{
setInfoLine("Weapon set to Spread", FONT_WHITE);
}
else
{
setInfoLine("Weapon set to Concentrate", FONT_WHITE);
}
}
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_SWITCH] = 0;
}
LIMIT_ADD(player.reload[0], -1, 0, 999);
LIMIT_ADD(player.reload[1], -1, 0, 999);
2013-09-30 16:52:43 +02:00
if (engine.keyState[KEY_UP])
{
player.y -= player.speed;
engine.ssy += 0.1;
ymoved = true;
}
2013-09-30 16:52:43 +02:00
if (engine.keyState[KEY_DOWN])
{
player.y += player.speed;
engine.ssy -= 0.1;
ymoved = true;
}
2013-09-30 16:52:43 +02:00
if (engine.keyState[KEY_LEFT])
{
player.x -= player.speed;
engine.ssx += 0.1;
player.face = 1;
xmoved = true;
}
2013-09-30 16:52:43 +02:00
if (engine.keyState[KEY_RIGHT])
{
player.x += player.speed;
engine.ssx -= 0.1;
player.face = 0;
xmoved = true;
}
2013-09-30 16:52:43 +02:00
if (engine.keyState[KEY_ESCAPE])
{
if ((engine.done == 0) && (engine.gameSection == SECTION_GAME) &&
(currentMission.remainingObjectives1 == 0))
{
2015-03-08 15:38:58 +01:00
audio_playSound(SFX_FLY, screen->w / 2);
engine.done = 2;
engine.missionCompleteTimer = (SDL_GetTicks() - 1);
}
}
2013-09-30 16:52:43 +02:00
if (engine.keyState[KEY_PAUSE])
{
engine.paused = true;
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_PAUSE] = 0;
}
if (((currentGame.area == MISN_ELLESH) &&
(aliens[ALIEN_BOSS].shield > 0)) ||
(currentGame.area == MISN_MARS))
{
player.face = 0;
xmoved = true;
ymoved = true;
}
if (engine.done == 0)
{
if (xmoved)
{
if (player.x < xViewBorder)
{
engine.smx += xViewBorder - player.x;
player.x = xViewBorder;
}
else if (player.x > screen->w - xViewBorder)
{
engine.smx += (screen->w - xViewBorder) - player.x;
player.x = screen->w - xViewBorder;
}
}
else if (currentGame.difficulty != DIFFICULTY_ORIGINAL)
{
cd = player.x - screen->w / 2;
if (cd < 0)
{
2015-03-17 21:54:00 +01:00
cc = MAX(cd / 10, MAX(0, engine.ssx) - cameraMaxSpeed);
2015-02-27 07:10:27 +01:00
player.x -= cc;
engine.smx -= cc;
}
else if (cd > 0)
{
2015-03-17 21:54:00 +01:00
cc = MIN(cd / 10, cameraMaxSpeed + MIN(0, engine.ssx));
2015-02-27 07:10:27 +01:00
player.x -= cc;
engine.smx -= cc;
}
}
2015-03-28 18:18:37 +01:00
if (ymoved)
{
if (player.y < yViewBorder)
{
engine.smy += yViewBorder - player.y;
player.y = yViewBorder;
}
else if (player.y > screen->h - yViewBorder)
{
engine.smy += (screen->h - yViewBorder) - player.y;
player.y = screen->h - yViewBorder;
}
}
else if (currentGame.difficulty != DIFFICULTY_ORIGINAL)
{
cd = player.y - screen->h / 2;
if (cd < 0)
{
2015-03-17 21:54:00 +01:00
cc = MAX(cd / 10, MAX(0, engine.ssy) - cameraMaxSpeed);
2015-02-27 07:10:27 +01:00
player.y -= cc;
engine.smy -= cc;
}
else if (cd > 0)
{
2015-03-17 21:54:00 +01:00
cc = MIN(cd / 10, cameraMaxSpeed + MIN(0, engine.ssy));
2015-02-27 07:10:27 +01:00
player.y -= cc;
engine.smy -= cc;
}
}
}
if ((player.maxShield <= 1) || (player.shield > engine.lowShield))
addEngine(&player);
shapeToUse = player.face;
if (player.hit)
shapeToUse += SHIP_HIT_INDEX;
LIMIT_ADD(player.hit, -1, 0, 100);
blit(shipShape[shapeToUse], (int)player.x, (int)player.y);
if ((player.maxShield > 1) && (player.shield <= engine.lowShield) &&
(rand() % 5 < 1))
addExplosion(player.x + RANDRANGE(-10, 10),
player.y + RANDRANGE(-10, 20), E_SMOKE);
}
else
{
player.active = false;
player.shield--;
if (player.shield == -1)
{
if ((currentGame.hasWingMate1) || (aliens[ALIEN_KLINE].active))
getPlayerDeathMessage();
// Make it look like the ships are all still moving...
if (currentGame.area == MISN_ELLESH)
{
for (int i = 0 ; i < ALIEN_MAX ; i++)
aliens[i].flags |= FL_LEAVESECTOR;
}
2015-03-08 15:38:58 +01:00
audio_playSound(SFX_DEATH, player.x);
audio_playSound(SFX_EXPLOSION, player.x);
}
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_UP] = engine.keyState[KEY_DOWN] = engine.keyState[KEY_LEFT] = engine.keyState[KEY_RIGHT] = 0;
if ((rand() % 3) == 0)
addExplosion(player.x + RANDRANGE(-10, 10),
player.y + RANDRANGE(-10, 10), E_BIG_EXPLOSION);
if (player.shield == -99)
addDebris((int)player.x, (int)player.y, player.maxShield);
}
}
LIMIT(engine.ssx, -cameraMaxSpeed, cameraMaxSpeed);
LIMIT(engine.ssy, -cameraMaxSpeed, cameraMaxSpeed);
// Specific for the mission were you have to chase the Executive Transport
if ((currentGame.area == MISN_ELLESH) && (aliens[ALIEN_BOSS].shield > 0) &&
(player.shield > 0))
{
engine.ssx = -6;
engine.ssy = 0;
}
if (currentGame.area == MISN_MARS)
{
engine.ssx = -6;
engine.ssy = 0;
}
player.dx = engine.ssx;
player.dy = engine.ssy;
}
void flushInput()
{
2013-09-30 16:52:43 +02:00
for (int i = 0; i < KEY_LAST; i++)
engine.keyState[i] = 0;
while (SDL_PollEvent(&engine.event)){}
}
2013-09-30 16:52:43 +02:00
static enum keys mapkey(uint32_t code) {
switch (code) {
case SDLK_UP:
case SDLK_KP_8:
2013-09-30 16:52:43 +02:00
return KEY_UP;
case SDLK_DOWN:
case SDLK_KP_2:
case SDLK_KP_5:
2013-09-30 16:52:43 +02:00
return KEY_DOWN;
case SDLK_LEFT:
case SDLK_KP_4:
2013-09-30 16:52:43 +02:00
return KEY_LEFT;
case SDLK_RIGHT:
case SDLK_KP_6:
2013-09-30 16:52:43 +02:00
return KEY_RIGHT;
case SDLK_LCTRL:
case SDLK_RCTRL:
case SDLK_RETURN:
case SDLK_z:
case SDLK_c:
case SDLK_a:
case SDLK_d:
case SDLK_f:
case SDLK_SLASH:
case SDLK_COMMA:
case SDLK_1:
case SDLK_3:
case SDLK_KP_0:
2013-09-30 16:52:43 +02:00
return KEY_FIRE;
case SDLK_SPACE:
case SDLK_x:
case SDLK_s:
case SDLK_PERIOD:
case SDLK_2:
case SDLK_KP_1:
2013-09-30 16:52:43 +02:00
return KEY_ALTFIRE;
case SDLK_LSHIFT:
case SDLK_RSHIFT:
case SDLK_LALT:
case SDLK_RALT:
case SDLK_KP_7:
case SDLK_KP_9:
2013-09-30 16:52:43 +02:00
return KEY_SWITCH;
case SDLK_p:
return KEY_PAUSE;
case SDLK_ESCAPE:
case SDLK_q:
case SDLK_BACKSPACE:
2013-09-30 16:52:43 +02:00
return KEY_ESCAPE;
case SDLK_F11:
return KEY_FULLSCREEN;
default:
return KEY_DUMMY;
}
}
void getPlayerInput()
{
while (SDL_PollEvent(&engine.event))
{
switch (engine.event.type)
{
case SDL_QUIT:
exit(0);
break;
case SDL_MOUSEBUTTONDOWN:
if (engine.gameSection == SECTION_INTERMISSION)
{
2013-09-30 16:52:43 +02:00
if (engine.event.button.button == SDL_BUTTON_LEFT) engine.keyState[KEY_FIRE] = 1;
if (engine.event.button.button == SDL_BUTTON_RIGHT) engine.keyState[KEY_ALTFIRE] = 1;
}
break;
case SDL_KEYDOWN:
2013-09-30 16:52:43 +02:00
engine.keyState[mapkey(engine.event.key.keysym.sym)] = 1;
if (engine.gameSection != SECTION_GAME)
engine.paused = false;
break;
case SDL_KEYUP:
2015-02-27 01:27:38 +01:00
if (engine.event.key.keysym.sym != SDLK_p)
2013-09-30 16:52:43 +02:00
engine.keyState[mapkey(engine.event.key.keysym.sym)] = 0;
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
switch (engine.event.jbutton.button)
{
case 0:
case 3:
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_ALTFIRE] = engine.event.jbutton.state;
break;
case 1:
case 2:
engine.keyState[KEY_FIRE] = engine.event.jbutton.state;
break;
case 4:
case 6:
engine.keyState[KEY_ESCAPE] = engine.event.jbutton.state;
break;
case 5:
case 7:
case 8:
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_SWITCH] = engine.event.jbutton.state;
break;
case 9:
if (engine.event.jbutton.state)
engine.keyState[KEY_PAUSE] = 1;
break;
}
break;
case SDL_JOYHATMOTION:
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_UP] = engine.event.jhat.value & SDL_HAT_UP;
engine.keyState[KEY_DOWN] = engine.event.jhat.value & SDL_HAT_DOWN;
engine.keyState[KEY_LEFT] = engine.event.jhat.value & SDL_HAT_LEFT;
engine.keyState[KEY_RIGHT] = engine.event.jhat.value & SDL_HAT_RIGHT;
break;
case SDL_JOYAXISMOTION:
static bool prevjoyup, prevjoydown, prevjoyleft, prevjoyright;
if (engine.event.jaxis.axis & 1) {
bool joyup = engine.event.jaxis.value < -16384;
bool joydown = engine.event.jaxis.value >= 16384;
if(joyup != prevjoyup)
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_UP] = prevjoyup = joyup;
if(joydown != prevjoydown)
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_DOWN] = prevjoydown = joydown;
} else {
bool joyleft = engine.event.jaxis.value < -16384;
bool joyright = engine.event.jaxis.value >= 16384;
if(joyleft != prevjoyleft)
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_LEFT] = prevjoyleft = joyleft;
if(joyright != prevjoyright)
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_RIGHT] = prevjoyright = joyright;
}
break;
2013-09-30 16:52:43 +02:00
case SDL_WINDOWEVENT:
if(engine.event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
engine.paused = 1;
break;
}
2013-09-30 16:52:43 +02:00
if (engine.keyState[KEY_FULLSCREEN])
{
engine.fullScreen = !engine.fullScreen;
2013-09-30 16:52:43 +02:00
SDL_SetWindowFullscreen(window, engine.fullScreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
engine.keyState[KEY_FULLSCREEN] = 0;
}
}
if (engine.gameSection == SECTION_INTERMISSION)
{
// Get the current mouse position
static int px = -1, py = -1;
int x, y;
SDL_GetMouseState(&x, &y);
if (px == x && py == y) {
2013-09-30 16:52:43 +02:00
if(engine.keyState[KEY_UP] && engine.cursor_y > 0)
engine.cursor_y -= 4;
2013-09-30 16:52:43 +02:00
if(engine.keyState[KEY_DOWN] && engine.cursor_y < screen->h - 4)
engine.cursor_y += 4;
2013-09-30 16:52:43 +02:00
if(engine.keyState[KEY_LEFT] && engine.cursor_x > 0)
engine.cursor_x -= 4;
2013-09-30 16:52:43 +02:00
if(engine.keyState[KEY_RIGHT] && engine.cursor_x < screen->w - 4)
engine.cursor_x += 4;
} else {
engine.cursor_x = px = x;
engine.cursor_y = py = y;
}
}
}
void leaveSector()
{
2013-09-30 16:52:43 +02:00
engine.keyState[KEY_UP] = engine.keyState[KEY_DOWN] = engine.keyState[KEY_LEFT] = engine.keyState[KEY_RIGHT] = 0;
engine.keyState[KEY_FIRE] = engine.keyState[KEY_ALTFIRE] = 0;
if (engine.done == 0)
engine.done = 3;
if (engine.done == 3)
{
player.face = 0;
if (player.x > -100)
{
player.x += engine.ssx;
engine.ssx -= 1;
if (player.y > screen->h / 2)
player.y--;
if (player.y < screen->h / 2)
player.y++;
}
if (player.x <= -100)
{
engine.done = 2;
2015-03-08 15:38:58 +01:00
audio_playSound(SFX_FLY, screen->w / 2);
}
}
if (engine.done == 2)
{
player.face = 0;
player.x += 12;
engine.ssx -= 0.2;
if (player.x > (2 * screen->w))
engine.done = 1;
}
}