|
Mouse Click Inside Timer Function |
Scooter
Member #16,799
January 2018
|
Hi all: MOUSE DOWN inside a Timer function. The code below works as far as the Timer, but allegro5 does NOT recognize when I click the mouse button. 1 if(ev.type == ALLEGRO_EVENT_TIMER && play == true)
2 {
3 if(ev.timer.source == game_timer)
4 {
5 if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
6 {
7 if(ev.mouse.button == 1)
8 {
9 pos_x = ev.mouse.x;
10 pos_y = ev.mouse.y;
11 angle = atan2(pos_y - ball_y, pos_x - ball_x);
12
13 for(i=0; i < 30; i++)
14 {
15 ball_x += cos(angle) * speed;
16 ball_y += sin(angle) * speed;
17 al_clear_to_color(al_map_rgb(20, 20, 20));
18 al_draw_filled_circle(ball_x, ball_y, 15, al_map_rgb(255, 0, 0));
19 al_flip_display();
20 update();
21 }
22 }
23 }
24 }
25code
Sorry code got kind of chopped off, but you can see the code. If this is NOT legal, how could it be written to work. Thanks for your time! |
DanielH
Member #934
January 2001
|
The EVENT object is a union of specialized events. In a timer event, the mouse event data is invalid. You need to get mouse data elsewhere. Personally I keep variables that get updates during mouse events. |
Scooter
Member #16,799
January 2018
|
Hi Daniel: Thank you for the info! I was afraid I had hit another bump in the road! I will have to try something else! Thanks again! |
Edgar Reynaldo
Major Reynaldo
May 2007
|
I think what you're looking for is something slightly different than what you tried. Your condition is impossible because if the event type is a TIMER event, then it can't be a MOUSE_DOWN event. 1//vars
2bool mb1 = false;
3
4if (ev.type == ALLEGRO_EVENT_MOUSE_DOWN) {
5 if (ev.mouse.button == 1) {mb1 = true;}
6} else if (ev.type == ALLEGRO_EVENT_MOUSE_UP) {
7 if (ev.mouse.button == 1) {mb1 = false;}
8}
9
10if (ev.type == ALLEGRO_EVENT_TIMER) {
11 if (ev.timer.source == logic_timer) {
12 if (mb1) {
13 /// Check if the mouse is held down during our logic timer
14 }
15 }
16}
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Scooter
Member #16,799
January 2018
|
Thanks Edgar: understanding how the mouse click is connected to the timer function. I will work on the info you posted and maybe I can see how it is connected. Thanks for the information! |
Edgar Reynaldo
Major Reynaldo
May 2007
|
In allegro 5, we no longer use callbacks with timer functions. You process the event and then handle it at your leisure. I am in effect replicating the ALLEGRO_MOUSE_STATE by using the mouse button up and down events to get the pressed state of the button. Then inside our reaction to the timer event, we process our mouse state so it only happens when the timer has a tick on it. This makes the rate steady with your timer.
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Scooter
Member #16,799
January 2018
|
Hi Edgar: That was the answer I was looking for. Thanks again. Have a great day |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Scooter said:
for(i=0; i < 30; i++) { ball_x += cos(angle) * speed; ball_y += sin(angle) * speed; al_clear_to_color(al_map_rgb(20, 20, 20)); al_draw_filled_circle(ball_x, ball_y, 15, al_map_rgb(255, 0, 0)); al_flip_display(); update(); }
Hey Scooter, just checking, does this code do what you want it to? Typically we only flip the display when we draw everything else on a timer event. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Scooter
Member #16,799
January 2018
|
Hi Edgar: |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Most likely you only need one timer and two variables for ticks that increment on different rates. As for collision detection, keep it simple as you can. A slot in a disc can be represented by a line segment on the radii of the disc. Then you test if the ball is at a certain angle to the center of the disc and see if it is close enough to be inside. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Scooter
Member #16,799
January 2018
|
Edgar: Thanks |
DanielH
Member #934
January 2001
|
The event variable gives you the timer that triggered the event. Use that to determine which update is needed. That being said, you don't need a timer for each object. You really just need one timer and update all objects when triggered. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
An example of what DanielH and I are saying : 1
2double FPS = 60;
3double SPF = 1.0/FPS;
4ALLEGRO_TIMER* mtimer = al_create_timer(SPF);/// Or as fast as you need for more precision
5
6/// Vary the tick rate here for the disc and the ball
7double bticks = 0.0;
8double dticks = 0.0;
9/// Next we have tick rates for the individual counters
10const double BTICKRATE = 0.5;/// Tick half as fast as master timer
11const double DTICKRATE = 1.0;/// Tick as fast as the master timer
12
13if (ev.type == ALLEGRO_EVENT_TIMER && ev.timer.source == mtimer) {
14 /// Our master timer ticked, add partial or whole ticks to the counters
15 bticks += BTICKRATE*SPF;
16 dticks += DTICKRATE*SPF;
17}
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Scooter
Member #16,799
January 2018
|
Hi Daniel and Edgar: 1
2 this of course using two timers
3 code works perfect by themselves, NOT TOGETHER
4 problem is how these should interact with only one timer
5 operating at two different speeds
6
7 // this rotates the disc
8 if(ev.type == ALLEGRO_EVENT_TIMER)
9 {
10 if(ev.timer.source == disc_timer && start == true)
11 {
12 double angleX = (angle * PI) / 180.0; //convert angle to radians
13 al_clear_to_color(al_map_rgb(20, 20, 20));
14 al_draw_scaled_rotated_bitmap(image, 40, 40, 637, 170, 1, 1, -angleX, 0);
15 al_draw_bitmap(image2, 500, 727, 0);
16 al_draw_bitmap(image3, 383, 20, 0);
17 al_draw_bitmap(image4, 582, 495, 0);
18 al_flip_display();
19 update_angle(angle);
20 }
21 }
22
23 // this shoots the ball
24 if (ev.type == ALLEGRO_EVENT_TIMER)
25 {
26 if(al_key_down(&keyState, ALLEGRO_KEY_SPACE))
27 {
28 ball_x = 638;
29 ball_y = 524;
30
31 for(i = 0; i < 45; i++)
32 {
33 al_clear_to_color(al_map_rgb(0,0,0));
34 al_draw_bitmap(image2, 500, 727, 0);
35 al_draw_bitmap(image3, 383, 20, 0);
36 al_draw_bitmap(image4, 582, 495, 0);
37 al_draw_filled_circle(ball_x, ball_y, ball_dia, al_map_rgb(255, 0, 0));
38 al_flip_display();
39 update(10);
40 }
41 }
42 }
43
44
45 // these are for the updates
46 double update_angle() // update rotating disc
47 {
48 angle += 2.0;
49 if(angle >= 360) angle = 2.0;
50 }
51
52 int update(int value) // update shooting the ball
53 {
54 ball_y -= value;
55 }
|
DanielH
Member #934
January 2001
|
Just a suggestion, but input, logic and drawing should ALL be separated. 1. process input What are the speeds of your timers, can't you adjust to use one? Or adjust ball velocity to match the speed of one timer. 1int logic_counter = 0;
2
3void main_loop()
4{
5 while (true)
6 {
7 if (process_input() < 0) break;
8
9 while (logic_counter > 0)
10 {
11 process_input();
12 --logic_counter;
13 }
14
15 process_drawing();
16 }
17}
18
19int process_input()
20{
21/// get event info
22 if (ev.type == ALLEGRO_EVENT_TIMER) ++logic_counter;
23 if (ev.type == ALLEGRO_EVENT_KEYBOARD && ev.keycode == ALLEGRO_KEY_ESCAPE) return -1;
24
25 return 0;
26}
27
28
29void process_logic()
30{
31}
32
33void process_drawing()
34{
35}
|
torhu
Member #2,727
September 2002
|
You have to check which timer it is in both cases: // this shoots the ball if (ev.type == ALLEGRO_EVENT_TIMER && ev.timer.source == ball_timer)
|
Scooter
Member #16,799
January 2018
|
Edgar: 1
2#include <allegro5/allegro.h>
3#include <allegro5/allegro_primitives.h>
4#include <allegro5/allegro_image.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <allegro5/allegro_font.h>
8#include <allegro5/allegro_ttf.h>
9#include <math.h>
10#include <time.h>
11#include <stdbool.h>
12
13#define PI 3.1415927
14
15float screen_width = 1280;
16float screen_height = 750;
17
18float image_height;
19float image_width;
20
21int i;
22
23bool done = false;
24bool draw = false;
25bool start = false;
26
27//double FPS = 60.0;
28double SPF = 1.0/60.0;
29double bticks = 0.0;
30double dticks = 0.0;
31const double BTICKRATE = 0.5;/// Tick half as fast as master timer
32const double DTICKRATE = 1.0;/// Tick as fast as the master timer
33
34float ball_x = 636;
35float ball_y = 588;
36int ball_dia = 6;
37
38float new_x, new_y;
39int pos_x, pos_y;
40double angle = 2.0;
41double angleX;
42
43int i;
44int speed;
45
46int update(int value);
47double update_angle();
48
49int main()
50 {
51 ALLEGRO_DISPLAY *display = NULL;
52 ALLEGRO_BITMAP *image = NULL;
53 ALLEGRO_BITMAP *image2 = NULL;
54 ALLEGRO_BITMAP *image3 = NULL;
55 ALLEGRO_BITMAP *image4 = NULL;
56 ALLEGRO_TIMER *timer;
57 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
58
59 if(!al_init())
60 {
61 fprintf(stderr,"Couldn't initialize allegro!\n");
62 return -1;
63 }
64
65 if(!al_install_mouse())
66 {
67 fprintf(stderr, "failed to initialize the mouse!\n");
68 return -1;
69 }
70
71 if(!al_init_primitives_addon())
72 {
73 fprintf(stderr,"Couldn't initialize primitives addon!\n");
74 return -1;
75 }
76
77 if(!al_install_mouse())
78 {
79 fprintf(stderr, "failed to initialize the mouse!\n");
80 return -1;
81 }
82
83 display = al_create_display(screen_width, screen_height);
84
85 if(!display)
86 {
87 fprintf(stderr,"Couldn't create allegro display!\n");
88 return -1;
89 }
90
91 if(!al_init_image_addon())
92 {
93 fprintf(stderr,"Couldn't display image!\n");
94 return -1;
95 }
96
97 al_install_keyboard();
98
99 al_init_font_addon();
100 al_init_ttf_addon();
101
102 timer = al_create_timer(1.0 / 60);
103
104 event_queue = al_create_event_queue();
105
106 al_register_event_source(event_queue, al_get_display_event_source(display));
107 al_register_event_source(event_queue, al_get_mouse_event_source());;
108 al_register_event_source(event_queue, al_get_timer_event_source(timer));
109 al_register_event_source(event_queue, al_get_keyboard_event_source());
110
111 image = al_load_bitmap("disc.png");
112 // al_draw_bitmap(image, 637, 170, 0);
113
114 image2 = al_load_bitmap("menu.png");
115 al_draw_bitmap(image2, 500, 727, 0);
116 image3 = al_load_bitmap("new_frame.png");
117 al_draw_bitmap(image3, 383, 20, 0);
118 image4 = al_load_bitmap("ship.png");
119 al_draw_bitmap(image4, 582, 495, 0);
120 // al_draw_line(637, 50, 637, 710, al_map_rgb(255, 0, 0), 1);
121
122 al_flip_display();
123
124 if(!image)
125 {
126 fprintf(stderr,"Couldn't display image!\n");
127 return -1;
128 }
129
130 ALLEGRO_KEYBOARD_STATE keyState;
131 al_start_timer(timer);
132 done = false;
133
134 while(!done)
135 {
136 ALLEGRO_EVENT ev;
137 al_wait_for_event(event_queue, &ev);
138 al_get_keyboard_state(&keyState);
139 if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
140 {
141 done = true;
142 }
143
144 if (ev.type == ALLEGRO_EVENT_TIMER && ev.timer.source == timer)
145 {
146 /// Our master timer ticked, add partial or whole ticks to the counters
147 bticks += BTICKRATE*SPF;
148 dticks += DTICKRATE*SPF;
149 }
150
151
152 if(ev.type == ALLEGRO_EVENT_TIMER && start == true)
153 {
154 if(ev.timer.source == timer)
155 {
156 float angleX = (angle * PI) / 180.0; //convert angle to radians
157 al_clear_to_color(al_map_rgb(20, 20, 20));
158 al_draw_rotated_bitmap(image, 40, 40, 637, 170, -angleX, 0);
159 al_draw_bitmap(image2, 500, 727, 0);
160 al_draw_bitmap(image3, 383, 20, 0);
161 al_draw_bitmap(image4, 582, 495, 0);
162 al_flip_display();
163 angle += 2.0;
164 if(angle >= 360) angle = 2.0;
165 }
166 }
167
168 if (ev.type == ALLEGRO_EVENT_TIMER && start == true)
169 {
170 if(al_key_down(&keyState, ALLEGRO_KEY_SPACE))
171 {
172 ball_x = 638;
173 ball_y = 524;
174
175 for(i = 0; i < 60; i++)
176 {
177 al_clear_to_color(al_map_rgb(0,0,0));
178 al_draw_bitmap(image2, 500, 727, 0);
179 al_draw_bitmap(image3, 383, 20, 0);
180 al_draw_bitmap(image4, 582, 495, 0);
181 al_draw_filled_circle(ball_x, ball_y, ball_dia, al_map_rgb(255, 0, 0));
182 al_flip_display();
183 update(10);
184 }
185 }
186 }
187
188 if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
189 {
190 if( ev.mouse.button == 1)
191 {
192 pos_x = ev.mouse.x;
193 pos_y = ev.mouse.y;
194
195 if ((pos_x > 727 && pos_x < 765) && (pos_y > 727 && pos_y < 750)) // EXIT
196 {
197 start = false;
198 draw = false;
199 done = true;
200 break;
201 }
202
203 if ((pos_x > 510 && pos_x < 565) && (pos_y > 727 && pos_y < 750)) // START
204 {
205 start = true;
206 draw = true;
207 }
208
209 }
210 }
211
212 }
213
214 al_destroy_display(display);
215 al_destroy_bitmap(image);
216 al_destroy_bitmap(image2);
217 al_destroy_bitmap(image3);
218 al_destroy_timer(timer);
219 al_destroy_event_queue(event_queue);
220
221 return 0;
222 }
223
224double update_angle() // update rotating disc
225 {
226 angle += 2.0;
227 if(angle >= 360) angle = 2.0;
228 }
229
230int update(int value) // update shooting the ball
231 {
232 ball_y -= value;
233 }
|
DanielH
Member #934
January 2001
|
Oh, where to start? You only have one timer now. You won't need to check if the timer source matches anymore. You can also consolidate it all under one allegro_event_timer if statement 1if (ev.type == ALLEGRO_EVENT_TIMER)
2{
3 /// Our master timer ticked, add partial or whole ticks to the counters
4 bticks += BTICKRATE*SPF;
5 dticks += DTICKRATE*SPF;
6
7 if(start == true)
8 {
9 float angleX = (angle * PI) / 180.0; //convert angle to radians
10 al_clear_to_color(al_map_rgb(20, 20, 20));
11 al_draw_rotated_bitmap(image, 40, 40, 637, 170, -angleX, 0);
12 al_draw_bitmap(image2, 500, 727, 0);
13 al_draw_bitmap(image3, 383, 20, 0);
14 al_draw_bitmap(image4, 582, 495, 0);
15 al_flip_display();
16 angle += 2.0;
17 if(angle >= 360) angle = 2.0;
18
19 if(al_key_down(&keyState, ALLEGRO_KEY_SPACE))
20 {
21 ball_x = 638;
22 ball_y = 524;
23
24 for(i = 0; i < 60; i++)
25 {
26 al_clear_to_color(al_map_rgb(0,0,0));
27 al_draw_bitmap(image2, 500, 727, 0);
28 al_draw_bitmap(image3, 383, 20, 0);
29 al_draw_bitmap(image4, 582, 495, 0);
30 al_draw_filled_circle(ball_x, ball_y, ball_dia, al_map_rgb(255, 0, 0));
31 al_flip_display();
32 update(10);
33 }
34 }
35 }
36}
37}
Why are you doing this 60 times? for(i = 0; i < 60; i++) { al_clear_to_color(al_map_rgb(0,0,0)); al_draw_bitmap(image2, 500, 727, 0); al_draw_bitmap(image3, 383, 20, 0); al_draw_bitmap(image4, 582, 495, 0); al_draw_filled_circle(ball_x, ball_y, ball_dia, al_map_rgb(255, 0, 0)); al_flip_display(); update(10); }
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
I think he wants a short animation of the ball going into the disc. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Scooter
Member #16,799
January 2018
|
Hi Daniel: Thanks guys!!!!!!!!! |
Edgar Reynaldo
Major Reynaldo
May 2007
|
You can do animation this way, but be aware it is blocking your program from getting input. You need to draw the disc in the same section of code you draw your ball. That's why it disappears. Track the state of the 'start' variable. bticks and dticks do no good if you don't use them. You need variables to track the accumulated time. Then check if one of the variables has ticked or not. What you should try to achieve is freeing your logic from drawing. Always draw the whole screen, based on what is visible. And use your logic to determine what is where and when. Hope this helps. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|