Skip to content

Commit 01aa092

Browse files
committed
[pingpong] Two player pingpong gameplay ready
1 parent 859580f commit 01aa092

File tree

5 files changed

+138
-27
lines changed

5 files changed

+138
-27
lines changed

include/fuzzy/kernel/process/process.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ void process_scheduler(int *_e_ip, int *_e_cs, int *_e_sp, int *_e_ss);
7575
// user space <-> kernel space data transfer helper
7676
extern void syscall_strncpy_user_to_kernel(int user_ds, char *src_es_address, char *dest_ds_address, size_t size);
7777
extern void syscall_strncpy_kernel_to_user(int user_ds, char *dest_address, char *src_address, size_t size);
78+
// assumes size is multiple of 4
7879
extern void kernel_memncpy_absolute(int dst_ds, char *dst_address, int src_ds, char *src_address, size_t size);
7980

8081
// operations

src/kernel/process/process.asm

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ global kernel_memncpy_absolute
5959
ret
6060

6161
kernel_memncpy_absolute:
62+
; assumes count is multiple of 4
6263
push ebp
6364
mov ebp, esp
6465
; callee save register
@@ -69,13 +70,14 @@ global kernel_memncpy_absolute
6970
push es
7071

7172
mov ecx, [ebp + 0x18] ; count
73+
shr ecx, 2 ; count/4
7274
mov esi, [ebp + 0x14] ; src_loc
7375
mov ds, [ebp + 0x10] ; src_ds
7476
mov edi, [ebp + 0x0C] ; dest_loc
7577
mov es, [ebp + 0x08] ; dest_ds
7678

7779
; strcpy
78-
rep movsb
80+
rep movsd ; move double word
7981

8082
pop es
8183
pop ds

src/usr/include/graphics.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@ int graphresult();
3434
void closegraph();
3535
void cleardevice();
3636

37+
void graphautoflush_enable();
38+
void graphautoflush_disable();
3739
int graphflush();
3840

3941
void setcolor(int color);
4042
int getcolor();
4143
void setbkcolor(int color);
4244
int getbkcolor();
4345

44-
void putpixel_noflush(int x, int y, int color);
4546
void putpixel(int x, int y, int color);
4647

4748
void line(int x1, int y1, int x2, int y2);

src/usr/lib/graphics.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ static struct GraphicsState {
66
int bkcolor;
77
int color;
88
int last_err;
9+
int auto_flush_disabled;
910
} gstate = {0};
1011

1112
static uint8_t BUFFER[GRAPHICS_MAX_HEIGHT][GRAPHICS_MAX_WIDTH]={0};
@@ -32,6 +33,20 @@ void closegraph() {
3233
gstate.last_err = SYSCALL_A1(SYSCALL_GRAPHICS, SYSCALL_GRAPHICS_CLOSEGRAPH);
3334
}
3435

36+
void graphautoflush_enable() {
37+
gstate.auto_flush_disabled = 1;
38+
}
39+
40+
void graphautoflush_disable() {
41+
gstate.auto_flush_disabled = 0;
42+
}
43+
44+
static void _autoflushnow() {
45+
if(!gstate.auto_flush_disabled) {
46+
graphflush();
47+
}
48+
}
49+
3550
int graphflush() {
3651
gstate.last_err = SYSCALL_A2(SYSCALL_GRAPHICS, SYSCALL_GRAPHICS_COPYBUFFER, BUFFER);
3752
return gstate.last_err;
@@ -40,7 +55,7 @@ int graphflush() {
4055
void cleardevice() {
4156
memset(BUFFER, gstate.bkcolor, sizeof(BUFFER));
4257
moveto(0, 0);
43-
graphflush();
58+
_autoflushnow();
4459
}
4560

4661
void setviewport(int left, int top, int right, int bottom, int clip) {
@@ -73,11 +88,7 @@ int getbkcolor() {
7388

7489
void putpixel(int x, int y, int color) {
7590
BUFFER[y][x]=color;
76-
graphflush();
77-
}
78-
79-
void putpixel_noflush(int x, int y, int color) {
80-
BUFFER[y][x]=color;
91+
_autoflushnow();
8192
}
8293

8394
void line(int x1, int y1, int x2, int y2) {
@@ -111,7 +122,7 @@ void line(int x1, int y1, int x2, int y2) {
111122
BUFFER[y][x]=color;
112123
}
113124
}
114-
graphflush();
125+
_autoflushnow();
115126
}
116127

117128
void drawpoly(int num, int polypoints[]) {
@@ -133,7 +144,7 @@ void rectangle(int left, int top, int right, int bottom) {
133144
BUFFER[y][left]=color;
134145
BUFFER[y][right]=color;
135146
}
136-
graphflush();
147+
_autoflushnow();
137148
}
138149

139150
void bar(int left, int top, int right, int bottom) {
@@ -144,7 +155,7 @@ void bar(int left, int top, int right, int bottom) {
144155
BUFFER[y][x]=color;
145156
}
146157
}
147-
graphflush();
158+
_autoflushnow();
148159
}
149160

150161
void ellipse(int x, int y, int x_radius, int y_radius) {
@@ -173,7 +184,7 @@ void fillellipse(int xcenter, int ycenter, int x_radius, int y_radius) {
173184
}
174185
}
175186
}
176-
graphflush();
187+
_autoflushnow();
177188
}
178189

