While doing a map editor for the RPG we're making, we've found that it would be very convenient to be able to give the packfiles we use a name during the editing, and not having to go back to the code to do it, could anyone point out how? Here's an example of the function we're using:
1 | void save_map() |
2 | { |
3 | PACKFILE *pfile; |
4 | |
5 | pfile=pack_fopen("mapaprueba.map", "wp"); |
6 | for (m=0; m<1; m++) |
7 | { |
8 | for (k=0; k<2; k++) |
9 | { |
10 | for (l=0; l<2; l++) |
11 | { |
12 | for (i=0; i<32; i++) |
13 | { |
14 | for (j=0; j<24; j++) |
15 | { |
16 | pack_iputl(mapa.grid<i>[j].tile[k][l].capas[m], pfile); |
17 | } } } } } |
18 | pack_fclose(pfile); |
19 | } |
What we would like to do is to somehow put the name of the map form the editor not the compiler. We'd really appreciate it if anyone points us in the right direction . TXS!!
Cheers.
void save_map(char *filename) { PACKFILE *pfile; pfile=pack_fopen(filename, "wp"); [...] } save_map("mapaprueba.map");
?
void save_map(char *filename) { PACKFILE *pfile; pfile=pack_fopen(filename, "wp"); [...] } save_map("mapaprueba.map");
But that doesn't even compile...
Txs people, you are right dint think of that... not to used to think in C... anyone could point me out to some functions the allegro has for managing user input (its for the same thing, now that i can change the name the file has, i want th user to be able to do it by himself)
Txs a lot... I'm relay sorry to have to come back to ask over and over again
Cheers!
there are none beside the allegro GUI stuff but here some code from Chris he thought up a way to do it.
it was in the code gallery.
Author: Chris Barry
Version:
edit: the file seems to have lostest it host i think i down loaded it befor ill find it and post it.;D
http://www.allegro.cc/resource/code/text-input.php
edit:
if your looking for more examples of stuff check out my game in the Projects RPG area.
it is very up-to date. don't be to shy to wright a review . good luck;;D
TXS everyone! Problem solved
404
File not found.
witch file is that
Then let's burn it for crimes against the church, Yoda!
Or you can use a save file dialog...
piccolo: Try clicking that link you posted.
ok i think this is all the code from the link
1 | // edittext.cpp |
2 | #include <allegro.h> |
3 | #include <string> |
4 | using namespace std; |
5 | |
6 | #define WHITE makecol(255, 255, 255) |
7 | |
8 | int main() |
9 | { |
10 | // typical Allegro initialization |
11 | allegro_init(); |
12 | install_keyboard(); |
13 | set_gfx_mode(GFX_AUTODETECT, 320, 240, 0, 0); |
14 | |
15 | // all variables are here |
16 | BITMAP* buffer = create_bitmap(320, 240); // initialize the double buffer |
17 | string edittext; // an empty string for editting |
18 | string::iterator iter = edittext.begin(); // string iterator |
19 | int caret = 0; // tracks the text caret |
20 | bool insert = true; // true of should text be inserted |
21 | |
22 | // the game loop |
23 | do |
24 | { |
25 | while(keypressed()) |
26 | { |
27 | int newkey = readkey(); |
28 | char ASCII = newkey & 0xff; |
29 | char scancode = newkey >> 8; |
30 | |
31 | // a character key was pressed; add it to the string |
32 | if(ASCII >= 32 && ASCII <= 126) |
33 | { |
34 | // add the new char, inserting or replacing as need be |
35 | if(insert || iter == edittext.end()) |
36 | iter = edittext.insert(iter, ASCII); |
37 | else |
38 | edittext.replace(caret, 1, 1, ASCII); |
39 | |
40 | // increment both the caret and the iterator |
41 | caret++; |
42 | iter++; |
43 | } |
44 | // some other, "special" key was pressed; handle it here |
45 | else |
46 | switch(scancode) |
47 | { |
48 | case KEY_DEL: |
49 | if(iter != edittext.end()) iter = edittext.erase(iter); |
50 | break; |
51 | |
52 | case KEY_BACKSPACE: |
53 | if(iter != edittext.begin()) |
54 | { |
55 | caret--; |
56 | iter--; |
57 | iter = edittext.erase(iter); |
58 | } |
59 | break; |
60 | |
61 | case KEY_RIGHT: |
62 | if(iter != edittext.end()) caret++, iter++; |
63 | break; |
64 | |
65 | case KEY_LEFT: |
66 | if(iter != edittext.begin()) caret--, iter--; |
67 | break; |
68 | |
69 | case KEY_INSERT: |
70 | if(insert) insert = 0; else insert = 1; |
71 | break; |
72 | |
73 | default: |
74 | |
75 | break; |
76 | } |
77 | } |
78 | |
79 | // clear screen |
80 | clear(buffer); |
81 | |
82 | // output the string to the screen |
83 | textout(buffer, font, edittext.c_str(), 0, 10, WHITE); |
84 | |
85 | // output some stats using Allegro's printf functions |
86 | textprintf(buffer, font, 0, 20, WHITE, "length: %d", edittext.length()); |
87 | textprintf(buffer, font, 0, 30, WHITE, "capacity: %d", edittext.capacity()); |
88 | textprintf(buffer, font, 0, 40, WHITE, "empty?: %d", edittext.empty()); |
89 | if(insert) |
90 | textout(buffer, font, "Inserting", 0, 50, WHITE); |
91 | else |
92 | textout(buffer, font, "Replacing", 0, 50, WHITE); |
93 | |
94 | // draw the caret |
95 | vline(buffer, caret * 8, 8, 18, WHITE); |
96 | |
97 | // blit to screen |
98 | blit(buffer, screen, 0, 0, 0, 0, 320, 240); |
99 | |
100 | }while(!key[KEY_ESC]); // end of game loop |
101 | |
102 | // clean up |
103 | destroy_bitmap(buffer); |
104 | set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); |
105 | |
106 | return 0; |
107 | } |
108 | END_OF_MAIN() |
if(insert) insert = 0; else insert = 1;
Imo this is much cleaner
insert = !insert;
What about home and end? Personally I think insert is more of an annoance then a feature, and you support it but not home and end? shame on you.
Anyway, you also forgot about two important things. 1) The box scroll! The text inside an input widget needs to scroll to the left and right so that the user sees the correct data inside the box. And 2) clicking to move the caret. There doesnt seem to be a way to click somewhere to get the caret to move there.
Anyway, heres some code ripped out of my Input widget. Its a bit dependent on internal frameworks and such, but it hopefully conveys the idea.
1 | Input::Action Input::onIdle() |
2 | { |
3 | string &value = attributes["value"]; |
4 | |
5 | if(hasFocus && keypressed()) { |
6 | |
7 | int val = readkey(); |
8 | |
9 | if((val >> 8) == KEY_ENTER && attributes.count("enterAction")) { |
10 | |
11 | GuiScreen::active->generateAction(attributes["enterAction"], this); |
12 | } |
13 | else if((val >> 8) == KEY_BACKSPACE) { |
14 | |
15 | if(cursorPos != 0 && !value.empty()) { |
16 | |
17 | value.erase(cursorPos - 1, 1); |
18 | |
19 | setCursorPos(cursorPos - 1); |
20 | boundsCheckScroll(); |
21 | } |
22 | } |
23 | else if((val >> 8) == KEY_DEL) { |
24 | |
25 | if(cursorPos < (signed)value.size() && !value.empty()) { |
26 | |
27 | value.erase(cursorPos, 1); |
28 | |
29 | setCursorPos(cursorPos); |
30 | boundsCheckScroll(); |
31 | } |
32 | } |
33 | else if((val >> 8) == KEY_LEFT) { |
34 | |
35 | setCursorPos(cursorPos - 1); |
36 | } |
37 | else if((val >> 8) == KEY_RIGHT) { |
38 | |
39 | setCursorPos(cursorPos + 1); |
40 | } |
41 | else if((val >> 8) == KEY_HOME) { |
42 | |
43 | setCursorPos(0); |
44 | } |
45 | else if((val >> 8) == KEY_END) { |
46 | |
47 | setCursorPos(value.size()); |
48 | } |
49 | else if(val & 0xff) { |
50 | |
51 | if(!attributes.count("restrictTo") || attributes["restrictTo"].find((char)(val & 0xff)) != string::npos) { |
52 | |
53 | value.insert(cursorPos, 1, val & 0xff); |
54 | setCursorPos(cursorPos + 1); |
55 | |
56 | if(attributes.count("checkOnType")) { |
57 | |
58 | Widget *widget = GuiScreen::active->findByKey("name", attributes["checkOnType"]); |
59 | |
60 | if(widget) |
61 | widget->attributes["checked"] = "1"; |
62 | } |
63 | |
64 | if(attributes.count("uncheckOnType")) { |
65 | |
66 | Widget *widget = GuiScreen::active->findByKey("name", attributes["uncheckOnType"]); |
67 | |
68 | if(widget) |
69 | widget->attributes["checked"] = "0"; |
70 | } |
71 | } |
72 | } |
73 | |
74 | if(value.empty()) { |
75 | |
76 | if(attributes.count("checkOnEmpty")) { |
77 | |
78 | Widget *widget = GuiScreen::active->findByKey("name", attributes["checkOnEmpty"]); |
79 | |
80 | if(widget) |
81 | widget->attributes["checked"] = "1"; |
82 | } |
83 | |
84 | if(attributes.count("uncheckOnEmpty")) { |
85 | |
86 | Widget *widget = GuiScreen::active->findByKey("name", attributes["uncheckOnEmpty"]); |
87 | |
88 | if(widget) |
89 | widget->attributes["checked"] = "0"; |
90 | } |
91 | } |
92 | |
93 | if(attributes.count("syncValueWith")) |
94 | syncValue(); |
95 | } |
96 | |
97 | return OK; |
98 | } |
99 | |
100 | void Input::load() |
101 | { |
102 | if(attributes.count("syncValueWith")) |
103 | syncValue(); |
104 | |
105 | setCursorPos(attributes["value"].size()); |
106 | } |
107 | |
108 | void Input::syncValue() |
109 | { |
110 | string &value = attributes["value"]; |
111 | |
112 | Widget *widget = GuiScreen::active->findByKey("name", attributes["syncValueWith"]); |
113 | |
114 | if(widget) |
115 | if(attributes.count("isConfirm")) |
116 | widget->attributes["confirm"] = value; |
117 | else |
118 | widget->attributes["value"] = value; |
119 | } |
120 | |
121 | int Input::visibleChars() |
122 | { |
123 | string &value = attributes["value"]; |
124 | |
125 | int w = this->w - 32; |
126 | |
127 | for(unsigned int i = scrollPos; i < value.size(); i++) { |
128 | |
129 | w -= getWidth(value.at(i)); |
130 | |
131 | if(w <= 0) |
132 | return i - scrollPos; |
133 | } |
134 | |
135 | return value.size() - scrollPos; |
136 | } |
137 | |
138 | int Input::getWidth(string str) |
139 | { |
140 | FontRenderer &font = Print::getFontRenderer(); |
141 | |
142 | if(attributes["special"] == "password") |
143 | str = string(str.size(), '*'); |
144 | |
145 | return font.stringWidth(str); |
146 | } |
147 | |
148 | int Input::getWidth(char c) |
149 | { |
150 | FontRenderer &font = Print::getFontRenderer(); |
151 | |
152 | if(attributes["special"] == "password") |
153 | return font.width('*'); |
154 | else |
155 | return font.width(c); |
156 | } |
157 | |
158 | int Input::getCursorPixel() |
159 | { |
160 | string &value = attributes["value"]; |
161 | |
162 | int ret = 0; |
163 | |
164 | for(int i = scrollPos; i < cursorPos; i++) |
165 | ret += getWidth(value.at(i)); |
166 | |
167 | return ret; |
168 | } |
169 | |
170 | void Input::setCursorPixel(int x) |
171 | { |
172 | string &value = attributes["value"]; |
173 | |
174 | int newPos, tmp; |
175 | string::iterator itr = value.begin(); |
176 | |
177 | //x -= 16; |
178 | |
179 | for(newPos = 0; newPos < scrollPos && itr != value.end(); newPos++) |
180 | ++itr; |
181 | |
182 | for(; itr != value.end(); ++itr, ++newPos) { |
183 | |
184 | tmp = getWidth(*itr); |
185 | |
186 | if(x <= tmp / 2) |
187 | break; |
188 | |
189 | x -= tmp; |
190 | } |
191 | |
192 | setCursorPos(newPos); |
193 | } |
194 | |
195 | void Input::setCursorPos(int newPos) |
196 | { |
197 | string &value = attributes["value"]; |
198 | |
199 | if(newPos > (signed)value.size()) |
200 | newPos = value.size(); |
201 | |
202 | if(newPos < 0) |
203 | newPos = 0; |
204 | |
205 | cursorPos = newPos; |
206 | |
207 | boundsCheckScroll(); |
208 | } |
209 | |
210 | void Input::boundsCheckScroll() |
211 | { |
212 | string &value = attributes["value"]; |
213 | |
214 | if(scrollPos >= (signed)value.size()) |
215 | scrollPos = value.size() - 1; |
216 | if(scrollPos < 0) |
217 | scrollPos = 0; |
218 | |
219 | if(cursorPos < scrollPos) |
220 | scrollPos = cursorPos; |
221 | else while(cursorPos > scrollPos && getWidth(value.substr(scrollPos, cursorPos - scrollPos)) > w - 32) |
222 | scrollPos++; |
223 | } |
It also supports variable width fonts, which is why there are setCursorPos and getCursorPos functions.