1 //Copyright Paul Reiche, Fred Ford. 1992-2002
2 
3 /*
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #include "velocity.h"
20 
21 #include "units.h"
22 #include "libs/compiler.h"
23 
24 
25 #define VELOCITY_REMAINDER(v) ((v) & (VELOCITY_SCALE - 1))
26 
27 void
GetCurrentVelocityComponents(VELOCITY_DESC * velocityptr,SIZE * pdx,SIZE * pdy)28 GetCurrentVelocityComponents (VELOCITY_DESC *velocityptr, SIZE *pdx, SIZE *pdy)
29 {
30 	*pdx = WORLD_TO_VELOCITY (velocityptr->vector.width)
31 			+ (velocityptr->fract.width - (SIZE)HIBYTE (velocityptr->incr.width));
32 	*pdy = WORLD_TO_VELOCITY (velocityptr->vector.height)
33 			+ (velocityptr->fract.height - (SIZE)HIBYTE (velocityptr->incr.height));
34 }
35 
36 void
GetNextVelocityComponents(VELOCITY_DESC * velocityptr,SIZE * pdx,SIZE * pdy,COUNT num_frames)37 GetNextVelocityComponents (VELOCITY_DESC *velocityptr, SIZE *pdx, SIZE *pdy,
38 		COUNT num_frames)
39 {
40 	COUNT e;
41 
42 	e = (COUNT)((COUNT)velocityptr->error.width +
43 			((COUNT)velocityptr->fract.width * num_frames));
44 	*pdx = (velocityptr->vector.width * num_frames)
45 			+ ((SIZE)((SBYTE)LOBYTE (velocityptr->incr.width))
46 			* (e >> VELOCITY_SHIFT));
47 	velocityptr->error.width = VELOCITY_REMAINDER (e);
48 
49 	e = (COUNT)((COUNT)velocityptr->error.height +
50 			((COUNT)velocityptr->fract.height * num_frames));
51 	*pdy = (velocityptr->vector.height * num_frames)
52 			+ ((SIZE)((SBYTE)LOBYTE (velocityptr->incr.height))
53 			* (e >> VELOCITY_SHIFT));
54 	velocityptr->error.height = VELOCITY_REMAINDER (e);
55 }
56 
57 void
SetVelocityVector(VELOCITY_DESC * velocityptr,SIZE magnitude,COUNT facing)58 SetVelocityVector (VELOCITY_DESC *velocityptr, SIZE magnitude, COUNT facing)
59 {
60 	COUNT angle;
61 	SIZE dx, dy;
62 
63 	angle = velocityptr->TravelAngle =
64 			FACING_TO_ANGLE (NORMALIZE_FACING (facing));
65 	magnitude = WORLD_TO_VELOCITY (magnitude);
66 	dx = COSINE (angle, magnitude);
67 	dy = SINE (angle, magnitude);
68 	if (dx >= 0)
69 	{
70 		velocityptr->vector.width = VELOCITY_TO_WORLD (dx);
71 		velocityptr->incr.width = MAKE_WORD ((BYTE)1, (BYTE)0);
72 	}
73 	else
74 	{
75 		dx = -dx;
76 		velocityptr->vector.width = -VELOCITY_TO_WORLD (dx);
77 		velocityptr->incr.width =
78 				MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dx) << 1));
79 	}
80 	if (dy >= 0)
81 	{
82 		velocityptr->vector.height = VELOCITY_TO_WORLD (dy);
83 		velocityptr->incr.height = MAKE_WORD ((BYTE)1, (BYTE)0);
84 	}
85 	else
86 	{
87 		dy = -dy;
88 		velocityptr->vector.height = -VELOCITY_TO_WORLD (dy);
89 		velocityptr->incr.height =
90 				MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dy) << 1));
91 	}
92 
93 	velocityptr->fract.width = VELOCITY_REMAINDER (dx);
94 	velocityptr->fract.height = VELOCITY_REMAINDER (dy);
95 	velocityptr->error.width = velocityptr->error.height = 0;
96 }
97 
98 void
SetVelocityComponents(VELOCITY_DESC * velocityptr,SIZE dx,SIZE dy)99 SetVelocityComponents (VELOCITY_DESC *velocityptr, SIZE dx, SIZE dy)
100 {
101 	COUNT angle;
102 
103 	if ((angle = ARCTAN (dx, dy)) == FULL_CIRCLE)
104 	{
105 		ZeroVelocityComponents (velocityptr);
106 	}
107 	else
108 	{
109 		if (dx >= 0)
110 		{
111 			velocityptr->vector.width = VELOCITY_TO_WORLD (dx);
112 			velocityptr->incr.width = MAKE_WORD ((BYTE)1, (BYTE)0);
113 		}
114 		else
115 		{
116 			dx = -dx;
117 			velocityptr->vector.width = -VELOCITY_TO_WORLD (dx);
118 			velocityptr->incr.width =
119 					MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dx) << 1));
120 		}
121 		if (dy >= 0)
122 		{
123 			velocityptr->vector.height = VELOCITY_TO_WORLD (dy);
124 			velocityptr->incr.height = MAKE_WORD ((BYTE)1, (BYTE)0);
125 		}
126 		else
127 		{
128 			dy = -dy;
129 			velocityptr->vector.height = -VELOCITY_TO_WORLD (dy);
130 			velocityptr->incr.height =
131 					MAKE_WORD ((BYTE)0xFF, (BYTE)(VELOCITY_REMAINDER (dy) << 1));
132 		}
133 
134 		velocityptr->fract.width = VELOCITY_REMAINDER (dx);
135 		velocityptr->fract.height = VELOCITY_REMAINDER (dy);
136 		velocityptr->error.width = velocityptr->error.height = 0;
137 	}
138 
139 	velocityptr->TravelAngle = angle;
140 }
141 
142 void
DeltaVelocityComponents(VELOCITY_DESC * velocityptr,SIZE dx,SIZE dy)143 DeltaVelocityComponents (VELOCITY_DESC *velocityptr, SIZE dx, SIZE dy)
144 {
145 
146 	dx += WORLD_TO_VELOCITY (velocityptr->vector.width)
147 			+ (velocityptr->fract.width - (SIZE)HIBYTE (velocityptr->incr.width));
148 	dy += WORLD_TO_VELOCITY (velocityptr->vector.height)
149 			+ (velocityptr->fract.height - (SIZE)HIBYTE (velocityptr->incr.height));
150 
151 	SetVelocityComponents (velocityptr, dx, dy);
152 }
153 
154