71 |
double radius; |
double radius; |
72 |
}; |
}; |
73 |
} |
} |
74 |
|
|
75 |
//---------------------------------------- |
//---------------------------------------- |
76 |
// Sphere |
// Sphere |
77 |
//---------------------------------------- |
//---------------------------------------- |
125 |
} |
} |
126 |
|
|
127 |
RubberBand::RubberBand (Actor *a1, Actor *a2, double strength_, double length_) |
RubberBand::RubberBand (Actor *a1, Actor *a2, double strength_, double length_) |
128 |
: actor(a1), actor2(a2), stone(0), model(0) |
: actor(a1), actor2(a2), stone(0), model(0) |
129 |
, strength(strength_), length(length_) |
, strength(strength_), length(length_) |
130 |
{ |
{ |
131 |
assert(actor); |
assert(actor); |
132 |
assert(length >= 0); |
assert(length >= 0); |
134 |
} |
} |
135 |
|
|
136 |
RubberBand::RubberBand (Actor *a1, Stone *st, double strength_, double length_) |
RubberBand::RubberBand (Actor *a1, Stone *st, double strength_, double length_) |
137 |
: actor(a1), actor2(0), stone(st), model(0) |
: actor(a1), actor2(0), stone(st), model(0) |
138 |
, strength(strength_), length(length_) |
, strength(strength_), length(length_) |
139 |
{ |
{ |
140 |
assert(actor); |
assert(actor); |
141 |
assert(length >= 0); |
assert(length >= 0); |
911 |
} |
} |
912 |
|
|
913 |
|
|
914 |
|
namespace |
915 |
|
{ |
916 |
//---------------------------------------- |
//---------------------------------------- |
917 |
// Layer |
// Layer |
918 |
// |
// |
919 |
// Changes to a layer are cached and only applied at the end of a |
// Changes to a layer are cached and only applied at the end of a |
920 |
// tick. [### not implemented] |
// tick. [### not implemented] |
921 |
//---------------------------------------- |
//---------------------------------------- |
922 |
template <class T> |
template <class T> |
923 |
class Layer { |
class Layer { |
924 |
T *defaultval; |
T *defaultval; |
925 |
public: |
public: |
926 |
Layer(T* deflt = 0) : defaultval(deflt) {} |
Layer(T* deflt = 0) : defaultval(deflt) {} |
927 |
T *get(GridPos p) { |
virtual ~Layer() {} |
|
if (Field *f=level->get_field(p)) |
|
|
return raw_get(*f); |
|
|
else |
|
|
return defaultval; |
|
|
} |
|
928 |
|
|
929 |
T *yield(GridPos p) { |
T *get(GridPos p) { |
930 |
if (Field *f=level->get_field(p)) { |
if (Field *f=level->get_field(p)) |
931 |
T *x = raw_get(*f); |
return raw_get(*f); |
932 |
if (x) { |
else |
933 |
raw_set(*f, 0); |
return defaultval; |
934 |
x->removal(); |
} |
|
} |
|
|
return x; |
|
|
} else |
|
|
return defaultval; |
|
|
} |
|
935 |
|
|
936 |
void set(GridPos p, T *x) { |
T *yield(GridPos p) { |
|
if (x) { |
|
937 |
if (Field *f=level->get_field(p)) { |
if (Field *f=level->get_field(p)) { |
938 |
dispose(raw_get(*f)); |
T *x = raw_get(*f); |
939 |
raw_set(*f, x); |
if (x) { |
940 |
x->creation(p); |
raw_set(*f, 0); |
941 |
} |
x->removal(); |
942 |
else |
} |
943 |
dispose(x); |
return x; |
944 |
|
} else |
945 |
|
return defaultval; |
946 |
} |
} |
|
} |
|
|
void kill(GridPos p) { dispose(yield(p)); } |
|
947 |
|
|
948 |
virtual T* raw_get (Field &) = 0; |
void set(GridPos p, T *x) { |
949 |
virtual void raw_set (Field &, T *) = 0; |
if (x) { |
950 |
|
if (Field *f=level->get_field(p)) { |
951 |
|
dispose(raw_get(*f)); |
952 |
|
raw_set(*f, x); |
953 |
|
x->creation(p); |
954 |
|
} |
955 |
|
else |
956 |
|
dispose(x); |
957 |
|
} |
958 |
|
} |
959 |
|
void kill(GridPos p) { dispose(yield(p)); } |
960 |
|
|
961 |
private: |
virtual T* raw_get (Field &) = 0; |
962 |
void dispose(T *x) { if (x) DisposeObject(x); } |
virtual void raw_set (Field &, T *) = 0; |
|
}; |
|
963 |
|
|
964 |
//---------------------------------------- |
private: |
965 |
// Floor manipulation. |
virtual void dispose(T *x) { if (x) DisposeObject(x); } |
966 |
//---------------------------------------- |
}; |
967 |
|
|
968 |
namespace |
/* |
969 |
{ |
** Floor layer |
970 |
|
*/ |
971 |
class FloorLayer : public Layer<Floor> { |
class FloorLayer : public Layer<Floor> { |
972 |
private: |
private: |
973 |
Floor *raw_get (Field &f) { return f.floor; } |
Floor *raw_get (Field &f) { return f.floor; } |
974 |
void raw_set (Field &f, Floor *x) { f.floor = x;} |
void raw_set (Field &f, Floor *x) { f.floor = x;} |
975 |
}; |
}; |
|
FloorLayer fl_layer; |
|
|
} |
|
976 |
|
|
|
void world::KillFloor(GridPos p) {fl_layer.kill(p);} |
|
|
Floor *world::GetFloor(GridPos p) {return fl_layer.get(p);} |
|
|
void world::SetFloor(GridPos p, Floor* st) {fl_layer.set(p,st);} |
|
977 |
|
|
978 |
//---------------------------------------- |
/* |
979 |
// Stone manipulation. |
** Item layer |
980 |
//---------------------------------------- |
*/ |
981 |
|
class ItemLayer : public Layer<Item> { |
982 |
namespace |
private: |
983 |
{ |
Item *raw_get (Field &f) { return f.item; } |
984 |
/* This stone is used as the virtual border of the playing area. |
void raw_set (Field &f, Item *x) { f.item = x;} |
|
It is immovable and indestructible and makes sure the player's |
|
|
marble cannot leave the level. */ |
|
|
class BorderStone : public Stone { |
|
|
public: |
|
|
BorderStone() : Stone("borderstone") {} |
|
|
Object *clone() { return this; } |
|
|
void dispose() {} |
|
985 |
}; |
}; |
986 |
|
|
987 |
BorderStone borderstone; |
/* |
988 |
|
** Stone layer |
989 |
|
*/ |
990 |
class StoneLayer : public Layer<Stone> { |
class StoneLayer : public Layer<Stone> |
991 |
|
{ |
992 |
public: |
public: |
993 |
StoneLayer() : Layer<Stone>(&borderstone) {} |
StoneLayer() : Layer<Stone>(&borderstone) {} |
994 |
private: |
private: |
995 |
Stone *raw_get (Field &f) { return f.stone; } |
Stone *raw_get (Field &f) { return f.stone; } |
996 |
void raw_set (Field &f, Stone *st) { f.stone = st;} |
void raw_set (Field &f, Stone *st) { f.stone = st;} |
997 |
|
void dispose (Stone *st) { |
998 |
|
if (st) { |
999 |
|
KillRubberBands(st); |
1000 |
|
DisposeObject(st); |
1001 |
|
} |
1002 |
|
} |
1003 |
|
|
1004 |
|
/* This stone is used as the virtual border of the playing area. |
1005 |
|
It is immovable and indestructible and makes sure the player's |
1006 |
|
marble cannot leave the level. */ |
1007 |
|
class BorderStone : public Stone { |
1008 |
|
public: |
1009 |
|
BorderStone() : Stone("borderstone") {} |
1010 |
|
Object *clone() { return this; } |
1011 |
|
void dispose() {} |
1012 |
|
}; |
1013 |
|
|
1014 |
|
BorderStone borderstone; |
1015 |
}; |
}; |
1016 |
|
|
1017 |
StoneLayer st_layer; |
} |
1018 |
|
|
1019 |
|
namespace |
1020 |
|
{ |
1021 |
|
FloorLayer fl_layer; |
1022 |
|
ItemLayer it_layer; |
1023 |
|
StoneLayer st_layer; |
1024 |
vector<GridPos> changed_stones; |
vector<GridPos> changed_stones; |
1025 |
|
} |
1026 |
|
|
1027 |
|
|
1028 |
|
//---------------------------------------- |
1029 |
|
// Floor manipulation. |
1030 |
|
//---------------------------------------- |
1031 |
|
|
1032 |
|
void world::KillFloor(GridPos p) {fl_layer.kill(p);} |
1033 |
|
Floor *world::GetFloor(GridPos p) {return fl_layer.get(p);} |
1034 |
|
void world::SetFloor(GridPos p, Floor* st) {fl_layer.set(p,st);} |
1035 |
|
|
1036 |
|
//---------------------------------------- |
1037 |
|
// Stone manipulation. |
1038 |
|
//---------------------------------------- |
1039 |
|
|
1040 |
|
namespace |
1041 |
|
{ |
1042 |
void stone_change(GridPos p) { |
void stone_change(GridPos p) { |
1043 |
Stone *st = GetStone(p); |
Stone *st = GetStone(p); |
1044 |
if (Item *it = GetItem(p)) |
if (Item *it = GetItem(p)) |
1050 |
} |
} |
1051 |
|
|
1052 |
|
|
1053 |
void world::KillStone(GridPos p) { |
void |
1054 |
|
world::KillStone(GridPos p) |
1055 |
|
{ |
1056 |
st_layer.kill(p); |
st_layer.kill(p); |
1057 |
// stone_change(p); |
// stone_change(p); |
1058 |
changed_stones.push_back(p); |
changed_stones.push_back(p); |
1113 |
// Item manipulation. |
// Item manipulation. |
1114 |
//---------------------------------------- |
//---------------------------------------- |
1115 |
|
|
|
namespace |
|
|
{ |
|
|
class ItemLayer : public Layer<Item> { |
|
|
private: |
|
|
Item *raw_get (Field &f) { return f.item; } |
|
|
void raw_set (Field &f, Item *x) { f.item = x;} |
|
|
}; |
|
|
ItemLayer it_layer; |
|
|
} |
|
|
|
|
1116 |
void world::KillItem(GridPos p) { |
void world::KillItem(GridPos p) { |
1117 |
laser::MaybeRecalcLight(p); |
laser::MaybeRecalcLight(p); |
1118 |
it_layer.kill(p); |
it_layer.kill(p); |