|
Ivan Mahonin |
d6ae44 |
#include <stdlib.h>
|
|
Ivan Mahonin |
d6ae44 |
#include <time.h>
|
|
Ivan Mahonin |
d6ae44 |
#include <stdio.h>
|
|
Ivan Mahonin |
d6ae44 |
#include <math.h>
|
|
Ivan Mahonin |
d6ae44 |
#include <gtk/gtk.h>
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
#define COUNT 10
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
const double speed = 10.0;
|
|
Ivan Mahonin |
d6ae44 |
const double jump = 40.0;
|
|
Ivan Mahonin |
d6ae44 |
const double gravity = 2.0;
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
typedef struct {
|
|
Ivan Mahonin |
d6ae44 |
double left;
|
|
Ivan Mahonin |
d6ae44 |
double top;
|
|
Ivan Mahonin |
d6ae44 |
double right;
|
|
Ivan Mahonin |
d6ae44 |
double bottom;
|
|
Ivan Mahonin |
d6ae44 |
} Block;
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
cairo_surface_t *surface;
|
|
Ivan Mahonin |
d6ae44 |
GtkWidget *window;
|
|
Ivan Mahonin |
d6ae44 |
Block blocks[COUNT];
|
|
Ivan Mahonin |
d6ae44 |
gboolean left_key = FALSE;
|
|
Ivan Mahonin |
d6ae44 |
gboolean right_key = FALSE;
|
|
Ivan Mahonin |
d6ae44 |
double px = 0.0;
|
|
Ivan Mahonin |
d6ae44 |
double py = 0.0;
|
|
Ivan Mahonin |
d6ae44 |
double vx = 0.0;
|
|
Ivan Mahonin |
d6ae44 |
double vy = 0.0;
|
|
Ivan Mahonin |
d6ae44 |
double score = 0.0;
|
|
Ivan Mahonin |
d6ae44 |
double max_score = 0.0;
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
void generate_block(Block *block, double top) {
|
|
Ivan Mahonin |
d6ae44 |
double window_width = gtk_widget_get_allocated_width(window);
|
|
Ivan Mahonin |
d6ae44 |
double width = ((double)rand()/(double)RAND_MAX + 1.0) * window_width / 6.0;
|
|
Ivan Mahonin |
d6ae44 |
block->left = (double)rand()/(double)RAND_MAX * (window_width - width);
|
|
Ivan Mahonin |
d6ae44 |
block->right = block->left + width;
|
|
Ivan Mahonin |
d6ae44 |
block->top = top;
|
|
Ivan Mahonin |
d6ae44 |
block->bottom = block->top + 10;
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
void generate_blocks() {
|
|
Ivan Mahonin |
d6ae44 |
srand(time(NULL));
|
|
Ivan Mahonin |
d6ae44 |
double window_height = gtk_widget_get_allocated_height(window);
|
|
Ivan Mahonin |
d6ae44 |
for(int i = 0; i < COUNT; ++i)
|
|
Ivan Mahonin |
d6ae44 |
generate_block(&blocks[i], window_height);
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
void scroll_blocks(double dy) {
|
|
Ivan Mahonin |
d6ae44 |
double window_height = gtk_widget_get_allocated_height(window);
|
|
Ivan Mahonin |
d6ae44 |
score += dy;
|
|
Ivan Mahonin |
d6ae44 |
if (score > max_score) max_score = score;
|
|
Ivan Mahonin |
d6ae44 |
py += dy;
|
|
Ivan Mahonin |
d6ae44 |
for(int i = 0; i < COUNT; ++i) {
|
|
Ivan Mahonin |
d6ae44 |
blocks[i].top += dy;
|
|
Ivan Mahonin |
d6ae44 |
blocks[i].bottom += dy;
|
|
Ivan Mahonin |
d6ae44 |
if (blocks[i].top < 0) {
|
|
Ivan Mahonin |
d6ae44 |
generate_block(&blocks[i], window_height + (double)rand()/(double)RAND_MAX*fabs(dy));
|
|
Ivan Mahonin |
d6ae44 |
} else
|
|
Ivan Mahonin |
d6ae44 |
if (blocks[i].top > window_height) {
|
|
Ivan Mahonin |
d6ae44 |
generate_block(&blocks[i], -10.0 - (double)rand()/(double)RAND_MAX*fabs(dy));
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
gboolean timeout(gpointer data) {
|
|
Ivan Mahonin |
d6ae44 |
double window_height = gtk_widget_get_allocated_height(window);
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
vy += gravity;
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
if (left_key) px -= speed;
|
|
Ivan Mahonin |
d6ae44 |
if (right_key) px += speed;
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
if (vy > 0.0) {
|
|
Ivan Mahonin |
d6ae44 |
gboolean found = FALSE;
|
|
Ivan Mahonin |
d6ae44 |
double top = py + vy;
|
|
Ivan Mahonin |
d6ae44 |
for(int i = 0; i < COUNT; ++i) {
|
|
Ivan Mahonin |
d6ae44 |
if ( px >= blocks[i].left
|
|
Ivan Mahonin |
d6ae44 |
&& px <= blocks[i].right
|
|
Ivan Mahonin |
d6ae44 |
&& blocks[i].top >= py
|
|
Ivan Mahonin |
d6ae44 |
&& blocks[i].top <= top )
|
|
Ivan Mahonin |
d6ae44 |
{
|
|
Ivan Mahonin |
d6ae44 |
found = TRUE;
|
|
Ivan Mahonin |
d6ae44 |
top = blocks[i].top;
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
if (found) {
|
|
Ivan Mahonin |
d6ae44 |
py = top;
|
|
Ivan Mahonin |
d6ae44 |
vy = -jump;
|
|
Ivan Mahonin |
d6ae44 |
} else {
|
|
Ivan Mahonin |
d6ae44 |
py += vy;
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
} else {
|
|
Ivan Mahonin |
d6ae44 |
py += vy;
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
scroll_blocks(window_height/2.0 - py);
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
gtk_widget_queue_draw(window);
|
|
Ivan Mahonin |
d6ae44 |
return TRUE;
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
gboolean key_press(GtkWidget *widget, GdkEventKey *event, gpointer data) {
|
|
Ivan Mahonin |
d6ae44 |
if (event->keyval == GDK_KEY_Left) left_key = TRUE;
|
|
Ivan Mahonin |
d6ae44 |
if (event->keyval == GDK_KEY_Right) right_key = TRUE;
|
|
Ivan Mahonin |
d6ae44 |
if (event->keyval == GDK_KEY_space) generate_blocks();
|
|
Ivan Mahonin |
d6ae44 |
return TRUE;
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
gboolean key_release(GtkWidget *widget, GdkEventKey *event, gpointer data) {
|
|
Ivan Mahonin |
d6ae44 |
if (event->keyval == GDK_KEY_Left) left_key = FALSE;
|
|
Ivan Mahonin |
d6ae44 |
if (event->keyval == GDK_KEY_Right) right_key = FALSE;
|
|
Ivan Mahonin |
d6ae44 |
return TRUE;
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
gboolean draw(GtkWidget *widget, cairo_t *cr, gpointer data) {
|
|
Ivan Mahonin |
d6ae44 |
cairo_set_source_rgba(cr, 0.9, 0.9, 0.9, 1);
|
|
Ivan Mahonin |
d6ae44 |
cairo_paint(cr);
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
cairo_set_source_rgba(cr, 0, 0, 0, 1);
|
|
Ivan Mahonin |
d6ae44 |
for(int i = 0; i < COUNT; ++i) {
|
|
Ivan Mahonin |
d6ae44 |
cairo_rectangle(
|
|
Ivan Mahonin |
d6ae44 |
cr,
|
|
Ivan Mahonin |
d6ae44 |
blocks[i].left,
|
|
Ivan Mahonin |
d6ae44 |
blocks[i].top,
|
|
Ivan Mahonin |
d6ae44 |
blocks[i].right - blocks[i].left,
|
|
Ivan Mahonin |
d6ae44 |
blocks[i].bottom - blocks[i].top );
|
|
Ivan Mahonin |
d6ae44 |
cairo_fill(cr);
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
cairo_set_source_surface(
|
|
Ivan Mahonin |
d6ae44 |
cr,
|
|
Ivan Mahonin |
d6ae44 |
surface,
|
|
Ivan Mahonin |
d6ae44 |
px - cairo_image_surface_get_width(surface)/2.0,
|
|
Ivan Mahonin |
d6ae44 |
py - cairo_image_surface_get_height(surface) );
|
|
Ivan Mahonin |
d6ae44 |
cairo_paint(cr);
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
cairo_set_source_rgba(cr, 0, 0, 0, 1);
|
|
Ivan Mahonin |
d6ae44 |
cairo_set_font_size(cr, 15);
|
|
Ivan Mahonin |
d6ae44 |
char text[1024];
|
|
Ivan Mahonin |
d6ae44 |
sprintf(text, "Score: %.0f", score);
|
|
Ivan Mahonin |
d6ae44 |
cairo_move_to(cr, 10, 30);
|
|
Ivan Mahonin |
d6ae44 |
cairo_show_text(cr, text);
|
|
Ivan Mahonin |
d6ae44 |
sprintf(text, "Max score: %.0f", max_score);
|
|
Ivan Mahonin |
d6ae44 |
cairo_move_to(cr, 10, 50);
|
|
Ivan Mahonin |
d6ae44 |
cairo_show_text(cr, text);
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
return TRUE;
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
void activate(GtkApplication* app, gpointer data) {
|
|
Ivan Mahonin |
d6ae44 |
window = gtk_application_window_new(app);
|
|
Ivan Mahonin |
d6ae44 |
g_signal_connect(window, "draw", G_CALLBACK(draw), NULL);
|
|
Ivan Mahonin |
d6ae44 |
g_signal_connect(window, "key-press-event", G_CALLBACK(key_press), NULL);
|
|
Ivan Mahonin |
d6ae44 |
g_signal_connect(window, "key-release-event", G_CALLBACK(key_release), NULL);
|
|
Ivan Mahonin |
d6ae44 |
gtk_widget_add_events(window, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
|
|
Ivan Mahonin |
d6ae44 |
gtk_window_set_default_size(GTK_WINDOW(window), 800, 500);
|
|
Ivan Mahonin |
d6ae44 |
gtk_widget_show_all(window);
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
generate_blocks();
|
|
Ivan Mahonin |
d6ae44 |
px = (blocks[0].left + blocks[0].right) / 2;
|
|
Ivan Mahonin |
d6ae44 |
py = blocks[0].top;
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
g_timeout_add(50, timeout, NULL);
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
int main(int argc, char **argv) {
|
|
Ivan Mahonin |
d6ae44 |
surface = cairo_image_surface_create_from_png("ghost.png");
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
GtkApplication *application = gtk_application_new(NULL, 0);
|
|
Ivan Mahonin |
d6ae44 |
g_signal_connect(application, "activate", G_CALLBACK(activate), NULL);
|
|
Ivan Mahonin |
d6ae44 |
int status = g_application_run(G_APPLICATION(application), argc, argv);
|
|
Ivan Mahonin |
d6ae44 |
g_object_unref(application);
|
|
Ivan Mahonin |
d6ae44 |
|
|
Ivan Mahonin |
d6ae44 |
cairo_surface_destroy(surface);
|
|
Ivan Mahonin |
d6ae44 |
return status;
|
|
Ivan Mahonin |
d6ae44 |
}
|
|
Ivan Mahonin |
d6ae44 |
|