This example shows how to implement a simple user interface using the advanced mouse functions. At the same time it is also a good example of a simple yet aesthetic animation.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define SCRW 800 // Screen width
#define SCRH 600 // and height
#define SCRTITLE "Drawing with lines"
#define SCRBKGC MGS_CBLACK
#define RMAX ((SCRH / 2) - 10) // Max radius
#define RMIN (SCRH / 8) // Min radius
#define LMIN 5 // Min number of sides
#define LMAX 20 // Max number of sides
#define LINIT 9 // Initial number of sides
#define CCOLOR MGS_CBLUE // Some colors
#define CSCOLOR MGS_CGREY
#define PCOLOR MGS_CCYAN
#define RMARGEN 400 // Circumference click band
#define RWIDTH 100 // Conf squares data
#define RHEIGHT 80
#define RCTMAR 20
#define RCOLOR 0xE02020
#define LSHADOW 6 // Distance to the shadow of lines
#define CSHADOW 0x282828 // Its color
#define NUMSTARS 600 // Stars for the background
#define CHKSIZE 10 // Little check squares size
#define CHKX1 10 // and positions
#define CHKX2 (SCRW - 135)
#define CHKY1 30
#define CHKY2 (SCRH - 30)
#define EF1LIMIT 20 // Count limit for the wave efect
#define EF2RISE 90 // Steps for the pulse to rise
#define EF2FALL 45 // and to fall
#define EF2EXTRA 0.05 // % of radius to rise
enum states {CONFIG, DRAW};
int main()
{
int i, j, dist, r2, mx, my, scr, dumb, nlados = LINIT;
double *puntos, ang, vang, step, radio;
int rectX[3], rectY[3];
char *texts[3] = {"Click to decrease side count", "Click to increase side count", "Click to show animation"};
int ef1front, ef1vertex, ef1count, ef1O, ef1D;
int ef1Orig[5], ef1Dest[5], ef1Colors[5] = {0x55FF00, 0xAAFF00, MGS_CCYAN, 0xAAFF00, 0x55FF00};
int ef2idx;
double ef2Rad[EF2RISE + EF2FALL];
unsigned char msgRad, msgRadMin, msgRadMax, msgClick[3], modif, press, shadow, anti, efcol1, efcol2, efcol2Sync;
enum states st = CONFIG;
mgsShowError(scr,
"Error creating screen. Aborting program", MGS_EFWAIT);
exit(EXIT_FAILURE);
}
rectX[0] = RCTMAR;
rectY[0] = RCTMAR;
rectX[1] = SCRW - RCTMAR - RWIDTH;
rectY[1] = RCTMAR;
rectX[2] = RCTMAR;
rectY[2] = SCRH - RCTMAR - RHEIGHT;
radio = (RMAX + RMIN) >> 1;
modif = 0;
while(1) {
dumb += rand();
switch(st) {
case CONFIG:
msgRadMax = 0;
msgRadMin = 0;
for (i = 0; i < 3; msgClick[i++] = 0);
dist = (mx - (SCRW >> 1)) * (mx - (SCRW >> 1)) + (my - (SCRH >> 1)) * (my - (SCRH >> 1));
r2 = radio * radio;
msgRad = ((dist < r2 + RMARGEN) && (dist > r2 - RMARGEN)) ? 1 : 0;
if (!modif) {
if ((press & MGS_MNEW) && msgRad) {
msgRad = 0;
modif = 1;
}
}
else {
msgRad = 0;
if (press == MGS_MNO)
modif = 0;
else {
radio = sqrt(dist);
if (radio > RMAX) {
radio = RMAX;
msgRadMax = 1;
}
else if (radio < RMIN) {
radio = RMIN;
msgRadMin = 1;
}
}
}
if (press == MGS_MNO) {
if (
mgsLeftMouseClk(scr, rectX[0], rectY[0], rectX[0] + RWIDTH, rectY[0]+ RHEIGHT)) {
if (nlados > LMIN) nlados--;
}
else if (
mgsLeftMouseClk(scr, rectX[1], rectY[1], rectX[1] + RWIDTH, rectY[1]+ RHEIGHT)) {
if (nlados < LMAX) nlados++;
}
else if (
mgsLeftMouseClk(scr, rectX[2], rectY[2], rectX[2] + RWIDTH, rectY[2]+ RHEIGHT)) {
st = DRAW;
puntos = malloc (2 * nlados * sizeof(double));
if (puntos == NULL) {
puts("Memory failure");
exit(EXIT_SUCCESS);
}
ang = 0.0;
step = 2.0 * M_PI / nlados;
shadow = 0;
anti = 0;
efcol1 = 0;
ef1front = nlados - 4;
ef1vertex = 0;
ef1count = EF1LIMIT - 1;
efcol2 = 0;
efcol2Sync = 0;
ef2idx = 0;
ef2Rad[0] = radio;
for (i = 1; i < EF2RISE; i++)
ef2Rad[i] = ef2Rad[i - 1] + radio * EF2EXTRA / EF2RISE;
for (; i < EF2FALL + EF2RISE; i++)
ef2Rad[i] = ef2Rad[i - 1] - radio * EF2EXTRA / EF2FALL;
for (i = 0; i < NUMSTARS; i++)
mgsEllipse(scr, rand() % SCRW, rand() % SCRH, rand() % 3, rand() % 3,
mgsRGBColor(rand() % 255, rand() % 255, rand() % 255));
break;
}
else if (
mgsMouseOver(scr, rectX[0], rectY[0], rectX[0] + RWIDTH, rectY[0]+ RHEIGHT)) {
msgClick[0] = 1;
}
else if (
mgsMouseOver(scr, rectX[1], rectY[1], rectX[1] + RWIDTH, rectY[1]+ RHEIGHT)) {
msgClick[1] = 1;
}
else if (
mgsMouseOver(scr, rectX[2], rectY[2], rectX[2] + RWIDTH, rectY[2]+ RHEIGHT)) {
msgClick[2] = 1;
}
}
for (i = 0; i < 3; i++)
mgsRectangle(scr, rectX[i], rectY[i], rectX[i] + RWIDTH, rectY[i]+ RHEIGHT, RCOLOR);
if (msgRad)
mgsPuts(scr, mx + 2, my - 25,
"Click and drag to change radius");
else if (msgRadMax)
mgsPuts(scr, mx + 2, my - 25,
"It cannot be bigger");
else if (msgRadMin)
mgsPuts(scr, mx + 2, my - 25,
"It cannot be smaller");
else if (msgClick[0])
mgsPuts(scr, mx + 2, my - 25, texts[0]);
else if (msgClick[1])
mgsPuts(scr, mx - 290, my - 25, texts[1]);
else if (msgClick[2])
mgsPuts(scr, mx + 2, my - 25, texts[2]);
break;
case DRAW:
if (efcol2Sync) {
radio = ef2Rad[ef2idx];
ef2idx++;
if (ef2idx == EF2RISE + EF2FALL) {
efcol2Sync = efcol2;
ef2idx = 0;
}
}
else radio = ef2Rad[0];
vang = ang;
ang += anti ? -0.002 : 0.002;
for(i = 0; i < nlados; i++) {
vang += step;
puntos[2 * i] = radio * cos(vang) + (SCRW >> 1);
puntos[2 * i + 1] = radio * sin(vang) + (SCRH >> 1);
}
shadow = 1 - shadow;
else if (
mgsLeftMouseClk(scr, CHKX1, CHKY2, CHKX1 + CHKSIZE, CHKY2 + CHKSIZE))
efcol1 = 1 - efcol1;
else if (
mgsLeftMouseClk(scr, CHKX2, CHKY1, CHKX2 + CHKSIZE, CHKY1 + CHKSIZE)) {
efcol2 = 1 - efcol2;
if (efcol2 == 1) efcol2Sync = 1;
}
else if (
mgsLeftMouseClk(scr, CHKX2, CHKY2, CHKX2 + CHKSIZE, CHKY2 + CHKSIZE))
anti = 1 - anti;
if (efcol1) {
ef1O = ef1vertex;
ef1D = ef1front;
for (i = 0; i < 5; i++) {
ef1Orig[i] = ef1O;
ef1Dest[i] = (ef1O + 2 + ef1D) % nlados;
ef1D--;
if (ef1D < 0) {
ef1D = nlados - 4;
ef1O = (ef1O + 1) % nlados;
}
}
ef1count++;
if (ef1count == EF1LIMIT) {
ef1count = 0;
ef1front--;
if (ef1front < 0) {
ef1front = nlados - 4;
ef1vertex = (ef1vertex + 1) % nlados;
}
}
}
puts("GOOD BYE");
exit(EXIT_SUCCESS);
}
mgsPuts(scr, (SCRW >> 1) - 145, 10,
"PRESS S TO EXIT");
if (shadow) {
for (j = 0; j < nlados; j++)
mgsLine(scr, puntos[2 * j], puntos[2 * j + 1], puntos[2 * j] + LSHADOW, puntos[2 * j + 1] + LSHADOW, 2, CSHADOW);
for (j = 2; j < nlados - 1; j++)
mgsLine(scr, puntos[0] + LSHADOW, puntos[1] + LSHADOW, puntos[2 * j] + LSHADOW, puntos[2 * j + 1] + LSHADOW, 2, CSHADOW);
for(i = 1; i < nlados - 2; i++)
for (j = i + 2; j < nlados; j++)
mgsLine(scr, puntos[2 * i] + LSHADOW, puntos[2 * i + 1] + LSHADOW, puntos[2 * j] + LSHADOW, puntos[2 * j + 1] + LSHADOW, 2, CSHADOW);
}
for (j = 2; j < nlados - 1; j++)
mgsLine(scr, puntos[0], puntos[1], puntos[2 * j], puntos[2 * j + 1], 2, MGS_CGREEN);
for(i = 1; i < nlados - 2; i++)
for (j = i + 2; j < nlados; j++)
mgsLine(scr, puntos[2 * i], puntos[2 * i + 1], puntos[2 * j], puntos[2 * j + 1], 2, MGS_CGREEN);
mgsLine(scr, puntos[0], puntos[1], puntos[2 * nlados - 2], puntos[2 * nlados - 1], 1, MGS_CGREY);
for (j = 0; j < nlados - 1; j++)
mgsLine(scr, puntos[2 * j], puntos[2 * j + 1], puntos[2 * j + 2], puntos[2 * j + 3], 1, MGS_CGREY);
if (efcol1)
for (i = 0; i < 5; i++)
mgsLine(scr, puntos[2 * ef1Orig[i]], puntos[2 * ef1Orig[i] + 1], puntos[2 * ef1Dest[i]], puntos[2 * ef1Dest[i] + 1], 3, ef1Colors[i]);
for (j = 0; j < nlados; j++)
mgsEllipse(scr, puntos[2 * j], puntos[2 * j + 1], 4, 4, MGS_CRED);
mgsRectangle(scr, CHKX1, CHKY1, CHKX1 + CHKSIZE, CHKY1 + CHKSIZE, MGS_CCYAN);
mgsPuts(scr, CHKX1 + CHKSIZE + 10, CHKY1 - 7,
"Shadow");
mgsRectangle(scr, CHKX1, CHKY2, CHKX1 + CHKSIZE, CHKY2 + CHKSIZE, MGS_CCYAN);
mgsPuts(scr, CHKX1 + CHKSIZE + 10, CHKY2 - 7,
"Wave");
mgsRectangle(scr, CHKX2, CHKY1, CHKX2 + CHKSIZE, CHKY1 + CHKSIZE, MGS_CCYAN);
mgsPuts(scr, CHKX2 + CHKSIZE + 10, CHKY1 - 7,
"Pulse");
mgsRectangle(scr, CHKX2, CHKY2, CHKX2 + CHKSIZE, CHKY2 + CHKSIZE, MGS_CCYAN);
mgsPuts(scr, CHKX2 + CHKSIZE + 10, CHKY2 - 7,
"CClkWise");
if (shadow)
mgsEllipse(scr, CHKX1 + (CHKSIZE >> 1), CHKY1 + (CHKSIZE >> 1), CHKSIZE >> 1, CHKSIZE >> 1, MGS_CBLUE);
if (efcol1)
mgsEllipse(scr, CHKX1 + (CHKSIZE >> 1), CHKY2 + (CHKSIZE >> 1), CHKSIZE >> 1, CHKSIZE >> 1, MGS_CBLUE);
if (efcol2)
mgsEllipse(scr, CHKX2 + (CHKSIZE >> 1), CHKY1 + (CHKSIZE >> 1), CHKSIZE >> 1, CHKSIZE >> 1, MGS_CBLUE);
if (anti)
mgsEllipse(scr, CHKX2 + (CHKSIZE >> 1), CHKY2 + (CHKSIZE >> 1), CHKSIZE >> 1, CHKSIZE >> 1, MGS_CBLUE);
break;
}
}
}