Compare commits

...

55 Commits
master ... rope

Author SHA1 Message Date
Armin Burgmeier db68467d91 WIP First step in introducing rope links 2012-12-30 15:43:25 +01:00
Armin Burgmeier f10f7a4d48 Don't apply rope forces in directions in which an object is attached 2012-12-30 14:46:14 +01:00
Armin Burgmeier 80599754c7 Merge branch 'master' into rope
Conflicts:
	planet/Experimental.ocd/LiftTower.ocd/Script.c
	planet/Objects.ocd/Structures.ocd/Elevator.ocd/Script.c
2012-12-30 11:45:57 +01:00
Armin Burgmeier ecec556395 Make sure rope script functions are only called from rope contexts 2012-06-07 23:41:21 +02:00
Armin Burgmeier cd67961aa6 Merge default into rope 2012-06-07 21:36:29 +02:00
Armin Burgmeier 74ab62b66f Merge default into rope 2012-05-13 20:30:48 +02:00
Armin Burgmeier c16c7e4298 Fix C4Real math when deciding whether to use the PathFinder 2012-05-13 20:22:54 +02:00
Armin Burgmeier d388f1a3f3 Merge default into rope 2012-05-06 20:38:24 +02:00
Armin Burgmeier 7452f11dca Rope: Use integer sqrt algorithm for calculating distances 2012-05-06 20:16:00 +02:00
Armin Burgmeier e16de2d46f Reduce the mass of the plane chassis 2012-05-06 19:33:50 +02:00
Armin Burgmeier 6006b83aa6 Rope: Compute forces from last contact vertex for connected objects 2012-05-06 19:14:25 +02:00
Armin Burgmeier 2aef0d896d Rope: Enable debug draw by defining C4ROPE_DRAW_DEBUG 2012-05-06 18:19:03 +02:00
Armin Burgmeier 24b93532a1 Rope: Fix force magnitude when finding direction via PathFinder 2012-05-06 18:16:46 +02:00
Armin Burgmeier f58b565604 Make LiftTower use the engine rope 2012-05-06 15:25:51 +02:00
Armin Burgmeier 6bb893f387 Rope: When first element is at target position, continue pulling at next 2012-05-06 15:17:18 +02:00
Armin Burgmeier a309e52de3 Rope: Fix possible C4Real overflow 2012-05-06 14:37:28 +02:00
Armin Burgmeier f54b471115 Rope: Add Pull functions 2012-05-06 13:59:47 +02:00
Armin Burgmeier 27d72b12ce Rope: Fix BackAutoSegmentation 2012-05-06 13:58:11 +02:00
Armin Burgmeier c3eaa66bef Rope: Change third parameter of CreateRope to nominal segment length
Was number of segments before
2012-05-06 00:53:41 +02:00
Armin Burgmeier 4f2aedd635 Merge default into rope 2012-05-05 23:42:33 +02:00
Armin Burgmeier 012507805f Rope: Add SetFront() and SetBack() functions 2012-05-05 22:52:23 +02:00
Armin Burgmeier 76dfb050e4 Rope: Rename CreateRope2() script function to CreateRope() 2012-05-05 21:45:50 +02:00
Armin Burgmeier aaa76be2c4 Rope: Reduce number of iterations to 10 every frame 2012-05-05 21:29:49 +02:00
Armin Burgmeier 2c82a66083 Rope: Add a script function to set fixed rope ends 2012-05-05 21:24:20 +02:00
Armin Burgmeier 002d64108d Rope: Add a script function to remove a rope 2012-05-05 21:07:16 +02:00
Armin Burgmeier 72d4aa69c5 Rope: Fix crash when a connected object is removed 2012-05-05 20:50:24 +02:00
Armin Burgmeier dd4469ec30 Rope: Implement dynamic rope length (AutoSegmentation) 2012-05-05 17:50:58 +02:00
Armin Burgmeier da0109919b Rope: Only apply force redirection to objects not attached to landscape 2012-05-02 21:12:46 +02:00
Armin Burgmeier 32b650c462 Rope: Use PathFinder to better handle clumsy landscapes
There's two remaining problems:
	* When the rope hangs over a cliff it's moving around funny and does
	  not get to rest properly
	* Redirection does not work correctly yet for very pointed angles,
	  O(10 deg). Rope will get stuck.