179190
void floodfill(int x,int y, int color) {

src/usr/local/src/pingpong.c

Lines changed: 111 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,140 @@
88
#define PLAYER_1 1
99
#define PLAYER_2 2
1010

11+
const int BUSY_WAIT_FRAMECOUNTER = 2e7;
12+
1113
const int WINDOW_HEIGHT = GRAPHICS_MAX_HEIGHT;
1214
const int WINDOW_WIDTH = GRAPHICS_MAX_WIDTH;
1315

16+
const int BORDER = 5;
17+
1418
const int BAT_HALF_HEIGHT = 15;
1519
const int BAT_HALF_WIDTH = 2;
1620
const int BAT_SPEED = 5;
1721

18-
const int bat_miny = BAT_HALF_HEIGHT;
19-
const int bat_maxy = (WINDOW_HEIGHT-1)-BAT_HALF_HEIGHT;
20-
2122
const int p1_x = 10;
2223
const int p2_x = (WINDOW_WIDTH-1)-p1_x;
2324

24-
const int BALL_SPEED = 2;
25+
const float BALL_SPEED_MAX = 10;
26+
const float BALL_SPEED_INIT = 5;
27+
const float BALL_SPEED_INC = 1.1;
2528
const int BALL_RADIUS = 3;
2629

2730
struct playerState {
28-
int y;
31+
float y;
32+
float yspeed;
2933
};
3034

3135
struct {
32-
int x,y;
33-
int xspeed, yspeed;
36+
int top, bottom;
37+
int left, right;
38+
} field;
39+
40+
41+
struct {
42+
float x, y, xprev, yprev;
43+
float xspeed, yspeed;
3444
} ball;
3545

3646
struct {
3747
struct playerState p1, p2;
48+
int turn;
49+
int p1Score;
50+
int p2Score;
3851
} gstate;
3952

4053
void frame_wait() {
4154
// busy wait
42-
volatile int counter = 1e7;
55+
volatile int counter = BUSY_WAIT_FRAMECOUNTER;
4356
while (counter--);
4457
}
4558

59+
void reset_ball() {
60+
ball.xprev = ball.x = WINDOW_WIDTH/2;
61+
ball.yprev = ball.y = WINDOW_HEIGHT/2;
62+
if(gstate.turn == PLAYER_1) {
63+
ball.xspeed = BALL_SPEED_INIT*0.8;
64+
ball.yspeed = BALL_SPEED_INIT*0.6;
65+
} else {
66+
ball.xspeed = -BALL_SPEED_INIT*0.8;
67+
ball.yspeed = BALL_SPEED_INIT*0.6;
68+
}
69+
}
70+
4671
void game_init() {
47-
gstate.p1.y = (bat_miny+bat_maxy)/2;
72+
graphautoflush_disable();
73+
74+
field.top = BORDER-1;
75+
field.bottom = WINDOW_HEIGHT-BORDER;
76+
field.left = BORDER-1;
77+
field.right = WINDOW_WIDTH-BORDER;
78+
79+
gstate.p1.y = (field.top+field.bottom)/2;
4880
gstate.p2 = gstate.p1;
4981

50-
ball.x = WINDOW_WIDTH/2;
51-
ball.y = WINDOW_HEIGHT/2;
52-
ball.xspeed = BALL_SPEED*0.8;
53-
ball.yspeed = BALL_SPEED*0.6;
82+
gstate.p1Score = gstate.p2Score = 0;
83+
gstate.turn = PLAYER_1;
84+
reset_ball();
85+
}
86+
87+
static void collision(float zm_border, float zm_prevx, float *zm_newx, float *zm_xspeed, float rigid_x) {
88+
// assumes: zm is a square object
89+
// collison is written along x-coordinates but can be generalized.
90+
if(zm_prevx<=rigid_x-zm_border<=*zm_newx) {
91+
// move object as per collision for object moving from left to right.
92+
*zm_newx = 2*(rigid_x-zm_border) - (*zm_newx);
93+
*zm_xspeed = -1;
94+
} else if(zm_prevx>=rigid_x+zm_border>=*zm_newx) {
95+
// move object as per collision for object moving from right to left.
96+
*zm_newx = 2*(rigid_x+zm_border) - (*zm_newx);
97+
*zm_xspeed = -1;
98+
}
99+
}
100+
101+
void check_collision() {
102+
// wall
103+
104+
if(ball.y>field.bottom-BALL_RADIUS) {
105+
ball.yspeed *= -1;
106+
ball.y = 2*(field.bottom-BALL_RADIUS)-ball.y;
107+
} else if(ball.y<field.top+BALL_RADIUS) {
108+
ball.yspeed *= -1;
109+
ball.y = 2*(field.top+BALL_RADIUS)-ball.y;
110+
}
111+
112+
if(ball.x>p2_x-BAT_HALF_WIDTH-BALL_RADIUS && ball.y>=gstate.p2.y-BAT_HALF_HEIGHT && ball.y<=gstate.p2.y+BAT_HALF_HEIGHT) {
113+
// right bat
114+
ball.xspeed *= -1 * BALL_SPEED_INC;
115+
ball.x = 2*(p2_x-BAT_HALF_WIDTH-BALL_RADIUS)-ball.x;
116+
} else if(ball.x<p1_x+BAT_HALF_WIDTH+BALL_RADIUS && ball.y>=gstate.p1.y-BAT_HALF_HEIGHT && ball.y<=gstate.p1.y+BAT_HALF_HEIGHT) {
117+
// left bat
118+
ball.xspeed *= -1 * BALL_SPEED_INC;
119+
ball.x = 2*(p1_x+BAT_HALF_WIDTH+BALL_RADIUS)-ball.x;
120+
}
121+
122+
123+
if(ball.x>WINDOW_WIDTH-1) {
124+
// player 2 missed ball
125+
gstate.p1Score += 1;
126+
gstate.turn = (gstate.turn==PLAYER_1)?PLAYER_2:PLAYER_1;
127+
reset_ball();
128+
} else if(ball.x<0) {
129+
// player 1 missed ball
130+
gstate.p2Score += 1;
131+
gstate.turn = (gstate.turn==PLAYER_1)?PLAYER_2:PLAYER_1;
132+
reset_ball();
133+
}
54134
}
55135

56136
void draw_board() {
57137
// clear screen
58138
setbkcolor(GREEN);
59139
cleardevice();
60140

141+
setcolor(BROWN);
142+
bar(0, 0, WINDOW_WIDTH, field.top);
143+
bar(0, field.bottom, WINDOW_WIDTH-1, WINDOW_HEIGHT-1);
144+
61145
setcolor(BLUE);
62146
bar(p1_x-BAT_HALF_WIDTH, gstate.p1.y-BAT_HALF_HEIGHT,
63147
p1_x+BAT_HALF_WIDTH, gstate.p1.y+BAT_HALF_HEIGHT);
@@ -68,6 +152,8 @@ void draw_board() {
68152

69153
setcolor(WHITE);
70154
fillellipse(ball.x, ball.y, BALL_RADIUS, BALL_RADIUS);
155+
156+
graphflush();
71157
}
72158

73159
void move_bat(int player_id, int dir) {
@@ -87,23 +173,33 @@ void move_bat(int player_id, int dir) {
87173
}
88174

89175
// keep bat in bounds
90-
p->y = max(bat_miny, min(bat_maxy, p->y));
176+
const int bat_miny = field.top+1+BAT_HALF_HEIGHT;
177+
const int bat_maxy = field.bottom-1-BAT_HALF_HEIGHT;
178+
179+
if(p->y > bat_maxy) {
180+
p->y = bat_maxy;
181+
} else if(p->y < bat_miny) {
182+
p->y = bat_miny;
183+
}
91184
}
92185

93186
void move_ball() {
187+
ball.xprev = ball.x;
188+
ball.yprev = ball.y;
94189
ball.x += ball.xspeed;
95190
ball.y += ball.yspeed;
96191
}
97192

98193
void game() {
99194
game_init();
100195
while (1) {
196+
check_collision();
101197
draw_board();
102198

103199
move_ball();
104200

201+
frame_wait();
105202
if(!kbhit()) {
106-
frame_wait();
107203
continue;
108204
}
109205
char c = getch();

0 commit comments

Comments
 (0)