cGameLib_12.c 96.8 KB
Newer Older
Peter Achten's avatar
Peter Achten committed
1
2
3

/* Clean Game Library by Mike Wiering, Nijmegen */

4
5
#include "util.h"
#include "intrface.h"
Peter Achten's avatar
Peter Achten committed
6

7
#include "cGameLib.h"
Peter Achten's avatar
Peter Achten committed
8

9
#include "cOSGameLib.h"  /* OS specific functions */
Peter Achten's avatar
Peter Achten committed
10
11
12
13


// #define SMART_DRAW

14
/* defined in cCrossCall.h and cCrossCall.c */
Peter Achten's avatar
Peter Achten committed
15
16
17
18
19
20
extern CrossCallInfo gCci;
extern char *gAppName;
extern HWND ghMainWindow;
extern HINSTANCE ghInst;

extern void SendMessageToClean (int mess,
21
                         int p1,int p2,int p3, int p4,int p5,int p6);
Peter Achten's avatar
Peter Achten committed
22
23
24
25
26
27
28
29
30
31
32
33
34

#define SendMessage0ToClean(mess)                   SendMessageToClean((mess), 0,0,0,0,0,0)
#define SendMessage1ToClean(mess,p1)                SendMessageToClean((mess), (int)(p1),0,0,0,0,0)
#define SendMessage2ToClean(mess,p1,p2)             SendMessageToClean((mess), (int)(p1),(int)(p2),0,0,0,0)
#define SendMessage3ToClean(mess,p1,p2,p3)          SendMessageToClean((mess), (int)(p1),(int)(p2),(int)(p3),0,0,0)
#define SendMessage4ToClean(mess,p1,p2,p3,p4)       SendMessageToClean((mess), (int)(p1),(int)(p2),(int)(p3),(int)(p4),0,0)
#define SendMessage5ToClean(mess,p1,p2,p3,p4,p5)    SendMessageToClean((mess), (int)(p1),(int)(p2),(int)(p3),(int)(p4),(int)(p5),0)
#define SendMessage6ToClean(mess,p1,p2,p3,p4,p5,p6) SendMessageToClean((mess), (int)(p1),(int)(p2),(int)(p3),(int)(p4),(int)(p5),(int)(p6))



typedef struct SPRITEANIMATION
{
35
    int iSpriteID;
Peter Achten's avatar
Peter Achten committed
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    int iBitmapID;
    int iSequenceLength;
    char *sSequence;
    int iPosition;
    int iCounter;
    struct SPRITEANIMATION *saNext;
    BOOL bLoop;
} SPRITEANIMATION;

typedef struct OBJECTREC
{
    int iObjectID;
    int iMapX;
    int iMapY;
    int iObjType;
    int iSubType;
52
    BOOL bActive;
Peter Achten's avatar
Peter Achten committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
    int iXPos;
    int iYPos;
    int iXSize;
    int iYSize;
    int iXOffset;
    int iYOffset;
    int iSpriteID;
    int iSpriteIndex;
    int iDisplayOptions;
    int iOwnBounds;
    int iBounceBounds;
    int iCollideBounds;
    int iForgetX;
    int iForgetY;
    int iLastXPos;
    int iLastYPos;
    int iTimeCounter;
    int iLayer;
    int iXAcc;
    int iYAcc;
    int iXSpeed;
    int iYSpeed;
    int iXBounce;
    int iYBounce;
    int iMaxXSpeed;
    int iMaxYSpeed;
    int iXSlowDown;
    int iYSlowDown;
    int iSkipMove;
    int iOptions;

    int iFixedXPos;
    int iFixedYPos;
    int iLastFixedXPos;
    int iLastFixedYPos;
    int iLastSprite;
    int iPosition;
    int iCounter;
91
92
93
94
95
96
97
98
99
100

    int iDiag;
    int iDiagUpDn;
    int iDiagX;
    int iDiagY;
    int iDiagLeftX;
    int iDiagLeftY;
    int iDiagRightX;
    int iDiagRightY;

Peter Achten's avatar
Peter Achten committed
101
102
103
104
105
106
    struct OBJECTREC *objNext;
} OBJECTREC;


typedef struct GAMELAYERMAPINFO
{
107
    int iMapID;
Peter Achten's avatar
Peter Achten committed
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    int iBitmapID;
    int iMapWidth;
    int iMapHeight;
    char *sMap;
    int iTotalXSize;
    int iTotalYSize;
    BOOL bTile;
    struct GAMELAYERMAPINFO *glmipNext;
} GAMELAYERMAPINFO;


extern BOOL bGameActive;
extern HWND ghGameWindow;
extern int ScreenWidth;
extern int ScreenHeight;
extern int BitsPerPixel;
extern BOOL FullScreen;

