Commit db07689d authored by AlisterT's avatar AlisterT

Event refactoring, bug fixes.

parent 6e631c48
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Part of the OpenJazz project * Part of the OpenJazz project
* *
* *
* Copyright (c) 2005-2009 Alister Thomson * Copyright (c) 2005-2010 Alister Thomson
* *
* OpenJazz is distributed under the terms of * OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0 * the GNU General Public License, version 2.0
...@@ -42,10 +42,12 @@ Anim::~Anim () { ...@@ -42,10 +42,12 @@ Anim::~Anim () {
} }
void Anim::setData (int amount, signed char x, signed char y) { void Anim::setData (int amount, signed char sX, signed char sY, signed char x, signed char y) {
frames = amount; frames = amount;
xOffset = x << 2; shootX = sX;
shootY = sY;
xOffset = x;
yOffset = y; yOffset = y;
return; return;
...@@ -66,7 +68,7 @@ void Anim::setFrame (int nextFrame, bool looping) { ...@@ -66,7 +68,7 @@ void Anim::setFrame (int nextFrame, bool looping) {
void Anim::setFrameData (Sprite *sprite, signed char x, signed char y) { void Anim::setFrameData (Sprite *sprite, signed char x, signed char y) {
sprites[frame] = sprite; sprites[frame] = sprite;
xOffsets[frame] = x << 2; xOffsets[frame] = x;
yOffsets[frame] = y; yOffsets[frame] = y;
return; return;
...@@ -81,14 +83,28 @@ int Anim::getWidth () { ...@@ -81,14 +83,28 @@ int Anim::getWidth () {
} }
int Anim::getHeight() { int Anim::getHeight () {
return sprites[frame]->getHeight(); return sprites[frame]->getHeight();
} }
void Anim::draw (int x, int y) { fixed Anim::getShootX () {
return ITOF(shootX + xOffsets[frame] - xOffset);
}
fixed Anim::getShootY () {
return ITOF(shootY + yOffsets[frame] - yOffset);
}
void Anim::draw (fixed x, fixed y) {
sprites[frame]->draw(FTOI(x) + xOffsets[frame] - xOffset - FTOI(viewX), sprites[frame]->draw(FTOI(x) + xOffsets[frame] - xOffset - FTOI(viewX),
FTOI(y) + yOffsets[frame] - yOffset - FTOI(viewY)); FTOI(y) + yOffsets[frame] - yOffset - FTOI(viewY));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Part of the OpenJazz project * Part of the OpenJazz project
* *
* *
* Copyright (c) 2005-2009 Alister Thomson * Copyright (c) 2005-2010 Alister Thomson
* *
* OpenJazz is distributed under the terms of * OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0 * the GNU General Public License, version 2.0
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#define _ANIM_H #define _ANIM_H
#include "OpenJazz.h"
#include <SDL/SDL.h> #include <SDL/SDL.h>
...@@ -35,6 +37,8 @@ class Anim { ...@@ -35,6 +37,8 @@ class Anim {
private: private:
Sprite *sprites[19]; Sprite *sprites[19];
signed char shootX;
signed char shootY;
signed char xOffset; signed char xOffset;
signed char yOffset; signed char yOffset;
signed char xOffsets[19]; signed char xOffsets[19];
...@@ -46,15 +50,17 @@ class Anim { ...@@ -46,15 +50,17 @@ class Anim {
Anim (); Anim ();
~Anim (); ~Anim ();
void setData (int amount, signed char x, signed char y); void setData (int amount, signed char sX, signed char sY, signed char x, signed char y);
void setFrame (int nextFrame, bool looping); void setFrame (int nextFrame, bool looping);
void setFrameData (Sprite *frameSprite, signed char x, signed char y); void setFrameData (Sprite *frameSprite, signed char x, signed char y);
int getWidth (); int getWidth ();
int getHeight (); int getHeight ();
void draw (int x, int y); fixed getShootX ();
void setPalette (SDL_Color *palette, int start, int amount); fixed getShootY ();
void flashPalette (int index); void draw (fixed x, fixed y);
void restorePalette (); void setPalette (SDL_Color *palette, int start, int amount);
void flashPalette (int index);
void restorePalette ();
}; };
......
...@@ -82,6 +82,8 @@ Bullet::Bullet (Player *sourcePlayer, bool lower, unsigned int ticks) { ...@@ -82,6 +82,8 @@ Bullet::Bullet (Player *sourcePlayer, bool lower, unsigned int ticks) {
Bullet::Bullet (Event *sourceEvent, bool facing, unsigned int ticks) { Bullet::Bullet (Event *sourceEvent, bool facing, unsigned int ticks) {
Anim *anim;
// Properties based on the event // Properties based on the event
next = level->firstBullet; next = level->firstBullet;
...@@ -89,8 +91,9 @@ Bullet::Bullet (Event *sourceEvent, bool facing, unsigned int ticks) { ...@@ -89,8 +91,9 @@ Bullet::Bullet (Event *sourceEvent, bool facing, unsigned int ticks) {
type = sourceEvent->getProperty(E_BULLET); type = sourceEvent->getProperty(E_BULLET);
direction = facing? 1: 0; direction = facing? 1: 0;
x = sourceEvent->getX() + (sourceEvent->getWidth() >> 1); anim = level->getAnim(sourceEvent->getProperty(facing? E_LSHOOTANIM: E_RSHOOTANIM));
y = sourceEvent->getY() - (sourceEvent->getHeight() >> 1); x = sourceEvent->getX() + anim->getShootX();
y = sourceEvent->getY() + anim->getShootY();
dx = level->getBullet(type)[B_XSPEED + direction] * 500 * F1; dx = level->getBullet(type)[B_XSPEED + direction] * 500 * F1;
dy = level->getBullet(type)[B_YSPEED + direction] * 250 * F1; dy = level->getBullet(type)[B_YSPEED + direction] * 250 * F1;
time = ticks + T_BULLET; time = ticks + T_BULLET;
...@@ -193,7 +196,7 @@ bool Bullet::step (unsigned int ticks, int msps) { ...@@ -193,7 +196,7 @@ bool Bullet::step (unsigned int ticks, int msps) {
// If the time has expired, destroy the bullet // If the time has expired, destroy the bullet
if (ticks > time) { if (ticks > time) {
// If the bullet is TNT, destroy all destructible events nearby // If the bullet is TNT, hit all destructible events nearby twice
if (type == -1) { if (type == -1) {
event = level->firstEvent; event = level->firstEvent;
...@@ -201,8 +204,12 @@ bool Bullet::step (unsigned int ticks, int msps) { ...@@ -201,8 +204,12 @@ bool Bullet::step (unsigned int ticks, int msps) {
while (event) { while (event) {
// If the event is within range, hit it // If the event is within range, hit it
if (event->overlap(x - F160, y - F100, 2 * F160, 2 * F100)) if (event->overlap(x - F160, y - F100, 2 * F160, 2 * F100)) {
event->hit(source, true, ticks);
event->hit(source, ticks);
event->hit(source, ticks);
}
event = event->getNext(); event = event->getNext();
...@@ -245,7 +252,7 @@ bool Bullet::step (unsigned int ticks, int msps) { ...@@ -245,7 +252,7 @@ bool Bullet::step (unsigned int ticks, int msps) {
if (event->overlap(x, y, 0, 0)) { if (event->overlap(x, y, 0, 0)) {
// If the event is hittable, hit it and destroy the bullet // If the event is hittable, hit it and destroy the bullet
if (event->hit(source, false, ticks)) return true; if (event->hit(source, ticks)) return true;
} }
......
/*
*
* guardians.cpp
*
* 2nd March 2010: Created bridge.cpp from parts of event.cpp and eventframe.cpp
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Provides the functions of bridge events.
*
*/
#include "../level.h"
#include "event.h"
#include "player/player.h"
Bridge::Bridge (unsigned char gX, unsigned char gY, Event *nextEvent) {
x = TTOF(gX);
y = TTOF(gY + 1);
dx = 0;
dy = 0;
next = nextEvent;
gridX = gX;
gridY = gY;
flashTime = 0;
animType = E_LEFTANIM;
x -= F2;
y += ITOF(getProperty(E_YAXIS)) - F40;
// dx and dy used to store leftmost and rightmost player on bridge
// Start with minimum values
dx = getProperty(E_MULTIPURPOSE) * F8;
dy = 0;
return;
}
bool Bridge::step (unsigned int ticks, int msps) {
signed char *set;
int count;
fixed offset;
set = prepareStep(ticks, msps);
if (!set) return true;
// Gradually stop the bridge sagging
if (dx < set[E_MULTIPURPOSE] * F8) dx += 320 * msps;
if (dx > set[E_MULTIPURPOSE] * F8) dx = set[E_MULTIPURPOSE] * F8;
if (dy > 0) dy -= 320 * msps;
if (dy < 0) dy = 0;
for (count = 0; count < nPlayers; count++) {
offset = players[count].getX() + PXO_MID;
if (players[count].overlap(x, y, set[E_MULTIPURPOSE] * F8, F8) &&
!level->checkMaskDown(offset, y - F32)) {
// Player is on the bridge
players[count].setEvent(gridX, gridY);
offset -= x;
if (offset < dx) dx = offset;
if ((offset > dy) && (offset < set[E_MULTIPURPOSE] * F8)) dy = offset;
if (offset < set[E_MULTIPURPOSE] * F4)
players[count].setPosition(players[count].getX(), y + (offset >> 3) - F8);
else
players[count].setPosition(players[count].getX(), y + (set[E_MULTIPURPOSE] * F1) - (offset >> 3) - F8);
} else players[count].clearEvent(gridX, gridY);
}
return false;
}
void Bridge::draw (unsigned int ticks, int change) {
Anim *anim;
signed char *set;
int count;
fixed bridgeLength, dipA, dipB;
// Get the event properties
set = level->getEvent(gridX, gridY);
// If the event has been removed from the grid, do not show it
if (!set) return;
// Check if the event has anything to draw
if (!animType || (set[animType] < 0)) return;
if ((animType == E_LFINISHANIM) || (animType == E_RFINISHANIM))
frame = (ticks + T_FINISH - level->getEventTime(gridX, gridY)) / 40;
else if (set[E_ANIMSP])
frame = ticks / (set[E_ANIMSP] * 40);
else
frame = ticks / 20;
anim = level->getAnim(set[animType]);
anim->setFrame(frame + gridX + gridY, true);
// Draw the bridge
bridgeLength = set[E_MULTIPURPOSE] * F8;
if (dy >= dx) {
dipA = (dx <= (bridgeLength >> 1)) ? dx >> 3: (bridgeLength - dx) >> 3;
dipB = (dy <= (bridgeLength >> 1)) ? dy >> 3: (bridgeLength - dy) >> 3;
for (count = 0; count < bridgeLength; count += F8) {
if (count < dx)
anim->draw(x + count, y + (count * dipA / dx));
else if (count < dy)
anim->draw(x + count, y + dipA + ((count - dx) * (dipB - dipA) / (dy - dx)));
else
anim->draw(x + count, y + ((bridgeLength - count) * dipB / (bridgeLength - dy)));
}
} else {
// No players on the bridge, de-sagging in progress
dipA = (dx + dy) >> 1;
dipB = (dy < bridgeLength - dx) ? dy >> 3: (bridgeLength - dx) >> 3;
for (count = 0; count < bridgeLength; count += F8) {
if (count < dipA)
anim->draw(x + count, y + (count * dipB / dipA));
else
anim->draw(x + count, y + ((bridgeLength - count) * dipB / (bridgeLength - dipA)));
}
}
return;
}
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
* 19th March 2009: Created sprite.cpp from parts of event.cpp and player.cpp * 19th March 2009: Created sprite.cpp from parts of event.cpp and player.cpp
* 19th July 2009: Created eventframe.cpp from parts of events.cpp * 19th July 2009: Created eventframe.cpp from parts of events.cpp
* 19th July 2009: Renamed events.cpp to event.cpp * 19th July 2009: Renamed events.cpp to event.cpp
* 2nd March 2010: Created guardians.cpp from parts of event.cpp and eventframe.cpp
* 2nd March 2010: Created bridge.cpp from parts of event.cpp and eventframe.cpp
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -41,6 +43,13 @@ ...@@ -41,6 +43,13 @@
#include <math.h> #include <math.h>
Event::Event () {
return;
}
Event::Event (unsigned char gX, unsigned char gY, Event *nextEvent) { Event::Event (unsigned char gX, unsigned char gY, Event *nextEvent) {
x = TTOF(gX); x = TTOF(gX);
...@@ -53,8 +62,6 @@ Event::Event (unsigned char gX, unsigned char gY, Event *nextEvent) { ...@@ -53,8 +62,6 @@ Event::Event (unsigned char gX, unsigned char gY, Event *nextEvent) {
gridY = gY; gridY = gY;
flashTime = 0; flashTime = 0;
// Choose initial settings
switch (getProperty(E_BEHAVIOUR)) { switch (getProperty(E_BEHAVIOUR)) {
case 21: // Destructible block case 21: // Destructible block
...@@ -74,19 +81,6 @@ Event::Event (unsigned char gX, unsigned char gY, Event *nextEvent) { ...@@ -74,19 +81,6 @@ Event::Event (unsigned char gX, unsigned char gY, Event *nextEvent) {
break; break;
case 28:
animType = E_LEFTANIM;
x -= F2;
y += ITOF(getProperty(E_YAXIS)) - F40;
// dx and dy used to store leftmost and rightmost player on bridge
// Start with minimum values
dx = getProperty(E_MULTIPURPOSE) * F8;
dy = 0;
break;
default: default:
animType = E_LEFTANIM; animType = E_LEFTANIM;
...@@ -100,13 +94,6 @@ Event::Event (unsigned char gX, unsigned char gY, Event *nextEvent) { ...@@ -100,13 +94,6 @@ Event::Event (unsigned char gX, unsigned char gY, Event *nextEvent) {
} }
Event::~Event () {
return;
}
Event * Event::getNext () { Event * Event::getNext () {
return next; return next;
...@@ -145,7 +132,7 @@ void Event::destroy (unsigned int ticks) { ...@@ -145,7 +132,7 @@ void Event::destroy (unsigned int ticks) {
} }
bool Event::hit (Player *source, bool TNT, unsigned int ticks) { bool Event::hit (Player *source, unsigned int ticks) {
int hitsRemaining; int hitsRemaining;
...@@ -155,7 +142,7 @@ bool Event::hit (Player *source, bool TNT, unsigned int ticks) { ...@@ -155,7 +142,7 @@ bool Event::hit (Player *source, bool TNT, unsigned int ticks) {
if ((animType == E_LFINISHANIM) || (animType == E_RFINISHANIM) || if ((animType == E_LFINISHANIM) || (animType == E_RFINISHANIM) ||
(ticks < flashTime)) return false; (ticks < flashTime)) return false;
hitsRemaining = level->hitEvent(gridX, gridY, source, TNT); hitsRemaining = level->hitEvent(gridX, gridY, source);
// If the event cannot be hit, do not register hit // If the event cannot be hit, do not register hit
if (hitsRemaining < 0) return false; if (hitsRemaining < 0) return false;
...@@ -172,6 +159,17 @@ bool Event::hit (Player *source, bool TNT, unsigned int ticks) { ...@@ -172,6 +159,17 @@ bool Event::hit (Player *source, bool TNT, unsigned int ticks) {
} }
bool Event::isEnemy () {
signed char *set;
set = level->getEvent(gridX, gridY);
return set[E_HITSTOKILL] && (set[E_MODIFIER] == 0);
}
bool Event::isFrom (unsigned char gX, unsigned char gY) { bool Event::isFrom (unsigned char gX, unsigned char gY) {
return (gX == gridX) && (gY == gridY); return (gX == gridX) && (gY == gridY);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* 11th February 2009: Created bullet.h from parts of events.h * 11th February 2009: Created bullet.h from parts of events.h
* 1st March 2009: Created bird.h from parts of events.h * 1st March 2009: Created bird.h from parts of events.h
* 19th July 2009: Renamed events.h to event.h * 19th July 2009: Renamed events.h to event.h
* 2nd March 2010: Created guardians.h from parts of event.h
* *
* Part of the OpenJazz project * Part of the OpenJazz project
* *
...@@ -23,8 +24,8 @@ ...@@ -23,8 +24,8 @@
*/ */
#ifndef _EVENTS_H #ifndef _EVENT_H
#define _EVENTS_H #define _EVENT_H
#include "movable.h" #include "movable.h"
...@@ -68,8 +69,8 @@ ...@@ -68,8 +69,8 @@
#define T_SHOOT 300 #define T_SHOOT 300
// Speed factors // Speed factors
#define ES_SLOW 80 #define ES_SLOW ITOF(80)
#define ES_FAST 240 #define ES_FAST ITOF(240)
// Classes // Classes
...@@ -78,31 +79,42 @@ class Player; ...@@ -78,31 +79,42 @@ class Player;
class Event : public Movable { class Event : public Movable {
private: protected:
Event *next; Event *next;
unsigned char gridX, gridY; // Grid position of the event unsigned char gridX, gridY; // Grid position of the event
unsigned char animType; // E_LEFTANIM, etc, or 0 unsigned char animType; // E_LEFTANIM, etc, or 0
unsigned char frame; unsigned char frame;
unsigned int flashTime; unsigned int flashTime;
void destroy (unsigned int ticks); Event ();
void destroy (unsigned int ticks);
fixed getWidth ();
fixed getHeight ();
signed char * prepareStep (unsigned int ticks, int msps);
public: public:
Event (unsigned char gX, unsigned char gY, Event (unsigned char gX, unsigned char gY, Event *nextEvent);
Event *nextEvent);
~Event (); Event * getNext ();
void removeNext ();
Event * getNext (); bool hit (Player *source, unsigned int ticks);
void removeNext (); bool isEnemy ();
bool hit (Player *source, bool TNT, unsigned int ticks); bool isFrom (unsigned char gX, unsigned char gY);
bool isFrom (unsigned char gX, unsigned char gY); virtual bool overlap (fixed left, fixed top, fixed width, fixed height);
fixed getWidth (); signed char getProperty (unsigned char property);
fixed getHeight (); virtual bool step (unsigned int ticks, int msps);
bool overlap (fixed left, fixed top, fixed width, virtual void draw (unsigned int ticks, int change);
fixed height);
signed char getProperty (unsigned char property); };
bool step (unsigned int ticks, int msps);
void draw (unsigned int ticks, int change); class Bridge : public Event {
public:
Bridge (unsigned char gX, unsigned char gY, Event *nextEvent);
bool step (unsigned int ticks, int msps);
void draw (unsigned int ticks, int change);
}; };
......
This diff is collapsed.
/*
*
* guardians.cpp
*
* 2nd March 2010: Created guardians.cpp from parts of event.cpp and eventframe.cpp
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Provides the functions of guardian events.
*
*/
#include "../level.h"
#include "guardians.h"
#include "io/gfx/video.h"
#include "player/player.h"
DeckGuardian::DeckGuardian (unsigned char gX, unsigned char gY, Event *nextEvent) {
x = TTOF(gX);
y = TTOF(gY + 1);
dx = 0;
dy = 0;
next = nextEvent;
gridX = gX;
gridY = gY;
flashTime = 0;
stage = 0;
return;
}
bool DeckGuardian::overlap (fixed left, fixed top, fixed width, fixed height) {
if (stage == 0)
return (x + F8 - F64 >= left) && (x - F64 < left + width) &&
(y + F64 >= top) && (y + F32 < top + height);
if (stage == 1)
return (x + F32 >= left) && (x + F32 - F8 < left + width) &&
(y + F64 >= top) && (y + F32 < top + height);
if (stage == 2)
return (x + F64 - F16 >= left) && (x + F32 - F8 < left + width) &&
(y + F64 >= top) && (y + F32 < top + height);
return false;
}
bool DeckGuardian::step (unsigned int ticks, int msps) {
signed char *set;
int count;
set = prepareStep(ticks, msps);
if (!set) return true;
// Handle behaviour
count = level->getEventHits(gridX, gridY);
if (count < 8) stage = 0;
else if (count < 16) stage = 1;
else if (count < 24) stage = 2;
else stage = 3;
// If the event has been destroyed, play its finishing animation and set its
// reaction time
if (set[E_HITSTOKILL] &&
(level->getEventHits(gridX, gridY) >= set[E_HITSTOKILL]) &&
(animType != E_LFINISHANIM) && (animType != E_RFINISHANIM)) {
destroy(ticks);
}
// If the reaction time has expired
if (level->getEventTime(gridX, gridY) &&
(ticks > level->getEventTime(gridX, gridY))) {
if ((animType == E_LFINISHANIM) || (animType == E_RFINISHANIM)) {
// The event has been destroyed, so remove it
level->clearEvent(gridX, gridY);
return true;
} else {
level->setEventTime(gridX, gridY, 0);
}
}
if (level->getStage() == LS_END) return false;
return false;
}
void DeckGuardian::draw (unsigned int ticks, int change) {
Anim *anim;
signed char *set;
int count;
// Get the event properties
set = level->getEvent(gridX, gridY);
// If the event has been removed from the grid, do not show it
if (!set) return;
// Draw the boss
if (stage < 3) {
// Draw unit
anim = level->getAnim(29 + stage);
if (ticks < flashTime) anim->flashPalette(0);
if (stage == 0) anim->draw(x - F64, y + F32);
else if (stage == 1) anim->draw(x + F32 - F8 - F4, y + F32);
else anim->draw(x + F8 - F64, y + F32);
if (ticks < flashTime) anim->restorePalette();
}
if (set[E_HITSTOKILL]) {
// Draw boss energy bar
count = level->getEventHits(gridX, gridY) * 100 / set[E_HITSTOKILL];
// Devan head
anim = level->getMiscAnim(1);
anim->setFrame(0, true);
if (ticks < flashTime) anim->flashPalette(0);
anim->draw(viewX + ITOF(viewW - 44), viewY + ITOF(count + 48));
if (ticks < flashTime) anim->restorePalette();
// Bar
drawRect(viewW - 40, count + 40, 12, 100 - count,
(ticks < flashTime)? 0: 32);
}
return;
}
/*
*
* guardians.h
*
* 2nd March 2010: Created guardians.h from parts of event.h
*
* Part of the OpenJazz project
*
*
* Copyright (c) 2005-2010 Alister Thomson
*
* OpenJazz is distributed under the terms of
* the GNU General Public License, version 2.0
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef _GUARDIANS_H
#define _GUARDIANS_H
#include "event.h"
// Class
class DeckGuardian : public Event {
private:
int stage;
public:
DeckGuardian (unsigned char gX, unsigned char gY, Event *nextEvent);
bool overlap (fixed left, fixed top, fixed width, fixed height);
bool step (unsigned int ticks, int msps);
void draw (unsigned int ticks, int change);
};
#endif
...@@ -272,7 +272,7 @@ void Level::clearEvent (unsigned char gridX, unsigned char gridY) { ...@@ -272,7 +272,7 @@ void Level::clearEvent (unsigned char gridX, unsigned char gridY) {
} }
int Level::hitEvent (unsigned char gridX, unsigned char gridY, Player *source, bool TNT) { int Level::hitEvent (unsigned char gridX, unsigned char gridY, Player *source) {
GridElement *ge; GridElement *ge;
unsigned char buffer[MTL_L_GRID]; unsigned char buffer[MTL_L_GRID];
...@@ -286,15 +286,14 @@ int Level::hitEvent (unsigned char gridX, unsigned char gridY, Player *source, b ...@@ -286,15 +286,14 @@ int Level::hitEvent (unsigned char gridX, unsigned char gridY, Player *source, b
if (!hitsToKill) return -1; if (!hitsToKill) return -1;
// Increase the hit count // Increase the hit count
if (TNT) ge->hits = hitsToKill; ge->hits++;
else ge->hits++;
// Check if the event has been killed // Check if the event has been killed
if (ge->hits == hitsToKill) { if (ge->hits == hitsToKill) {
// Notify the player that shot the bullet // Notify the player that shot the bullet
// If this returns false, ignore the hit // If this returns false, ignore the hit
if (!source->shootEvent(gridX, gridY, ticks)) { if (!source->takeEvent(gridX, gridY, ticks)) {
ge->hits--; ge->hits--;
......
...@@ -155,7 +155,7 @@ class Level { ...@@ -155,7 +155,7 @@ class Level {
unsigned char getEventHits (unsigned char gridX, unsigned char gridY); unsigned char getEventHits (unsigned char gridX, unsigned char gridY);
unsigned int getEventTime (unsigned char gridX, unsigned char gridY); unsigned int getEventTime (unsigned char gridX, unsigned char gridY);
void clearEvent (unsigned char gridX, unsigned char gridY); void clearEvent (unsigned char gridX, unsigned char gridY);
int hitEvent (unsigned char gridX, unsigned char gridY, Player *source, bool TNT); int hitEvent (unsigned char gridX, unsigned char gridY, Player *source);
void setEventTime (unsigned char gridX, unsigned char gridY, unsigned int time); void setEventTime (unsigned char gridX, unsigned char gridY, unsigned int time);
signed char * getBullet (unsigned char bullet); signed char * getBullet (unsigned char bullet);
Sprite * getSprite (unsigned char sprite); Sprite * getSprite (unsigned char sprite);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "bullet.h" #include "bullet.h"
#include "event/event.h" #include "event/event.h"
#include "event/guardians.h"
#include "level.h" #include "level.h"
#include "game/game.h" #include "game/game.h"
...@@ -70,7 +71,31 @@ int Level::step () { ...@@ -70,7 +71,31 @@ int Level::step () {
} }
// If the event wasn't found, create it // If the event wasn't found, create it
if (!nextEvent) firstEvent = new Event(x, y, firstEvent); if (!nextEvent) {
switch (getEvent(x, y)[E_BEHAVIOUR]) {
case 28:
firstEvent = new Bridge(x, y, firstEvent);
break;
case 60:
firstEvent = new DeckGuardian(x, y, firstEvent);
break;
default:
firstEvent = new Event(x, y, firstEvent);
break;
}
}
} }
......
...@@ -706,15 +706,19 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -706,15 +706,19 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) {
for (y = 0; y < LH; y++) { for (y = 0; y < LH; y++) {
// Eliminate event references for events of too high a difficulty type = grid[y][x].event;
if (eventSet[grid[y][x].event][E_DIFFICULTY] > difficulty)
grid[y][x].event = 0;
// If the event hurts and can be killed, it is an enemy if (type) {
// Anything else that scores is an item
if ((eventSet[grid[y][x].event][E_MODIFIER] == 0) && // Eliminate event references for events of too high a difficulty
eventSet[grid[y][x].event][E_HITSTOKILL]) enemies++; if (eventSet[type][E_DIFFICULTY] > difficulty) grid[y][x].event = 0;
else if (eventSet[grid[y][x].event][E_ADDEDSCORE]) items++;
// If the event hurts and can be killed, it is an enemy
// Anything else that scores is an item
if ((eventSet[type][E_MODIFIER] == 0) && eventSet[type][E_HITSTOKILL]) enemies++;
else if (eventSet[type][E_ADDEDSCORE]) items++;
}
} }
...@@ -727,24 +731,25 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) { ...@@ -727,24 +731,25 @@ int Level::load (char *fileName, unsigned char diff, bool checkpoint) {
// Load animation set // Load animation set
buffer = file->loadRLE(ANIMS * 64); buffer = file->loadRLE(ANIMS << 6);
// Create animation set based on that data // Create animation set based on that data
for (count = 0; count < ANIMS; count++) { for (count = 0; count < ANIMS; count++) {
animSet[count].setData(buffer[(count * 64) + 6], animSet[count].setData(buffer[(count << 6) + 6],
buffer[(count * 64) + 4], buffer[(count * 64) + 5]); buffer[count << 6], buffer[(count << 6) + 1],
buffer[(count << 6) + 4], buffer[(count << 6) + 5]);
for (y = 0; y < buffer[(count * 64) + 6]; y++) { for (y = 0; y < buffer[(count << 6) + 6]; y++) {
// Get frame // Get frame
x = buffer[(count * 64) + 7 + y]; x = buffer[(count << 6) + 7 + y];
if (x > sprites) x = sprites; if (x > sprites) x = sprites;
// Assign sprite and vertical offset // Assign sprite and vertical offset
animSet[count].setFrame(y, true); animSet[count].setFrame(y, true);
animSet[count].setFrameData(spriteSet + x, animSet[count].setFrameData(spriteSet + x,
buffer[(count * 64) + 26 + y], buffer[(count * 64) + 45 + y]); buffer[(count << 6) + 26 + y], buffer[(count << 6) + 45 + y]);
} }
......
...@@ -81,7 +81,6 @@ void Bird::hit () { ...@@ -81,7 +81,6 @@ void Bird::hit () {
bool Bird::step (unsigned int ticks, int msps) { bool Bird::step (unsigned int ticks, int msps) {
Event *nextEvent; Event *nextEvent;
fixed eventX, eventY;
bool target; bool target;
if (fleeing) { if (fleeing) {
...@@ -161,20 +160,9 @@ bool Bird::step (unsigned int ticks, int msps) { ...@@ -161,20 +160,9 @@ bool Bird::step (unsigned int ticks, int msps) {
if (player->getFacing()) { if (player->getFacing()) {
while (nextEvent) { while (nextEvent && !target) {
eventX = nextEvent->getX(); target = nextEvent->isEnemy() && nextEvent->overlap(x, y, F160, F100);
eventY = nextEvent->getY() - nextEvent->getHeight();
if (nextEvent->getProperty(E_HITSTOKILL) &&
(eventX > x) && (eventX < x + F160) && (eventY > y) &&
(eventY < y + F100)) {
target = true;
break;
}
nextEvent = nextEvent->getNext(); nextEvent = nextEvent->getNext();
...@@ -182,20 +170,9 @@ bool Bird::step (unsigned int ticks, int msps) { ...@@ -182,20 +170,9 @@ bool Bird::step (unsigned int ticks, int msps) {
} else { } else {
while (nextEvent) { while (nextEvent && !target) {
eventX = nextEvent->getX();
eventY = nextEvent->getY() - nextEvent->getHeight();
if (nextEvent->getProperty(E_HITSTOKILL) &&
(eventX > x - F160) && (eventX < x) && (eventY > y) &&
(eventY < y + F100)) {
target = true;
break;
} target = nextEvent->isEnemy() && nextEvent->overlap(x - F160, y, F160, F100);
nextEvent = nextEvent->getNext(); nextEvent = nextEvent->getNext();
......
...@@ -65,8 +65,7 @@ Player::~Player () { ...@@ -65,8 +65,7 @@ Player::~Player () {
} }
void Player::init (char *playerName, unsigned char *playerCols, void Player::init (char *playerName, unsigned char *playerCols, unsigned char newTeam) {
unsigned char newTeam) {
int offsets[15] = {PC_WHITE, PC_SGREEN, PC_BLUE, PC_RED, PC_LGREEN, int offsets[15] = {PC_WHITE, PC_SGREEN, PC_BLUE, PC_RED, PC_LGREEN,
PC_LEVEL1, PC_YELLOW, PC_LEVEL2, PC_ORANGE, PC_LEVEL3, PC_LEVEL4, PC_LEVEL1, PC_YELLOW, PC_LEVEL2, PC_ORANGE, PC_LEVEL3, PC_LEVEL4,
...@@ -205,7 +204,7 @@ void Player::reset () { ...@@ -205,7 +204,7 @@ void Player::reset () {
if (bird) bird->reset(); if (bird) bird->reset();
event = NULL; event = 0;
for (count = 0; count < PCONTROLS; count++) pcontrols[count] = false; for (count = 0; count < PCONTROLS; count++) pcontrols[count] = false;
...@@ -237,15 +236,12 @@ void Player::setControl (int control, bool state) { ...@@ -237,15 +236,12 @@ void Player::setControl (int control, bool state) {
} }
bool Player::shootEvent (unsigned char gridX, unsigned char gridY, bool Player::takeEvent (unsigned char gridX, unsigned char gridY, unsigned int ticks) {
unsigned int ticks) {
signed char *set; signed char *set;
set = level->getEvent(gridX, gridY); set = level->getEvent(gridX, gridY);
addScore(set[E_ADDEDSCORE]);
switch (set[E_MODIFIER]) { switch (set[E_MODIFIER]) {
case 41: // Bonus level case 41: // Bonus level
...@@ -257,17 +253,57 @@ bool Player::shootEvent (unsigned char gridX, unsigned char gridY, ...@@ -257,17 +253,57 @@ bool Player::shootEvent (unsigned char gridX, unsigned char gridY,
case 8: // Boss case 8: // Boss
case 27: // End of level case 27: // End of level
if (getEnergy()) { if (!getEnergy()) return false;
if (!gameMode) { if (!gameMode) {
if (game) game->setCheckpoint(gridX, gridY); if (game) game->setCheckpoint(gridX, gridY);
level->setStage(LS_END); level->setStage(LS_END);
} else return gameMode->endOfLevel(this, gridX, gridY); } else if (!(gameMode->endOfLevel(this, gridX, gridY))) return false;
} break;
case 0: // Enemy
break;
case 1: // Invincibility
if (!getEnergy()) return false;
reaction = PR_INVINCIBLE;
reactionTime = ticks + PRT_INVINCIBLE;
break;
case 2:
case 3: // Health
if (energy < 4) energy++;
break;
case 4: // Extra life
if (lives < 99) lives++;
break;
case 5: // High-jump feet
jumpHeight += F16;
break;
case 7: // Used with destructible blocks
break;
case 9: // Sand timer
level->addTimer();
break; break;
...@@ -277,131 +313,139 @@ bool Player::shootEvent (unsigned char gridX, unsigned char gridY, ...@@ -277,131 +313,139 @@ bool Player::shootEvent (unsigned char gridX, unsigned char gridY,
break; break;
case 15: case 11: // Item
break;
case 12: // Rapid fire
fireSpeed++;
break;
case 15: // Ammo
addAmmo(0, 15); addAmmo(0, 15);
break; break;
case 16: case 16: // Ammo
addAmmo(1, 15); addAmmo(1, 15);
break; break;
case 17: case 17: // Ammo
addAmmo(2, 15); addAmmo(2, 15);
break; break;
case 26: case 18: // Ammo
fastFeetTime = ticks + T_FASTFEET; addAmmo(0, 2);
break; break;
case 33: case 19: // Ammo
if (shield < 2) shield = 2; addAmmo(1, 2);
break; break;
case 34: // Bird case 20: // Ammo
if (!bird) bird = new Bird(this, gridX, gridY); addAmmo(2, 2);
break; break;
case 36: case 26: // Fast feet box
shield = 6; fastFeetTime = ticks + T_FASTFEET;
break; break;
} case 30: // TNT
// Add to player's enemy/item tally addAmmo(3, 1);
// If the event hurts and can be killed, it is an enemy
// Anything else that scores is an item
if ((set[E_MODIFIER] == 0) && set[E_HITSTOKILL]) enemies++;
else if (set[E_ADDEDSCORE]) items++;
return true; break;
} case 31: // Water level
level->setWaterLevel(gridY);
bool Player::touchEvent (unsigned char gridX, unsigned char gridY, break;
unsigned int ticks) {
signed char *set; case 33: // 2-hit shield
set = level->getEvent(gridX, gridY); if (shield < 2) shield = 2;
switch (set[E_MODIFIER]) { break;
case 0: // Hurt case 34: // Bird
case 8: // Boss
if ((set[E_BEHAVIOUR] < 37) || (set[E_BEHAVIOUR] > 44)) if (!bird) bird = new Bird(this, gridX, gridY);
hit(NULL, ticks);
break; break;
case 1: // Invincibility case 35: // Airboard, etc.
if (getEnergy()) { floating = true;
reaction = PR_INVINCIBLE; break;
reactionTime = ticks + PRT_INVINCIBLE;
addScore(set[E_ADDEDSCORE]);
return true; case 36: // 4-hit shield
} shield = 6;
break; break;
case 2: case 37: // Diamond
case 3: // Health
if (energy < 4) energy++; // Yellow flash
addScore(set[E_ADDEDSCORE]); firstPE = new FlashPaletteEffect(255, 255, 0, 320, firstPE);
return true; break;
case 4: // Extra life default:
if (lives < 99) lives++; return false;
addScore(set[E_ADDEDSCORE]);
return true; }
case 5: // High-jump feet addScore(set[E_ADDEDSCORE]);
jumpHeight += F16; // Add to player's enemy/item tally
// If the event hurts and can be killed, it is an enemy
// Anything else that scores is an item
if ((set[E_MODIFIER] == 0) && set[E_HITSTOKILL]) enemies++;
else if (set[E_ADDEDSCORE]) items++;
return true; return true;
case 9: // Sand timer }
level->addTimer();
addScore(set[E_ADDEDSCORE]);
return true; bool Player::touchEvent (unsigned char gridX, unsigned char gridY, unsigned int ticks, int msps) {
case 11: // Item signed char *set;
addScore(set[E_ADDEDSCORE]); set = level->getEvent(gridX, gridY);
return true; switch (set[E_MODIFIER]) {
case 12: // Rapid fire case 0: // Hurt
case 8: // Boss
fireSpeed++; if ((set[E_BEHAVIOUR] < 37) || (set[E_BEHAVIOUR] > 44))
hit(NULL, ticks);
break;
return true; case 7: // Used with destructible blocks, but should not destroy on contact
break;
case 13: // Warp case 13: // Warp
...@@ -419,60 +463,42 @@ bool Player::touchEvent (unsigned char gridX, unsigned char gridY, ...@@ -419,60 +463,42 @@ bool Player::touchEvent (unsigned char gridX, unsigned char gridY,
break; break;
case 18: // Ammo case 28: // Belt
addAmmo(0, 2);
addScore(set[E_ADDEDSCORE]);
return true;
case 19: // Ammo
addAmmo(1, 2);
addScore(set[E_ADDEDSCORE]);
return true;
case 20: // Ammo x += set[E_MAGNITUDE] * 4 * msps;
addAmmo(2, 2);
addScore(set[E_ADDEDSCORE]);
return true; break;
case 29: // Upwards spring case 29: // Upwards spring
setEvent(set); setEvent(gridX, gridY);
level->playSound(set[E_SOUND]); level->playSound(set[E_SOUND]);
break; break;
case 30: // TNT
addAmmo(3, 1);
return true;
case 31: // Water level case 31: // Water level
if (!set[E_HITSTOKILL]) level->setWaterLevel(gridY); level->setWaterLevel(gridY);
break; break;
case 35: // Airboard, etc. case 32: // Float up / sideways
floating = true; if (set[E_YAXIS]) {
addScore(set[E_ADDEDSCORE]);
return true; eventX = gridX;
eventY = gridY;
event = 2;
case 37: // Diamond if (dy > set[E_MULTIPURPOSE] * -F20)
dy -= set[E_MULTIPURPOSE] * 320 * msps;
// Yellow flash jumpY = y - (8 * F16);
firstPE = new FlashPaletteEffect(255, 255, 0, 320, firstPE);
return true; } else x += set[E_MAGNITUDE] * 20 * msps;
break;
case 38: // Airboard, etc. off case 38: // Airboard, etc. off
...@@ -480,6 +506,12 @@ bool Player::touchEvent (unsigned char gridX, unsigned char gridY, ...@@ -480,6 +506,12 @@ bool Player::touchEvent (unsigned char gridX, unsigned char gridY,
break; break;
default:
if (!set[E_HITSTOKILL]) return takeEvent(gridX, gridY, ticks);
break;
} }
return false; return false;
...@@ -619,8 +651,24 @@ int Player::getItems () { ...@@ -619,8 +651,24 @@ int Player::getItems () {
bool Player::overlap (fixed left, fixed top, fixed width, fixed height) { bool Player::overlap (fixed left, fixed top, fixed width, fixed height) {
return (x + PXO_R >= left) && (x + PXO_L < left + width) && (y >= top) && return (x + PXO_R >= left) && (x + PXO_L < left + width) &&
(y + PYO_TOP < top + height); (y >= top) && (y + PYO_TOP < top + height);
}
bool Player::isOnPlatform () {
// Check for platform event, bridge or level mask below player
return
(event >= 3) ||
level->checkMaskDown(x + PXO_ML, y + F2) ||
level->checkMaskDown(x + PXO_MID, y + F2) ||
level->checkMaskDown(x + PXO_MR, y + F2) ||
level->checkMaskDown(x + PXO_ML, y + F8) ||
level->checkMaskDown(x + PXO_MID, y + F8) ||
level->checkMaskDown(x + PXO_MR, y + F8);
} }
...@@ -659,49 +707,35 @@ unsigned char Player::getTeam () { ...@@ -659,49 +707,35 @@ unsigned char Player::getTeam () {
} }
void Player::floatUp (signed char *newEvent, int speed) { void Player::setEvent (unsigned char gridX, unsigned char gridY) {
event = newEvent;
if ((dy > 0) && level->checkMaskDown(x + PXO_MID, y + F4))
dy = event[E_MULTIPURPOSE] * -F40;
if (dy > event[E_MULTIPURPOSE] * -F40)
dy -= event[E_MULTIPURPOSE] * 320 * speed;
jumpY = y - (8 * F16);
return;
}
void Player::belt (int speed) {
dx += speed * 20; signed char *set;
return;
} set = level->getEvent(gridX, gridY);
if (set[E_MODIFIER] == 29) {
void Player::setEvent (signed char *newEvent) { // Upwards spring
jumpY = y + (set[E_MAGNITUDE] * (F20 + F1));
event = 1;
event = newEvent; } else if (set[E_MODIFIER] == 6) event = 3;
else if (set[E_BEHAVIOUR] == 28) event = 4;
else return;
if (event[E_MODIFIER] == 29) // Upwards spring eventX = gridX;
jumpY = y + (event[E_MAGNITUDE] * (F20 + F1)); eventY = gridY;
return; return;
} }
void Player::clearEvent (signed char *newEvent, unsigned char property) { void Player::clearEvent (unsigned char gridX, unsigned char gridY) {
// If the given property matches, clear the event // If the location matches, clear the event
if (event && (event[property] == newEvent[property])) event = NULL; if ((gridX == eventX) && (gridY == eventY)) event = 0;
return; return;
......
...@@ -160,24 +160,22 @@ class Player : public Movable { ...@@ -160,24 +160,22 @@ class Player : public Movable {
private: private:
Bird *bird; Bird *bird;
char *name; char *name;
signed char *event; /* A member of the event set (spring, float up,
belt, platform) */
char anims[PANIMS]; char anims[PANIMS];
bool pcontrols[PCONTROLS]; bool pcontrols[PCONTROLS];
SDL_Color palette[256]; SDL_Color palette[256];
unsigned char cols[4]; unsigned char cols[4];
int ammo[4]; int ammo[4];
int ammoType; /* -1 = blaster, 0 = toaster, 1 = missiles, int ammoType; /* -1 = blaster, 0 = toaster, 1 = missiles, 2 = bouncer 3 = TNT */
2 = bouncer 3 = TNT */
int score; int score;
int energy; int energy;
int lives; int lives;
int shield; /* 0 = none, 1 = 1 yellow, 2 = 2 yellow, int shield; /* 0 = none, 1 = 1 yellow, 2 = 2 yellow, 3 = 1 orange, 4 = 2 orange, 5 = 3 orange, 6 = 4 orange */
3 = 1 orange, 4 = 2 orange, 5 = 3 orange, 6 = 4 orange */ bool floating; /* false = normal, true = boarding/bird/etc. */
bool floating; // false = normal, true = boarding/bird/etc.
bool facing; bool facing;
int lookTime; /* Negative if looking up, positive if looking unsigned char eventX;
down, 0 if neither */ unsigned char eventY; /* Position of an event (spring, platform, bridge) */
int event; /* 0 = none, 1 = spring, 2 = float up, 3 = platform, 4 = bridge */
int lookTime; /* Negative if looking up, positive if looking down, 0 if neither */
int reaction; int reaction;
unsigned int reactionTime; unsigned int reactionTime;
int fireSpeed; int fireSpeed;
...@@ -190,7 +188,8 @@ class Player : public Movable { ...@@ -190,7 +188,8 @@ class Player : public Movable {
int enemies, items; int enemies, items;
unsigned char team; unsigned char team;
void addAmmo (int type, int amount); void addAmmo (int type, int amount);
bool isOnPlatform ();
public: public:
int teamScore; int teamScore;
...@@ -198,18 +197,17 @@ class Player : public Movable { ...@@ -198,18 +197,17 @@ class Player : public Movable {
Player (); Player ();
~Player (); ~Player ();
void init (char *playerName, unsigned char *cols, void init (char *playerName, unsigned char *cols, unsigned char newTeam);
unsigned char newTeam);
void deinit (); void deinit ();
void setAnims (char *newAnims); void setAnims (char *newAnims);
char * getName (); char * getName ();
unsigned char * getCols (); unsigned char * getCols ();
void reset (); void reset ();
void setControl (int control, bool state); void setControl (int control, bool state);
bool shootEvent (unsigned char gridX, unsigned char gridY, bool takeEvent (unsigned char gridX, unsigned char gridY, unsigned int ticks);
unsigned int ticks); bool touchEvent (unsigned char gridX, unsigned char gridY, unsigned int ticks, int msps);
bool touchEvent (unsigned char gridX, unsigned char gridY, void setEvent (unsigned char gridX, unsigned char gridY);
unsigned int ticks); void clearEvent (unsigned char gridX, unsigned char gridY);
bool hit (Player *source, unsigned int ticks); bool hit (Player *source, unsigned int ticks);
void kill (Player *source, unsigned int ticks); void kill (Player *source, unsigned int ticks);
void addScore (int addedScore); void addScore (int addedScore);
...@@ -219,17 +217,11 @@ class Player : public Movable { ...@@ -219,17 +217,11 @@ class Player : public Movable {
int getAmmo (bool amount); int getAmmo (bool amount);
int getEnemies (); int getEnemies ();
int getItems (); int getItems ();
bool overlap (fixed left, fixed top, fixed width, bool overlap (fixed left, fixed top, fixed width, fixed height);
fixed height);
void setPosition (fixed newX, fixed newY); void setPosition (fixed newX, fixed newY);
void setSpeed (fixed newDx, fixed newDy); void setSpeed (fixed newDx, fixed newDy);
bool getFacing (); bool getFacing ();
unsigned char getTeam (); unsigned char getTeam ();
void floatUp (signed char *newEvent, int speed);
void belt (int speed);
void setEvent (signed char *newEvent);
void clearEvent (signed char *newEvent,
unsigned char property);
void send (unsigned char *data); void send (unsigned char *data);
void receive (unsigned char *buffer); void receive (unsigned char *buffer);
void control (unsigned int ticks, int msps); void control (unsigned int ticks, int msps);
......
...@@ -42,6 +42,9 @@ ...@@ -42,6 +42,9 @@
void Player::control (unsigned int ticks, int msps) { void Player::control (unsigned int ticks, int msps) {
int speed;
bool platform;
// Respond to controls, unless the player has been killed // Respond to controls, unless the player has been killed
// If the player has been killed, drop but otherwise do not move // If the player has been killed, drop but otherwise do not move
...@@ -145,8 +148,8 @@ void Player::control (unsigned int ticks, int msps) { ...@@ -145,8 +148,8 @@ void Player::control (unsigned int ticks, int msps) {
if (event) { if (event) {
if (event[E_MODIFIER] == 29) dy = event[E_MULTIPURPOSE] * -F20; if (event == 1) dy = level->getEvent(eventX, eventY)[E_MULTIPURPOSE] * -F20;
else if (event[E_BEHAVIOUR] == 25) dy = PYS_JUMP; else if (event == 2) dy = PYS_JUMP;
} }
...@@ -172,7 +175,7 @@ void Player::control (unsigned int ticks, int msps) { ...@@ -172,7 +175,7 @@ void Player::control (unsigned int ticks, int msps) {
if (dx < 0) jumpY += dx >> 4; if (dx < 0) jumpY += dx >> 4;
else if (dx > 0) jumpY -= dx >> 4; else if (dx > 0) jumpY -= dx >> 4;
event = NULL; event = 0;
} }
...@@ -198,71 +201,50 @@ void Player::control (unsigned int ticks, int msps) { ...@@ -198,71 +201,50 @@ void Player::control (unsigned int ticks, int msps) {
} else { } else {
if ((event && ((event[E_MODIFIER] == 6) || platform = isOnPlatform();
(event[E_BEHAVIOUR] == 28))) ||
level->checkMaskDown(x + PXO_ML, y + F2) ||
level->checkMaskDown(x + PXO_MID, y + F2) ||
level->checkMaskDown(x + PXO_MR, y + F2)) {
// Mask/platform/bridge below player
if (pcontrols[C_JUMP] && !level->checkMask(x + PXO_MID, y - F36)) {
// Jump
jumpY = y - jumpHeight;
// Increase jump height if walking/running if (platform && pcontrols[C_JUMP] &&
if (dx < 0) jumpY += dx >> 3; !level->checkMask(x + PXO_MID, y - F36)) {
else if (dx > 0) jumpY -= dx >> 3;
event = NULL; // Jump
playSound(S_JUMPA); jumpY = y - jumpHeight;
} // Increase jump height if walking/running
if (dx < 0) jumpY += dx >> 3;
if (!lookTime) { else if (dx > 0) jumpY -= dx >> 3;
// If requested, look up or down
if (pcontrols[C_UP]) lookTime = -ticks;
else if (pcontrols[C_DOWN]) lookTime = ticks;
}
} else { event = 0;
// No mask/platform/bridge below player playSound(S_JUMPA);
// Cannot look up or down
lookTime = 0;
} }
// Stop jumping // Stop jumping
if (!pcontrols[C_JUMP] && if (!pcontrols[C_JUMP] && (event != 1) && (event != 2))
(!event || ((event[E_MODIFIER] != 29) && jumpY = TTOF(LH);
(event[E_BEHAVIOUR] != 25)))) jumpY = TTOF(LH);
// If jumping, rise
if (y >= jumpY) { if (y >= jumpY) {
// If jumping, rise
dy = (jumpY - y - F64) * 4; dy = (jumpY - y - F64) * 4;
// Spring speed limit // Spring/float up speed limit
if (event && (event[E_MODIFIER] == 29)) { if ((event == 1) || (event == 2)) {
speed = level->getEvent(eventX, eventY)[E_MULTIPURPOSE] * -F20;
if ((event[E_MULTIPURPOSE] == 0) && (dy < PYS_JUMP)) if (speed == 0) speed = PYS_JUMP;
dy = PYS_JUMP;
if ((event[E_MULTIPURPOSE] > 0) && (dy < event[E_MULTIPURPOSE] * -F20)) if (dy < speed) dy = speed;
dy = event[E_MULTIPURPOSE] * -F20;
} }
// Avoid jumping too fast, unless caused by an event // Avoid jumping too fast, unless caused by an event
if (!event && (dy < PYS_JUMP)) dy = PYS_JUMP; if (!event && (dy < PYS_JUMP)) dy = PYS_JUMP;
} else { } else if (!platform) {
// Fall under gravity // Fall under gravity
dy += PYA_GRAVITY * msps; dy += PYA_GRAVITY * msps;
...@@ -270,22 +252,29 @@ void Player::control (unsigned int ticks, int msps) { ...@@ -270,22 +252,29 @@ void Player::control (unsigned int ticks, int msps) {
} }
// Stop looking if (platform && !lookTime) {
if (!pcontrols[C_UP] && (lookTime < 0)) lookTime = 0;
if (!pcontrols[C_DOWN] && (lookTime > 0)) lookTime = 0; // If requested, look up or down
if (pcontrols[C_UP]) lookTime = -ticks;
else if (pcontrols[C_DOWN]) lookTime = ticks;
}
// Stop looking if there is no platform or the control has been released
if (!platform ||
(!pcontrols[C_UP] && (lookTime < 0)) ||
(!pcontrols[C_DOWN] && (lookTime > 0))) lookTime = 0;
} }
// If there is an obstacle above and the player is not floating up, stop // If there is an obstacle above and the player is not floating up, stop
// rising // rising
if (level->checkMask(x + PXO_MID, y + PYO_TOP - F4) && (jumpY < y) && if (level->checkMask(x + PXO_MID, y + PYO_TOP - F4) && (jumpY < y) && (event != 2)) {
(!event || event[E_BEHAVIOUR] != 25)) {
jumpY = TTOF(LH); jumpY = TTOF(LH);
if (dy < 0) dy = 0; if (dy < 0) dy = 0;
if (event && (event[E_MODIFIER] != 6) && (event[E_BEHAVIOUR] != 28)) if ((event != 3) && (event != 4)) event = 0;
event = NULL;
} }
...@@ -294,8 +283,7 @@ void Player::control (unsigned int ticks, int msps) { ...@@ -294,8 +283,7 @@ void Player::control (unsigned int ticks, int msps) {
jumpY = TTOF(LH); jumpY = TTOF(LH);
if (event && (event[E_MODIFIER] != 6) && (event[E_BEHAVIOUR] != 28)) if ((event != 3) && (event != 4)) event = 0;
event = NULL;
} }
...@@ -303,7 +291,7 @@ void Player::control (unsigned int ticks, int msps) { ...@@ -303,7 +291,7 @@ void Player::control (unsigned int ticks, int msps) {
// Handle firing // Handle firing
if (pcontrols[C_FIRE]) { if (pcontrols[C_FIRE]) {
if (ticks > fireTime) { if ((ticks > fireTime) && (level->getBullet(ammoType + 1)[B_SPRITE] != 0)) {
// Create new bullet // Create new bullet
level->firstBullet = new Bullet(this, false, ticks); level->firstBullet = new Bullet(this, false, ticks);
...@@ -395,7 +383,14 @@ void Player::move (unsigned int ticks, int msps) { ...@@ -395,7 +383,14 @@ void Player::move (unsigned int ticks, int msps) {
while (count > 0) { while (count > 0) {
if (level->checkMask(x + PXO_MID, y + PYO_TOP - F4)) break; if (level->checkMask(x + PXO_MID, y + PYO_TOP - F4)) {
y &= ~4095;
dy = 0;
break;
}
y -= F4; y -= F4;
count--; count--;
...@@ -404,8 +399,14 @@ void Player::move (unsigned int ticks, int msps) { ...@@ -404,8 +399,14 @@ void Player::move (unsigned int ticks, int msps) {
pdy = (-pdy) & 4095; pdy = (-pdy) & 4095;
if (!level->checkMask(x + PXO_MID, y + PYO_TOP - pdy)) y -= pdy; if (!level->checkMask(x + PXO_MID, y + PYO_TOP - pdy))
else y &= ~4095; y -= pdy;
else {
y &= ~4095;
dy = 0;
}
} else if (pdy > 0) { } else if (pdy > 0) {
...@@ -417,7 +418,14 @@ void Player::move (unsigned int ticks, int msps) { ...@@ -417,7 +418,14 @@ void Player::move (unsigned int ticks, int msps) {
if (level->checkMaskDown(x + PXO_ML, y + F4) || if (level->checkMaskDown(x + PXO_ML, y + F4) ||
level->checkMaskDown(x + PXO_MID, y + F4) || level->checkMaskDown(x + PXO_MID, y + F4) ||
level->checkMaskDown(x + PXO_MR, y + F4)) break; level->checkMaskDown(x + PXO_MR, y + F4)) {
y |= 4095;
dy = 0;
break;
}
y += F4; y += F4;
count--; count--;
...@@ -428,8 +436,14 @@ void Player::move (unsigned int ticks, int msps) { ...@@ -428,8 +436,14 @@ void Player::move (unsigned int ticks, int msps) {
if (!(level->checkMaskDown(x + PXO_ML, y + pdy) || if (!(level->checkMaskDown(x + PXO_ML, y + pdy) ||
level->checkMaskDown(x + PXO_MID, y + pdy) || level->checkMaskDown(x + PXO_MID, y + pdy) ||
level->checkMaskDown(x + PXO_MR, y + pdy))) y += pdy; level->checkMaskDown(x + PXO_MR, y + pdy)))
else y |= 4095; y += pdy;
else {
y |= 4095;
dy = 0;
}
} }
...@@ -446,7 +460,13 @@ void Player::move (unsigned int ticks, int msps) { ...@@ -446,7 +460,13 @@ void Player::move (unsigned int ticks, int msps) {
while (count > 0) { while (count > 0) {
// If there is an obstacle, stop // If there is an obstacle, stop
if (level->checkMask(x + PXO_L - F4, y + PYO_MID)) break; if (level->checkMask(x + PXO_L - F4, y + PYO_MID)) {
x &= ~4095;
break;
}
x -= F4; x -= F4;
count--; count--;
...@@ -475,7 +495,13 @@ void Player::move (unsigned int ticks, int msps) { ...@@ -475,7 +495,13 @@ void Player::move (unsigned int ticks, int msps) {
while (count > 0) { while (count > 0) {
// If there is an obstacle, stop // If there is an obstacle, stop
if (level->checkMask(x + PXO_R + F4, y + PYO_MID)) break; if (level->checkMask(x + PXO_R + F4, y + PYO_MID)) {
x |= 4095;
break;
}
x += F4; x += F4;
count--; count--;
...@@ -499,11 +525,10 @@ void Player::move (unsigned int ticks, int msps) { ...@@ -499,11 +525,10 @@ void Player::move (unsigned int ticks, int msps) {
// If using a float up event and have hit a ceiling, ignore event // If using a float up event and have hit a ceiling, ignore event
if (event && (event[E_BEHAVIOUR] == 25) && if ((event == 2) && level->checkMask(x + PXO_MID, y + PYO_TOP - F4)) {
level->checkMask(x + PXO_MID, y + PYO_TOP - F4)) {
jumpY = TTOF(LH); jumpY = TTOF(LH);
event = NULL; event = 0;
} }
...@@ -610,17 +635,7 @@ void Player::draw (unsigned int ticks, int change) { ...@@ -610,17 +635,7 @@ void Player::draw (unsigned int ticks, int change) {
else if (dy >= 0) { else if (dy >= 0) {
if ((event && ((event[E_MODIFIER] == 6) || if (isOnPlatform()) {
(event[E_BEHAVIOUR] == 28))) ||
level->checkMaskDown(x + PXO_ML, y + F2) ||
level->checkMaskDown(x + PXO_MID, y + F2) ||
level->checkMaskDown(x + PXO_MR, y + F2) ||
level->checkMaskDown(x + PXO_ML, y + F8) ||
level->checkMaskDown(x + PXO_MID, y + F8) ||
level->checkMaskDown(x + PXO_MR, y + F8)) {
drawX = x;
drawY = y;
if (dx) { if (dx) {
...@@ -634,14 +649,12 @@ void Player::draw (unsigned int ticks, int change) { ...@@ -634,14 +649,12 @@ void Player::draw (unsigned int ticks, int change) {
if (!level->checkMaskDown(x + PXO_ML, y + F12) && if (!level->checkMaskDown(x + PXO_ML, y + F12) &&
!level->checkMaskDown(x + PXO_L, y + F2) && !level->checkMaskDown(x + PXO_L, y + F2) &&
(!event || ((event[E_MODIFIER] != 6) && (event != 3) && (event != 4))
(event[E_BEHAVIOUR] != 28))))
anim = anims[PA_LEDGE]; anim = anims[PA_LEDGE];
else if (!level->checkMaskDown(x + PXO_MR, y + F12) && else if (!level->checkMaskDown(x + PXO_MR, y + F12) &&
!level->checkMaskDown(x + PXO_R, y + F2) && !level->checkMaskDown(x + PXO_R, y + F2) &&
(!event || ((event[E_MODIFIER] != 6) && (event != 3) && (event != 4))
(event[E_BEHAVIOUR] != 28))))
anim = anims[PA_REDGE]; anim = anims[PA_REDGE];
else if (pcontrols[C_FIRE]) else if (pcontrols[C_FIRE])
...@@ -662,7 +675,7 @@ void Player::draw (unsigned int ticks, int change) { ...@@ -662,7 +675,7 @@ void Player::draw (unsigned int ticks, int change) {
} else anim = anims[facing? PA_RFALL: PA_LFALL]; } else anim = anims[facing? PA_RFALL: PA_LFALL];
} else if (event && (event[E_MODIFIER] == 29)) } else if (event == 1)
anim = anims[facing? PA_RSPRING: PA_LSPRING]; anim = anims[facing? PA_RSPRING: PA_LSPRING];
else anim = anims[facing? PA_RJUMP: PA_LJUMP]; else anim = anims[facing? PA_RJUMP: PA_LJUMP];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment