Bounce the Ball
When the ball hits the edge of the screen we want it to bounce to stay in the screen
Published
Liked the article? Share it!

Now that we have a base to work with, we can make something that starts to look like Brickout. In this step we bounce our ball around the screen.
main.c
#include <epoxy/gl.h>
#include <epoxy/glx.h>
#include <gtk/gtk.h>
#include <math.h>
#include "DashGL/dashgl.h"
#define WIDTH 640.0f
#define HEIGHT 480.0f
static void on_realize(GtkGLArea *area);
static void on_render(GtkGLArea *area, GdkGLContext *context);
static gboolean on_idle(gpointer data);
float dx, dy;
vec3 pos = { 50.0f, 50.0f, 0.0f };
mat4 mvp;
GLuint program;
GLuint vao, vbo_circle;
GLint attribute_coord2d;
GLint uniform_mvp;
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *glArea;
gtk_init(&argc, &argv);
// Initialize Window
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Brickout Tutorial");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_UTILITY);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
// Initialize GTK GL Area
glArea = gtk_gl_area_new();
gtk_widget_set_vexpand(glArea, TRUE);
gtk_widget_set_hexpand(glArea, TRUE);
g_signal_connect(glArea, "realize", G_CALLBACK(on_realize), NULL);
g_signal_connect(glArea, "render", G_CALLBACK(on_render), NULL);
gtk_container_add(GTK_CONTAINER(window), glArea);
// Show widgets
gtk_widget_show_all(window);
gtk_main();
return 0;
}
static void on_realize(GtkGLArea *area) {
// Debug Message
g_print("on realize\n");
gtk_gl_area_make_current(area);
if(gtk_gl_area_get_error(area) != NULL) {
fprintf(stderr, "Unknown error\n");
return;
}
const GLubyte *renderer = glGetString(GL_RENDER);
const GLubyte *version = glGetString(GL_VERSION);
const GLubyte *shader = glGetString(GL_SHADING_LANGUAGE_VERSION);
printf("Shader %s\n", shader);
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
int i;
float angle, nextAngle;
int num_segments = 100;
GLfloat circle_vertices[6 * 100];
for(i = 0; i dx = 2.0f;
dy = 3.0f;
}
static void on_render(GtkGLArea *area, GdkGLContext *context) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mat4_translate(pos, mvp);
glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
glBindVertexArray(vao);
glEnableVertexAttribArray(attribute_coord2d);
glBindBuffer(GL_ARRAY_BUFFER, vbo_circle);
glVertexAttribPointer(
attribute_coord2d,
2,
GL_FLOAT,
GL_FALSE,
0,
0
);
glDrawArrays(GL_TRIANGLES, 0, 3 * 100);
glDisableVertexAttribArray(attribute_coord2d);
}
static gboolean on_idle(gpointer data) {
pos[0] += dx;
pos[1] += dy;
if(pos[0] > WIDTH) {
pos[0] = WIDTH;
dx *= -1;
} else if(pos[0] <0) {
pos[0] = 0;
dx *= -1;
}
if(pos[1] > HEIGHT) {
pos[1] = HEIGHT;
dy *= -1;
} else if(pos[1] <0) {
pos[1] = 0;
dy *= -1;
}
gtk_widget_queue_draw(GTK_WIDGET(data));
return TRUE;
}
Compile
$ gcc -c -o DashGL/dashgl.o DashGL/dashgl.c -lepoxy -lpng -lm
$ gcc `pkg-config --cflags gtk+-3.0` main.c DashGL/dashgl.o `pkg-config --libs gtk+-3.0` \
-lepoxy -lm -lpng
Run
$ ./a.out