126
127
128
extern int XShiftScreen;
extern int YShiftScreen;

Peter Achten's avatar
Peter Achten committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
int iFrameCounter;

static GAMELAYERMAPINFO *glmipGameLayerMapInfo = NULL;
static SPRITEANIMATION *saSprites = NULL;
static OBJECTREC *objObjects = NULL;

static int XView = 0;
static int YView = 0;
static int XScrollSpeed = 0;
static int YScrollSpeed = 0;

static int iNextLayer = 0;

/* bound map */
static char *sBoundMap = NULL;
static int BoundMapWidth = 0;
static int BoundMapHeight = 0;
static int BoundBlockWidth = 0;
static int BoundBlockHeight = 0;
static int TotalWidth = 0;
static int TotalHeight = 0;

#ifdef SMART_DRAW
/* smart draw data (only draw changed tiles) */
static char *sLastTile = NULL;
static int iLastTileW;
static int iLastTileH;
static int iTopLayerLastX;
static int iTopLayerLastY;
static int bSmartDraw;
static int bAllowSmartDraw;
#endif

/* min. value for objects */
163
static int iObjectValueStart;
Peter Achten's avatar
Peter Achten committed
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

/* smallest distance to visible screen before initializing object */
static int iStartObjX = 5;
static int iStartObjY = 5;

/* ID of the object that is performing a crosscall */
static int iCCObjectID = 0;

static BOOL bCheckEscape = TRUE;
static BOOL DebugScroll = FALSE;
static BOOL bFillBackground = TRUE;
static COLORREF FillBackgroundRGB = 0;
static BOOL bFadeIn = FALSE;
static BOOL bFadeOut = FALSE;

static char FullScreenGameWindowClassName[] = "__CleanFullScreenGameWindow";
static char GameWindowClassName[] = "__CleanGameWindow";


/* focusing the main character */
static int iFollowID = 0;
static int iFollowX1 = 0;
static int iFollowY1 = 0;
static int iFollowX2 = 0;
static int iFollowY2 = 0;

static int iMaxXScrollSpeed = 1;
static int iMaxYScrollSpeed = 1;
static int iActualXView = 0;
static int iActualYView = 0;

/* info for user defined events and scheduled */
typedef struct USER_EVENT_INFO
{
    int iEventID;
    int iEventParameter1;
    int iEventParameter2;
    int iEventParameter3;
    int iEventParameter4;
    int iDestination;
    int iSubDestination;
205
    int iTimeCounter;
Peter Achten's avatar
Peter Achten committed
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    struct USER_EVENT_INFO *ueiNext;
} USER_EVENT_INFO;

static USER_EVENT_INFO *ueiUserEventInfo = NULL;

#define EV_PLAY_SOUND  (-1)


ClearUserEvents ()
{
    struct USER_EVENT_INFO *ueiNext;

    while (ueiUserEventInfo)
    {
        ueiNext = ueiUserEventInfo->ueiNext;
        rfree (ueiUserEventInfo);
        ueiUserEventInfo = ueiNext;
    }
}


int NextFrame (int);


/* use one integer to save info for both pages */
static int setflipint (int x, int value)
{
    if ((iFrameCounter % 2) == 0)
        return ((x & 0xFFFF0000) + (value & 0xFFFF));
    else
        return ((x & 0xFFFF) + (value << 16));
}

static int getflipint (int value)
{
    if ((iFrameCounter % 2) == 0)
        return (value & 0xFFFF);
    else
        return (value >> 16);
}

static BOOL cmpflipint (int x, int value)
{
    if ((iFrameCounter % 2) == 0)
        return ((x & 0xFFFF0000) == (value << 16));
    else
        return ((x & 0xFFFF) == (value & 0xFFFF));
}



/*
258
259
     3 / 2 =  1
     2 / 2 =  1
Peter Achten's avatar
Peter Achten committed
260
261
     1 / 2 =  0
     0 / 2 =  0
262
    -1 / 2 =  0   <-- fill up this gap
Peter Achten's avatar
Peter Achten committed
263
264
265
266
267
268
    -2 / 2 = -1
    -3 / 2 = -1
*/

int intdiv (int x, int y)
{
269
    return (x < 0)? (x - y + 1) / y : x / y;
Peter Achten's avatar
Peter Achten committed
270
271
272
273
}

int Min (int x, int y)
{
274
    return (x < y)? x : y;
Peter Achten's avatar
Peter Achten committed
275
276
277
278
}

int Max (int x, int y)
{
279
    return (x > y)? x : y;
Peter Achten's avatar
Peter Achten committed
280
281
282
283
284
285
286
287
288
}


