Subversion Repositories spacemission

Rev

Rev 4 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4 Rev 6
1
unit DXSprite;
1
unit DXSprite;
2
 
2
 
3
interface
3
interface
4
 
4
 
5
{$INCLUDE DelphiXcfg.inc}
5
{$INCLUDE DelphiXcfg.inc}
6
 
6
 
7
uses
7
uses
8
  Windows, SysUtils, Classes, Graphics, DXClass, DXDraws,
8
  Windows, SysUtils, Classes, Graphics, DXClass, DXDraws,
9
  {$IFDEF VER9UP} Types,{$ENDIF}
9
  {$IFDEF VER9UP} Types,{$ENDIF}
10
{$IFDEF StandardDX}
10
{$IFDEF StandardDX}
11
  DirectDraw;
11
  DirectDraw;
12
{$ELSE}
12
{$ELSE}
13
  DirectX;
13
  DirectX;
14
{$ENDIF}
14
{$ENDIF}
15
 
15
 
16
type
16
type
17
 
17
 
18
  {  ESpriteError  }
18
  {  ESpriteError  }
19
 
19
 
20
  ESpriteError = class(Exception);
20
  ESpriteError = class(Exception);
21
 
21
 
22
  {  TSprite  }
22
  {  TSprite  }
23
 
23
 
24
  TSpriteEngine = class;
24
  TSpriteEngine = class;
25
 
25
 
26
  TSprite = class;
26
  TSprite = class;
27
  TCollisionEvent = procedure(Sender: TObject; var Done: Boolean) of object;
27
  TCollisionEvent = procedure(Sender: TObject; var Done: Boolean) of object;
28
  TMoveEvent = procedure(Sender: TObject; var MoveCount: Integer) of object;
28
  TMoveEvent = procedure(Sender: TObject; var MoveCount: Integer) of object;
29
  TDrawEvent = procedure(Sender: TObject) of object;
29
  TDrawEvent = procedure(Sender: TObject) of object;
30
  TGetImage = procedure(Sender: TObject; var Image: TPictureCollectionItem) of object;
30
  TGetImage = procedure(Sender: TObject; var Image: TPictureCollectionItem) of object;
31
 
31
 
32
  TSprite = class(TPersistent)
32
  TSprite = class(TPersistent)
33
  private
33
  private
34
    FEngine: TSpriteEngine;
34
    FEngine: TSpriteEngine;
35
    FParent: TSprite;
35
    FParent: TSprite;
36
    FList: TList;
36
    FList: TList;
37
    FDeaded: Boolean;
37
    FDeaded: Boolean;
38
    FDrawList: TList;
38
    FDrawList: TList;
39
    FCollisioned: Boolean;
39
    FCollisioned: Boolean;
40
    FMoved: Boolean;
40
    FMoved: Boolean;
41
    FVisible: Boolean;
41
    FVisible: Boolean;
42
    FX: Double;
42
    FX: Double;
43
    FY: Double;
43
    FY: Double;
44
    FZ: Integer;
44
    FZ: Integer;
45
    FWidth: Integer;
45
    FWidth: Integer;
46
    FHeight: Integer;
46
    FHeight: Integer;
47
    {$IFDEF Ver4Up}
47
    {$IFDEF Ver4Up}
48
    FSelected: Boolean;
48
    FSelected: Boolean;
49
    FGroupNumber: Integer;
49
    FGroupNumber: Integer;
50
    {$ENDIF}
50
    {$ENDIF}
51
    FCaption: string;
51
    FCaption: string;
52
    FTag: Integer;
52
    FTag: Integer;
53
 
53
 
54
    FDXImageList: TCustomDXImageList;
54
    FDXImageList: TCustomDXImageList;
55
    FDXImage: TPictureCollectionItem;
55
    FDXImage: TPictureCollectionItem;
56
    FDXImageName: string;
56
    FDXImageName: string;
57
 
57
 
58
    FOnDraw: TDrawEvent;
58
    FOnDraw: TDrawEvent;
59
    FOnMove: TMoveEvent;
59
    FOnMove: TMoveEvent;
60
    FOnCollision: TCollisionEvent;
60
    FOnCollision: TCollisionEvent;
61
    FOnGetImage: TGetImage;
61
    FOnGetImage: TGetImage;
62
    procedure Add(Sprite: TSprite);
62
    procedure Add(Sprite: TSprite);
63
    procedure Remove(Sprite: TSprite);
63
    procedure Remove(Sprite: TSprite);
64
    procedure AddDrawList(Sprite: TSprite);
64
    procedure AddDrawList(Sprite: TSprite);
65
    procedure Collision2;
65
    procedure Collision2;
66
    procedure Draw; {$IFDEF VER9UP}inline;{$ENDIF}
66
    procedure Draw; {$IFDEF VER9UP}inline;{$ENDIF}
67
    function GetClientRect: TRect;
67
    function GetClientRect: TRect;
68
    function GetCount: Integer;
68
    function GetCount: Integer;
69
    function GetItem(Index: Integer): TSprite;
69
    function GetItem(Index: Integer): TSprite;
70
    function GetWorldX: Double; {$IFDEF VER9UP}inline;{$ENDIF}
70
    function GetWorldX: Double; {$IFDEF VER9UP}inline;{$ENDIF}
71
    function GetWorldY: Double; {$IFDEF VER9UP}inline;{$ENDIF}
71
    function GetWorldY: Double; {$IFDEF VER9UP}inline;{$ENDIF}
72
    procedure SetZ(Value: Integer);
72
    procedure SetZ(Value: Integer);
73
  protected
73
  protected
74
    procedure DoCollision(Sprite: TSprite; var Done: Boolean); virtual;
74
    procedure DoCollision(Sprite: TSprite; var Done: Boolean); virtual;
75
    procedure DoDraw; virtual;
75
    procedure DoDraw; virtual;
76
    procedure DoMove(MoveCount: Integer); virtual;
76
    procedure DoMove(MoveCount: Integer); virtual;
77
    function GetBoundsRect: TRect; virtual;
77
    function GetBoundsRect: TRect; virtual;
78
    function TestCollision(Sprite: TSprite): Boolean; virtual;
78
    function TestCollision(Sprite: TSprite): Boolean; virtual;
79
    {$IFDEF Ver4Up}
79
    {$IFDEF Ver4Up}
80
    procedure SetGroupNumber(AGroupNumber: Integer); virtual;
80
    procedure SetGroupNumber(AGroupNumber: Integer); virtual;
81
    procedure SetSelected(ASelected: Boolean); virtual;
81
    procedure SetSelected(ASelected: Boolean); virtual;
82
    {$ENDIF}
82
    {$ENDIF}
83
  public
83
  public
84
    constructor Create(AParent: TSprite); virtual;
84
    constructor Create(AParent: TSprite); virtual;
85
    destructor Destroy; override;
85
    destructor Destroy; override;
86
    procedure Clear;
86
    procedure Clear;
87
    function Collision: Integer;
87
    function Collision: Integer;
88
    procedure Dead;
88
    procedure Dead;
89
    procedure Move(MoveCount: Integer);
89
    procedure Move(MoveCount: Integer);
90
    procedure ReAnimate(MoveCount: Integer); virtual;
90
    procedure ReAnimate(MoveCount: Integer); virtual;
91
    function GetSpriteAt(X, Y: Integer): TSprite;
91
    function GetSpriteAt(X, Y: Integer): TSprite;
92
    property BoundsRect: TRect read GetBoundsRect;
92
    property BoundsRect: TRect read GetBoundsRect;
93
    property ClientRect: TRect read GetClientRect;
93
    property ClientRect: TRect read GetClientRect;
94
    property Count: Integer read GetCount;
94
    property Count: Integer read GetCount;
95
    property Engine: TSpriteEngine read FEngine;
95
    property Engine: TSpriteEngine read FEngine;
96
    property Items[Index: Integer]: TSprite read GetItem; default;
96
    property Items[Index: Integer]: TSprite read GetItem; default;
97
    property Deaded: Boolean read FDeaded;
97
    property Deaded: Boolean read FDeaded;
98
    property Parent: TSprite read FParent;
98
    property Parent: TSprite read FParent;
99
    property WorldX: Double read GetWorldX;
99
    property WorldX: Double read GetWorldX;
100
    property WorldY: Double read GetWorldY;
100
    property WorldY: Double read GetWorldY;
101
    // Group handling support
101
    // Group handling support
102
    {$IFDEF Ver4Up}  // if GroupNumber < 0 then no group is assigned
102
    {$IFDEF Ver4Up}  // if GroupNumber < 0 then no group is assigned
103
    property GroupNumber: Integer read FGroupNumber write SetGroupNumber;
103
    property GroupNumber: Integer read FGroupNumber write SetGroupNumber;
104
    property Selected: Boolean read FSelected write SetSelected;
104
    property Selected: Boolean read FSelected write SetSelected;
105
    {$ENDIF}
105
    {$ENDIF}
106
    procedure Assign(Source: TPersistent); override;
106
    procedure Assign(Source: TPersistent); override;
107
  published
107
  published
108
    property Height: Integer read FHeight write FHeight;
108
    property Height: Integer read FHeight write FHeight;
109
    property Moved: Boolean read FMoved write FMoved;
109
    property Moved: Boolean read FMoved write FMoved;
110
    property Visible: Boolean read FVisible write FVisible;
110
    property Visible: Boolean read FVisible write FVisible;
111
    property Width: Integer read FWidth write FWidth;
111
    property Width: Integer read FWidth write FWidth;
112
    property X: Double read FX write FX;
112
    property X: Double read FX write FX;
113
    property Y: Double read FY write FY;
113
    property Y: Double read FY write FY;
114
    property Z: Integer read FZ write SetZ;
114
    property Z: Integer read FZ write SetZ;
115
    property Collisioned: Boolean read FCollisioned write FCollisioned;
115
    property Collisioned: Boolean read FCollisioned write FCollisioned;
116
    property Tag: Integer read FTag write FTag;
116
    property Tag: Integer read FTag write FTag;
117
    property Caption: string read FCaption write FCaption;
117
    property Caption: string read FCaption write FCaption;
118
 
118
 
119
    property DXImageList: TCustomDXImageList read FDXImageList write FDXImageList;
119
    property DXImageList: TCustomDXImageList read FDXImageList write FDXImageList;
120
    property DXImageName: string read FDXImageName write FDXImageName;
120
    property DXImageName: string read FDXImageName write FDXImageName;
121
 
121
 
122
    property OnDraw: TDrawEvent read FOnDraw write FOnDraw;
122
    property OnDraw: TDrawEvent read FOnDraw write FOnDraw;
123
    property OnMove: TMoveEvent read FOnMove write FOnMove;
123
    property OnMove: TMoveEvent read FOnMove write FOnMove;
124
    property OnCollision: TCollisionEvent read FOnCollision write FOnCollision;
124
    property OnCollision: TCollisionEvent read FOnCollision write FOnCollision;
125
    property OnGetImage: TGetImage read FOnGetImage write FOnGetImage;
125
    property OnGetImage: TGetImage read FOnGetImage write FOnGetImage;
126
  end;
126
  end;
127
 
127
 
128
  TSpriteClass = class of TSprite;
128
  TSpriteClass = class of TSprite;
129
 
129
 
130
  {  TImageSprite  }
130
  {  TImageSprite  }
131
 
131
 
132
  TImageSprite = class(TSprite)
132
  TImageSprite = class(TSprite)
133
  private
133
  private
134
    FAnimCount: Integer;
134
    FAnimCount: Integer;
135
    FAnimLooped: Boolean;
135
    FAnimLooped: Boolean;
136
    FAnimPos: Double;
136
    FAnimPos: Double;
137
    FAnimSpeed: Double;
137
    FAnimSpeed: Double;
138
    FAnimStart: Integer;
138
    FAnimStart: Integer;
139
    FPixelCheck: Boolean;
139
    FPixelCheck: Boolean;
140
    FTile: Boolean;
140
    FTile: Boolean;
141
    FTransparent: Boolean;
141
    FTransparent: Boolean;
142
    FAngle: Single;
142
    FAngle: Single;
143
    FAlpha: Integer;
143
    FAlpha: Integer;
144
    FBlendMode: TRenderType;
144
    FBlendMode: TRenderType;
145
    FCenterX: Double;
145
    FCenterX: Double;
146
    FCenterY: Double;
146
    FCenterY: Double;
147
    FBlurImageArr: TBlurImageArr;
147
    FBlurImageArr: TBlurImageArr;
148
    FBlurImage: Boolean;
148
    FBlurImage: Boolean;
149
    FMirrorFlip: TRenderMirrorFlipSet;
149
    FMirrorFlip: TRenderMirrorFlipSet;
150
    FTextureFilter: TD2DTextureFilter;
150
    FTextureFilter: TD2DTextureFilter;
151
    function GetDrawImageIndex: Integer;
151
    function GetDrawImageIndex: Integer;
152
    function GetDrawRect: TRect;
152
    function GetDrawRect: TRect;
153
    function ImageCollisionTest(suf1, suf2: TDirectDrawSurface;
153
    function ImageCollisionTest(suf1, suf2: TDirectDrawSurface;
154
      const rect1, rect2: TRect; x1, y1, x2, y2: Integer;
154
      const rect1, rect2: TRect; x1, y1, x2, y2: Integer;
155
      DoPixelCheck: Boolean): Boolean;
155
      DoPixelCheck: Boolean): Boolean;
156
    function StoreCenterX: Boolean;
156
    function StoreCenterX: Boolean;
157
    function StoreCenterY: Boolean;
157
    function StoreCenterY: Boolean;
158
    function StoreAlpha: Boolean;
158
    function StoreAlpha: Boolean;
159
    procedure SetBlurImage(const Value: Boolean);
159
    procedure SetBlurImage(const Value: Boolean);
160
    procedure SetBlurImageArr(const Value: TBlurImageArr);
160
    procedure SetBlurImageArr(const Value: TBlurImageArr);
161
    function GetImage: TPictureCollectionItem;
161
    function GetImage: TPictureCollectionItem;
162
    procedure SetMirrorFlip(const Value: TRenderMirrorFlipSet);
162
    procedure SetMirrorFlip(const Value: TRenderMirrorFlipSet);
163
    procedure ReadMirrorFlip(Reader: TReader);
163
    procedure ReadMirrorFlip(Reader: TReader);
164
    procedure WriteMirrorFlip(Writer: TWriter);
164
    procedure WriteMirrorFlip(Writer: TWriter);
165
  protected
165
  protected
166
    {accessed methods}
166
    {accessed methods}
167
    procedure ReadAlpha(Reader: TReader);
167
    procedure ReadAlpha(Reader: TReader);
168
    procedure ReadAngle(Reader: TReader);
168
    procedure ReadAngle(Reader: TReader);
169
    procedure ReadAnimCount(Reader: TReader);
169
    procedure ReadAnimCount(Reader: TReader);
170
    procedure ReadAnimLooped(Reader: TReader);
170
    procedure ReadAnimLooped(Reader: TReader);
171
    procedure ReadAnimPos(Reader: TReader);
171
    procedure ReadAnimPos(Reader: TReader);
172
    procedure ReadAnimSpeed(Reader: TReader);
172
    procedure ReadAnimSpeed(Reader: TReader);
173
    procedure ReadAnimStart(Reader: TReader);
173
    procedure ReadAnimStart(Reader: TReader);
174
    procedure ReadBlendMode(Reader: TReader);
174
    procedure ReadBlendMode(Reader: TReader);
175
    procedure ReadCenterX(Reader: TReader);
175
    procedure ReadCenterX(Reader: TReader);
176
    procedure ReadCenterY(Reader: TReader);
176
    procedure ReadCenterY(Reader: TReader);
177
    procedure ReadPixelCheck(Reader: TReader);
177
    procedure ReadPixelCheck(Reader: TReader);
178
    procedure ReadTile(Reader: TReader);
178
    procedure ReadTile(Reader: TReader);
179
    procedure ReadBlurImage(Reader: TReader);
179
    procedure ReadBlurImage(Reader: TReader);
180
    procedure ReadTextureFilter(Reader: TReader);
180
    procedure ReadTextureFilter(Reader: TReader);
181
    procedure WriteAlpha(Writer: TWriter);
181
    procedure WriteAlpha(Writer: TWriter);
182
    procedure WriteAngle(Writer: TWriter);
182
    procedure WriteAngle(Writer: TWriter);
183
    procedure WriteAnimCount(Writer: TWriter);
183
    procedure WriteAnimCount(Writer: TWriter);
184
    procedure WriteAnimLooped(Writer: TWriter);
184
    procedure WriteAnimLooped(Writer: TWriter);
185
    procedure WriteAnimPos(Writer: TWriter);
185
    procedure WriteAnimPos(Writer: TWriter);
186
    procedure WriteAnimSpeed(Writer: TWriter);
186
    procedure WriteAnimSpeed(Writer: TWriter);
187
    procedure WriteAnimStart(Writer: TWriter);
187
    procedure WriteAnimStart(Writer: TWriter);
188
    procedure WriteBlendMode(Writer: TWriter);
188
    procedure WriteBlendMode(Writer: TWriter);
189
    procedure WriteCenterX(Writer: TWriter);
189
    procedure WriteCenterX(Writer: TWriter);
190
    procedure WriteCenterY(Writer: TWriter);
190
    procedure WriteCenterY(Writer: TWriter);
191
    procedure WritePixelCheck(Writer: TWriter);
191
    procedure WritePixelCheck(Writer: TWriter);
192
    procedure WriteTile(Writer: TWriter);
192
    procedure WriteTile(Writer: TWriter);
193
    procedure WriteBlurImage(Writer: TWriter);
193
    procedure WriteBlurImage(Writer: TWriter);
194
    procedure WriteTextureFilter(Writer: TWriter);
194
    procedure WriteTextureFilter(Writer: TWriter);
195
    {own store of properties}
195
    {own store of properties}
196
    procedure DefineProperties(Filer: TFiler); override;
196
    procedure DefineProperties(Filer: TFiler); override;
197
    procedure LoadImage; virtual;
197
    procedure LoadImage; virtual;
198
    procedure DoDraw; override;
198
    procedure DoDraw; override;
199
    procedure DoMove(MoveCount: Integer); override;
199
    procedure DoMove(MoveCount: Integer); override;
200
    function GetBoundsRect: TRect; override;
200
    function GetBoundsRect: TRect; override;
201
    function TestCollision(Sprite: TSprite): Boolean; override;
201
    function TestCollision(Sprite: TSprite): Boolean; override;
202
    procedure SetImage(AImage: TPictureCollectionItem); virtual;
202
    procedure SetImage(AImage: TPictureCollectionItem); virtual;
203
  public
203
  public
204
    constructor Create(AParent: TSprite); override;
204
    constructor Create(AParent: TSprite); override;
205
    procedure Assign(Source: TPersistent); override;
205
    procedure Assign(Source: TPersistent); override;
206
    procedure ReAnimate(MoveCount: Integer); override;
206
    procedure ReAnimate(MoveCount: Integer); override;
207
    property Image: TPictureCollectionItem read GetImage write SetImage;
207
    property Image: TPictureCollectionItem read GetImage write SetImage;
208
    property BlurImageArr: TBlurImageArr read FBlurImageArr write SetBlurImageArr;
208
    property BlurImageArr: TBlurImageArr read FBlurImageArr write SetBlurImageArr;
209
    {un-published property}
209
    {un-published property}
210
    property BlendMode: TRenderType read FBlendMode write FBlendMode default rtDraw;
210
    property BlendMode: TRenderType read FBlendMode write FBlendMode default rtDraw;
211
    property Angle: Single read FAngle write FAngle stored StoreAlpha;
211
    property Angle: Single read FAngle write FAngle stored StoreAlpha;
212
    property Alpha: Integer read FAlpha write FAlpha default $FF;
212
    property Alpha: Integer read FAlpha write FAlpha default $FF;
213
    property CenterX: Double read FCenterX write FCenterX stored StoreCenterX;
213
    property CenterX: Double read FCenterX write FCenterX stored StoreCenterX;
214
    property CenterY: Double read FCenterY write FCenterY stored StoreCenterY;
214
    property CenterY: Double read FCenterY write FCenterY stored StoreCenterY;
215
    property AnimCount: Integer read FAnimCount write FAnimCount default 0;
215
    property AnimCount: Integer read FAnimCount write FAnimCount default 0;
216
    property AnimLooped: Boolean read FAnimLooped write FAnimLooped default False;
216
    property AnimLooped: Boolean read FAnimLooped write FAnimLooped default False;
217
    property AnimPos: Double read FAnimPos write FAnimPos;
217
    property AnimPos: Double read FAnimPos write FAnimPos;
218
    property AnimSpeed: Double read FAnimSpeed write FAnimSpeed;
218
    property AnimSpeed: Double read FAnimSpeed write FAnimSpeed;
219
    property AnimStart: Integer read FAnimStart write FAnimStart default 0;
219
    property AnimStart: Integer read FAnimStart write FAnimStart default 0;
220
    property PixelCheck: Boolean read FPixelCheck write FPixelCheck default False;
220
    property PixelCheck: Boolean read FPixelCheck write FPixelCheck default False;
221
    property Tile: Boolean read FTile write FTile default False;
221
    property Tile: Boolean read FTile write FTile default False;
222
    property BlurImage: Boolean read FBlurImage write SetBlurImage default False;
222
    property BlurImage: Boolean read FBlurImage write SetBlurImage default False;
223
    property MirrorFlip: TRenderMirrorFlipSet read FMirrorFlip write SetMirrorFlip default [];
223
    property MirrorFlip: TRenderMirrorFlipSet read FMirrorFlip write SetMirrorFlip default [];
224
    property TextureFilter: TD2DTextureFilter read FTextureFilter write FTextureFilter default D2D_POINT;
224
    property TextureFilter: TD2DTextureFilter read FTextureFilter write FTextureFilter default D2D_POINT;
225
  published
225
  published
226
    property DXImageList;
226
    property DXImageList;
227
    property DXImageName;
227
    property DXImageName;
228
 
228
 
229
    property OnDraw;
229
    property OnDraw;
230
    property OnMove;
230
    property OnMove;
231
    property OnCollision;
231
    property OnCollision;
232
    property OnGetImage;
232
    property OnGetImage;
233
  end;
233
  end;
234
 
234
 
235
  {  TImageSpriteEx  }
235
  {  TImageSpriteEx  }
236
 
236
 
237
  TImageSpriteEx = class(TImageSprite)
237
  TImageSpriteEx = class(TImageSprite)
238
  end{$IFDEF VER9UP}deprecated{$IFDEF VER14UP} 'Use for backward compatibility only or replace by TImageSprite instead...'{$ENDIF}{$ENDIF};
238
  end{$IFDEF VER9UP}deprecated{$IFDEF VER14UP} 'Use for backward compatibility only or replace by TImageSprite instead...'{$ENDIF}{$ENDIF};
239
 
239
 
240
  {  TBackgroundSprite  }
240
  {  TBackgroundSprite  }
241
 
241
 
242
  PMapType = ^TMapType;
242
  PMapType = ^TMapType;
243
  TMapType = packed record
243
  TMapType = packed record
244
    MapChip: Integer; {image chip as number}
244
    MapChip: Integer; {image chip as number}
245
    //ImageName: string[127];
245
    //ImageName: string[127];
246
    CollisionChip: Boolean; {is collision brick}
246
    CollisionChip: Boolean; {is collision brick}
247
    CollisionRect: TRect; {dirty vollision area, can be smaller or bigger than silhouette}
247
    CollisionRect: TRect; {dirty vollision area, can be smaller or bigger than silhouette}
248
    Overlap: Integer; {for pulse image, like zoom etc.}
248
    Overlap: Integer; {for pulse image, like zoom etc.}
249
    AnimLooped: Boolean; {chip can be live}
249
    AnimLooped: Boolean; {chip can be live}
250
    AnimStart, AnimCount: Integer;
250
    AnimStart, AnimCount: Integer;
251
    AnimSpeed, AnimPos: Double; {phase of picture by one map chip}
251
    AnimSpeed, AnimPos: Double; {phase of picture by one map chip}
252
    Rendered: TRenderType; {can be blended}
252
    Rendered: TRenderType; {can be blended}
253
    Alpha: Byte; {and blend level}
253
    Alpha: Byte; {and blend level}
254
    Angle: Single;
254
    Angle: Single;
255
    CenterX, CenterY: Double;
255
    CenterX, CenterY: Double;
256
    MirrorFlip: TRenderMirrorFlipSet;
256
    MirrorFlip: TRenderMirrorFlipSet;
257
    TextureFilter: TD2DTextureFilter;