2012-05-02 00:35:15 +02:00
Armin Burgmeier 628e3a9b13 Rope: Apply force redirection at vertex position for attached objects 2012-05-02 00:30:33 +02:00
Armin Burgmeier c9f91af4d2 Merge default into rope 2012-05-01 23:07:12 +02:00
Armin Burgmeier 4306ba7648 Rope: Clean up and simplify the code a bit 2012-05-01 16:19:09 +02:00
Armin Burgmeier 889be3d2e4 Rope: Apply force redirection to connected objects 2012-04-29 23:08:12 +02:00
Armin Burgmeier 4c3629cde6 Rope: Improve landscape interaction a bit 2012-04-29 20:42:41 +02:00
Armin Burgmeier 886b1e254b Rope: Don't apply repulsive forces on rope segments 2012-04-29 16:21:22 +02:00
Armin Burgmeier bd45ae0fab Fix compilation with MSVC 2012-04-29 15:47:36 +02:00
Armin Burgmeier a2997fc763 Rope: Apply sticking friction 2012-04-29 15:36:06 +02:00
Armin Burgmeier 56282e6168 Rope: Implement landscape force redirection for C4RopeSegments 2012-04-29 14:12:09 +02:00
Armin Burgmeier eacc4d6917 FnCreateRope: Protect against null or non-definition graphics proplist 2012-04-29 00:44:58 +02:00
Armin Burgmeier 89c63b393b Make C4Rope a proplist for easy script access 2012-04-29 00:09:04 +02:00
Armin Burgmeier a84faff0cf Merged default into rope 2012-04-28 22:08:37 +02:00
Armin Burgmeier 8952bc4f43 Rope: Texturized graphics 2012-04-28 21:45:36 +02:00
Armin Burgmeier 54540a8dac Rope: Take into account Zoom and Viewport position when drawing 2012-04-28 20:09:02 +02:00
Armin Burgmeier 4b7b924961 Rope: Improve graphics when pointed angles (<90 deg) occur 2012-04-28 19:16:39 +02:00
Armin Burgmeier acff7e76be Rope.ocs: Add a rope between the player's clonk and a fixpoint 2012-04-28 17:24:34 +02:00
Armin Burgmeier a556dc1798 Rope: Draw the rope with GL_QUAD_STRIP 2012-04-28 17:24:02 +02:00
Armin Burgmeier 1ef0f3ce41 Rope: Preliminary collision with landscape 2012-04-28 13:54:40 +02:00
Armin Burgmeier 6cf22b7d22 Rope: Don't apply forces to C4D_StaticBack objects 2012-04-28 13:54:24 +02:00
Armin Burgmeier 4b8c7e9c6a Rope: Choose some sane defaults for k and rho 2012-04-28 13:54:03 +02:00
Armin Burgmeier a4b455a2a4 Rope: Make sure texture unit is disabled when drawing 2012-04-28 13:53:08 +02:00
Armin Burgmeier abc948d591 Rope: Apply friction in correct direction 2012-04-28 13:52:42 +02:00
Armin Burgmeier 2484f44ecb Fix gravity on rope segments 2012-04-28 00:33:53 +02:00
Armin Burgmeier a0ec851b70 Fix a graphics glitch 2012-04-28 00:08:40 +02:00
Armin Burgmeier 745ab91665 Apply gravity to rope segments 2012-04-28 00:06:32 +02:00
Armin Burgmeier b83cc3c6d2 Add start of a engine-side rope implementation
basic rope physics works, but many things remain to be done:
	* collision with landscape
	* graphics
	* savegames
	* ClearPointers
	* Proper script interface
	* You name it
2012-04-26 22:56:24 +02:00
23 changed files with 1551 additions and 19 deletions

View File

