├── COPYING.txt
├── README.txt
├── index.html
├── js
├── actorai.js
├── actors.js
├── actstat.js
├── ai.js
├── angle.js
├── areas.js
├── doors.js
├── episodes.js
├── file.js
├── game.js
├── input.js
├── level.js
├── load.js
├── maps.sample.js
├── math.js
├── menu.js
├── player.js
├── powerups.js
├── pushwall.js
├── random.js
├── raycaster.js
├── renderer.js
├── requestanimframe.js
├── sound.js
├── sprites.js
├── weapon.js
└── wolf.js
├── styles.css
└── wolf3d.html
/COPYING.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Library General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 |
60 | GNU GENERAL PUBLIC LICENSE
61 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
62 |
63 | 0. This License applies to any program or other work which contains
64 | a notice placed by the copyright holder saying it may be distributed
65 | under the terms of this General Public License. The "Program", below,
66 | refers to any such program or work, and a "work based on the Program"
67 | means either the Program or any derivative work under copyright law:
68 | that is to say, a work containing the Program or a portion of it,
69 | either verbatim or with modifications and/or translated into another
70 | language. (Hereinafter, translation is included without limitation in
71 | the term "modification".) Each licensee is addressed as "you".
72 |
73 | Activities other than copying, distribution and modification are not
74 | covered by this License; they are outside its scope. The act of
75 | running the Program is not restricted, and the output from the Program
76 | is covered only if its contents constitute a work based on the
77 | Program (independent of having been made by running the Program).
78 | Whether that is true depends on what the Program does.
79 |
80 | 1. You may copy and distribute verbatim copies of the Program's
81 | source code as you receive it, in any medium, provided that you
82 | conspicuously and appropriately publish on each copy an appropriate
83 | copyright notice and disclaimer of warranty; keep intact all the
84 | notices that refer to this License and to the absence of any warranty;
85 | and give any other recipients of the Program a copy of this License
86 | along with the Program.
87 |
88 | You may charge a fee for the physical act of transferring a copy, and
89 | you may at your option offer warranty protection in exchange for a fee.
90 |
91 | 2. You may modify your copy or copies of the Program or any portion
92 | of it, thus forming a work based on the Program, and copy and
93 | distribute such modifications or work under the terms of Section 1
94 | above, provided that you also meet all of these conditions:
95 |
96 | a) You must cause the modified files to carry prominent notices
97 | stating that you changed the files and the date of any change.
98 |
99 | b) You must cause any work that you distribute or publish, that in
100 | whole or in part contains or is derived from the Program or any
101 | part thereof, to be licensed as a whole at no charge to all third
102 | parties under the terms of this License.
103 |
104 | c) If the modified program normally reads commands interactively
105 | when run, you must cause it, when started running for such
106 | interactive use in the most ordinary way, to print or display an
107 | announcement including an appropriate copyright notice and a
108 | notice that there is no warranty (or else, saying that you provide
109 | a warranty) and that users may redistribute the program under
110 | these conditions, and telling the user how to view a copy of this
111 | License. (Exception: if the Program itself is interactive but
112 | does not normally print such an announcement, your work based on
113 | the Program is not required to print an announcement.)
114 |
115 |
116 | These requirements apply to the modified work as a whole. If
117 | identifiable sections of that work are not derived from the Program,
118 | and can be reasonably considered independent and separate works in
119 | themselves, then this License, and its terms, do not apply to those
120 | sections when you distribute them as separate works. But when you
121 | distribute the same sections as part of a whole which is a work based
122 | on the Program, the distribution of the whole must be on the terms of
123 | this License, whose permissions for other licensees extend to the
124 | entire whole, and thus to each and every part regardless of who wrote it.
125 |
126 | Thus, it is not the intent of this section to claim rights or contest
127 | your rights to work written entirely by you; rather, the intent is to
128 | exercise the right to control the distribution of derivative or
129 | collective works based on the Program.
130 |
131 | In addition, mere aggregation of another work not based on the Program
132 | with the Program (or with a work based on the Program) on a volume of
133 | a storage or distribution medium does not bring the other work under
134 | the scope of this License.
135 |
136 | 3. You may copy and distribute the Program (or a work based on it,
137 | under Section 2) in object code or executable form under the terms of
138 | Sections 1 and 2 above provided that you also do one of the following:
139 |
140 | a) Accompany it with the complete corresponding machine-readable
141 | source code, which must be distributed under the terms of Sections
142 | 1 and 2 above on a medium customarily used for software interchange; or,
143 |
144 | b) Accompany it with a written offer, valid for at least three
145 | years, to give any third party, for a charge no more than your
146 | cost of physically performing source distribution, a complete
147 | machine-readable copy of the corresponding source code, to be
148 | distributed under the terms of Sections 1 and 2 above on a medium
149 | customarily used for software interchange; or,
150 |
151 | c) Accompany it with the information you received as to the offer
152 | to distribute corresponding source code. (This alternative is
153 | allowed only for noncommercial distribution and only if you
154 | received the program in object code or executable form with such
155 | an offer, in accord with Subsection b above.)
156 |
157 | The source code for a work means the preferred form of the work for
158 | making modifications to it. For an executable work, complete source
159 | code means all the source code for all modules it contains, plus any
160 | associated interface definition files, plus the scripts used to
161 | control compilation and installation of the executable. However, as a
162 | special exception, the source code distributed need not include
163 | anything that is normally distributed (in either source or binary
164 | form) with the major components (compiler, kernel, and so on) of the
165 | operating system on which the executable runs, unless that component
166 | itself accompanies the executable.
167 |
168 | If distribution of executable or object code is made by offering
169 | access to copy from a designated place, then offering equivalent
170 | access to copy the source code from the same place counts as
171 | distribution of the source code, even though third parties are not
172 | compelled to copy the source along with the object code.
173 |
174 |
175 | 4. You may not copy, modify, sublicense, or distribute the Program
176 | except as expressly provided under this License. Any attempt
177 | otherwise to copy, modify, sublicense or distribute the Program is
178 | void, and will automatically terminate your rights under this License.
179 | However, parties who have received copies, or rights, from you under
180 | this License will not have their licenses terminated so long as such
181 | parties remain in full compliance.
182 |
183 | 5. You are not required to accept this License, since you have not
184 | signed it. However, nothing else grants you permission to modify or
185 | distribute the Program or its derivative works. These actions are
186 | prohibited by law if you do not accept this License. Therefore, by
187 | modifying or distributing the Program (or any work based on the
188 | Program), you indicate your acceptance of this License to do so, and
189 | all its terms and conditions for copying, distributing or modifying
190 | the Program or works based on it.
191 |
192 | 6. Each time you redistribute the Program (or any work based on the
193 | Program), the recipient automatically receives a license from the
194 | original licensor to copy, distribute or modify the Program subject to
195 | these terms and conditions. You may not impose any further
196 | restrictions on the recipients' exercise of the rights granted herein.
197 | You are not responsible for enforcing compliance by third parties to
198 | this License.
199 |
200 | 7. If, as a consequence of a court judgment or allegation of patent
201 | infringement or for any other reason (not limited to patent issues),
202 | conditions are imposed on you (whether by court order, agreement or
203 | otherwise) that contradict the conditions of this License, they do not
204 | excuse you from the conditions of this License. If you cannot
205 | distribute so as to satisfy simultaneously your obligations under this
206 | License and any other pertinent obligations, then as a consequence you
207 | may not distribute the Program at all. For example, if a patent
208 | license would not permit royalty-free redistribution of the Program by
209 | all those who receive copies directly or indirectly through you, then
210 | the only way you could satisfy both it and this License would be to
211 | refrain entirely from distribution of the Program.
212 |
213 | If any portion of this section is held invalid or unenforceable under
214 | any particular circumstance, the balance of the section is intended to
215 | apply and the section as a whole is intended to apply in other
216 | circumstances.
217 |
218 | It is not the purpose of this section to induce you to infringe any
219 | patents or other property right claims or to contest validity of any
220 | such claims; this section has the sole purpose of protecting the
221 | integrity of the free software distribution system, which is
222 | implemented by public license practices. Many people have made
223 | generous contributions to the wide range of software distributed
224 | through that system in reliance on consistent application of that
225 | system; it is up to the author/donor to decide if he or she is willing
226 | to distribute software through any other system and a licensee cannot
227 | impose that choice.
228 |
229 | This section is intended to make thoroughly clear what is believed to
230 | be a consequence of the rest of this License.
231 |
232 |
233 | 8. If the distribution and/or use of the Program is restricted in
234 | certain countries either by patents or by copyrighted interfaces, the
235 | original copyright holder who places the Program under this License
236 | may add an explicit geographical distribution limitation excluding
237 | those countries, so that distribution is permitted only in or among
238 | countries not thus excluded. In such case, this License incorporates
239 | the limitation as if written in the body of this License.
240 |
241 | 9. The Free Software Foundation may publish revised and/or new versions
242 | of the General Public License from time to time. Such new versions will
243 | be similar in spirit to the present version, but may differ in detail to
244 | address new problems or concerns.
245 |
246 | Each version is given a distinguishing version number. If the Program
247 | specifies a version number of this License which applies to it and "any
248 | later version", you have the option of following the terms and conditions
249 | either of that version or of any later version published by the Free
250 | Software Foundation. If the Program does not specify a version number of
251 | this License, you may choose any version ever published by the Free Software
252 | Foundation.
253 |
254 | 10. If you wish to incorporate parts of the Program into other free
255 | programs whose distribution conditions are different, write to the author
256 | to ask for permission. For software which is copyrighted by the Free
257 | Software Foundation, write to the Free Software Foundation; we sometimes
258 | make exceptions for this. Our decision will be guided by the two goals
259 | of preserving the free status of all derivatives of our free software and
260 | of promoting the sharing and reuse of software generally.
261 |
262 | NO WARRANTY
263 |
264 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
265 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
266 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
267 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
268 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
269 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
270 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
271 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
272 | REPAIR OR CORRECTION.
273 |
274 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
275 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
276 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
277 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
278 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
279 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
280 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
281 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
282 | POSSIBILITY OF SUCH DAMAGES.
283 |
284 | END OF TERMS AND CONDITIONS
285 |
286 |
287 | How to Apply These Terms to Your New Programs
288 |
289 | If you develop a new program, and you want it to be of the greatest
290 | possible use to the public, the best way to achieve this is to make it
291 | free software which everyone can redistribute and change under these terms.
292 |
293 | To do so, attach the following notices to the program. It is safest
294 | to attach them to the start of each source file to most effectively
295 | convey the exclusion of warranty; and each file should have at least
296 | the "copyright" line and a pointer to where the full notice is found.
297 |
298 |
299 | Copyright (C)
300 |
301 | This program is free software; you can redistribute it and/or modify
302 | it under the terms of the GNU General Public License as published by
303 | the Free Software Foundation; either version 2 of the License, or
304 | (at your option) any later version.
305 |
306 | This program is distributed in the hope that it will be useful,
307 | but WITHOUT ANY WARRANTY; without even the implied warranty of
308 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
309 | GNU General Public License for more details.
310 |
311 | You should have received a copy of the GNU General Public License
312 | along with this program; if not, write to the Free Software
313 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
314 |
315 |
316 | Also add information on how to contact you by electronic and paper mail.
317 |
318 | If the program is interactive, make it output a short notice like this
319 | when it starts in an interactive mode:
320 |
321 | Gnomovision version 69, Copyright (C) year name of author
322 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
323 | This is free software, and you are welcome to redistribute it
324 | under certain conditions; type `show c' for details.
325 |
326 | The hypothetical commands `show w' and `show c' should show the appropriate
327 | parts of the General Public License. Of course, the commands you use may
328 | be called something other than `show w' and `show c'; they could even be
329 | mouse-clicks or menu items--whatever suits your program.
330 |
331 | You should also get your employer (if you work as a programmer) or your
332 | school, if any, to sign a "copyright disclaimer" for the program, if
333 | necessary. Here is a sample; alter the names:
334 |
335 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
336 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
337 |
338 | , 1 April 1989
339 | Ty Coon, President of Vice
340 |
341 | This General Public License does not permit incorporating your program into
342 | proprietary programs. If your program is a subroutine library, you may
343 | consider it more useful to permit linking proprietary applications with the
344 | library. If this is what you want to do, use the GNU Library General
345 | Public License instead of this License.
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | WOLF3D Browser Version GPL source release
2 | ===============================================
3 |
4 | This file contains the following sections:
5 |
6 | GENERAL NOTES
7 | LICENSE
8 |
9 | GENERAL NOTES
10 | =============
11 |
12 | WOLF3D Browser Version is a free release, and can be downloaded from
13 | https://github.com/id-Software/wolf3d-browser
14 |
15 | This source release does not contain any game data, the game data remains subject to the original EULA and applicable law.
16 |
17 |
18 | LICENSE
19 | =======
20 |
21 | See COPYING.txt for the GNU GENERAL PUBLIC LICENSE. If COPYING.txt does not accompany, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 |
23 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 | Test Page
11 |
23 |
24 |
25 |
26 |
28 |
29 |
30 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/js/actors.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 | /**
28 | * @namespace
29 | * @description Actors
30 | */
31 | Wolf.Actors = (function() {
32 |
33 | Wolf.setConsts({
34 | SPDPATROL : 512,
35 | SPDDOG : 1500,
36 |
37 | FL_SHOOTABLE : 1,
38 | FL_BONUS : 2,
39 | FL_NEVERMARK : 4,
40 | FL_VISABLE : 8,
41 | FL_ATTACKMODE : 16,
42 | FL_FIRSTATTACK : 32,
43 | FL_AMBUSH : 64,
44 | FL_NONMARK : 128,
45 |
46 | MAX_GUARDS : 255,
47 | NUMENEMIES : 31,
48 | NUMSTATES : 34,
49 |
50 | MINACTORDIST : 0x10000
51 | });
52 |
53 | Wolf.setConsts({
54 | en_guard : 0,
55 | en_officer : 1,
56 | en_ss : 2,
57 | en_dog : 3,
58 | en_boss : 4,
59 | en_schabbs : 5,
60 | en_fake : 6,
61 | en_mecha : 7,
62 | en_hitler : 8,
63 | en_mutant : 9,
64 | en_blinky : 10,
65 | en_clyde : 11,
66 | en_pinky : 12,
67 | en_inky : 13,
68 | en_gretel : 14,
69 | en_gift : 15,
70 | en_fat : 16,
71 | // --- Projectiles
72 | en_needle : 17,
73 | en_fire : 18,
74 | en_rocket : 19,
75 | en_smoke : 20,
76 | en_bj : 21,
77 | // --- Spear of destiny!
78 | en_spark : 22,
79 | en_hrocket : 23,
80 | en_hsmoke : 24,
81 |
82 | en_spectre : 25,
83 | en_angel : 26,
84 | en_trans : 27,
85 | en_uber : 28,
86 | en_will : 29,
87 | en_death : 30
88 | });
89 |
90 | Wolf.setConsts({
91 | st_stand : 0,
92 | st_path1 : 1,
93 | st_path1s : 2,
94 | st_path2 : 3,
95 | st_path3 : 4,
96 | st_path3s : 5,
97 | st_path4 : 6,
98 | st_pain : 7,
99 | st_pain1 : 8,
100 | st_shoot1 : 9,
101 | st_shoot2 : 10,
102 | st_shoot3 : 11,
103 | st_shoot4 : 12,
104 | st_shoot5 : 13,
105 | st_shoot6 : 14,
106 | st_shoot7 : 15,
107 | st_shoot8 : 16,
108 | st_shoot9 : 17,
109 | st_chase1 : 18,
110 | st_chase1s : 19,
111 | st_chase2 : 20,
112 | st_chase3 : 21,
113 | st_chase3s : 22,
114 | st_chase4 : 23,
115 | st_die1 : 24,
116 | st_die2 : 25,
117 | st_die3 : 26,
118 | st_die4 : 27,
119 | st_die5 : 28,
120 | st_die6 : 29,
121 | st_die7 : 30,
122 | st_die8 : 31,
123 | st_die9 : 32,
124 | st_dead : 33,
125 | st_remove : 34
126 | });
127 |
128 | var add8dir = [4, 5, 6, 7, 0, 1, 2, 3, 0],
129 | r_add8dir = [4, 7, 6, 5, 0, 1, 2, 3, 0];
130 |
131 | /**
132 | * @description Create new actor.
133 | * @memberOf Wolf.Actors
134 | * @param {object} level The level object.
135 | * @returns {object} The new actor object.
136 | */
137 | function getNewActor(level) {
138 |
139 | if (level.state.numGuards > Wolf.MAX_GUARDS) {
140 | return null;
141 | }
142 |
143 | var actor = {
144 | x : 0,
145 | y : 0,
146 | angle : 0,
147 | type : 0,
148 | health : 0,
149 | max_health : 0,
150 | speed : 0,
151 | ticcount : 0,
152 | temp2 : 0,
153 | distance : 0,
154 | tile : {
155 | x : 0,
156 | y : 0
157 | },
158 | areanumber : 0,
159 | waitfordoorx : 0,
160 | waitfordoory : 0, // waiting on this door if non 0
161 | flags : 0, // FL_SHOOTABLE, etc
162 | state : 0,
163 | dir : 0,
164 | sprite : 0
165 | };
166 | level.state.guards[level.state.numGuards++] = actor;
167 |
168 | return actor;
169 | }
170 |
171 | /**
172 | * @description Process a single actor.
173 | * @private
174 | * @param {object} ent The actor object.
175 | * @param {object} level The level object.
176 | * @param {object} player The player object.
177 | * @param {number} tics The number of tics.
178 | * @returns {boolean} False if actor should be removed, otherwise true.
179 | */
180 | function doGuard(ent, game, tics) { // FIXME: revise!
181 | var think;
182 |
183 | //assert( ent->tilex >= 0 && ent->tilex < 64 );
184 | //assert( ent->tiley >= 0 && ent->tiley < 64 );
185 | //assert( ent->dir >= 0 && ent->dir <= 8 );
186 |
187 |
188 | // ticcounts fire discrete actions separate from think functions
189 | if (ent.ticcount) {
190 | ent.ticcount -= tics;
191 |
192 | while (ent.ticcount <= 0) {
193 | //assert( ent->type >= 0 && ent->type < NUMENEMIES );
194 | //assert( ent->state >= 0 && ent->state < NUMSTATES );
195 |
196 | think = Wolf.objstate[ent.type][ent.state].action; // end of state action
197 | if (think) {
198 | think(ent, game, tics);
199 | if (ent.state == Wolf.st_remove) {
200 | return false;
201 | }
202 | }
203 |
204 | ent.state = Wolf.objstate[ent.type][ent.state].next_state;
205 | if (ent.state == Wolf.st_remove) {
206 | return false;
207 | }
208 |
209 | if (!Wolf.objstate[ent.type][ent.state].timeout) {
210 | ent.ticcount = 0;
211 | break;
212 | }
213 |
214 | ent.ticcount += Wolf.objstate[ent.type][ent.state].timeout;
215 | }
216 | }
217 | //
218 | // think
219 | //
220 | //assert( ent->type >= 0 && ent->type < NUMENEMIES );
221 | //assert( ent->state >= 0 && ent->state < NUMSTATES );
222 | think = Wolf.objstate[ent.type][ent.state].think;
223 |
224 | if (think) {
225 | think(ent, game, tics);
226 | if (ent.state == Wolf.st_remove) {
227 | return false;
228 | }
229 | }
230 |
231 | return true;
232 | }
233 |
234 |
235 | /**
236 | * @description Changes guard's state to that defined in newState.
237 | * @memberOf Wolf.Actors
238 | * @param {object} ent The actor object.
239 | * @param {number} newState The new state.
240 | */
241 | function stateChange(ent, newState) {
242 | ent.state = newState;
243 | // assert( ent->type >= 0 && ent->type < NUMENEMIES );
244 | if (newState == Wolf.st_remove) {
245 | ent.ticcount = 0;
246 | } else {
247 | // assert( ent->state >= 0 && ent->state < NUMSTATES );
248 | ent.ticcount = Wolf.objstate[ent.type][ent.state].timeout; //0;
249 | }
250 | }
251 |
252 | /**
253 | * @description Process all the enemy actors.
254 | * @memberOf Wolf.Actors
255 | * @param {object} level The level object.
256 | * @param {object} player The player object.
257 | * @param {number} tics The number of tics.
258 | */
259 | function process(game, tics) {
260 | var level = game.level,
261 | player = game.player,
262 | n, tex, guard,
263 | liveGuards = [];
264 |
265 | for (n = 0 ; n < level.state.numGuards ; ++n ) {
266 | guard = level.state.guards[n];
267 |
268 | if (!doGuard(guard, game, tics)) {
269 | // remove guard from the game forever!
270 | // remove(game, guards[n--]);
271 | Wolf.Sprites.remove(level, guard.sprite);
272 | level.state.guards[n] = null;
273 | continue;
274 | }
275 |
276 | Wolf.Sprites.setPos(level, guard.sprite, guard.x, guard.y, guard.angle);
277 |
278 | tex = Wolf.objstate[guard.type][guard.state].texture;
279 |
280 | if (Wolf.objstate[guard.type][guard.state].rotate) {
281 | if (guard.type == Wolf.en_rocket || guard.type == Wolf.en_hrocket) {
282 | tex += r_add8dir[Wolf.Math.get8dir( Wolf.Angle.distCW(Wolf.FINE2RAD(player.angle), Wolf.FINE2RAD(guard.angle)))];
283 | } else {
284 | tex += add8dir[Wolf.Math.get8dir( Wolf.Angle.distCW(Wolf.FINE2RAD(player.angle), Wolf.FINE2RAD(guard.angle)))];
285 | }
286 | }
287 | Wolf.Sprites.setTex(level, guard.sprite, 0, tex);
288 | }
289 |
290 | for (n = 0 ; n < level.state.numGuards ; ++n ) {
291 | if (level.state.guards[n]) {
292 | liveGuards.push(level.state.guards[n]);
293 | }
294 | }
295 | level.state.guards = liveGuards;
296 | level.state.numGuards = liveGuards.length;
297 | }
298 |
299 | /**
300 | * @description Reset and clear the enemy actors in the level.
301 | * @memberOf Wolf.Actors
302 | * @param {object} level The level object.
303 | */
304 | function resetGuards(level) {
305 | level.state.guards = [];
306 | level.state.numGuards = 0;
307 | //New = NULL;
308 | }
309 |
310 | /**
311 | * @description Spawn a new enemy actor at the given position.
312 | * @memberOf Wolf.Actors
313 | * @param {object} level The level object.
314 | * @param {number} skill The difficulty level.
315 | * @param {number} which The actor type.
316 | * @param {number} x The x position.
317 | * @param {number} y The y position.
318 | * @param {number} dir The direction.
319 | * @returns {object} The new actor object or null if actor creation failed.
320 | */
321 | function spawn(level, skill, which, x, y, dir) {
322 | var ent = getNewActor(level);
323 |
324 | if (!ent) {
325 | return null;
326 | }
327 |
328 | ent.x = Wolf.TILE2POS(x);
329 | ent.y = Wolf.TILE2POS(y);
330 |
331 | ent.tile.x = x;
332 | ent.tile.y = y;
333 |
334 | // assert( dir >= 0 && dir <= 4 );
335 | ent.angle = Wolf.Math.dir4angle[dir];
336 | ent.dir = Wolf.Math.dir4to8[dir];
337 |
338 | ent.areanumber = level.areas[x][y];
339 |
340 | if (ent.areanumber < 0) {
341 | // ambush marker tiles are listed as -3 area
342 | ent.areanumber = 0;
343 | }
344 |
345 | // assert( ent->areanumber >= 0 && ent->areanumber < NUMAREAS );
346 | ent.type = which;
347 | ent.health = Wolf.starthitpoints[skill][which];
348 | ent.sprite = Wolf.Sprites.getNewSprite(level);
349 |
350 | return ent;
351 | }
352 |
353 | /**
354 | * @description Spawn a dead guard.
355 | * @memberOf Wolf.Actors
356 | * @param {object} level The level object.
357 | * @param {number} skill The difficulty level.
358 | * @param {number} which The actor type.
359 | * @param {number} x The x position.
360 | * @param {number} y The y position.
361 | */
362 | function spawnDeadGuard(level, skill, which, x, y) {
363 | var self = spawn(level, skill, which, x, y, Wolf.Math.dir4_nodir);
364 | if (!self) {
365 | return;
366 | }
367 | self.state = Wolf.st_dead;
368 | self.speed = 0;
369 | self.health = 0;
370 | self.ticcount = Wolf.objstate[which][Wolf.st_dead].timeout ? Wolf.Random.rnd() % Wolf.objstate[which][Wolf.st_dead].timeout + 1 : 0;
371 | }
372 |
373 | /**
374 | * @description Spawn a patrolling guard.
375 | * @memberOf Wolf.Actors
376 | * @param {object} level The level object.
377 | * @param {number} skill The difficulty level.
378 | * @param {number} which The actor type.
379 | * @param {number} x The x position.
380 | * @param {number} y The y position.
381 | */
382 | function spawnPatrol(level, skill, which, x, y, dir) {
383 | var self = spawn(level, skill, which, x, y, dir);
384 | if (!self) {
385 | return;
386 | }
387 |
388 | self.state = Wolf.st_path1;
389 | self.speed = (which == Wolf.en_dog) ? Wolf.SPDDOG : Wolf.SPDPATROL;
390 | self.distance = Wolf.TILEGLOBAL;
391 | self.ticcount = Wolf.objstate[which][Wolf.st_path1].timeout ? Wolf.Random.rnd() % Wolf.objstate[which][Wolf.st_path1].timeout + 1 : 0;
392 | self.flags |= Wolf.FL_SHOOTABLE;
393 |
394 | level.state.totalMonsters++;
395 | }
396 |
397 | /**
398 | * @description Spawn a standing guard.
399 | * @memberOf Wolf.Actors
400 | * @param {object} level The level object.
401 | * @param {number} skill The difficulty level.
402 | * @param {number} which The actor type.
403 | * @param {number} x The x position.
404 | * @param {number} y The y position.
405 | */
406 | function spawnStand(level, skill, which, x, y, dir) {
407 | var self = spawn(level, skill, which, x, y, dir);
408 | if (!self) {
409 | return;
410 | }
411 |
412 | self.state = Wolf.st_stand;
413 | self.speed = Wolf.SPDPATROL;
414 | self.ticcount = Wolf.objstate[which][Wolf.st_stand].timeout ? Wolf.Random.rnd() % Wolf.objstate[which][Wolf.st_stand].timeout + 1 : 0;
415 | self.flags |= Wolf.FL_SHOOTABLE;
416 |
417 | if (level.tileMap[x][y] & Wolf.AMBUSH_TILE) {
418 | self.flags |= Wolf.FL_AMBUSH;
419 | }
420 |
421 | level.state.totalMonsters++;
422 | }
423 |
424 | function spawnBoss(level, skill, which, x, y) {
425 | var self,
426 | face;
427 |
428 | switch (which) {
429 | case Wolf.en_boss:
430 | case Wolf.en_schabbs:
431 | case Wolf.en_fat:
432 | case Wolf.en_hitler:
433 | face = Wolf.Math.dir4_south;
434 | break;
435 |
436 | case Wolf.en_fake:
437 | case Wolf.en_gretel:
438 | case Wolf.en_gift:
439 | face = Wolf.Math.dir4_north;
440 | break;
441 |
442 | case Wolf.en_trans:
443 | case Wolf.en_uber:
444 | case Wolf.en_will:
445 | case Wolf.en_death:
446 | case Wolf.en_angel:
447 | case Wolf.en_spectre:
448 | face = Wolf.Math.dir4_nodir;
449 | break;
450 |
451 | default:
452 | face = Wolf.Math.dir4_nodir;
453 | break;
454 | }
455 |
456 | self = spawn(level, skill, which, x, y, face);
457 | if (!self) {
458 | return;
459 | }
460 |
461 | self.state = which == Wolf.en_spectre ? Wolf.st_path1 : Wolf.st_stand;
462 | self.speed = Wolf.SPDPATROL;
463 | self.health = Wolf.starthitpoints[skill][which];
464 | self.ticcount = Wolf.objstate[which][Wolf.st_stand].timeout ? Wolf.Random.rnd() % Wolf.objstate[which][Wolf.st_stand].timeout + 1 : 0;
465 | self.flags |= Wolf.FL_SHOOTABLE | Wolf.FL_AMBUSH;
466 |
467 | level.state.totalMonsters++;
468 | }
469 |
470 |
471 | function spawnGhosts(level, skill, which, x, y) {
472 | var self = spawn(level, skill, which, x, y, Wolf.Math.dir4_nodir);
473 | if (!self) {
474 | return;
475 | }
476 |
477 | self.state = Wolf.st_chase1;
478 | self.speed = Wolf.SPDPATROL * 3;
479 | self.health = Wolf.starthitpoints[skill][which];
480 | self.ticcount = Wolf.objstate[which][Wolf.st_chase1].timeout ? Wolf.Random.rnd() % Wolf.objstate[which][Wolf.st_chase1].timeout + 1: 0;
481 | self.flags |= Wolf.FL_AMBUSH;
482 |
483 | level.state.totalMonsters++;
484 | }
485 |
486 | function spawnBJVictory(player, level, skill) {
487 | var x = Wolf.POS2TILE(player.position.x),
488 | y = Wolf.POS2TILE(player.position.y),
489 | bj = spawn(level, skill, Wolf.en_bj, x, y + 1, Wolf.Math.dir4_north);
490 |
491 | if (!bj) {
492 | return;
493 | }
494 |
495 | bj.x = player.position.x;
496 | bj.y = player.position.y;
497 | bj.state = Wolf.st_path1;
498 | bj.speed = Wolf.BJRUNSPEED;
499 | bj.flags = Wolf.FL_NONMARK; // FL_NEVERMARK;
500 | bj.temp2 = 6;
501 | bj.ticcount = 1;
502 | }
503 |
504 | return {
505 | process : process,
506 | resetGuards : resetGuards,
507 | getNewActor : getNewActor,
508 | spawn : spawn,
509 | spawnDeadGuard : spawnDeadGuard,
510 | spawnPatrol : spawnPatrol,
511 | spawnStand : spawnStand,
512 | spawnBoss : spawnBoss,
513 | spawnGhosts : spawnGhosts,
514 | spawnBJVictory : spawnBJVictory,
515 | stateChange : stateChange
516 | };
517 |
518 | })();
519 |
--------------------------------------------------------------------------------
/js/angle.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 |
28 | /**
29 | * @namespace
30 | * @description Angle math
31 | */
32 | Wolf.Angle = (function() {
33 |
34 | Wolf.setConsts({
35 | DEG2RAD : function(a) { return a * 0.01745329251994329576; }, // a * M_PI / 180.0f
36 | RAD2DEG : function(a) { return a / 0.01745329251994329576; }, // a * 180.0f / M_PI
37 | ANGLE2SHORT : function(x) { return ((x * 65536 / 360)>>0) & 65535; },
38 | SHORT2ANGLE : function(x) { return x * 360.0 / 65536; }
39 | });
40 |
41 | /**
42 | * @description Finds the difference between two angles.
43 | * @memberOf Wolf.Angle
44 | * @param {number} angle1 Angle in radians.
45 | * @param {number} angle2 Angle in radians.
46 | * @returns {number} The absolute difference between two angles, this will always be between 0 and 180 degrees.
47 | */
48 | function diff(angle1, angle2) {
49 | var d;
50 |
51 | if (angle1 > angle2) {
52 | d = angle1 - angle2;
53 | } else {
54 | d = angle2 - angle1;
55 | }
56 |
57 | if (d > Math.PI) {
58 | return 2 * Math.PI - d;
59 | } else {
60 | return d;
61 | }
62 | }
63 |
64 | /**
65 | * @description Clockwise distance between two angles.
66 | * @memberOf Wolf.Angle
67 | * @param {number} angle1 Angle in radians.
68 | * @param {number} angle2 Angle in radians.
69 | * @returns {number} The clockwise distance from angle2 to angle1, this may be greater than 180 degrees.
70 | */
71 | function distCW(angle1, angle2) {
72 | if (angle1 > angle2) {
73 | return angle1 - angle2;
74 | } else {
75 | return angle1 + 2 * Math.PI - angle2;
76 | }
77 | }
78 |
79 | /**
80 | * @description Linear interpolate between angle from and to by fraction frac.
81 | * @memberOf Wolf.Angle
82 | * @param {number} from Angle in radians.
83 | * @param {number} to Angle in radians.
84 | * @param {number} frac Fraction.
85 | * @returns {number}
86 | */
87 | function interpolate(from, to, frac) {
88 | var d = diff(from, to) * frac;
89 |
90 | if (distCW(to, from) >= Math.PI) {
91 | return from - diff;
92 | } else {
93 | return from + diff;
94 | }
95 | }
96 |
97 |
98 | /**
99 | * @description Normalize angle.
100 | * @memberOf Wolf.Angle
101 | * @param {number} angle
102 | * @returns {number}
103 | */
104 | function normalize(angle) {
105 | while (angle < 0) {
106 | angle += (2 * Math.PI);
107 | }
108 | while (angle >= (2 * Math.PI)) {
109 | angle -= (2 * Math.PI);
110 | }
111 | return angle;
112 | }
113 |
114 |
115 |
116 | /**
117 | * @description Linear interpolate allowing for the Modulo 360 problem.
118 | * @memberOf Wolf.Angle
119 | * @param {number} from Angle in radians.
120 | * @param {number} to Angle in radians.
121 | * @param {number} frac fraction.
122 | * @returns {number}
123 | */
124 |
125 | function lerp(from, to, frac) {
126 | if (to - from > 180) {
127 | to -= 360;
128 | }
129 | if (to - from < -180) {
130 | to += 360;
131 | }
132 | return from + frac * (to - from);
133 | }
134 |
135 | return {
136 | diff : diff,
137 | distCW : distCW,
138 | normalize : normalize,
139 | interpolate : interpolate,
140 | lerp : lerp
141 | }
142 |
143 | })();
--------------------------------------------------------------------------------
/js/areas.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 |
28 | /**
29 | * @namespace
30 | * @description Area management
31 | */
32 | Wolf.Areas = (function() {
33 | /*
34 | Notes:
35 |
36 | Open doors connect two areas, so sounds will travel between them and sight
37 | will be checked when the player is in a connected area.
38 |
39 | Areaconnect is incremented/decremented by each door. If >0 they connect.
40 |
41 | Every time a door opens or closes the areabyplayer matrix gets recalculated.
42 | An area is true if it connects with the player's current spor.
43 |
44 | */
45 |
46 | /**
47 | * @description Initialize areas
48 | * @memberOf Wolf.Areas
49 | * @param {object} levelState The level state object
50 | * @param {number} areanumber Initial area
51 | */
52 | function init(level, areanumber) {
53 | level.state.areaconnect = [];
54 | level.state.areabyplayer = [];
55 | for (var i=0;i= Wolf.NUMAREAS) {
91 | throw new Error("areanumber >= Wolf.NUMAREAS");
92 | }
93 |
94 | level.state.areabyplayer = [];
95 | level.state.areabyplayer[areanumber] = true;
96 |
97 | recursiveConnect(level, areanumber);
98 | for (i = 0; i < Wolf.NUMAREAS; i++) {
99 | if (level.state.areabyplayer[i]) {
100 | c++;
101 | }
102 | }
103 | }
104 |
105 | /**
106 | * @description Join ares
107 | * @memberOf Wolf.Areas
108 | * @param {object} level The level object
109 | * @param {number} area1 Area 1
110 | * @param {number} area2 Area 2
111 | */
112 | function join(level, area1, area2) {
113 | if (area1 < 0 || area1 >= Wolf.NUMAREAS) {
114 | throw new Error("area1 < 0 || area1 >= Wolf.NUMAREAS");
115 | }
116 | if (area2 < 0 || area2 >= Wolf.NUMAREAS) {
117 | throw new Error("area2 < 0 || area2 >= Wolf.NUMAREAS");
118 | }
119 | level.state.areaconnect[area1][area2]++;
120 | level.state.areaconnect[area2][area1]++;
121 | }
122 |
123 | /**
124 | * @description Disconnect ares
125 | * @memberOf Wolf.Areas
126 | * @param {object} level The level object
127 | * @param {number} area1 Area 1
128 | * @param {number} area2 Area 2
129 | */
130 | function disconnect(level, area1, area2) {
131 | if (area1 < 0 || area1 >= Wolf.NUMAREAS) {
132 | throw new Error("area1 < 0 || area1 >= Wolf.NUMAREAS");
133 | }
134 | if (area2 < 0 || area2 >= Wolf.NUMAREAS) {
135 | throw new Error("area2 < 0 || area2 >= Wolf.NUMAREAS");
136 | }
137 | level.state.areaconnect[area1][area2]--;
138 | level.state.areaconnect[area2][area1]--;
139 | }
140 |
141 | return {
142 | init : init,
143 | connect : connect,
144 | join : join,
145 | disconnect : disconnect
146 | };
147 |
148 | })();
149 |
150 |
--------------------------------------------------------------------------------
/js/doors.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 |
28 | /**
29 | * @namespace
30 | * @description Door management
31 | */
32 | Wolf.Doors = (function() {
33 |
34 | Wolf.setConsts({
35 | CLOSEWALL : Wolf.MINDIST, // Space between wall & player
36 | MAXDOORS : 64, // max number of sliding doors
37 |
38 | MAX_DOORS : 256, // jseidelin: doesn't look like this is used?
39 | DOOR_TIMEOUT : 300,
40 | DOOR_MINOPEN : 50,
41 | DOOR_FULLOPEN : 63,
42 | DOOR_VERT : 255,
43 | DOOR_HORIZ : 254,
44 | DOOR_E_VERT : 253,
45 | DOOR_E_HORIZ : 252,
46 | DOOR_G_VERT : 251,
47 | DOOR_G_HORIZ : 250,
48 | DOOR_S_VERT : 249,
49 | DOOR_S_HORIZ : 248,
50 | FIRST_DOOR : 248,
51 | LAST_LOCK : 251,
52 |
53 | TEX_DOOR : 98,
54 | // TEX_DOOR : 126,
55 |
56 | dr_closing : -1,
57 | dr_closed : 0,
58 | dr_opening : 1,
59 | dr_open : 2
60 | });
61 | Wolf.setConsts({
62 | // texture IDs used by cache routines
63 | TEX_DDOOR : (0 + Wolf.TEX_DOOR), // Simple Door
64 | TEX_PLATE : (2 + Wolf.TEX_DOOR), // Door Plate
65 | TEX_DELEV : (4 + Wolf.TEX_DOOR), // Elevator Door
66 | TEX_DLOCK : (6 + Wolf.TEX_DOOR) // Locked Door
67 | });
68 |
69 |
70 | /**
71 | * @description Reset doors in the level
72 | * @memberOf Wolf.Doors
73 | * @param {object} level The level object.
74 | */
75 | function reset(level) {
76 | level.state.numDoors = 0;
77 |
78 | for (var x=0;x<64;x++) {
79 | level.state.doorMap[x] = [];
80 | for (var y=0;y<64;y++) {
81 | level.state.doorMap[x][y] = 0;
82 | }
83 | }
84 | }
85 |
86 | /**
87 | * @description Spawn a door at the specified position.
88 | * @memberOf Wolf.Doors
89 | * @param {object} level The level object.
90 | * @param {number} x The x coordinate.
91 | * @param {number} y The y coordinate.
92 | * @param {number} type The door type.
93 | * @returns {number} The index of the new door.
94 | */
95 | function spawn(level, x, y, type) {
96 | if (level.state.numDoors >= Wolf.MAXDOORS) {
97 | throw new Error("Too many Doors on level!");
98 | }
99 | var door = level.state.doorMap[x][y] = {
100 | type : -1,
101 | vertical : 0,
102 | texture : -1,
103 | ticcount : 0
104 | };
105 |
106 | switch(type) {
107 | case 0x5A:
108 | door.type = Wolf.DOOR_VERT;
109 | door.vertical = true;
110 | door.texture = Wolf.TEX_DDOOR + 1;
111 | break;
112 | case 0x5B:
113 | door.type = Wolf.DOOR_HORIZ;
114 | door.vertical = false;
115 | door.texture = Wolf.TEX_DDOOR;
116 | break;
117 | case 0x5C:
118 | door.type = Wolf.DOOR_G_VERT;
119 | door.vertical = true;
120 | door.texture = Wolf.TEX_DLOCK;
121 | break;
122 | case 0x5D:
123 | door.type = Wolf.DOOR_G_HORIZ;
124 | door.vertical = false;
125 | door.texture = Wolf.TEX_DLOCK;
126 | break;
127 | case 0x5E:
128 | door.type = Wolf.DOOR_S_VERT;
129 | door.vertical = true;
130 | door.texture = Wolf.TEX_DLOCK + 1;
131 | break;
132 | case 0x5F:
133 | door.type = Wolf.DOOR_S_HORIZ;
134 | door.vertical = false;
135 | door.texture = Wolf.TEX_DLOCK + 1;
136 | break;
137 | case 0x64:
138 | door.type = Wolf.DOOR_E_VERT;
139 | door.vertical = true;
140 | door.texture = Wolf.TEX_DELEV + 1;
141 | break;
142 | case 0x65:
143 | door.type = Wolf.DOOR_E_HORIZ;
144 | door.vertical = false;
145 | door.texture = Wolf.TEX_DELEV;
146 | break;
147 | default:
148 | throw new Error("Unknown door type: " + type);
149 | }
150 |
151 | door.tile = {
152 | x : x,
153 | y : y
154 | };
155 | door.action = Wolf.dr_closed;
156 |
157 | level.state.doors[level.state.numDoors] = door;
158 | level.state.numDoors++;
159 |
160 | return level.state.numDoors - 1;
161 | }
162 |
163 | /**
164 | * @description Check to see if a door is open. If there are no doors in tile assume a closed door!
165 | * @memberOf Wolf.Doors
166 | * @param {object} doors The door object.
167 | * @returns {number} DOOR_FULLOPEN if door is opened,
168 | 0 if door is closed,
169 | >0 = Wolf.DOOR_FULLOPEN) { // door fully opened!
200 | door.action = Wolf.dr_open;
201 | door.ticcount = 0;
202 | } else { // opening!
203 | if (door.ticcount == 0) {
204 | // door is just starting to open, so connect the areas
205 | Wolf.Areas.join(level, door.area1, door.area2);
206 | Wolf.Areas.connect(level, player.areanumber);
207 |
208 | if (level.state.areabyplayer[door.area1]) { // Door Opening sound!
209 | Wolf.Sound.startSound(player.position, doorPos, 1, Wolf.CHAN_AUTO, "sfx/010.wav", 1, Wolf.ATTN_STATIC, 0);
210 | }
211 | }
212 |
213 | door.ticcount += tics;
214 |
215 | if (door.ticcount > Wolf.DOOR_FULLOPEN) {
216 | door.ticcount = Wolf.DOOR_FULLOPEN;
217 | }
218 | }
219 | break;
220 |
221 | case Wolf.dr_closing:
222 | if (door.ticcount <= 0) { // door fully closed! disconnect areas!
223 | Wolf.Areas.disconnect(level, door.area1, door.area2);
224 | Wolf.Areas.connect(level, player.areanumber);
225 | door.ticcount = 0;
226 | door.action = Wolf.dr_closed;
227 | } else { // closing!
228 | if (door.ticcount == Wolf.DOOR_FULLOPEN) {
229 | if (level.state.areabyplayer[door.area1]) { // Door Closing sound!
230 | Wolf.Sound.startSound(player.position, doorPos, 1, Wolf.CHAN_AUTO, "sfx/007.wav", 1, Wolf.ATTN_STATIC, 0);
231 | }
232 | }
233 | door.ticcount -= tics;
234 | if (door.ticcount < 0) {
235 | door.ticcount = 0;
236 | }
237 | }
238 | break;
239 |
240 | case Wolf.dr_open:
241 | if (door.ticcount > Wolf.DOOR_MINOPEN) {
242 | // If player or something is in door do not close it!
243 | if (!canCloseDoor(level, player, door.tile.x, door.tile.y, door.vertical)) {
244 | door.ticcount = Wolf.DOOR_MINOPEN; // do not close door immediately!
245 | }
246 | }
247 | if (door.ticcount >= Wolf.DOOR_TIMEOUT) {
248 | // Door timeout, time to close it!
249 | door.action = Wolf.dr_closing;
250 | door.ticcount = Wolf.DOOR_FULLOPEN;
251 | } else {
252 | // Increase timeout!
253 | door.ticcount += tics;
254 | }
255 | break;
256 | } // End switch lvldoors->Doors[ n ].action
257 | } // End for n = 0 ; n < lvldoors->numDoors ; ++n
258 | }
259 |
260 | /**
261 | * @description Set the areas doors in a level
262 | * @memberOf Wolf.Doors
263 | * @param {object} level The level object.
264 | * @param {array} areas The areas map.
265 | */
266 | function setAreas(level) {
267 | var n, x, y,
268 | door;
269 | for (n=0; n= 0 ? level.areas[x + 1][y] : 0;
276 | door.area2 = level.areas[x - 1][y] >= 0 ? level.areas[x - 1][y] : 0;
277 | } else {
278 | door.area1 = level.areas[x][y + 1] >= 0 ? level.areas[x][y + 1] : 0;
279 | door.area2 = level.areas[x][y - 1] >= 0 ? level.areas[x][y - 1] : 0;
280 | }
281 | }
282 | }
283 |
284 |
285 | /**
286 | * @description Open a door
287 | * @memberOf Wolf.Doors
288 | * @param {object} doors The door object.
289 | */
290 | function open(door) {
291 | if (door.action == Wolf.dr_open) {
292 | door.ticcount = 0; // reset opened time
293 | } else {
294 | door.action = Wolf.dr_opening; // start opening it
295 | }
296 | }
297 |
298 | /**
299 | * @description Change the state of a door
300 | * @private
301 | * @param {object} level The level object.
302 | * @param {object} player The player object.
303 | * @param {object} doors The door object.
304 | */
305 | function changeDoorState(level, player, door) {
306 | if (door.action < Wolf.dr_opening ) {
307 | open(door);
308 | } else if (door.action == Wolf.dr_open && canCloseDoor(level, player, door.tile.x, door.tile.y, door.vertical)) {
309 | // !@# for the iphone with automatic using, don't allow any door close actions
310 | // Door->action = dr_closing;
311 | // Door->ticcount = DOOR_FULLOPEN;
312 | }
313 | }
314 |
315 |
316 | function canCloseDoor(level, player, x, y, vert ) {
317 | var n,
318 | tileX = Wolf.POS2TILE(player.position.x),
319 | tileY = Wolf.POS2TILE(player.position.y),
320 | guard;
321 |
322 | if (tileX == x && tileY == y ) {
323 | return false;
324 | }
325 |
326 | if (vert) {
327 | if (tileY == y) {
328 | if (Wolf.POS2TILE(player.position.x + Wolf.CLOSEWALL) == x) {
329 | return false;
330 | }
331 | if (Wolf.POS2TILE(player.position.x - Wolf.CLOSEWALL) == x) {
332 | return false;
333 | }
334 | }
335 |
336 | for (n = 0; n.
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 |
28 | /**
29 | * @namespace
30 | * @description Episode data
31 | */
32 | Wolf.Episodes = [
33 | {
34 | name : "Escape from Wolfenstein",
35 | enabled : true,
36 | levels : [
37 | { file : "maps/w00.map", partime : 1.5 },
38 | { file : "maps/w01.map", partime : 2.0 },
39 | { file : "maps/w02.map", partime : 2.0 },
40 | { file : "maps/w03.map", partime : 3.5 },
41 | { file : "maps/w04.map", partime : 3.0 },
42 | { file : "maps/w05.map", partime : 3.0 },
43 | { file : "maps/w06.map", partime : 2.5 },
44 | { file : "maps/w07.map", partime : 2.5 },
45 | { file : "maps/w08.map", partime : 0.0 },
46 | { file : "maps/w09.map", partime : 0.0, secret : true }
47 | ]
48 | },{
49 | name : "Operation: Eisenfaust",
50 | enabled : true,
51 | levels : [
52 | { file : "maps/w10.map", partime : 1.5 },
53 | { file : "maps/w11.map", partime : 3.5 },
54 | { file : "maps/w12.map", partime : 3.0 },
55 | { file : "maps/w13.map", partime : 2.0 },
56 | { file : "maps/w14.map", partime : 4.0 },
57 | { file : "maps/w15.map", partime : 6.0 },
58 | { file : "maps/w16.map", partime : 1.0 },
59 | { file : "maps/w17.map", partime : 3.0 },
60 | { file : "maps/w18.map", partime : 0.0 },
61 | { file : "maps/w19.map", partime : 0.0, secret : true }
62 | ]
63 | },{
64 | name : "Die, Fuhrer, Die!",
65 | enabled : true,
66 | levels : [
67 | { file : "maps/w20.map", partime : 1.5 },
68 | { file : "maps/w21.map", partime : 1.5 },
69 | { file : "maps/w22.map", partime : 2.5 },
70 | { file : "maps/w23.map", partime : 2.5 },
71 | { file : "maps/w24.map", partime : 3.5 },
72 | { file : "maps/w25.map", partime : 2.5 },
73 | { file : "maps/w26.map", partime : 2.0 },
74 | { file : "maps/w27.map", partime : 6.0 },
75 | { file : "maps/w28.map", partime : 0.0 },
76 | { file : "maps/w29.map", partime : 0.0, secret : true }
77 | ]
78 | }
79 | ];
80 |
81 |
--------------------------------------------------------------------------------
/js/file.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 |
28 | /**
29 | * @namespace
30 | * @description Binary file reading
31 | */
32 | Wolf.File = (function() {
33 |
34 |
35 | /**
36 | * @description Open a file from URL
37 | * @memberOf Wolf.File
38 | * @param {string} url The URL to open
39 | * @param {function} callback Is called when file has been loaded. Second argument is file obj.
40 | */
41 | function openURL(url, callback) {
42 | var xhr = new XMLHttpRequest();
43 |
44 | xhr.onreadystatechange = function() {
45 | if (xhr.readyState == 4) {
46 | if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 0) {
47 | callback(null, {
48 | data : xhr.responseText,
49 | size : xhr.responseText.length,
50 | position : 0
51 | });
52 | } else {
53 | callback(new Error("Server returned HTTP status: " + xhr.status));
54 | }
55 | }
56 | }
57 | xhr.open("GET", url, true);
58 | xhr.overrideMimeType('text/plain; charset=x-user-defined');
59 | xhr.send(null);
60 | }
61 |
62 |
63 | function atob(str) {
64 | str = str.replace(/=+$/, "");
65 | var b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
66 | a, b, c, b1, b2, b3, b4,
67 | chr = String.fromCharCode,
68 | out = [];
69 | for (var i=0,len=str.length;i> 4) & 0x3);
76 | b = ((b2 & 0xF) << 4) | ((b3 >> 2) & 0xF);
77 | c = ((b3 & 0x3) << 6) | (b4 & 0x3F);
78 |
79 | out.push(chr(a), chr(b), chr(c));
80 | }
81 | return out.join("");
82 | }
83 |
84 | /**
85 | * @description Open a file from base64 filetable
86 | * @memberOf Wolf.File
87 | * @param {string} filename The name of the file to open
88 | * @param {object} files The filetable
89 | * @param {function} callback Is called when file has been loaded. Second argument is file obj.
90 | */
91 | function open(filename, files, callback) {
92 | var b64data = files[filename];
93 | if (b64data) {
94 | var data = atob(b64data);
95 | callback(null, {
96 | data : data,
97 | size : data.length,
98 | position : 0
99 | });
100 | } else {
101 | callback(new Error("File not found: " + filename));
102 | }
103 | }
104 |
105 | /**
106 | * @description Read an unsigned 8-bit integer from a file and advance the file position.
107 | * @memberOf Wolf.File
108 | * @param {object} f The file
109 | * @returns {number}
110 | */
111 | function readUInt8(f) {
112 | var b = f.data.charCodeAt(f.position) & 0xFF
113 | f.position++;
114 | return b;
115 | }
116 |
117 | /**
118 | * @description Read a signed 8-bit integer from a file and advance the file position.
119 | * @memberOf Wolf.File
120 | * @param {object} f The file
121 | * @returns {number}
122 | */
123 | function readInt8(f) {
124 | var v = readUInt8(f);
125 | return v > 127 ? v - 256 : v;
126 | }
127 |
128 | /**
129 | * @description Read an unsigned 16-bit integer from a file and advance the file position.
130 | * @memberOf Wolf.File
131 | * @param {object} f The file
132 | * @returns {number}
133 | */
134 | function readUInt16(f) {
135 | var v = readUInt8(f) + (readUInt8(f) << 8);
136 | return (v < 0) ? v + 0x10000 : v;
137 | }
138 |
139 | /**
140 | * @description Read a signed 16-bit integer from a file and advance the file position.
141 | * @memberOf Wolf.File
142 | * @param {object} f The file
143 | * @returns {number}
144 | */
145 | function readInt16(f) {
146 | var v = readUInt16(f);
147 | return (v > 0x7fff) ? v - 0x10000 : v;
148 | }
149 |
150 | /**
151 | * @description Read an unsigned 32-bit integer from a file and advance the file position.
152 | * @memberOf Wolf.File
153 | * @param {object} f The file
154 | * @returns {number}
155 | */
156 | function readUInt32(f) {
157 | var b0 = readUInt8(f),
158 | b1 = readUInt8(f),
159 | b2 = readUInt8(f),
160 | b3 = readUInt8(f),
161 | v = ((((b3 << 8) + b2) << 8) + b1 << 8) + b0;
162 | return (v < 0) ? v + 0x100000000 : v;
163 | }
164 |
165 | /**
166 | * @description Read a signed 32-bit int from a file and advance the file position.
167 | * @memberOf Wolf.File
168 | * @param {object} f The file
169 | * @returns {number}
170 | */
171 | function readInt32(f) {
172 | var v = readUInt32(f);
173 | return (v > 0x7fffffff) ? v - 0x100000000 : v;
174 | }
175 |
176 | /**
177 | * @description Read a string from a file and advance the file position.
178 | * @memberOf Wolf.File
179 | * @param {object} f The file
180 | * @param {number} length The length of the string
181 | * @returns {string}
182 | */
183 | function readString(f, length) {
184 | var str = f.data.substr(f.position, length);
185 | f.position += length;
186 | return str;
187 | }
188 |
189 | /**
190 | * @description Read an array of bytes a file and advance the file position.
191 | * @memberOf Wolf.File
192 | * @param {object} f The file
193 | * @param {number} num The number of bytes to read
194 | * @returns {array}
195 | */
196 | function readBytes(f, num) {
197 | var b = [];
198 | for (var i=0;i.
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 |
28 | /**
29 | * @namespace
30 | * @description Functions for capturing keyboard/mouse input
31 | */
32 | Wolf.Input = (function() {
33 |
34 | var keys,
35 | lmbDown = false,
36 | rmbDown = false,
37 | bindings = [],
38 | hasFocus = false,
39 | mouseX = -1, mouseY = -1,
40 | mouseMoveX = 0, mouseMoveY = 0;
41 |
42 | function init() {
43 | var game = $("#game"),
44 | main = $("#main"),
45 | renderer = $("#game .renderer");
46 |
47 | if (!keys) {
48 | keys = [];
49 |
50 | $(document)
51 | .on("keydown", function(e) {
52 | e.preventDefault();
53 |
54 | if (!Wolf.Game.isPlaying()) {
55 | return;
56 | }
57 |
58 | keys[e.keyCode] = true;
59 | if (bindings[e.keyCode]) {
60 | for (var i=0,n=bindings[e.keyCode].length;i 1 || mouseY < 0 || mouseY > 1) {
210 | return null;
211 | } else {
212 | return {
213 | x : (mouseX - 0.5) * 2,
214 | y : (mouseY - 0.5) * 2
215 | };
216 | }
217 | }
218 |
219 | function getMouseMovement() {
220 | var x = mouseMoveX,
221 | y = mouseMoveY;
222 | mouseMoveX = 0;
223 | mouseMoveY = 0;
224 | return {
225 | x : x / screen.width,
226 | y : y / screen.height
227 | };
228 | }
229 |
230 | function getPointer() {
231 | var pointer = navigator.pointer ||
232 | navigator.webkitPointer ||
233 | navigator.mozPointer ||
234 | navigator.msPointer ||
235 | navigator.oPointer;
236 | return pointer;
237 | }
238 |
239 | function isPointerLocked() {
240 | var pointer = getPointer();
241 | return pointer && pointer.isLocked && pointer.isLocked();
242 | }
243 |
244 | function lockPointer() {
245 | var pointer = getPointer();
246 | if (!pointer) {
247 | return;
248 | }
249 |
250 | if (Wolf.Game.isFullscreen()) {
251 | pointer.lock($("#game")[0],
252 | function(e) {
253 | Wolf.log("Pointer locked")
254 | }, function(e) {
255 | Wolf.log("Could not lock pointer: " + e);
256 | }
257 | );
258 | }
259 | }
260 |
261 | function unlockPointer() {
262 | var pointer = getPointer();
263 | if (!pointer) {
264 | return;
265 | }
266 | pointer.unlock($("#game")[0]);
267 | }
268 |
269 |
270 | return {
271 | init : init,
272 | reset : reset,
273 | resetMouse : resetMouse,
274 | checkKeys : checkKeys,
275 | clearKeys : clearKeys,
276 | bindKey : bindKey,
277 | leftMouseDown : leftMouseDown,
278 | rightMouseDown : rightMouseDown,
279 | getMouseCoords : getMouseCoords,
280 | getMouseMovement : getMouseMovement,
281 | isPointerLocked : isPointerLocked,
282 | lockPointer : lockPointer,
283 | unlockPointer : unlockPointer
284 | };
285 |
286 | })();
287 |
288 |
289 | Wolf.Keys = {
290 | LEFT : 37,
291 | UP : 38,
292 | RIGHT : 39,
293 | DOWN : 40,
294 | ENTER : 13,
295 | SPACE : 32,
296 | SHIFT : 16,
297 | CTRL : 17,
298 | ALT : 18,
299 | ESC : 27,
300 | HOME : 36,
301 | END : 35,
302 | DEL : 46,
303 | INS : 45,
304 | PGUP : 33,
305 | PGDN : 34,
306 | SLASH : 111,
307 | MINUS : 109,
308 | PLUS : 107,
309 | COMMA : 188,
310 | PERIOD : 190,
311 | 1 : 49,
312 | 2 : 50,
313 | 3 : 51,
314 | 4 : 52,
315 | 5 : 53,
316 | 6 : 54,
317 | 7 : 55,
318 | 8 : 56,
319 | 9 : 57,
320 | 0 : 58,
321 | A : 65,
322 | B : 66,
323 | C : 67,
324 | D : 68,
325 | E : 69,
326 | F : 70,
327 | G : 71,
328 | H : 72,
329 | I : 73,
330 | J : 74,
331 | K : 75,
332 | L : 76,
333 | M : 77,
334 | N : 78,
335 | O : 79,
336 | P : 80,
337 | Q : 81,
338 | R : 82,
339 | S : 83,
340 | T : 84,
341 | U : 85,
342 | V : 86,
343 | W : 87,
344 | X : 88,
345 | Y : 89,
346 | Z : 90,
347 | F1 : 112,
348 | F2 : 113,
349 | F3 : 114,
350 | F4 : 115,
351 | F5 : 116,
352 | F6 : 117,
353 | F7 : 118,
354 | F8 : 119,
355 | F9 : 120,
356 | F10 : 121,
357 | F11 : 122,
358 | F12 : 123
359 | };
--------------------------------------------------------------------------------
/js/load.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 |
28 | (function($) {
29 |
30 | // these files are preloaded while the title screen is showing
31 | var files = [
32 | "js/requestanimframe.js",
33 |
34 | "js/wolf.js",
35 | "js/random.js",
36 | "js/angle.js",
37 | "js/math.js",
38 | "js/input.js",
39 | "js/sound.js",
40 | "js/menu.js",
41 | "js/file.js",
42 | "js/game.js",
43 | "js/player.js",
44 | "js/sprites.js",
45 | "js/powerups.js",
46 | "js/ai.js",
47 | "js/actorai.js",
48 | "js/actors.js",
49 | "js/actstat.js",
50 | "js/weapon.js",
51 | "js/doors.js",
52 | "js/pushwall.js",
53 | "js/areas.js",
54 | "js/level.js",
55 | "js/raycaster.js",
56 | "js/renderer.js",
57 |
58 | "js/episodes.js",
59 | "js/maps.js",
60 |
61 | "preload!art/menubg_main.png",
62 | "preload!art/menuitems.png",
63 | "preload!art/menuselector.png"
64 |
65 | ];
66 |
67 | // these files are preloaded in the background after the menu is displayed.
68 | // only non-essential files here
69 | var files2 = [
70 | "preload!art/menubg_episodes.png",
71 | "preload!art/menuitems_episodes.png",
72 | "preload!art/menubg_skill.png",
73 | "preload!art/menubg_levels.png",
74 | "preload!art/menuitems_levels.png",
75 | "preload!art/skillfaces.png",
76 | "preload!art/getpsyched.png",
77 | "preload!art/menubg_control.png",
78 | "preload!art/menulight.png",
79 | "preload!art/menubg_customize.png",
80 | "preload!art/control_keys.png",
81 | "preload!art/confirm_newgame.png",
82 | "preload!art/paused.png"
83 | ];
84 |
85 | $(document).ready(function() {
86 |
87 | var progress = $("
"),
88 | n = 0;
89 |
90 | progress.addClass("load-progress").appendTo("#title-screen");
91 | $("#title-screen").show();
92 |
93 |
94 | yepnope.addPrefix("preload", function(resource) {
95 | resource.noexec = true;
96 | resource.instead = function(input, callback) {
97 | var image = new Image();
98 | image.onload = callback;
99 | image.onerror = callback;
100 | image.src = input.substr(input.lastIndexOf("!")+1);
101 | };
102 | return resource;
103 | });
104 |
105 |
106 | Modernizr.load([
107 | {
108 | load : files,
109 | callback : function(file) {
110 | progress.width((++n / files.length) * 100 + "%");
111 | },
112 | complete : function() {
113 | progress.remove();
114 | $("#title-screen").fadeOut(1500, function() {
115 | Wolf.Input.init();
116 | Wolf.Game.init();
117 | Wolf.Menu.show();
118 | });
119 | // preload non-essential art
120 | Modernizr.load(files2);
121 | }
122 | }
123 | ]);
124 | });
125 |
126 | })(jQuery);
--------------------------------------------------------------------------------
/js/maps.sample.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 | /**
28 | * @description Encoded map file data (Example)
29 | *
30 | * This file is a table of base64 encoded map data.
31 | * Note: No actual data is included in this release.
32 | */
33 |
34 | Wolf.MapData = {
35 | "maps/w00.map" : "... base64 encoded map file data here ...",
36 | "maps/w01.map" : "... base64 encoded map file data here ..."
37 | };
38 |
--------------------------------------------------------------------------------
/js/math.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 | /**
28 | * @namespace
29 | * @description Math functions and lookup tables
30 | */
31 | Wolf.Math = (function() {
32 |
33 | // ------------------------- * LUTs * -------------------------
34 | var SinTable = [], // [ ANG_360 + ANG_90 + 1 ],
35 | CosTable = [], // SinTable + ANG_90,
36 | TanTable = [], //[ ANG_360 + 1 ];
37 |
38 | XnextTable = [], //[ ANG_360 + 1 ],
39 | YnextTable = [], //[ ANG_360 + 1 ],
40 |
41 | ColumnAngle = [], // [ 640 ]; // ViewAngle=PlayerAngle+ColumnAngle[curcolumn]; /in fines/
42 |
43 | // Angle Direction Types & LUTs (Hard Coded! Please do not mess them)
44 | q_first = 0, q_second = 1, q_third = 2, q_fourth = 3, // quadrant;
45 | dir4_east = 0, dir4_north = 1, dir4_west = 2, dir4_south = 3, dir4_nodir = 4, // dir4type;
46 |
47 | dir8_east = 0, dir8_northeast = 1, dir8_north = 2, dir8_northwest = 3, dir8_west = 4,
48 | dir8_southwest = 5, dir8_south = 6, dir8_southeast = 7, dir8_nodir = 8, // dir8type;
49 |
50 | dx4dir = [1, 0, -1, 0, 0], // dx & dy based on direction
51 | dy4dir = [0, 1, 0, -1, 0],
52 | dx8dir = [1, 1, 0, -1, -1, -1, 0, 1, 0], // dx & dy based on direction
53 | dy8dir = [0, 1, 1, 1, 0, -1, -1, -1, 0],
54 | opposite4 = [2, 3, 0, 1, 4],
55 | opposite8 = [4, 5, 6, 7, 0, 1, 2, 3, 8],
56 | dir4to8 = [0, 2, 4, 6, 8],
57 | diagonal = [
58 | /* east */ [dir8_nodir, dir8_nodir, dir8_northeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southeast, dir8_nodir, dir8_nodir],
59 | [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
60 | /* north */ [dir8_northeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_northwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
61 | [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
62 | /* west */ [dir8_nodir, dir8_nodir, dir8_northwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southwest, dir8_nodir, dir8_nodir],
63 | [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
64 | /* south */ [dir8_southeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
65 | [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
66 | [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir]
67 | ],
68 |
69 | // dir of delta tooks dx{-1|0|1}+1 & dy{-1|0|1}+1 and give direction
70 | dir4d = [
71 | [dir4_nodir, dir4_west , dir4_nodir],
72 | [dir4_south, dir4_nodir, dir4_north],
73 | [dir4_nodir, dir4_east , dir4_nodir]
74 | ],
75 | dir8angle = [Wolf.ANG_0, Wolf.ANG_45, Wolf.ANG_90, Wolf.ANG_135, Wolf.ANG_180, Wolf.ANG_225, Wolf.ANG_270, Wolf.ANG_315, Wolf.ANG_0];
76 | dir4angle = [Wolf.ANG_0, Wolf.ANG_90, Wolf.ANG_180, Wolf.ANG_270, Wolf.ANG_0];
77 |
78 |
79 | /**
80 | * @private
81 | * @description Build LUTs, etc.
82 | */
83 | function buildTables() {
84 | var angle, tanfov2, tanval, value,
85 | n;
86 |
87 | for (n = 0; n <= Wolf.ANG_90 ; ++n) {
88 | angle = Wolf.FINE2RAD(n);
89 | value = Math.sin(angle);
90 | SinTable[n] = SinTable[Wolf.ANG_180 - n] = SinTable[n + Wolf.ANG_360] = value;
91 | SinTable[Wolf.ANG_180 + n] = SinTable[Wolf.ANG_360 - n] = -value;
92 | }
93 |
94 | for (n = 0; n <= SinTable.length - Wolf.ANG_90; ++n) {
95 | CosTable[n] = SinTable[n + Wolf.ANG_90];
96 | }
97 |
98 | for (n = 0; n <= Wolf.ANG_360 ; ++n) {
99 | angle = Wolf.FINE2RAD(n); //angle is in radians, n is in FINEs
100 |
101 | if (n == Wolf.ANG_90 || n == Wolf.ANG_270) {
102 | TanTable[n] = Math.tan(Wolf.FINE2RAD(n - 0.5)); // infinity
103 | YnextTable[n] = (Wolf.FLOATTILE * Math.tan(Wolf.FINE2RAD(n - 0.5)))>>0; // infinity
104 | } else {
105 | TanTable[n] = Math.tan(angle);
106 | YnextTable[n] = (Wolf.FLOATTILE * Math.tan(angle))>>0;
107 | }
108 |
109 | if(n == Wolf.ANG_0 || n == Wolf.ANG_360) {
110 | XnextTable[n] = (Wolf.FLOATTILE / Math.tan(Wolf.FINE2RAD(n + 0.5)))>>0; // infinity
111 | } else if (n == Wolf.ANG_180) {
112 | XnextTable[n] = (Wolf.FLOATTILE / Math.tan(Wolf.FINE2RAD(n - 0.5)))>>0; // -infinity
113 | } else if (n == Wolf.ANG_90 || n == Wolf.ANG_270) {
114 | XnextTable[n] = 0;
115 | } else {
116 | XnextTable[n] = (Wolf.FLOATTILE / Math.tan(angle))>>0;
117 | }
118 | }
119 |
120 | tanfov2 = (Math.tan(Wolf.DEG2RAD((calcFov(75, Wolf.XRES, Wolf.YRES) / 2.0)))) * (Wolf.XRES / Wolf.YRES);
121 | for (n = 0; n < Wolf.XRES; ++n) {
122 | tanval = tanfov2 * (-1.0 + 2.0 * n / (Wolf.XRES-1));
123 | ColumnAngle[n] = Wolf.RAD2FINE(Math.atan(tanval)) >> 0;
124 | }
125 |
126 | Wolf.Random.init(1); // random number generators
127 |
128 | return 1;
129 | }
130 |
131 |
132 | /**
133 | * @description Calculate the field of view.
134 | * @memberOf Wolf.Math
135 | * @param {number} fovX Must be within 1 and 179 degrees.
136 | * @param {number} width Width of viewing area.
137 | * @param {number} height Height of viewing area.
138 | * @returns {number} The field of view in degrees.
139 | */
140 |
141 | function calcFov(fovX, width, height) {
142 | if (fovX < 1 || fovX > 179) {
143 | throw Error("Bad fov: " + fovX );
144 | }
145 |
146 | return Wolf.RAD2DEG(Math.atan(height / (width / Math.tan(fovX / 360 * Math.PI)))) * 2;
147 | }
148 |
149 |
150 | /**
151 | * @description Clips angle to [0..360] bounds.
152 | * @memberOf Wolf.Math
153 | * @param {number} alpha Angle in degrees.
154 | * @returns {number} Normalized angle.
155 | */
156 | function normalizeAngle(alpha) {
157 | if (alpha > Wolf.ANG_360) {
158 | alpha %= Wolf.ANG_360;
159 | }
160 | if (alpha < Wolf.ANG_0) {
161 | alpha = Wolf.ANG_360 - (-alpha) % Wolf.ANG_360;
162 | }
163 | return alpha;
164 | }
165 |
166 |
167 | /**
168 | * @description Get quadrant.
169 | * @memberOf Wolf.Math
170 | * @param {number} angle Radian angle.
171 | * @returns {number}
172 | */
173 | function getQuadrant(angle) {
174 | angle = Wolf.Angle.normalize(angle);
175 |
176 | if (angle < Math.PI / 2) {
177 | return q_first;
178 | } else if (angle < Math.PI) {
179 | return q_second;
180 | } else if (angle < 3 * Math.PI / 2) {
181 | return q_third;
182 | } else {
183 | return q_fourth;
184 | }
185 | }
186 |
187 | /**
188 | * @description Get 4 point direction.
189 | * @memberOf Wolf.Math
190 | * @param {number} angle Radian angle.
191 | * @returns {number} Directional point.
192 | */
193 | function get4dir(angle) {
194 | angle = Wolf.Angle.normalize(angle + Math.PI / 4);
195 |
196 | if (angle < Math.PI / 2) {
197 | return dir4_east;
198 | } else if( angle < Math.PI ) {
199 | return dir4_north;
200 | } else if( angle < 3 * Math.PI / 2 ) {
201 | return dir4_west;
202 | } else {
203 | return dir4_south;
204 | }
205 | }
206 |
207 | /**
208 | * @description Get 8 point direction.
209 | * @memberOf Wolf.Math
210 | * @param {number} angle Radian angle.
211 | * @returns {number} Directional point.
212 | */
213 | function get8dir(angle) {
214 | angle = Wolf.Angle.normalize(angle + Math.PI / 12);
215 |
216 | if ( angle <= (Math.PI / 4)) {
217 | return dir8_east;
218 | } else if (angle < (Math.PI / 2)) {
219 | return dir8_northeast;
220 | } else if (angle <= (3 * Math.PI / 4)) {
221 | return dir8_north;
222 | } else if (angle < Math.PI) {
223 | return dir8_northwest;
224 | } else if (angle <= (5 * Math.PI / 4)) {
225 | return dir8_west;
226 | } else if (angle < (3 * Math.PI / 2)) {
227 | return dir8_southwest;
228 | } else if (angle <= (7 * Math.PI / 4)) {
229 | return dir8_south;
230 | } else {
231 | return dir8_southeast;
232 | }
233 | }
234 |
235 | /**
236 | * @description calculates distance between a point (x, y) and a line.
237 | * @memberOf Wolf.Math
238 | * @param {number} x X coord of point
239 | * @param {number} y Y coord of point
240 | * @param {number} a Line angle in degrees
241 | * @returns {number} Distance
242 | */
243 | function point2LineDist(x, y, a) {
244 | return Math.abs( (x * SinTable[a] - y * CosTable[a]) >> 0);
245 | }
246 |
247 |
248 |
249 | /**
250 | * @description Calculates line length to the point nearest to (poin).
251 | * @memberOf Wolf.Math
252 | * @param {number} x X coord of point
253 | * @param {number} y Y coord of point
254 | * @param {number} a Line angle in degrees
255 | * @returns {number} Distance
256 | */
257 | function lineLen2Point( x, y, a) {
258 | return (x * CosTable[a] + y * SinTable[a]) >> 0;
259 | }
260 |
261 |
262 | /*
263 | point2 = {x,y}
264 | / |
265 | / |
266 | / |
267 | /a______|----------> x
268 | point1 = {x, y}
269 | */
270 | /**
271 | * @description Returns angle in radians
272 | * @memberOf Wolf.Math
273 | * @param {number} x X coord of point
274 | * @param {number} y Y coord of point
275 | * @param {number} a Line angle in degrees
276 | * @returns {number} Distance
277 | */
278 | function transformPoint(point1X, point1Y, point2X, point2Y) {
279 | var angle = Math.atan2(point1Y - point2Y, point1X - point2X);
280 | return Wolf.Angle.normalize(angle);
281 | }
282 |
283 |
284 | buildTables();
285 |
286 | return {
287 | calcFov : calcFov,
288 | normalizeAngle : normalizeAngle,
289 | getQuadrant : getQuadrant,
290 | get4dir : get4dir,
291 | get8dir : get8dir,
292 | point2LineDist : point2LineDist,
293 | lineLen2Point : lineLen2Point,
294 | transformPoint : transformPoint,
295 |
296 | SinTable : SinTable,
297 | CosTable : CosTable,
298 | TanTable : TanTable,
299 | XnextTable : XnextTable,
300 | YnextTable : YnextTable,
301 | ColumnAngle : ColumnAngle,
302 |
303 | dir4_east : dir4_east,
304 | dir4_north : dir4_north,
305 | dir4_west : dir4_west,
306 | dir4_south : dir4_south,
307 | dir4_nodir : dir4_nodir,
308 | dir8_east : dir8_east,
309 | dir8_northeast : dir8_northeast,
310 | dir8_north : dir8_north,
311 | dir8_northwest : dir8_northwest,
312 | dir8_west : dir8_west,
313 | dir8_southwest : dir8_southwest,
314 | dir8_south : dir8_south,
315 | dir8_southeast : dir8_southeast,
316 | dir8_nodir : dir8_nodir,
317 | dx4dir : dx4dir,
318 | dy4dir : dy4dir,
319 | dx8dir : dx8dir,
320 | dy8dir : dy8dir,
321 | dir4angle : dir4angle,
322 | dir8angle : dir8angle,
323 | dir4to8 : dir4to8,
324 | opposite4 : opposite4,
325 | opposite8 : opposite8,
326 | diagonal : diagonal
327 | };
328 |
329 | })();
--------------------------------------------------------------------------------
/js/menu.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 | /**
28 | * @namespace
29 | * @description Game menu management
30 | */
31 | Wolf.Menu = (function() {
32 | var setupDone = false,
33 | menuInputActive = false,
34 | activeIndex = 0,
35 | activeMouseItem = null,
36 | activeEpisode,
37 | messageBlink,
38 | activeMessage,
39 | activeSkill;
40 |
41 | var keySprites = {},
42 | i,
43 | keySpriteNames = [
44 | "BLANK",
45 | "QUESTION",
46 | "SHIFT",
47 | "SPACE",
48 | "CTRL",
49 | "LEFT",
50 | "RIGHT",
51 | "UP",
52 | "DOWN",
53 | "ENTER",
54 | "DEL",
55 | "PGUP",
56 | "PGDN",
57 | "INS",
58 | "SLASH",
59 | "HOME",
60 | "COMMA",
61 | "PERIOD",
62 | "PLUS",
63 | "MINUS",
64 | "0",
65 | "1",
66 | "2",
67 | "3",
68 | "4",
69 | "5",
70 | "6",
71 | "7",
72 | "8",
73 | "9",
74 | "A",
75 | "B",
76 | "C",
77 | "D",
78 | "E",
79 | "F",
80 | "G",
81 | "H",
82 | "I",
83 | "J",
84 | "K",
85 | "L",
86 | "M",
87 | "N",
88 | "O",
89 | "P",
90 | "Q",
91 | "R",
92 | "S",
93 | "T",
94 | "U",
95 | "V",
96 | "W",
97 | "X",
98 | "Y",
99 | "Z"
100 | ];
101 |
102 | for (i=0;i.
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 |
28 | Wolf.Powerups = (function() {
29 |
30 | Wolf.setConsts({
31 | pow_gibs : 0, // 1% if <=10%; SLURPIESND
32 | pow_gibs2 : 1, // 1% if <=10%; SLURPIESND
33 | pow_alpo : 2, // 4% if <100%; HEALTH1SND
34 | pow_firstaid : 3, // 25% if <100%; HEALTH2SND
35 | pow_key1 : 4, // gold key; GETKEYSND
36 | pow_key2 : 5, // silver key; GETKEYSND
37 | pow_key3 : 6, // not used
38 | pow_key4 : 7, // not used
39 | pow_cross : 8, // 100pts; BONUS1SND
40 | pow_chalice : 9, // 500pts; BONUS2SND
41 | pow_bible : 10, // 1000pts; BONUS3SND
42 | pow_crown : 11, // 5000pts; BONUS4SND
43 | pow_clip : 12, // 8bul if <99bul; GETAMMOSND
44 | pow_clip2 : 13, // 4bul if <99bul; GETAMMOSND
45 | pow_machinegun : 14, // machine gun; GETMACHINESND
46 | pow_chaingun : 15, // gatling gun; GETGATLINGSND
47 | pow_food : 16, // 10% if <100%; HEALTH1SND
48 | pow_fullheal : 17, // 99%, 25bul; BONUS1UPSND
49 | pow_25clip : 18, // 25bul if <99bul; GETAMMOBOXSND
50 | pow_spear : 19, // spear of destiny!
51 | pow_last : 20
52 | // add new types here (after last)
53 | });
54 |
55 | var texture = [
56 | Wolf.SPR_STAT_34, // pow_gibs
57 | Wolf.SPR_STAT_38, // pow_gibs2
58 | Wolf.SPR_STAT_6, // pow_alpo
59 | Wolf.SPR_STAT_25, // pow_firstaid
60 | Wolf.SPR_STAT_20, // pow_key1
61 | Wolf.SPR_STAT_21, // pow_key2
62 | // not used
63 | Wolf.SPR_STAT_20, // pow_key3
64 | Wolf.SPR_STAT_20, // pow_key4
65 |
66 | Wolf.SPR_STAT_29, // pow_cross
67 | Wolf.SPR_STAT_30, // pow_chalice
68 | Wolf.SPR_STAT_31, // pow_bible
69 | Wolf.SPR_STAT_32, // pow_crown
70 | Wolf.SPR_STAT_26, // pow_clip
71 | Wolf.SPR_STAT_26, // pow_clip2
72 | Wolf.SPR_STAT_27, // pow_machinegun
73 | Wolf.SPR_STAT_28, // pow_chaingun
74 | Wolf.SPR_STAT_24, // pow_food
75 | Wolf.SPR_STAT_33, // pow_fullheal
76 | // spear
77 | Wolf.SPR_STAT_49, // pow_25clip
78 | Wolf.SPR_STAT_51 // pow_spear
79 | ];
80 |
81 |
82 | function remove(level, powerup) {
83 | powerup.x = -1;
84 | powerup.y = -1;
85 | }
86 |
87 | function addNew(level) {
88 | /*
89 | for (var i = 0;i < level.state.numPowerups; i++ ) {
90 | if (level.state.powerups[i].x == -1 ) {
91 | return level.state.powerups[i];
92 | }
93 | }
94 | */
95 | /*
96 | if (level.state.numPowerups == Wolf.MAX_POWERUPS ) {
97 | return level.state.powerups[0];
98 | }
99 | */
100 | level.state.numPowerups++;
101 |
102 | var newp = {
103 | x : -1,
104 | y : -1,
105 | type : 0,
106 | sprite : null
107 | };
108 |
109 | level.state.powerups[level.state.numPowerups-1] = newp;
110 |
111 | return newp;
112 | }
113 |
114 | function reset(level) {
115 | level.state.numPowerups = 0;
116 | level.state.powerups = [];
117 | }
118 |
119 | // x,y are in TILES.
120 | function spawn(level, x, y, type) {
121 | var newp = addNew(level);
122 |
123 | newp.sprite = Wolf.Sprites.getNewSprite(level);
124 | newp.type = type;
125 |
126 | Wolf.Sprites.setPos(level, newp.sprite, Wolf.TILE2POS(newp.x = x), Wolf.TILE2POS(newp.y = y), 0);
127 |
128 | Wolf.Sprites.setTex(level, newp.sprite, -1, texture[type]);
129 |
130 | level.tileMap[x][y] |= Wolf.POWERUP_TILE;
131 | // good place to update total treasure count!
132 | }
133 |
134 |
135 | function give(level, player, type) {
136 | var keynames = ["Gold", "Silver", "?", "?"];
137 |
138 | switch (type) {
139 | // Keys
140 | case Wolf.pow_key1:
141 | case Wolf.pow_key2:
142 | case Wolf.pow_key3:
143 | case Wolf.pow_key4:
144 | type -= Wolf.pow_key1;
145 | Wolf.Player.giveKey(player, type);
146 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/012.wav", 1, Wolf.ATTN_NORM, 0);
147 | Wolf.Game.notify(keynames[type] + " key");
148 | break;
149 | // Treasure
150 | case Wolf.pow_cross:
151 | Wolf.Player.givePoints(player, 100);
152 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/035.wav", 1, Wolf.ATTN_NORM, 0);
153 | if ( ++level.state.foundTreasure == level.state.totalTreasure ) {
154 | Wolf.Game.notify("You found the last treasure!");
155 | }
156 | break;
157 |
158 | case Wolf.pow_chalice:
159 | Wolf.Player.givePoints(player, 500);
160 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/036.wav", 1, Wolf.ATTN_NORM, 0);
161 | if (++level.state.foundTreasure == level.state.totalTreasure) {
162 | Wolf.Game.notify("You found the last treasure!");
163 | }
164 | break;
165 |
166 | case Wolf.pow_bible:
167 | Wolf.Player.givePoints(player, 1000);
168 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/037.wav", 1, Wolf.ATTN_NORM, 0);
169 | if (++level.state.foundTreasure == level.state.totalTreasure) {
170 | Wolf.Game.notify("You found the last treasure!");
171 | }
172 | break;
173 |
174 | case Wolf.pow_crown:
175 | Wolf.Player.givePoints(player, 5000);
176 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/045.wav", 1, Wolf.ATTN_NORM, 0);
177 | if (++level.state.foundTreasure == level.state.totalTreasure) {
178 | Wolf.Game.notify("You found the last treasure!");
179 | }
180 | break;
181 |
182 | // Health
183 | case Wolf.pow_gibs:
184 | if (!Wolf.Player.giveHealth(player, 1, 11)) {
185 | return false;
186 | }
187 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/061.wav", 1, Wolf.ATTN_NORM, 0);
188 | break;
189 |
190 | case Wolf.pow_alpo:
191 | if (!Wolf.Player.giveHealth(player, 4, 0)) {
192 | return false;
193 | }
194 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/033.wav", 1, Wolf.ATTN_NORM, 0);
195 | break;
196 |
197 | case Wolf.pow_food:
198 | if (!Wolf.Player.giveHealth(player, 10, 0)) {
199 | return false;
200 | }
201 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/033.wav", 1, Wolf.ATTN_NORM, 0);
202 | break;
203 |
204 | case Wolf.pow_firstaid:
205 | if (!Wolf.Player.giveHealth(player, 25, 0)) {
206 | return false;
207 | }
208 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/034.wav", 1, Wolf.ATTN_NORM, 0);
209 | break;
210 |
211 | // Weapon & Ammo
212 | case Wolf.pow_clip:
213 | if (!Wolf.Player.giveAmmo(player, Wolf.AMMO_BULLETS, 8)) {
214 | return false;
215 | }
216 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/031.wav", 1, Wolf.ATTN_NORM, 0);
217 | break;
218 |
219 | case Wolf.pow_clip2:
220 | if (!Wolf.Player.giveAmmo(player, Wolf.AMMO_BULLETS, 4)) {
221 | return false;
222 | }
223 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/031.wav", 1, Wolf.ATTN_NORM, 0);
224 | break;
225 |
226 | case Wolf.pow_25clip:
227 | if (!Wolf.Player.giveAmmo(player, Wolf.AMMO_BULLETS, 25)) {
228 | return false;
229 | }
230 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/031.wav", 1, Wolf.ATTN_NORM, 0);
231 | break;
232 |
233 | case Wolf.pow_machinegun:
234 | Wolf.Player.giveWeapon(player, Wolf.WEAPON_AUTO );
235 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/030.wav", 1, Wolf.ATTN_NORM, 0);
236 | Wolf.Game.notify("Machinegun");
237 | break;
238 |
239 | case Wolf.pow_chaingun:
240 | Wolf.Player.giveWeapon(player, Wolf.WEAPON_CHAIN );
241 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/038.wav", 1, Wolf.ATTN_NORM, 0);
242 | Wolf.Game.notify("Chaingun");
243 |
244 | player.faceCount = -100;
245 | player.faceGotGun = true;
246 | break;
247 |
248 | // Artifacts
249 | case Wolf.pow_fullheal:
250 | // go to 150 health
251 | Wolf.Player.giveHealth(player, 99, 99 );
252 | Wolf.Player.giveAmmo(player, Wolf.AMMO_BULLETS, 25 );
253 | Wolf.Player.giveLife(player);
254 | if (++level.state.foundTreasure == level.state.totalTreasure) {
255 | Wolf.Game.notify("You found the last treasure!");
256 | } else {
257 | Wolf.Game.notify("Full Heal");
258 | }
259 | Wolf.Sound.startSound(null, null, 0, Wolf.CHAN_ITEM, "lsfx/034.wav", 1, Wolf.ATTN_NORM, 0);
260 | Wolf.log("Extra life!");
261 | break;
262 |
263 | default:
264 | Wolf.log("Warning: Unknown item type: " + type);
265 | break;
266 | }
267 |
268 | Wolf.Game.startBonusFlash();
269 |
270 | return true;
271 | }
272 |
273 | // x,y are in TILES.
274 | function pickUp(level, player, x, y) {
275 | var i, pow,
276 | p_left = false,
277 | p_pick = false;
278 |
279 | for (i=0; i.
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 | /**
28 | * @namespace
29 | * @description Push wall management
30 | */
31 | Wolf.PushWall = (function() {
32 |
33 | var PWall = {};
34 | reset();
35 |
36 | function reset() {
37 | PWall.active = false;
38 | PWall.tilesMoved = 0;
39 | PWall.pointsMoved = 0;
40 | PWall.dir = 0;
41 | PWall.x = 0;
42 | PWall.y = 0;
43 | PWall.dx = 0;
44 | PWall.dy = 0;
45 | PWall.texX = 0;
46 | PWall.texY = 0;
47 | }
48 |
49 |
50 | function push(level, x, y, dir) {
51 | var dx, dy;
52 |
53 | if (PWall.active) {
54 | return false; // another PWall is moving [only one at a time!]
55 | }
56 |
57 | dx = Wolf.Math.dx4dir[dir];
58 | dy = Wolf.Math.dy4dir[dir];
59 |
60 | if (level.tileMap[x + dx][y + dy] & (Wolf.SOLID_TILE | Wolf.DOOR_TILE)) {
61 | // noway (smth is blocking)
62 | return true;
63 | }
64 |
65 | // remove secret flag & make everything needed when pushwall used!
66 | level.tileMap[x][y] &= (~Wolf.SECRET_TILE);
67 | level.tileMap[x][y] &= (~Wolf.WALL_TILE);
68 | level.tileMap[x][y] |= Wolf.PUSHWALL_TILE;
69 |
70 | if (++level.state.foundSecrets == level.state.totalSecrets) {
71 | Wolf.Game.notify("You found the last secret!");
72 | } else {
73 | Wolf.Game.notify("You found a secret!");
74 | }
75 |
76 | Wolf.Sound.startSound(null, null, 1, Wolf.CHAN_AUTO, "sfx/034.wav", 1, Wolf.ATTN_STATIC, 0);
77 |
78 | // good way to avoid stuckness; [un]comment one more down!
79 | // it makes a tile behind pushwall unpassable
80 | level.tileMap[x + dx][y + dy] |= Wolf.PUSHWALL_TILE;
81 | level.wallTexX[x + dx][y + dy] = level.wallTexX[x][y];
82 | level.wallTexY[x + dx][y + dy] = level.wallTexY[x][y];
83 |
84 | // write down PWall info
85 | PWall.active = true;
86 | PWall.tilesMoved = PWall.pointsMoved = 0;
87 | PWall.dir = dir;
88 | PWall.x = x;
89 | PWall.y = y;
90 | PWall.dx = dx;
91 | PWall.dy = dy;
92 | PWall.texX = level.wallTexX[x][y];
93 | PWall.texY = level.wallTexY[x][y];
94 |
95 | return true;
96 | }
97 |
98 |
99 | function process(level, tics) {
100 | if (!PWall.active) {
101 | return; // no active PWall to work with
102 | }
103 |
104 | PWall.pointsMoved += tics;
105 |
106 | if (PWall.pointsMoved < 128) {
107 | return;
108 | }
109 |
110 | PWall.pointsMoved -= 128;
111 | PWall.tilesMoved++;
112 | // Free tile
113 | level.tileMap[PWall.x][PWall.y] &= (~Wolf.PUSHWALL_TILE);
114 | // Occupy new tile
115 | PWall.x += PWall.dx;
116 | PWall.y += PWall.dy;
117 |
118 | // Shall we move further?
119 | if (level.tileMap[PWall.x + PWall.dx][PWall.y + PWall.dy] & (Wolf.SOLID_TILE | Wolf.DOOR_TILE | Wolf.ACTOR_TILE | Wolf.POWERUP_TILE) || PWall.tilesMoved == 3) {
120 | level.tileMap[PWall.x][PWall.y] &= (~Wolf.PUSHWALL_TILE); // wall now
121 | level.tileMap[PWall.x][PWall.y] |= Wolf.WALL_TILE; // wall now
122 | level.wallTexX[PWall.x][PWall.y] = PWall.texX;
123 | level.wallTexY[PWall.x][PWall.y] = PWall.texY;
124 | PWall.active = false; // Free Push Wall
125 | } else {
126 | level.tileMap[PWall.x + PWall.dx][PWall.y + PWall.dy] |= Wolf.PUSHWALL_TILE;
127 |
128 | // Not sure if this is right but it fixed an issue with the pushwall texture changing mid-slide.
129 | level.wallTexX[PWall.x + PWall.dx][PWall.y + PWall.dy] = PWall.texX;
130 | level.wallTexY[PWall.x + PWall.dx][PWall.y + PWall.dy] = PWall.texY;
131 | }
132 | }
133 |
134 | function get() {
135 | return PWall;
136 | }
137 |
138 | return {
139 | reset : reset,
140 | process : process,
141 | push : push,
142 | get : get
143 | };
144 |
145 | })();
146 |
--------------------------------------------------------------------------------
/js/random.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 | Wolf.Random = (function() {
28 |
29 | /* This is just John Carmack's table driven pseudo-random number generator */
30 | var rndtable = [
31 | 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66,
32 | 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36,
33 | 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188,
34 | 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224,
35 | 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242,
36 | 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0,
37 | 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235,
38 | 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113,
39 | 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75,
40 | 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196,
41 | 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113,
42 | 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241,
43 | 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224,
44 | 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95,
45 | 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226,
46 | 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36,
47 | 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106,
48 | 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136,
49 | 120, 163, 236, 249
50 | ];
51 |
52 | var rndindex = 0;
53 |
54 | function init(randomize) {
55 | if (randomize ) {
56 | rndindex = (new Date).getTime() & 0xFF;
57 | } else {
58 | rndindex = 0;
59 | }
60 | }
61 |
62 | function rnd() {
63 | rndindex++;
64 | rndindex &= 0xFF;
65 | return rndtable[rndindex];
66 | }
67 |
68 |
69 | return {
70 | init : init,
71 | rnd : rnd
72 | }
73 |
74 | })();
--------------------------------------------------------------------------------
/js/raycaster.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 | Wolf.setConsts({
28 | UPPERZCOORD : 0.6,
29 | LOWERZCOORD : -0.6,
30 |
31 | // marks
32 | TRACE_MARK_MAP : 1, // marks traced area in 'AM_AutoMap.vis' array
33 | // obstacle levels
34 | TRACE_SIGHT : 2, // player sight
35 | TRACE_SIGHT_AI : 4, // enemy sight
36 | TRACE_BULLET : 8, // bullet
37 | TRACE_OBJECT : 16, // object
38 |
39 | TRACE_HIT_VERT : 32, // vertical wall was hit
40 | TRACE_HIT_DOOR : 64, // door was hit
41 | TRACE_HIT_PWALL : 128 // pushwall was hit
42 | });
43 |
44 | Wolf.Raycaster = (function() {
45 |
46 | var x_tile_step = [ 1, -1, -1, 1 ],
47 | y_tile_step = [ 1, 1, -1, -1 ];
48 |
49 | var TILESHIFT = Wolf.TILESHIFT,
50 | TRACE_HIT_VERT = Wolf.TRACE_HIT_VERT,
51 | TILEGLOBAL = Wolf.TILEGLOBAL,
52 | WALL_TILE = Wolf.WALL_TILE,
53 | DOOR_TILE = Wolf.DOOR_TILE,
54 | TILE2POS = Wolf.TILE2POS,
55 | POS2TILE = Wolf.POS2TILE,
56 | FINE2RAD = Wolf.FINE2RAD,
57 | TRACE_HIT_DOOR = Wolf.TRACE_HIT_DOOR,
58 | PUSHWALL_TILE = Wolf.PUSHWALL_TILE,
59 | TRACE_HIT_PWALL = Wolf.TRACE_HIT_PWALL,
60 | DOOR_FULLOPEN = Wolf.DOOR_FULLOPEN,
61 | XnextTable = Wolf.Math.XnextTable,
62 | YnextTable = Wolf.Math.YnextTable,
63 | getQuadrant = Wolf.Math.getQuadrant,
64 | TanTable = Wolf.Math.TanTable;
65 |
66 | function traceCheck(tileMap, doorMap, visibleTiles, x, y, frac, dfrac, vert, flip, tracePoint) {
67 | var door;
68 |
69 | if (tileMap[x][y] & WALL_TILE) {
70 | if (vert) {
71 | tracePoint.x = (x << TILESHIFT) + (flip ? TILEGLOBAL : 0);
72 | tracePoint.y = (y << TILESHIFT) + frac;
73 | tracePoint.flags |= TRACE_HIT_VERT;
74 | } else {
75 | tracePoint.x = (x << TILESHIFT) + frac;
76 | tracePoint.y = (y << TILESHIFT) + (flip ? TILEGLOBAL : 0);
77 | tracePoint.flags &= ~TRACE_HIT_VERT;
78 | }
79 | tracePoint.tileX = x;
80 | tracePoint.tileY = y;
81 | tracePoint.frac = frac / TILEGLOBAL;
82 |
83 | return true; // wall, stop tracing
84 | }
85 |
86 | if (visibleTiles) {
87 | visibleTiles[x][y] = true; // this tile is visible
88 | }
89 |
90 | if (tileMap[x][y] & DOOR_TILE && doorMap[x][y].action != Wolf.dr_open) {
91 | door = doorMap[x][y];
92 |
93 | frac += dfrac >> 1;
94 |
95 | if (POS2TILE(frac)) {
96 | return false;
97 | }
98 |
99 | if (vert) {
100 | if (door.action != Wolf.dr_closed && (frac >> 10) > DOOR_FULLOPEN - Wolf.Doors.opened(door)) {
101 | return false; // opened enough
102 | }
103 | tracePoint.x = TILE2POS(x);
104 | tracePoint.y = (y << TILESHIFT) + frac;
105 | tracePoint.flags |= TRACE_HIT_VERT;
106 | tracePoint.frac = frac / TILEGLOBAL;
107 | } else {
108 | if (door.action != Wolf.dr_closed && (frac >> 10) < Wolf.Doors.opened(door)) {
109 | return false; // opened enough
110 | }
111 | tracePoint.y = TILE2POS(y);
112 | tracePoint.x = (x << TILESHIFT) + frac;
113 | tracePoint.flags &= ~TRACE_HIT_VERT;
114 | tracePoint.frac = 1 - frac / TILEGLOBAL;
115 | }
116 |
117 | tracePoint.flags |= TRACE_HIT_DOOR;
118 | tracePoint.tileX = x;
119 | tracePoint.tileY = y;
120 | tracePoint.frac += Wolf.Doors.opened(door) / DOOR_FULLOPEN;
121 | return true; // closed door, stop tracing
122 | }
123 |
124 |
125 | if (tileMap[x][y] & PUSHWALL_TILE) {
126 |
127 | var pwall = Wolf.PushWall.get(),
128 | offset = pwall.pointsMoved / 128;
129 |
130 | frac += dfrac * offset;
131 |
132 | if (POS2TILE(frac)) {
133 | return false;
134 | }
135 |
136 | if (vert) {
137 | tracePoint.x = (x << TILESHIFT) + (flip ? TILEGLOBAL : 0) + offset * TILEGLOBAL * (flip ? -1 : 1);
138 | tracePoint.y = (y << TILESHIFT) + frac;
139 | tracePoint.flags |= TRACE_HIT_VERT;
140 | } else {
141 | tracePoint.x = (x << TILESHIFT) + frac;
142 | tracePoint.y = (y << TILESHIFT) + (flip ? TILEGLOBAL : 0) + offset * TILEGLOBAL * (flip ? -1 : 1);
143 | tracePoint.flags &= ~TRACE_HIT_VERT;
144 | }
145 |
146 | tracePoint.flags |= TRACE_HIT_PWALL;
147 | tracePoint.tileX = x;
148 | tracePoint.tileY = y;
149 | tracePoint.frac = frac / TILEGLOBAL;
150 | return true;
151 | }
152 |
153 | return false; // no intersection, go on!
154 | }
155 |
156 | function trace(level, visibleTiles, tracePoint) {
157 | var xtilestep, ytilestep,
158 | xstep, ystep,
159 | xtile, ytile,
160 | xintercept, yintercept,
161 | YmapPos, XmapPos,
162 | tileMap = level.tileMap,
163 | doorMap = level.state.doorMap,
164 | q;
165 |
166 | // Setup for ray casting
167 | q = getQuadrant(FINE2RAD(tracePoint.angle));
168 |
169 | xtilestep = x_tile_step[q];
170 | ytilestep = y_tile_step[q];
171 |
172 | xtile = POS2TILE(tracePoint.x) + xtilestep;
173 | ytile = POS2TILE(tracePoint.y) + ytilestep;
174 |
175 | xstep = ytilestep * XnextTable[tracePoint.angle];
176 | ystep = xtilestep * YnextTable[tracePoint.angle];
177 |
178 | xintercept = (((((ytilestep == -1 ? ytile+1 : ytile) << TILESHIFT) - tracePoint.y)
179 | / TanTable[tracePoint.angle])>>0) + tracePoint.x;
180 | yintercept = (((((xtilestep == -1 ? xtile+1 : xtile) << TILESHIFT) - tracePoint.x)
181 | * TanTable[tracePoint.angle])>>0) + tracePoint.y;
182 |
183 | YmapPos = yintercept >> TILESHIFT; // toXray
184 | XmapPos = xintercept >> TILESHIFT; // toYray
185 |
186 | if (visibleTiles) {
187 | // this tile is visible
188 | visibleTiles[POS2TILE(tracePoint.x)][POS2TILE(tracePoint.y)] = true;
189 | }
190 |
191 | var traceCount = 0;
192 |
193 | // Start of ray-casting
194 | while (1) {
195 |
196 | traceCount++;
197 |
198 | // Vertical loop // an analogue for X-Ray
199 | while (!(ytilestep == -1 && YmapPos <= ytile) && !(ytilestep == 1 && YmapPos >= ytile)) {
200 |
201 | if (xtile < 0 || xtile >= 64 || YmapPos < 0 || YmapPos >= 64) {
202 | tracePoint.oob = true;
203 | return;
204 | }
205 |
206 | if (traceCheck(tileMap, doorMap, visibleTiles, xtile, YmapPos, yintercept % TILEGLOBAL, ystep, true, (xtilestep == -1), tracePoint)) {
207 | if (xstep < 0) {
208 | tracePoint.frac = 1 - tracePoint.frac;
209 | }
210 | return;
211 | }
212 |
213 | // prepare for next step
214 | xtile += xtilestep;
215 | yintercept += ystep;
216 | YmapPos = yintercept >> TILESHIFT;
217 | }
218 |
219 | // Horizontal loop // an analogue for Y-Ray
220 | while (!(xtilestep == -1 && XmapPos <= xtile) && !(xtilestep == 1 && XmapPos >= xtile)) {
221 |
222 | if (ytile < 0 || ytile >= 64 || XmapPos < 0 || XmapPos >= 64) {
223 | tracePoint.oob = true;
224 | return;
225 | }
226 |
227 | if (traceCheck(tileMap, doorMap, visibleTiles, XmapPos, ytile, xintercept % TILEGLOBAL, xstep, false, (ytilestep == -1), tracePoint)) {
228 | if (ystep > 0) {
229 | tracePoint.frac = 1 - tracePoint.frac;
230 | }
231 | return;
232 | }
233 |
234 | // prepare for next step
235 | ytile += ytilestep;
236 | xintercept += xstep;
237 | XmapPos = xintercept >> TILESHIFT;
238 | }
239 |
240 | if (traceCount > 1000) {
241 | return;
242 | }
243 |
244 | } // end of while( 1 )
245 |
246 |
247 | }
248 |
249 |
250 | function traceRays(viewport, level) {
251 | var n, i, j,
252 | tileMap = level.tileMap,
253 | tracePoint,
254 | visibleTiles = [],
255 | numRays = Wolf.XRES / Wolf.SLICE_WIDTH,
256 | tracers = [];
257 |
258 | for (i=0;i<64;i++) {
259 | visibleTiles[i] = [];
260 | for (j=0;j<64;j++) {
261 | visibleTiles[i][j] = 0;
262 | }
263 | }
264 |
265 | // Ray casting
266 |
267 | for (n = 0 ; n < numRays ; ++n) {
268 |
269 | tracePoint = {
270 | x : viewport.x,
271 | y : viewport.y,
272 | angle : Wolf.Math.normalizeAngle(viewport.angle - Wolf.Math.ColumnAngle[n * Wolf.SLICE_WIDTH]),
273 | flags : Wolf.TRACE_SIGHT | Wolf.TRACE_MARK_MAP,
274 | oob : false
275 | };
276 |
277 | trace(level, visibleTiles, tracePoint);
278 |
279 | tracers[n] = tracePoint;
280 |
281 | // Ugly hack to get rid of "blank slice" glitch due to out-of-bounds raycasting.
282 | // We simply re-use the previous slice if possible.
283 | if (tracePoint.oob) {
284 | if (n > 0 && !tracers[n-1].oob) {
285 | tracers[n] = tracers[n-1];
286 | }
287 | }
288 | }
289 |
290 | return {
291 | visibleTiles : visibleTiles,
292 | tracers : tracers
293 | };
294 | }
295 |
296 |
297 | return {
298 | traceRays : traceRays,
299 | trace : trace
300 | };
301 |
302 | })();
303 |
--------------------------------------------------------------------------------
/js/renderer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * ===========================================================================
3 | *
4 | * Wolf3D Browser Version GPL Source Code
5 | * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
6 | *
7 | * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
8 | *
9 | * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 2 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License version 2
20 | * along with Wolf3D Browser Source Code. If not, see .
21 | *
22 | * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
23 | *
24 | * ===========================================================================
25 | */
26 |
27 | Wolf.setConsts({
28 | FOV_RAD : 75 * Math.PI / 180,
29 | ISCHROME : /chrome/.test(navigator.userAgent.toLowerCase()),
30 | ISSAFARI : /safari/.test(navigator.userAgent.toLowerCase()),
31 | ISFIREFOX : /firefox/.test(navigator.userAgent.toLowerCase()),
32 | ISXP : /windows nt 5\./.test(navigator.userAgent.toLowerCase()),
33 | ISWEBKIT : /webkit/.test(navigator.userAgent.toLowerCase())
34 | });
35 | Wolf.setConsts({
36 | VIEW_DIST : (Wolf.XRES / 2) / Math.tan((Wolf.FOV_RAD / 2)),
37 | TEXTURERESOLUTION : Wolf.ISCHROME ? 128 : 64
38 | });
39 |
40 |
41 | Wolf.Renderer = (function() {
42 |
43 | var slices = [],
44 | useBackgroundImage = Wolf.ISWEBKIT,
45 | texturePath = "art/walls-shaded/" + Wolf.TEXTURERESOLUTION + "/",
46 | spritePath = "art/sprites/" + Wolf.TEXTURERESOLUTION + "/",
47 | sprites = [],
48 | maxDistZ = 64 * 0x10000,
49 | hasInit = false;
50 | visibleSprites = [];
51 |
52 | var TILESHIFT = Wolf.TILESHIFT,
53 | TILEGLOBAL = Wolf.TILEGLOBAL,
54 | TRACE_HIT_VERT = Wolf.TRACE_HIT_VERT,
55 | TRACE_HIT_DOOR = Wolf.TRACE_HIT_DOOR,
56 | WALL_TILE = Wolf.WALL_TILE,
57 | DOOR_TILE = Wolf.DOOR_TILE,
58 | TEX_PLATE = Wolf.TEX_PLATE,
59 | TILE2POS = Wolf.TILE2POS,
60 | POS2TILE = Wolf.POS2TILE,
61 | VIEW_DIST = Wolf.VIEW_DIST,
62 | SLICE_WIDTH = Wolf.SLICE_WIDTH,
63 | WALL_TEXTURE_WIDTH = Wolf.WALL_TEXTURE_WIDTH,
64 | FINE2RAD = Wolf.FINE2RAD,
65 | XRES = Wolf.XRES,
66 | YRES = Wolf.YRES,
67 | MINDIST = Wolf.MINDIST,
68 | cos = Math.cos,
69 | sin = Math.sin,
70 | tan = Math.tan,
71 | atan2 = Math.atan2,
72 | round = Math.round,
73 | sqrt = Math.sqrt;
74 |
75 | function init() {
76 | var image, slice, x;
77 | if (hasInit) {
78 | return;
79 | }
80 | hasInit = true;
81 |
82 | $("#game .renderer")
83 | .width(Wolf.XRES + "px")
84 | .height(Wolf.YRES + "px");
85 |
86 | for (x=0; x");
88 | slice.css({
89 | position : "absolute",
90 | width : Wolf.SLICE_WIDTH + "px",
91 | height : Wolf.YRES + "px",
92 | left : x + "px",
93 | top : 0,
94 | overflow : "hidden"
95 | });
96 | slice.appendTo("#game .renderer");
97 |
98 | image = useBackgroundImage ? $("