257
    TextureFilter: TD2DTextureFilter;
258
    Tag: Integer; {for application use}
258
    Tag: Integer; {for application use}
259
  end;
259
  end;
260
 
260
 
261
  TBackgroundSprite = class(TImageSprite)
261
  TBackgroundSprite = class(TImageSprite)
262
  private
262
  private
263
    FMap: Pointer;
263
    FMap: Pointer;
264
    FMapWidth: Integer;
264
    FMapWidth: Integer;
265
    FMapHeight: Integer;
265
    FMapHeight: Integer;
266
 
266
 
267
    FChipsRect: TRect;
267
    FChipsRect: TRect;
268
    FChipsPatternIndex: Integer;
268
    FChipsPatternIndex: Integer;
269
    function GetCollisionMapItem(X, Y: Integer): Boolean;
269
    function GetCollisionMapItem(X, Y: Integer): Boolean;
270
    function GetChip(X, Y: Integer): Integer;
270
    function GetChip(X, Y: Integer): Integer;
271
    procedure SetChip(X, Y: Integer; Value: Integer);
271
    procedure SetChip(X, Y: Integer; Value: Integer);
272
    procedure SetCollisionMapItem(X, Y: Integer; Value: Boolean);
272
    procedure SetCollisionMapItem(X, Y: Integer; Value: Boolean);
273
    procedure SetMapHeight(Value: Integer);
273
    procedure SetMapHeight(Value: Integer);
274
    procedure SetMapWidth(Value: Integer);
274
    procedure SetMapWidth(Value: Integer);
275
 
275
 
276
    function GetCollisionRectItem(X, Y: Integer): TRect;
276
    function GetCollisionRectItem(X, Y: Integer): TRect;
277
    function GetMap(X, Y: Integer): TMapType;
277
    function GetMap(X, Y: Integer): TMapType;
278
    function GetTagMap(X, Y: Integer): Integer;
278
    function GetTagMap(X, Y: Integer): Integer;
279
    procedure SetCollisionRectItem(X, Y: Integer; Value: TRect);
279
    procedure SetCollisionRectItem(X, Y: Integer; Value: TRect);
280
    procedure SetMap(X, Y: Integer; Value: TMapType);
280
    procedure SetMap(X, Y: Integer; Value: TMapType);
281
    procedure SetTagMap(X, Y, Value: Integer);
281
    procedure SetTagMap(X, Y, Value: Integer);
282
    function GetOverlap(X, Y: Integer): Integer;
282
    function GetOverlap(X, Y: Integer): Integer;
283
    procedure SetOverlap(X, Y: Integer; const Value: Integer);
283
    procedure SetOverlap(X, Y: Integer; const Value: Integer);
284
  protected
284
  protected
285
    procedure ReadMapData(Stream: TStream);
285
    procedure ReadMapData(Stream: TStream);
286
    procedure WriteMapData(Stream: TStream);
286
    procedure WriteMapData(Stream: TStream);
287
    procedure DoDraw; override;
287
    procedure DoDraw; override;
288
    function GetBoundsRect: TRect; override;
288
    function GetBoundsRect: TRect; override;
289
    function TestCollision(Sprite: TSprite): Boolean; override;
289
    function TestCollision(Sprite: TSprite): Boolean; override;
290
    procedure SetImage(Img: TPictureCollectionItem); override;
290
    procedure SetImage(Img: TPictureCollectionItem); override;
291
    procedure DefineProperties(Filer: TFiler); override;
291
    procedure DefineProperties(Filer: TFiler); override;
292
  public
292
  public
293
    constructor Create(AParent: TSprite); override;
293
    constructor Create(AParent: TSprite); override;
294
    destructor Destroy; override;
294
    destructor Destroy; override;
295
    procedure ChipsDraw(Image: TPictureCollectionItem; X, Y, PatternIndex: Integer);
295
    procedure ChipsDraw(Image: TPictureCollectionItem; X, Y, PatternIndex: Integer);
296
    procedure SetMapSize(AMapWidth, AMapHeight: Integer);
296
    procedure SetMapSize(AMapWidth, AMapHeight: Integer);
297
    function IsMapEmpty: Boolean;
297
    function IsMapEmpty: Boolean;
298
    property Chips[X, Y: Integer]: Integer read GetChip write SetChip;
298
    property Chips[X, Y: Integer]: Integer read GetChip write SetChip;
299
    property CollisionMap[X, Y: Integer]: Boolean read GetCollisionMapItem write SetCollisionMapItem;
299
    property CollisionMap[X, Y: Integer]: Boolean read GetCollisionMapItem write SetCollisionMapItem;
300
    property CollisionRect[X, Y: Integer]: TRect read GetCollisionRectItem write SetCollisionRectItem;
300
    property CollisionRect[X, Y: Integer]: TRect read GetCollisionRectItem write SetCollisionRectItem;
301
    property Overlap[X, Y: Integer]: Integer read GetOverlap write SetOverlap;
301
    property Overlap[X, Y: Integer]: Integer read GetOverlap write SetOverlap;
302
    property TagMap[X, Y: Integer]: Integer read GetTagMap write SetTagMap;
302
    property TagMap[X, Y: Integer]: Integer read GetTagMap write SetTagMap;
303
    property Map[X, Y: Integer]: TMapType read GetMap write SetMap;
303
    property Map[X, Y: Integer]: TMapType read GetMap write SetMap;
304
    procedure Assign(Source: TPersistent); override;
304
    procedure Assign(Source: TPersistent); override;
305
    property ChipsRect: TRect read FChipsRect write FChipsRect;
305
    property ChipsRect: TRect read FChipsRect write FChipsRect;
306
    property ChipsPatternIndex: Integer read FChipsPatternIndex write FChipsPatternIndex default 0;
306
    property ChipsPatternIndex: Integer read FChipsPatternIndex write FChipsPatternIndex default 0;
307
    {un-published property}
307
    {un-published property}
308
    property MapHeight: Integer read FMapHeight write SetMapHeight;
308
    property MapHeight: Integer read FMapHeight write SetMapHeight;
309
    property MapWidth: Integer read FMapWidth write SetMapWidth;
309
    property MapWidth: Integer read FMapWidth write SetMapWidth;
310
  published
310
  published
311
    property DXImageList;
311
    property DXImageList;
312
    property DXImageName;
312
    property DXImageName;
313
 
313
 
314
    property OnDraw;
314
    property OnDraw;
315
    property OnMove;
315
    property OnMove;
316
    property OnCollision;
316
    property OnCollision;
317
    property OnGetImage;
317
    property OnGetImage;
318
  end;
318
  end;
319
 
319
 
320
  {  forward class  }
320
  {  forward class  }
321
 
321
 
322
  TCustomDXSpriteEngine = class;
322
  TCustomDXSpriteEngine = class;
323
 
323
 
324
  {  TSpriteEngine  }
324
  {  TSpriteEngine  }
325
 
325
 
326
  TSpriteEngine = class(TSprite)
326
  TSpriteEngine = class(TSprite)
327
  private
327
  private
328
    FOwner: TCustomDXSpriteEngine;
328
    FOwner: TCustomDXSpriteEngine;
329
    FAllCount: Integer;
329
    FAllCount: Integer;
330
    FCollisionCount: Integer;
330
    FCollisionCount: Integer;
331
    FCollisionDone: Boolean;
331
    FCollisionDone: Boolean;
332
    FCollisionRect: TRect;
332
    FCollisionRect: TRect;
333
    FCollisionSprite: TSprite;
333
    FCollisionSprite: TSprite;
334
    FDeadList: TList;
334
    FDeadList: TList;
335
    FDrawCount: Integer;
335
    FDrawCount: Integer;
336
    FSurface: TDirectDrawSurface;
336
    FSurface: TDirectDrawSurface;
337
    FSurfaceRect: TRect;
337
    FSurfaceRect: TRect;
338
{$IFDEF Ver4Up}
338
{$IFDEF Ver4Up}
339
    FObjectsSelected: Boolean;
339
    FObjectsSelected: Boolean;
340
    FGroupCount: Integer;
340
    FGroupCount: Integer;
341
    FGroups: array of Tlist;
341
    FGroups: array of Tlist;
342
    FCurrentSelected: Tlist;
342
    FCurrentSelected: Tlist;
343
{$ENDIF}
343
{$ENDIF}
344
  protected
344
  protected
345
    procedure SetSurface(Value: TDirectDrawSurface); virtual;
345
    procedure SetSurface(Value: TDirectDrawSurface); virtual;
346
{$IFDEF Ver4Up}
346
{$IFDEF Ver4Up}
347
    procedure SetGroupCount(AGroupCount: Integer); virtual;
347
    procedure SetGroupCount(AGroupCount: Integer); virtual;
348
    function GetGroup(Index: Integer): Tlist; virtual;
348
    function GetGroup(Index: Integer): Tlist; virtual;
349
{$ENDIF}
349
{$ENDIF}
350
  public
350
  public
351
    constructor Create(AParent: TSprite); override;
351
    constructor Create(AParent: TSprite); override;
352
    destructor Destroy; override;
352
    destructor Destroy; override;
353
    procedure Dead;
353
    procedure Dead;
354
    procedure Draw;
354
    procedure Draw;
355
    property AllCount: Integer read FAllCount;
355
    property AllCount: Integer read FAllCount;
356
    property DrawCount: Integer read FDrawCount;
356
    property DrawCount: Integer read FDrawCount;
357
    property Surface: TDirectDrawSurface read FSurface write SetSurface;
357
    property Surface: TDirectDrawSurface read FSurface write SetSurface;
358
    property SurfaceRect: TRect read FSurfaceRect;
358
    property SurfaceRect: TRect read FSurfaceRect;
359
 
359
 
360
    // Extended Sprite Engine
360
    // Extended Sprite Engine
361
    procedure Collisions;
361
    procedure Collisions;
362
 
362
 
363
    // Group handling support
363
    // Group handling support
364
    {$IFDEF Ver4Up}
364
    {$IFDEF Ver4Up}
365
    procedure ClearCurrent;
365
    procedure ClearCurrent;
366
    procedure ClearGroup(GroupNumber: Integer);
366
    procedure ClearGroup(GroupNumber: Integer);
367
    procedure GroupToCurrent(GroupNumber: Integer; Add: Boolean = False);
367
    procedure GroupToCurrent(GroupNumber: Integer; Add: Boolean = False);
368
    procedure CurrentToGroup(GroupNumber: Integer; Add: Boolean = False);
368
    procedure CurrentToGroup(GroupNumber: Integer; Add: Boolean = False);
369
    procedure GroupSelect(const Area: TRect; Filter: array of TSpriteClass; Add: Boolean = False); overload;
369
    procedure GroupSelect(const Area: TRect; Filter: array of TSpriteClass; Add: Boolean = False); overload;
370
    procedure GroupSelect(const Area: TRect; Add: Boolean = False); overload;
370
    procedure GroupSelect(const Area: TRect; Add: Boolean = False); overload;
371
    function Select(Point: TPoint; Filter: array of TSpriteClass; Add: Boolean = False): Tsprite; overload;
371
    function Select(Point: TPoint; Filter: array of TSpriteClass; Add: Boolean = False): Tsprite; overload;
372
    function Select(Point: TPoint; Add: Boolean = False): Tsprite; overload;
372
    function Select(Point: TPoint; Add: Boolean = False): Tsprite; overload;
373
 
373
 
374
    property CurrentSelected: TList read fCurrentSelected;
374
    property CurrentSelected: TList read fCurrentSelected;
375
    property ObjectsSelected: Boolean read fObjectsSelected;
375
    property ObjectsSelected: Boolean read fObjectsSelected;
376
    property Groups[Index: Integer]: Tlist read GetGroup;
376
    property Groups[Index: Integer]: Tlist read GetGroup;
377
    property GroupCount: Integer read fGroupCount write SetGroupCount;
377
    property GroupCount: Integer read fGroupCount write SetGroupCount;
378
    {$ENDIF}
378
    {$ENDIF}
379
  end;
379
  end;
380
 
380
 
381
  {  EDXSpriteEngineError  }
381
  {  EDXSpriteEngineError  }
382
 
382
 
383
  EDXSpriteEngineError = class(Exception);
383
  EDXSpriteEngineError = class(Exception);
384
 
384
 
385
  TSpriteCollection = class;
385
  TSpriteCollection = class;
386
 
386
 
387
  {  TSpriteType  }
387
  {  TSpriteType  }
388
 
388
 
389
  TSpriteType = (stSprite, stImageSprite, stImageSpriteEx, stBackgroundSprite);
389
  TSpriteType = (stSprite, stImageSprite, stImageSpriteEx, stBackgroundSprite);
390
 
390
 
391
  {  TSpriteCollectionItem  }
391
  {  TSpriteCollectionItem  }
392
 
392
 
393
  TSpriteCollectionItem = class(THashCollectionItem)
393
  TSpriteCollectionItem = class(THashCollectionItem)
394
  private
394
  private
395
    FOwner: TPersistent;
395
    FOwner: TPersistent;
396
    FOwnerItem: TSpriteEngine;
396
    FOwnerItem: TSpriteEngine;
397
    FSpriteType: TSpriteType;
397
    FSpriteType: TSpriteType;
398
    FSprite: TSprite;
398
    FSprite: TSprite;
399
    procedure Finalize;
399
    procedure Finalize;
400
    procedure Initialize;
400
    procedure Initialize;
401
    function GetSpriteCollection: TSpriteCollection;
401
    function GetSpriteCollection: TSpriteCollection;
402
    procedure SetSprite(const Value: TSprite);
402
    procedure SetSprite(const Value: TSprite);
403
    procedure SetOnCollision(const Value: TCollisionEvent);
403
    procedure SetOnCollision(const Value: TCollisionEvent);
404
    procedure SetOnDraw(const Value: TDrawEvent);
404
    procedure SetOnDraw(const Value: TDrawEvent);
405
    procedure SetOnMove(const Value: TMoveEvent);
405
    procedure SetOnMove(const Value: TMoveEvent);
406
    function GetSpriteType: TSpriteType;
406
    function GetSpriteType: TSpriteType;
407
    procedure SetSpriteType(const Value: TSpriteType);
407
    procedure SetSpriteType(const Value: TSpriteType);
408
    function GetOnCollision: TCollisionEvent;
408
    function GetOnCollision: TCollisionEvent;
409
    function GetOnDraw: TDrawEvent;
409
    function GetOnDraw: TDrawEvent;
410
    function GetOnMove: TMoveEvent;
410
    function GetOnMove: TMoveEvent;
411
    function GetOnGetImage: TGetImage;
411
    function GetOnGetImage: TGetImage;
412
    procedure SetOnGetImage(const Value: TGetImage);
412
    procedure SetOnGetImage(const Value: TGetImage);
413
    function GetImageList: TCustomDXImageList;
413
    function GetImageList: TCustomDXImageList;
414
    procedure SetImageList(const Value: TCustomDXImageList);
414
    procedure SetImageList(const Value: TCustomDXImageList);
415
  protected
415
  protected
416
    function GetDisplayName: string; override;
416
    function GetDisplayName: string; override;
417
    procedure SetDisplayName(const Value: string); override;
417
    procedure SetDisplayName(const Value: string); override;
418
  public
418
  public
419
    constructor Create(Collection: TCollection); override;
419
    constructor Create(Collection: TCollection); override;
420
    destructor Destroy; override;
420
    destructor Destroy; override;
421
    procedure Assign(Source: TPersistent); override;
421
    procedure Assign(Source: TPersistent); override;
422
    property SpriteCollection: TSpriteCollection read GetSpriteCollection;
422
    property SpriteCollection: TSpriteCollection read GetSpriteCollection;
423
    function Clone(NewName: string): TSprite;
423
    function Clone(NewName: string): TSprite;
424
  published
424
  published
425
    {published property of sprite}
425
    {published property of sprite}
426
    property KindSprite: TSpriteType read GetSpriteType write SetSpriteType;
426
    property KindSprite: TSpriteType read GetSpriteType write SetSpriteType;
427
    property ImageList: TCustomDXImageList read GetImageList write SetImageList;
427
    property ImageList: TCustomDXImageList read GetImageList write SetImageList;
428
    property Sprite: TSprite read FSprite write SetSprite;
428
    property Sprite: TSprite read FSprite write SetSprite;
429
    {published events of sprite}
429
    {published events of sprite}
430
    property OnDraw: TDrawEvent read GetOnDraw write SetOnDraw;
430
    property OnDraw: TDrawEvent read GetOnDraw write SetOnDraw;
431
    property OnMove: TMoveEvent read GetOnMove write SetOnMove;
431
    property OnMove: TMoveEvent read GetOnMove write SetOnMove;
432
    property OnCollision: TCollisionEvent read GetOnCollision write SetOnCollision;
432
    property OnCollision: TCollisionEvent read GetOnCollision write SetOnCollision;
433
    property OnGetImage: TGetImage read GetOnGetImage write SetOnGetImage;
433
    property OnGetImage: TGetImage read GetOnGetImage write SetOnGetImage;
434
  end;
434
  end;
435
 
435
 
436
  {  ESpriteCollectionError  }
436
  {  ESpriteCollectionError  }
437
 
437
 
438
  ESpriteCollectionError = class(Exception);
438
  ESpriteCollectionError = class(Exception);
439
 
439
 
440
  {  TSpriteCollection  }
440
  {  TSpriteCollection  }
441
 
441
 
442
  TSCInitialize = procedure(Owner: TSpriteEngine) of object;
442
  TSCInitialize = procedure(Owner: TSpriteEngine) of object;
443
  TSCFinalize = procedure(Owner: TSpriteEngine) of object;
443
  TSCFinalize = procedure(Owner: TSpriteEngine) of object;
444
 
444
 
445
  TSpriteCollection = class(THashCollection)
445
  TSpriteCollection = class(THashCollection)
446
  private
446
  private
447
    FInitializeFlag: Boolean;
447
    FInitializeFlag: Boolean;
448
    FOwner: TPersistent;
448
    FOwner: TPersistent;
449
    FOwnerItem: TSpriteEngine;
449
    FOwnerItem: TSpriteEngine;
450
    FOnInitialize: TSCInitialize;
450
    FOnInitialize: TSCInitialize;
451
    FOnFinalize: TSCFinalize;
451
    FOnFinalize: TSCFinalize;
452
    function GetItem(Index: Integer): TSpriteCollectionItem;
452
    function GetItem(Index: Integer): TSpriteCollectionItem;
453
  protected
453
  protected
454
    function GetOwner: TPersistent; override;
454
    function GetOwner: TPersistent; override;
455
  public
455
  public
456
    constructor Create(AOwner: TPersistent);
456
    constructor Create(AOwner: TPersistent);
457
    destructor Destroy; override;
457
    destructor Destroy; override;
458
    function Initialized: Boolean;
458
    function Initialized: Boolean;
459
    function Find(const Name: string): TSpriteCollectionItem;
459
    function Find(const Name: string): TSpriteCollectionItem;
460
    function Add: TSpriteCollectionItem;
460
    function Add: TSpriteCollectionItem;
461
    procedure Finalize;
461
    procedure Finalize;
462
    function Initialize(DXSpriteEngine: TSpriteEngine): Boolean;
462
    function Initialize(DXSpriteEngine: TSpriteEngine): Boolean;
463
    property Items[Index: Integer]: TSpriteCollectionItem read GetItem; default;
463
    property Items[Index: Integer]: TSpriteCollectionItem read GetItem; default;
464
  published
464
  published
465
    property OnInitialize: TSCInitialize read FOnInitialize write FOnInitialize;
465
    property OnInitialize: TSCInitialize read FOnInitialize write FOnInitialize;
466
    property OnFinalize: TSCFinalize read FOnFinalize write FOnFinalize;
466
    property OnFinalize: TSCFinalize read FOnFinalize write FOnFinalize;
467
  end;
467
  end;
468
 
468
 
469
  {  TCustomDXSpriteEngine  }
469
  {  TCustomDXSpriteEngine  }
470
 
470
 
471
  TCustomDXSpriteEngine = class(TComponent)
471
  TCustomDXSpriteEngine = class(TComponent)
472
  private
472
  private
473
    FDXDraw: TCustomDXDraw;
473
    FDXDraw: TCustomDXDraw;
474
    FEngine: TSpriteEngine;
474
    FEngine: TSpriteEngine;
475
    FItems: TSpriteCollection;
475
    FItems: TSpriteCollection;
476
    procedure DXDrawNotifyEvent(Sender: TCustomDXDraw; NotifyType: TDXDrawNotifyType);
476
    procedure DXDrawNotifyEvent(Sender: TCustomDXDraw; NotifyType: TDXDrawNotifyType);
477
    procedure SetDXDraw(Value: TCustomDXDraw);
477
    procedure SetDXDraw(Value: TCustomDXDraw);
478
    procedure SetItems(const Value: TSpriteCollection);
478
    procedure SetItems(const Value: TSpriteCollection);
479
  protected
479
  protected
480
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
480
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
481
  public
481
  public
482
    constructor Create(AOwner: TComponent); override;
482
    constructor Create(AOwner: TComponent); override;
483
    destructor Destroy; override;
483
    destructor Destroy; override;
484
    procedure Dead;
484
    procedure Dead;
485
    procedure Draw;
485
    procedure Draw;
486
    procedure Move(MoveCount: Integer);
486
    procedure Move(MoveCount: Integer);
487
    procedure Clone(const Amount: Word; const BaseNameOfSprite: string);
487
    procedure Clone(const Amount: Word; const BaseNameOfSprite: string);
488
    function ForEach(PrefixNameOdSprite: string; var Names: TStringList): Boolean;
488
    function ForEach(PrefixNameOdSprite: string; var Names: TStringList): Boolean;
489
    property DXDraw: TCustomDXDraw read FDXDraw write SetDXDraw;
489
    property DXDraw: TCustomDXDraw read FDXDraw write SetDXDraw;
490
    property Engine: TSpriteEngine read FEngine;
490
    property Engine: TSpriteEngine read FEngine;
491
    property Items: TSpriteCollection read FItems write SetItems;
491
    property Items: TSpriteCollection read FItems write SetItems;
492
  end;
492
  end;
493
 
493
 
494
  {  TDXSpriteEngine  }
494
  {  TDXSpriteEngine  }
495
 
495
 
496
  TDXSpriteEngine = class(TCustomDXSpriteEngine)
496
  TDXSpriteEngine = class(TCustomDXSpriteEngine)
497
    property Items;
497
    property Items;
498
  published
498
  published
499
    property DXDraw;
499
    property DXDraw;
500
  end;
500
  end;
501
 
501
 
502
function Mod2(i, i2: Integer): Integer; {$IFDEF VER9UP}inline;{$ENDIF}
502
function Mod2(i, i2: Integer): Integer; {$IFDEF VER9UP}inline;{$ENDIF}
503
function Mod2f(i: Double; i2: Integer): Double; {$IFDEF VER9UP}inline;{$ENDIF}
503
function Mod2f(i: Double; i2: Integer): Double; {$IFDEF VER9UP}inline;{$ENDIF}
504
function DefaultMapChip(iMapChip: Integer = -1; iCollisionChip: Boolean = False): TMapType; {$IFDEF VER9UP}inline;{$ENDIF}
504
function DefaultMapChip(iMapChip: Integer = -1; iCollisionChip: Boolean = False): TMapType; {$IFDEF VER9UP}inline;{$ENDIF}
505
 
505
 
506
implementation
506
implementation
507
 
507
 
508
uses DXConsts, TypInfo;
508
uses DXConsts, TypInfo;
509
 
509
 
510
const
510
const
511
  SSpriteNotFound = 'Sprite not found';
511
  SSpriteNotFound = 'Sprite not found';
512
  SSpriteDuplicateName = 'Item duplicate name "%s" error';
512
  SSpriteDuplicateName = 'Item duplicate name "%s" error';
513
 
513
 
514
function DefaultMapChip(iMapChip: Integer = -1; iCollisionChip: Boolean = False): TMapType;
514
function DefaultMapChip(iMapChip: Integer = -1; iCollisionChip: Boolean = False): TMapType;
515
begin
515
begin
516
  FillChar(Result, SizeOf(Result), 0);
516
  FillChar(Result, SizeOf(Result), 0);
517
  with Result do
517
  with Result do
518
  begin
518
  begin
519
    MapChip := iMapChip; {image chip as number}
519
    MapChip := iMapChip; {image chip as number}
520
    CollisionChip := iCollisionChip; {is collision brick}
520
    CollisionChip := iCollisionChip; {is collision brick}