/* get a pointer to the SPRITEANIMATION structure with id ID */
SPRITEANIMATION *GetSpriteAnimation (int ID)
{
    SPRITEANIMATION *sa = saSprites;
    BOOL bFound = FALSE;

289
    while (sa && (!bFound))
Peter Achten's avatar
Peter Achten committed
290
    {
291
292
        if (sa->iSpriteID == ID)
            bFound = TRUE;
Peter Achten's avatar
Peter Achten committed
293
        else
294
            sa = sa->saNext;
Peter Achten's avatar
Peter Achten committed
295
296
    }
    if (bFound)
297
        return sa;
Peter Achten's avatar
Peter Achten committed
298
299
300
301
302
303
304
305
306
    else
        return NULL;
}

/* free the SPRITEANIMATION list */
void FreeSpriteAnimationList ()
{
    SPRITEANIMATION *sa;

307
    while (saSprites)
Peter Achten's avatar
Peter Achten committed
308
    {
309
310
311
312
313
314
        sa = saSprites->saNext;
        if (saSprites->sSequence)
        {
            rfree (saSprites->sSequence);
            saSprites->sSequence = NULL;
        }
Peter Achten's avatar
Peter Achten committed
315
316
317
318
319
320
321
322
323
324
325
        rfree (saSprites);
        saSprites = sa;
    }
}

/* get a pointer to the GAMELAYERMAPINFO structure with id MID */
GAMELAYERMAPINFO *GetGameLayerMapInfo (int MapID)
{
    GAMELAYERMAPINFO *glmip = glmipGameLayerMapInfo;
    BOOL bFound = FALSE;

326
    while (glmip && (!bFound))
Peter Achten's avatar
Peter Achten committed
327
    {
328
329
        if (glmip->iMapID == MapID)
            bFound = TRUE;
Peter Achten's avatar
Peter Achten committed
330
        else
331
            glmip = glmip->glmipNext;
Peter Achten's avatar
Peter Achten committed
332
    }
333
    return glmip;
Peter Achten's avatar
Peter Achten committed
334
335
336
337
338
339
340
}

/* free the GAMELAYERMAPINFO list and all the map strings */
void FreeGameLayerMapInfoList ()
{
    GAMELAYERMAPINFO *glmip;

341
    while (glmipGameLayerMapInfo)
Peter Achten's avatar
Peter Achten committed
342
    {
343
        glmip = glmipGameLayerMapInfo->glmipNext;
Peter Achten's avatar
Peter Achten committed
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
        if (glmipGameLayerMapInfo->sMap != NULL)
        {
            rfree (glmipGameLayerMapInfo->sMap);
            glmipGameLayerMapInfo->sMap = NULL;
        }
        rfree (glmipGameLayerMapInfo);
        glmipGameLayerMapInfo = glmip;
    }
}


/* get a pointer to the OBJECTREC structure with id ID */
OBJECTREC *GetObjectRec (int ID)
{
    OBJECTREC *obj = objObjects;
    BOOL bFound = FALSE;

361
    while (obj && (!bFound))
Peter Achten's avatar
Peter Achten committed
362
    {
363
364
        if (obj->iObjectID == ID)
            bFound = TRUE;
Peter Achten's avatar
Peter Achten committed
365
        else
366
            obj = obj->objNext;
Peter Achten's avatar
Peter Achten committed
367
    }
368
    return obj;
Peter Achten's avatar
Peter Achten committed
369
370
}

Mike Wiering's avatar
Mike Wiering committed
371
372
373
374
375
376
377
378
379
380
381
382
383
/* update last position if pos has been changed during an event */
void UpdatePosition (OBJECTREC *obj)
{
    obj->iLastXPos = obj->iXPos;
    obj->iLastYPos = obj->iYPos;

    obj->iFixedXPos = obj->iXPos << 8;
    obj->iFixedYPos = obj->iYPos << 8;
    obj->iLastFixedXPos = obj->iFixedXPos;
    obj->iLastFixedYPos = obj->iFixedYPos;
}


Peter Achten's avatar
Peter Achten committed
384
385
386
387
388
389
390
391
392
393
394
395

