Tutorial 3 

In this tutorial-part we just add the moving ball and check for collision of it with the player-racket and the borders.
At first an overview about modifications in the file pingpong.c.
pingpong.c: Overview about modifications /* global declarations */ [...] /* show help-text */ [...] /* check for collisions */ [CODEBOX] /* main function */ int main(int argc, char **argv) { /* variable declaration */ [CODEBOX] /* initializing */ [CODEBOX] /* opening */ [...] /* set keys */ [...] /* initialize player-racket */ [CODEBOX] /* initialize ball */ [...] /* show help, start background music */ /* game loop */ [...] /* receive input-events and check the local key-strokes */ [CODEBOX] /* check key-strokes for player-racket */ [CODEBOX] /* move ball */ [CODEBOX] /* draw out */ [...] /* flush and wait */ /* end game */ [...] /* destroy and exit */ }
An overview about the used variables in function main().
We add two audio descriptors and the ball structure.
[To Position]
pingpong.c: the variables in function main() const int border_size = 10; /* size of borders in pixels */ int winw, winh; /* window's width and height */ int audc_hit, audc_gameover, audc_bgmusic; /* audio descriptors */ struct { /* player's structure */ struct VG_Image *imgp; /* image */ struct VG_Rect rect; /* rectangle position */ } player; struct { /* ball's structure */ struct VG_Image *imgp; /* image */ struct VG_RectCent rectc; /* rectangle position */ int angle; /* moving direction angle */ int factor; /* moving velocity in 1/1000 pixels */ } ball; /* helper variables */ struct VG_Rect rect; struct VG_RectCent *rectcp; int rectc_nr, ipos; struct VG_Position posi;
We open the window, deactivate mouse grabbing, open the audio system
and load the audio-files, adding one for ball's collision and one for game-over.
[To Position]
pingpong.c: function main() /* initialize and open window */ if (!VG_init("VgaGames4 tutorial 3")) { exit(1); } if (!vg4->window->open(VG_WINDOW_SIZE_LOW, VG_WINDOW_SCALE_BEST)) { VG_dest(); exit(1); } vg4->window->getsize(&winw, &winh); /* get window-size */ /* set mouse grabbing to off */ vg4->input->mouse_grabbing(VG_FALSE); /* open audio system */ if (!vg4->audio->open(VG_AUDIO_FREQ_MEDIUM, VG_FALSE)) { VG_dest(); exit(1); } /* load audio files */ audc_hit = vg4->audio->load("files/hit.wav", 100, VG_AUDIO_VOLUME_SOUND); audc_gameover = vg4->audio->load("files/gameover.wav", 100, VG_AUDIO_VOLUME_SOUND); audc_bgmusic = vg4->audio->load("files/bgmusic.wav", 50, VG_AUDIO_VOLUME_MUSIC);
We initialize the ball, using the structure-variable ball.
The ball-image is loaded and the rectangle of the ball is set
to the center of the window with a randomized moving angle.
The velocity of the ball is set to 3.5 pixels per moving-step.
[To Position]
pingpong.c: function main() /* initialize ball, put it at the center of the window */ /* load image */ ball.imgp = vg4->image->load("files/ball.bmp"); if (ball.imgp == NULL) { VG_dest(); exit(1); } /* set rectangle */ vg4->image->getsize(ball.imgp, NULL, &ball.rectc.rect.w, &ball.rectc.rect.h); ball.rectc.rect.x = (winw - ball.rectc.rect.w) / 2; ball.rectc.rect.y = (winh - ball.rectc.rect.h) / 2; ball.rectc.centx = ball.rectc.centy = 0; /* set moving angle and factor */ ball.angle = 45 + 90 * vg4->random->get("ball-angle", 0, 3); /* randomized moving direction */ ball.factor = 3500;
Now we are in the game-loop.
When moving the player-racket we also check for collision with the ball.
[To Position]
pingpong.c: in the game-loop of the function main() /* +++ player: check for key-strokes +++ */ /* moving up */ if (vg4->input->key_pressed(kref.k_up)) { int y = player.rect.y; player.rect.y -= 2; if (player.rect.y < border_size) { player.rect.y = border_size; } /* check for collision with ball */ if (check_for_collision(&ball.rectc.rect, &ball.angle, &player.rect)) { player.rect.y = y; vg4->audio->play(audc_hit, VG_FALSE, VG_FALSE); } } /* moving down */ if (vg4->input->key_pressed(kref.k_down)) { int y = player.rect.y; player.rect.y += 2; if (player.rect.y > winh - border_size - player.rect.h) { player.rect.y = winh - border_size - player.rect.h; } /* check for collision with ball */ if (check_for_collision(&ball.rectc.rect, &ball.angle, &player.rect)) { player.rect.y = y; vg4->audio->play(audc_hit, VG_FALSE, VG_FALSE); } }
We also have to move the ball.
The function vg4->misc->moving_one_step() is used to get the moving positions.
Then we iterate over these positions,
checking for collisions with borders and the player-racket.
If the player missed the ball (moving outside the window), the game is over.
[To Position]
pingpong.c: in the game-loop of the function main() /* +++ move ball +++ */ /* increase ball-factor for 1/1000 pixel */ ball.factor++; /* get moving steps */ rectc_nr = vg4->misc->moving_one_step(&ball.rectc, ball.angle, ball.factor / 100, &rectcp); /* iterate moving steps and check for collisions */ for (ipos = 0; ipos < rectc_nr; ipos++) { /* player missed the ball? */ if (rectcp[ipos].rect.x + ball.rectc.rect.w <= 0) { /* play audio and wait for its end */ vg4->audio->stop(audc_bgmusic, VG_FALSE); vg4->audio->play(audc_gameover, VG_FALSE, VG_FALSE); while (vg4->audio->is_playing(audc_gameover, NULL)) { vg4->window->flush(); vg4->misc->wait_time(40); } goto endgame; } /* check right border */ if (rectcp[ipos].rect.x > winw - border_size - ball.rectc.rect.w) { /* change moving direction */ ball.angle = 360 - ball.angle; ball.angle %= 360; ball.angle += 360; ball.angle %= 360; vg4->audio->play(audc_hit, VG_FALSE, VG_FALSE); break; } /* check top border */ if (rectcp[ipos].rect.y < border_size) { /* change moving direction */ ball.angle = 180 - ball.angle; ball.angle %= 360; ball.angle += 360; ball.angle %= 360; vg4->audio->play(audc_hit, VG_FALSE, VG_FALSE); break; } /* check bottom border */ if (rectcp[ipos].rect.y > winh - border_size - ball.rectc.rect.h) { /* change moving direction */ ball.angle = 180 - ball.angle; ball.angle %= 360; ball.angle += 360; ball.angle %= 360; vg4->audio->play(audc_hit, VG_FALSE, VG_FALSE); break; } /* check for collision with player */ if (check_for_collision(&rectcp[ipos].rect, &ball.angle, &player.rect)) { vg4->audio->play(audc_hit, VG_FALSE, VG_FALSE); break; } /* actualize rectangle position */ ball.rectc = rectcp[ipos]; }
We have all moving done, now we draw out all to the window,
where we just add the drawing of the ball.
[To Position]
pingpong.c: in the game-loop of the function main() /* +++ draw out +++ */ /* clear window */ vg4->window->clear(); /* draw background and borders */ vg4->window->fill(vg4->misc->colorbrightness(VG_COLOR_BLUE, 50)); /* top border */ rect.x = rect.y = 0; rect.w = winw; rect.h = border_size; vg4->window->draw_rect(&rect, VG_COLOR_RGB(0xb1, 0, 0), VG_TRUE); /* bottom border */ rect.x = 0; rect.y = winh - border_size; rect.w = winw; rect.h = border_size; vg4->window->draw_rect(&rect, VG_COLOR_RGB(0xb1, 0, 0), VG_TRUE); /* right border */ rect.x = winw - border_size; rect.y = 0; rect.w = border_size; rect.h = winh; vg4->window->draw_rect(&rect, VG_COLOR_RGB(0xb1, 0, 0), VG_TRUE); /* draw player */ vg4->window->copy(player.imgp, vg4->misc->rect2position(&posi, &player.rect), NULL); /* draw ball */ vg4->window->copy(ball.imgp, vg4->misc->rect2position(&posi, &ball.rectc.rect), NULL);
At last we add the function check_for_collision(),
which checks whether the ball collides with the player-racket.
[To Position]
pingpong.c: function check_for_collision() /* check whether ball collides with player * @param ball_rect rectangle of the ball * @param ball_angle angle of the ball, will be updated * @param player_rect rectangle of the player-racket * @return VG_TRUE = collision or VG_FALSE = no collision */ static VG_BOOL check_for_collision(const struct VG_Rect *ball_rect, int *ball_angle, const struct VG_Rect *player_rect) { VG_BOOL retw; if (ball_rect == NULL || ball_angle == NULL || player_rect == NULL) { return VG_FALSE; } /* check if ball touches player */ if (ball_rect->x + ball_rect->w - 1 < player_rect->x || ball_rect->x > player_rect->x + player_rect->w - 1) { return VG_FALSE; } if (ball_rect->y + ball_rect->h - 1 < player_rect->y || ball_rect->y > player_rect->y + player_rect->h - 1) { return VG_FALSE; } /* modify ball-angle according to collision side */ retw = VG_FALSE; if (ball_rect->x <= player_rect->x + player_rect->w - 1 && ball_rect->x + ball_rect->w - 1 >= player_rect->x + player_rect->w - 1) { /* ball collides with player on the right */ *ball_angle = 360 - (*ball_angle); *ball_angle %= 360; *ball_angle += 360; *ball_angle %= 360; retw = VG_TRUE; } if (ball_rect->y + ball_rect->h - 1 >= player_rect->y && ball_rect->y <= player_rect->y) { /* ball collides with player on the top */ *ball_angle = 180 - (*ball_angle); *ball_angle %= 360; *ball_angle += 360; *ball_angle %= 360; retw = VG_TRUE; } if (ball_rect->y <= player_rect->y + player_rect->h - 1 && ball_rect->y + ball_rect->h - 1 >= player_rect->y + player_rect->h - 1) { /* ball collides with player on the bottom */ *ball_angle = 180 - (*ball_angle); *ball_angle %= 360; *ball_angle += 360; *ball_angle %= 360; retw = VG_TRUE; } return retw; }
<<Previous |
Download ![]() |
Next>> |