521
//    CollisionRect: TRect; {dirty vollision area, can be smaller or bigger than silhouette}
521
//    CollisionRect: TRect; {dirty vollision area, can be smaller or bigger than silhouette}
522
//    Overlap: Integer; {for pulse image, like zoom etc.}
522
//    Overlap: Integer; {for pulse image, like zoom etc.}
523
//    AnimLooped: Boolean; {chip can be live}
523
//    AnimLooped: Boolean; {chip can be live}
524
//    AnimStart, AnimCount: Integer;
524
//    AnimStart, AnimCount: Integer;
525
//    AnimSpeed, AnimPos: Double; {phase of picture by one map chip}
525
//    AnimSpeed, AnimPos: Double; {phase of picture by one map chip}
526
    Rendered := rtDraw; {can be blended}
526
    Rendered := rtDraw; {can be blended}
527
    Alpha := $FF; {and blend level}
527
    Alpha := $FF; {and blend level}
528
    Angle := 0;
528
    Angle := 0;
529
    CenterX := 0.5;
529
    CenterX := 0.5;
530
    CenterY := 0.5;
530
    CenterY := 0.5;
531
    TextureFilter := D2D_POINT;
531
    TextureFilter := D2D_POINT;
532
//    Tag: Integer; {for application use}
532
//    Tag: Integer; {for application use}
533
  end;
533
  end;
534
end;
534
end;
535
 
535
 
536
function Mod2(i, i2: Integer): Integer;
536
function Mod2(i, i2: Integer): Integer;
537
begin
537
begin
538
  Result := i mod i2;
538
  Result := i mod i2;
539
  if Result < 0 then
539
  if Result < 0 then
540
    Result := i2 + Result;
540
    Result := i2 + Result;
541
end;
541
end;
542
 
542
 
543
function Mod2f(i: Double; i2: Integer): Double;
543
function Mod2f(i: Double; i2: Integer): Double;
544
begin
544
begin
545
  if i2 = 0 then
545
  if i2 = 0 then
546
    Result := i
546
    Result := i
547
  else
547
  else
548
  begin
548
  begin
549
    Result := i - Round(i / i2) * i2;
549
    Result := i - Round(i / i2) * i2;
550
    if Result < 0 then
550
    if Result < 0 then
551
      Result := i2 + Result;
551
      Result := i2 + Result;
552
  end;
552
  end;
553
end;
553
end;
554
 
554
 
555
{  TSprite  }
555
{  TSprite  }
556
 
556
 
557
constructor TSprite.Create(AParent: TSprite);
557
constructor TSprite.Create(AParent: TSprite);
558
begin
558
begin
559
  inherited Create;
559
  inherited Create;
560
{$IFDEF Ver4Up}
560
{$IFDEF Ver4Up}
561
  fGroupnumber := -1;
561
  fGroupnumber := -1;
562
{$ENDIF}
562
{$ENDIF}
563
  FParent := AParent;
563
  FParent := AParent;
564
  if FParent <> nil then
564
  if FParent <> nil then
565
  begin
565
  begin
566
    FParent.Add(Self);
566
    FParent.Add(Self);
567
    if FParent is TSpriteEngine then
567
    if FParent is TSpriteEngine then
568
      FEngine := TSpriteEngine(FParent)
568
      FEngine := TSpriteEngine(FParent)
569
    else
569
    else
570
      FEngine := FParent.Engine;
570
      FEngine := FParent.Engine;
571
    Inc(FEngine.FAllCount);
571
    Inc(FEngine.FAllCount);
572
  end;
572
  end;
573
 
573
 
574
  FCollisioned := True;
574
  FCollisioned := True;
575
  FMoved := True;
575
  FMoved := True;
576
  FVisible := True;
576
  FVisible := True;
577
end;
577
end;
578
 
578
 
579
destructor TSprite.Destroy;
579
destructor TSprite.Destroy;
580
begin
580
begin
581
{$IFDEF Ver4Up}
581
{$IFDEF Ver4Up}
582
  GroupNumber := -1;
582
  GroupNumber := -1;
583
  Selected := False;
583
  Selected := False;
584
{$ENDIF}
584
{$ENDIF}
585
  Clear;
585
  Clear;
586
  if FParent <> nil then
586
  if FParent <> nil then
587
  begin
587
  begin
588
    Dec(FEngine.FAllCount);
588
    Dec(FEngine.FAllCount);
589
    FParent.Remove(Self);
589
    FParent.Remove(Self);
590
    FEngine.FDeadList.Remove(Self);
590
    FEngine.FDeadList.Remove(Self);
591
  end;
591
  end;
592
  FList.Free;
592
  FList.Free;
593
  FDrawList.Free;
593
  FDrawList.Free;
594
  inherited Destroy;
594
  inherited Destroy;
595
end;
595
end;
596
 
596
 
597
{$IFDEF Ver4Up}
597
{$IFDEF Ver4Up}
598
 
598
 
599
procedure TSprite.SetGroupNumber(AGroupNumber: Integer);
599
procedure TSprite.SetGroupNumber(AGroupNumber: Integer);
600
begin
600
begin
601
  if (AGroupNumber <> GroupNumber) and (Engine <> nil) then
601
  if (AGroupNumber <> GroupNumber) and (Engine <> nil) then
602
  begin
602
  begin
603
    if Groupnumber >= 0 then
603
    if Groupnumber >= 0 then
604
      Engine.Groups[GroupNumber].Remove(self);
604
      Engine.Groups[GroupNumber].Remove(self);
605
    if AGroupNumber >= 0 then
605
    if AGroupNumber >= 0 then
606
      Engine.Groups[AGroupNumber].Add(self);
606
      Engine.Groups[AGroupNumber].Add(self);
607
  end;
607
  end;
608
end; {SetGroupNumber}
608
end; {SetGroupNumber}
609
 
609
 
610
procedure TSprite.SetSelected(ASelected: Boolean);
610
procedure TSprite.SetSelected(ASelected: Boolean);
611
begin
611
begin
612
  if (ASelected <> fSelected) and (Engine <> nil) then
612
  if (ASelected <> fSelected) and (Engine <> nil) then
613
  begin
613
  begin
614
    fSelected := ASelected;
614
    fSelected := ASelected;
615
    if Selected then
615
    if Selected then
616
      Engine.CurrentSelected.Add(self)
616
      Engine.CurrentSelected.Add(self)
617
    else
617
    else
618
      Engine.CurrentSelected.Remove(self);
618
      Engine.CurrentSelected.Remove(self);
619
    Engine.fObjectsSelected := Engine.CurrentSelected.count <> 0;
619
    Engine.fObjectsSelected := Engine.CurrentSelected.count <> 0;
620
  end;
620
  end;
621
end;
621
end;
622
{$ENDIF}
622
{$ENDIF}
623
 
623
 
624
procedure TSprite.Add(Sprite: TSprite);
624
procedure TSprite.Add(Sprite: TSprite);
625
begin
625
begin
626
  if FList = nil then
626
  if FList = nil then
627
  begin
627
  begin
628
    FList := TList.Create;
628
    FList := TList.Create;
629
    FDrawList := TList.Create;
629
    FDrawList := TList.Create;
630
  end;
630
  end;
631
  FList.Add(Sprite);
631
  FList.Add(Sprite);
632
  AddDrawList(Sprite);
632
  AddDrawList(Sprite);
633
end;
633
end;
634
 
634
 
635
procedure TSprite.Remove(Sprite: TSprite);
635
procedure TSprite.Remove(Sprite: TSprite);
636
begin
636
begin
637
  FList.Remove(Sprite);
637
  FList.Remove(Sprite);
638
  FDrawList.Remove(Sprite);
638
  FDrawList.Remove(Sprite);
639
  if FList.Count = 0 then
639
  if FList.Count = 0 then
640
  begin
640
  begin
641
    FList.Free;
641
    FList.Free;
642
    FList := nil;
642
    FList := nil;
643
    FDrawList.Free;
643
    FDrawList.Free;
644
    FDrawList := nil;
644
    FDrawList := nil;
645
  end;
645
  end;
646
end;
646
end;
647
 
647
 
648
procedure TSprite.AddDrawList(Sprite: TSprite);
648
procedure TSprite.AddDrawList(Sprite: TSprite);
649
var
649
var
650
  L, H, I, C: Integer;
650
  L, H, I, C: Integer;
651
begin
651
begin
652
  L := 0;
652
  L := 0;
653
  H := FDrawList.Count - 1;
653
  H := FDrawList.Count - 1;
654
  while L <= H do
654
  while L <= H do
655
  begin
655
  begin
656
    I := (L + H) div 2;
656
    I := (L + H) div 2;
657
    C := TSprite(FDrawList[I]).Z - Sprite.Z;
657
    C := TSprite(FDrawList[I]).Z - Sprite.Z;
658
    if C < 0 then
658
    if C < 0 then
659
      L := I + 1
659
      L := I + 1
660
    else
660
    else
661
      H := I - 1;
661
      H := I - 1;
662
  end;
662
  end;
663
  FDrawList.Insert(L, Sprite);
663
  FDrawList.Insert(L, Sprite);
664
end;
664
end;
665
 
665
 
666
procedure TSprite.Clear;
666
procedure TSprite.Clear;
667
begin
667
begin
668
  while Count > 0 do
668
  while Count > 0 do
669
    Items[Count - 1].Free;
669
    Items[Count - 1].Free;
670
end;
670
end;
671
 
671
 
672
function TSprite.Collision: Integer;
672
function TSprite.Collision: Integer;
673
var
673
var
674
  i: Integer;
674
  i: Integer;
675
begin
675
begin
676
  Result := 0;
676
  Result := 0;
677
  if (FEngine <> nil) and (not FDeaded) and (Collisioned) then
677
  if (FEngine <> nil) and (not FDeaded) and (Collisioned) then
678
  begin
678
  begin
679
    with FEngine do
679
    with FEngine do
680
    begin
680
    begin
681
      FCollisionCount := 0;
681
      FCollisionCount := 0;
682
      FCollisionDone := False;
682
      FCollisionDone := False;
683
      FCollisionRect := Self.BoundsRect;
683
      FCollisionRect := Self.BoundsRect;
684
      FCollisionSprite := Self;
684
      FCollisionSprite := Self;
685
 
685
 
686
      for i := 0 to Count - 1 do
686
      for i := 0 to Count - 1 do
687
        Items[i].Collision2;
687
        Items[i].Collision2;
688
 
688
 
689
      Result := FCollisionCount;
689
      Result := FCollisionCount;
690
    end;
690
    end;
691
  end;
691
  end;
692
end;
692
end;
693
 
693
 
694
procedure TSprite.Collision2;
694
procedure TSprite.Collision2;
695
var
695
var
696
  i: Integer;
696
  i: Integer;
697
begin
697
begin
698
  if Collisioned then
698
  if Collisioned then
699
  begin
699
  begin
700
    if (Self <> FEngine.FCollisionSprite) and OverlapRect(BoundsRect,
700
    if (Self <> FEngine.FCollisionSprite) and OverlapRect(BoundsRect,
701
      FEngine.FCollisionRect) and FEngine.FCollisionSprite.TestCollision(Self) and
701
      FEngine.FCollisionRect) and FEngine.FCollisionSprite.TestCollision(Self) and
702
      TestCollision(FEngine.FCollisionSprite) then
702
      TestCollision(FEngine.FCollisionSprite) then
703
    begin
703
    begin
704
      Inc(FEngine.FCollisionCount);
704
      Inc(FEngine.FCollisionCount);
705
      FEngine.FCollisionSprite.DoCollision(Self, FEngine.FCollisionDone);
705
      FEngine.FCollisionSprite.DoCollision(Self, FEngine.FCollisionDone);
706
      if (not FEngine.FCollisionSprite.Collisioned) or
706
      if (not FEngine.FCollisionSprite.Collisioned) or
707
        (FEngine.FCollisionSprite.FDeaded) then
707
        (FEngine.FCollisionSprite.FDeaded) then
708
      begin
708
      begin
709
        FEngine.FCollisionDone := True;
709
        FEngine.FCollisionDone := True;
710
      end;
710
      end;
711
    end;
711
    end;
712
    if FEngine.FCollisionDone then
712
    if FEngine.FCollisionDone then
713
      Exit;
713
      Exit;
714
    for i := 0 to Count - 1 do
714
    for i := 0 to Count - 1 do
715
      Items[i].Collision2;
715
      Items[i].Collision2;
716
  end;
716
  end;
717
end;
717
end;
718
 
718
 
719
procedure TSprite.Dead;
719
procedure TSprite.Dead;
720
begin
720
begin
721
  if (FEngine <> nil) and (not FDeaded) then
721
  if (FEngine <> nil) and (not FDeaded) then
722
  begin
722
  begin
723
    FDeaded := True;
723
    FDeaded := True;
724
    FEngine.FDeadList.Add(Self);
724
    FEngine.FDeadList.Add(Self);
725
  end;
725
  end;
726
end;
726
end;
727
 
727
 
728
procedure TSprite.DoMove(MoveCount: Integer);
728
procedure TSprite.DoMove(MoveCount: Integer);
729
begin
729
begin
730
  if AsSigned(FOnMove) then
730
  if AsSigned(FOnMove) then
731
    FOnMove(Self, MoveCount);
731
    FOnMove(Self, MoveCount);
732
end;
732
end;
733
 
733
 
734
procedure TSprite.DoDraw;
734
procedure TSprite.DoDraw;
735
begin
735
begin
736
  if AsSigned(FOnDraw) then
736
  if AsSigned(FOnDraw) then
737
    FOnDraw(Self);
737
    FOnDraw(Self);
738
end;
738
end;
739
 
739
 
740
procedure TSprite.DoCollision(Sprite: TSprite; var Done: Boolean);
740
procedure TSprite.DoCollision(Sprite: TSprite; var Done: Boolean);
741
begin
741
begin
742
  if AsSigned(FOnCollision) then
742
  if AsSigned(FOnCollision) then
743
    FOnCollision(Sprite, Done);
743
    FOnCollision(Sprite, Done);
744
end;
744
end;
745
 
745
 
746
function TSprite.TestCollision(Sprite: TSprite): Boolean;
746
function TSprite.TestCollision(Sprite: TSprite): Boolean;
747
begin
747
begin
748
  Result := True;
748
  Result := True;
749
end;
749
end;
750
 
750
 
751
procedure TSprite.Move(MoveCount: Integer);
751
procedure TSprite.Move(MoveCount: Integer);
752
var
752
var
753
  i: Integer;
753
  i: Integer;
754
begin
754
begin
755
  if FMoved then
755
  if FMoved then
756
  begin
756
  begin
757
    DoMove(MoveCount); ReAnimate(MoveCount);
757
    DoMove(MoveCount); ReAnimate(MoveCount);
758
    for i := 0 to Count - 1 do
758
    for i := 0 to Count - 1 do
759
      Items[i].Move(MoveCount);
759
      Items[i].Move(MoveCount);
760
  end;
760
  end;
761
end;
761
end;
762
 
762
 
763
procedure TSprite.Draw;
763
procedure TSprite.Draw;
764
var
764
var
765
  i: Integer;
765
  i: Integer;
766
begin
766
begin
767
  if FVisible then
767
  if FVisible then
768
  begin
768
  begin
769
    if FEngine <> nil then
769
    if FEngine <> nil then
770
    begin
770
    begin
771
      if OverlapRect(FEngine.FSurfaceRect, BoundsRect) then
771
      if OverlapRect(FEngine.FSurfaceRect, BoundsRect) then
772
      begin
772
      begin
773
        DoDraw;
773
        DoDraw;
774
        Inc(FEngine.FDrawCount);
774
        Inc(FEngine.FDrawCount);
775
      end;
775
      end;
776
    end;
776
    end;
777
 
777
 
778
    if FDrawList <> nil then
778
    if FDrawList <> nil then
779
    begin
779
    begin
780
      for i := 0 to FDrawList.Count - 1 do
780
      for i := 0 to FDrawList.Count - 1 do
781
      begin
781
      begin
782
        TSprite(FDrawList[i]).Draw;
782
        TSprite(FDrawList[i]).Draw;
783
      end;
783
      end;
784
    end;
784
    end;
785
  end;
785
  end;
786
end;
786
end;
787
 
787
 
788
function TSprite.GetSpriteAt(X, Y: Integer): TSprite;
788
function TSprite.GetSpriteAt(X, Y: Integer): TSprite;
789
 
789
 
790
  procedure Collision_GetSpriteAt(X, Y: Double; Sprite: TSprite);
790
  procedure Collision_GetSpriteAt(X, Y: Double; Sprite: TSprite);
791
  var
791
  var
792
    i: Integer;
792
    i: Integer;
793
    X2, Y2: Double;
793
    X2, Y2: Double;
794
  begin
794
  begin
795
    if Sprite.Visible and PointInRect(Point(Round(X), Round(Y)),
795
    if Sprite.Visible and PointInRect(Point(Round(X), Round(Y)),
796
      Bounds(Round(Sprite.X), Round(Sprite.Y), Sprite.Width, Sprite.Height)) then //corrected by Sergey
796
      Bounds(Round(Sprite.X), Round(Sprite.Y), Sprite.Width, Sprite.Height)) then //corrected by Sergey
797
    begin
797
    begin
798
      if (Result = nil) or (Sprite.Z > Result.Z) then
798
      if (Result = nil) or (Sprite.Z > Result.Z) then
799
        Result := Sprite;
799
        Result := Sprite;
800
    end;
800
    end;
801
 
801
 
802
    X2 := X - Sprite.X;
802
    X2 := X - Sprite.X;
803
    Y2 := Y - Sprite.Y;
803
    Y2 := Y - Sprite.Y;
804
    for i := 0 to Sprite.Count - 1 do
804
    for i := 0 to Sprite.Count - 1 do
805
      Collision_GetSpriteAt(X2, Y2, Sprite.Items[i]);
805
      Collision_GetSpriteAt(X2, Y2, Sprite.Items[i]);
806
  end;
806
  end;
807
 
807
 
808
var
808
var
809
  i: Integer;
809
  i: Integer;
810
  X2, Y2: Double;
810
  X2, Y2: Double;
811
begin
811
begin
812
  Result := nil;
812
  Result := nil;
813
 
813
 
814
  X2 := X - Self.X;
814
  X2 := X - Self.X;
815
  Y2 := Y - Self.Y;
815
  Y2 := Y - Self.Y;
816
  for i := 0 to Count - 1 do
816
  for i := 0 to Count - 1 do
817
    Collision_GetSpriteAt(X2, Y2, Items[i]);
817
    Collision_GetSpriteAt(X2, Y2, Items[i]);
818
end;
818
end;
819
 
819
 
820
function TSprite.GetBoundsRect: TRect;
820
function TSprite.GetBoundsRect: TRect;
821
begin
821
begin
822
  Result := Bounds(Round(WorldX), Round(WorldY), Width, Height);
822
  Result := Bounds(Round(WorldX), Round(WorldY), Width, Height);
823
end;
823
end;
824
 
824
 
825
function TSprite.GetClientRect: TRect;
825
function TSprite.GetClientRect: TRect;
826
begin
826
begin
827
  Result := Bounds(0, 0, Width, Height);
827
  Result := Bounds(0, 0, Width, Height);
828
end;
828
end;
829
 
829
 
830
function TSprite.GetCount: Integer;
830
function TSprite.GetCount: Integer;
831
begin
831
begin
832
  if FList <> nil then
832
  if FList <> nil then
833
    Result := FList.Count
833
    Result := FList.Count
834
  else
834
  else
835
    Result := 0;
835
    Result := 0;
836
end;
836
end;
837
 
837
 
838
function TSprite.GetItem(Index: Integer): TSprite;
838
function TSprite.GetItem(Index: Integer): TSprite;
839
begin
839
begin
840
  if FList <> nil then
840
  if FList <> nil then
841
    Result := FList[Index]
841
    Result := FList[Index]
842
  else
842
  else
843
    raise ESpriteError.CreateFmt(SListIndexError, [Index]);
843
    raise ESpriteError.CreateFmt(SListIndexError, [Index]);
844
end;
844
end;
845
 
845
 
846
function TSprite.GetWorldX: Double;
846
function TSprite.GetWorldX: Double;
847
begin
847
begin
848
  if Parent <> nil then
848
  if Parent <> nil then
849
    Result := Parent.WorldX + FX
849
    Result := Parent.WorldX + FX
850
  else
850
  else
851
    Result := FX;
851
    Result := FX;
852
end;
852
end;
853
 
853
 
854
function TSprite.GetWorldY: Double;
854
function TSprite.GetWorldY: Double;
855
begin
855
begin
856
  if Parent <> nil then
856
  if Parent <> nil then
857
    Result := Parent.WorldY + FY
857
    Result := Parent.WorldY + FY
858
  else
858
  else
859
    Result := FY;
859
    Result := FY;
860
end;
860
end;
861
 
861
 
862
procedure TSprite.SetZ(Value: Integer);
862
procedure TSprite.SetZ(Value: Integer);
863
begin
863
begin
864
  if FZ <> Value then
864
  if FZ <> Value then
865
  begin
865
  begin
866
    FZ := Value;
866
    FZ := Value;
867
    if Parent <> nil then
867
    if Parent <> nil then
868
    begin
868
    begin
869
      Parent.FDrawList.Remove(Self);
869
      Parent.FDrawList.Remove(Self);
870
      Parent.AddDrawList(Self);
870
      Parent.AddDrawList(Self);
871
    end;
871
    end;
872
  end;
872
  end;
873
end;
873
end;
874
 
874
 
875
procedure TSprite.Assign(Source: TPersistent);
875
procedure TSprite.Assign(Source: TPersistent);
876
begin
876
begin
877
  if Source is TSprite then
877
  if Source is TSprite then
878
  begin
878
  begin
879
    FCollisioned := TSprite(Source).FCollisioned;
879
    FCollisioned := TSprite(Source).FCollisioned;
880
    FMoved := TSprite(Source).FMoved;
880
    FMoved := TSprite(Source).FMoved;
881
    FVisible := TSprite(Source).FVisible;
881
    FVisible := TSprite(Source).FVisible;
882
    FHeight := TSprite(Source).FHeight;
882
    FHeight := TSprite(Source).FHeight;
883
    FWidth := TSprite(Source).FWidth;
883
    FWidth := TSprite(Source).FWidth;
884
    FX := TSprite(Source).FX;
884
    FX := TSprite(Source).FX;
885
    FY := TSprite(Source).FY;
885
    FY := TSprite(Source).FY;
886
    FZ := TSprite(Source).FZ;
886
    FZ := TSprite(Source).FZ;
887
{$IFDEF Ver4Up}
887
{$IFDEF Ver4Up}
888
    FSelected := TSprite(Source).FSelected;
888
    FSelected := TSprite(Source).FSelected;
889
    FGroupNumber := TSprite(Source).FGroupNumber;
889
    FGroupNumber := TSprite(Source).FGroupNumber;
890
{$ENDIF}
890
{$ENDIF}
891
    {copy image base - when exists}
891
    {copy image base - when exists}
892
    FDXImage := TSprite(Source).FDXImage;
892
    FDXImage := TSprite(Source).FDXImage;
893
    FDXImageName := TSprite(Source).FDXImageName;
893
    FDXImageName := TSprite(Source).FDXImageName;
894
    FDXImageList := TSprite(Source).FDXImageList;
894
    FDXImageList := TSprite(Source).FDXImageList;
895
    {events}
895
    {events}
896
    FOnDraw := TSprite(Source).FOnDraw;
896
    FOnDraw := TSprite(Source).FOnDraw;
897
    FOnMove := TSprite(Source).FOnMove;
897
    FOnMove := TSprite(Source).FOnMove;
898
    FOnCollision := TSprite(Source).FOnCollision;
898
    FOnCollision := TSprite(Source).FOnCollision;
899
    FOnGetImage := TSprite(Source).FOnGetImage;
899
    FOnGetImage := TSprite(Source).FOnGetImage;
900
  end
900
  end
901
  else
901
  else
902
    inherited;
902
    inherited;
903
end;
903
end;
904
 
904
 
905
procedure TSprite.ReAnimate(MoveCount: Integer);
905
procedure TSprite.ReAnimate(MoveCount: Integer);
906
begin
906
begin
907
 
907
 
908
end;
908
end;
909
 
909
 
910
{  TImageSprite  }
910
{  TImageSprite  }
911
 
911
 
912
constructor TImageSprite.Create(AParent: TSprite);
912
constructor TImageSprite.Create(AParent: TSprite);
913
begin
913
begin
914
  inherited Create(AParent);
914
  inherited Create(AParent);
915
  FTransparent := True;
915
  FTransparent := True;
916
  FAlpha := 255;
916
  FAlpha := 255;
917
  FAngle := 0;