@ -482,6 +482,9 @@ set(OC_CLONK_SOURCES
src/object/C4ObjectPtr.cpp
src/object/C4ObjectPtr.h
src/object/C4ObjectScript.cpp
src/object/C4Rope.cpp
src/object/C4Rope.h
src/object/C4RopeScript.cpp
src/object/C4Sector.cpp
src/object/C4Sector.h
src/object/C4Shape.cpp

View File

@ -28,7 +28,8 @@ public func ConnectTo(object connect)
/* rope->BreakRope(true);
SetRope(true);
rope->Connect(tower, connect);*/
rope->Reconnect(connect);
//rope->Reconnect(connect);
rope->SetFront(connect);
AddEffect("Connecting", this, 1, 1, this, nil, connect);
return true;
}
@ -61,7 +62,7 @@ private func FxConnectingTimer(object target, effect)
if (!effect.connection)
{
Unhook();
rope->BreakRope(true);
rope->Remove(); //BreakRope(true);
SetRope();
return -1;
}
@ -89,7 +90,7 @@ public func Interact(object clonk)
{
RemoveEffect("Connecting", this);
Unhook();
rope->BreakRope(true);
//rope->BreakRope(true);
SetRope();
return true;
}
@ -115,26 +116,34 @@ func Initialize()
func SetRope(bool no_connect)
{
rope = CreateObject(LiftTower_Rope,0,0,NO_OWNER);
rope = CreateRope(this, tower, 5, LiftTower_Rope);
if(rope)
{
rope->SetBackFixed(true);
rope->SetBackAutoSegmentation(250);
tower->SetRope(rope);
}
return rope;
/*rope = CreateObject(LiftTower_Rope,0,0,NO_OWNER);
if (!no_connect) rope->Connect(tower, this);
tower->SetRope(rope);
return rope;
return rope;*/
}
public func Destruction()
{
if(rope)
rope->HookRemoved();
rope->Remove();
}
protected func Rotation()
{
if (!rope) return;
SetR(rope->GetHookAngle());
//SetR(rope->GetHookAngle()); // TODO: Hook rotation by last segment
}
public func NoLiftTowerConnection() { return true; }
local Name = "$Name$";
local Description = "$Description$";
local Collectible = 1;
local Collectible = 1;

View File

