Fix casting range.

Fix missile by introducing PixelPos (instead of Vec2i).
This commit is contained in:
Joris 2011-02-05 22:50:44 +01:00
parent 027a95a816
commit 4e62d647f7
10 changed files with 117 additions and 70 deletions

View file

@ -110,7 +110,6 @@ static void SpellMoveToTarget(CUnit &unit)
goal = order->GetGoal();
if (goal && unit.MapDistanceTo(*goal) <= order->Range) {
// there is goal and it is in range
unit.State = 0;
UnitHeadingFromDeltaXY(unit, goal->tilePos + goal->Type->GetHalfTileSize() - unit.tilePos);
@ -118,9 +117,7 @@ static void SpellMoveToTarget(CUnit &unit)
return;
} else if (!goal && unit.MapDistanceTo(order->goalPos.x, order->goalPos.y) <= order->Range) {
// there is no goal and target spot is in range
const Vec2i diag = {order->Arg1.Spell->Range, order->Arg1.Spell->Range};
UnitHeadingFromDeltaXY(unit, order->goalPos + diag - unit.tilePos);
UnitHeadingFromDeltaXY(unit, order->goalPos - unit.tilePos);
unit.SubAction++; // cast the spell
return;
} else if (err == PF_UNREACHABLE) {

View file

@ -1078,7 +1078,6 @@ void CommandSpellCast(CUnit &unit, const Vec2i &pos, CUnit *dest, SpellType *spe
order->SetGoal(dest);
}
} else {
order->Range = 1;
order->goalPos = pos;
}
order->Arg1.Spell = spell;

View file

@ -36,6 +36,10 @@
#include "unit_cache.h"
#endif
#ifndef __VEC2I_H__
#include "vec2i.h"
#endif
//#include "vec2i.h"
/*----------------------------------------------------------------------------
@ -54,7 +58,7 @@ class CUnitType;
class CUpgrade;
class SpellType;
class CAnimation;
class Vec2i;
/*----------------------------------------------------------------------------
-- Variables

View file

@ -37,13 +37,15 @@
#include <string>
#include "player.h"
#include "icons.h"
#ifndef __VEC2I_H__
#include "vec2i.h"
#endif
/*----------------------------------------------------------------------------
-- Declarations
----------------------------------------------------------------------------*/
class CUnitType;
class Vec2i;
enum EditorRunningType {
EditorNotRunning = 0, /// Not Running

View file

@ -383,10 +383,10 @@ public:
/// load the graphics for a missile type
void LoadMissileSprite();
void Init(void);
void DrawMissileType(int frame, const Vec2i &pos) const;
void Init();
void DrawMissileType(int frame, const PixelPos &pos) const;
void DrawMissileType(int frame, int x, int y) const {
Vec2i pos = {x, y};
PixelPos pos = {x, y};
DrawMissileType(frame, pos);
}
@ -396,7 +396,7 @@ public:
std::string Ident; /// missile name
int Transparency; /// missile transparency
Vec2i size; /// missile size in pixels
PixelSize size; /// missile size in pixels
int DrawLevel; /// Level to draw missile at
int SpriteFrames; /// number of sprite frames in graphic
int NumDirections; /// number of directions missile can face
@ -439,10 +439,10 @@ protected:
public:
virtual ~Missile() {};
static Missile *Init(MissileType *mtype, const Vec2i &startPos, const Vec2i &destPos);
static Missile *Init(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos);
static Missile *Init(MissileType *mtype, int sx, int sy, int dx, int dy) {
Vec2i startPos = {sx, sy};
Vec2i destPos = {dx, dy};
PixelPos startPos = {sx, sy};
PixelPos destPos = {dx, dy};
return Init(mtype, startPos, destPos);
}
@ -452,9 +452,9 @@ public:
void DrawMissile(const CViewport *vp) const;
void SaveMissile(CFile *file) const;
Vec2i source; /// Missile source position
Vec2i position; /// missile pixel position
Vec2i destination; /// missile pixel destination
PixelPos source; /// Missile source position
PixelPos position; /// missile pixel position
PixelPos destination; /// missile pixel destination
MissileType *Type; /// missile-type pointer
int SpriteFrame; /// sprite frame counter
int State; /// state
@ -585,18 +585,18 @@ extern MissileType *NewMissileTypeSlot(const std::string& ident);
/// Get missile-type by ident
extern MissileType *MissileTypeByIdent(const std::string& ident);
/// create a missile
extern Missile *MakeMissile(MissileType *mtype, const Vec2i &startPos, const Vec2i &destPos);
extern Missile *MakeMissile(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos);
inline Missile *MakeMissile(MissileType *mtype, int sx, int sy, int dx, int dy) {
const Vec2i startPos = {sx, sy};
const Vec2i destPos = {dx, dy};
const PixelPos startPos = {sx, sy};
const PixelPos destPos = {dx, dy};
return MakeMissile(mtype, startPos, destPos);
}
/// create a local missile
extern Missile *MakeLocalMissile(MissileType *mtype, const Vec2i &startPos, const Vec2i &destPos);
extern Missile *MakeLocalMissile(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos);
inline Missile *MakeLocalMissile(MissileType *mtype, int sx, int sy, int dx, int dy) {
const Vec2i startPos = {sx, sy};
const Vec2i destPos = {dx, dy};
const PixelPos startPos = {sx, sy};
const PixelPos destPos = {dx, dy};
return MakeLocalMissile(mtype, startPos, destPos);
}

View file

@ -409,6 +409,21 @@ static inline int MapDistance(const Vec2i& pos1, const Vec2i &pos2)
return isqrt(diff.x * diff.x + diff.y * diff.y);
}
/**
** Returns the map distance between two points.
**
** @param pos1 map pixel position.
** @param pos2 map pixel position.
**
** @return The distance between in pixels.
*/
static inline int MapDistance(const PixelPos& pos1, const PixelPos &pos2)
{
const PixelDiff diff = pos2 - pos1;
return isqrt(diff.x * diff.x + diff.y * diff.y);
}
/// Returns the map distance between two points with unit-type
extern int MapDistanceToType(const Vec2i &pos1, const CUnitType &type, const Vec2i &pos2);
@ -1279,6 +1294,8 @@ extern void RescueUnits();
/// Convert direction (dx,dy) to heading (0-255)
extern int DirectionToHeading(const Vec2i &dir);
/// Convert direction (dx,dy) to heading (0-255)
extern int DirectionToHeading(const PixelDiff &dir);
/// Update frame from heading
extern void UnitUpdateHeading(CUnit &unit);

