-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathphysics.c
138 lines (127 loc) · 3.21 KB
/
physics.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* Game physics/mechanics - i.e. How do things move inside the game
* vim:set cin sm ts=8 sw=4 sts=4: - Sec <sec@42.org>
* $Id: physics.c,v 1.15 2004/06/22 21:57:45 sec Exp $
*/
#include "brillion.h"
void move_step(signed int input){
int x,y;
int xn,yn;
int ballx,bally;
field *lvl=play->f;
ballx=lvl->x;bally=lvl->y;
x=lvl->x/2; y=lvl->y/2;
lvl->y+=lvl->dir; lvl->x+=input;
xn=lvl->x/2; yn=lvl->y/2;
/* NOTE: In the original level 4 the following happens:
* Frame 1: Ball inside disk (24,20), heading downward
* Frame 2: Ball displaced into block, block is exploding
* Frame 3: Ball bounced back into disk,
* Frame 4: Ball bounces back into (now) free sqaure.
*
* Because this behaviour is hard to implement, and i doesn't matter for
* gameplay, I moved the starting point of the ball into the block, and
* 'hit' the block without moving simultaneously with the first frame.
*/
if(PIECE(x,y)) /* Are we inside something? Can happen at start of level */
move_touch(x,y,0,0);
/* Where are we moving into? */
if(xn==x){
if(yn==y){
/* inside of own square */;
}else{
if (move_touch(xn,yn,0,lvl->dir)){
lvl->dir=-lvl->dir;
lvl->y+=2*lvl->dir;
}
};
}else{
if(yn==y){
if(move_touch(xn,yn,input,0)){
input=-input;
lvl->x+=2*input;
};
}else{ /* Tricky case: leaving square diagonally */
if(PIECE(x,yn) && PIECE(xn,y)){
/* XXX: What happens if both are STAR?
* XXX: both disks: This does only move one disk in the original.
*/
move_touch(x,yn,0,lvl->dir);
move_touch(xn,y,input,0);
input=-input;
lvl->x+=2*input;
lvl->dir=-lvl->dir;
lvl->y+=2*lvl->dir;
}else if(PIECE(x,yn)){
if(move_touch(x,yn,0,lvl->dir)){
lvl->dir=-lvl->dir;
lvl->y+=2*lvl->dir;
};
}else if(PIECE(xn,y)){
if(move_touch(xn,y,input,0)){
input=-input;
lvl->x+=2*input;
};
}else{
if(move_touch(xn,yn,0,0)){
input=-input;
lvl->x+=2*input;
lvl->dir=-lvl->dir;
lvl->y+=2*lvl->dir;
};
};
};
};
if(play->status == S_DIE){ /* Don't move if you die */
lvl->x=ballx;
lvl->y=bally;
}else{
create_moveanim(A_BALL,lvl->color,ballx,bally,lvl->x,lvl->y);
};
return;
}
int move_touch(int x, int y,signed int dx,signed int dy){
int bounce=1;
field *lvl=play->f;
switch(PIECE(x,y)){
case SPACE:
bounce=0;
break;
case WALL:
case OUTER_WALL:
play_touch(PIECE(x,y));
break;
case DEATH:
play_touch(DEATH);
printf("You die, how embarrassing!\n");
play->status=S_DIE; /* XXX: layering */
break;
case BLOCK:
if(lvl->color==COLOR(x,y)){
play_touch(BLOCK);
PIECE(x,y)=SPACE;
create_staticanim(A_EXPLODE,COLOR(x,y),x,y);
if(--lvl->blocks ==0 && play->status!=S_DIE)
play->status=S_FINISH;
play->points+=lvl->ppb;
};
break;
case DISK:
if(lvl->color==COLOR(x,y)){
if(!PIECE(x+dx,y+dy)){
play_touch(DISK);
PIECE(x+dx,y+dy)=PIECE(x,y);
COLOR(x+dx,y+dy)=COLOR(x,y);
PIECE(x,y)=SPACE;
create_moveanim(A_DISK, COLOR(x,y), x, y, x+dx, y+dy);
}
};
break;
case STAR:
play_touch(STAR);
lvl->color=COLOR(x,y);
break;
default:
printf("Whoops?\n");
};
return bounce;
}