@ -4,5 +4,5 @@ Version=5,2,0,1
Category=C4D_StaticBack
Vertices=2
Width=2
Height=12
Offset=-1,-6
Height=11
Offset=-1,-5

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -66,7 +66,7 @@ func Interact(object clonk)
return true;
}
func SetRope(object rope_to_set)
func SetRope(proplist rope_to_set)
{
rope = rope_to_set;
}
@ -75,7 +75,7 @@ func SetRope(object rope_to_set)
public func ControlUp(object clonk)
{
return DrawIn();
return this->DrawIn();
}
public func ControlStop(object clonk)
{
@ -89,10 +89,14 @@ public func DrawIn()
if (hook->Contained() == this) return false;
if (ObjectDistance(hook) < LIFTTOWER_HOOK_LOOSEDIST) return false;
if (GetEffect("DrawIn", this)) return false;
rope->ConnectPull();
return AddEffect("DrawIn", this, 1, 1, this);
}
private func FxDrawInStart(effect)
{
rope->PullBack(40);
}
private func FxDrawInTimer(effect)
{
if (!rope) return -1;
@ -101,15 +105,17 @@ private func FxDrawInTimer(effect)
OnRopeBreak();
return -1;
}
rope->DoLength(-1);
//rope->DoLength(-1);
if (ObjectDistance(hook) < LIFTTOWER_HOOK_LOOSEDIST) return -1;
}
private func FxDrawInStop(object target, effect, int temp)
{
rope->PullBack(0);
if (temp) return;
if (!rope) return;
rope->ConnectLoose();
//rope->ConnectLoose();
}
/* Animation */
@ -167,4 +173,4 @@ func Definition(def) {
local Name = "$Name$";
local Description = "$Description$";
local Touchable = 2;
local BlastIncinerate = 100;
local BlastIncinerate = 100;

View File

@ -11,7 +11,7 @@ VertexX=-22,-22,0,0,20,20
VertexY=7,-7,7,-7,-8,1
VertexFriction=30,60,30,60,60,30
Value=40
Mass=100
Mass=70
Components=Wood=3;Metal=2;
Rotate=1
Float=1

View File

@ -32,7 +32,7 @@ func Initialize()
{
SetCategory(C4D_StaticBack);
CreateCase();
CreateRope();
CreateCaseRope();
if (partner)
{
@ -54,7 +54,7 @@ func CreateCase()
case->Connect(this);
}
func CreateRope()
func CreateCaseRope()
{
rope = CreateObject(ElevatorRope, -19 * GetCalcDir(), -11, GetOwner());
rope->SetAction("Be", case.back);

View File

@ -0,0 +1,8 @@
[DefCore]
id=LiftTower_Rope
Version=5,2,0,1
Category=C4D_StaticBack
Vertices=2
Width=2
Height=11
Offset=-1,-5

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,21 @@
func Initialize()
{
var a = CreateObject(Rock, 100, 100, NO_OWNER);
var b = CreateObject(Rock, 200, 100, NO_OWNER);
//a->SetCategory(C4D_StaticBack);
//b->SetCategory(C4D_StaticBack);
Scenario.rope = CreateRope(a, b, 5, LiftTower_Rope);
//CreateRope(a, b, 100, LiftTower_Rope);
}
func InitializePlayer(int plr)
{
var clonk = GetCrew(plr, 0);
var a = CreateObject(Rock, clonk->GetX(), clonk->GetY()-100, NO_OWNER);
a->SetCategory(C4D_StaticBack);
var rope = CreateRope(a, clonk, 5, LiftTower_Rope);
rope->SetFrontAutoSegmentation(200);
}

View File

@ -678,6 +678,7 @@ bool C4Game::GameOverCheck()
C4ST_NEW(ControlRcvStat, "C4Game::Execute ReceiveControl")
C4ST_NEW(ControlStat, "C4Game::Execute ExecuteControl")
C4ST_NEW(ExecRopesStat, "C4Game::Execute ExecRopes")
C4ST_NEW(ExecObjectsStat, "C4Game::Execute ExecObjects")
C4ST_NEW(GEStats, "C4Game::Execute pGlobalEffects->Execute")
C4ST_NEW(PXSStat, "C4Game::Execute PXS.Execute")
@ -736,6 +737,7 @@ bool C4Game::Execute() // Returns true if the game is over
// Game
EXEC_S( ExecObjects(); , ExecObjectsStat )
EXEC_S( Ropes.Execute(); , ExecRopesStat )
if (pGlobalEffects)
EXEC_S_DR( pGlobalEffects->Execute(NULL); , GEStats , "GEEx\0");
EXEC_S_DR( PXS.Execute(); , PXSStat , "PXSEx")
@ -916,6 +918,7 @@ void C4Game::ClearPointers(C4Object * pObj)
TransferZones.ClearPointers(pObj);
if (pGlobalEffects)
pGlobalEffects->ClearPointers(pObj);
Ropes.ClearPointers(pObj);
}
bool C4Game::TogglePause()
@ -2192,6 +2195,7 @@ bool C4Game::InitScriptEngine()
InitCoreFunctionMap(&ScriptEngine);
InitObjectFunctionMap(&ScriptEngine);
InitGameFunctionMap(&ScriptEngine);
Ropes.InitFunctionMap(&ScriptEngine);
// system functions: check if system group is open
if (!Application.OpenSystemGroup())

View File

@ -30,6 +30,7 @@
#include <C4Extra.h>
#include "C4Scoreboard.h"
#include <C4PlayerControl.h>
#include <C4Rope.h>
class C4Game
{
@ -88,6 +89,8 @@ public:
C4FileMonitor *pFileMonitor;
C4GameSec1Timer *pSec1Timer;
C4RopeList Ropes;
char CurrentScenarioSection[C4MaxName+1];
char ScenarioFilename[_MAX_PATH+1];
StdCopyStrBuf ScenarioTitle;

View File

@ -254,6 +254,11 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawOverlay)
::Objects.Draw(cgo, Player, 1, 2147483647 /* INT32_MAX */);
C4ST_STOP(ObjStat)
// draw ropes
C4ST_STARTNEW(ObjStat, "C4Viewport::Draw: Ropes")
::Game.Ropes.Draw(cgo, NULL);
C4ST_STOP(ObjStat)
// draw global particles
C4ST_STARTNEW(PartStat, "C4Viewport::Draw: Particles")
::Particles.GlobalParticles.Draw(cgo,NULL);

View File

@ -2264,6 +2264,23 @@ static C4String *FnGetPlayerControlAssignment(C4PropList * _this, long player, l
return String(assignment->GetKeysAsString(human_readable, short_name).getData());
}
static C4PropList* FnCreateRope(C4PropList* _this, C4Object* First, C4Object* Second, int SegmentLength, C4PropList* Graphics)
{
try
{
if(!Graphics) return NULL;
C4Def* Def = Graphics->GetDef();
if(!Def) return NULL;
return Game.Ropes.CreateRope(First, Second, itofix(SegmentLength), &Def->Graphics);
}
catch(const C4RopeError& err)
{
DebugLogF("Failed to create rope: %s", err.what());
return NULL;
}
}
extern C4ScriptConstDef C4ScriptGameConstMap[];
extern C4ScriptFnDef C4ScriptGameFnMap[];
@ -2428,6 +2445,7 @@ void InitGameFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "GetPlayerControlAssignment", FnGetPlayerControlAssignment);
AddFunc(pEngine, "PlayerObjectCommand", FnPlayerObjectCommand);
AddFunc(pEngine, "EditCursor", FnEditCursor);
AddFunc(pEngine, "CreateRope", FnCreateRope);
F(GetPlrKnowledge);
F(GetComponent);

View File

@ -29,6 +29,16 @@
#ifdef C4REAL_USE_FIXNUM
C4Fixed Sqrt(C4Fixed x)
{
assert(x.val >= 0);
assert(FIXED_SHIFT % 2 == 0);
C4Fixed ret;
ret.val = SqrtI(x.val) << (FIXED_SHIFT >> 1);
return ret;
}
// static table with sinus values from 0.00 degree to 90.00 degree inclusively
long SineTable[9001] =
{

View File

@ -71,6 +71,7 @@ class C4Fixed
friend C4Fixed itofix(int32_t x, int32_t prec);
friend float fixtof(const C4Fixed &x);
friend C4Fixed ftofix(float x);
friend C4Fixed Sqrt(C4Fixed x);
#else
friend void FIXED_TO_FLOAT(float *pVal);
#endif
@ -296,6 +297,8 @@ inline C4Real C4REAL100(int x) { return itofix(x, 100); }
inline C4Real C4REAL256(int x) { C4Fixed r; r.val = x * FIXED_FPF / 256; return r; }
inline C4Real C4REAL10(int x) { return itofix(x, 10); }
C4Fixed Sqrt(C4Fixed x);
#else
// *** wrap C4Real to float

View File

@ -71,6 +71,28 @@ int Pow(int base, int exponent)
return result;
}
/* Fast(?) Integer square root */
uint32_t SqrtI(uint32_t a)
{
uint32_t rem = 0;
uint32_t root = 0;
for(unsigned int i = 0; i < (sizeof(a)*8)/2; i++)
{
root <<= 1;
rem = ((rem << 2) + (a >> (sizeof(a)*8 - 2)));
a <<= 2;
root ++;
if(root <= rem)
{
rem -= root;
root++;
}
else
root--;
}
return root >> 1;
}
bool ForLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
bool (*fnCallback)(int32_t, int32_t, int32_t), int32_t iPar,
int32_t *lastx, int32_t *lasty)