View file

@ -33,93 +33,108 @@
//@{
class Vec2i
template <typename T>
class Vec2T
{
public:
short int x;
short int y;
T x;
T y;
};
inline bool operator == (const Vec2i &lhs, const Vec2i & rhs)
template <typename T>
inline bool operator == (const Vec2T<T> &lhs, const Vec2T<T> &rhs)
{
return lhs.x == rhs.x && lhs.y == rhs.y;
}
inline bool operator != (const Vec2i &lhs, const Vec2i & rhs)
template <typename T>
inline bool operator != (const Vec2T<T> &lhs, const Vec2T<T> &rhs)
{
return !(lhs == rhs);
}
inline const Vec2i& operator += (Vec2i &lhs, const Vec2i& rhs)
template <typename T>
inline const Vec2T<T>& operator += (Vec2T<T> &lhs, const Vec2T<T>& rhs)
{
lhs.x += rhs.x;
lhs.y += rhs.y;
return lhs;
}
inline const Vec2i& operator -= (Vec2i &lhs, const Vec2i& rhs)
template <typename T>
inline const Vec2T<T>& operator -= (Vec2T<T> &lhs, const Vec2T<T> &rhs)
{
lhs.x -= rhs.x;
lhs.y -= rhs.y;
return lhs;
}
inline const Vec2i& operator *= (Vec2i &lhs, int rhs)
template <typename T>
inline const Vec2T<T>& operator *= (Vec2T<T> &lhs, int rhs)
{
lhs.x *= rhs;
lhs.y *= rhs;
return lhs;
}
inline const Vec2i& operator /= (Vec2i &lhs, int rhs)
template <typename T>
inline const Vec2T<T>& operator /= (Vec2T<T> &lhs, int rhs)
{
lhs.x /= rhs;
lhs.y /= rhs;
return lhs;
}
inline Vec2i operator + (const Vec2i &lhs, const Vec2i& rhs)
template <typename T>
inline Vec2T<T> operator + (const Vec2T<T> &lhs, const Vec2T<T>& rhs)
{
Vec2i res(lhs);
Vec2T<T> res(lhs);
res += rhs;
return res;
}
inline Vec2i operator - (const Vec2i &lhs, const Vec2i& rhs)
template <typename T>
inline Vec2T<T> operator - (const Vec2T<T> &lhs, const Vec2T<T>& rhs)
{
Vec2i res(lhs);
Vec2T<T> res(lhs);
res -= rhs;
return res;
}
inline Vec2i operator * (const Vec2i &lhs, int rhs)
template <typename T>
inline Vec2T<T> operator * (const Vec2T<T> &lhs, int rhs)
{
Vec2i res(lhs);
Vec2T<T> res(lhs);
res *= rhs;
return res;
}
inline Vec2i operator * (int lhs, const Vec2i &rhs)
template <typename T>
inline Vec2T<T> operator * (int lhs, const Vec2T<T> &rhs)
{
Vec2i res(rhs);
Vec2T<T> res(rhs);
res *= lhs;
return res;
}
inline Vec2i operator / (const Vec2i &lhs, int rhs)
template <typename T>
inline Vec2T<T> operator / (const Vec2T<T> &lhs, int rhs)
{
Vec2i res(lhs);
Vec2T<T> res(lhs);
res /= rhs;
return res;
}
typedef Vec2T<short int> Vec2i;
typedef Vec2T<int> PixelPos;
typedef Vec2T<int> PixelDiff;
typedef Vec2T<int> PixelSize;
//@}