/* initialize a new game object */
void InitGameObject (int mapx, int mapy)
{
    OBJECTREC *objNew;
    OBJECTREC *obj1;
    OBJECTREC *obj2;
    int mappos;
    int origmapval, mapval, above;
    int newid;

    if ((mapx < 0) || (mapy < 0))
396
        return;
Peter Achten's avatar
Peter Achten committed
397
398
399
400
401
402
    if ((mapx > BoundMapWidth - 1) || (mapy > BoundMapHeight - 1))
        return;
    mappos = (mapy * BoundMapWidth + mapx) * sizeof (int);
    origmapval = (*(int *) &sBoundMap[mappos]);
    mapval = origmapval >> 8;
    if (mapval < iObjectValueStart)
403
        return;
Peter Achten's avatar
Peter Achten committed
404
405
406
407
408

    (*(int *) &sBoundMap[mappos]) = origmapval & 0x00FF;  // remove object

    // create a unique id number
    newid = 1;
409
    while (GetObjectRec (newid))
Peter Achten's avatar
Peter Achten committed
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
        newid++;

    objNew = rmalloc (sizeof (OBJECTREC));
    objNew->objNext = NULL;
    objNew->iMapX = mapx;
    objNew->iMapY = mapy;
  /*
    objNew->iObjType = mapval;
    objNew->iSubType = above >> 8;
  */
    if (mapy == 0)
        above = 0;
    else
    {
        origmapval = (*(int *) &sBoundMap[mappos - BoundMapWidth * sizeof (int)]);
        above = origmapval >> 8;
    }

    if (above >= iObjectValueStart)
        above = 0;

    if (above > 0)
        (*(int *) &sBoundMap[mappos - BoundMapWidth * sizeof (int)]) =
            origmapval & 0x00FF;  // remove subcode

    objNew->iObjectID = newid;
    objNew->bActive = FALSE;

    objNew->iPosition = 0;
    objNew->iCounter = 0;

    obj1 = objObjects;
    obj2 = NULL;

    while (obj1)
    {
446
        obj2 = obj1;
Peter Achten's avatar
Peter Achten committed
447
448
449
450
451
        obj1 = obj1->objNext;
    }

    if (obj2)
    {
452
        obj2->objNext = objNew;
Peter Achten's avatar
Peter Achten committed
453
454
455
456
457
    }
    else
    {
        objObjects = objNew;
    }
458
459


Peter Achten's avatar
Peter Achten committed
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
    // inform Clean that new object has been created
    iCCObjectID = newid;
    SendMessage6ToClean (CcWmINITOBJECT, mapval, above, newid,
                           mapx * BoundBlockWidth,
                           mapy * BoundBlockHeight, iFrameCounter);
    iCCObjectID = 0;

    UpdatePosition (objNew);
}

/* remove game object with id ID and all objects that are not active (id==0) */
void GameObjectDone (int id)
{
    OBJECTREC *objCur = objObjects;
    OBJECTREC *objNext = NULL;
    OBJECTREC *objPrev = NULL;
    int mappos, mapval;

    while (objCur)
    {
        if ((id != -1) &&
            (((id > 0) && (objCur->iObjectID != id)) ||
             ((id == 0) && (objCur->bActive))
            )
           )
        {
486
487
            /* skip this object */
            objPrev = objCur;
Peter Achten's avatar
Peter Achten committed
488
489
490
491
            objNext = objCur->objNext;
        }
        else
        {
492
            /* remove this object */
Peter Achten's avatar
Peter Achten committed
493

494
495
            if (objCur->iObjectID == iFollowID)
                iFollowID = 0;
Peter Achten's avatar
Peter Achten committed
496

497
498
499
            /* link previous node to next node */
            if (objPrev)
                objPrev->objNext = objCur->objNext;
Peter Achten's avatar
Peter Achten committed
500
501
502
503
504
505
506
507
508
            else
                objObjects = objCur->objNext;

            objNext = objCur->objNext;

            /* call object's done function */

            if (id != -1)
            {
509
510
511
                iCCObjectID = objCur->iObjectID;
                SendMessage2ToClean (CcWmOBJECTDONE, objCur->iObjType, objCur->iObjectID);
                iCCObjectID = 0;
Peter Achten's avatar
Peter Achten committed
512
513
514
515
516
517
518
519
520

              /*  UpdatePosition (objCur);  */
            }
         /*
            objCur->iObjType = gCci.p1;
            objCur->iSubType = gCci.p2;
         */
            /* put ObjType and SubType back into map if >= 0 */
            if (!(objCur->iOptions & OO_REMOVE_MAP_CODE))
521
522
523
524
525
526
527
528
529
530
531
532
533
534
                if ((objCur->iMapX >= 0) && (objCur->iMapY >= 0))
                    if (objCur->iObjType >= 0)
                    {
                        mappos = (objCur->iMapY * BoundMapWidth + objCur->iMapX) * sizeof (int);
                        mapval = (*(int *) &sBoundMap[mappos]);
                        (*(int *) &sBoundMap[mappos]) = mapval | (objCur->iObjType << 8);

                        if (objCur->iSubType >= 0)
                        {
                            mappos = ((objCur->iMapY - 1) * BoundMapWidth + objCur->iMapX) * sizeof (int);
                            mapval = (*(int *) &sBoundMap[mappos]);
                            (*(int *) &sBoundMap[mappos]) = mapval | (objCur->iSubType << 8);
                        }
                    }
Peter Achten's avatar
Peter Achten committed
535
536

            /* free the current node */
537
            rfree (objCur);
Peter Achten's avatar
Peter Achten committed
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
        }
        objCur = objNext;
    }
}


