Overview
Comment: | Implement coordinate input. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
87a8bc6a74f1c8ca189ba21dc66c980a |
User & Date: | user on 2022-07-06 19:36:13 |
Other Links: | manifest | tags |
Context
2022-07-07
| ||
00:08 | Add the documentation about coordinate input binding into the bindings.doc file. check-in: ef46fdbc36 user: user tags: trunk | |
2022-07-06
| ||
19:36 | Implement coordinate input. check-in: 87a8bc6a74 user: user tags: trunk | |
05:20 | Several changes needed to allow coordinate input to be implemented in future (including the CLICK message and InputXY keyword). Also fixes a bug that was caused by changing MoveItem from Uint8 to Uint16. check-in: 156b0a7c35 user: user tags: trunk | |
Changes
Modified TODO from [2d7748f974] to [8666aa5000].
1 2 3 4 5 6 7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | - | * Sound effects * Compressed wave sounds (?) * Numeric sounds (?) * Game engine features * String data (partially implemented) * A ,PopUp command to use a popup with arguments starting from a mark * Returning a class from COLLIDE/COLLIDEBY to transform |
︙ |
Modified class.c from [1c13f6111e] to [23e8cf302b].
︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | + | char**stringpool; AnimationSlot anim_slot[8]; Uint8 keymask[256/8]; Uint16 array_size; Uint16*orders; Uint8 norders; Uint16 control_class; Uint8 has_xy_input; char*ll_head; DisplayColumn*ll_disp; Uint8 ll_ndisp; DataColumn*ll_data; Uint8 ll_ndata; Uint8 ll_naggregate; |
︙ | |||
2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 | 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 | + + + + + | } nxttok(); if(tokent!=TF_CLOSE) ParseError("Expected close parenthesis\n"); break; case OP_LEVELTABLE: level_table_definition(); break; case OP_INPUTXY: has_xy_input=1; nxttok(); if(tokent!=TF_CLOSE) ParseError("Expected close parenthesis\n"); break; default: ParseError("Invalid top level definition: %s\n",tokenstr); } } else { ParseError("Invalid top level definition\n"); } } |
︙ |
Modified class.doc from [09d41b7e9c] to [b650a160b5].
︙ | |||
285 286 287 288 289 290 291 292 293 294 295 296 297 298 | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | + + + + + | created, destroyed, or moved. It still receives broadcast messages normally, and can also be addressed specifically. (CollisionLayers <userflags...>) Define user flags as CollisionLayers bits; the first defined flag is bit0. Up to 8 flags can be defined in this way. (InputXY <options...>) Enables coordinate input. Currently there are no options, so the options must be left blank. See the documentation about the CLICK message for more details about coordinate input. (LevelTable <definitions...>) Define the level table. See the section about level table definition for details. Can only occur once. (Misc4 <userflags...>) Define user flags as Misc4 bits; the first defined flag is bit0. Up to 32 flags can be defined in this way. |
︙ | |||
1610 1611 1612 1613 1614 1615 1616 | 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 | - + + | successfully teleported. ,JumpTo ( obj x y -- bool ) ** As ,MoveTo but sends JUMPED message to that object after it has been successfully teleported. Key ( -- number ) |
︙ | |||
2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 | 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 | + + + + + + + + + | When scheduling deferred movement, if the moving object is blocked by another object, then the moving object sends this message to the object which is blocking it. From is the object attempting to move, Arg1 and Arg2 are that object's coordinates, and Arg3 is 1 for +Move or 0 for -Move. Of the return value, bit0 clears the Moving flag (causing the move to fail), and bit1 causes it to not send any more BLOCKED messages. CLICK Sent during coordinate input. It is first sent to the control object, and then if IgnoreKey is not executed, to each object at the clicked coordinates, from top to bottom; it will stop if any one returns nonzero or if the object that received this message has moved. Arg1 and Arg2 are the X and Y coordinates. Arg3 is zero for the control object, but is the return value of the CLICK message from the control object when this message is sent to other objects. COLLIDE Received when this object is trying to move into a location where there is a collision, so it can't move there. Of the return value, bit0 means to prevent the movement (even if the objects are moved out of the way or destroyed in order to make room), bit1 means to not send any COLLIDEBY messages, and bit2 means to pretend the move attempt was successful even if it isn't successful. Even if bit0 is set, that won't prevent sending |
︙ |
Modified default.heromeshrc from [62267c997a] to [f6f6f8f1b2].
︙ | |||
101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | + | ?.gameKey.alt.N: 'NUMLOCK ?.gameKey.alt.O: 'SCRLOCK ?.gameKey.alt.S: 'SHIFT ?.gameKey.alt.T: 'TAB ?.gameKey.alt.Z: 'CTRL ! Game key bindings ?.gameClick.left: select 'xy',$X,$Y where has_xy_input(); ?.gameKey.ctrl.D: select '^d',$key_xy; ?.gameKey.ctrl.E: ^E ?.gameKey.ctrl.I: select 'mi',:import_move_list; ?.gameKey.ctrl.K: with a(x,y,z) as (select count() filter (where solved),count() filter (where solved or solvable),count() from levels) select ':m',x||'/'||y||' ('||(100*x/y)||'%)'||iif(z-y,' + '||(z-y),'') from a; ?.gameKey.ctrl.L: ^L ?.gameKey.ctrl.R: select 'go',id from levels order by random() limit 1; ?.gameKey.ctrl.X: select 'mx',:export_move_list; |
︙ |
Modified exec.c from [a0ee5dcd19] to [4c5452cf58].
︙ | |||
3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 | 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 | + + - - + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | const char*execute_turn(int key) { Uint8 busy,clock,x,y; Uint32 m,n,turn,tc; Object*o; Value v; int i; tc=0; if(!key) { // This is part of initialization; if anything triggered, it must be executed now all_flushed=1; goto trig; } if(setjmp(my_env)) return my_error; if(quiz_text) { if(key>256 && !key_ignored) return 0; sqlite3_free(quiz_text); quiz_text=0; if(key_ignored) { if(quiz_obj.t) quiz_obj=NVALUE(0); else return 0; } else if(!quiz_obj.t) { move_number++; return 0; } } changed=0; key_ignored=0; all_flushed=0; lastimage_processing=0; vstackptr=0; |
︙ |
Modified fileformat.doc from [723b223c5e] to [5da3136896].
︙ | |||
149 150 151 152 153 154 155 156 157 158 159 160 161 162 | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | + + + + + | * Move list: One byte per turn, being the key codes. (Use of numbers 0-7 here is reserved for future use; they are not valid key codes.) (Free Hero Mesh currently ignores the comment and time stamp, although this might change in a future version of Free Hero Mesh.) Special key codes are: * 1 = Coordinate input; follow by two more bytes being the X coordinate and Y coordinate (both in the range 1 to 64). === xclass/*.DEP === A dependent picture (defined by transforming one or more other pictures); the part of the name before the dot is the picture name. It starts with the base picture name (which must be a IMG lump, and cannot |
︙ |
Modified function.c from [0fcaf673c8] to [793458f469].
︙ | |||
170 171 172 173 174 175 176 177 178 179 180 181 182 183 | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | + + + + | const unsigned char*u=sqlite3_value_blob(*argv); int n=sqlite3_value_bytes(*argv); long long h=sqlite3_value_int64(argv[1]); int m=hash_length(h); if(sqlite3_value_type(*argv)==SQLITE_NULL || !m) return; sqlite3_result_blob(cxt,hash_buffer(h,u,n),m,free); } static void fn_has_xy_input(sqlite3_context*cxt,int argc,sqlite3_value**argv) { sqlite3_result_int(cxt,has_xy_input); } static void fn_heromesh_escape(sqlite3_context*cxt,int argc,sqlite3_value**argv) { const unsigned char*u=sqlite3_value_blob(*argv); int un=sqlite3_value_bytes(*argv); char*e; int en=0; int i=0; |
︙ | |||
1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 | 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 | + | sqlite3_create_function(userdb,"BEST_MOVE_LIST",0,SQLITE_UTF8,0,fn_best_move_list,0,0); sqlite3_create_function(userdb,"BEST_SCORE",0,SQLITE_UTF8,0,fn_best_score,0,0); sqlite3_create_function(userdb,"BYTE",-1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_byte,0,0); sqlite3_create_function(userdb,"CL",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_cl,0,0); sqlite3_create_function(userdb,"CLASS_DATA",2,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_class_data,0,0); sqlite3_create_function(userdb,"CVALUE",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_cvalue,0,0); sqlite3_create_function(userdb,"HASH",2,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_hash,0,0); sqlite3_create_function(userdb,"HAS_XY_INPUT",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_has_xy_input,0,0); sqlite3_create_function(userdb,"HEROMESH_ESCAPE",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_heromesh_escape,0,0); sqlite3_create_function(userdb,"HEROMESH_TYPE",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_heromesh_type,0,0); sqlite3_create_function(userdb,"HEROMESH_UNESCAPE",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_heromesh_unescape,0,0); sqlite3_create_function(userdb,"INRECT",2,SQLITE_UTF8,0,fn_inrect,0,0); sqlite3_create_function(userdb,"LEVEL",0,SQLITE_UTF8,&level_ord,fn_level,0,0); sqlite3_create_function(userdb,"LEVEL_CACHEID",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,ptr0,fn_cacheid,0,0); sqlite3_create_function(userdb,"LEVEL_ID",0,SQLITE_UTF8,&level_id,fn_level,0,0); |
︙ |
Modified game.c from [d2afebc6be] to [05d4b7dc52].
︙ | |||
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | + + + + + + + + | int encode_move(FILE*fp,MoveItem v) { // Encodes a single move and writes the encoded move to the file. // Returns the number of bytes of the encoded move. if(v>=8 && v<256) { fputc(v,fp); return 1; } else if(v>=0x8000 && v<=0x8FFF) { fputc(KEY_XY,fp); fputc(((v>>6)&63)+1,fp); fputc((v&63)+1,fp); return 3; } else { fatal("Unencodable move (%u)\n",(int)v); } } int encode_move_list(FILE*fp) { // Encodes the current replay list into the file; returns the number of bytes. // Does not write a null terminator. int i; int c=0; for(i=0;i<replay_count;i++) c+=encode_move(fp,replay_list[i]); return c; } MoveItem decode_move(FILE*fp) { // Decodes a single move from the file, and returns the move. // Returns zero if there is no more moves. int v=fgetc(fp); if(v>=8 && v<256) { return v; } else if(v==KEY_XY) { v=0x8000|((fgetc(fp)-1)<<6); return v|(fgetc(fp)-1); } else if(v==EOF || !v) { return 0; } else { fatal("Undecodable move (%u)\n",v); } } |
︙ | |||
204 205 206 207 208 209 210 | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | - + + + + + + + + + + | snprintf(buf,8,"%5d",replay_pos); draw_text(8,52,buf,0xF0,0xF9); snprintf(buf,8,"%5d",replay_count); draw_text(8,screen->h-8,buf,0xF0,solution_replay?0xFA:0xFC); for(y=44,x=replay_pos-(screen->h-68)/32;;x++) { y+=16; if(y+24>screen->h) break; |
︙ | |||
1212 1213 1214 1215 1216 1217 1218 | 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 | - + | sqlite3_finalize(st); if(i==1) begin_level(mo&8?-sel-divmin:~sel); return i; } static int game_command(int prev,int cmd,int number,int argc,sqlite3_stmt*args,void*aux) { switch(cmd) { |
︙ | |||
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 | 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 | + + + + + + + | do_export_moves(sqlite3_column_text(args,1)); return 0; case 'rs': // Replay speed number+=replay_speed; if(number<1) number=1; else if(number>255) number=255; replay_speed=number; return prev; case 'xy': // Coordinate input if(argc<3 || !has_xy_input) break; argc=sqlite3_column_int(args,1); number=sqlite3_column_int(args,2); if(argc<1 || argc>pfwidth || number<1 || number>pfheight) return 0; number=(number-1)|((argc-1)<<6)|0x8000; goto play; default: return prev; } } static void do_autowin(void) { const char*name; |
︙ | |||
1422 1423 1424 1425 1426 1427 1428 | 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 | - + | static SDL_Event ev={SDL_USEREVENT}; SDL_PushEvent(&ev); } timerflag=1; return n; } |
︙ |
Modified heromesh.h from [38b9ed2d66] to [c5267bcf80].
︙ | |||
182 183 184 185 186 187 188 189 190 191 192 193 194 195 | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | + | extern char**stringpool; extern AnimationSlot anim_slot[8]; extern Uint8 keymask[256/8]; extern Uint16 array_size; extern Uint16*orders; extern Uint8 norders; extern Uint16 control_class; extern Uint8 has_xy_input; // zero if not, nonzero if it has typedef struct { // Flags: 1=fill-width, 2=multi-colours, 4=built-in-data Uint8 width,data,color,flag; Uint8 form[2]; Uint16 ptr; } DisplayColumn; |
︙ | |||
241 242 243 244 245 246 247 248 249 250 251 252 253 254 | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | + | #define ANI_STOP 0x00 #define ANI_ONCE 0x01 #define ANI_LOOP 0x02 #define ANI_OSC 0x08 #define ANI_SYNC 0x80 // Special key codes; used in encoded move lists and in some cases also values for Key // Only numbers 1 to 7 can be used in this way. #define KEY_XY 1 typedef struct { Uint8 flag,start,end; union { Uint8 speed; // unsynchronized Uint8 slot; // synchronized |
︙ |
Modified sql.doc from [e099c9daa4] to [632d4d9f5a].
︙ | |||
65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | + + + + | Makes a game value of type 'class', given the class number. You can also specify the class name instead of the number. HASH(data,algorithm) Make the hash of the data as a binary blob. See hash.h for a list of the valid numbers to use as the hash algorithm numbers. HAS_XY_INPUT() Returns nonzero if this puzzle set has coordinate input, or zero if it does not have coordinate input. HEROMESH_ESCAPE(blob) Converts blob representation of a game string into escaped format. HEROMESH_TYPE(value) The type of a game value, given as a 64-bit integer. The types are 'class', 'number', 'string', 'object', and 'sound'. |
︙ |