/* * This file is part of 'Garden of coloured lights'. * * 'Garden of coloured lights' is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 'Garden of coloured lights' is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 'Garden of coloured lights'. If not, see . */ /* This file contains some maths and utility functions. The only ones used at present are: xpart/ypart - call them with angle x and distance d; they'll give you the x component and y component of a line in the angle x and the distance d angle_to_radians - I use a 1024-degree circle in a format called 'angle'. It lets me use lookup tables radians_to_angle without interpolation for simple trig, and minimises slow floating-point operations. angle_to_radians takes 'angle' values and turns them into radians; radians_to_angle etc. grand(n) - random number from 1 to n */ #include "config.h" #include "allegro.h" #include int turn_towards_angle (int angle, int tangle, int turning); int delta_turn_towards_angle (int angle, int tangle, int turning); float lcos (int angle); float lsin (int angle); float angle_to_radians (int angle); // I have no idea why, but the first few elements of cos_table always get corrupted // unless I put a big fat decoy array just above. A similar thing happens to the // palette arrays; allegro seems to have a problem with global arrays like these. float decoy_table[ANGLE_1]; // not used float cos_table[ANGLE_1]; float sin_table[ANGLE_1]; int xpart (int angle, int length); void init_trig (void) { int i; for (i = 0; i < ANGLE_1; i++) { cos_table[i] = cos (angle_to_radians (i)); // * ANGLE_1; sin_table[i] = sin (angle_to_radians (i)); // * ANGLE_1; } } int xpart (int angle, int length) { return (cos_table[angle & 1023] * length); } int ypart (int angle, int length) { return (sin_table[angle & 1023] * length); } float lcos (int angle) { return cos_table[angle & 1023]; } float lsin (int angle) { return sin_table[angle & 1023]; } float angle_to_radians (int angle) { return ((float) angle * PI * 2) / ANGLE_1; } int radians_to_angle (float angle) { if (angle < 0) angle += PI * 2; return (int) ((angle * ANGLE_1) / (PI * 2)); } fixed angle_to_fixed (int angle) { return itofix (angle / ANGLE_TO_FIXED); } int grand (int number) { if (number == 0) return 0; return ((rand () + (rand () << 16)) & 0x7fffffff) % number; } // returns the new angle int turn_towards_angle (int angle, int tangle, int turning) { if ((angle < tangle && tangle > angle + ANGLE_2) || (angle > tangle && tangle > angle - ANGLE_2)) { angle -= turning; if (angle < 0) angle += ANGLE_1; } else { angle += turning; if (angle > ANGLE_1) angle -= ANGLE_1; } return angle; } int turn_towards_xy (int x1, int y1, int x2, int y2, int angle, int turning) { int tangle = radians_to_angle (atan2 ((y2 - y1), (x2 - x1))) & 1023; /* if (tangle < 0) tangle += ANGLE_1; if (tangle > ANGLE_1) tangle -= ANGLE_1;*/ return turn_towards_angle (angle, tangle, turning); } // delta version just returns the change needed int delta_turn_towards_angle (int angle, int tangle, int turning) { // if ((angle < tangle && tangle > angle + ANGLE_2) if ((angle < tangle && tangle > angle + ANGLE_2) || (angle > tangle && tangle > angle - ANGLE_2)) { return turning * -1; } return turning; } int odd_even (int v) { if ((v | 1) == 1) return 1; return -1; } int delta_turn_towards_xy (int x1, int y1, int x2, int y2, int angle, int turning) { int tangle = radians_to_angle (atan2 ((y2 - y1), (x2 - x1))); if (tangle < 0) tangle += ANGLE_1; if (tangle > ANGLE_1) tangle -= ANGLE_1; return delta_turn_towards_angle (angle, tangle, turning); } // speed must be at least 4, and a factor of 1024 int pulsate (int speed, int amount, int county) { return xpart ((county * speed) & 1023, amount); } void error_message_out (const char *errm) { set_gfx_mode (GFX_TEXT, 0, 0, 0, 0); allegro_message ("%s", errm); exit (1); } int angle_difference (int a1, int a2) { int d1, d2; d1 = (a1 - a2 + ANGLE_1) % ANGLE_1; d2 = (a2 - a1 + ANGLE_1) % ANGLE_1; if (d1 < d2) return abs (d1); return abs (d2); } int pos_or_neg (int a) { if (grand (2) == 0) return a; return a * -1; }