View File

@ -48,6 +48,7 @@ int32_t Distance(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2);
int Angle(int iX1, int iY1, int iX2, int iY2);
int Pow(int base, int exponent);
int32_t StrToI32(const char *s, int base, const char **scan_end);
uint32_t SqrtI(uint32_t a);
#include <cstring>
inline void ZeroMem(void *lpMem, size_t dwSize)

1077
src/object/C4Rope.cpp 100644

File diff suppressed because it is too large Load Diff

189
src/object/C4Rope.h 100644
View File

@ -0,0 +1,189 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2012 Armin Burgmeier
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#ifndef INC_C4Rope
#define INC_C4Rope
#include <stdexcept>
#include <C4Object.h>
// All units in pixels and frames
class C4RopeError: public std::runtime_error
{
public:
C4RopeError(const std::string& message): std::runtime_error(message) {}
};
// C4RopeLinks are intermediate rope elements that are inserted and removed
// such that
class C4RopeLink
{
public:
C4Real x, y; // pos
C4RopeLink* Next;
C4RopeLink* Prev;
};
class C4Rope;
class C4RopeElement
{
friend class C4Rope;
public:
C4RopeElement(C4Object* obj, bool fixed);
C4RopeElement(C4Real x, C4Real y, C4Real m, bool fixed);
~C4RopeElement();
C4Real GetX() const { return Object ? GetTargetX() : x; }
C4Real GetY() const { return Object ? GetTargetY() : y; }
C4Real GetVx() const { return Object ? Object->xdir : vx; }
C4Real GetVy() const { return Object ? Object->ydir : vy; }
C4Real GetMass() const { return Object ? itofix(Object->Mass) : m; }
C4Object* GetObject() const { return Object; }
C4Real GetTargetX() const;
C4Real GetTargetY() const;
C4Real GetPrevLinkX() const { assert(Prev); return LastLink ? LastLink->x : Prev->oldx; }
C4Real GetPrevLinkY() const { assert(Prev); return LastLink ? LastLink->y : Prev->oldy; }
C4Real GetNextLinkX() const { assert(Next); return FirstLink ? FirstLink->x : Next->oldx; }
C4Real GetNextLinkY() const { assert(Next); return FirstLink ? FirstLink->y : Next->oldy; }
void AddForce(C4Real x, C4Real y);
void Execute(const C4Rope* rope, C4Real dt);
private:
bool InsertLinkPosition(int from_x, int from_y, int to_x, int to_y, int link_x, int link_y, int& insert_x, int& insert_y);
void InsertLink(C4RopeElement* from, C4RopeElement* to, int insert_x, int insert_y);
void ResetForceRedirection(C4Real dt);
void SetForceRedirection(const C4Rope* rope, int ox, int oy);
bool SetForceRedirectionByLookAround(const C4Rope* rope, int ox, int oy, C4Real dx, C4Real dy, C4Real l, C4Real angle);
bool Fixed; // Apply rope forces to this element?
C4Real x, y; // pos; ignored if Object != NULL
C4Real oldx, oldy; // position in the previous frame. Used for linking
C4Real vx, vy; // velocity; ignored if Object != NULL
C4Real m; // mass; ignored if Object != NULL
C4Real fx, fy; // force
C4Real rx, ry; // force redirection
C4Real rdt; // force redirection timeout
C4Real fcx, fcy; // force after solve -- for debug output only
C4RopeElement* Next; // next rope element, or NULL
C4RopeElement* Prev; // prev rope element, or NULL
C4RopeLink* FirstLink; // first rope link between this and next, or NULL
C4RopeLink* LastLink; // last rope link between this and prev, or NULL
C4Object* Object; // Connected object. If set, x/y/vx/vy/m are ignored.
int LastContactVertex; // Vertex which most recently had collision with landscape
};
class C4Rope: public C4PropListNumbered
{
public:
C4Rope(C4PropList* Prototype, C4Object* first_obj, C4Object* second_obj, C4Real segment_length, C4DefGraphics* graphics);
~C4Rope();
void Draw(C4TargetFacet& cgo, C4BltTransform* pTransform);
void Execute();
void ClearPointers(C4Object* obj);
C4Real GetSegmentLength() const { return l; }
C4Real GetOuterFriction() const { return mu; }
C4RopeElement* GetFront() const { return Front; }
C4RopeElement* GetBack() const { return Back; }
void SetFront(C4Object* obj, C4Real x, C4Real y) { Front->Object = obj; Front->x = x; Front->y = y; Front->LastContactVertex = -1; }
void SetBack(C4Object* obj, C4Real x, C4Real y) { Back->Object = obj; Back->x = x; Back->y = y; Back->LastContactVertex = -1; }
C4Real GetFrontAutoSegmentation() const { return FrontAutoSegmentation; }
C4Real GetBackAutoSegmentation() const { return BackAutoSegmentation; }
void SetFrontAutoSegmentation(C4Real max) { FrontAutoSegmentation = max; }
void SetBackAutoSegmentation(C4Real max) { BackAutoSegmentation = max; }
bool GetFrontFixed() const { return Front->Fixed; }
bool GetBackFixed() const { return Back->Fixed; }
void SetFrontFixed(bool fixed) { Front->Fixed = fixed; }
void SetBackFixed(bool fixed) { Back->Fixed = fixed; }
void PullFront(C4Real f) { FrontPull = f; }
void PullBack(C4Real f) { BackPull = f; }
private:
C4Real GetL(const C4RopeElement* prev, const C4RopeElement* next) const;
void DoAutoSegmentation(C4RopeElement* fixed, C4RopeElement* first, C4Real max);
void Solve(C4RopeElement* prev, C4RopeElement* next);
// Whether to apply repulsive forces between rope segments.
// TODO: Could be made a property...
static const bool ApplyRepulsive = false;
unsigned int NumIterations; // Number of iterations per frame
const float Width; // Width of rope
C4DefGraphics* Graphics;
int32_t SegmentCount;
C4Real l; // spring length in equilibrium
C4Real k; // spring constant
C4Real mu; // outer friction constant
C4Real eta; // inner friction constant
C4RopeElement* Front;
C4RopeElement* Back;
C4Real FrontAutoSegmentation;
C4Real BackAutoSegmentation;
C4Real FrontPull;
C4Real BackPull;
};
class C4RopeAul: public C4AulScript
{
public:
C4RopeAul();
virtual ~C4RopeAul();
virtual bool Delete() { return false; }
virtual C4PropListStatic* GetPropList() { return RopeDef; }
void InitFunctionMap(C4AulScriptEngine* pEngine);
protected:
C4PropListStatic* RopeDef;
};
class C4RopeList
{
public:
C4RopeList();
void InitFunctionMap(C4AulScriptEngine* pEngine) { RopeAul.InitFunctionMap(pEngine); }
void Execute();
void Draw(C4TargetFacet& cgo, C4BltTransform* pTransform);
C4Rope* CreateRope(C4Object* first_obj, C4Object* second_obj, C4Real segment_length, C4DefGraphics* graphics);
void RemoveRope(C4Rope* rope);
void ClearPointers(C4Object* obj);
private:
C4RopeAul RopeAul;
std::vector<C4Rope*> Ropes;
};
#endif // INC_C4Rope

