![]() |
|
Text input. |
julian_boolean
Member #8,201
January 2007
|
Just wondering how everyone here deals with inputting text to the screen when your using graphics. I was trying to use gstream but it didn't seem to work very well.. Whenever I tried normal output the characters would just flash as if they weren't being buffered properly, then when I tried input, it would just be a black screen until I mashed a bunch of keys then my graphics would show. The characters always went over my mouse too no matter where I put the functions. Before gstream, I was looking at this: http://www.gamedev.net/reference/articles/article2130.asp It seemed to work pretty good, but I was just curious to see other ideas. |
Steve Terry
Member #1,989
March 2002
![]() |
I don't see any better way of handling text input other than using keypressed and the scancode/ascii code of the key pressed. The methods in the article are correct, if you are seeing text written over your cursor than that is a problem with how you are drawing things to the screen, draw text, then cursor, not the other way around. ___________________________________ |
julian_boolean
Member #8,201
January 2007
|
This guy's example is a little difficult for me to use. What I was trying to do with it was make it into a class, then use it in my game state classes like this: But I think the buffers are kinda conflicting and it's making the entire screen flash.. Even if I could get this to work I have no idea how I'd be able to choose and input text between "name" and "pass" with the mouse. |
Steve Terry
Member #1,989
March 2002
![]() |
Why would you create a new cText object each time you called logic that makes no sense. Just make a name and pass object in your constructor, then in your logic you can do an if(needs_login){ name.set_coords(100, 100); pass.set_coords(100, 150); } Your class should get input only when needed so I'm guessing set_coords would activate the input box or you could have a separate activate object. When the user clicks OK or whatever then you call name.get_text() and pass.get_text() which will return the buffers in those classes. ___________________________________ |
julian_boolean
Member #8,201
January 2007
|
Not really sure what you mean.. I had always created different instances of interface stuff if I wanted them to have different properties and do different things. I also managed to sorta get the text to stop flashing by putting it in with my draw function.. Which kinda annoys me because basically everything has to be in the draw function since its the only one thats blitting the buffer. If i try to blit the buffer in a different function then try to run it through the game loop it'll flicker again, ugh. |
Steve Terry
Member #1,989
March 2002
![]() |
What I am trying to say is that you should not have your text input functions stop the program and loop within, instead your functions should simply check for a keypress, if so then add or subtract a character and blit to the buffer, otherwise blit to the buffer the text and return. ___________________________________ |
julian_boolean
Member #8,201
January 2007
|
I think I know what your trying to get at now, goina try it out. Also, does anyone know how I could go about setting the capacity or coordinates of the text? Was looking at some Allegro functions for text, but I'm 95% sure this ISN'T how they're suppose to be used, because it's not working. void text::set_coords(int w, int h) { w = text_length(font, edittext.c_str()); h = text_height(font); } No idea how I make a function for capacity though. |
Steve Terry
Member #1,989
March 2002
![]() |
void text::set_coords(int &w, int &h) { w = text_length(font, edittext.c_str()); h = text_height(font); } Hmm that would be a get_coords function anyway and it's not coords but bounds. ___________________________________ |
Johan Halmén
Member #1,550
September 2001
|
Allegro GUI. d_edit_proc() to be more specific. You define the max length, placement of the text box, font colours etc. You have the backspace functionality, and delete, I think. And you can customise it. I made a customised thing that works with non-even coloured fonts. My Christmashack entry uses it for name input in the score list. Check there how it works. Does it echo here? Feels like a dejavu. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest. |
julian_boolean
Member #8,201
January 2007
|
Thanks for the help guys.
So! Inside the logic function for the new/converted button class called text, I had it set selection_status to SELECTED only if the textfield is pressed. For some reason, if I mash a bunch of keys THEN press the textfield, even though it's set to NOT_SELECTED (yet), all the keys that I pressed will appear. |
Jeff Bernard
Member #6,698
December 2005
![]() |
Sounds like you just need to clear the keyboard buffer. clear_keybuf() before readkey() and prossibly before keypressed() too. -- |
julian_boolean
Member #8,201
January 2007
|
I went with "else if(selection_status == NOT_SELECTED) { clear_keybuf(); }" and it seems to work sorta okay. Now I want it so, when you click the text field it sets the status to selected and keeps it that way until I say otherwise! Because right now I have to hold in the text field with my mouse to type, then when I let go it stops me from polling the text. For the record I'm using the code for the Loomsoft Button (which can be found here: http://www.loomsoft.net/util_lsbutton.shtml) Here's what I'm working with now: 1#include "text.h"
2#define WHITE makecol(255, 255, 255)
3#include <allegro.h>
4#include <string>
5using namespace std;
6
7string edittext;
8string::iterator iter = edittext.begin();
9int caret = 0;
10bool insert = true;
11
12void text::initialize(BITMAP *bitmap_on, BITMAP *bitmap_down, BITMAP *bitmap_off, int MOUSE_DETECTION_MODE, int MOUSE_CLICK_MODE)
13{
14 // Set the bitmap pointers
15 on_bitmap = bitmap_on;
16 down_bitmap = bitmap_down;
17 off_bitmap = bitmap_off;
18
19 // Set all the modes that were passed.
20 mouse_detection_mode = MOUSE_DETECTION_MODE;
21 mouse_status = BUTTON_NOT_ON_FOCUS;
22 mouse_click_mode = MOUSE_CLICK_MODE;
23
24 // Set the bounding box to be the dimensions of the off_bitmap.
25 bound_left = 0;
26 bound_top = 0;
27 bound_right = off_bitmap->w;
28 bound_bottom = off_bitmap->h;
29
30 // Set the x/y position to 0,0
31 x_position = 0;
32 y_position = 0;
33
34 // Set the masking color to the default "magic pink".
35 masking_color = makecol(255,0,255);
36
37 // Turn off the bounding box display feature
38 show_bbox = FALSE;
39
40 // Set the original frame to draw the button to off_bitmap
41 draw_frame = BUTTON_DRAW_FRAME_OFF;
42
43 // Set the button to an active state.
44 is_active = TRUE;
45
46 selection_status = BUTTON_NOT_SELECTED;
47}
48
49void text::set_bounds(int left_bound, int right_bound, int top_bound, int bottom_bound)
50{
51 if(mouse_detection_mode == BUTTON_BOUNDING_BOX)
52 {
53 bound_left = left_bound;
54 bound_right = right_bound;
55 bound_top = top_bound;
56 bound_bottom = bottom_bound;
57 }
58}
59
60void text::set_masking_color(int red, int blue, int green)
61{
62 if(red < 0)
63 red = 0;
64 else if(red > 255)
65 red = 255;
66
67 if(blue < 0)
68 blue = 0;
69 else if(blue > 255)
70 blue = 255;
71
72 if(green < 0)
73 green = 0;
74 else if(green > 255)
75 green = 255;
76
77 masking_color = makecol(red,blue,green);
78}
79
80//Sets if the drawing function should show the bounding box.
81void text::set_show_bounding_box(int value)
82{
83 show_bbox = value;
84}
85
86//Sets the active state for the button
87void text::set_active(int value)
88{
89 is_active = value;
90}
91
92void text::set_coords(int x, int y)
93{
94 x_position = x;
95 y_position = y;
96}
97
98void text::poll()
99{
100 if(mouse_x > bound_left+x_position && mouse_x < bound_right+x_position &&
101 mouse_y > bound_top+y_position && mouse_y < bound_bottom+y_position)
102 {
103 if(is_active && selection_status == BUTTON_SELECTED)
104 {
105 while(keypressed())
106 {
107 int newkey = readkey();
108 char ASCII = newkey & 0xff;
109 char scancode = newkey >> 8;
110
111 if(ASCII >= 32 && ASCII <= 126)
112 {
113 if(insert || iter == edittext.end())
114 iter = edittext.insert(iter, ASCII);
115
116 else
117 edittext.replace(caret, 1, 1, ASCII);
118 caret++;
119 iter++;
120 }
121
122 else
123 switch(scancode)
124 {
125 case KEY_DEL:
126 if(iter != edittext.end()) iter = edittext.erase(iter);
127 break;
128
129 case KEY_BACKSPACE:
130 if(iter != edittext.begin())
131 {
132 caret--;
133 iter--;
134 iter = edittext.erase(iter);
135 }break;
136
137 case KEY_RIGHT:
138 if(iter != edittext.end()) caret++, iter++;
139 break;
140
141 case KEY_LEFT:
142 if(iter != edittext.begin()) caret--, iter--;
143 break;
144
145 case KEY_INSERT:
146 insert = !insert;
147 break;
148
149 default:
150 break;
151 }
152 }
153 }
154
155 else if(selection_status == BUTTON_NOT_SELECTED) { clear_keybuf(); }
156
157 if(mouse_detection_mode == BUTTON_PIXEL_PERFECT)
158 {
159
160 if(getpixel(off_bitmap, mouse_x-x_position,mouse_y-y_position) != makecol(255,0,255))
161 {
162 if(mouse_b & 1)
163 {
164 selection_status = BUTTON_SELECTED;
165 draw_frame = BUTTON_DRAW_FRAME_DOWN;
166 }
167
168 else
169 {
170 selection_status = BUTTON_NOT_SELECTED;
171 draw_frame = BUTTON_DRAW_FRAME_ON;
172 }
173 }
174
175 else
176 {
177 selection_status = BUTTON_NOT_SELECTED;
178 draw_frame = BUTTON_DRAW_FRAME_OFF;
179
180 if(mouse_status != BUTTON_MOUSE_STATUS_DOWN)
181 {
182 mouse_status = BUTTON_NOT_ON_FOCUS;
183 }
184 }
185 }
186
187 else
188 {
189 if(mouse_b & 1)
190 {
191 draw_frame = BUTTON_DRAW_FRAME_DOWN;
192 }
193
194 else
195 {
196 draw_frame = BUTTON_DRAW_FRAME_ON;
197 }
198 }
199 }
200
201 else
202 {
203 draw_frame = BUTTON_DRAW_FRAME_OFF;
204
205 if(mouse_status != BUTTON_MOUSE_STATUS_DOWN)
206 {
207 mouse_status = BUTTON_NOT_ON_FOCUS;
208 }
209 }
210}
211
212int text::is_clicked()
213{
214 if(mouse_x > (bound_left+x_position) && mouse_x < (bound_right+x_position) &&
215 mouse_y > (bound_top+y_position) && mouse_y < (bound_bottom+y_position))
216 {
217 if(!(mouse_b & 1) && mouse_status == BUTTON_NOT_ON_FOCUS)
218 {
219 mouse_status = BUTTON_MOUSE_STATUS_UP;
220 }
221
222 if(mouse_b & 1 && mouse_click_mode == BUTTON_CLICK_MODE_CONSTANT)
223 {
224 return TRUE;
225 }
226
227 if(mouse_b & 1 && mouse_status != BUTTON_NOT_ON_FOCUS)
228 {
229 mouse_status = BUTTON_MOUSE_STATUS_DOWN;
230 }
231
232 else if(!(mouse_b & 1) && mouse_status == BUTTON_MOUSE_STATUS_DOWN)
233 {
234 mouse_status = BUTTON_MOUSE_STATUS_UP;
235
236 if(mouse_detection_mode == BUTTON_PIXEL_PERFECT)
237 {
238 if(getpixel(off_bitmap, mouse_x-x_position,mouse_y-y_position) != masking_color)
239 {
240 return TRUE;
241 }
242 }
243
244 else
245 {
246 return TRUE;
247 }
248 }
249 }
250
251 else if(!(mouse_b & 1))
252 {
253 mouse_status = BUTTON_NOT_ON_FOCUS;
254 }
255
256 return FALSE;
257}
258
259void text::draw_button(BITMAP *bitmap_buffer)
260{
261 if(draw_frame == BUTTON_DRAW_FRAME_DOWN)
262 {
263 if(down_bitmap != NULL)
264 {
265 acquire_screen();
266 draw_sprite(bitmap_buffer, down_bitmap, x_position, y_position);
267 release_screen();
268 vline(bitmap_buffer, caret* 8, 8, 18, WHITE);
269 }
270 }
271
272 else if(draw_frame == BUTTON_DRAW_FRAME_ON)
273 {
274 if(on_bitmap != NULL)
275 {
276 acquire_screen();
277 draw_sprite(bitmap_buffer, on_bitmap, x_position, y_position);
278 release_screen();
279 }
280 }
281
282 else if(draw_frame == BUTTON_DRAW_FRAME_OFF)
283 {
284 if(off_bitmap != NULL)
285 {
286 acquire_screen();
287 draw_sprite(bitmap_buffer, off_bitmap, x_position, y_position);
288 release_screen();
289 }
290 }
291
292 if(show_bbox)
293 {
294 rect(bitmap_buffer, bound_left+x_position, bound_top+y_position, bound_right+x_position, bound_bottom+y_position, makecol(255,0,0));
295 }
296
297 textout_ex(bitmap_buffer, font, edittext.c_str(), 0, 10, WHITE, -1);
298}
The string edittext stuff is put right under where I include allegro, the header, etc. I tried to put it somewhere else though it doesn't seem to like it when I do that. Which is sorta a problem because it's always storing the information in the same things. |
Steve Terry
Member #1,989
March 2002
![]() |
Nice globals You just need an active flag which simply is turned on when you move the mouse inside the bounds of the box and click. The only way it will not be active is if you loose focus to that edit box and into another. For that purpose you can have a text manager which stores a list of all edit boxes you have active at any given time so that when one gains focus you can deactivate the other one. You can even capture TAB as a key to toggle through your list of text objects. if(green < 0) green = 0; else if(green > 255) green = 255;
You can use MID for this purpose, MID(0, green, 255) ___________________________________ |
23yrold3yrold
Member #1,134
March 2001
![]() |
Quote: Just wondering how everyone here deals with inputting text to the screen when your using graphics. Probably past this point for you, but I wrote this a long time ago and maybe it's worth something ... -- |
julian_boolean
Member #8,201
January 2007
|
Steve: I thought that's what I already have. I was planning on having somewhere in my logic function for the game states that if a text field is clicked, it'll stop polling any of the other ones on the screen. Actually I did try to do that but the program would just crash.. It was something simple like: if(firstName.is_clicked()) { lastName.is_active(false) } 23yrold3yrold: I'm already using your code |
|