ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
travel_path.c
Go to the documentation of this file.
1/*****************************************************************************
2 * ugBASIC - an isomorphic BASIC language compiler for retrocomputers *
3 *****************************************************************************
4 * Copyright 2021-2026 Marco Spedaletti (asimov@mclink.it)
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *----------------------------------------------------------------------------
18 * Concesso in licenza secondo i termini della Licenza Apache, versione 2.0
19 * (la "Licenza"); è proibito usare questo file se non in conformità alla
20 * Licenza. Una copia della Licenza è disponibile all'indirizzo:
21 *
22 * http://www.apache.org/licenses/LICENSE-2.0
23 *
24 * Se non richiesto dalla legislazione vigente o concordato per iscritto,
25 * il software distribuito nei termini della Licenza è distribuito
26 * "COSÌ COM'È", SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO, esplicite o
27 * implicite. Consultare la Licenza per il testo specifico che regola le
28 * autorizzazioni e le limitazioni previste dalla medesima.
29 ****************************************************************************/
30
31/****************************************************************************
32 * INCLUDE SECTION
33 ****************************************************************************/
34
35#include "../../ugbc.h"
36
37/****************************************************************************
38 * CODE SECTION
39 ****************************************************************************/
40
49/* <usermanual>
50@keyword TRAVEL
51
52The ''TRAVEL'' command allows you to move an entity (for example, a character in a video
53game, a robot in a simulated environment, or a cursor on a map) from a starting point to
54a destination point, following a previous created ''PATH''. The coordinates of the
55starting point and of the destination point are given using the ''CREATE PATH'' command.
56So, this command will update a pair of variables (''x'',''y'') with the next point.
57Optionally, you can give a multiplier factor (''times''), in order to move more than one pixel
58at a time. By adding the ''CLAMP'' keyword, the increment of the coordinate variables
59will be limited to the coordinates of the destination point. The function version can be
60used to check if destination coordinate is reached (if ''CLAMP'' has been requested).
61
62The command uses the Bresenham algorithm to calculate the sequence of intermediate
63coordinates that define the most efficient path between the starting point and the
64destination point. The Bresenham algorithm is particularly suitable for drawing
65straight lines on discrete grids (such as pixel grids), ensuring an optimized path in
66terms of steps. In other words, the entity is moved along the calculated path,
67updating its coordinates at each step. The speed of the movement can be controlled by
68the ''times'' parameter. If the speed is not specified, a value of 1 is implicit considered.
69
70The Bresenham algorithm is efficient and ensures an optimized path, but produces straight
71paths. In scenarios where more complex paths are required (e.g. with curves or obstacles),
72more advanced pathfinding algorithms may be needed.
73
74@italian
75
76Il comando ''TRAVEL'' consente di spostare un'entità (ad esempio, un personaggio in un videogioco, un robot in un ambiente simulato o un cursore su una mappa) da un punto di partenza a un punto di destinazione, seguendo un ''PATH'' creato in precedenza. Le coordinate del punto di partenza e del punto di destinazione vengono fornite utilizzando il comando ''CREATE PATH''.
77Quindi, questo comando aggiornerà una coppia di variabili (''x'',''y'') con il punto successivo.
78Facoltativamente, è possibile fornire un fattore moltiplicatore (''times''), per spostare più di un pixel
79alla volta.
80
81Il comando utilizza l'algoritmo di Bresenham per calcolare la sequenza di coordinate intermedie che definiscono il percorso più efficiente tra il punto di partenza e il punto di destinazione. L'algoritmo di Bresenham è particolarmente adatto per disegnare linee rette su griglie discrete (come le griglie di pixel), garantendo un percorso ottimizzato in termini di passaggi. In altre parole, l'entità viene spostata lungo il percorso calcolato,
82aggiornando le sue coordinate a ogni passo. La velocità del movimento può essere controllata dal
83parametro ''times''. Se la velocità non è specificata, viene implicitamente considerato un
84valore pari a 1. Aggiungendo la parola chiave ''CLAMP'', l'incremento delle variabili coordinate
85sarà limitato alle coordinate del punto di destinazione. Nella versione che ritorna un valore,
86è possibile utilizzare tale valore per comprendere se le coordinate di destinazione sono
87state raggiunte (purché sia stata usata la parola chiave ''CLAMP'').
88
89L'algoritmo di Bresenham è efficiente e garantisce un percorso ottimizzato, ma produce percorsi
90retti. In scenari in cui sono richiesti percorsi più complessi (ad esempio con curve o ostacoli),
91potrebbero essere necessari algoritmi di pathfinding più avanzati.
92
93@syntax TRAVEL path TO x, y [BY times] [CLAMP]
94@syntax = TRAVEL ( path TO x, y [BY times] [CLAMP] )
95
96@example ebltPath = CREATE PATH(posX, posY TO endX, endY)
97@example DO
98@example EXIT IF TRAVEL( ebltPath TO ebltX, ebltY CLAMP )
99@example PUT IMAGE enmBlt FRAME 0 AT ebltX, ebltY
100@example LOOP
101
102</usermanual> */
103
104Variable * travel_path( Environment * _environment, char * _p, char * _x, char * _y, char * _times, char * _limited ) {
105
107
109 char loopLabel[ MAX_TEMPORARY_STORAGE ]; sprintf( loopLabel, "%stimes", label );
110 char unlimitedLabel[ MAX_TEMPORARY_STORAGE ]; sprintf( unlimitedLabel, "%sunlimited", label );
111 char doneLabel[ MAX_TEMPORARY_STORAGE ]; sprintf( doneLabel, "%sdone", label );
112
113 Variable * path = variable_define( _environment, "travelpath__path", VT_PATH, 0 );
114 path->bankReadOrWrite = 1;
115
116 Variable * xout = variable_define( _environment, "travelpath__xout", VT_POSITION, 0 );
117 Variable * yout = variable_define( _environment, "travelpath__yout", VT_POSITION, 0 );
118
119 Variable * times = variable_define( _environment, "travelpath__times", VT_BYTE, 0 );
120 Variable * limited = variable_define( _environment, "travelpath__limited", VT_SBYTE, 0 );
121 Variable * check = variable_temporary( _environment, VT_SBYTE, "(stepx)");
122
123 Variable * fraction = variable_temporary( _environment, VT_POSITION, "(fraction)");
124 Variable * x = variable_temporary( _environment, VT_POSITION, "(x)" );
125 Variable * y = variable_temporary( _environment, VT_POSITION, "(y)" );
126 Variable * dx2 = variable_temporary( _environment, VT_POSITION, "(dx2)");
127 Variable * dy2 = variable_temporary( _environment, VT_POSITION, "(dy2)");
128 Variable * stepx = variable_temporary( _environment, VT_SBYTE, "(stepx)");
129 Variable * stepy = variable_temporary( _environment, VT_SBYTE, "(stepy)");
130 Variable * x1 = variable_temporary( _environment, VT_POSITION, "(x1)" );
131 Variable * y1 = variable_temporary( _environment, VT_POSITION, "(y1)" );
132
133 cpu_move_16bit( _environment, path->realName, x->realName );
134 cpu_move_16bit( _environment, address_displacement( _environment, path->realName, "2" ), y->realName );
135 cpu_move_16bit( _environment, address_displacement( _environment, path->realName, "4" ), dx2->realName );
136 cpu_move_16bit( _environment, address_displacement( _environment, path->realName, "6" ), dy2->realName );
137 cpu_move_8bit( _environment, address_displacement( _environment, path->realName, "8" ), stepx->realName );
138 cpu_move_8bit( _environment, address_displacement( _environment, path->realName, "9" ), stepy->realName );
139 cpu_move_16bit( _environment, address_displacement( _environment, path->realName, "10" ), fraction->realName );
140 cpu_move_16bit( _environment, address_displacement( _environment, path->realName, "12" ), x1->realName );
141 cpu_move_16bit( _environment, address_displacement( _environment, path->realName, "14" ), y1->realName );
142
143 cpu_store_8bit( _environment, check->realName, 0 );
144
145 cpu_label( _environment, loopLabel );
146
147 cpu_compare_and_branch_8bit_const( _environment, limited->realName, 0, unlimitedLabel, 1 );
148
149 variable_move( _environment,
150 variable_and( _environment,
151 variable_compare( _environment, x->name, x1->name )->name,
152 variable_compare( _environment, y->name, y1->name )->name
153 )->name, check->name );
154 cpu_compare_and_branch_8bit_const( _environment, check->realName, 0xff, doneLabel, 1 );
155
156 cpu_label( _environment, unlimitedLabel );
157
158 if_then( _environment, variable_greater_than( _environment, dx2->name, dy2->name, 0 )->name );
159 variable_move( _environment, variable_add( _environment, x->name, stepx->name )->name, x->name );
160 if_then( _environment, variable_greater_than_const( _environment, fraction->name, 0, 1 )->name );
161 variable_move( _environment, variable_add( _environment, y->name, stepy->name )->name, y->name );
162 variable_move( _environment, variable_sub( _environment, fraction->name, dx2->name )->name, fraction->name );
163 end_if_then( _environment );
164 variable_move( _environment, variable_add( _environment, fraction->name, dy2->name )->name, fraction->name );
165 else_if_then_label( _environment );
166 else_if_then( _environment, NULL );
167 if_then( _environment, variable_greater_than_const( _environment, fraction->name, 0, 1 )->name );
168 variable_move( _environment, variable_add( _environment, x->name, stepx->name )->name, x->name );
169 variable_move( _environment, variable_sub( _environment, fraction->name, dy2->name )->name, fraction->name );
170 end_if_then( _environment );
171 variable_move( _environment, variable_add( _environment, y->name, stepy->name )->name, y->name );
172 variable_move( _environment, variable_add( _environment, fraction->name, dx2->name )->name, fraction->name );
173 end_if_then( _environment );
174
175 cpu_dec( _environment, times->realName );
176 cpu_compare_and_branch_8bit_const( _environment, times->realName, 0, loopLabel, 0 );
177
178 cpu_label( _environment, doneLabel );
179
180 cpu_move_16bit( _environment, x->realName, path->realName );
181 cpu_move_16bit( _environment, y->realName, address_displacement( _environment, path->realName, "2" ) );
182 cpu_move_16bit( _environment, dx2->realName, address_displacement( _environment, path->realName, "4" ) );
183 cpu_move_16bit( _environment, dy2->realName, address_displacement( _environment, path->realName, "6" ) );
184 cpu_move_16bit( _environment, stepx->realName, address_displacement( _environment, path->realName, "8" ) );
185 cpu_move_16bit( _environment, stepy->realName, address_displacement( _environment, path->realName, "9" ) );
186 cpu_move_16bit( _environment, fraction->realName, address_displacement( _environment, path->realName, "10" ) );
187 cpu_move_16bit( _environment, x1->realName, address_displacement( _environment, path->realName, "12" ) );
188 cpu_move_16bit( _environment, y1->realName, address_displacement( _environment, path->realName, "14" ) );
189
190 cpu_move_16bit( _environment, x->realName, xout->realName );
191 cpu_move_16bit( _environment, y->realName, yout->realName );
192
193 cpu_move_8bit( _environment, check->realName, limited->realName );
194
195 cpu_return( _environment );
196
198
199 Variable * p = variable_retrieve( _environment, _p );
200 Variable * x = variable_retrieve( _environment, _x );
201 Variable * y = variable_retrieve( _environment, _y );
202
203 Variable * path = variable_retrieve( _environment, "travelpath__path" );
204 Variable * xout = variable_retrieve( _environment, "travelpath__xout" );
205 Variable * yout = variable_retrieve( _environment, "travelpath__yout" );
206 Variable * ptimes = variable_retrieve( _environment, "travelpath__times" );
207 Variable * plimited = variable_retrieve( _environment, "travelpath__limited" );
208
209 variable_move( _environment, p->name, path->name );
210 if ( _times ) {
211 Variable * times = variable_retrieve( _environment, _times );
212 if ( times->initializedByConstant ) {
213 variable_store( _environment, ptimes->name, times->value );
214 } else {
215 variable_move( _environment, times->name, ptimes->name );
216 }
217 } else {
218 variable_store( _environment, ptimes->name, 1 );
219 }
220
221 Variable * limited;
222 if ( _limited ) {
223 limited = variable_retrieve_or_define( _environment, _limited, VT_SBYTE, 0 );
224 variable_move( _environment, limited->name, plimited->name );
225 } else {
226 limited = variable_temporary( _environment, VT_SBYTE, "(limited)" );
227 variable_store( _environment, plimited->name, 0 );
228 }
229
230 cpu_call( _environment, "lib_travel_path" );
231
232 variable_move( _environment, path->name, p->name );
233 variable_move( _environment, xout->name, x->name );
234 variable_move( _environment, yout->name, y->name );
235 variable_move( _environment, plimited->name, limited->name );
236
237 return limited;
238
239}
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_dec(Environment *_environment, char *_variable)
Definition 6309.c:4630
void cpu_move_16bit(Environment *_environment, char *_source, char *_destination)
CPU 6309: emit code to move 16 bit
Definition 6309.c:1474
void cpu_call(Environment *_environment, char *_label)
Definition 6309.c:3755
void cpu_store_8bit(Environment *_environment, char *_destination, int _value)
CPU 6309: emit code to store 8 bit
Definition 6309.c:761
void cpu_return(Environment *_environment)
Definition 6309.c:4030
void cpu_move_8bit(Environment *_environment, char *_source, char *_destination)
CPU 6309: emit code to move 8 bit
Definition 6309.c:743
void cpu_compare_and_branch_8bit_const(Environment *_environment, char *_source, int _destination, char *_label, int _positive)
CPU 6309: emit code to compare two 8 bit values and jump if they are equal/different
Definition 6309.c:876
Variable * variable_add(Environment *_environment, char *_source, char *_destination)
Add two variable and return the sum of them.
Variable * variable_retrieve(Environment *_environment, char *_name)
Variable * variable_retrieve_or_define(Environment *_environment, char *_name, VariableType _type, int _value)
Variable * variable_and(Environment *_environment, char *_left, char *_right)
Calculate logical "and" and return it as the result.
Variable * variable_greater_than(Environment *_environment, char *_source, char *_destination, int _equal)
Compare two variable and return the result of comparation.
Variable * variable_move(Environment *_environment, char *_source, char *_destination)
Store the value of a variable inside another variable by converting it.
Variable * variable_define(Environment *_environment, char *_name, VariableType _type, int _value)
Define a variable for the program.
Variable * variable_sub(Environment *_environment, char *_source, char *_dest)
Make a differenze between two variable and return the difference of them.
Variable * variable_temporary(Environment *_environment, VariableType _type, char *_meaning)
Define a temporary variable.
Variable * variable_compare(Environment *_environment, char *_source, char *_destination)
Compare two variable and return the result of comparation.
Variable * variable_store(Environment *_environment, char *_destination, unsigned int _value)
Store a direct value to a variable.
Variable * variable_greater_than_const(Environment *_environment, char *_source, int _destination, int _equal)
char * address_displacement(Environment *_environment, char *_address, char *_displacement)
void else_if_then_label(Environment *_environment)
Emit ASM code for ... ELSE [IF] ....
void else_if_then(Environment *_environment, char *_expression)
Emit ASM code for ... ELSE [IF] ....
void end_if_then(Environment *_environment)
Emit ASM code for ENDIF.
Definition end_if_then.c:50
void if_then(Environment *_environment, char *_expression)
Emit ASM code for IF ... THEN ....
Definition if_then.c:123
int bankReadOrWrite
Definition ugbc.h:1181
char * name
Definition ugbc.h:979
int value
Definition ugbc.h:1025
int initializedByConstant
Definition ugbc.h:1036
char * realName
Definition ugbc.h:982
Variable * travel_path(Environment *_environment, char *_p, char *_x, char *_y, char *_times, char *_limited)
Emit ASM code to implement TRAVEL PATH command.
#define deploy_end(s)
Definition ugbc.h:4365
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
struct _Variable Variable
Structure of a single variable.
struct _Environment Environment
Structure of compilation environment.
@ VT_POSITION
Definition ugbc.h:468
@ VT_BYTE
Definition ugbc.h:450
@ VT_SBYTE
Definition ugbc.h:452
@ VT_PATH
Definition ugbc.h:540
#define deploy_begin(s)
Definition ugbc.h:4356
#define MAKE_LABEL
Definition ugbc.h:3351