From 0ce713180efd07da3107f0b2dd989fc213bcc1dc Mon Sep 17 00:00:00 2001 From: Cong Date: Thu, 12 Sep 2013 01:07:34 +1000 Subject: [PATCH] Repel allies (#34) Add mailing list to readme --- README.md | 9 +++++++-- README.md.cmake | 9 +++++++-- src/cdogs/actors.c | 41 +++++++++++++++++++++++++++++++++++++---- src/cdogs/ai.c | 3 ++- src/cdogs/collision.c | 38 ++++++++++++++++++++++++++++++++++---- src/cdogs/collision.h | 14 +++++++++++++- src/cdogs/map.h | 1 + src/cdogs/objs.c | 3 ++- src/cdogs/vector.c | 13 +++++++++++++ src/cdogs/vector.h | 1 + 10 files changed, 117 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index dafc36809..d35407638 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ For the latest release notes please see https://github.com/cxong/cdogs-sdl/wiki/ For more information about the original C-Dogs read 'original\_readme.txt'. +Join the C-Dogs SDL mailing list here: https://groups.google.com/forum/#!forum/c-dogs-sdl + 2.Tested Environments --------------------- @@ -103,7 +105,10 @@ Which will make the game try to run fullscreen at 400x300 resolution. ---------- If you have an questions, comments, bug reports (yes please), patches (even -better) or anything else related to C-Dogs SDL email: +better) or anything else related to C-Dogs SDL, check out the mailing list: -> Cong +> https://groups.google.com/forum/#!forum/c-dogs-sdl +Or email: + +> Cong diff --git a/README.md.cmake b/README.md.cmake index fb23046fa..1e10eca68 100644 --- a/README.md.cmake +++ b/README.md.cmake @@ -34,6 +34,8 @@ For the latest release notes please see https://github.com/cxong/cdogs-sdl/wiki/ For more information about the original C-Dogs read 'original\_readme.txt'. +Join the C-Dogs SDL mailing list here: https://groups.google.com/forum/#!forum/c-dogs-sdl + 2.Tested Environments --------------------- @@ -103,7 +105,10 @@ Which will make the game try to run fullscreen at 400x300 resolution. ---------- If you have an questions, comments, bug reports (yes please), patches (even -better) or anything else related to C-Dogs SDL email: +better) or anything else related to C-Dogs SDL, check out the mailing list: -> Cong +> https://groups.google.com/forum/#!forum/c-dogs-sdl +Or email: + +> Cong diff --git a/src/cdogs/actors.c b/src/cdogs/actors.c index b04ebc45b..05c87bfed 100644 --- a/src/cdogs/actors.c +++ b/src/cdogs/actors.c @@ -69,6 +69,7 @@ #define SOUND_LOCK_FOOTSTEP 4 #define FOOTSTEP_DISTANCE_PLUS 380 +#define REPEL_STRENGTH 20 TActor *gPlayer1 = NULL; @@ -327,6 +328,7 @@ TActor *AddActor(int character) actor->tileItem.w = 7; actor->tileItem.h = 5; actor->tileItem.flags = TILEITEM_IMPASSABLE | TILEITEM_CAN_BE_SHOT; + actor->tileItem.actor = actor; actor->next = actorList; actorList = actor; actor->flags = FLAGS_SLEEPING | gCharacterDesc[character].flags; @@ -515,7 +517,8 @@ int MoveActor(TActor * actor, int x, int y) realPos = Vec2iScaleDiv(Vec2iNew(x, y), 256); target = GetItemOnTileInCollision( - &actor->tileItem, realPos, TILEITEM_IMPASSABLE); + &actor->tileItem, realPos, TILEITEM_IMPASSABLE, + CalcCollisionTeam(1, actor->flags)); if (target) { Vec2i realXPos, realYPos; @@ -556,13 +559,15 @@ int MoveActor(TActor * actor, int x, int y) realYPos = Vec2iScaleDiv(Vec2iNew(actor->x, y), 256); if (GetItemOnTileInCollision( - &actor->tileItem, realYPos, TILEITEM_IMPASSABLE)) + &actor->tileItem, realYPos, TILEITEM_IMPASSABLE, + CalcCollisionTeam(1, actor->flags))) { y = actor->y; } realXPos = Vec2iScaleDiv(Vec2iNew(x, actor->y), 256); if (GetItemOnTileInCollision( - &actor->tileItem, realXPos, TILEITEM_IMPASSABLE)) + &actor->tileItem, realXPos, TILEITEM_IMPASSABLE, + CalcCollisionTeam(1, actor->flags))) { x = actor->x; } @@ -581,7 +586,8 @@ int MoveActor(TActor * actor, int x, int y) { realPos = Vec2iScaleDiv(Vec2iNew(x, y), 256); target = GetItemOnTileInCollision( - &actor->tileItem, realPos, TILEITEM_CAN_BE_TAKEN); + &actor->tileItem, realPos, TILEITEM_CAN_BE_TAKEN, + CalcCollisionTeam(1, actor->flags)); if (target && target->kind == KIND_OBJECT) { PickupObject(actor, target->data); @@ -870,6 +876,33 @@ void UpdateAllActors(int ticks) } else { + // Find actors that are on the same team and colliding, + // and repel them + Vec2i realPos = Vec2iScaleDiv( + Vec2iNew(actor->x, actor->y), 256); + TTileItem *collidingItem = GetItemOnTileInCollision( + &actor->tileItem, realPos, TILEITEM_IMPASSABLE, + COLLISIONTEAM_NONE); + if (collidingItem && collidingItem->kind == KIND_CHARACTER) + { + TActor *collidingActor = collidingItem->actor; + if (CalcCollisionTeam(1, collidingActor->flags) == + CalcCollisionTeam(1, actor->flags)) + { + Vec2i v = Vec2iNew( + actor->x - collidingActor->x, + actor->y - collidingActor->y); + if (Vec2iEqual(v, Vec2iZero())) + { + v = Vec2iNew(1, 0); + } + v = Vec2iScale(Vec2iNorm(v), REPEL_STRENGTH); + actor->dx += v.x; + actor->dy += v.y; + collidingActor->dx -= v.x; + collidingActor->dy -= v.y; + } + } actor = actor->next; } } diff --git a/src/cdogs/ai.c b/src/cdogs/ai.c index c539ea60f..5095d687b 100644 --- a/src/cdogs/ai.c +++ b/src/cdogs/ai.c @@ -258,7 +258,8 @@ static int PositionOK(TActor * actor, int x, int y) return 0; } if (GetItemOnTileInCollision( - &actor->tileItem, realPos, TILEITEM_IMPASSABLE)) + &actor->tileItem, realPos, TILEITEM_IMPASSABLE, + CalcCollisionTeam(1, actor->flags))) { return 0; } diff --git a/src/cdogs/collision.c b/src/cdogs/collision.c index ded91a23d..9e85bd0ab 100644 --- a/src/cdogs/collision.c +++ b/src/cdogs/collision.c @@ -48,6 +48,23 @@ */ #include "collision.h" +#include "actors.h" + +CollisionTeam CalcCollisionTeam(int isActor, int actorFlags) +{ + // Need to have prisoners collide with everything otherwise they will not + // be "rescued" + if (!isActor || (actorFlags & FLAGS_PRISONER)) + { + return COLLISIONTEAM_NONE; + } + if (actorFlags & (FLAGS_PLAYERS | FLAGS_GOOD_GUY)) + { + return COLLISIONTEAM_GOOD; + } + return COLLISIONTEAM_BAD; +} + int IsCollisionWithWall(Vec2i pos, Vec2i size) { if (HitWall(pos.x - size.x, pos.y - size.y) || @@ -84,7 +101,8 @@ int ItemsCollide(TTileItem *item1, TTileItem *item2, Vec2i pos) return 0; } -TTileItem *GetItemOnTileInCollision(TTileItem *item, Vec2i pos, int mask) +TTileItem *GetItemOnTileInCollision( + TTileItem *item, Vec2i pos, int mask, CollisionTeam team) { int dy; int tx = pos.x / TILE_WIDTH; @@ -103,11 +121,23 @@ TTileItem *GetItemOnTileInCollision(TTileItem *item, Vec2i pos, int mask) TTileItem *i = Map(tx + dx, ty + dy).things; while (i) { - if (item != i && + // Don't collide if items are on the same team + CollisionTeam itemTeam = COLLISIONTEAM_NONE; + if (i->kind == KIND_CHARACTER) + { + TActor *a = i->actor; + itemTeam = CalcCollisionTeam(1, a->flags); + } + if (team == COLLISIONTEAM_NONE || + itemTeam == COLLISIONTEAM_NONE || + team != itemTeam) + { + if (item != i && (i->flags & mask) && ItemsCollide(item, i, pos)) - { - return i; + { + return i; + } } i = i->next; } diff --git a/src/cdogs/collision.h b/src/cdogs/collision.h index 28cf5489e..8885f971c 100644 --- a/src/cdogs/collision.h +++ b/src/cdogs/collision.h @@ -53,7 +53,19 @@ #define HitWall(x, y) (gMap[(y)/TILE_HEIGHT][(x)/TILE_WIDTH].flags & MAPTILE_NO_WALK) +// Which "team" the actor's on, for collision +// Actors on the same team don't have to collide +typedef enum +{ + COLLISIONTEAM_NONE, + COLLISIONTEAM_GOOD, + COLLISIONTEAM_BAD +} CollisionTeam; + +CollisionTeam CalcCollisionTeam(int isActor, int actorFlags); + int IsCollisionWithWall(Vec2i pos, Vec2i size); -TTileItem *GetItemOnTileInCollision(TTileItem *item, Vec2i pos, int mask); +TTileItem *GetItemOnTileInCollision( + TTileItem *item, Vec2i pos, int mask, CollisionTeam team); #endif diff --git a/src/cdogs/map.h b/src/cdogs/map.h index e3849cf3d..1dbb9c15b 100644 --- a/src/cdogs/map.h +++ b/src/cdogs/map.h @@ -103,6 +103,7 @@ struct TileItem { int flags; void *data; TileItemDrawFunc drawFunc; + void *actor; struct TileItem *next; struct TileItem *nextToDisplay; }; diff --git a/src/cdogs/objs.c b/src/cdogs/objs.c index ef057e55c..cc59c04d9 100644 --- a/src/cdogs/objs.c +++ b/src/cdogs/objs.c @@ -810,7 +810,7 @@ int HitItem(TMobileObject * obj, int x, int y, special_damage_e special) } item = GetItemOnTileInCollision( - &obj->tileItem, realPos, TILEITEM_CAN_BE_SHOT); + &obj->tileItem, realPos, TILEITEM_CAN_BE_SHOT, COLLISIONTEAM_NONE); hasHit = DamageSomething( Vec2iNew(obj->dx, obj->dy), obj->power, @@ -1323,6 +1323,7 @@ void InternalAddObject( o->tileItem.drawFunc = (TileItemDrawFunc)DrawObject; o->tileItem.w = w; o->tileItem.h = h; + o->tileItem.actor = NULL; MoveTileItem(&o->tileItem, x >> 8, y >> 8); o->next = objList; objList = o; diff --git a/src/cdogs/vector.c b/src/cdogs/vector.c index 4964bdf80..6ef3b1a32 100644 --- a/src/cdogs/vector.c +++ b/src/cdogs/vector.c @@ -61,6 +61,19 @@ Vec2i Vec2iScaleDiv(Vec2i v, int scaleDiv) return v; } +Vec2i Vec2iNorm(Vec2i v) +{ + double magnitude; + if (Vec2iEqual(v, Vec2iZero())) + { + return v; + } + magnitude = sqrt(v.x*v.x + v.y*v.y); + v.x = (int)floor(v.x / magnitude + 0.5); + v.y = (int)floor(v.y / magnitude + 0.5); + return v; +} + int Vec2iEqual(Vec2i a, Vec2i b) { return a.x == b.x && a.y == b.y; diff --git a/src/cdogs/vector.h b/src/cdogs/vector.h index 987506965..f0106770c 100644 --- a/src/cdogs/vector.h +++ b/src/cdogs/vector.h @@ -41,6 +41,7 @@ Vec2i Vec2iZero(void); Vec2i Vec2iAdd(Vec2i a, Vec2i b); Vec2i Vec2iScale(Vec2i v, int scalar); Vec2i Vec2iScaleDiv(Vec2i v, int scaleDiv); +Vec2i Vec2iNorm(Vec2i v); int Vec2iEqual(Vec2i a, Vec2i b); int DistanceSquared(Vec2i a, Vec2i b);