View File

@ -0,0 +1,117 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2012 Armin Burgmeier
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#include <C4Include.h>
#include <C4Rope.h>
#include <C4AulDefFunc.h>
static C4Void FnRemove(C4Rope* Rope)
{
Game.Ropes.RemoveRope(Rope);
return C4Void();
}
static C4Object* FnGetFront(C4Rope* Rope)
{
return Rope->GetFront()->GetObject();
}
static C4Object* FnGetBack(C4Rope* Rope)
{
return Rope->GetBack()->GetObject();
}
static C4Void FnSetFront(C4Rope* Rope, C4Object* obj, Nillable<int> x, Nillable<int> y)
{
Rope->SetFront(obj, x.IsNil() ? Fix0 : itofix(x), y.IsNil() ? Fix0 : itofix(y));
return C4Void();
}
static C4Void FnSetBack(C4Rope* Rope, C4Object* obj, Nillable<int> x, Nillable<int> y)
{
Rope->SetBack(obj, x.IsNil() ? Fix0 : itofix(x), y.IsNil() ? Fix0 : itofix(y));
return C4Void();
}
static C4Void FnSetFrontAutoSegmentation(C4Rope* Rope, int max)
{
Rope->SetFrontAutoSegmentation(itofix(max));
return C4Void();
}
static C4Void FnSetBackAutoSegmentation(C4Rope* Rope, int max)
{
Rope->SetBackAutoSegmentation(itofix(max));
return C4Void();
}
static C4Void FnSetFrontFixed(C4Rope* Rope, bool fixed)
{
Rope->SetFrontFixed(fixed);
return C4Void();
}
static C4Void FnSetBackFixed(C4Rope* Rope, bool fixed)
{
Rope->SetBackFixed(fixed);
return C4Void();
}
static C4Void FnPullFront(C4Rope* Rope, int force)
{
Rope->PullFront(itofix(force));
return C4Void();
}
static C4Void FnPullBack(C4Rope* Rope, int force)
{
Rope->PullBack(itofix(force));
return C4Void();
}
C4RopeAul::C4RopeAul():
RopeDef(NULL)
{
}
C4RopeAul::~C4RopeAul()
{
delete RopeDef;
}
void C4RopeAul::InitFunctionMap(C4AulScriptEngine* pEngine)
{
delete RopeDef;
RopeDef = C4PropList::NewStatic(NULL, NULL, ::Strings.RegString("Rope"));
RopeDef->SetName("Rope");
pEngine->RegisterGlobalConstant("Rope", C4VPropList(RopeDef));
Reg2List(pEngine);
::AddFunc(this, "Remove", FnRemove);
::AddFunc(this, "GetFront", FnGetFront);
::AddFunc(this, "GetBack", FnGetBack);
::AddFunc(this, "SetFront", FnSetFront);
::AddFunc(this, "SetBack", FnSetBack);
::AddFunc(this, "SetFrontAutoSegmentation", FnSetFrontAutoSegmentation);
::AddFunc(this, "SetBackAutoSegmentation", FnSetBackAutoSegmentation);
::AddFunc(this, "SetFrontFixed", FnSetFrontFixed);
::AddFunc(this, "SetBackFixed", FnSetBackFixed);
::AddFunc(this, "PullFront", FnPullFront);
::AddFunc(this, "PullBack", FnPullBack);
RopeDef->Freeze();
}