void InitGameGlobals ()
{
    ghGameWindow = NULL;
    bGameActive = FALSE;
    iFrameCounter = 0;
}



/* GameTranslateKey translates WM_KEYDOWN wPara fields to GameKey values */
static int
GameTranslateKey (WPARAM wPara)
{
557
558
559
    switch (wPara)
    {
        case VK_BACK:        return GK_BACKSPACE; break;
Peter Achten's avatar
Peter Achten committed
560
        case VK_RETURN:      return GK_RETURN;    break;
561
562
        case VK_ESCAPE:      return GK_ESCAPE;    break;
        case VK_UP:          return GK_UP;        break;
Peter Achten's avatar
Peter Achten committed
563
        case VK_DOWN:        return GK_DOWN;      break;
564
565
        case VK_LEFT:        return GK_LEFT;      break;
        case VK_RIGHT:       return GK_RIGHT;     break;
Peter Achten's avatar
Peter Achten committed
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
        case VK_HOME:        return GK_HOME;      break;
        case VK_END:         return GK_END;       break;
//        case VK_PAGE_UP:     return GK_PAGE_UP;   break;
//        case VK_PAGE_DOWN:   return GK_PAGE_DOWN; break;
        case VK_F1:          return GK_F1;        break;
        case VK_F2:          return GK_F2;        break;
        case VK_F3:          return GK_F3;        break;
        case VK_F4:          return GK_F4;        break;
        case VK_F5:          return GK_F5;        break;
        case VK_F6:          return GK_F6;        break;
        case VK_F7:          return GK_F7;        break;
        case VK_F8:          return GK_F8;        break;
        case VK_F9:          return GK_F9;        break;
        case VK_F10:         return GK_F10;       break;
        case VK_F11:         return GK_F11;       break;
        case VK_F12:         return GK_F12;       break;
        case VK_SPACE:       return GK_SPACE;     break;
583
        default:
Peter Achten's avatar
Peter Achten committed
584
585
586
587
588
589
590
        {
             if ((wPara > 32) && (wPara <= 127))
                 return wPara;
             else
                 return GK_UNKNOWN;
             break;
        }
591
    }
Peter Achten's avatar
Peter Achten committed
592
593
594
595
596
597
}



/* buffer which holds the last state of each key */
static BOOL gk_state[GK_MAX_KEY + 1] =
598
    {FALSE};
Peter Achten's avatar
Peter Achten committed
599
600
601
602
603
604
605
606
607


//   MessageBox (NULL, "", NULL, MB_OK);