917
  FAngle := 0;
918
  FBlendMode := rtDraw;
918
  FBlendMode := rtDraw;
919
  FCenterX := 0.5;
919
  FCenterX := 0.5;
920
  FCenterY := 0.5;
920
  FCenterY := 0.5;
921
  FBlurImage := False;
921
  FBlurImage := False;
922
  FillChar(FBlurImageArr, SizeOf(FBlurImageArr), 0);
922
  FillChar(FBlurImageArr, SizeOf(FBlurImageArr), 0);
923
  FTextureFilter := D2D_POINT;
923
  FTextureFilter := D2D_POINT;
924
end;
924
end;
925
 
925
 
926
procedure TImageSprite.SetImage(AImage: TPictureCollectionItem);
926
procedure TImageSprite.SetImage(AImage: TPictureCollectionItem);
927
begin
927
begin
928
  FDXImage := AImage;
928
  FDXImage := AImage;
929
  FDXImageName := '';
929
  FDXImageName := '';
930
  if AImage <> nil then
930
  if AImage <> nil then
931
  begin
931
  begin
932
    Width := AImage.Width;
932
    Width := AImage.Width;
933
    Height := AImage.Height;
933
    Height := AImage.Height;
934
    FDXImageName := FDXImage.Name;
934
    FDXImageName := FDXImage.Name;
935
  end
935
  end
936
  else
936
  else
937
  begin
937
  begin
938
    Width := 0;
938
    Width := 0;
939
    Height := 0;
939
    Height := 0;
940
  end;
940
  end;
941
end; {SetImage}
941
end; {SetImage}
942
 
942
 
943
function TImageSprite.GetBoundsRect: TRect;
943
function TImageSprite.GetBoundsRect: TRect;
944
var
944
var
945
  dx, dy: Integer;
945
  dx, dy: Integer;
946
begin
946
begin
947
  dx := Round(WorldX);
947
  dx := Round(WorldX);
948
  dy := Round(WorldY);
948
  dy := Round(WorldY);
949
  if FTile then
949
  if FTile then
950
  begin
950
  begin
951
    dx := Mod2(dx, FEngine.SurfaceRect.Right + Width);
951
    dx := Mod2(dx, FEngine.SurfaceRect.Right + Width);
952
    dy := Mod2(dy, FEngine.SurfaceRect.Bottom + Height);
952
    dy := Mod2(dy, FEngine.SurfaceRect.Bottom + Height);
953
 
953
 
954
    if dx > FEngine.SurfaceRect.Right then
954
    if dx > FEngine.SurfaceRect.Right then
955
      dx := (dx - FEngine.SurfaceRect.Right) - Width;
955
      dx := (dx - FEngine.SurfaceRect.Right) - Width;
956
 
956
 
957
    if dy > FEngine.SurfaceRect.Bottom then
957
    if dy > FEngine.SurfaceRect.Bottom then
958
      dy := (dy - FEngine.SurfaceRect.Bottom) - Height;
958
      dy := (dy - FEngine.SurfaceRect.Bottom) - Height;
959
  end;
959
  end;
960
 
960
 
961
  Result := Bounds(dx, dy, Width, Height);
961
  Result := Bounds(dx, dy, Width, Height);
962
end;
962
end;
963
 
963
 
964
procedure TImageSprite.DoMove(MoveCount: Integer);
964
procedure TImageSprite.DoMove(MoveCount: Integer);
965
begin
965
begin
966
  if AsSigned(FOnMove) then
966
  if AsSigned(FOnMove) then
967
    FOnMove(Self, MoveCount)
967
    FOnMove(Self, MoveCount)
968
  else
968
  else
969
  begin
969
  begin
970
    ReAnimate(MoveCount);
970
    ReAnimate(MoveCount);
971
  end;
971
  end;
972
end;
972
end;
973
 
973
 
974
function TImageSprite.GetDrawImageIndex: Integer;
974
function TImageSprite.GetDrawImageIndex: Integer;
975
begin
975
begin
976
  Result := FAnimStart + Trunc(FAnimPos); //solve 1.07f to Round()
976
  Result := FAnimStart + Trunc(FAnimPos); //solve 1.07f to Round()
977
end;
977
end;
978
 
978
 
979
function TImageSprite.GetDrawRect: TRect;
979
function TImageSprite.GetDrawRect: TRect;
980
begin
980
begin
981
  Result := BoundsRect;
981
  Result := BoundsRect;
982
  OffsetRect(Result, (Width - Image.Width) div 2, (Height - Image.Height) div 2);
982
  OffsetRect(Result, (Width - Image.Width) div 2, (Height - Image.Height) div 2);
983
end;
983
end;
984
 
984
 
985
procedure TImageSprite.LoadImage;
985
procedure TImageSprite.LoadImage;
986
var
986
var
987
 vImage: TPictureCollectionItem;
987
 vImage: TPictureCollectionItem;
988
begin
988
begin
989
  if Image = nil then
989
  if Image = nil then
990
    if AsSigned(FOnGetImage) then
990
    if AsSigned(FOnGetImage) then
991
    begin
991
    begin
992
      vImage := nil;
992
      vImage := nil;
993
      FOnGetImage(Self, vImage);
993
      FOnGetImage(Self, vImage);
994
      if vImage <> Image then
994
      if vImage <> Image then
995
        Image := vImage;
995
        Image := vImage;
996
    end
996
    end
997
    else
997
    else
998
      if FDXImageName <> '' then
998
      if FDXImageName <> '' then
999
        if Assigned(FDXImageList) then
999
        if Assigned(FDXImageList) then
1000
        begin
1000
        begin
1001
          Image := FDXImageList.Items.Find(FDXImageName);
1001
          Image := FDXImageList.Items.Find(FDXImageName);
1002
        end;
1002
        end;
1003
end;
1003
end;
1004
 
1004
 
1005
procedure TImageSprite.DoDraw;
1005
procedure TImageSprite.DoDraw;
1006
var
1006
var
1007
  r: TRect;
1007
  r: TRect;
1008
begin
1008
begin
1009
  LoadImage;
1009
  LoadImage;
1010
  if Image = nil then
1010
  if Image = nil then
1011
    Exit;
1011
    Exit;
1012
  if AsSigned(FOnDraw) then {owner draw called here}
1012
  if AsSigned(FOnDraw) then {owner draw called here}
1013
    FOnDraw(Self)
1013
    FOnDraw(Self)
1014
  else {when is not owner draw then go here}
1014
  else {when is not owner draw then go here}
1015
  begin
1015
  begin
1016
    r := Bounds(Round(WorldX), Round(WorldY), Width, Height);
1016
    r := Bounds(Round(WorldX), Round(WorldY), Width, Height);
1017
    {New function implemented}
1017
    {New function implemented}
1018
    if Assigned(FEngine.FOwner) then
1018
    if Assigned(FEngine.FOwner) then
1019
      DXDraws.DXDraw_Paint(FEngine.FOwner.FDXDraw, Image, r, GetDrawImageIndex,
1019
      DXDraws.DXDraw_Paint(FEngine.FOwner.FDXDraw, Image, r, GetDrawImageIndex,
1020
        FBlurImageArr, FBlurImage, FTextureFilter, FMirrorFlip, FBlendMode, FAngle,
1020
        FBlurImageArr, FBlurImage, FTextureFilter, FMirrorFlip, FBlendMode, FAngle,
1021
        FAlpha, FCenterX, FCenterY);
1021
        FAlpha, FCenterX, FCenterY);
1022
  end;
1022
  end;
1023
end;
1023
end;
1024
 
1024
 
1025
{$WARNINGS OFF}
1025
{$WARNINGS OFF}
1026
{$HINTS OFF}
1026
{$HINTS OFF}
1027
 
1027
 
1028
function TImageSprite.ImageCollisionTest(suf1, suf2: TDirectDrawSurface;
1028
function TImageSprite.ImageCollisionTest(suf1, suf2: TDirectDrawSurface;
1029
  const rect1, rect2: TRect; x1, y1, x2, y2: Integer; DoPixelCheck: Boolean): Boolean;
1029
  const rect1, rect2: TRect; x1, y1, x2, y2: Integer; DoPixelCheck: Boolean): Boolean;
1030
 
1030
 
1031
  function ClipRect(var DestRect: TRect; const DestRect2: TRect): Boolean;
1031
  function ClipRect(var DestRect: TRect; const DestRect2: TRect): Boolean;
1032
  begin
1032
  begin
1033
    with DestRect do
1033
    with DestRect do
1034
    begin
1034
    begin
1035
      Left := Max(Left, DestRect2.Left);
1035
      Left := Max(Left, DestRect2.Left);
1036
      Right := Min(Right, DestRect2.Right);
1036
      Right := Min(Right, DestRect2.Right);
1037
      Top := Max(Top, DestRect2.Top);
1037
      Top := Max(Top, DestRect2.Top);
1038
      Bottom := Min(Bottom, DestRect2.Bottom);
1038
      Bottom := Min(Bottom, DestRect2.Bottom);
1039
 
1039
 
1040
      Result := (Left < Right) and (Top < Bottom);
1040
      Result := (Left < Right) and (Top < Bottom);
1041
    end;
1041
    end;
1042
  end;
1042
  end;
1043
 
1043
 
1044
type
1044
type
1045
  PRGB = ^TRGB;
1045
  PRGB = ^TRGB;
1046
 
1046
 
1047
  TRGB = packed record
1047
  TRGB = packed record
1048
    R, G, B: byte;
1048
    R, G, B: byte;
1049
  end;
1049
  end;
1050
var
1050
var
1051
  ddsd1, ddsd2: {$IFDEF D3D_deprecated}TDDSURFACEDESC{$ELSE}TDDSurfaceDesc2{$ENDIF};
1051
  ddsd1, ddsd2: {$IFDEF D3D_deprecated}TDDSURFACEDESC{$ELSE}TDDSurfaceDesc2{$ENDIF};
1052
  r1, r2, r1a, r2a: TRect;
1052
  r1, r2, r1a, r2a: TRect;
1053
  tc1, tc2: DWORD;
1053
  tc1, tc2: DWORD;
1054
  x, y, w, h: Integer;
1054
  x, y, w, h: Integer;
1055
  P1, P2: Pointer;
1055
  P1, P2: Pointer;
1056
begin
1056
begin
1057
  with rect1 do
1057
  with rect1 do
1058
    r1 := Bounds(0, 0, Right - Left, Bottom - Top);
1058
    r1 := Bounds(0, 0, Right - Left, Bottom - Top);
1059
  r1a := r1;
1059
  r1a := r1;
1060
  with rect2 do
1060
  with rect2 do
1061
    r2 := Bounds(0, 0, Right - Left, Bottom - Top);
1061
    r2 := Bounds(0, 0, Right - Left, Bottom - Top);
1062
  r2a := r2;
1062
  r2a := r2;
1063
 
1063
 
1064
  with rect2 do
1064
  with rect2 do
1065
    r2 := Bounds(x2 - x1, y2 - y1, Right - Left, Bottom - Top);
1065
    r2 := Bounds(x2 - x1, y2 - y1, Right - Left, Bottom - Top);
1066
 
1066
 
1067
  Result := OverlapRect(r1, r2);
1067
  Result := OverlapRect(r1, r2);
1068
 
1068
 
1069
  if (suf1 = nil) or (suf2 = nil) then
1069
  if (suf1 = nil) or (suf2 = nil) then
1070
    Exit;
1070
    Exit;
1071
 
1071
 
1072
  if DoPixelCheck and Result then
1072
  if DoPixelCheck and Result then
1073
  begin
1073
  begin
1074
    {  Get Overlapping rectangle  }
1074
    {  Get Overlapping rectangle  }
1075
    with r1 do
1075
    with r1 do
1076
      r1 := Bounds(Max(x2 - x1, 0), Max(y2 - y1, 0), Right - Left, Bottom - Top);
1076
      r1 := Bounds(Max(x2 - x1, 0), Max(y2 - y1, 0), Right - Left, Bottom - Top);
1077
    with r2 do
1077
    with r2 do
1078
      r2 := Bounds(Max(x1 - x2, 0), Max(y1 - y2, 0), Right - Left, Bottom - Top);
1078
      r2 := Bounds(Max(x1 - x2, 0), Max(y1 - y2, 0), Right - Left, Bottom - Top);
1079
 
1079
 
1080
    ClipRect(r1, r1a);
1080
    ClipRect(r1, r1a);
1081
    ClipRect(r2, r2a);
1081
    ClipRect(r2, r2a);
1082
 
1082
 
1083
    w := Min(r1.Right - r1.Left, r2.Right - r2.Left);
1083
    w := Min(r1.Right - r1.Left, r2.Right - r2.Left);
1084
    h := Min(r1.Bottom - r1.Top, r2.Bottom - r2.Top);
1084
    h := Min(r1.Bottom - r1.Top, r2.Bottom - r2.Top);
1085
 
1085
 
1086
    ClipRect(r1, bounds(r1.Left, r1.Top, w, h));
1086
    ClipRect(r1, bounds(r1.Left, r1.Top, w, h));
1087
    ClipRect(r2, bounds(r2.Left, r2.Top, w, h));
1087
    ClipRect(r2, bounds(r2.Left, r2.Top, w, h));
1088
 
1088
 
1089
    {  Pixel check !!!  }
1089
    {  Pixel check !!!  }
1090
    ddsd1.dwSize := SizeOf(ddsd1);
1090
    ddsd1.dwSize := SizeOf(ddsd1);
1091
 
1091
 
1092
    with rect1 do
1092
    with rect1 do
1093
      r1 := Bounds(r1.Left + left, r1.Top + top, w, h);
1093
      r1 := Bounds(r1.Left + left, r1.Top + top, w, h);
1094
    with rect2 do
1094
    with rect2 do
1095
      r2 := Bounds(r2.Left + left, r2.Top + top, w, h);
1095
      r2 := Bounds(r2.Left + left, r2.Top + top, w, h);
1096
 
1096
 
1097
    if suf1 = suf2 then
1097
    if suf1 = suf2 then
1098
    begin
1098
    begin
1099
      suf2.Lock(r2, ddsd2);
1099
      suf2.Lock(r2, ddsd2);
1100
      suf2.unlock;
1100
      suf2.unlock;
1101
    end;
1101
    end;
1102
 
1102
 
1103
    if suf1.Lock(r1, ddsd1) then
1103
    if suf1.Lock(r1, ddsd1) then
1104
    begin
1104
    begin
1105
      try
1105
      try
1106
        ddsd2.dwSize := SizeOf(ddsd2);
1106
        ddsd2.dwSize := SizeOf(ddsd2);
1107
        if (suf1 = suf2) or suf2.Lock(r2, ddsd2) then
1107
        if (suf1 = suf2) or suf2.Lock(r2, ddsd2) then
1108
        begin
1108
        begin
1109
          try
1109
          try
