Blame c/gtk3/jumper/jumper.c

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