/* GameWindowProcedure is the Windows callback routine for a game window. */
static LRESULT CALLBACK
GameWindowProcedure (HWND hWin, UINT uMess, WPARAM wPara, LPARAM lPara)
{
608
609
610
    printMessage ("Game Window", hWin, uMess, wPara, lPara);
    switch (uMess)
    {
Peter Achten's avatar
Peter Achten committed
611
612
613
614
615
616
617
618
619
        case WM_CLOSE:
            bGameActive = FALSE;
            return 0;
            break;

        case WM_DESTROY:
            bGameActive = FALSE;
            ClearUserEvents ();
            GameObjectDone (-1);
620
            FreeGameLayerMapInfoList ();
Peter Achten's avatar
Peter Achten committed
621
            FreeSpriteAnimationList ();
622
            OSFreeGameBitmaps ();
Peter Achten's avatar
Peter Achten committed
623
624
625
626
627
628
629
            OSStopMusic ();
            OSDeInitSound ();
            OSDeInitGameWindow ();
            ShowCursor (TRUE);
            return 0;
            break;
        case MCI_NOTIFY:
630
            {
Peter Achten's avatar
Peter Achten committed
631
                // MessageBeep (MB_ICONASTERISK);
632
                if (wPara == MCI_NOTIFY_SUCCESSFUL)
Peter Achten's avatar
Peter Achten committed
633
                    OSPlayMusic (NULL, TRUE);  /* restart music */
634
635
            }
            break;
Peter Achten's avatar
Peter Achten committed
636
637
638
        case WM_PAINT:
            if (!FullScreen)
            {
639
640
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint (hWin, &ps);
Peter Achten's avatar
Peter Achten committed
641
642

                NextFrame (0);
643
                EndPaint (hWin, &ps);
Peter Achten's avatar
Peter Achten committed
644
            }
645
            break;
Peter Achten's avatar
Peter Achten committed
646
647
        case WM_KEYUP:
            {
648
                int keycode = GameTranslateKey (wPara);
Peter Achten's avatar
Peter Achten committed
649
650
651
652
653
654

                if (gk_state[keycode])
                {
                    OBJECTREC *obj = objObjects;
                    while (obj)
                    {
655
                        if ((obj->bActive) && (obj->iOptions & OO_CHECK_KEYBOARD))
Peter Achten's avatar
Peter Achten committed
656
657
658
659
660
                        {
                            int ix = obj->iXPos;
                            int iy = obj->iYPos;

                            iCCObjectID = obj->iObjectID;
661
                            SendMessage3ToClean (CcWmOBJECTKEYUP, obj->iObjType, obj->iObjectID, keycode);
Peter Achten's avatar
Peter Achten committed
662
663
664
665
666
                            iCCObjectID = 0;

                            if ((ix != obj->iXPos) || (iy != obj->iYPos))
                                UpdatePosition (obj);
                        }
667
                        obj = obj->objNext;
Peter Achten's avatar
Peter Achten committed
668
                    }
669
                    gk_state[keycode] = FALSE;
Peter Achten's avatar
Peter Achten committed
670
671
672
673
                }
            }
            break;
        case WM_KEYDOWN:
674
675
            {
                int keycode = GameTranslateKey (wPara);
Peter Achten's avatar
Peter Achten committed
676
677
678
679
                if (keycode == GK_ESCAPE)
                    if (bCheckEscape)
                        bGameActive = FALSE;

680
681
                switch (keycode)
                {
Peter Achten's avatar
Peter Achten committed
682
                    case GK_UNKNOWN:
683
684
685
686
                        return DefWindowProc (hWin, uMess, wPara, lPara);
                        break;
                    default:
                        {
Peter Achten's avatar
Peter Achten committed
687
688
689
690
691
                            BOOL found = FALSE;
                            OBJECTREC *obj = objObjects;

                            while (obj)
                            {
692
                                if ( (obj->bActive) &&
Peter Achten's avatar
Peter Achten committed
693
694
695
696
697
698
699
700
701
                                     (obj->iOptions & OO_CHECK_KEYBOARD) &&
                                     ( (!gk_state[keycode]) ||
                                       (obj->iOptions & OO_ALLOW_KEYBOARD_REPEAT)
                                     )
                                   )
                                {
                                    int ix = obj->iXPos;
                                    int iy = obj->iYPos;

702
703
704
                                    iCCObjectID = obj->iObjectID;
                                    SendMessage3ToClean (CcWmOBJECTKEYDOWN, obj->iObjType, obj->iObjectID, keycode);
                                    iCCObjectID = 0;
Peter Achten's avatar
Peter Achten committed
705
706
707
708
709
710

                                    if ((ix != obj->iXPos) || (iy != obj->iYPos))
                                        UpdatePosition (obj);

                                    found = TRUE;
                                }
711
                                obj = obj->objNext;
Peter Achten's avatar
Peter Achten committed
712
713
714
                            }

                            gk_state[keycode] = TRUE;
715
                        }
Peter Achten's avatar
Peter Achten committed
716

717
718
                        // debugging level, just move around
                        if (DebugScroll == TRUE)
Peter Achten's avatar
Peter Achten committed
719
                        {
720
721
722
                            SendMessage3ToClean (CcWmGAMEKEYBOARD, keycode, XScrollSpeed, YScrollSpeed);
                            XScrollSpeed = gCci.p1;
                            YScrollSpeed = gCci.p2;
Peter Achten's avatar
Peter Achten committed
723
724
725
                            iMaxXScrollSpeed = 8;
                            iMaxYScrollSpeed = 8;
                        }
726
727
728
729
730
                }
            }
            break;
        default:
            return DefWindowProc (hWin, uMess, wPara, lPara);
Peter Achten's avatar
Peter Achten committed
731
            break;
732
733
    }
    return 0;
Peter Achten's avatar
Peter Achten committed
734
735
736
737
738
739
740
}