1110
            {this line out: don't test pixel but rect only, its wrong}
1110
            {this line out: don't test pixel but rect only, its wrong}
1111
            {if suf1=suf2 then ddsd2 := ddsd1;}
1111
            {if suf1=suf2 then ddsd2 := ddsd1;}
1112
            if ddsd1.ddpfPixelFormat.dwRGBBitCount <> ddsd2.ddpfPixelFormat.dwRGBBitCount then
1112
            if ddsd1.ddpfPixelFormat.dwRGBBitCount <> ddsd2.ddpfPixelFormat.dwRGBBitCount then
1113
              Exit;
1113
              Exit;
1114
 
1114
 
1115
            {  Get transparent color  }
1115
            {  Get transparent color  }
1116
            tc1 := ddsd1.ddckCKSrcBlt.dwColorSpaceLowValue;
1116
            tc1 := ddsd1.ddckCKSrcBlt.dwColorSpaceLowValue;
1117
            tc2 := ddsd2.ddckCKSrcBlt.dwColorSpaceLowValue;
1117
            tc2 := ddsd2.ddckCKSrcBlt.dwColorSpaceLowValue;
1118
 
1118
 
1119
            case ddsd1.ddpfPixelFormat.dwRGBBitCount of
1119
            case ddsd1.ddpfPixelFormat.dwRGBBitCount of
1120
              8:
1120
              8:
1121
                begin
1121
                begin
1122
                  for y := 0 to h - 1 do
1122
                  for y := 0 to h - 1 do
1123
                  begin
1123
                  begin
1124
                    P1 := Pointer(Integer(ddsd1.lpSurface) + y * ddsd1.lPitch);
1124
                    P1 := Pointer(Integer(ddsd1.lpSurface) + y * ddsd1.lPitch);
1125
                    P2 := Pointer(Integer(ddsd2.lpSurface) + y * ddsd2.lPitch);
1125
                    P2 := Pointer(Integer(ddsd2.lpSurface) + y * ddsd2.lPitch);
1126
                    for x := 0 to w - 1 do
1126
                    for x := 0 to w - 1 do
1127
                    begin
1127
                    begin
1128
                      if (PByte(P1)^ <> tc1) and (PByte(P2)^ <> tc2) then
1128
                      if (PByte(P1)^ <> tc1) and (PByte(P2)^ <> tc2) then
1129
                        Exit;
1129
                        Exit;
1130
                      Inc(PByte(P1));
1130
                      Inc(PByte(P1));
1131
                      Inc(PByte(P2));
1131
                      Inc(PByte(P2));
1132
                    end;
1132
                    end;
1133
                  end;
1133
                  end;
1134
                end;
1134
                end;
1135
              16:
1135
              16:
1136
                begin
1136
                begin
1137
                  for y := 0 to h - 1 do
1137
                  for y := 0 to h - 1 do
1138
                  begin
1138
                  begin
1139
                    P1 := Pointer(Integer(ddsd1.lpSurface) + y * ddsd1.lPitch);
1139
                    P1 := Pointer(Integer(ddsd1.lpSurface) + y * ddsd1.lPitch);
1140
                    P2 := Pointer(Integer(ddsd2.lpSurface) + y * ddsd2.lPitch);
1140
                    P2 := Pointer(Integer(ddsd2.lpSurface) + y * ddsd2.lPitch);
1141
                    for x := 0 to w - 1 do
1141
                    for x := 0 to w - 1 do
1142
                    begin
1142
                    begin
1143
                      if (PWord(P1)^ <> tc1) and (PWord(P2)^ <> tc2) then
1143
                      if (PWord(P1)^ <> tc1) and (PWord(P2)^ <> tc2) then
1144
                        Exit;
1144
                        Exit;
1145
                      Inc(PWord(P1));
1145
                      Inc(PWord(P1));
1146
                      Inc(PWord(P2));
1146
                      Inc(PWord(P2));
1147
                    end;
1147
                    end;
1148
                  end;
1148
                  end;
1149
                end;
1149
                end;
1150
              24:
1150
              24:
1151
                begin
1151
                begin
1152
                  for y := 0 to h - 1 do
1152
                  for y := 0 to h - 1 do
1153
                  begin
1153
                  begin
1154
                    P1 := Pointer(Integer(ddsd1.lpSurface) + y * ddsd1.lPitch);
1154
                    P1 := Pointer(Integer(ddsd1.lpSurface) + y * ddsd1.lPitch);
1155
                    P2 := Pointer(Integer(ddsd2.lpSurface) + y * ddsd2.lPitch);
1155
                    P2 := Pointer(Integer(ddsd2.lpSurface) + y * ddsd2.lPitch);
1156
                    for x := 0 to w - 1 do
1156
                    for x := 0 to w - 1 do
1157
                    begin
1157
                    begin
1158
                      with PRGB(P1)^ do
1158
                      with PRGB(P1)^ do
1159
                        if (R shl 16) or (G shl 8) or B <> tc1 then
1159
                        if (R shl 16) or (G shl 8) or B <> tc1 then
1160
                          Exit;
1160
                          Exit;
1161
                      with PRGB(P2)^ do
1161
                      with PRGB(P2)^ do
1162
                        if (R shl 16) or (G shl 8) or B <> tc2 then
1162
                        if (R shl 16) or (G shl 8) or B <> tc2 then
1163
                          Exit;
1163
                          Exit;
1164
                      Inc(PRGB(P1));
1164
                      Inc(PRGB(P1));
1165
                      Inc(PRGB(P2));
1165
                      Inc(PRGB(P2));
1166
                    end;
1166
                    end;
1167
                  end;
1167
                  end;
1168
                end;
1168
                end;
1169
              32:
1169
              32:
1170
                begin
1170
                begin
1171
                  for y := 0 to h - 1 do
1171
                  for y := 0 to h - 1 do
1172
                  begin
1172
                  begin
1173
                    P1 := Pointer(Integer(ddsd1.lpSurface) + y * ddsd1.lPitch);
1173
                    P1 := Pointer(Integer(ddsd1.lpSurface) + y * ddsd1.lPitch);
1174
                    P2 := Pointer(Integer(ddsd2.lpSurface) + y * ddsd2.lPitch);
1174
                    P2 := Pointer(Integer(ddsd2.lpSurface) + y * ddsd2.lPitch);
1175
                    for x := 0 to w - 1 do
1175
                    for x := 0 to w - 1 do
1176
                    begin
1176
                    begin
1177
                      if (PDWORD(P1)^ <> tc1) and (PDWORD(P2)^ <> tc2) then
1177
                      if (PDWORD(P1)^ <> tc1) and (PDWORD(P2)^ <> tc2) then
1178
                        Exit;
1178
                        Exit;
1179
                      Inc(PDWORD(P1));
1179
                      Inc(PDWORD(P1));
1180
                      Inc(PDWORD(P2));
1180
                      Inc(PDWORD(P2));
1181
                    end;
1181
                    end;
1182
                  end;
1182
                  end;
1183
                end;
1183
                end;
1184
            end;
1184
            end;
1185
          finally
1185
          finally
1186
            if suf1 <> suf2 then
1186
            if suf1 <> suf2 then
1187
              suf2.UnLock;
1187
              suf2.UnLock;
1188
          end;
1188
          end;
1189
        end;
1189
        end;
1190
      finally
1190
      finally
1191
        suf1.UnLock;
1191
        suf1.UnLock;
1192
      end;
1192
      end;
1193
    end;
1193
    end;
1194
 
1194
 
1195
    Result := False;
1195
    Result := False;
1196
  end;
1196
  end;
1197
end;
1197
end;
1198
 
1198
 
1199
{$HINTS ON}
1199
{$HINTS ON}
1200
{$WARNINGS ON}
1200
{$WARNINGS ON}
1201
 
1201
 
1202
function TImageSprite.TestCollision(Sprite: TSprite): Boolean;
1202
function TImageSprite.TestCollision(Sprite: TSprite): Boolean;
1203
var
1203
var
1204
  img1, img2: Integer;
1204
  img1, img2: Integer;
1205
  box1, box2: TRect;
1205
  box1, box2: TRect;
1206
begin
1206
begin
1207
  if (Sprite is TImageSprite) then
1207
  if (Sprite is TImageSprite) then
1208
    if FPixelCheck then
1208
    if FPixelCheck then
1209
    begin
1209
    begin
1210
      box1 := GetDrawRect;
1210
      box1 := GetDrawRect;
1211
      box2 := TImageSprite(Sprite).GetDrawRect;
1211
      box2 := TImageSprite(Sprite).GetDrawRect;
1212
 
1212
 
1213
      img1 := GetDrawImageIndex;
1213
      img1 := GetDrawImageIndex;
1214
      img2 := TImageSprite(Sprite).GetDrawImageIndex;
1214
      img2 := TImageSprite(Sprite).GetDrawImageIndex;
1215
 
1215
 
1216
      Result := ImageCollisionTest(Image.PatternSurfaces[img1],
1216
      Result := ImageCollisionTest(Image.PatternSurfaces[img1],
1217
        TImageSprite(Sprite).Image.PatternSurfaces[img2], Image.PatternRects[img1],
1217
        TImageSprite(Sprite).Image.PatternSurfaces[img2], Image.PatternRects[img1],
1218
        TImageSprite(Sprite).Image.PatternRects[img2], box1.Left, box1.Top,
1218
        TImageSprite(Sprite).Image.PatternRects[img2], box1.Left, box1.Top,
1219
        box2.Left, box2.Top, True);
1219
        box2.Left, box2.Top, True);
1220
    end
1220
    end
1221
    else
1221
    else
1222
      Result := OverlapRect(Bounds(Round(Sprite.WorldX), Round(Sprite.WorldY),
1222
      Result := OverlapRect(Bounds(Round(Sprite.WorldX), Round(Sprite.WorldY),
1223
        Sprite.Width, Sprite.Height), Bounds(Round(WorldX), Round(WorldY), Width, Height))
1223
        Sprite.Width, Sprite.Height), Bounds(Round(WorldX), Round(WorldY), Width, Height))
1224
  else
1224
  else
1225
    Result := inherited TestCollision(Sprite);
1225
    Result := inherited TestCollision(Sprite);
1226
end;
1226
end;
1227
 
1227
 
1228
procedure TImageSprite.Assign(Source: TPersistent);
1228
procedure TImageSprite.Assign(Source: TPersistent);
1229
begin
1229
begin
1230
  if Source is TImageSprite then begin
1230
  if Source is TImageSprite then begin
1231
    FCenterX := TImageSprite(Source).FCenterX;
1231
    FCenterX := TImageSprite(Source).FCenterX;
1232
    FCenterY := TImageSprite(Source).FCenterY;
1232
    FCenterY := TImageSprite(Source).FCenterY;
1233
    FAnimCount := TImageSprite(Source).FAnimCount;
1233
    FAnimCount := TImageSprite(Source).FAnimCount;
1234
    FAnimLooped := TImageSprite(Source).FAnimLooped;
1234
    FAnimLooped := TImageSprite(Source).FAnimLooped;
1235
    FAnimPos := TImageSprite(Source).FAnimPos;
1235
    FAnimPos := TImageSprite(Source).FAnimPos;
1236
    FAnimSpeed := TImageSprite(Source).FAnimSpeed;
1236
    FAnimSpeed := TImageSprite(Source).FAnimSpeed;
1237
    FAnimStart := TImageSprite(Source).FAnimStart;
1237
    FAnimStart := TImageSprite(Source).FAnimStart;
1238
    FDXImage := TImageSprite(Source).FDXImage;
1238
    FDXImage := TImageSprite(Source).FDXImage;
1239
    FPixelCheck := TImageSprite(Source).FPixelCheck;
1239
    FPixelCheck := TImageSprite(Source).FPixelCheck;
1240
    FTile := TImageSprite(Source).FTile;
1240
    FTile := TImageSprite(Source).FTile;
1241
    FTransparent := TImageSprite(Source).FTransparent;
1241
    FTransparent := TImageSprite(Source).FTransparent;
1242
    FAngle := TImageSprite(Source).FAngle;
1242
    FAngle := TImageSprite(Source).FAngle;
1243
    FAlpha := TImageSprite(Source).FAlpha;
1243
    FAlpha := TImageSprite(Source).FAlpha;
1244
    FBlendMode := TImageSprite(Source).FBlendMode;
1244
    FBlendMode := TImageSprite(Source).FBlendMode;
1245
    FBlurImage := TImageSprite(Source).FBlurImage;
1245
    FBlurImage := TImageSprite(Source).FBlurImage;
1246
  end;
1246
  end;
1247
  inherited;
1247
  inherited;
1248
end;
1248
end;
1249
 
1249
 
1250
procedure TImageSprite.ReAnimate(MoveCount: Integer);
1250
procedure TImageSprite.ReAnimate(MoveCount: Integer);
1251
var
1251
var
1252
  I: Integer;
1252
  I: Integer;
1253
begin
1253
begin
1254
  FAnimPos := FAnimPos + FAnimSpeed * MoveCount;
1254
  FAnimPos := FAnimPos + FAnimSpeed * MoveCount;
1255
 
1255
 
1256
  if FAnimLooped then
1256
  if FAnimLooped then
1257
  begin
1257
  begin
1258
    if FAnimCount > 0 then
1258
    if FAnimCount > 0 then
1259
      FAnimPos := Mod2f(FAnimPos, FAnimCount)
1259
      FAnimPos := Mod2f(FAnimPos, FAnimCount)
1260
    else
1260
    else
1261
      FAnimPos := 0;
1261
      FAnimPos := 0;
1262
  end
1262
  end
1263
  else
1263
  else
1264
  begin
1264
  begin
1265
    if Round(FAnimPos) >= FAnimCount then
1265
    if Round(FAnimPos) >= FAnimCount then
1266
    begin
1266
    begin
1267
      FAnimPos := FAnimCount - 1;
1267
      FAnimPos := FAnimCount - 1;
1268
      FAnimSpeed := 0;
1268
      FAnimSpeed := 0;
1269
    end;
1269
    end;
1270
    if FAnimPos < 0 then
1270
    if FAnimPos < 0 then
1271
    begin
1271
    begin
1272
      FAnimPos := 0;
1272
      FAnimPos := 0;
1273
      FAnimSpeed := 0;
1273
      FAnimSpeed := 0;
1274
    end;
1274
    end;
1275
  end;
1275
  end;
1276
  if FBlurImage then
1276
  if FBlurImage then
1277
  begin
1277
  begin
1278
    {ale jen jsou-li jine souradnice}
1278
    {ale jen jsou-li jine souradnice}
1279
    if (FBlurImageArr[High(FBlurImageArr)].eX <> Round(WorldX)) or
1279
    if (FBlurImageArr[High(FBlurImageArr)].eX <> Round(WorldX)) or
1280
    (FBlurImageArr[High(FBlurImageArr)].eY <> Round(WorldY)) then
1280
    (FBlurImageArr[High(FBlurImageArr)].eY <> Round(WorldY)) then
1281
    begin
1281
    begin
1282
      for i := Low(FBlurImageArr) + 1 to High(FBlurImageArr) do
1282
      for i := Low(FBlurImageArr) + 1 to High(FBlurImageArr) do
1283
      begin
1283
      begin
1284
        FBlurImageArr[i - 1] := FBlurImageArr[i];
1284
        FBlurImageArr[i - 1] := FBlurImageArr[i];
1285
        {adjust the blur intensity}
1285
        {adjust the blur intensity}
1286
        FBlurImageArr[i - 1].eIntensity := Round(FAlpha / (High(FBlurImageArr) + 1)) * (i - 1);
1286
        FBlurImageArr[i - 1].eIntensity := Round(FAlpha / (High(FBlurImageArr) + 1)) * (i - 1);
1287
      end;
1287
      end;
1288
      with FBlurImageArr[High(FBlurImageArr)] do
1288
      with FBlurImageArr[High(FBlurImageArr)] do
1289
      begin
1289
      begin
1290
        eX := Round(WorldX);
1290
        eX := Round(WorldX);
1291
        eY := Round(WorldY);
1291
        eY := Round(WorldY);
1292
        ePatternIndex := GetDrawImageIndex;
1292
        ePatternIndex := GetDrawImageIndex;
1293
        eIntensity := Round(FAlpha / (High(FBlurImageArr) + 1)) * High(FBlurImageArr);
1293
        eIntensity := Round(FAlpha / (High(FBlurImageArr) + 1)) * High(FBlurImageArr);
1294
        eBlendMode := FBlendMode;
1294
        eBlendMode := FBlendMode;
1295
        eActive := True;
1295
        eActive := True;
1296
      end;
1296
      end;
1297
    end;
1297
    end;
1298
  end;
1298
  end;
1299
end;
1299
end;
1300
 
1300
 
1301
function TImageSprite.StoreCenterX: Boolean;
1301
function TImageSprite.StoreCenterX: Boolean;
1302
begin
1302
begin
1303
  Result := FCenterX <> 0.5;
1303
  Result := FCenterX <> 0.5;
1304
end;
1304
end;
1305
 
1305
 
1306
function TImageSprite.StoreCenterY: Boolean;
1306
function TImageSprite.StoreCenterY: Boolean;
1307
begin
1307
begin
1308
  Result := FCenterY <> 0.5;
1308
  Result := FCenterY <> 0.5;
1309
end;
1309
end;
1310
 
1310
 
1311
function TImageSprite.StoreAlpha: Boolean;
1311
function TImageSprite.StoreAlpha: Boolean;
1312
begin
1312
begin
1313
  Result := FAlpha <> 0.0;
1313
  Result := FAlpha <> 0.0;
1314
end;
1314
end;
1315
 
1315
 
1316
procedure TImageSprite.DefineProperties(Filer: TFiler);
1316
procedure TImageSprite.DefineProperties(Filer: TFiler);
1317
begin
1317
begin
1318
  inherited DefineProperties(Filer);
1318
  inherited DefineProperties(Filer);
1319
  Filer.DefineProperty('BlendMode', ReadBlendMode, WriteBlendMode, FBlendMode <> rtDraw);
1319
  Filer.DefineProperty('BlendMode', ReadBlendMode, WriteBlendMode, FBlendMode <> rtDraw);
1320
  Filer.DefineProperty('Angle', ReadAngle, WriteAngle, FAngle <> 0);
1320
  Filer.DefineProperty('Angle', ReadAngle, WriteAngle, FAngle <> 0);
1321
  Filer.DefineProperty('CenterX', ReadCenterX, WriteCenterX, FCenterX <> 0.5);
1321
  Filer.DefineProperty('CenterX', ReadCenterX, WriteCenterX, FCenterX <> 0.5);
1322
  Filer.DefineProperty('CenterY', ReadCenterY, WriteCenterY, FCenterY <> 0.5);
1322
  Filer.DefineProperty('CenterY', ReadCenterY, WriteCenterY, FCenterY <> 0.5);
1323
  Filer.DefineProperty('Alpha', ReadAlpha, WriteAlpha, FAlpha <> $FF);
1323
  Filer.DefineProperty('Alpha', ReadAlpha, WriteAlpha, FAlpha <> $FF);
1324
  Filer.DefineProperty('AnimCount', ReadAnimCount, WriteAnimCount, FAnimCount <> 0);
1324
  Filer.DefineProperty('AnimCount', ReadAnimCount, WriteAnimCount, FAnimCount <> 0);
1325
  Filer.DefineProperty('AnimLooped', ReadAnimLooped, WriteAnimLooped, FAnimLooped);
1325
  Filer.DefineProperty('AnimLooped', ReadAnimLooped, WriteAnimLooped, FAnimLooped);
1326
  Filer.DefineProperty('AnimPos', ReadAnimPos, WriteAnimPos, FAnimPos <> 0);
1326
  Filer.DefineProperty('AnimPos', ReadAnimPos, WriteAnimPos, FAnimPos <> 0);
1327
  Filer.DefineProperty('AnimSpeed', ReadAnimSpeed, WriteAnimSpeed, FAnimSpeed <> 0);
1327
  Filer.DefineProperty('AnimSpeed', ReadAnimSpeed, WriteAnimSpeed, FAnimSpeed <> 0);
1328
  Filer.DefineProperty('AnimStart', ReadAnimStart, WriteAnimStart, True);
1328
  Filer.DefineProperty('AnimStart', ReadAnimStart, WriteAnimStart, True);
1329
  Filer.DefineProperty('PixelCheck', ReadPixelCheck, WritePixelCheck, FPixelCheck);
1329
  Filer.DefineProperty('PixelCheck', ReadPixelCheck, WritePixelCheck, FPixelCheck);
1330
  Filer.DefineProperty('Tile', ReadTile, WriteTile, FTile);
1330
  Filer.DefineProperty('Tile', ReadTile, WriteTile, FTile);
1331
  Filer.DefineProperty('BlurImage', ReadBlurImage, WriteBlurImage, FBlurImage);
1331
  Filer.DefineProperty('BlurImage', ReadBlurImage, WriteBlurImage, FBlurImage);
1332
  Filer.DefineProperty('MirrorFlip', ReadMirrorFlip, WriteMirrorFlip, FMirrorFlip <> []);
1332
  Filer.DefineProperty('MirrorFlip', ReadMirrorFlip, WriteMirrorFlip, FMirrorFlip <> []);
1333
  Filer.DefineProperty('TextureFilter', ReadTextureFilter, WriteTextureFilter, FTextureFilter <> D2D_POINT);
1333
  Filer.DefineProperty('TextureFilter', ReadTextureFilter, WriteTextureFilter, FTextureFilter <> D2D_POINT);
1334
end;
1334
end;
1335
 
1335
 
1336
procedure TImageSprite.WriteMirrorFlip(Writer: TWriter);
1336
procedure TImageSprite.WriteMirrorFlip(Writer: TWriter);
1337
var
1337
var
1338
  q: TRenderMirrorFlip;
1338
  q: TRenderMirrorFlip;
1339
  s, ss: string;
1339
  s, ss: string;
1340
//  I: Integer;
1340
//  I: Integer;
1341
  //PI: PPropInfo;
1341
  //PI: PPropInfo;
1342
begin
1342
begin
1343
//  PI := GetPropInfo(Self,'MirrorFlip');
1343
//  PI := GetPropInfo(Self,'MirrorFlip');
1344
//  I := Integer(FMirrorFlip);
1344
//  I := Integer(FMirrorFlip);
1345
  s := '[]'; ss := '';
1345
  s := '[]'; ss := '';
1346
  for q := Low(TRenderMirrorFlip) to High(TRenderMirrorFlip) do
1346
  for q := Low(TRenderMirrorFlip) to High(TRenderMirrorFlip) do
1347
    if q in FMirrorFlip then
1347
    if q in FMirrorFlip then
1348
      ss := ss + GetEnumName(TypeInfo(TRenderMirrorFlip), Ord(q)) + ', ';
1348
      ss := ss + GetEnumName(TypeInfo(TRenderMirrorFlip), Ord(q)) + ', ';
1349
  if ss <> '' then
1349
  if ss <> '' then
1350
    s := '[' + Copy(ss, 1, Length(ss) - 2) + ']';
1350
    s := '[' + Copy(ss, 1, Length(ss) - 2) + ']';
1351
  Writer.WriteString(s);
1351
  Writer.WriteString(s);
1352
//---  Writer.WriteString(SetToString(PI, GetOrdProp(Self, PI), True));
1352
//---  Writer.WriteString(SetToString(PI, GetOrdProp(Self, PI), True));
1353
end;
1353
end;
1354
 
1354
 
1355
procedure TImageSprite.ReadMirrorFlip(Reader: TReader);
1355
procedure TImageSprite.ReadMirrorFlip(Reader: TReader);
1356
var
1356
var
1357
  q: TRenderMirrorFlip;
1357
  q: TRenderMirrorFlip;
1358
  qq: TRenderMirrorFlipSet;
1358
  qq: TRenderMirrorFlipSet;
1359
  s {, ss}: string;
1359
  s {, ss}: string;
1360
//  PI: PPropInfo;
1360
//  PI: PPropInfo;
1361
begin
1361
begin
1362
//  PI := GetPropInfo(Self,'MirrorFlip');
1362
//  PI := GetPropInfo(Self,'MirrorFlip');
1363
//  SetOrdProp(Self,PI,StringToSet(PI, Reader.ReadString));
1363
//  SetOrdProp(Self,PI,StringToSet(PI, Reader.ReadString));
1364
  qq := [];
1364
  qq := [];
1365
  s := Reader.ReadString;
1365
  s := Reader.ReadString;
1366
  for q := Low(TRenderMirrorFlip) to High(TRenderMirrorFlip) do
1366
  for q := Low(TRenderMirrorFlip) to High(TRenderMirrorFlip) do
1367
    if Pos(GetEnumName(TypeInfo(TRenderMirrorFlip), Ord(q)), s) <> 0 then
1367
    if Pos(GetEnumName(TypeInfo(TRenderMirrorFlip), Ord(q)), s) <> 0 then
1368
      qq := qq + [q];
1368
      qq := qq + [q];
1369
  FMirrorFlip := qq;
1369
  FMirrorFlip := qq;
1370
end;
1370
end;
1371
 
1371
 
1372
procedure TImageSprite.ReadAnimLooped(Reader: TReader);
1372
procedure TImageSprite.ReadAnimLooped(Reader: TReader);
1373
begin
1373
begin
1374
  FAnimLooped := Reader.ReadBoolean;
1374
  FAnimLooped := Reader.ReadBoolean;
1375
end;
1375
end;
1376
 
1376
 
1377
procedure TImageSprite.WriteAnimLooped(Writer: TWriter);
1377
procedure TImageSprite.WriteAnimLooped(Writer: TWriter);
1378
begin
1378
begin
1379
  Writer.WriteBoolean(FAnimLooped);
1379
  Writer.WriteBoolean(FAnimLooped);
1380
end;
1380
end;
1381
 
1381
 
1382
procedure TImageSprite.ReadAnimPos(Reader: TReader);
1382
procedure TImageSprite.ReadAnimPos(Reader: TReader);
1383
begin
1383
begin
1384
  FAnimPos := Reader.ReadFloat;
1384
  FAnimPos := Reader.ReadFloat;
1385
end;
1385
end;
1386
 
1386
 
1387
procedure TImageSprite.WriteAnimPos(Writer: TWriter);
1387
procedure TImageSprite.WriteAnimPos(Writer: TWriter);
1388
begin
1388
begin
1389
  Writer.WriteFloat(FAnimPos);
1389
  Writer.WriteFloat(FAnimPos);
1390
end;
1390
end;
1391
 
1391
 
1392
procedure TImageSprite.ReadAnimSpeed(Reader: TReader);
1392
procedure TImageSprite.ReadAnimSpeed(Reader: TReader);
1393
begin
1393
begin
1394
  FAnimSpeed := Reader.ReadFloat;
1394
  FAnimSpeed := Reader.ReadFloat;
1395
end;
1395
end;
1396
 
1396
 
1397
procedure TImageSprite.WriteAnimSpeed(Writer: TWriter);
1397
procedure TImageSprite.WriteAnimSpeed(Writer: TWriter);
1398
begin
1398
begin
1399
  Writer.WriteFloat(FAnimSpeed);
1399
  Writer.WriteFloat(FAnimSpeed);
1400
end;
1400
end;
1401
 
1401
 
1402
procedure TImageSprite.ReadAnimStart(Reader: TReader);
1402
procedure TImageSprite.ReadAnimStart(Reader: TReader);
1403
begin
1403
begin
1404
  FAnimStart := Reader.ReadInteger;
1404
  FAnimStart := Reader.ReadInteger;
1405
end;
1405
end;
1406
 
1406
 
1407
procedure TImageSprite.WriteAnimStart(Writer: TWriter);
1407
procedure TImageSprite.WriteAnimStart(Writer: TWriter);
1408
begin
1408
begin
1409
  Writer.WriteInteger(FAnimStart);
1409
  Writer.WriteInteger(FAnimStart);
1410
end;
1410
end;
1411
 
1411
 
1412
procedure TImageSprite.ReadPixelCheck(Reader: TReader);
1412
procedure TImageSprite.ReadPixelCheck(Reader: TReader);
1413
begin
1413
begin
1414
  FPixelCheck := Reader.ReadBoolean;
1414
  FPixelCheck := Reader.ReadBoolean;
1415
end;
1415
end;
1416
 
1416
 
1417
procedure TImageSprite.WritePixelCheck(Writer: TWriter);
1417
procedure TImageSprite.WritePixelCheck(Writer: TWriter);
1418
begin
1418
begin
1419
  Writer.WriteBoolean(FPixelCheck);
1419
  Writer.WriteBoolean(FPixelCheck);
1420
end;
1420
end;
1421
 
1421
 
1422
procedure TImageSprite.ReadTile(Reader: TReader);
1422
procedure TImageSprite.ReadTile(Reader: TReader);
1423
begin
1423
begin
1424
  FTile := Reader.ReadBoolean;
1424
  FTile := Reader.ReadBoolean;
1425
end;
1425
end;
1426
 
1426
 
1427
procedure TImageSprite.WriteTile(Writer: TWriter);
1427
procedure TImageSprite.WriteTile(Writer: TWriter);
1428
begin
1428
begin
1429
  Writer.WriteBoolean(FTile);
1429
  Writer.WriteBoolean(FTile);
1430
end;
1430
end;
1431
 
1431
 
1432
procedure TImageSprite.ReadAnimCount(Reader: TReader);
1432
procedure TImageSprite.ReadAnimCount(Reader: TReader);
1433
begin
1433
begin
1434
  FAnimCount := Reader.ReadInteger;
1434
  FAnimCount := Reader.ReadInteger;
1435
end;
1435
end;
1436
 
1436
 
1437
procedure TImageSprite.WriteAnimCount(Writer: TWriter);
1437
procedure TImageSprite.WriteAnimCount(Writer: TWriter);
1438
begin
1438
begin
1439
  Writer.WriteInteger(FAnimCount);
1439
  Writer.WriteInteger(FAnimCount);
1440
end;
1440
end;
1441
 
1441
 
1442
procedure TImageSprite.ReadAlpha(Reader: TReader);
1442
procedure TImageSprite.ReadAlpha(Reader: TReader);
1443
begin
1443
begin
1444
  FAlpha := Reader.ReadInteger;
1444
  FAlpha := Reader.ReadInteger;
1445
end;
1445
end;
1446
 
1446
 
1447
procedure TImageSprite.WriteAlpha(Writer: TWriter);
1447
procedure TImageSprite.WriteAlpha(Writer: TWriter);
1448
begin
1448
begin
1449
  Writer.WriteInteger(FAlpha);
1449
  Writer.WriteInteger(FAlpha);
1450
end;
1450
end;
1451
 
1451
 
1452
procedure TImageSprite.ReadCenterY(Reader: TReader);
1452
procedure TImageSprite.ReadCenterY(Reader: TReader);
1453
begin
1453
begin
1454
  FCenterY := Reader.ReadFloat;
1454
  FCenterY := Reader.ReadFloat;
1455
end;
1455
end;
1456
 
1456
 
1457
procedure TImageSprite.WriteCenterY(Writer: TWriter);
1457
procedure TImageSprite.WriteCenterY(Writer: TWriter);
1458
begin
1458
begin
1459
  Writer.WriteFloat(FCenterY);
1459
  Writer.WriteFloat(FCenterY);
1460
end;
1460
end;
1461
 
1461
 
1462
procedure TImageSprite.ReadCenterX(Reader: TReader);
1462
procedure TImageSprite.ReadCenterX(Reader: TReader);
1463
begin
1463
begin
1464
  FCenterX := Reader.ReadFloat;
1464
  FCenterX := Reader.ReadFloat;
1465
end;
1465
end;
1466
 
1466
 
1467
procedure TImageSprite.WriteCenterX(Writer: TWriter);
1467
procedure TImageSprite.WriteCenterX(Writer: TWriter);
1468
begin
1468
begin
1469
  Writer.WriteFloat(FCenterX);
1469
  Writer.WriteFloat(FCenterX);
1470
end;
1470
end;
1471
 
1471
 
1472
procedure TImageSprite.ReadAngle(Reader: TReader);
1472
procedure TImageSprite.ReadAngle(Reader: TReader);
1473
begin
1473
begin
1474
  FAngle := Reader.{$IFDEF VER4UP}ReadSingle{$ELSE}ReadFloat{$ENDIF};
1474
  FAngle := Reader.{$IFDEF VER4UP}ReadSingle{$ELSE}ReadFloat{$ENDIF};
1475
end;
1475
end;
1476
 
1476
 
1477
procedure TImageSprite.WriteAngle(Writer: TWriter);
1477
procedure TImageSprite.WriteAngle(Writer: TWriter);
1478
begin
1478
begin
1479
  Writer.{$IFDEF VER4UP}WriteSingle{$ELSE}WriteFloat{$ENDIF}(FAngle);
1479
  Writer.{$IFDEF VER4UP}WriteSingle{$ELSE}WriteFloat{$ENDIF}(FAngle);
1480
end;
1480
end;
1481
 
1481
 
1482
procedure TImageSprite.ReadBlendMode(Reader: TReader);
1482
procedure TImageSprite.ReadBlendMode(Reader: TReader);
1483
begin
1483
begin
1484
  FBlendMode := TRenderType(GetEnumValue(TypeInfo(TRenderType), Reader.ReadString));
1484
  FBlendMode := TRenderType(GetEnumValue(TypeInfo(TRenderType), Reader.ReadString));
1485
end;
1485
end;
1486
 
1486
 
1487
procedure TImageSprite.WriteBlendMode(Writer: TWriter);
1487
procedure TImageSprite.WriteBlendMode(Writer: TWriter);
1488
begin
1488
begin
1489
  Writer.WriteString(GetEnumName(TypeInfo(TRenderType), Ord(FBlendMode)));
1489
  Writer.WriteString(GetEnumName(TypeInfo(TRenderType), Ord(FBlendMode)));
1490
end;
1490
end;
1491
 
1491
 
1492
procedure TImageSprite.ReadBlurImage(Reader: TReader);
1492
procedure TImageSprite.ReadBlurImage(Reader: TReader);
1493
begin
1493
begin
1494
  FBlurImage := Reader.ReadBoolean;
1494
  FBlurImage := Reader.ReadBoolean;
1495
end;
1495
end;
1496
 
1496
 
1497
procedure TImageSprite.WriteBlurImage(Writer: TWriter);
1497
procedure TImageSprite.WriteBlurImage(Writer: TWriter);
1498
begin
1498
begin
1499
  Writer.WriteBoolean(FBlurImage);
1499
  Writer.WriteBoolean(FBlurImage);
1500
end;
1500
end;
1501
 
1501
 
1502
procedure TImageSprite.ReadTextureFilter(Reader: TReader);
1502
procedure TImageSprite.ReadTextureFilter(Reader: TReader);
1503
begin
1503
begin
1504
  FTextureFilter := TD2DTextureFilter(Reader.ReadInteger);
1504
  FTextureFilter := TD2DTextureFilter(Reader.ReadInteger);
1505
end;
1505
end;
1506
 
1506
 
1507
procedure TImageSprite.WriteTextureFilter(Writer: TWriter);
1507
procedure TImageSprite.WriteTextureFilter(Writer: TWriter);
1508
begin
1508
begin
1509
  Writer.WriteInteger(Ord(FTextureFilter));
1509
  Writer.WriteInteger(Ord(FTextureFilter));
1510
end;
1510
end;
1511
 
1511
 
1512
procedure TImageSprite.SetBlurImageArr(const Value: TBlurImageArr);
1512
procedure TImageSprite.SetBlurImageArr(const Value: TBlurImageArr);
1513
begin
1513
begin
1514
  FBlurImageArr := Value;
1514
  FBlurImageArr := Value;
1515
end;
1515
end;
1516
 
1516
 
1517
procedure TImageSprite.SetBlurImage(const Value: Boolean);
1517
procedure TImageSprite.SetBlurImage(const Value: Boolean);
1518
begin
1518
begin
1519
  if (FBlurImage <> Value) and (Value) then
1519
  if (FBlurImage <> Value) and (Value) then
1520
  begin
1520
  begin
1521
    FillChar(FBlurImageArr, SizeOf(FBlurImageArr), 0); //get out when set up
1521
    FillChar(FBlurImageArr, SizeOf(FBlurImageArr), 0); //get out when set up
1522
  end;
1522
  end;
1523
  FBlurImage := Value;
1523
  FBlurImage := Value;
1524
end;
1524
end;
1525
 
1525
 
1526
function TImageSprite.GetImage: TPictureCollectionItem;
1526
function TImageSprite.GetImage: TPictureCollectionItem;
1527
begin
1527
begin
1528
  Result := FDXImage;
1528
  Result := FDXImage;
1529
end;
1529
end;
1530
 
1530
 
1531
procedure TImageSprite.SetMirrorFlip(const Value: TRenderMirrorFlipSet);
1531
procedure TImageSprite.SetMirrorFlip(const Value: TRenderMirrorFlipSet);
1532
begin
1532
begin
1533
  FMirrorFlip := Value;
1533
  FMirrorFlip := Value;
1534
end;
1534
end;
1535
 
1535
 
1536
{  TBackgroundSprite  }
1536
{  TBackgroundSprite  }
1537
 
1537
 
1538
constructor TBackgroundSprite.Create(AParent: TSprite);
1538
constructor TBackgroundSprite.Create(AParent: TSprite);
1539
begin
1539
begin
1540
  inherited Create(AParent);
1540
  inherited Create(AParent);
1541
  FMap := nil;
1541
  FMap := nil;
1542
  FMapWidth := 0;
1542
  FMapWidth := 0;
1543
  FMapHeight := 0;
1543
  FMapHeight := 0;
1544
  Collisioned := False;
1544
  Collisioned := False;
1545
end;
1545
end;
1546
 
1546
 
1547
destructor TBackgroundSprite.Destroy;
1547
destructor TBackgroundSprite.Destroy;
1548
begin
1548
begin
1549
  SetMapSize(0, 0);
1549
  SetMapSize(0, 0);
1550
  inherited Destroy;
1550
  inherited Destroy;
1551
end;
1551
end;
1552
 
1552
 
1553
procedure TBackgroundSprite.ChipsDraw(Image: TPictureCollectionItem; X, Y: Integer; PatternIndex: Integer);
1553
procedure TBackgroundSprite.ChipsDraw(Image: TPictureCollectionItem; X, Y: Integer; PatternIndex: Integer);
1554
begin
1554
begin
1555
  if AsSigned(FOnDraw) then
1555
  if AsSigned(FOnDraw) then
1556
    FOnDraw(Self)
1556
    FOnDraw(Self)
1557
  else
1557
  else
1558
  begin
1558
  begin
1559
    //Image.Draw(FEngine.Surface, X, Y, PatternIndex);
1559
    //Image.Draw(FEngine.Surface, X, Y, PatternIndex);
1560
    {New function implemented}
1560
    {New function implemented}
1561
    if Assigned(FEngine.FOwner) then
1561
    if Assigned(FEngine.FOwner) then
1562
      //Image.DrawAlpha(DXDraw1.Surface,ChipsRect,ChipsPatternIndex,Blend);
1562
      //Image.DrawAlpha(DXDraw1.Surface,ChipsRect,ChipsPatternIndex,Blend);
1563
      DXDraws.DXDraw_Paint(FEngine.FOwner.FDXDraw, Image, ChipsRect, ChipsPatternIndex,
1563
      DXDraws.DXDraw_Paint(FEngine.FOwner.FDXDraw, Image, ChipsRect, ChipsPatternIndex,
1564
        FBlurImageArr, FBlurImage, FTextureFilter, FMirrorFlip, FBlendMode, FAngle,
1564
        FBlurImageArr, FBlurImage, FTextureFilter, FMirrorFlip, FBlendMode, FAngle,
1565
        Map[X,Y].Alpha, FCenterX, FCenterY);
1565
        Map[X,Y].Alpha, FCenterX, FCenterY);
1566
  end;
1566
  end;
1567
end;
1567
end;
1568
 
1568
 
1569
procedure TBackgroundSprite.DoDraw;
1569
procedure TBackgroundSprite.DoDraw;
1570
var
1570
var
1571
  TmpX, TmpY, cx, cy, cx2, cy2, PatternIndex, ChipWidth, ChipHeight: Integer;
1571
  TmpX, TmpY, cx, cy, cx2, cy2, PatternIndex, ChipWidth, ChipHeight: Integer;
1572
  StartX, StartY, EndX, EndY, StartX_, StartY_, OfsX, OfsY, dWidth, dHeight: Integer;
1572
  StartX, StartY, EndX, EndY, StartX_, StartY_, OfsX, OfsY, dWidth, dHeight: Integer;
1573
  r: TRect;
1573
  r: TRect;
1574
  Q: TMapType;
1574
  Q: TMapType;
1575
begin
1575
begin
1576
  LoadImage;
1576
  LoadImage;
1577
  if Image = nil then
1577
  if Image = nil then
1578
    Exit;
1578
    Exit;
1579
 
1579
 
1580
  if (FMapWidth <= 0) or (FMapHeight <= 0) then
1580
  if (FMapWidth <= 0) or (FMapHeight <= 0) then
1581
    Exit;
1581
    Exit;
1582
 
1582
 
1583
  r := Image.PatternRects[0];
1583
  r := Image.PatternRects[0];
1584
  ChipWidth := r.Right - r.Left;
1584
  ChipWidth := r.Right - r.Left;
1585
  ChipHeight := r.Bottom - r.Top;
1585
  ChipHeight := r.Bottom - r.Top;
1586
 
1586
 
1587
  dWidth := (FEngine.SurfaceRect.Right + ChipWidth) div ChipWidth + 1;
1587
  dWidth := (FEngine.SurfaceRect.Right + ChipWidth) div ChipWidth + 1;
1588
  dHeight := (FEngine.SurfaceRect.Bottom + ChipHeight) div ChipHeight + 1;
1588
  dHeight := (FEngine.SurfaceRect.Bottom + ChipHeight) div ChipHeight + 1;
1589
 
1589
 
1590
  TmpX := Round(WorldX);
1590
  TmpX := Round(WorldX);
1591
  TmpY := Round(WorldY);
1591
  TmpY := Round(WorldY);
1592
 
1592
 
1593
  OfsX := TmpX mod ChipWidth;
1593
  OfsX := TmpX mod ChipWidth;
1594
  OfsY := TmpY mod ChipHeight;
1594
  OfsY := TmpY mod ChipHeight;
1595
 
1595
 
1596
  StartX := TmpX div ChipWidth;
1596
  StartX := TmpX div ChipWidth;
1597
  StartX_ := 0;
1597
  StartX_ := 0;
1598
 
1598
 
1599
  if StartX < 0 then
1599
  if StartX < 0 then
1600
  begin
1600
  begin
1601
    StartX_ := -StartX;
1601
    StartX_ := -StartX;
1602
    StartX := 0;
1602
    StartX := 0;
1603
  end;
1603
  end;
1604
 
1604
 
1605
  StartY := TmpY div ChipHeight;
1605
  StartY := TmpY div ChipHeight;
1606
  StartY_ := 0;
1606
  StartY_ := 0;
1607
 
1607
 
1608
  if StartY < 0 then
1608
  if StartY < 0 then
1609
  begin
1609
  begin
1610
    StartY_ := -StartY;
1610
    StartY_ := -StartY;
1611
    StartY := 0;
1611
    StartY := 0;
1612
  end;
1612
  end;
1613
 
1613
 
1614
  EndX := Min(StartX + FMapWidth - StartX_, dWidth);
1614
  EndX := Min(StartX + FMapWidth - StartX_, dWidth);
1615
  EndY := Min(StartY + FMapHeight - StartY_, dHeight);
1615
  EndY := Min(StartY + FMapHeight - StartY_, dHeight);
1616
 
1616
 
1617
  if FTile then
1617
  if FTile then
1618
  begin
1618
  begin
1619
    for cy := -1 to dHeight do
1619
    for cy := -1 to dHeight do
1620
    begin
1620
    begin
1621
      cy2 := Mod2((cy - StartY + StartY_), FMapHeight);
1621
      cy2 := Mod2((cy - StartY + StartY_), FMapHeight);
1622
      for cx := -1 to dWidth do
1622
      for cx := -1 to dWidth do
1623
      begin
1623
      begin
1624
        cx2 := Mod2((cx - StartX + StartX_), FMapWidth);
1624
        cx2 := Mod2((cx - StartX + StartX_), FMapWidth);
1625
        PatternIndex := Chips[cx2, cy2];
1625
        PatternIndex := Chips[cx2, cy2];
1626
        ChipsPatternIndex := PatternIndex; //refresh only
1626
        ChipsPatternIndex := PatternIndex; //refresh only
1627
        ChipsRect := Bounds(cx * ChipWidth + OfsX, cy * ChipHeight + OfsY, ChipWidth, ChipHeight);
1627
        ChipsRect := Bounds(cx * ChipWidth + OfsX, cy * ChipHeight + OfsY, ChipWidth, ChipHeight);
1628
        if PatternIndex >= 0 then
1628
        if PatternIndex >= 0 then
1629
        begin
1629
        begin
1630
          if AsSigned(FOnDraw) then
1630
          if AsSigned(FOnDraw) then
1631
            FOnDraw(Self)
1631
            FOnDraw(Self)
1632
          else
1632
          else
1633
          begin
1633
          begin
1634
            {New function implemented}
1634
            {New function implemented}
1635
            if Assigned(FEngine.FOwner) then
1635
            if Assigned(FEngine.FOwner) then
1636
            begin
1636
            begin
1637
              Q := Map[cx2,cy2];
1637
              Q := Map[cx2,cy2];
1638
              DXDraws.DXDraw_Paint(FEngine.FOwner.FDXDraw, Image, ChipsRect, Q.MapChip,
1638
              DXDraws.DXDraw_Paint(FEngine.FOwner.FDXDraw, Image, ChipsRect, Q.MapChip,
1639
                FBlurImageArr, FBlurImage, Q.TextureFilter, Q.MirrorFlip, Q.Rendered, Q.Angle,
1639
                FBlurImageArr, FBlurImage, Q.TextureFilter, Q.MirrorFlip, Q.Rendered, Q.Angle,
1640
                Q.Alpha, Q.CenterX, Q.CenterY);
1640
                Q.Alpha, Q.CenterX, Q.CenterY);
1641
            end;
1641
            end;
1642
          end;
1642
          end;
1643
        end;
1643
        end;
1644
      end;
1644
      end;
1645
    end;
1645
    end;
1646
  end
1646
  end
1647
  else
1647
  else
1648
  begin
1648
  begin
1649
    for cy := StartY to EndY - 1 do
1649
    for cy := StartY to EndY - 1 do
1650
      for cx := StartX to EndX - 1 do
1650
      for cx := StartX to EndX - 1 do
1651
      begin
1651
      begin
1652
        PatternIndex := Chips[cx - StartX + StartX_, cy - StartY + StartY_];
1652
        PatternIndex := Chips[cx - StartX + StartX_, cy - StartY + StartY_];
1653
        ChipsPatternIndex := PatternIndex; //refresh only
1653
        ChipsPatternIndex := PatternIndex; //refresh only
1654
        ChipsRect := Bounds(cx * ChipWidth + OfsX, cy * ChipHeight + OfsY, ChipWidth, ChipHeight);
1654
        ChipsRect := Bounds(cx * ChipWidth + OfsX, cy * ChipHeight + OfsY, ChipWidth, ChipHeight);
1655
        if PatternIndex >= 0 then
1655
        if PatternIndex >= 0 then
1656
        begin
1656
        begin
1657
          if AsSigned(FOnDraw) then
1657
          if AsSigned(FOnDraw) then
1658
            FOnDraw(Self)
1658
            FOnDraw(Self)
1659
          else
1659
          else
1660
          begin
1660
          begin
1661
            {New function implemented}
1661
            {New function implemented}
1662
            if Assigned(FEngine.FOwner) then
1662
            if Assigned(FEngine.FOwner) then
1663
            begin
1663
            begin
1664
              Q := Map[cx,cy];
1664
              Q := Map[cx,cy];
1665
              DXDraws.DXDraw_Paint(FEngine.FOwner.FDXDraw, Image, ChipsRect, Q.MapChip,
1665
              DXDraws.DXDraw_Paint(FEngine.FOwner.FDXDraw, Image, ChipsRect, Q.MapChip,
1666
                FBlurImageArr, FBlurImage, Q.TextureFilter, Q.MirrorFlip, Q.Rendered, Q.Angle,
1666
                FBlurImageArr, FBlurImage, Q.TextureFilter, Q.MirrorFlip, Q.Rendered, Q.Angle,
1667
                Q.Alpha, Q.CenterX, Q.CenterY);
1667
                Q.Alpha, Q.CenterX, Q.CenterY);
1668
            end;
1668
            end;
1669
          end;
1669
          end;
1670
        end
1670
        end
1671
      end;
1671
      end;
1672
  end;
1672
  end;
1673
end;
1673
end;
1674
 
1674
 
1675
function TBackgroundSprite.TestCollision(Sprite: TSprite): Boolean;
1675
function TBackgroundSprite.TestCollision(Sprite: TSprite): Boolean;
1676
var
1676
var
1677
  box0, box1, box2: TRect;
1677
  box0, box1, box2: TRect;
1678
  cx, cy, ChipWidth, ChipHeight: Integer;
1678
  cx, cy, ChipWidth, ChipHeight: Integer;
1679
  r: TRect;
1679
  r: TRect;
1680
begin
1680
begin
1681
  Result := True;
1681
  Result := True;
1682
  if Image = nil then
1682
  if Image = nil then
1683
    Exit;
1683
    Exit;
1684
  if (FMapWidth <= 0) or (FMapHeight <= 0) then
1684
  if (FMapWidth <= 0) or (FMapHeight <= 0) then
1685
    Exit;
1685
    Exit;
1686
 
1686
 
1687
  r := Image.PatternRects[0];
1687
  r := Image.PatternRects[0];
1688
  ChipWidth := r.Right - r.Left;
1688
  ChipWidth := r.Right - r.Left;
1689
  ChipHeight := r.Bottom - r.Top;
1689
  ChipHeight := r.Bottom - r.Top;
1690
 
1690
 
1691
  box1 := Sprite.BoundsRect;
1691
  box1 := Sprite.BoundsRect;
1692
  box2 := BoundsRect;
1692
  box2 := BoundsRect;
1693
 
1693
 
1694
  IntersectRect(box0, box1, box2);
1694
  IntersectRect(box0, box1, box2);
1695
 
1695
 
1696
  OffsetRect(box0, -Round(WorldX), -Round(WorldY));
1696
  OffsetRect(box0, -Round(WorldX), -Round(WorldY));
1697
  OffsetRect(box1, -Round(WorldX), -Round(WorldY));
1697
  OffsetRect(box1, -Round(WorldX), -Round(WorldY));
1698
 
1698
 
1699
  for cy := (box0.Top - ChipHeight + 1) div ChipHeight to box0.Bottom div ChipHeight do
1699
  for cy := (box0.Top - ChipHeight + 1) div ChipHeight to box0.Bottom div ChipHeight do
1700
    for cx := (box0.Left - ChipWidth + 1) div ChipWidth to box0.Right div ChipWidth do
1700
    for cx := (box0.Left - ChipWidth + 1) div ChipWidth to box0.Right div ChipWidth do
1701
      if CollisionMap[Mod2(cx, MapWidth), Mod2(cy, MapHeight)] then
1701
      if CollisionMap[Mod2(cx, MapWidth), Mod2(cy, MapHeight)] then
1702
      begin
1702
      begin
1703
        if OverlapRect(Bounds(cx * ChipWidth, cy * ChipHeight, ChipWidth,
1703
        if OverlapRect(Bounds(cx * ChipWidth, cy * ChipHeight, ChipWidth,
1704
          ChipHeight), box1) then
1704
          ChipHeight), box1) then
1705
          Exit;
1705
          Exit;
1706
      end;
1706
      end;
1707
 
1707
 
1708
  Result := False;
1708
  Result := False;
1709
end;
1709
end;
1710
 
1710
 
1711
function TBackgroundSprite.GetChip(X, Y: Integer): Integer;
1711
function TBackgroundSprite.GetChip(X, Y: Integer): Integer;
1712
begin
1712
begin
1713
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1713
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1714
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.MapChip
1714
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.MapChip
1715
  else
1715
  else
1716
    Result := -1;
1716
    Result := -1;
1717
end;
1717
end;
1718
 
1718
 
1719
function TBackgroundSprite.GetCollisionMapItem(X, Y: Integer): Boolean;
1719
function TBackgroundSprite.GetCollisionMapItem(X, Y: Integer): Boolean;
1720
begin
1720
begin
1721
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1721
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1722
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.CollisionChip
1722
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.CollisionChip
1723
  else
1723
  else
1724
    Result := False;
1724
    Result := False;
1725
end;
1725
end;
1726
 
1726
 
1727
function TBackgroundSprite.GetCollisionRectItem(X, Y: Integer): TRect;
1727
function TBackgroundSprite.GetCollisionRectItem(X, Y: Integer): TRect;
1728
begin
1728
begin
1729
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1729
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1730
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.CollisionRect
1730
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.CollisionRect
1731
  else
1731
  else
1732
    Result := Rect(0, 0, 0, 0);
1732
    Result := Rect(0, 0, 0, 0);
1733
end;
1733
end;
1734
 
1734
 
1735
function TBackgroundSprite.GetTagMap(X, Y: Integer): Integer;
1735
function TBackgroundSprite.GetTagMap(X, Y: Integer): Integer;
1736
begin
1736
begin
1737
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1737
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1738
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.Tag
1738
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.Tag
1739
  else
1739
  else
1740
    Result := 0;
1740
    Result := 0;
1741
end;
1741
end;
1742
 
1742
 
1743
function TBackgroundSprite.GetMap(X, Y: Integer): TMapType;
1743
function TBackgroundSprite.GetMap(X, Y: Integer): TMapType;
1744
begin
1744
begin
1745
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1745
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1746
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^
1746
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^
1747
  else
1747
  else
1748
    FillChar(Result, SizeOf(Result), 0);
1748
    FillChar(Result, SizeOf(Result), 0);
1749
end;
1749
end;
1750
 
1750
 
1751
function TBackgroundSprite.GetBoundsRect: TRect;
1751
function TBackgroundSprite.GetBoundsRect: TRect;
1752
begin
1752
begin
1753
  if FTile then
1753
  if FTile then
1754
    Result := FEngine.SurfaceRect
1754
    Result := FEngine.SurfaceRect
1755
  else
1755
  else
1756
  begin
1756
  begin
1757
    LoadImage;
1757
    LoadImage;
1758
    if Image <> nil then
1758
    if Image <> nil then
1759
      Result := Bounds(Round(WorldX), Round(WorldY), Image.Width * FMapWidth,
1759
      Result := Bounds(Round(WorldX), Round(WorldY), Image.Width * FMapWidth,
1760
        Image.Height * FMapHeight)
1760
        Image.Height * FMapHeight)
1761
    else
1761
    else
1762
      Result := Rect(0, 0, 0, 0);
1762
      Result := Rect(0, 0, 0, 0);
1763
  end;
1763
  end;
1764
end;
1764
end;
1765
 
1765
 
1766
procedure TBackgroundSprite.SetChip(X, Y: Integer; Value: Integer);
1766
procedure TBackgroundSprite.SetChip(X, Y: Integer; Value: Integer);
1767
begin
1767
begin
1768
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1768
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1769
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.MapChip := Value;
1769
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.MapChip := Value;
1770
end;
1770
end;
1771
 
1771
 
1772
procedure TBackgroundSprite.SetCollisionMapItem(X, Y: Integer; Value: Boolean);
1772
procedure TBackgroundSprite.SetCollisionMapItem(X, Y: Integer; Value: Boolean);
1773
begin
1773
begin
1774
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1774
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1775
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.CollisionChip := Value;
1775
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.CollisionChip := Value;
1776
end;
1776
end;
1777
 
1777
 
1778
procedure TBackgroundSprite.SetCollisionRectItem(X, Y: Integer; Value: TRect);
1778
procedure TBackgroundSprite.SetCollisionRectItem(X, Y: Integer; Value: TRect);
1779
begin
1779
begin
1780
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1780
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1781
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.CollisionRect := Value;
1781
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.CollisionRect := Value;
1782
end;
1782
end;
1783
 
1783
 
1784
procedure TBackgroundSprite.SetTagMap(X, Y: Integer; Value: Integer);
1784
procedure TBackgroundSprite.SetTagMap(X, Y: Integer; Value: Integer);
1785
begin
1785
begin
1786
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1786
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1787
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.Tag := Value;
1787
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.Tag := Value;
1788
end;
1788
end;
1789
 
1789
 
1790
procedure TBackgroundSprite.SetMap(X, Y: Integer; Value: TMapType);
1790
procedure TBackgroundSprite.SetMap(X, Y: Integer; Value: TMapType);
1791
begin
1791
begin
1792
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1792
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1793
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^ := Value;
1793
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^ := Value;
1794
end;
1794
end;
1795
 
1795
 
1796
procedure TBackgroundSprite.SetMapHeight(Value: Integer);
1796
procedure TBackgroundSprite.SetMapHeight(Value: Integer);
1797
begin
1797
begin
1798
  SetMapSize(FMapWidth, Value);
1798
  SetMapSize(FMapWidth, Value);
1799
end;
1799
end;
1800
 
1800
 
1801
procedure TBackgroundSprite.SetMapWidth(Value: Integer);
1801
procedure TBackgroundSprite.SetMapWidth(Value: Integer);
1802
begin
1802
begin
1803
  SetMapSize(Value, FMapHeight);
1803
  SetMapSize(Value, FMapHeight);
1804
end;
1804
end;
1805
 
1805
 
1806
procedure TBackgroundSprite.SetImage(Img: TPictureCollectionItem);
1806
procedure TBackgroundSprite.SetImage(Img: TPictureCollectionItem);
1807
begin
1807
begin
1808
  inherited SetImage(Img);
1808
  inherited SetImage(Img);
1809
  if Assigned(Img) then
1809
  if Assigned(Img) then
1810
  begin
1810
  begin
1811
    FWidth := FMapWidth * Img.Width;
1811
    FWidth := FMapWidth * Img.Width;
1812
    FHeight := FMapHeight * Img.Height;
1812
    FHeight := FMapHeight * Img.Height;
1813
  end
1813
  end
1814
  else
1814
  else
1815
  begin
1815
  begin
1816
    FWidth := 0;
1816
    FWidth := 0;
1817
    FHeight := 0;
1817
    FHeight := 0;
1818
  end;
1818
  end;
1819
end;
1819
end;
1820
 
1820
 
1821
procedure TBackgroundSprite.SetMapSize(AMapWidth, AMapHeight: Integer);
1821
procedure TBackgroundSprite.SetMapSize(AMapWidth, AMapHeight: Integer);
1822
var I: Integer;
1822
var I: Integer;
1823
begin
1823
begin
1824
  if (FMapWidth <> AMapWidth) or (FMapHeight <> AMapHeight) or (FMap = nil) then
1824
  if (FMapWidth <> AMapWidth) or (FMapHeight <> AMapHeight) or (FMap = nil) then
1825
  begin
1825
  begin
1826
    try
1826
    try
1827
      if (AMapWidth <= 0) or (AMapHeight <= 0) then
1827
      if (AMapWidth <= 0) or (AMapHeight <= 0) then
1828
      begin
1828
      begin
1829
        FreeMem(FMap, FMapWidth * FMapHeight * SizeOf(TMapType)); FMap := nil;
1829
        FreeMem(FMap, FMapWidth * FMapHeight * SizeOf(TMapType)); FMap := nil;
1830
        AMapWidth := 0;
1830
        AMapWidth := 0;
1831
        AMapHeight := 0;
1831
        AMapHeight := 0;
1832
      end;
1832
      end;
1833
      FMapWidth := AMapWidth;
1833
      FMapWidth := AMapWidth;
1834
      FMapHeight := AMapHeight;
1834
      FMapHeight := AMapHeight;
1835
      System.ReallocMem(FMap, FMapWidth * FMapHeight * SizeOf(TMapType));
1835
      System.ReallocMem(FMap, FMapWidth * FMapHeight * SizeOf(TMapType));
1836
      if Assigned(FMap) then
1836
      if Assigned(FMap) then
1837
      begin
1837
      begin
1838
        FillChar(FMap^, FMapWidth * FMapHeight * SizeOf(TMapType), 0);
1838
        FillChar(FMap^, FMapWidth * FMapHeight * SizeOf(TMapType), 0);
1839
        for I := 0 to FMapWidth * FMapHeight - 1 do
1839
        for I := 0 to FMapWidth * FMapHeight - 1 do
1840
          PMapType(Integer(FMap) + (I) * SizeOf(TMapType))^.CollisionChip := True;
1840
          PMapType(Integer(FMap) + (I) * SizeOf(TMapType))^.CollisionChip := True;
1841
      end
1841
      end
1842
    except
1842
    except
1843
      FreeMem(FMap, FMapWidth * FMapHeight * SizeOf(TMapType));
1843
      FreeMem(FMap, FMapWidth * FMapHeight * SizeOf(TMapType));
1844
      FMap := nil;
1844
      FMap := nil;
1845
    end;
1845
    end;
1846
  end
1846
  end
1847
end;
1847
end;
1848
 
1848
 
1849
procedure TBackgroundSprite.Assign(Source: TPersistent);
1849
procedure TBackgroundSprite.Assign(Source: TPersistent);
1850
begin
1850
begin
1851
  if Source is TBackgroundSprite then
1851
  if Source is TBackgroundSprite then
1852
  begin
1852
  begin
1853
    FMapWidth := TBackgroundSprite(Source).FMapWidth;
1853
    FMapWidth := TBackgroundSprite(Source).FMapWidth;
1854
    FMapHeight := TBackgroundSprite(Source).FMapHeight;
1854
    FMapHeight := TBackgroundSprite(Source).FMapHeight;
1855
    FTile := TBackgroundSprite(Source).FTile;
1855
    FTile := TBackgroundSprite(Source).FTile;
1856
  end;
1856
  end;
1857
  inherited;
1857
  inherited;
1858
end;
1858
end;
1859
 
1859
 
1860
procedure TBackgroundSprite.DefineProperties(Filer: TFiler);
1860
procedure TBackgroundSprite.DefineProperties(Filer: TFiler);
1861
begin
1861
begin
1862
  inherited DefineProperties(Filer);
1862
  inherited DefineProperties(Filer);
1863
  Filer.DefineBinaryProperty('Map', ReadMapData, WriteMapData, FMap <> nil);
1863
  Filer.DefineBinaryProperty('Map', ReadMapData, WriteMapData, FMap <> nil);
1864
end;
1864
end;
1865
 
1865
 
1866
type
1866
type
1867
  TMapDataHeader = packed record
1867
  TMapDataHeader = packed record
1868
    MapWidth: Integer;
1868
    MapWidth: Integer;
1869
    MapHeight: Integer;
1869
    MapHeight: Integer;
1870
  end;
1870
  end;
1871
 
1871
 
1872
procedure TBackgroundSprite.ReadMapData(Stream: TStream);
1872
procedure TBackgroundSprite.ReadMapData(Stream: TStream);
1873
var
1873
var
1874
  Header: TMapDataHeader;
1874
  Header: TMapDataHeader;
1875
begin
1875
begin
1876
  Stream.ReadBuffer(Header, SizeOf(Header));
1876
  Stream.ReadBuffer(Header, SizeOf(Header));
1877
  FMapWidth := Header.MapWidth;
1877
  FMapWidth := Header.MapWidth;
1878
  FMapHeight := Header.MapHeight;
1878
  FMapHeight := Header.MapHeight;
1879
  SetMapSize(Header.MapWidth, Header.MapHeight);
1879
  SetMapSize(Header.MapWidth, Header.MapHeight);
1880
  if Assigned(FMap) and (Header.MapWidth > 0) and (Header.MapHeight > 0) then
1880
  if Assigned(FMap) and (Header.MapWidth > 0) and (Header.MapHeight > 0) then
1881
  begin
1881
  begin
1882
    Stream.ReadBuffer(FMap^, FMapWidth * FMapHeight * SizeOf(TMapType));
1882
    Stream.ReadBuffer(FMap^, FMapWidth * FMapHeight * SizeOf(TMapType));
1883
  end;
1883
  end;
1884
end;
1884
end;
1885
 
1885
 
1886
procedure TBackgroundSprite.WriteMapData(Stream: TStream);
1886
procedure TBackgroundSprite.WriteMapData(Stream: TStream);
1887
var
1887
var
1888
  Header: TMapDataHeader;
1888
  Header: TMapDataHeader;
1889
begin
1889
begin
1890
  Header.MapWidth := FMapWidth;
1890
  Header.MapWidth := FMapWidth;
1891
  Header.MapHeight := FMapHeight;
1891
  Header.MapHeight := FMapHeight;
1892
  Stream.WriteBuffer(Header, SizeOf(Header));
1892
  Stream.WriteBuffer(Header, SizeOf(Header));
1893
  if Assigned(FMap) then
1893
  if Assigned(FMap) then
1894
    Stream.WriteBuffer(FMap^, FMapWidth * FMapHeight * SizeOf(TMapType));
1894
    Stream.WriteBuffer(FMap^, FMapWidth * FMapHeight * SizeOf(TMapType));
1895
end;
1895
end;
1896
 
1896
 
1897
function TBackgroundSprite.GetOverlap(X, Y: Integer): Integer;
1897
function TBackgroundSprite.GetOverlap(X, Y: Integer): Integer;
1898
begin
1898
begin
1899
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1899
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1900
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.Overlap
1900
    Result := PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.Overlap
1901
  else
1901
  else
1902
    Result := 0;
1902
    Result := 0;
1903
end;
1903
end;
1904
 
1904
 
1905
procedure TBackgroundSprite.SetOverlap(X, Y: Integer; const Value: Integer);
1905
procedure TBackgroundSprite.SetOverlap(X, Y: Integer; const Value: Integer);
1906
begin
1906
begin
1907
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1907
  if (X >= 0) and (X < FMapWidth) and (Y >= 0) and (Y < FMapHeight) then
1908
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.Overlap := Value;
1908
    PMapType(Integer(FMap) + (Y * FMapWidth + X) * SizeOf(TMapType))^.Overlap := Value;
1909
end;
1909
end;
1910
 
1910
 
1911
function TBackgroundSprite.IsMapEmpty: Boolean;
1911
function TBackgroundSprite.IsMapEmpty: Boolean;
1912
begin
1912
begin
1913
  Result := (FMap = nil) or (FMapWidth <= 0) or (FMapHeight <= 0);
1913
  Result := (FMap = nil) or (FMapWidth <= 0) or (FMapHeight <= 0);
1914
end;
1914
end;
1915
 
1915
 
1916
{  TSpriteEngine  }
1916
{  TSpriteEngine  }
1917
 
1917
 
1918
constructor TSpriteEngine.Create(AParent: TSprite);
1918
constructor TSpriteEngine.Create(AParent: TSprite);
1919
begin
1919
begin
1920
  inherited Create(AParent);
1920
  inherited Create(AParent);
1921
  FDeadList := TList.Create;
1921
  FDeadList := TList.Create;
1922
  // group handling
1922
  // group handling
1923
{$IFDEF Ver4Up}
1923
{$IFDEF Ver4Up}
1924
  fCurrentSelected := Tlist.create;
1924
  fCurrentSelected := Tlist.create;
1925
  GroupCount := 10;
1925
  GroupCount := 10;
1926
{$ENDIF}
1926
{$ENDIF}
1927
end;
1927
end;
1928
 
1928
 
1929
destructor TSpriteEngine.Destroy;
1929
destructor TSpriteEngine.Destroy;
1930
begin
1930
begin
1931
  // cleanup Group handling
1931
  // cleanup Group handling
1932
{$IFDEF Ver4Up}
1932
{$IFDEF Ver4Up}
1933
  ClearCurrent;
1933
  ClearCurrent;
1934
  GroupCount := 0;
1934
  GroupCount := 0;
1935
{$ENDIF}
1935
{$ENDIF}
1936
  FDeadList.Free;
1936
  FDeadList.Free;
1937
  inherited Destroy;
1937
  inherited Destroy;
1938
{$IFDEF Ver4Up}
1938
{$IFDEF Ver4Up}
1939
  fCurrentSelected.free;
1939
  fCurrentSelected.free;
1940
{$ENDIF}
1940
{$ENDIF}
1941
end;
1941
end;
1942
 
1942
 
1943
procedure TSpriteEngine.Collisions;
1943
procedure TSpriteEngine.Collisions;
1944
var
1944
var
1945
  index: Integer;
1945
  index: Integer;
1946
begin
1946
begin
1947
  for index := 0 to Count - 1 do
1947
  for index := 0 to Count - 1 do
1948
    Items[index].Collision;
1948
    Items[index].Collision;
1949
end;
1949
end;
1950
{Collisions}
1950
{Collisions}
1951
{$IFDEF Ver4Up}
1951
{$IFDEF Ver4Up}
1952
 
1952
 
1953
procedure TSpriteEngine.GroupSelect(const Area: TRect; Add: Boolean = False);
1953
procedure TSpriteEngine.GroupSelect(const Area: TRect; Add: Boolean = False);
1954
begin
1954
begin
1955
  GroupSelect(Area, [Tsprite], Add);
1955
  GroupSelect(Area, [Tsprite], Add);
1956
end; {GroupSelect}
1956
end; {GroupSelect}
1957
 
1957
 
1958
procedure TSpriteEngine.GroupSelect(const Area: TRect; Filter: array of TSpriteClass; Add: Boolean = False);
1958
procedure TSpriteEngine.GroupSelect(const Area: TRect; Filter: array of TSpriteClass; Add: Boolean = False);
1959
var
1959
var
1960
  index, index2: Integer;
1960
  index, index2: Integer;
1961
  sprite: TSprite;
1961
  sprite: TSprite;
1962
begin
1962
begin
1963
  Assert(length(Filter) <> 0, 'Filter = []');
1963
  Assert(length(Filter) <> 0, 'Filter = []');
1964
  if not Add then
1964
  if not Add then
1965
    ClearCurrent;
1965
    ClearCurrent;
1966
  if length(Filter) = 1 then
1966
  if length(Filter) = 1 then
1967
  begin
1967
  begin
1968
    for Index := 0 to Count - 1 do
1968
    for Index := 0 to Count - 1 do
1969
    begin
1969
    begin
1970
      sprite := Items[Index];
1970
      sprite := Items[Index];
1971
      if (sprite is Filter[0]) and OverlapRect(sprite.GetBoundsRect, Area) then
1971
      if (sprite is Filter[0]) and OverlapRect(sprite.GetBoundsRect, Area) then
1972
        sprite.Selected := true;
1972
        sprite.Selected := true;
1973
    end
1973
    end
1974
  end
1974
  end
1975
  else
1975
  else
1976
  begin
1976
  begin
1977
    for Index := 0 to Count - 1 do
1977
    for Index := 0 to Count - 1 do
1978
    begin
1978
    begin
1979
      sprite := Items[index];
1979
      sprite := Items[index];
1980
      for index2 := 0 to high(Filter) do
1980
      for index2 := 0 to high(Filter) do
1981
        if (sprite is Filter[index2]) and OverlapRect(sprite.GetBoundsRect, Area) then
1981
        if (sprite is Filter[index2]) and OverlapRect(sprite.GetBoundsRect, Area) then
1982
        begin
1982
        begin
1983
          sprite.Selected := true;
1983
          sprite.Selected := true;
1984
          break;
1984
          break;
1985
        end;
1985
        end;
1986
    end
1986
    end
1987
  end;
1987
  end;
1988
  fObjectsSelected := CurrentSelected.count <> 0;
1988
  fObjectsSelected := CurrentSelected.count <> 0;
1989
end; {GroupSelect}
1989
end; {GroupSelect}
1990
 
1990
 
1991
function TSpriteEngine.Select(Point: TPoint; Filter: array of TSpriteClass; Add: Boolean = False): Tsprite;
1991
function TSpriteEngine.Select(Point: TPoint; Filter: array of TSpriteClass; Add: Boolean = False): Tsprite;
1992
var
1992
var
1993
  index, index2: Integer;
1993
  index, index2: Integer;
1994
begin
1994
begin
1995
  Assert(length(Filter) <> 0, 'Filter = []');
1995
  Assert(length(Filter) <> 0, 'Filter = []');
1996
  if not Add then
1996
  if not Add then
1997
    ClearCurrent;
1997
    ClearCurrent;
1998
  // By searching the Drawlist in reverse
1998
  // By searching the Drawlist in reverse
1999
  // we select the highest sprite if the sprit is under the point
1999
  // we select the highest sprite if the sprit is under the point
2000
  assert(FDrawList <> nil, 'FDrawList = nil');
2000
  assert(FDrawList <> nil, 'FDrawList = nil');
2001
  if length(Filter) = 1 then
2001
  if length(Filter) = 1 then
2002
  begin
2002
  begin
2003
    for Index := FDrawList.Count - 1 downto 0 do
2003
    for Index := FDrawList.Count - 1 downto 0 do
2004
    begin
2004
    begin
2005
      Result := FDrawList[Index];
2005
      Result := FDrawList[Index];
2006
      if (Result is Filter[0]) and PointInRect(Point, Result.GetBoundsRect) then
2006
      if (Result is Filter[0]) and PointInRect(Point, Result.GetBoundsRect) then
2007
      begin
2007
      begin
2008
        Result.Selected := true;
2008
        Result.Selected := true;
2009
        fObjectsSelected := CurrentSelected.count <> 0;
2009
        fObjectsSelected := CurrentSelected.count <> 0;
2010
        exit;
2010
        exit;
2011
      end;
2011
      end;
2012
    end
2012
    end
2013
  end
2013
  end
2014
  else
2014
  else
2015
  begin
2015
  begin
2016
    for Index := FDrawList.Count - 1 downto 0 do
2016
    for Index := FDrawList.Count - 1 downto 0 do
2017
    begin
2017
    begin
2018
      Result := FDrawList[index];
2018
      Result := FDrawList[index];
2019
      for index2 := 0 to high(Filter) do
2019
      for index2 := 0 to high(Filter) do
2020
        if (Result is Filter[index2]) and PointInRect(Point, Result.GetBoundsRect) then
2020
        if (Result is Filter[index2]) and PointInRect(Point, Result.GetBoundsRect) then
2021
        begin
2021
        begin
2022
          Result.Selected := true;
2022
          Result.Selected := true;
2023
          fObjectsSelected := CurrentSelected.count <> 0;
2023
          fObjectsSelected := CurrentSelected.count <> 0;
2024
          exit;
2024
          exit;
2025
        end;
2025
        end;
2026
    end
2026
    end
2027
  end;
2027
  end;
2028
  Result := nil;
2028
  Result := nil;
2029
end; {Select}
2029
end; {Select}
2030
 
2030
 
2031
function TSpriteEngine.Select(Point: TPoint; Add: Boolean = False): TSprite;
2031
function TSpriteEngine.Select(Point: TPoint; Add: Boolean = False): TSprite;
2032
begin
2032
begin
2033
  Result := Select(Point, [Tsprite], Add);
2033
  Result := Select(Point, [Tsprite], Add);
2034
end; {Select}
2034
end; {Select}
2035
 
2035
 
2036
procedure TSpriteEngine.ClearCurrent;
2036
procedure TSpriteEngine.ClearCurrent;
2037
begin
2037
begin
2038
  while CurrentSelected.count <> 0 do
2038
  while CurrentSelected.count <> 0 do
2039
    TSprite(CurrentSelected[CurrentSelected.count - 1]).Selected := False;
2039
    TSprite(CurrentSelected[CurrentSelected.count - 1]).Selected := False;
2040
  fObjectsSelected := False;
2040
  fObjectsSelected := False;
2041
end; {ClearCurrent}
2041
end; {ClearCurrent}
2042
 
2042
 
2043
procedure TSpriteEngine.ClearGroup(GroupNumber: Integer);
2043
procedure TSpriteEngine.ClearGroup(GroupNumber: Integer);
2044
var
2044
var
2045
  index: Integer;
2045
  index: Integer;
2046
  Group: Tlist;
2046
  Group: Tlist;
2047
begin
2047
begin
2048
  Group := Groups[GroupNumber];
2048
  Group := Groups[GroupNumber];
2049
  if Group <> nil then
2049
  if Group <> nil then
2050
    for index := 0 to Group.count - 1 do
2050
    for index := 0 to Group.count - 1 do
2051
      TSprite(Group[index]).Selected := False;
2051
      TSprite(Group[index]).Selected := False;
2052
end; {ClearGroup}
2052
end; {ClearGroup}
2053
 
2053
 
2054
procedure TSpriteEngine.CurrentToGroup(GroupNumber: Integer; Add: Boolean = False);
2054
procedure TSpriteEngine.CurrentToGroup(GroupNumber: Integer; Add: Boolean = False);
2055
var
2055
var
2056
  Group: Tlist;
2056
  Group: Tlist;
2057
  index: Integer;
2057
  index: Integer;
2058
begin
2058
begin
2059
  Group := Groups[GroupNumber];
2059
  Group := Groups[GroupNumber];
2060
  if Group = nil then
2060
  if Group = nil then
2061
    exit;
2061
    exit;
2062
  if not Add then
2062
  if not Add then
2063
    ClearGroup(GroupNumber);
2063
    ClearGroup(GroupNumber);
2064
  for index := 0 to Group.count - 1 do
2064
  for index := 0 to Group.count - 1 do
2065
    TSprite(Group[index]).GroupNumber := GroupNumber;
2065
    TSprite(Group[index]).GroupNumber := GroupNumber;
2066
end; {CurrentToGroup}
2066
end; {CurrentToGroup}
2067
 
2067
 
2068
procedure TSpriteEngine.GroupToCurrent(GroupNumber: Integer; Add: Boolean = False);
2068
procedure TSpriteEngine.GroupToCurrent(GroupNumber: Integer; Add: Boolean = False);
2069
var
2069
var
2070
  Group: Tlist;
2070
  Group: Tlist;
2071
  index: Integer;
2071
  index: Integer;
2072
begin
2072
begin
2073
  if not Add then
2073
  if not Add then
2074
    ClearCurrent;
2074
    ClearCurrent;
2075
  Group := Groups[GroupNumber];
2075
  Group := Groups[GroupNumber];
2076
  if Group <> nil then
2076
  if Group <> nil then
2077
    for index := 0 to Group.count - 1 do
2077
    for index := 0 to Group.count - 1 do
2078
      TSprite(Group[index]).Selected := true;
2078
      TSprite(Group[index]).Selected := true;
2079
end; {GroupToCurrent}
2079
end; {GroupToCurrent}
2080
 
2080
 
2081
function TSpriteEngine.GetGroup(Index: Integer): Tlist;
2081
function TSpriteEngine.GetGroup(Index: Integer): Tlist;
2082
begin
2082
begin
2083
  if (index >= 0) or (index < fGroupCount) then
2083
  if (index >= 0) or (index < fGroupCount) then
2084
    Result := fGroups[index]
2084
    Result := fGroups[index]
2085
  else
2085
  else
2086
    Result := nil;
2086
    Result := nil;
2087
end; {GetGroup}
2087
end; {GetGroup}
2088
 
2088
 
2089
procedure TSpriteEngine.SetGroupCount(AGroupCount: Integer);
2089
procedure TSpriteEngine.SetGroupCount(AGroupCount: Integer);
2090
var
2090
var
2091
  index: Integer;
2091
  index: Integer;
2092
begin
2092
begin
2093
  if (AGroupCount <> FGroupCount) and (AGroupCount >= 0) then
2093
  if (AGroupCount <> FGroupCount) and (AGroupCount >= 0) then
2094
  begin
2094
  begin
2095
    if FGroupCount > AGroupCount then
2095
    if FGroupCount > AGroupCount then
2096
    begin // remove groups
2096
    begin // remove groups
2097
      for index := AGroupCount to FGroupCount - 1 do
2097
      for index := AGroupCount to FGroupCount - 1 do
2098
      begin
2098
      begin
2099
        ClearGroup(index);
2099
        ClearGroup(index);
2100
        FGroups[index].Free;
2100
        FGroups[index].Free;
2101
      end;
2101
      end;
2102
      SetLength(FGroups, AGroupCount);
2102
      SetLength(FGroups, AGroupCount);
2103
    end
2103
    end
2104
    else
2104
    else
2105
    begin // add groups
2105
    begin // add groups
2106
      SetLength(FGroups, AGroupCount);
2106
      SetLength(FGroups, AGroupCount);
2107
      for index := FGroupCount to AGroupCount - 1 do
2107
      for index := FGroupCount to AGroupCount - 1 do
2108
        FGroups[index] := Tlist.Create;
2108
        FGroups[index] := Tlist.Create;
2109
    end;
2109
    end;
2110
    FGroupCount := Length(FGroups);
2110
    FGroupCount := Length(FGroups);
2111
  end;
2111
  end;
2112
end; {SetGroupCount}
2112
end; {SetGroupCount}
2113
{$ENDIF}
2113
{$ENDIF}
2114
 
2114
 
2115
procedure TSpriteEngine.Dead;
2115
procedure TSpriteEngine.Dead;
2116
begin
2116
begin
2117
  while FDeadList.Count > 0 do
2117
  while FDeadList.Count > 0 do
2118
    TSprite(FDeadList[FDeadList.Count - 1]).Free;
2118
    TSprite(FDeadList[FDeadList.Count - 1]).Free;
2119
end;
2119
end;
2120
 
2120
 
2121
procedure TSpriteEngine.Draw;
2121
procedure TSpriteEngine.Draw;
2122
begin
2122
begin
2123
  FDrawCount := 0;
2123
  FDrawCount := 0;
2124
  inherited Draw;
2124
  inherited Draw;
2125
end;
2125
end;
2126
 
2126
 
2127
procedure TSpriteEngine.SetSurface(Value: TDirectDrawSurface);
2127
procedure TSpriteEngine.SetSurface(Value: TDirectDrawSurface);
2128
begin
2128
begin
2129
  FSurface := Value;
2129
  FSurface := Value;
2130
  if FSurface <> nil then
2130
  if FSurface <> nil then
2131
  begin
2131
  begin
2132
    FSurfaceRect := Surface.ClientRect;
2132
    FSurfaceRect := Surface.ClientRect;
2133
    Width := FSurfaceRect.Right - FSurfaceRect.Left;
2133
    Width := FSurfaceRect.Right - FSurfaceRect.Left;
2134
    Height := FSurfaceRect.Bottom - FSurfaceRect.Top;
2134
    Height := FSurfaceRect.Bottom - FSurfaceRect.Top;
2135
  end;
2135
  end;
2136
end;
2136
end;
2137
 
2137
 
2138
{  TCustomDXSpriteEngine  }
2138
{  TCustomDXSpriteEngine  }
2139
 
2139
 
2140
constructor TCustomDXSpriteEngine.Create(AOwner: TComponent);
2140
constructor TCustomDXSpriteEngine.Create(AOwner: TComponent);
2141
begin
2141
begin
2142
  inherited Create(AOwner);
2142
  inherited Create(AOwner);
2143
  FEngine := TSpriteEngine.Create(nil);
2143
  FEngine := TSpriteEngine.Create(nil);
2144
  FEngine.FOwner := Self;
2144
  FEngine.FOwner := Self;
2145
  FItems := TSpriteCollection.Create(Self);
2145
  FItems := TSpriteCollection.Create(Self);
2146
  FItems.FOwner := Self;
2146
  FItems.FOwner := Self;
2147
  FItems.FOwnerItem := FEngine;
2147
  FItems.FOwnerItem := FEngine;
2148
  FItems.Initialize(FEngine);
2148
  FItems.Initialize(FEngine);
2149
end;
2149
end;
2150
 
2150
 
2151
destructor TCustomDXSpriteEngine.Destroy;
2151
destructor TCustomDXSpriteEngine.Destroy;
2152
begin
2152
begin
2153
  FEngine.Free;
2153
  FEngine.Free;
2154
  inherited Destroy;
2154
  inherited Destroy;
2155
end;
2155
end;
2156
 
2156
 
2157
procedure TCustomDXSpriteEngine.Notification(AComponent: TComponent;
2157
procedure TCustomDXSpriteEngine.Notification(AComponent: TComponent;
2158
  Operation: TOperation);
2158
  Operation: TOperation);
2159
begin
2159
begin
2160
  inherited Notification(AComponent, Operation);
2160
  inherited Notification(AComponent, Operation);
2161
  if (Operation = opRemove) and (DXDraw = AComponent) then
2161
  if (Operation = opRemove) and (DXDraw = AComponent) then
2162
    DXDraw := nil;
2162
    DXDraw := nil;
2163
end;
2163
end;
2164
 
2164
 
2165
procedure TCustomDXSpriteEngine.Dead;
2165
procedure TCustomDXSpriteEngine.Dead;
2166
begin
2166
begin
2167
  FEngine.Dead;
2167
  FEngine.Dead;
2168
end;
2168
end;
2169
 
2169
 
2170
procedure TCustomDXSpriteEngine.Draw;
2170
procedure TCustomDXSpriteEngine.Draw;
2171
begin
2171
begin
2172
  if (FDXDraw <> nil) and (FDXDraw.Initialized) then
2172
  if (FDXDraw <> nil) and (FDXDraw.Initialized) then
2173
    FEngine.Draw;
2173
    FEngine.Draw;
2174
end;
2174
end;
2175
 
2175
 
2176
procedure TCustomDXSpriteEngine.Move(MoveCount: Integer);
2176
procedure TCustomDXSpriteEngine.Move(MoveCount: Integer);
2177
begin
2177
begin
2178
  FEngine.Move(MoveCount);
2178
  FEngine.Move(MoveCount);
2179
end;
2179
end;
2180
 
2180
 
2181
procedure TCustomDXSpriteEngine.DXDrawNotifyEvent(Sender: TCustomDXDraw;
2181
procedure TCustomDXSpriteEngine.DXDrawNotifyEvent(Sender: TCustomDXDraw;
2182
  NotifyType: TDXDrawNotifyType);
2182
  NotifyType: TDXDrawNotifyType);
2183
begin
2183
begin
2184
  case NotifyType of
2184
  case NotifyType of
2185
    dxntDestroying: DXDraw := nil;
2185
    dxntDestroying: DXDraw := nil;
2186
    dxntInitialize: FEngine.Surface := Sender.Surface;
2186
    dxntInitialize: FEngine.Surface := Sender.Surface;
2187
    dxntFinalize: FEngine.Surface := nil;
2187
    dxntFinalize: FEngine.Surface := nil;
2188
  end;
2188
  end;
2189
end;
2189
end;
2190
 
2190
 
2191
procedure TCustomDXSpriteEngine.SetDXDraw(Value: TCustomDXDraw);
2191
procedure TCustomDXSpriteEngine.SetDXDraw(Value: TCustomDXDraw);
2192
begin
2192
begin
2193
  if FDXDraw <> nil then
2193
  if FDXDraw <> nil then
2194
    FDXDraw.UnRegisterNotifyEvent(DXDrawNotifyEvent);
2194
    FDXDraw.UnRegisterNotifyEvent(DXDrawNotifyEvent);
2195
 
2195
 
2196
  FDXDraw := Value;
2196
  FDXDraw := Value;
2197
 
2197
 
2198
  if FDXDraw <> nil then
2198
  if FDXDraw <> nil then
2199
    FDXDraw.RegisterNotifyEvent(DXDrawNotifyEvent);
2199
    FDXDraw.RegisterNotifyEvent(DXDrawNotifyEvent);
2200
end;
2200
end;
2201
 
2201
 
2202
procedure TCustomDXSpriteEngine.SetItems(const Value: TSpriteCollection);
2202
procedure TCustomDXSpriteEngine.SetItems(const Value: TSpriteCollection);
2203
begin
2203
begin
2204
  FItems.Assign(Value);
2204
  FItems.Assign(Value);
2205
end;
2205
end;
2206
 
2206
 
2207
procedure TCustomDXSpriteEngine.Clone(const Amount: Word; const BaseNameOfSprite: string);
2207
procedure TCustomDXSpriteEngine.Clone(const Amount: Word; const BaseNameOfSprite: string);
2208
var
2208
var
2209
  i: Integer;
2209
  i: Integer;
2210
begin
2210
begin
2211
  if Amount = 0 then Exit;
2211
  if Amount = 0 then Exit;
2212
  for i := 1 to Amount do
2212
  for i := 1 to Amount do
2213
  begin
2213
  begin
2214
    with FItems.Add do
2214
    with FItems.Add do
2215
    begin
2215
    begin
2216
      KindSprite := FItems.Find(BaseNameOfSprite).KindSprite;
2216
      KindSprite := FItems.Find(BaseNameOfSprite).KindSprite;
2217
      Sprite.AsSign(FItems.Find(BaseNameOfSprite).Sprite);
2217
      Sprite.AsSign(FItems.Find(BaseNameOfSprite).Sprite);
2218
      {name has to be different}
2218
      {name has to be different}
2219
      Name := Format(BaseNameOfSprite + '_%d', [I]); //simple name for sprite like Name_1 etc.
2219
      Name := Format(BaseNameOfSprite + '_%d', [I]); //simple name for sprite like Name_1 etc.
2220
      Sprite.Tag := 0; //for sprite you can use Tag property in future as well
2220
      Sprite.Tag := 0; //for sprite you can use Tag property in future as well
2221
    end;
2221
    end;
2222
  end;
2222
  end;
2223
end;
2223
end;
2224
 
2224
 
2225
function TCustomDXSpriteEngine.ForEach(PrefixNameOdSprite: string; var Names: TStringList): Boolean;
2225
function TCustomDXSpriteEngine.ForEach(PrefixNameOdSprite: string; var Names: TStringList): Boolean;
2226
var
2226
var
2227
  I: Integer;
2227
  I: Integer;
2228
begin
2228
begin
2229
  if Names = nil then
2229
  if Names = nil then
2230
    Names := TStringList.Create;
2230
    Names := TStringList.Create;
2231
  for I := 0 to Items.Count - 1 do
2231
  for I := 0 to Items.Count - 1 do
2232
  begin
2232
  begin
2233
    if PrefixNameOdSprite = '' then
2233
    if PrefixNameOdSprite = '' then
2234
      Names.Add(Items[I].Name)
2234
      Names.Add(Items[I].Name)
2235
    else
2235
    else
2236
      {is prefix, fo names like Player????}
2236
      {is prefix, fo names like Player????}
2237
      if Pos(PrefixNameOdSprite, Items[I].Name) = 1 then
2237
      if Pos(PrefixNameOdSprite, Items[I].Name) = 1 then
2238
        Names.Add(Items[I].Name);
2238
        Names.Add(Items[I].Name);
2239
  end;
2239
  end;
2240
  Result := Names.Count > 0;
2240
  Result := Names.Count > 0;
2241
  if not Result then {$IFDEF VER5UP}FreeAndNil(Names){$ELSE}begin Names.Free; names := nil end{$ENDIF};
2241
  if not Result then {$IFDEF VER5UP}FreeAndNil(Names){$ELSE}begin Names.Free; names := nil end{$ENDIF};
2242
end;
2242
end;
2243
 
2243
 
2244
{ TSpriteCollectionItem }
2244
{ TSpriteCollectionItem }
2245
 
2245
 
2246
function TSpriteCollectionItem.GetSpriteCollection: TSpriteCollection;
2246
function TSpriteCollectionItem.GetSpriteCollection: TSpriteCollection;
2247
begin
2247
begin
2248
  Result := Collection as TSpriteCollection;
2248
  Result := Collection as TSpriteCollection;
2249
end;
2249
end;
2250
 
2250
 
2251
procedure TSpriteCollectionItem.SetSprite(const Value: TSprite);
2251
procedure TSpriteCollectionItem.SetSprite(const Value: TSprite);
2252
begin
2252
begin
2253
  FSprite.Assign(Value);
2253
  FSprite.Assign(Value);
2254
end;
2254
end;
2255
 
2255
 
2256
constructor TSpriteCollectionItem.Create(Collection: TCollection);
2256
constructor TSpriteCollectionItem.Create(Collection: TCollection);
2257
begin
2257
begin
2258
  inherited Create(Collection);
2258
  inherited Create(Collection);
2259
  FOwner := Collection;
2259
  FOwner := Collection;
2260
  FOwnerItem := (Collection as TSpriteCollection).FOwnerItem;
2260
  FOwnerItem := (Collection as TSpriteCollection).FOwnerItem;
2261
  FSpriteType := stSprite;
2261
  FSpriteType := stSprite;
2262
  FSprite := TSprite.Create(FOwnerItem);
2262
  FSprite := TSprite.Create(FOwnerItem);
2263
end;
2263
end;
2264
 
2264
 
2265
procedure TSpriteCollectionItem.Assign(Source: TPersistent);
2265
procedure TSpriteCollectionItem.Assign(Source: TPersistent);
2266
begin
2266
begin
2267
  if Source is TSpriteCollectionItem then
2267
  if Source is TSpriteCollectionItem then
2268
  begin
2268
  begin
2269
    Finalize;
2269
    Finalize;
2270
    FSprite.Assign(TSpriteCollectionItem(Source).FSprite);
2270
    FSprite.Assign(TSpriteCollectionItem(Source).FSprite);
2271
    inherited Assign(Source);
2271
    inherited Assign(Source);
2272
    Initialize;
2272
    Initialize;
2273
  end
2273
  end
2274
  else
2274
  else
2275
    inherited;
2275
    inherited;
2276
end;
2276
end;
2277
 
2277
 
2278
procedure TSpriteCollectionItem.Initialize;
2278
procedure TSpriteCollectionItem.Initialize;
2279
begin
2279
begin
2280
 
2280
 
2281
end;
2281
end;
2282
 
2282
 
2283
destructor TSpriteCollectionItem.Destroy;
2283
destructor TSpriteCollectionItem.Destroy;
2284
begin
2284
begin
2285
  FSprite.Destroy;
2285
  FSprite.Destroy;
2286
  inherited;
2286
  inherited;
2287
end;
2287
end;
2288
 
2288
 
2289
procedure TSpriteCollectionItem.Finalize;
2289
procedure TSpriteCollectionItem.Finalize;
2290
begin
2290
begin
2291
 
2291
 
2292
end;
2292
end;
2293
 
2293
 
2294
procedure TSpriteCollectionItem.SetOnCollision(
2294
procedure TSpriteCollectionItem.SetOnCollision(
2295
  const Value: TCollisionEvent);
2295
  const Value: TCollisionEvent);
2296
begin
2296
begin
2297
  FSprite.FOnCollision := Value;
2297
  FSprite.FOnCollision := Value;
2298
end;
2298
end;
2299
 
2299
 
2300
procedure TSpriteCollectionItem.SetOnDraw(const Value: TDrawEvent);
2300
procedure TSpriteCollectionItem.SetOnDraw(const Value: TDrawEvent);
2301
begin
2301
begin
2302
  FSprite.FOnDraw := Value;
2302
  FSprite.FOnDraw := Value;
2303
end;
2303
end;
2304
 
2304
 
2305
procedure TSpriteCollectionItem.SetOnMove(const Value: TMoveEvent);
2305
procedure TSpriteCollectionItem.SetOnMove(const Value: TMoveEvent);
2306
begin
2306
begin
2307
  FSprite.FOnMove := Value
2307
  FSprite.FOnMove := Value
2308
end;
2308
end;
2309
 
2309
 
2310
function TSpriteCollectionItem.GetDisplayName: string;
2310
function TSpriteCollectionItem.GetDisplayName: string;
2311
begin
2311
begin
2312
  Result := inherited GetDisplayName
2312
  Result := inherited GetDisplayName
2313
end;
2313
end;
2314
 
2314
 
2315
procedure TSpriteCollectionItem.SetDisplayName(const Value: string);
2315
procedure TSpriteCollectionItem.SetDisplayName(const Value: string);
2316
begin
2316
begin
2317
  if (Value <> '') and (AnsiCompareText(Value, GetDisplayName) <> 0) and
2317
  if (Value <> '') and (AnsiCompareText(Value, GetDisplayName) <> 0) and
2318
    (Collection is TSpriteCollection) and (TSpriteCollection(Collection).IndexOf(Value) >= 0) then
2318
    (Collection is TSpriteCollection) and (TSpriteCollection(Collection).IndexOf(Value) >= 0) then
2319
    raise Exception.Create(Format(SSpriteDuplicateName, [Value]));
2319
    raise Exception.Create(Format(SSpriteDuplicateName, [Value]));
2320
  inherited SetDisplayName(Value);
2320
  inherited SetDisplayName(Value);
2321
end;
2321
end;
2322
 
2322
 
2323
function TSpriteCollectionItem.GetSpriteType: TSpriteType;
2323
function TSpriteCollectionItem.GetSpriteType: TSpriteType;
2324
begin
2324
begin
2325
  Result := FSpriteType;
2325
  Result := FSpriteType;
2326
end;
2326
end;
2327
 
2327
 
2328
procedure TSpriteCollectionItem.SetSpriteType(const Value: TSpriteType);
2328
procedure TSpriteCollectionItem.SetSpriteType(const Value: TSpriteType);
2329
var
2329
var
2330
  tmpSprite: TSprite;
2330
  tmpSprite: TSprite;
2331
begin
2331
begin
2332
  if Value <> FSpriteType then
2332
  if Value <> FSpriteType then
2333
  begin
2333
  begin
2334
    case Value of
2334
    case Value of
2335
      stSprite: tmpSprite := TSprite.Create(TSpriteEngine(FOwnerItem));
2335
      stSprite: tmpSprite := TSprite.Create(TSpriteEngine(FOwnerItem));
2336
      stImageSprite: TImageSprite(tmpSprite) := TImageSprite.Create(TSpriteEngine(FOwnerItem));
2336
      stImageSprite: TImageSprite(tmpSprite) := TImageSprite.Create(TSpriteEngine(FOwnerItem));
-
 
2337
      {$WARN SYMBOL_DEPRECATED OFF} // Added by ViaThinkSoft [2015-12-07]
2337
      stImageSpriteEx: TImageSpriteEx(tmpSprite) := TImageSpriteEx.Create(TSpriteEngine(FOwnerItem));
2338
      stImageSpriteEx: TImageSpriteEx(tmpSprite) := TImageSpriteEx.Create(TSpriteEngine(FOwnerItem));
-
 
2339
      {$WARN SYMBOL_DEPRECATED ON} // Added by ViaThinkSoft [2015-12-07]
2338
      stBackgroundSprite: TBackgroundSprite(tmpSprite) := TBackgroundSprite.Create(TSpriteEngine(FOwnerItem));
2340
      stBackgroundSprite: TBackgroundSprite(tmpSprite) := TBackgroundSprite.Create(TSpriteEngine(FOwnerItem));
2339
    else
2341
    else
2340
      tmpSprite := nil
2342
      tmpSprite := nil
2341
    end;
2343
    end;
2342
    if Assigned(FSprite) then
2344
    if Assigned(FSprite) then
2343
    try
2345
    try
2344
      tmpSprite.Assign(FSprite);
2346
      tmpSprite.Assign(FSprite);
2345
      tmpSprite.FOnDraw := FSprite.FOnDraw;
2347
      tmpSprite.FOnDraw := FSprite.FOnDraw;
2346
      tmpSprite.FOnMove := FSprite.FOnMove;
2348
      tmpSprite.FOnMove := FSprite.FOnMove;
2347
      tmpSprite.FOnCollision := FSprite.FOnCollision;
2349
      tmpSprite.FOnCollision := FSprite.FOnCollision;
2348
      tmpSprite.FOnGetImage := FSprite.FOnGetImage;
2350
      tmpSprite.FOnGetImage := FSprite.FOnGetImage;
2349
    finally
2351
    finally
2350
      FSprite.Free; FSprite := nil;
2352
      FSprite.Free; FSprite := nil;
2351
    end;
2353
    end;
2352
    FSprite := tmpSprite;
2354
    FSprite := tmpSprite;
2353
    FSpriteType := Value;
2355
    FSpriteType := Value;
2354
  end;
2356
  end;
2355
end;
2357
end;
2356
 
2358
 
2357
function TSpriteCollectionItem.GetOnCollision: TCollisionEvent;
2359
function TSpriteCollectionItem.GetOnCollision: TCollisionEvent;
2358
begin
2360
begin
2359
  Result := FSprite.FOnCollision
2361
  Result := FSprite.FOnCollision
2360
end;
2362
end;
2361
 
2363
 
2362
function TSpriteCollectionItem.GetOnDraw: TDrawEvent;
2364
function TSpriteCollectionItem.GetOnDraw: TDrawEvent;
2363
begin
2365
begin
2364
  Result := FSprite.FOnDraw
2366
  Result := FSprite.FOnDraw
2365
end;
2367
end;
2366
 
2368
 
2367
function TSpriteCollectionItem.GetOnMove: TMoveEvent;
2369
function TSpriteCollectionItem.GetOnMove: TMoveEvent;
2368
begin
2370
begin
2369
  Result := FSprite.FOnMove
2371
  Result := FSprite.FOnMove
2370
end;
2372
end;
2371
 
2373
 
2372
function TSpriteCollectionItem.GetOnGetImage: TGetImage;
2374
function TSpriteCollectionItem.GetOnGetImage: TGetImage;
2373
begin
2375
begin
2374
  Result := FSprite.FOnGetImage;
2376
  Result := FSprite.FOnGetImage;
2375
end;
2377
end;
2376
 
2378
 
2377
procedure TSpriteCollectionItem.SetOnGetImage(const Value: TGetImage);
2379
procedure TSpriteCollectionItem.SetOnGetImage(const Value: TGetImage);
2378
begin
2380
begin
2379
  FSprite.FOnGetImage := Value;
2381
  FSprite.FOnGetImage := Value;
2380
end;
2382
end;
2381
 
2383
 
2382
function TSpriteCollectionItem.GetImageList: TCustomDXImageList;
2384
function TSpriteCollectionItem.GetImageList: TCustomDXImageList;
2383
begin
2385
begin
2384
  Result := FSprite.FDXImageList;
2386
  Result := FSprite.FDXImageList;
2385
end;
2387
end;
2386
 
2388
 
2387
procedure TSpriteCollectionItem.SetImageList(const Value: TCustomDXImageList);
2389
procedure TSpriteCollectionItem.SetImageList(const Value: TCustomDXImageList);
2388
begin
2390
begin
2389
  FSprite.FDXImageList := Value;
2391
  FSprite.FDXImageList := Value;
2390
end;
2392
end;
2391
 
2393
 
2392
function TSpriteCollectionItem.Clone(NewName: string): TSprite;
2394
function TSpriteCollectionItem.Clone(NewName: string): TSprite;
2393
var
2395
var
2394
  T: TSpriteCollectionItem;
2396
  T: TSpriteCollectionItem;
2395
begin
2397
begin
2396
  T := GetSpriteCollection.Add;
2398
  T := GetSpriteCollection.Add;
2397
  T.KindSprite := Self.FSpriteType;
2399
  T.KindSprite := Self.FSpriteType;
2398
  T.Assign(Self);
2400
  T.Assign(Self);
2399
  T.Name := NewName;
2401
  T.Name := NewName;
2400
  Result := T.FSprite;
2402
  Result := T.FSprite;
2401
end;
2403
end;
2402
 
2404
 
2403
{ TSpriteCollection }
2405
{ TSpriteCollection }
2404
 
2406
 
2405
function TSpriteCollection.Initialized: Boolean;
2407
function TSpriteCollection.Initialized: Boolean;
2406
begin
2408
begin
2407
  Result := FInitializeFlag;
2409
  Result := FInitializeFlag;
2408
end;
2410
end;
2409
 
2411
 
2410
constructor TSpriteCollection.Create(AOwner: TPersistent);
2412
constructor TSpriteCollection.Create(AOwner: TPersistent);
2411
begin
2413
begin
2412
  inherited Create(TSpriteCollectionItem);
2414
  inherited Create(TSpriteCollectionItem);
2413
  FOwner := AOwner;
2415
  FOwner := AOwner;
2414
  FInitializeFlag := Initialize(TSpriteEngine(AOwner));
2416
  FInitializeFlag := Initialize(TSpriteEngine(AOwner));
2415
end;
2417
end;
2416
 
2418
 
2417
function TSpriteCollection.GetItem(Index: Integer): TSpriteCollectionItem;
2419
function TSpriteCollection.GetItem(Index: Integer): TSpriteCollectionItem;
2418
begin
2420
begin
2419
  Result := TSpriteCollectionItem(inherited Items[Index]);
2421
  Result := TSpriteCollectionItem(inherited Items[Index]);
2420
end;
2422
end;
2421
 
2423
 
2422
function TSpriteCollection.Initialize(DXSpriteEngine: TSpriteEngine): Boolean;
2424
function TSpriteCollection.Initialize(DXSpriteEngine: TSpriteEngine): Boolean;
2423
begin
2425
begin
2424
  Result := True;
2426
  Result := True;
2425
  try
2427
  try
2426
    if AsSigned(FOnInitialize) then
2428
    if AsSigned(FOnInitialize) then
2427
      FOnInitialize(DXSpriteEngine);
2429
      FOnInitialize(DXSpriteEngine);
2428
  except
2430
  except
2429
    Result := False;
2431
    Result := False;
2430
  end
2432
  end
2431
end;
2433
end;
2432
 
2434
 
2433
function TSpriteCollection.Find(const Name: string): TSpriteCollectionItem;
2435
function TSpriteCollection.Find(const Name: string): TSpriteCollectionItem;
2434
var
2436
var
2435
  i: Integer;
2437
  i: Integer;
2436
begin
2438
begin
2437
  i := IndexOf(Name);
2439
  i := IndexOf(Name);
2438
  if i = -1 then
2440
  if i = -1 then
2439
    raise ESpriteCollectionError.CreateFmt(SSpriteNotFound, [Name]);
2441
    raise ESpriteCollectionError.CreateFmt(SSpriteNotFound, [Name]);
2440
  Result := Items[i];
2442
  Result := Items[i];
2441
end;
2443
end;
2442
 
2444
 
2443
procedure TSpriteCollection.Finalize;
2445
procedure TSpriteCollection.Finalize;
2444
begin
2446
begin
2445
  if AsSigned(FOnFinalize) then
2447
  if AsSigned(FOnFinalize) then
2446
    FOnFinalize(FOwnerItem);
2448
    FOnFinalize(FOwnerItem);
2447
end;
2449
end;
2448
 
2450
 
2449
function TSpriteCollection.GetOwner: TPersistent;
2451
function TSpriteCollection.GetOwner: TPersistent;
2450
begin
2452
begin
2451
  Result := FOwner;
2453
  Result := FOwner;
2452
end;
2454
end;
2453
 
2455
 
2454
function TSpriteCollection.Add: TSpriteCollectionItem;
2456
function TSpriteCollection.Add: TSpriteCollectionItem;
2455
begin
2457
begin
2456
  Result := TSpriteCollectionItem(inherited Add);
2458
  Result := TSpriteCollectionItem(inherited Add);
2457
  Result.FOwner := FOwner;
2459
  Result.FOwner := FOwner;
2458
  Result.FOwnerItem := FOwnerItem;
2460
  Result.FOwnerItem := FOwnerItem;
2459
end;
2461
end;
2460
 
2462
 
2461
destructor TSpriteCollection.Destroy;
2463
destructor TSpriteCollection.Destroy;
2462
begin
2464
begin
2463
  Finalize;
2465
  Finalize;
2464
  inherited;
2466
  inherited;
2465
end;
2467
end;
2466
 
2468
 
2467
end.
2469
end.
2468
 
2470