View file

@ -170,7 +170,7 @@ Missile::Missile() :
**
** @return created missile.
*/
Missile *Missile::Init(MissileType *mtype, const Vec2i &startPos, const Vec2i &destPos)
Missile *Missile::Init(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos)
{
Missile *missile = NULL;
@ -218,7 +218,7 @@ Missile *Missile::Init(MissileType *mtype, const Vec2i &startPos, const Vec2i &d
missile = new MissileDeathCoil;
break;
}
const Vec2i halfSize = mtype->size / 2;
const PixelPos halfSize = mtype->size / 2;
missile->position = startPos - halfSize;
missile->destination = destPos - halfSize;
missile->source = missile->position;
@ -238,7 +238,7 @@ Missile *Missile::Init(MissileType *mtype, const Vec2i &startPos, const Vec2i &d
**
** @return created missile.
*/
Missile *MakeMissile(MissileType *mtype, const Vec2i &startPos, const Vec2i &destPos)
Missile *MakeMissile(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos)
{
Missile *missile = Missile::Init(mtype, startPos, destPos);
@ -255,7 +255,7 @@ Missile *MakeMissile(MissileType *mtype, const Vec2i &startPos, const Vec2i &des
**
** @return created missile.
*/
Missile *MakeLocalMissile(MissileType *mtype, const Vec2i &startPos, const Vec2i &destPos)
Missile *MakeLocalMissile(MissileType *mtype, const PixelPos &startPos, const PixelPos &destPos)
{
Missile *missile = Missile::Init(mtype, startPos, destPos);
@ -513,7 +513,7 @@ static int MissileVisibleInViewport(const CViewport *vp, const Missile *missile)
** @param frame Animation frame
** @param pos Screen pixel position
*/
void MissileType::DrawMissileType(int frame, const Vec2i &pos) const
void MissileType::DrawMissileType(int frame, const PixelPos &pos) const
{
#ifdef DYNAMIC_LOAD
if (!this->G->IsLoaded()) {
@ -683,7 +683,7 @@ int FindAndSortMissiles(const CViewport *vp,
**
** @internal We have : SpriteFrame / (2 * (Numdirection - 1)) == DirectionToHeading / 256.
*/
static void MissileNewHeadingFromXY(Missile &missile, const Vec2i &delta)
static void MissileNewHeadingFromXY(Missile &missile, const PixelPos &delta)
{
int neg;
@ -720,7 +720,7 @@ static void MissileNewHeadingFromXY(Missile &missile, const Vec2i &delta)
*/
static int MissileInitMove(Missile &missile)
{
const Vec2i heading = missile.destination - missile.position;
const PixelPos heading = missile.destination - missile.position;
MissileNewHeadingFromXY(missile, heading);
if (!(missile.State & 1)) {
@ -759,11 +759,11 @@ static int PointToPointMissile(Missile &missile)
Assert(missile.Type != NULL);
Assert(missile.TotalStep != 0);
const Vec2i diff = (missile.destination - missile.source);
const PixelPos diff = (missile.destination - missile.source);
missile.position = missile.source + diff * missile.CurrentStep / missile.TotalStep;
if (missile.Type->SmokeMissile && missile.CurrentStep) {
const Vec2i position = missile.position + missile.Type->size / 2;
const PixelPos position = missile.position + missile.Type->size / 2;
MakeMissile(missile.Type->SmokeMissile, position, position);
}
return 0;
@ -792,10 +792,10 @@ static int ParabolicMissile(Missile &missile)
return 1;
}
Assert(missile.Type != NULL);
const Vec2i orig_pos = missile.position;
const PixelPos orig_pos = missile.position;
Assert(missile.TotalStep != 0);
const Vec2i step = (missile.destination - missile.source) * 1000 / missile.TotalStep;
missile.position = missile.source + step * missile.CurrentStep / 1000;
const PixelPos diff = (missile.destination - missile.source);
missile.position = missile.source + diff * missile.CurrentStep / missile.TotalStep;
Assert(k != 0);
z = missile.CurrentStep * (missile.TotalStep - missile.CurrentStep) / k;
@ -804,7 +804,7 @@ static int ParabolicMissile(Missile &missile)
missile.position.y += z * zprojToY / 64;
MissileNewHeadingFromXY(missile, missile.position - orig_pos);
if (missile.Type->SmokeMissile && missile.CurrentStep) {
const Vec2i position = missile.position + missile.Type->size / 2;
const PixelPos position = missile.position + missile.Type->size / 2;
MakeMissile(missile.Type->SmokeMissile, position, position);
}
return 0;
@ -875,18 +875,18 @@ void MissileHit(Missile *missile)
if (missile->Type->ImpactSound.Sound) {
PlayMissileSound(missile, missile->Type->ImpactSound.Sound);
}
Vec2i pos = missile->position + missile->Type->size / 2;
const PixelPos pixelPos = missile->position + missile->Type->size / 2;
//
// The impact generates a new missile.
//
if (missile->Type->ImpactMissile) {
MakeMissile(missile->Type->ImpactMissile, pos.x, pos.y, pos.x, pos.y);
MakeMissile(missile->Type->ImpactMissile, pixelPos, pixelPos);
}
if (missile->Type->ImpactParticle) {
missile->Type->ImpactParticle->pushPreamble();
missile->Type->ImpactParticle->pushInteger(pos.x);
missile->Type->ImpactParticle->pushInteger(pos.y);
missile->Type->ImpactParticle->pushInteger(pixelPos.x);
missile->Type->ImpactParticle->pushInteger(pixelPos.y);
missile->Type->ImpactParticle->run();
}
@ -894,8 +894,7 @@ void MissileHit(Missile *missile)
return;
}
pos.x /= TileSizeX;
pos.y /= TileSizeY;
const Vec2i pos = {pixelPos.x / TileSizeX, pixelPos.y / TileSizeY};
if (!Map.Info.IsPointOnMap(pos)) {
// FIXME: this should handled by caller?
@ -1126,7 +1125,7 @@ void MissileActions()
*/
int ViewPointDistanceToMissile(const Missile *missile)
{
const Vec2i pixelPos = missile->position + missile->Type->size / 2;
const PixelPos pixelPos = missile->position + missile->Type->size / 2;
const Vec2i tilePos = { pixelPos.x / TileSizeX, pixelPos.y / TileSizeY };
return ViewPointDistance(tilePos);
@ -1400,9 +1399,9 @@ void MissilePointToPointBounce::Action()
this->Wait = this->Type->Sleep;
if (PointToPointMissile(*this)) {
if (this->State < 2 * this->Type->NumBounces - 1 && this->TotalStep) {
const Vec2i step = (this->destination - this->source) * 1024 / this->TotalStep;
const PixelPos step = (this->destination - this->source);
this->destination += step * ((TileSizeX + TileSizeY) * 3) / 4 / 1024;
this->destination += step * ((TileSizeX + TileSizeY) * 3) / 4 / this->TotalStep;
this->State++; // !(State & 1) to initialise
this->source = this->position;
PointToPointMissile(*this);
@ -1625,7 +1624,7 @@ void MissileWhirlwind::Action()
//
// Center of the tornado
//
Vec2i center = this->position + this->Type->size / 2;
PixelPos center = this->position + this->Type->size / 2;
center.x = (center.x + TileSizeX / 2) / TileSizeX;
center.y = (center.y + TileSizeY) / TileSizeY;

View file

@ -197,9 +197,9 @@ static int CclDefineMissileType(lua_State *l)
static int CclMissile(lua_State *l)
{
MissileType *type = NULL;
Vec2i position = {-1, -1};
Vec2i destination = {-1, -1};
Vec2i source = {-1, -1};
PixelPos position = {-1, -1};
PixelPos destination = {-1, -1};
PixelPos source = {-1, -1};
Missile *missile = NULL;
DebugPrint("FIXME: not finished\n");

View file

@ -1744,6 +1744,20 @@ int DirectionToHeading(const Vec2i& delta)
return 0;
}
/**
** Convert direction to heading.
**
** @param delta Delta.
**
** @return Angle (0..255)
*/
int DirectionToHeading(const PixelDiff& delta)
{
// code is identic for Vec2i and PixelDiff
Vec2i delta2 = {delta.x, delta.y};
return DirectionToHeading(delta2);
}
/**
** Update sprite frame for new heading.
*/