/* move XView and YView towards iActualXView and iActualYView */
void CorrectView ()
{
    if (iActualXView > XView)
741
        XView = Min (XView + iMaxXScrollSpeed, iActualXView);
Peter Achten's avatar
Peter Achten committed
742
    if (iActualYView > YView)
743
        YView = Min (YView + iMaxYScrollSpeed, iActualYView);
Peter Achten's avatar
Peter Achten committed
744
    if (iActualXView < XView)
745
        XView = Max (XView - iMaxXScrollSpeed, iActualXView);
Peter Achten's avatar
Peter Achten committed
746
    if (iActualYView < YView)
747
        YView = Max (YView - iMaxYScrollSpeed, iActualYView);
Peter Achten's avatar
Peter Achten committed
748

749
750
751
    if (XView > TotalWidth - ScreenWidth)
    {
        XView = TotalWidth - ScreenWidth;
Peter Achten's avatar
Peter Achten committed
752
        iActualXView = XView;
753
754
755
756
757
        XScrollSpeed = 0;
    }
    if (YView > TotalHeight - ScreenHeight)
    {
        YView = TotalHeight - ScreenHeight;
Peter Achten's avatar
Peter Achten committed
758
        iActualYView = YView;
759
760
        YScrollSpeed = 0;
    }
Peter Achten's avatar
Peter Achten committed
761

762
763
764
    if (XView < 0)
    {
        XView = 0;
Peter Achten's avatar
Peter Achten committed
765
        iActualXView = XView;
766
767
768
769
770
        XScrollSpeed = 0;
    }
    if (YView < 0)
    {
        YView = 0;
Peter Achten's avatar
Peter Achten committed
771
        iActualYView = YView;
772
773
        YScrollSpeed = 0;
    }
Peter Achten's avatar
Peter Achten committed
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
}


void RunGame ()
{
    MSG msg;
    int i, j, x, y, w, h;
    int lastx, lasty;
    int fade;

    int result;
    int oos;

    iFrameCounter = 0;
    CorrectView ();

    x = XView / BoundBlockWidth;
    y = YView / BoundBlockHeight;
    w = ScreenWidth / BoundBlockWidth;
    h = ScreenHeight / BoundBlockHeight;
    for (i = -iStartObjX - 1; i < w + iStartObjX + 2; i++)
        for (j = -iStartObjY - 1; j < h + iStartObjY + 2; j++)
796
            InitGameObject (x + i, y + j);
Peter Achten's avatar
Peter Achten committed
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814

    lastx = x;
    lasty = y;

#ifdef SMART_DRAW
    bSmartDraw = 0;
    bAllowSmartDraw = 0;
#endif

    /* initialize autoinit object */
    CreateGameObject (0, 0, -1, -1, &result);

    fade = (bFadeIn)? -1 : 0;
    bGameActive = TRUE;
    while (bGameActive)
    {
        if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        {
815
816
            TranslateMessage (&msg);
            DispatchMessage (&msg);
Peter Achten's avatar
Peter Achten committed
817
818
819
820
821
        }

        if (iFollowID == 0)
        {
            iActualXView += XScrollSpeed;
822
            iActualYView += YScrollSpeed;
Peter Achten's avatar
Peter Achten committed
823
824
825
826
        }

        CorrectView ();

827
828
        x = XView / BoundBlockWidth;
        y = YView / BoundBlockHeight;
Peter Achten's avatar
Peter Achten committed
829
        if (y != lasty)
830
            for (i = -iStartObjX - 1; i < w + iStartObjX + 2; i++)
Peter Achten's avatar
Peter Achten committed
831
832
833
834
835
836
837
838
839
            {
                j = -iStartObjY;
                if (y < lasty)
                    InitGameObject (x + i, y + j);
                j = h + iStartObjY + 1;
                if (y > lasty)
                    InitGameObject (x + i, y + j);
             }
        if (x != lastx)
840
841
842
            for (j = -iStartObjY - 1; j < h + iStartObjY + 2; j++)
            {
                i = -iStartObjX;
Peter Achten's avatar
Peter Achten committed
843
                if (x < lastx)
844
845
                    InitGameObject (x + i, y + j);
                i = w + iStartObjX + 1;
Peter Achten's avatar
Peter Achten committed
846
                if (x > lastx)
847
848
                    InitGameObject (x + i, y + j);
            }
Peter Achten's avatar
Peter Achten committed
849
850
851
        lastx = x;
        lasty = y;

852
        NextFrame (fade);
Peter Achten's avatar
Peter Achten committed
853
        fade = 0;
854
        iFrameCounter++;
Peter Achten's avatar
Peter Achten committed
855

856
        SendMessage0ToClean (CcWmCHECKQUIT);
Peter Achten's avatar
Peter Achten committed
857
        if ((BOOL) gCci.p1)
858
            bGameActive = FALSE;
Peter Achten's avatar
Peter Achten committed
859
860
861
862
863
864
865
866

    }

    if (bFadeOut)
    {
        fade = 1;
        NextFrame (fade);
    }
867
    bGameActive = FALSE;
Peter Achten's avatar
Peter Achten committed
868
869

    ClearUserEvents ();
870
    GameObjectDone (-1);
Peter Achten's avatar
Peter Achten committed
871
872
873

    iFollowID = 0;

874
    //  MessageBeep (MB_ICONASTERISK);
Peter Achten's avatar
Peter Achten committed
875
876
877
}