View File

@ -25,6 +25,7 @@
#include <C4Object.h>
#include <C4Effect.h>
#include <C4DefList.h>
#include <C4Rope.h>
inline const static char *FnStringPar(C4String *pString)
{
@ -98,6 +99,14 @@ public:
NeedObjectContext(const char *function) : C4AulExecError(FormatString("%s: must be called from object context", function).getData()) {}
};
// Other functions are callable in rope context only.
// This exception gets thrown if they are called from anywhere else.
class NeedRopeContext : public C4AulExecError
{
public:
NeedRopeContext(const char *function) : C4AulExecError(FormatString("%s: must be called from rope context", function).getData()) {}
};
// Then there's functions that don't care, but need either defn or object context.
// This exception gets thrown if those are called from global scripts.
class NeedNonGlobalContext : public C4AulExecError
@ -313,6 +322,27 @@ public C4AulDefFuncHelper { \
Func pFunc; \
}; \
template <typename RType LIST(N, TYPENAMES)> \
class C4AulDefRopeFunc##N: \
public C4AulDefFuncHelper { \
public: \
/* A pointer to the function which this class wraps */ \
typedef RType (*Func)(C4Rope * LIST(N, PARS)); \
virtual int GetParCount() { return N; } \
virtual C4V_Type GetRetType() \
{ return C4ValueConv<RType>::Type(); } \
/* Constructor, using the base class to create the ParType array */ \
C4AulDefRopeFunc##N(C4AulScript *pOwner, const char *pName, Func pFunc, bool Public): \
C4AulDefFuncHelper(pOwner, pName, Public LIST(N, CONV_TYPE)), pFunc(pFunc) { } \
/* Extracts the parameters from C4Values and wraps the return value in a C4Value */ \
virtual C4Value Exec(C4PropList * _this, C4Value pPars[], bool fPassErrors) \
{ \
C4Rope * Rope; if (!_this || !(Rope = dynamic_cast<C4Rope*>(_this))) throw new NeedRopeContext(GetName()); \
return C4ValueConv<RType>::ToC4V(pFunc(Rope LIST(N, CONV_FROM_C4V))); \
} \
protected: \
Func pFunc; \
}; \
template <typename RType LIST(N, TYPENAMES)> \
inline void AddFunc(C4AulScript * pOwner, const char * Name, RType (*pFunc)(C4PropList * LIST(N, PARS)), bool Public=true) \
{ \
new C4AulDefFunc##N<RType LIST(N, PARS)>(pOwner, Name, pFunc, Public); \
@ -321,6 +351,11 @@ template <typename RType LIST(N, TYPENAMES)> \
inline void AddFunc(C4AulScript * pOwner, const char * Name, RType (*pFunc)(C4Object * LIST(N, PARS)), bool Public=true) \
{ \
new C4AulDefObjectFunc##N<RType LIST(N, PARS)>(pOwner, Name, pFunc, Public); \
} \
template <typename RType LIST(N, TYPENAMES)> \
inline void AddFunc(C4AulScript * pOwner, const char * Name, RType (*pFunc)(C4Rope * LIST(N, PARS)), bool Public=true) \
{ \
new C4AulDefRopeFunc##N<RType LIST(N, PARS)>(pOwner, Name, pFunc, Public); \
}
TEMPLATE(0)