2222#define TILE_ATTR_SOLID (0x0001)
2323#define TILE_ATTR_PLAYER_START (0x0002)
2424#define TILE_ATTR_PLAYER_END (0x0004)
25+ #define TILE_ATTR_PUSHABLE (0x0008)
2526
2627actor player ;
2728
@@ -51,6 +52,9 @@ const resource_entry_format *resource_entries = RESOURCE_BASE_ADDR + sizeof(reso
5152resource_entry_format * tile_attrs ;
5253char stage_clear ;
5354
55+ char map_data [9 * 16 ], map_floor [9 * 16 ];
56+ char is_map_data_dirty ;
57+
5458resource_entry_format * resource_find (char * name ) {
5559 SMS_mapROMBank (RESOURCE_BANK );
5660
@@ -103,8 +107,24 @@ void draw_tile(char x, char y, unsigned int tileNumber) {
103107 SMS_setTile (sms_tile + 3 );
104108}
105109
110+ inline char * get_map_tile_pointer (resource_map_format * map , char * data , char x , char y ) {
111+ return data + (y * map -> width ) + x ;
112+ }
113+
106114char get_map_tile (resource_map_format * map , char x , char y ) {
107- return * (map -> tiles + (y * map -> width ) + x );
115+ return * (get_map_tile_pointer (map , map_data , x , y ));
116+ }
117+
118+ void set_map_tile (resource_map_format * map , char x , char y , char new_value ) {
119+ * (get_map_tile_pointer (map , map_data , x , y )) = new_value ;
120+ }
121+
122+ char get_floor_tile (resource_map_format * map , char x , char y ) {
123+ return * (get_map_tile_pointer (map , map_floor , x , y ));
124+ }
125+
126+ void set_floor_tile (resource_map_format * map , char x , char y , char new_value ) {
127+ * (get_map_tile_pointer (map , map_floor , x , y )) = new_value ;
108128}
109129
110130unsigned int get_tile_attr (char tile_number ) {
@@ -120,8 +140,13 @@ resource_map_format *load_map(int n) {
120140 return map ;
121141}
122142
143+ void prepare_map_data (resource_map_format * map ) {
144+ memcpy (map_data , map -> tiles , map -> height * map -> width );
145+ memcpy (map_floor , 0 , map -> height * map -> width );
146+ }
147+
123148void draw_map (resource_map_format * map ) {
124- char * o = map -> tiles ;
149+ char * o = map_data ;
125150 for (char y = 0 ; y != map -> height ; y ++ ) {
126151 for (char x = 0 ; x != map -> width ; x ++ ) {
127152 draw_tile (x << 1 , y << 1 , * o );
@@ -143,6 +168,29 @@ void set_actor_map_xy(actor *act, char x, char y) {
143168 act -> y = (y << 4 ) + (MAP_SCREEN_Y << 3 );
144169}
145170
171+ char try_pushing_tile_on_map (resource_map_format * map , char x , char y , signed char delta_x , signed char delta_y ) {
172+ char new_x = x + delta_x ;
173+ char new_y = y + delta_y ;
174+ if (new_x >= map -> width || new_y >= map -> height ) return 0 ;
175+
176+ char target_tile = get_map_tile (map , new_x , new_y );
177+ unsigned int target_tile_attr = get_tile_attr (target_tile );
178+
179+ if (target_tile_attr & TILE_ATTR_SOLID ) return 0 ;
180+
181+ char source_tile = get_map_tile (map , x , y );
182+ char source_floor_tile = get_floor_tile (map , x , y );
183+
184+ set_map_tile (map , x , y , source_floor_tile ? source_floor_tile : 1 );
185+ set_map_tile (map , new_x , new_y , source_tile );
186+
187+ set_floor_tile (map , new_x , new_y , target_tile );
188+
189+ is_map_data_dirty = 1 ;
190+
191+ return 1 ;
192+ }
193+
146194void try_moving_actor_on_map (actor * act , resource_map_format * map , signed char delta_x , signed char delta_y ) {
147195 char x = get_actor_map_x (act );
148196 char y = get_actor_map_y (act );
@@ -155,7 +203,12 @@ void try_moving_actor_on_map(actor *act, resource_map_format *map, signed char d
155203 unsigned int tile_attr = get_tile_attr (tile );
156204
157205 if (tile_attr & TILE_ATTR_PLAYER_END ) stage_clear = 1 ;
158- if (tile_attr & TILE_ATTR_SOLID ) return ;
206+
207+ if (tile_attr & TILE_ATTR_PUSHABLE ) {
208+ if (!try_pushing_tile_on_map (map , new_x , new_y , delta_x , delta_y )) return ;
209+ } else if (tile_attr & TILE_ATTR_SOLID ) {
210+ return ;
211+ }
159212
160213 set_actor_map_xy (act , new_x , new_y );
161214}
@@ -212,6 +265,7 @@ char handle_title() {
212265 map_number = 1 ;
213266 map = load_map (map_number );
214267 }
268+ prepare_map_data (map );
215269 draw_map (map );
216270
217271 SMS_setNextTileatXY (2 , 1 );
@@ -230,6 +284,7 @@ char handle_title() {
230284 player_find_start (map );
231285
232286 stage_clear = 0 ;
287+ is_map_data_dirty = 0 ;
233288
234289 do {
235290 // Wait button press
@@ -258,6 +313,8 @@ char handle_title() {
258313 SMS_waitForVBlank ();
259314 SMS_copySpritestoSAT ();
260315
316+ if (is_map_data_dirty ) draw_map (map );
317+
261318 joy_prev = joy ;
262319 joy = SMS_getKeysStatus ();
263320 } while (!stage_clear && !(joy & (PORT_A_KEY_1 | PORT_A_KEY_2 | PORT_B_KEY_1 | PORT_B_KEY_2 )));
@@ -299,6 +356,6 @@ void main() {
299356}
300357
301358SMS_EMBED_SEGA_ROM_HEADER (9999 ,0 ); // code 9999 hopefully free, here this means 'homebrew'
302- SMS_EMBED_SDSC_HEADER (0 ,3 , 2025 ,02 ,13 , "Haroldo-OK\\2025" , "SMS-Puzzle-Maker base ROM" ,
359+ SMS_EMBED_SDSC_HEADER (0 ,4 , 2025 ,02 ,18 , "Haroldo-OK\\2025" , "SMS-Puzzle-Maker base ROM" ,
303360 "Made for SMS-Puzzle-Maker - https://github.com/haroldo-ok/SMS-Puzzle-Maker.\n"
304361 "Built using devkitSMS & SMSlib - https://github.com/sverx/devkitSMS" );
0 commit comments