Mike Wiering's avatar
Mike Wiering committed
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
/* create a new event */
void ScheduleEvent (int event, int par1, int par2, int par3, int par4,
                    int target, int subtarget, int time)
{
    struct USER_EVENT_INFO *uei;

    uei = rmalloc (sizeof (USER_EVENT_INFO));
    uei->iEventID = event;
    uei->iEventParameter1 = par1;
    uei->iEventParameter2 = par2;
    uei->iEventParameter3 = par3;
    uei->iEventParameter4 = par4;
    uei->iDestination = target;
    uei->iSubDestination = subtarget;
    uei->iTimeCounter = time;
    uei->ueiNext = ueiUserEventInfo;
    ueiUserEventInfo = uei;
}


Peter Achten's avatar
Peter Achten committed
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
/* play (actually schedule) a sound sample */
void PlaySoundSample (int id, int vol, int pan, int freq, int delay)
{
    ScheduleEvent (EV_PLAY_SOUND, id, vol, pan, freq, 0, -1, delay);
}

/* schedule any user event */
void ScheduleUserGameEvent (int event, int par1, int par2,
                            int target, int subtarget, int time)
{
    struct USER_EVENT_INFO *uei;

    if (event >= 0)
    {
        uei = rmalloc (sizeof (USER_EVENT_INFO));
        uei->iEventID = event;
        uei->iEventParameter1 = par1;
        uei->iEventParameter2 = par2;
        uei->iEventParameter3 = 0;
        uei->iEventParameter4 = 0;
        if (target == 0)
            uei->iDestination = -iCCObjectID;  /* only target current object */
        else
            if (target == -1)
                uei->iDestination = 0;  /* all objects */
            else
                uei->iDestination = target;  /* bounds */
        uei->iSubDestination = subtarget;
        uei->iTimeCounter = time;
        uei->ueiNext = ueiUserEventInfo;
        ueiUserEventInfo = uei;
    }
}


/* create the game window */
int CreateGameWindow (int w, int h, int bpp, BOOL fs)
{
    ScreenWidth = w;
    ScreenHeight = h;
    BitsPerPixel = bpp;
    FullScreen = fs;

    if (FullScreen)
        ghGameWindow =
            CreateWindowEx (WS_EX_TOPMOST,       /* extended style */
                            (LPCTSTR) FullScreenGameWindowClassName,  /* class */
                            (LPCTSTR) gAppName,  /* title */
                            WS_POPUP,            /* window style */
                            0, 0, ScreenWidth, ScreenHeight,
                            ghMainWindow,        /* ??? parent */
                            NULL,                /* menu */
                            (HANDLE) ghInst,
                            NULL                 /* window creation data */
                           );
    else
        ghGameWindow =
955
            CreateWindowEx (WS_OVERLAPPED,
Peter Achten's avatar
Peter Achten committed
956
957
958
959
960
961
962
963
964
965
966
967
968
                            (LPCTSTR) GameWindowClassName,
                            (LPCTSTR) gAppName,
                            WS_THICKFRAME,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            ScreenWidth,
                            ScreenHeight,
                            ghMainWindow,
                            NULL,
                            (HANDLE) ghInst,
                            NULL
                           );

969
970
    ShowWindow (ghGameWindow, SW_SHOWNORMAL);
    UpdateWindow (ghGameWindow);
Peter Achten's avatar
Peter Achten committed
971
972
973
974

    if (OSInitGameWindow ())
    {
        OSClearScreen ();
975
976
977
        if (FullScreen)
            OSFlip ();
        OSClearScreen ();
Peter Achten's avatar
Peter Achten committed
978
979
980
981
982
983
        OSClearVirtualScreen (FillBackgroundRGB);
        OSInitSound ();
    }
    else
        ErrorExit ("Game Window could not be created");

984
    iFrameCounter = 0;
Peter Achten's avatar
Peter Achten committed
985
986
987
988
989
990
991
992

    return ((int) ghGameWindow);
}


/* register game window class */
void RegisterGameWindowClass ()
{
993
    WNDCLASS wclass;
Peter Achten's avatar
Peter Achten committed
994
995
996
997
998
999
1000

    wclass.style = CS_HREDRAW | CS_VREDRAW;
    wclass.lpfnWndProc = (WNDPROC) GameWindowProcedure;
    wclass.cbClsExtra = 0;
    wclass.cbWndExtra = 0;
    wclass.hInstance = ghInst;
    wclass.hIcon = LoadIcon (ghInst, IDI_APPLICATION);
For faster browsing, not all history is shown. View entire blame