pax_global_header00006660000000000000000000000064070474304640014522gustar00rootroot0000000000000052 comment=353f0d2f20015f3c81301814161241eaede2e230 xinvaders3d-1.31/000077500000000000000000000000000704743046400137005ustar00rootroot00000000000000xinvaders3d-1.31/COPYING000066400000000000000000000431050704743046400147360ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. xinvaders3d-1.31/Makefile000066400000000000000000000021360704743046400153420ustar00rootroot00000000000000all: game CC = gcc XLIB = -L/usr/X11R6/lib -I/usr/X11R6/include LIBS = -lm -lX11 OBJS = game.o aliens.o player.o effects.o \ object.o camera.o main-x11.o vec4x1.o mat4x4.o DEPENDS = #CFLAGS = -g -Wall -pedantic -ansi CFLAGS = -ansi #OPTIONS = -D_GNU_SOURCE -DGAME_LINUX_X11 -DGAME_DEBUG OPTIONS= -DGAME_LINUX_X11 .c.o: $(DEPENDS) $(CC) -c $(CFLAGS) $(OPTIONS) $< -o $@ game: $(OBJS) $(DEPENDS) $(CC) -o xinv3d $(OBJS) $(XLIB) $(LIBS) $(OPTIONS) clean: rm *.o rm xinv3d aliens.o: aliens.c game.h vec4x1.h mat4x4.h camera.h system.h defines.h \ object.h externs.h camera.o: camera.c mat4x4.h vec4x1.h camera.h effects.o: effects.c game.h vec4x1.h mat4x4.h camera.h system.h \ defines.h object.h externs.h game.o: game.c game.h vec4x1.h mat4x4.h camera.h system.h defines.h \ object.h externs.h object.o: object.c mat4x4.h vec4x1.h defines.h object.h main-x11.o: main-x11.c game.h vec4x1.h mat4x4.h camera.h system.h \ defines.h object.h externs.h mat4x4.o: mat4x4.c mat4x4.h vec4x1.h player.o: player.c game.h vec4x1.h mat4x4.h camera.h system.h defines.h \ object.h externs.h vec4x1.o: vec4x1.c vec4x1.h xinvaders3d-1.31/Makefile.dos000066400000000000000000000021300704743046400161200ustar00rootroot00000000000000all: game CC = gcc LIBS = -lalleg -lm OBJS = game.o aliens.o player.o effects.o \ object.o camera.o main-dos.o vec4x1.o mat4x4.o DEPENDS = #CFLAGS = -pg -Wall -pedantic -ansi #CFLAGS = -ansi #OPTIONS = -D_GNU_SOURCE -DGAME_LINUX_X11 -DGAME_DEBUG OPTIONS= -DGAME_LINUX_X11 .c.o: $(DEPENDS) $(CC) -c $(CFLAGS) $(OPTIONS) $< -o $@ game: $(OBJS) $(DEPENDS) $(CC) -o xinv3d $(OBJS) $(LIBS) $(OPTIONS) clean: del *.o del xinv3d.exe aliens.o: aliens.c game.h vec4x1.h mat4x4.h camera.h system.h defines.h \ object.h externs.h camera.o: camera.c mat4x4.h vec4x1.h camera.h effects.o: effects.c game.h vec4x1.h mat4x4.h camera.h system.h \ defines.h object.h externs.h game.o: game.c game.h vec4x1.h mat4x4.h camera.h system.h defines.h \ object.h externs.h object.o: object.c mat4x4.h vec4x1.h defines.h object.h main-dos.o: main-dos.c game.h vec4x1.h mat4x4.h camera.h system.h \ defines.h object.h externs.h mat4x4.o: mat4x4.c mat4x4.h vec4x1.h player.o: player.c game.h vec4x1.h mat4x4.h camera.h system.h defines.h \ object.h externs.h vec4x1.o: vec4x1.c vec4x1.h xinvaders3d-1.31/README000066400000000000000000000065230704743046400145660ustar00rootroot00000000000000XInvaders 3D v1.31 =================== XInvaders 3D is a vector-graphics Space Invaders clone for the X Window System. Objective: ================= Clear all the aliens in each level. The UFO yields bonus points if hit. A new life will be added every 7500 points. Game-over: either if the player has lost all its lives or if the alien formation reaches the player position. From bottom to top: Row 0 aliens yield 10 pts Row 1 aliens yield 50 pts Row 2 aliens yield 100 pts Row 3 aliens yield 150 pts Row 4 aliens yield 200 pts UFO yields 500 pts Keys: ===== SPACE : Fire Missile Left Arrow : move left Right Arrow : move right Up Arrow : move up Down Arrow : move down q : Reset game f : Show frame-rate p : Pause game ESC : Terminate Program How to play the game: ===================== 1. Requirements: gcc and Xlib 2. Compile the game, type: make 3. Run the game, type: ./xinv3d note: You may have to edit the Makefile depending on where your headers and libraries are. Greetings: ========== Greets & Thanks to following people whose games helped inspire this project: Bill Kendrick who wrote ICBM3d http://www.newbreedsoftware.com Yuusuke Hashimoto who wrote XSoldier http://www.surfline.ne.jp/hachi/xsoldier.html James Eibisch who wrote a Space Invaders clone in quick-basic http://www.revolver.demon.co.uk/coding/index.html Have Fun! Don Llopis dllopi01@fiu.edu http://www.fiu.edu/~dllopi01 History: ======== 1.31: Fixed drawing order. Objects were being drawn in reverse. 1.3: Many thanks to Thomas Boutell, he has contributed a Windows port of XInvaders 3D. See README.win for more information. XInvaders 3D DOS port finished. XInvaders 3D will now run as a full-screen 640x480x8 DOS game. For windows users it will run in a DOS window just fine. I used DJGPP+Allegro to port it. See README.dos for more information. Added Vector-fonts. All text graphics have been replaced with Vector-fonts. Gives the game a cleaner look. New player blinking routine. Player now cycles through red colors, rather than being drawn each alternate frame, when a new level has been started. New special effect: 1-UP indicator. When 7500pts have been reached a new life is indicated by a nice little vector 1-UP floating towards the player. New alien-shoot missile routine. Aliens now shoot more. New Distance-of-Point-to-Line routine, used for collision detection. Added fix for FreeBSD systems, thanks to Peter da Silva. Fixed ZONE_HEIGHT bug in game.c, which was generating bad pointers, thanks to Sam Bushell. Cleaned up code, for portability reasons, thanks to Thomas Boutell for his help. Left-Shift key is no longer being used. 1.2: Cleaned up some more code. Adjusted formation movement. Changed missile color to yellow, suggested by Mattia Engdeg. Fixed some warnings which the pedantic flag generates, thanks to Jarmo Pussinen for pointing them out. 1.1: Fixed incompatible pointer warnings. Fixed window manager bug which Bill Kendrick pointed out. Windows were opening at an odd width and height under the Enlightenment Window manager. 1.0: Initial release. xinvaders3d-1.31/README.dos000066400000000000000000000014540704743046400153500ustar00rootroot00000000000000See the file README for complete information about XInvaders 3D in general. This file covers MS-DOS issues only. INFORMATION FOR PLAYERS: This is the MS-DOS port of XInvaders 3D. It should run on any IBM-PC or compatible, running some version of MS-DOS greater than 6.0. To start the game, just type: xinv3d. See README for instructions. MS-DOS port done by Don Llopis (dllopi01@fiu.edu). INFORMATION FOR PROGRAMMERS: To build the game, type: make -f Makefile.dos You must have the latest version of DJGPP (a 32bit DOS compiler) and at least version 3.12 of the Allegro graphics library. If you make any modifications to the code, please keep ALL DOS-specific code in main-dos.c. Both DJGPP and Allegro can be found here: http://www.delorie.com/djgpp/ Have Fun! Don Llopis dllopi01@fiu.edu xinvaders3d-1.31/README.win000066400000000000000000000020160704743046400153530ustar00rootroot00000000000000See the file README for complete information about XInvaders 3D in general. This file covers Microsoft Windows issues only. INFORMATION FOR PLAYERS: This Windows port of XInvaders 3D runs on Windows 95, 98, NT, and 2000. To start the game, just launch xinv3d.exe. See README for instructions, or look at "How to Play" on the system menu after you start the game. This Windows port was done by Thomas Boutell (boutell@boutell.com). INFORMATION FOR PROGRAMMERS: To build the game, just add all of the .c files to a "Win32 Application" project, including main-w.c, but excluding main-x11.c and any other main-*.c files for non-Windows operating systems. Then, BE SURE TO DEFINE THE PREPROCESSOR MACRO GAME_WIN32. If you prefer Makefiles, use the Unix Makefile as a guide. This game is very easy to build with any Windows development environment. If you make any modifications to the code, please keep ALL Windows-specific code in main-w.c where it belongs! Windows-specific questions? Contact Thomas Boutell (boutell@boutell.com). xinvaders3d-1.31/aliens.c000066400000000000000000000506760704743046400153350ustar00rootroot00000000000000/*------------------------------------------------------------------ aliens.c: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #include "game.h" #define ALIEN_RADIUS 20.0f #define ALIEN_RADIUS_SQUARED 400.0f #define BOMB_RADIUS 20.0f #define BOMB_RADIUS_SQUARED 400.0f #define UFO_RADIUS 20.0f #define UFO_RADIUS_SQUARED 400.0f #define UFO_MIN_X_POS -600.0f #define UFO_MAX_X_POS 600.0f #define UFO_Z_POS -950.0f #define FORMATION_X_INC 75.0f #define FORMATION_Y_INC 100.0f #define FORMATION_MAX_X_POS 550.0f #define FORMATION_MIN_X_POS -550.0f #define FORMATION_MAX_Y_POS 450.0f #define FORMATION_MIN_Y_POS 50.0f #define FORMATION_MAX_Z_POS -850.0f #define FORMATION_MIN_Z_POS 50.0f enum alien_enum { MAX_FORMATIONS = 5, MAX_ALIENS = 40, ALIENS_PER_FORMATION = 8, MAX_BOMBS = 12, LEFT = 0, RIGHT = 1, FORWARD = 2, DIRECTION_TOGGLE = 1, ANIMATION_TOGGLE = 1, MAX_COLUMNS = 8, START_LEAD_COLUMN = 7, FORMATION_STEP = 3, /* dist_between_aliens / thurust */ FORWARD_START = 21, /* formation x FORMATION_STEP */ FORWARD_MAX = 45, /* must calc by hand */ FORWARD_MIN = 0, DROP_BOMB_TIME = 500, /* 0.5 sec */ DROP_BOMB_CHANCE_1 = 50, DROP_BOMB_CHANCE_2 = 40, UFO_ZONE = 9, UFO_LIGHTS_CYCLE = 250, SPAWN_UFO_TIME = 5000, SPAWN_UFO_CHANCE_1 = 10, SPAWN_UFO_CHANCE_2 = 5 }; OBJECT aliens [MAX_ALIENS]; OBJECT bombs [MAX_BOMBS]; OBJECT alien_ufo, *ufo; OBJECT the_formation; OBJLIST flist[MAX_FORMATIONS], *af_list; OBJLIST abomblist, *abombs; /* formation speed in msec */ static int fspeed[9] = { 1000, 750, 500, 400, 400, 300, 200, 150, 100 }; static VEC fstart_pos = { FORMATION_MIN_X_POS, FORMATION_MIN_Y_POS, FORMATION_MAX_Z_POS, 1.0f }; static VEC fstart_dir = { 0.0f, 0.0f, 1.0f, 1.0f }; static VEC fthrust[3] = { { -25.0f, 0.0f, 0.0f, 1.0f }, { 25.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 100.0f, 1.0f } }; static VEC abomb_thrust = { 0.0f, 0.0f, 25.0f, 1.0f }; static VEC ufo_thrust = { 5.0f, 0.0f, 0.0f, 1.0f }; static VEC avert1[48] = { { -20.0f, 20.0f, 0.0f, 1.0f }, /* A0: body*/ { 20.0f, 20.0f, 0.0f, 1.0f }, { 20.0f, 0.0f, 0.0f, 1.0f }, { -20.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f }, /* A0: legs*/ { -20.0f, -10.0f, 0.0f, 1.0f }, { -15.0f, -15.0f, 0.0f, 1.0f }, { -20.0f, -25.0f, 0.0f, 1.0f }, { 20.0f, -10.0f, 0.0f, 1.0f }, { 15.0f, -15.0f, 0.0f, 1.0f }, { 20.0f, -25.0f, 0.0f, 1.0f }, { 0.0f, 10.0f, 0.0f, 1.0f }, /* A0: eyes*/ { -15.0, 18.0f, 0.0f, 1.0f }, { -15.0, 2.0f, 0.0f, 1.0f }, { 15.0, 18.0f, 0.0f, 1.0f }, { 15.0, 2.0f, 0.0f, 1.0f }, { -15.0f, 20.0f, 0.0f, 1.0f }, /* A1: body*/ { 15.0f, 20.0f, 0.0f, 1.0f }, { 5.0f, 0.0f, 0.0f, 1.0f }, { -5.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f }, /* A1: legs*/ { -20.0f, -10.0f, 0.0f, 1.0f }, { -15.0f, -15.0f, 0.0f, 1.0f }, { -20.0f, -25.0f, 0.0f, 1.0f }, { 20.0f, -10.0f, 0.0f, 1.0f }, { 15.0f, -15.0f, 0.0f, 1.0f }, { 20.0f, -25.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f }, /* A1: eyes*/ { -20.0, 15.0f, 0.0f, 1.0f }, { -15.0, 0.0f, 0.0f, 1.0f }, { 20.0, 15.0f, 0.0f, 1.0f }, { 15.0, 0.0f, 0.0f, 1.0f }, { -5.0f, 20.0f, 0.0f, 1.0f }, /* A2: body*/ { 5.0f, 20.0f, 0.0f, 1.0f }, { 20.0f, 0.0f, 0.0f, 1.0f }, { -20.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f }, /* A2: legs*/ { -20.0f, -10.0f, 0.0f, 1.0f }, { -15.0f, -15.0f, 0.0f, 1.0f }, { -20.0f, -25.0f, 0.0f, 1.0f }, { 20.0f, -10.0f, 0.0f, 1.0f }, { 15.0f, -15.0f, 0.0f, 1.0f }, { 20.0f, -25.0f, 0.0f, 1.0f }, { 0.0f, 20.0f, 0.0f, 1.0f }, /* A2: eyes*/ { -20.0, 25.0f, 0.0f, 1.0f }, { -15.0, 15.0f, 0.0f, 1.0f }, { 20.0, 25.0f, 0.0f, 1.0f }, { 15.0, 15.0f, 0.0f, 1.0f } }; static VEC avert2[48] = { { -20.0f, 20.0f, 0.0f, 1.0f }, /*A0: body*/ { 20.0f, 20.0f, 0.0f, 1.0f }, { 20.0f, 0.0f, 0.0f, 1.0f }, { -20.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f }, /*A0: legs*/ { -10.0f, -5.0f, 0.0f, 1.0f }, { -5.0f, -10.0f, 0.0f, 1.0f }, { -10.0f, -25.0f, 0.0f, 1.0f }, { 10.0f, -5.0f, 0.0f, 1.0f }, { 5.0f, -10.0f, 0.0f, 1.0f }, { 10.0f, -25.0f, 0.0f, 1.0f }, { 0.0f, 15.0f, 0.0f, 1.0f }, /* A0: eyes*/ { -10.0, 25.0f, 0.0f, 1.0f }, { -15.0, 7.0f, 0.0f, 1.0f }, { 10.0, 25.0f, 0.0f, 1.0f }, { 15.0, 7.0f, 0.0f, 1.0f }, { -15.0f, 20.0f, 0.0f, 1.0f }, /* A1: body*/ { 15.0f, 20.0f, 0.0f, 1.0f }, { 5.0f, 0.0f, 0.0f, 1.0f }, { -5.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f }, /*A1: legs*/ { -10.0f, -5.0f, 0.0f, 1.0f }, { -5.0f, -10.0f, 0.0f, 1.0f }, { -10.0f, -30.0f, 0.0f, 1.0f }, { 10.0f, -5.0f, 0.0f, 1.0f }, { 5.0f, -10.0f, 0.0f, 1.0f }, { 10.0f, -30.0f, 0.0f, 1.0f }, { 0.0f, 10.0f, 0.0f, 1.0f }, /* A1: eyes*/ { -20.0, 15.0f, 0.0f, 1.0f }, { -15.0, 0.0f, 0.0f, 1.0f }, { 20.0, 15.0f, 0.0f, 1.0f }, { 15.0, 0.0f, 0.0f, 1.0f }, { -5.0f, 20.0f, 0.0f, 1.0f }, /* A2: body*/ { 5.0f, 20.0f, 0.0f, 1.0f }, { 20.0f, 0.0f, 0.0f, 1.0f }, { -20.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f }, /*A2: legs*/ { -10.0f, -5.0f, 0.0f, 1.0f }, { -5.0f, -10.0f, 0.0f, 1.0f }, { -10.0f, -30.0f, 0.0f, 1.0f }, { 10.0f, -5.0f, 0.0f, 1.0f }, { 5.0f, -10.0f, 0.0f, 1.0f }, { 10.0f, -30.0f, 0.0f, 1.0f }, { 0.0f, 5.0f, 0.0f, 1.0f }, /* A2: eyes*/ { -20.0, 20.0f, 0.0f, 1.0f }, { -15.0, 0.0f, 0.0f, 1.0f }, { 20.0, 20.0f, 0.0f, 1.0f }, { 15.0, 0.0f, 0.0f, 1.0f } }; static VEC abomb_vert[3] = { { -10.0f, 0.0f, -10.0f, 1.0f }, { 0.0f, 0.0f, 10.0f, 1.0f }, { 10.0f, 0.0f, -10.0f, 1.0f } }; static VEC abomb_vert2[3] = { { 0.0f, 10.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 10.0f, 1.0f }, { 0.0f, -10.0f, 0.0f, 1.0f } }; static VEC uvert1[17] = { { -20.0f, 0.0f, 0.0f, 1.0f }, /* UFO body */ { -10.0f, 10.0f, 0.0f, 1.0f }, { 10.0f, 10.0f, 0.0f, 1.0f }, { 20.0f, 0.0f, 0.0f, 1.0f }, { -20.0f, -20.0f, 0.0f, 1.0f }, /* left leg */ { -10.0f, 0.0f, 0.0f, 1.0f }, { -5.0f, 0.0f, 0.0f, 1.0f }, { 20.0f, -20.0f, 0.0f, 1.0f }, /* right leg */ { 10.0f, 0.0f, 0.0f, 1.0f }, { 5.0f, 0.0f, 0.0f, 1.0f }, { -10.0f, 10.0f, 0.0f, 1.0f }, /* top */ { 0.0f, 20.0f, 0.0f, 1.0f }, { 10.0f, 10.0f, 1.0f, 1.0f }, { -15.0f, 5.0f, 0.0f, 1.0f }, /* windows */ { -5.0f, 5.0f, 0.0f, 1.0f }, { 5.0f, 5.0f, 0.0f, 1.0f }, { 15.0f, 5.0f, 0.0f, 1.0f } }; static int fmove; /* FORMATION move sideways timer */ static int fforward; /* FORMATION move forward counter */ static int fforward_max; /* FORMATION move forward max */ static int fleadcol; /* FORMATION lead column */ static int fanim; /* FORMATION animation counter */ static int fdir; /* FORMATION movement direction */ static int fscur; /* FORMATION speed variable */ static int drop_bomb; /* drop bomb timer */ static int fcolumn[MAX_COLUMNS]; /* FORMATION column count */ static int spawn_ufo; /* spawn ufo timer */ static int ucolor; /* ufo lights cycle timer */ static void Add_bomb ( OBJECT * ); /*================================================================*/ void Aliens_init ( void ) { int i, j; VEC tmp_pos; OBJECT *alien; OBJLIST *f_ptr; /* initialize formations */ /* * the formation is a dummy-object used for * object-sorting purposes */ Object_init ( &the_formation ); Object_set_drawfn ( &the_formation, Aliens_draw ); Vector_copy ( fstart_pos, the_formation.pos ); the_formation.zone = ZONE_8; gv->formation_zone = ZONE_8; gv->alien_count = MAX_ALIENS; fmove = 0; fforward = FORWARD_START; fforward_max = FORWARD_MAX; fleadcol = START_LEAD_COLUMN; fdir = RIGHT; fanim = 0; fscur = 0; drop_bomb = 0; /* place aliens into their appropriate formations */ /* 8 aliens per formation -- total of 5 formations */ af_list = &flist[0]; f_ptr = &flist[0]; alien = &aliens[0]; Vector_init ( tmp_pos ); for ( i=0; izone = gv->formation_zone; alien->zheight = i; alien->vpos = j; alien->radius = ALIEN_RADIUS; alien->radius_squared = ALIEN_RADIUS_SQUARED; Objlist_add ( f_ptr, alien ); tmp_pos[XPOS] += FORMATION_X_INC; fcolumn[j] +=1; alien++; } f_ptr++; } /* initialize alien bombs */ for ( i=0; iufo_zone = ZONE_9; ufo = &alien_ufo; Object_init ( ufo ); Object_set_drawfn ( ufo, Ufo_draw ); ufo->radius = UFO_RADIUS; ufo->radius_squared = UFO_RADIUS_SQUARED; ufo->delay = 0; ucolor = 0; } /*================================================================*/ void Update_fcolumn ( OBJECT *obj ) { int i, j, tmp; if ( gv->alien_count == 0 ) return; i = obj->vpos; fcolumn[i] -= 1; /* select new lead-column if current lead-column is empty */ if ( (fleadcol == i) && (fcolumn[i] == 0) ) { j = fleadcol; if ( fdir == LEFT ) { while ( j < MAX_COLUMNS ) { if ( fcolumn[j] > 0 ) break; j++; } tmp = (j-fleadcol) * 3; } else { while ( j > -1 ) { if ( fcolumn[j] > 0 ) break; j--; } tmp = (fleadcol-j) * 3; } fforward -= tmp; fleadcol = j; } /* update alien movement speed */ if ( ( gv->alien_count % 5 ) == 0 ) fscur++; } void Aliens_update ( void ) { int i, j, fdir_save, chance; OBJECT *alien, *abomb, *tmp; /* move alien bombs */ drop_bomb += gv->msec; abomb = abombs->head; while ( abomb ) { Vector_copy ( abomb->pos, abomb->old_pos ); abomb->pos[ZPOS] += abomb_thrust[ZPOS] * gv->fadjust; if ( abomb->pos[ZPOS] > 0.0 ) { abomb->active = FALSE; tmp = abomb->next; Objlist_del ( abombs, abomb ); abomb = tmp; } else { Object_update_zone ( abomb ); abomb = abomb->next; } } /* update alien formation */ if ( (gv->alien_count > 0) && player->active ) { fmove += gv->msec; if ( fmove > fspeed[fscur] ) { fmove -= fspeed[fscur]; fforward++; fanim ^= ANIMATION_TOGGLE; fdir_save = fdir; /* is it time to move the formation forward?? */ if ( fforward == fforward_max ) { fforward = 0; gv->formation_zone--; the_formation.zone--; Vector_addd ( the_formation.pos, fthrust[FORWARD] ); /* choose new lead column */ if ( fdir == LEFT ) { i = MAX_COLUMNS - 1; while ( i > -1 ) { if ( fcolumn[i] > 0 ) break; i--; } fforward = ( ( i - fleadcol ) * FORMATION_STEP ); fdir_save = RIGHT; } else { i = 0; while ( i < MAX_COLUMNS ) { if ( fcolumn[i] > 0 ) break; i++; } fforward = ( ( fleadcol - i ) * FORMATION_STEP ); fdir_save = LEFT; } fleadcol = i; fdir = FORWARD; } for ( i=0; ihead; while ( alien ) { Vector_addd ( alien->pos, fthrust[fdir] ); Object_update_zone ( alien ); alien = alien->next; } } fdir = fdir_save; } } /* move ufo */ if ( ufo->active ) { /* adjust velocity according to frame time */ /* set new position */ ufo->pos[XPOS] += ufo_thrust[XPOS] * gv->fadjust; ufo->pos[YPOS] += ufo_thrust[YPOS] * gv->fadjust; ufo->pos[ZPOS] += ufo_thrust[ZPOS] * gv->fadjust; Object_update_zone ( ufo ); if ( ufo->pos[XPOS] > UFO_MAX_X_POS ) { Jumpgate_open ( ufo->pos, RIGHT ); ufo->active = FALSE; } } else { spawn_ufo += gv->msec; if ( spawn_ufo > SPAWN_UFO_TIME ) { spawn_ufo -= SPAWN_UFO_TIME; Ufo_spawn (); } } /* drop a bomb or two */ if ( drop_bomb > DROP_BOMB_TIME ) { drop_bomb -= DROP_BOMB_TIME; chance = rand() % DROP_BOMB_CHANCE_1; if ( chance < DROP_BOMB_CHANCE_2 ) { /* pick formation infront of player */ i = pm->zheight; if ( (i > -1) && (ihead; if ( alien ) { /* pick an alien who will drop a bomb */ j = (rand() % (af_list+i)->obj_count ); while ( j ) { alien = alien->next; j--; } /* find an inactive bomb and use it */ Add_bomb ( alien ); } } /* pick a random formation */ i = rand () % MAX_FORMATIONS; alien = (af_list+i)->head; if ( alien ) { /* pick an alien who will drop a bomb */ j = (rand() % (af_list+i)->obj_count ); while ( j ) { alien = alien->next; j--; } /* find an inactive bomb and use it */ Add_bomb ( alien ); } } } } /*================================================================*/ void Add_bomb ( OBJECT *alien ) { int i; OBJECT *abomb; for ( i=0; iactive == FALSE ) { abomb->active = TRUE; Vector_copy ( alien->pos, abomb->pos ); Vector_copy ( alien->pos, abomb->old_pos ); Objlist_add ( abombs, abomb ); break; } } } /*================================================================*/ void Aliens_draw ( OBJECT *obj, MAT r ) { OBJECT *alien; VEC tmp[16]; MAT tmp_mat; int i, p[32], fmodel; for ( i=0; i 1 ) fmodel = 1; else fmodel = 0; alien = (af_list+i)->head; while ( alien ) { Matrix_vec_mult ( r, alien->pos, tmp[0] ); Camera_project_points ( tmp, p, 1 ); Matrix_copy ( r, tmp_mat ); Matrix_set_trans ( tmp_mat, tmp[0] ); if ( fanim ) Matrix_vec_multn ( tmp_mat, &avert2[fmodel*16], tmp, 16 ); else Matrix_vec_multn ( tmp_mat, &avert1[fmodel*16], tmp, 16 ); Camera_project_points ( tmp, p, 16 ); /* body */ Draw_line ( p[0], p[1], p[2], p[3], GREEN ); Draw_line ( p[2], p[3], p[4], p[5], GREEN ); Draw_line ( p[4], p[5], p[6], p[7], GREEN ); Draw_line ( p[6], p[7], p[0], p[1], GREEN ); /* left leg */ Draw_line ( p[8], p[9], p[10], p[11], GREEN ); Draw_line ( p[10], p[11], p[12], p[13], GREEN ); Draw_line ( p[12], p[13], p[8], p[9], GREEN ); Draw_line ( p[10], p[11], p[14], p[15], GREEN ); Draw_line ( p[14], p[15], p[12], p[13], GREEN ); /* right leg */ Draw_line ( p[8], p[9], p[16], p[17], GREEN ); Draw_line ( p[16], p[17], p[18], p[19], GREEN ); Draw_line ( p[18], p[19], p[8], p[9], GREEN ); Draw_line ( p[16], p[17], p[20], p[21], GREEN ); Draw_line ( p[20], p[21], p[18], p[19], GREEN ); /* left eye */ Draw_line ( p[22], p[23], p[24], p[25], RED ); Draw_line ( p[24], p[25], p[26], p[27], RED ); Draw_line ( p[26], p[27], p[22], p[23], RED ); /* right eye */ Draw_line ( p[22], p[23], p[28], p[29], RED ); Draw_line ( p[28], p[29], p[30], p[31], RED ); Draw_line ( p[30], p[31], p[22], p[23], RED ); alien = alien->next; } } } void Alien_missile_draw ( OBJECT *obj, MAT r ) { MAT tmp_mat; VEC tmp[3]; int p[6]; Matrix_vec_mult ( r, obj->pos, tmp[0] ); Matrix_copy ( r, tmp_mat ); Matrix_set_trans ( tmp_mat, tmp[0] ); Matrix_vec_multn ( tmp_mat, abomb_vert, tmp, 3 ); Camera_project_points ( tmp, p, 3 ); Draw_line ( p[0], p[1], p[2], p[3], YELLOW ); Draw_line ( p[2], p[3], p[4], p[5], YELLOW ); Draw_line ( p[4], p[5], p[0], p[1], YELLOW ); Matrix_vec_multn ( tmp_mat, abomb_vert2, tmp, 3 ); Camera_project_points ( tmp, p, 3 ); Draw_line ( p[0], p[1], p[2], p[3], YELLOW ); Draw_line ( p[2], p[3], p[4], p[5], YELLOW ); Draw_line ( p[4], p[5], p[0], p[1], YELLOW ); } /*================================================================*/ void Ufo_spawn ( void ) { int height; float y, z; height = rand() % MAX_FORMATIONS; y = ( (float)(height) * 100.0f ) + 50.0f; z = UFO_Z_POS; ufo->zone = UFO_ZONE; ufo->zheight = height; Vector_set ( ufo->pos, UFO_MIN_X_POS, y, z ); Jumpgate_open ( ufo->pos, LEFT ); ufo->active = TRUE; } void Ufo_draw ( OBJECT *obj, MAT r ) { MAT tmp_mat; VEC tmp[17]; int p[34]; unsigned int color; ufo->delay += gv->msec; if ( ufo->delay > UFO_LIGHTS_CYCLE ) { ufo->delay -= UFO_LIGHTS_CYCLE; ucolor++; if ( ucolor == 4 ) ucolor = 0; } color = RED - ( ucolor * 15 ); Matrix_vec_mult ( r, obj->pos, tmp[0] ); Matrix_copy ( r, tmp_mat ); Matrix_set_trans ( tmp_mat, tmp[0] ); Matrix_vec_multn ( tmp_mat, uvert1, tmp, 17 ); Camera_project_points ( tmp, p, 17 ); Draw_line ( p[0], p[1], p[2], p[3], GREEN ); Draw_line ( p[2], p[3], p[4], p[5], GREEN ); Draw_line ( p[4], p[5], p[6], p[7], GREEN ); Draw_line ( p[6], p[7], p[0], p[1], GREEN ); Draw_line ( p[8], p[9], p[10], p[11], GREEN ); Draw_line ( p[8], p[9], p[12], p[13], GREEN ); Draw_line ( p[14], p[15], p[16], p[17], GREEN ); Draw_line ( p[14], p[15], p[18], p[19], GREEN ); Draw_line ( p[20], p[21], p[22], p[23], GREEN ); Draw_line ( p[22], p[23], p[24], p[25], GREEN ); Draw_point ( p[26], p[27], color ); Draw_point ( p[28], p[29], color ); Draw_point ( p[30], p[31], color ); Draw_point ( p[32], p[33], color ); } /*================================================================*/ xinvaders3d-1.31/camera.c000066400000000000000000000075740704743046400153110ustar00rootroot00000000000000/*------------------------------------------------------------------ camera.c: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #include #include #include #include "mat4x4.h" #include "vec4x1.h" #include "camera.h" /* local variables */ static float hfov, vfov, hpc, vpc; static float screen_width, screen_height, half_screen_width, half_screen_height; static float aspect_ratio; static float hadjust, vadjust; static MAT r_2_l; void Camera_init ( unsigned int width, unsigned int height, float fov ) { screen_width = (float) width; screen_height = (float) height; half_screen_width = screen_width / 2.0f; half_screen_height = screen_height / 2.0f; /* calculate horizontal & vertical field of view */ /* horizontal compensate = HALF_SCREEN_WIDTH / tan ( degrees / 2 ) vertical compensate = HALF_SCREEN_HEIGHT / tan ( degrees / 2 ) see "Building 3d Game Engine" by Brain Hook */ hfov = vfov = fov; hpc = half_screen_width / tan ( hfov/1.5f ); vpc = half_screen_height / tan ( vfov/1.5f ); /* adjust aspect ratio if screen not square ( ie. 4/3 ratio )*/ aspect_ratio = screen_height / screen_height; /* calculate perspective adjustment values */ hadjust = hpc; vadjust = (vpc * aspect_ratio); /* initialize coordinate system conversion mat */ Matrix_id ( r_2_l ); r_2_l[2][2] = -1.0f; } void Camera_project_point ( VEC a, int b[2] ) { if ( a[2] < 0.0 ) { b[0] = b[1] = 0; return; } b[0] = (int) ( a[0] * hadjust / a[2] + half_screen_width ); b[1] = (int) ( -a[1] * vadjust / a[2] + half_screen_height ); } void Camera_project_points ( VEC a[], int b[], int n ) { int i, j; for ( i=0, j=0; ifadjust; if ( stars[i].pos[ZPOS] > -1.0f ) { m = rand() % 4; stars[i].thrust = m; stars[i].color = WHITE - (m*15); stars[i].pos[ZPOS] = -2000.0f; } Matrix_vec_mult ( r, stars[i].pos, tmp ); Camera_project_point ( tmp, p ); Draw_point ( p[0], p[1], stars[i].color ); } } /*------------------------------------------------------------------ * Explosions * * ------------------------------------------------------------------*/ #define EXPLOSION_ROT 0.23f enum explosions_enum { MAX_EXPLOSIONS = 10, MAX_PARTICLES = 4, EXPLOSIONS_LIFE = 1500, /* 1.5 sec */ EXPLOSION_BLEND_TIME = 375, /* 0.375 sec */ EXPLOSION_COLOR_INC = 15 }; struct EXPLOSIONSTRUCT { VEC pos[MAX_PARTICLES]; int thrust[MAX_PARTICLES]; long frame; long blend; int color; int active; } explosions[MAX_EXPLOSIONS]; static int ecur; /* EXPLOSION index */ static int ecount; /* EXPLOSION count */ static int pcur; /* THURST index */ static float erot; /* EXPLOSIONS rotation */ /* shard/particle thrust vectors */ VEC pthrust[8] = { {-2.0f, 0.0f, 0.0f, 1.0f}, {0.0f, -2.0f, 0.0f, 1.0f}, {2.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 2.0f, 0.0f, 1.0f}, {-2.0f, 2.0f, 0.0f, 1.0f}, {2.0f, -2.0f, 0.0f, 1.0f}, {-2.0f, -2.0f, 0.0f, 1.0f}, {2.0f, 2.0f, 0.0f, 1.0f} }; VEC shard[3] = { {-5.0f, 0.0f, 0.0f, 1.0f}, { 0.0f, 5.0f, 0.0f, 1.0f}, { 5.0f, -5.0f, 0.0f, 1.0f}}; void Explosions_clear ( void ) { int i, j; ecur = 0; ecount = 0; pcur = 0; erot = 0.0f; for ( i=0; ipos, explosions[ecur].pos[0] ); Vector_copy ( obj->pos, explosions[ecur].pos[1] ); Vector_copy ( obj->pos, explosions[ecur].pos[2] ); Vector_copy ( obj->pos, explosions[ecur].pos[3] ); explosions[ecur].thrust[0] = pcur; explosions[ecur].thrust[1] = pcur+1; explosions[ecur].thrust[2] = pcur+2; explosions[ecur].thrust[3] = pcur+3; ecur++; pcur += 4; ecount++; if ( ecur > MAX_EXPLOSIONS-1 ) ecur = 0; if ( pcur == 8 ) pcur = 0; } void Explosions_draw ( MAT r ) { int i, j, k, p0[6]; VEC tmp[3], shard_tmp[3]; MAT tmp_mat, tmp_mat2, erot_mat; erot += EXPLOSION_ROT * gv->fadjust; Matrix_x_rot ( tmp_mat, erot ); Matrix_z_rot ( tmp_mat2, erot ); Matrix_mult ( tmp_mat, tmp_mat2, erot_mat ); Matrix_vec_multn ( erot_mat, shard, shard_tmp, 3 ); for ( i=0; imsec; if ( explosions[i].frame > EXPLOSIONS_LIFE ) { explosions[i].active = FALSE; ecount--; } explosions[i].blend += gv->msec; if ( explosions[i].blend > EXPLOSION_BLEND_TIME ) { explosions[i].blend -= EXPLOSION_BLEND_TIME; explosions[i].color -= EXPLOSION_COLOR_INC; } for ( j=0; jfadjust; explosions[i].pos[j][YPOS] += pthrust[k][YPOS] * gv->fadjust; explosions[i].pos[j][ZPOS] += pthrust[k][ZPOS] * gv->fadjust; Matrix_vec_mult ( r, explosions[i].pos[j], tmp[0] ); Matrix_copy ( r, tmp_mat ); Matrix_set_trans ( tmp_mat, tmp[0] ); Matrix_vec_multn ( tmp_mat, shard_tmp, tmp, 3 ); Camera_project_points ( tmp, p0, 3 ); Draw_line ( p0[0], p0[1], p0[2], p0[3], explosions[i].color ); Draw_line ( p0[2], p0[3], p0[4], p0[5], explosions[i].color ); Draw_line ( p0[4], p0[5], p0[0], p0[1], explosions[i].color ); } } } } /*------------------------------------------------------------------ * Jump-gate * * ------------------------------------------------------------------*/ enum jumpgate_enum { MAX_JUMPGATES = 4, JUMPGATE_TIME = 10000, JUMPGATE_ANIM = 250, JUMPGATE_FRAMES = 3 }; struct JUMPGATESTRUCT { int active; long time; long anim; long frame; int dir; VEC pos; } jgates[MAX_JUMPGATES]; static int jgcur; /* JUMPGATE index */ static int jcount; /* JUMPGATE counter */ static VEC jgvert[32] = { {-10.0f, 0.0f, 10.0f, 1.0f}, {-0.0f, 10.0f, -10.0f, 1.0f}, {10.0f, 0.0f, -10.0f, 1.0f}, {0.0f, -10.0f, 10.0f, 1.0f}, {-30.0f, 0.0f, 30.0f, 1.0f}, {0.0f, 30.0f, -30.0f, 1.0f}, {30.0f, 0.0f, -30.0f, 1.0f}, {0.0f, -30.0f, 30.0f, 1.0f}, {-50.0f, 0.0f, 50.0f, 1.0f}, {0.0f, 50.0f, -50.0f, 1.0f}, {50.0f, 0.0f, -50.0f, 1.0f}, {0.0f, -50.0f, 50.0f, 1.0f}, {-70.0f, 0.0f, 70.0f, 1.0f}, {0.0f, 70.0f, -70.0f, 1.0f}, {70.0f, 0.0f, -70.0f, 1.0f}, {0.0f, -70.0f, 70.0f, 1.0f}, {-10.0f, 0.0f, -10.0f, 1.0f}, {0.0f, 10.0f, 10.0f, 1.0f}, {10.0f, 0.0f, 10.0f, 1.0f}, {0.0f, -10.0f, -10.0f, 1.0f}, {-30.0f, 0.0f, -30.0f, 1.0f}, {0.0f, 30.0f, 30.0f, 1.0f}, {30.0f, 0.0f, 30.0f, 1.0f}, {0.0f, -30.0f, -30.0f, 1.0f}, {-50.0f, 0.0f, -50.0f, 1.0f}, {0.0f, 50.0f, 50.0f, 1.0f}, {50.0f, 0.0f, 50.0f, 1.0f}, {0.0f, -50.0f, -50.0f, 1.0f}, {-70.0f, 0.0f, -70.0f, 1.0f}, {0.0f, 70.0f, 70.0f, 1.0f}, {70.0f, 0.0f, 70.0f, 1.0f}, {0.0f, -70.0f, -70.0f, 1.0f} }; void Jumpgate_init ( void ) { int i; for ( i=0; i MAX_JUMPGATES-1 ) return; jgates[jgcur].active = TRUE; jgates[jgcur].time = 0; jgates[jgcur].anim = 0; jgates[jgcur].frame = 0; jgates[jgcur].dir = dir * 16; Vector_copy ( pos, jgates[jgcur].pos ); jgcur++; if ( jgcur > MAX_JUMPGATES-1 ) jgcur = 0; jcount++; } void Jumpgate_animate ( MAT r ) { MAT tmp_mat; VEC tmp[16]; int i, j, p[32], f0; for ( i=0; imsec; jgates[i].anim += gv->msec; if ( jgates[i].anim > JUMPGATE_ANIM ) { jgates[i].anim -= JUMPGATE_ANIM; jgates[i].frame += 1; if ( jgates[i].frame > JUMPGATE_FRAMES ) jgates[i].frame = 0; } if ( jgates[i].time > JUMPGATE_TIME ) { jgates[i].active = FALSE; jcount--; } /* draw jumpgate */ Matrix_vec_mult ( r, jgates[i].pos, tmp[0] ); Matrix_copy ( r, tmp_mat ); Matrix_set_trans ( tmp_mat, tmp[0] ); f0 = ( jgates[i].frame + 1 ) * 4; Matrix_vec_multn ( tmp_mat, &jgvert[jgates[i].dir], tmp, f0 ); Camera_project_points ( tmp, p, f0 ); for ( j=0; j<((f0*2)-4); j+=8 ) { Draw_line ( p[0+j], p[1+j], p[2+j], p[3+j], GREEN ); Draw_line ( p[2+j], p[3+j], p[4+j], p[5+j], GREEN ); Draw_line ( p[4+j], p[5+j], p[6+j], p[7+j], GREEN ); Draw_line ( p[6+j], p[7+j], p[0+j], p[1+j], GREEN ); } } } } /*------------------------------------------------------------------ * One-up!!! * * ------------------------------------------------------------------*/ enum oneup_enum { ONEUP_LIFE = 2000, ONEUP_BLEND_TIME = 200 }; struct ONEUPSTRUCT { VEC pos; long frame; long blend; long color; int active; }one_up; static VEC one_up_vert[10] = { {-40.0f, 20.0f, 0.0f, 1.0f} , /* 1 */ {-40.0f, -20.0f, 0.0f, 1.0f }, {-20.0f, 20.0f, 0.0f, 1.0f }, /* U */ {-20.0f, -20.0f, 0.0f, 1.0f }, { 10.0f, -20.0f, 0.0f, 1.0f }, { 10.0f, 20.0f, 0.0f, 1.0f }, { 20.0f, 20.0f, 0.0f, 1.0f }, /* P */ { 20.0f, -20.0f, 0.0f, 1.0f }, { 60.0f, 0.0f, 0.0f, 1.0f }, { 20.0f, 0.0f, 0.0, 1.0f } }; static VEC oneup_thrust = { 0.0f, 0.0f, 10.0f, 1.0f }; void One_up_init ( void ) { one_up.active = FALSE; } void One_up_add ( OBJECT *obj ) { if ( one_up.active == FALSE ) { one_up.active = TRUE; Vector_copy ( obj->pos, one_up.pos ); one_up.frame = 0; one_up.blend = 0; one_up.color = WHITE; } } void One_up_draw ( MAT r ) { int p0[20]; VEC tmp[10]; MAT tmp_mat; if ( one_up.active ) { one_up.pos[ZPOS] += oneup_thrust[ZPOS] * gv->fadjust; if ( one_up.pos[ZPOS] > -50.0f ) one_up.active = FALSE; one_up.frame += gv->msec; if ( one_up.frame > ONEUP_LIFE ) { one_up.active = FALSE; } one_up.blend += gv->msec; if ( one_up.blend > ONEUP_BLEND_TIME ) { one_up.blend -= ONEUP_BLEND_TIME; one_up.color -= 3; } /* draw one_up */ Matrix_vec_mult ( r, one_up.pos, tmp[0] ); Matrix_copy ( r, tmp_mat ); Matrix_set_trans ( tmp_mat, tmp[0] ); Matrix_vec_multn ( tmp_mat, one_up_vert, tmp, 10 ); Camera_project_points ( tmp, p0, 10 ); /* draw 1 */ Draw_line ( p0[0], p0[1], p0[2], p0[3], one_up.color ); /* draw U */ Draw_line ( p0[4], p0[5], p0[6], p0[7], one_up.color ); Draw_line ( p0[6], p0[7], p0[8], p0[9], one_up.color ); Draw_line ( p0[8], p0[9], p0[10], p0[11], one_up.color ); /* draw P */ Draw_line ( p0[12], p0[13], p0[14], p0[15], one_up.color ); Draw_line ( p0[12], p0[13], p0[16], p0[17], one_up.color ); Draw_line ( p0[16], p0[17], p0[18], p0[19], one_up.color ); } } xinvaders3d-1.31/externs.h000066400000000000000000000050230704743046400155410ustar00rootroot00000000000000/*------------------------------------------------------------------ externs.h: Global Game Variables XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ /* general game variables */ typedef struct GAMEVARSSTRUCT GAMEVARS; struct GAMEVARSSTRUCT { /* obj pointers for rendering */ OBJECT *gobjs[MAX_OBJECTS]; int gobjcount; double fps; /* frames per second */ double ftime; /* frame-time in milliseconds as double */ double fadjust; /* frame-time adjust = rfps / ftime */ long msec; /* frame-time in milliseconds as int */ long fcount; /* frames rendered */ double rfps; /* reference frames per second */ long sw_t; /* stop-watch current # of seconds */ long sw_save; /* stop-watch pause */ int key_QUIT; int key_UP; int key_DOWN; int key_LEFT; int key_RIGHT; int key_FIRE; /* */ int formation_zone; int ufo_zone; int alien_count; /* flags */ int display_fps; int paused; int gameover; int new_level; int intro_done; long hi_score; long pscore; /* player's current score */ long pbonus; /* player bonus counter */ int plives; /* player's current # of lives */ int pblinking; /* player invunerable */ }; /* game.c */ extern GAMEVARS gvars, *gv; /* arrays for both 'about' and 'rules'. Null-terminated so that code to handle them only has to be written once. TBB 1.22 */ extern char *game_about_info[]; extern char *game_rules_info[]; /* timer.c : timer(s) */ extern TIMER gtimer, *gt; /* player.c : the player(s) */ extern OBJECT *player; extern OBJECT *pm; /* alien.c : the aliens, bombs, and ufo */ extern OBJECT *ufo; extern OBJECT the_formation; extern OBJLIST *af_list; extern OBJLIST *abombs; xinvaders3d-1.31/game.c000066400000000000000000000575130704743046400147700ustar00rootroot00000000000000/*------------------------------------------------------------------ game.c: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #include "game.h" #define SW_UPDATE gv->sw_t += gv->msec #define SW_PAUSE gv->sw_save = gv->sw_t #define SW_UNPAUSE gv->sw_t = gv->sw_save #define SW_RESET gv->sw_t = gv->sw_save = 0 static void Add_obj_2_world ( OBJECT * ); static void Clear_obj_list ( void ); static void Sort_obj_list ( void ); static void Draw_obj_list ( MAT ); static int Z_compare ( const void *obj0, const void *obj1 ); static float Dist_pt_2_line ( VEC p, VEC l0, VEC l1 ); static void Draw_vector_font ( int *s[], int x, int y, unsigned int color ); /*------------------------------------------------------------------ * Variables * * ------------------------------------------------------------------*/ GAMEVARS gvars, *gv; TIMER gtimer, *gt; static long score_table[ZONE_HEIGHT_MAX] = { 10L, 50L, 100L, 150L, 200L }; /* use a null terminator, so code doesn't have to be changed in many places. Don't use \n; assume a line break suitable to the particular platform should be generated after each line. TBB */ char *game_about_info[] = { "Thanks for playing XInvaders 3D.", "XInvaders 3D v1.31, Copyright 2000 Don Llopis", "XInvaders 3D comes with ABSOLUTELY NO WARRANTY.", "This is free software, and you are welcome to", "redistribute it under certain conditions. See", "file named COPYING for more information.", "Latest version of the game can be found at:", "http://www.fiu.edu/~dllopi01/xinv3d.htm", "Author can be reached at: dllopi01@fiu.edu", NULL }; char *game_rules_info[] = { "Keys:", "SPACE: Fire Missile", "Left Arrow: move left", "Right Arrow: move right", "Up Arrow: move up", "Down Arrow: move down", "f: Show frame-rate", "p: Pause game", "q: reset game", "ESC: Quit program", NULL }; /* * Not so nice vector-fonts: * perhaps one day, when the universe is kinder to me, * I'll implement a nice vector-font system. But * until the universe lets me go on my trip, * the stuff below stays! */ static int A[17] = { 4, 0, 0, 24, 0, 0, 12, 24, 12, 0, 0, 0, 24, 24, 0, 24, 24 }; static int C[13] = { 3, 0, 0, 24, 0, 0, 0, 0, 24, 0, 24, 24, 24 }; static int D[13] = { 3, 0, 0, 0, 24, 0, 0, 24, 12, 0, 24, 24, 12 }; static int E[17] = { 4, 0, 0, 24, 0, 0, 12, 24, 12, 0, 24, 24, 24, 0, 0, 0, 24 }; static int EXCLAMATION[33] = { 8, 0, 0, 24, 0, 5, 19, 15, 19, 0, 0, 5, 19, 24, 0, 15, 19, 5, 25, 15, 25, 5, 30, 15, 30, 5, 25, 5, 30, 15, 25, 15, 30 }; static int F[13] = { 3, 0, 0, 0, 24, 0, 0, 24, 0, 0, 12, 24, 12 }; static int G[17] = { 4, 24, 0, 0, 12, 0, 12, 24, 24, 24, 24, 24, 12, 24, 12, 12, 12 }; static int H[13] = { 3, 0, 0, 0, 24, 0, 12, 24, 12, 24, 0, 24, 24 }; static int I[13] = { 3, 0, 0, 24, 0, 0, 24, 24, 24, 12, 0, 12, 24 }; static int M[17] = { 4, 0, 0, 0, 24, 0, 0, 12, 12, 12, 12, 24, 0, 24, 0, 24, 24 }; static int N[13] = { 3, 0, 0, 0, 24, 0, 0, 24, 24, 24, 0, 24, 24 }; static int O[17] = { 4, 0, 0, 24, 0, 0, 0, 0, 24, 0, 24, 24, 24, 24, 0, 24, 24 }; static int P[13] = { 3, 0, 0, 0, 24, 0, 0, 24, 12, 24, 12, 0, 12 }; static int R[17] = { 4, 0, 0, 0, 24, 0, 0, 24, 12, 0, 12, 24, 12, 0, 12, 24, 24 }; static int S[13] = { 3, 24, 0, 0, 5, 0, 5, 24, 15, 24, 15, 0, 24 }; static int T[9] = { 2, 0, 0, 24, 0, 12, 0, 12, 24 }; static int U[13] = { 3, 0, 0, 0, 24, 0, 24, 24, 24, 24, 24, 24, 0 }; static int V[9] = { 2, 0, 0, 12, 24, 24, 0, 12, 24 }; static int X[9] = { 2, 0, 0, 24, 24, 24, 0, 0,24 }; static int Y[13] = { 3, 0, 0, 12, 12, 12, 12, 24, 0, 12, 12, 12, 24 }; static int ZERO[21] = { 5, 0, 0, 24, 24, 0, 0, 24, 0, 0, 24, 24, 24, 0, 0, 0, 24, 24, 0, 24, 24 }; static int ONE[5] = { 1, 12, 0, 12, 24 }; static int TWO[21] = { 5, 0, 0, 24, 0, 24, 0, 24, 12, 24, 12, 0, 12, 0, 12, 0, 24, 0, 24, 24, 24 }; static int THREE[17] = { 4, 0, 0, 24, 0, 24, 12, 0, 12, 0, 24, 24, 24, 24, 0, 24, 24 }; static int FOUR[13] = { 3, 0, 0, 0, 12, 0, 12, 24, 12, 24, 0, 24, 24 }; static int FIVE[21] = { 5, 0, 0, 24, 0, 0, 0, 0, 12, 0, 12, 24, 12, 24, 12, 24, 24, 24, 24, 0, 24 }; static int SIX[17] = { 4, 0, 0, 0, 24, 0, 24, 24, 24, 24, 24, 24, 12, 24, 12, 0, 12 }; static int SEVEN[9] = { 2, 0, 0, 24, 0, 24, 0, 0, 24 }; static int EIGHT[21] = { 5, 0, 0, 24, 0, 0, 12, 24, 12, 0, 24, 24, 24, 0, 0, 0, 24, 24, 0, 24, 24 }; static int NINE[17] = { 4, 0, 0, 24, 0, 0, 12, 24, 12, 0, 0, 0, 12, 24, 0, 24, 24 }; static int *NUMBER[10] = { &ZERO[0], &ONE[0], &TWO[0], &THREE[0], &FOUR[0], &FIVE[0], &SIX[0], &SEVEN[0], &EIGHT[0], &NINE[0] }; static int *XINVADERS3D_LOGO[] = { &X[0], &I[0], &N[0], &V[0], &A[0], &D[0], &E[0], &R[0], &S[0], &THREE[0], &D[0], NULL }; static int *GET[] = { &G[0], &E[0], &T[0], NULL }; static int *READY[] = { &R[0], &E[0], &A[0], &D[0], &Y[0], &EXCLAMATION[0], &EXCLAMATION[0], NULL }; static int *GAME_OVER[] = { &G[0], &A[0], &M[0], &E[0], &O[0], &V[0], &E[0], &R[0], NULL }; static int *PAUSED[] = { &P[0], &A[0], &U[0], &S[0], &E[0], &D[0], NULL }; static int *SCORE[] = { &S[0], &C[0], &O[0], &R[0], &E[0], NULL }; static int *HI_SCORE[] = { &H[0], &I[0], &S[0], &C[0], &O[0], &R[0], &E[0], NULL }; static int *PRESS[] = { &P[0], &R[0], &E[0], &S[0], &S[0], NULL }; static int *FIRE[] = { &F[0], &I[0], &R[0], &E[0], NULL }; static int *TO[] = { &T[0], &O[0], NULL }; static int *START[] = { &S[0], &T[0], &A[0], &R[0], &T[0], NULL }; /*================================================================*/ void Game_main ( void ) { while ( Handle_events() ) { /* get start-time of current frame */ gv->msec = Timer_msec ( gt ); gv->ftime = (double)gv->msec/1000L; gv->fps = 1.0 / gv->ftime; gv->fadjust = gv->rfps / gv->fps; (*Game_actionfn)(); Update_display (); } } /*================================================================*/ void (*Game_actionfn) (); /*================================================================*/ int Game_init ( float win_width, float win_height ) { /* initialize variables and timers */ gv = &gvars; Game_init_vars ( INITGAME ); Game_init_keys (); Stars_init (); Jumpgate_init (); Camera_init ( win_width, win_height, 0.785398163 ); gt = >imer; Timer_init( gt ); /* setup stopwatch timer and run menu */ SW_RESET; Game_actionfn = Game_menu; return TRUE; } /*================================================================*/ void Game_init_vars ( int init_type ) { /* Help me! I'm using the evil goto !!! */ switch ( init_type ) { case INITGAME: goto g_init_game; case NEWGAME: goto g_new_game; case NEWLEVEL: goto g_new_level; default: goto g_init_game; } g_init_game: gv->rfps = REFERENCE_FRAMERATE; gv->display_fps = FALSE; gv->hi_score = HISCORE; g_new_game: gv->paused = FALSE; gv->gameover = FALSE; gv->pscore = 0; gv->pbonus = 0; gv->plives = PLAYER_LIVES_START; g_new_level: gv->fcount = 0; gv->msec = 0; gv->ftime = 0.0; gv->fps = 0.0; gv->fadjust = 0.0; gv->new_level = FALSE; } /*================================================================*/ void Game_init_keys ( void ) { gv->key_QUIT = FALSE; gv->key_FIRE = FALSE; gv->key_UP = FALSE; gv->key_DOWN = FALSE; gv->key_LEFT = FALSE; gv->key_RIGHT = FALSE; } /*================================================================*/ void Game_newlevel ( void ) { srand ( time( NULL ) ); Game_init_vars ( NEWLEVEL ); Game_init_keys (); Stars_init (); Explosions_clear (); Jumpgate_init (); One_up_init (); Player_init (); Aliens_init (); SW_RESET; Game_actionfn = Game_ready; } /*================================================================*/ void Game_menu ( void ) { static int blink = 0; static int color = 0; int i, *tmp_score[20]; char buffer[256], tmp_num[2]; VEC up = { 0.0f, 1.0f, 0.0f, 1.0f }; VEC from = { 0.0f, 0.0f, 100.0f, 1.0f }; VEC at = { 0.0f, 0.0f, 0.0f, 1.0f }; MAT cam_mat; /* convert hi-score into a vector-font */ sprintf ( buffer, "%ld", gv->hi_score ); i = 0; tmp_num[0] = '0'; tmp_num[1] = '\0'; do { tmp_num[0] = buffer[i]; tmp_score[i] = NUMBER[atoi(tmp_num)]; i++; } while ( buffer[i] != '\0' ); tmp_score[strlen(buffer)] = NULL; Draw_vector_font ( HI_SCORE, 120, 15, GREEN ); Draw_vector_font ( tmp_score, 360, 15, GREEN ); Camera_transform ( cam_mat, up, from, at ); Stars_draw ( cam_mat ); blink += gv->msec; if ( blink > 250 ) { color++; blink -= 250; if ( color > 3 ) color = 0; } i = RED - ( color * 15 ); Draw_vector_font ( XINVADERS3D_LOGO, 155, 150, GREEN ); Draw_vector_font ( PRESS, 40, 400, i ); Draw_vector_font ( FIRE, 220, 400, i ); Draw_vector_font ( TO, 370, 400, i ); Draw_vector_font ( START, 460, 400, i ); if ( gv->key_FIRE ) { Game_actionfn = Game_newlevel; } } /*================================================================*/ void Game_ready ( void ) { static int blink = 0; static int color = 0; int i; VEC up = { 0.0f, 1.0f, 0.0f, 1.0f }; VEC from = { 0.0f, 0.0f, 100.0f, 1.0f }; VEC at = { 0.0f, 0.0f, 0.0f, 1.0f }; MAT cam_mat; Camera_transform ( cam_mat, up, from, at ); Stars_draw ( cam_mat ); blink += gv->msec; if ( blink > 250 ) { blink -= 250; color++; if ( color == 3 ) color = 0; } i = RED - ( color * 15 ); Draw_vector_font ( GET, 140, 200, i ); Draw_vector_font ( READY, 260, 200, i ); Game_overlay (); SW_UPDATE; if ( gv->key_FIRE || ( gv->sw_t > READY_TIME ) ) { SW_RESET; Game_actionfn = Game_run; } } /*================================================================*/ void Game_paused_toggle ( void ) { static void (*saved_action_fn)( void ) = NULL; gv->paused ^= TRUE; if ( gv->paused ) { SW_PAUSE; saved_action_fn = Game_actionfn; Game_actionfn = Game_paused; } else { SW_UNPAUSE; Game_actionfn = saved_action_fn; } } void Game_paused ( void ) { VEC up = { 0.0f, 1.0f, 0.0f, 1.0f }; VEC from = { 0.0f, 0.0f, 100.0f, 1.0f }; VEC at = { 0.0f, 0.0f, 0.0f, 1.0f }; MAT cam_mat; Camera_transform ( cam_mat, up, from, at ); Stars_draw ( cam_mat ); Draw_vector_font ( PAUSED, 230, 200, RED ); Game_overlay (); SW_UPDATE; } /*================================================================*/ void Game_reset ( void ) { SW_RESET; Game_init_vars ( INITGAME ); Game_init_keys (); Game_actionfn = Game_menu; } void Game_gameover ( void ) { VEC up = { 0.0f, 1.0f, 0.0f, 1.0f }; VEC from = { 0.0f, 0.0f, 100.0f, 1.0f }; VEC at = { 0.0f, 0.0f, 0.0f, 1.0f }; MAT cam_mat; Camera_transform ( cam_mat, up, from, at ); Stars_draw ( cam_mat ); Draw_vector_font ( GAME_OVER, 200, 200, RED ); Game_overlay (); SW_UPDATE; if ( gv->key_FIRE || (gv->sw_t > GAMEOVER_TIME) ) { SW_RESET; Game_init_vars ( NEWGAME ); Game_init_keys (); Game_actionfn = Game_menu; } } /*================================================================*/ void Game_overlay ( void ) { char buffer[256], tmp_num[2]; int i, x, *tmp_score[20]; int life[6] = { 0, 450, 25, 450, 12, 425 }; if ( gv->display_fps ) { if ( gv->ftime > 0.0f ) { sprintf ( buffer, "FPS:%3.0f:(%1.3f):ms(%ld)", gv->fps, gv->fadjust,gv->msec ); } else sprintf ( buffer, "FPS: n/a" ); Draw_text ( buffer, 0, 475, RED ); } /* convert score into a vector-font */ sprintf ( buffer, "%ld", gv->pscore ); i = 0; tmp_num[0] = '0'; tmp_num[1] = '\0'; do { tmp_num[0] = buffer[i]; tmp_score[i] = NUMBER[atoi(tmp_num)]; i++; } while ( buffer[i] != '\0' ); tmp_score[strlen(buffer)] = NULL; Draw_vector_font ( SCORE, 150, 14, GREEN ); Draw_vector_font ( tmp_score, 330, 15, GREEN ); if ( (gv->plives-1) > 0 ) { for ( i=0, x=15; i<(gv->plives-1); i++ ) { Draw_line ( life[0]+x, life[1], life[2]+x, life[3], GREEN ); Draw_line ( life[2]+x, life[3], life[4]+x, life[5], GREEN ); Draw_line ( life[4]+x, life[5], life[0]+x, life[1], GREEN ); x+= 30; } #ifdef GAME_DEBUG sprintf ( buffer, "Lives: %d", gv->plives-1 ); Draw_text ( buffer, 550, 470, GREEN ); #endif } #ifdef GAME_DEBUG sprintf ( buffer, "Time: %10.0fs", (double)gv->sw_t/1000); Draw_text ( buffer, 0, 470, RED ); sprintf ( buffer, "U: %d D: %d L: %d R: %d F: %d", gv->key_UP, gv->key_DOWN, gv->key_LEFT, gv->key_RIGHT, gv->key_FIRE ); Draw_text ( buffer, 200, 470, WHITE ); #endif } /*================================================================*/ void Game_run ( void ) { float dist = 0.0f; OBJECT *alien, *abomb; VEC up = { 0.0f, 1.0f, 0.0f, 1.0f }; VEC from = { 0.0f, 25.0f, 100.0f, 1.0f }; VEC at = { 0.0f, 0.0f, -100.0f, 1.0f }; MAT cam_mat; /* prepare for new frame */ Clear_obj_list (); /* update-player */ if ( player->active ) player->actionfn ( player ); /* update camera */ Vector_addd ( from, player->pos ); Vector_addd ( at, player->pos ); Camera_transform ( cam_mat, up, from, at ); /* * Do collisions checking : * player_missile vs aliens * player vs alien(s) * alien bombs vs player */ if ( pm->active ) { /* is player missile in the formation zone ?? */ if ( pm->zone == gv->formation_zone ) { if ( ( pm->zheight > -1 ) && (pm->zheight < ZONE_HEIGHT_MAX ) ) { /* if so which height-level?? */ alien = (af_list+pm->zheight)->head; while ( alien ) { dist = Dist_pt_2_line ( alien->pos, pm->old_pos, pm->pos ) - pm->radius_squared - 1.0f; if ( dist < alien->radius_squared ) { pm->active = alien->active = FALSE; gv->alien_count--; Objlist_del ( (af_list+pm->zheight), alien ); Explosions_add ( alien ); Update_fcolumn ( alien ); /* update player score & alien count */ gv->pscore += score_table[pm->zheight]; gv->pbonus += score_table[pm->zheight]; if ( gv->pbonus > PLAYER_LIFE_BONUS-1 ) { gv->pbonus -= PLAYER_LIFE_BONUS; if ( gv->plives < PLAYER_LIFE_MAX ) { gv->plives++; One_up_add ( alien ); } } if ( gv->alien_count == 0 ) gv->new_level = TRUE; break; } alien = alien->next; } } } /* is player missile in the UFO zone?? */ else { if ( (ufo->active) && ( pm->zone == ufo->zone ) && ( pm->zheight == ufo->zheight ) ) { dist = Dist_pt_2_line ( ufo->pos, pm->old_pos, pm->pos ) - pm->radius_squared - 1.0f; if ( dist < ufo->radius_squared ) { pm->active = ufo->active = FALSE; Explosions_add ( ufo ); /* update player score */ gv->pscore += UFO_BONUS; gv->pbonus += UFO_BONUS; if ( gv->pbonus > PLAYER_LIFE_BONUS-1 ) { gv->pbonus -= PLAYER_LIFE_BONUS; if ( gv->plives < PLAYER_LIFE_MAX ) { gv->plives++; One_up_add ( ufo ); } } } } } } /* alien bombs vs player */ if ( player->active && !gv->gameover && !gv->pblinking ) { for (abomb=abombs->head; abomb != NULL; abomb=abomb->next ) { if ( (abomb->zone == player->zone) && (abomb->zheight == player->zheight) ) { dist = Dist_pt_2_line ( player->pos, abomb->old_pos, abomb->pos ) - abomb->radius_squared - 1.0f; if ( dist < player->radius_squared ) { abomb->active = player->active = FALSE; Explosions_add ( player ); Objlist_del ( abombs, abomb ); break; } } } } /* * player vs aliens: * if the remaining aliens reach the player_zone * then the game is over! Reduce the number of * remaining lives to zero and blowup the player and * then initiate a game-over! */ if ( gv->formation_zone == ZONE_0 ) { gv->plives = 0; if ( player->active ) { Explosions_add ( player ); player->active = FALSE; } } /* * * Move Objects and Update Animations : * formation, alien_bombs, ufo, and player_missile * */ Aliens_update (); if ( pm->active ) pm->actionfn ( pm ); /* * * Draw Objects : * * special effects * alien: formation, bombs, and ufo * player missile * player * */ Stars_draw ( cam_mat ); Jumpgate_animate ( cam_mat ); Explosions_draw ( cam_mat ); One_up_draw ( cam_mat ); /* * major hack!! this is NOT the right way to draw in 3d * may the universe forgive my transgression! * * */ if ( ufo->active ) Add_obj_2_world ( ufo ); Add_obj_2_world ( &the_formation ); for (abomb=abombs->head; abomb != NULL; abomb=abomb->next ) { Add_obj_2_world ( abomb ); } if ( pm->active ) Add_obj_2_world ( pm ); if ( player->active ) Add_obj_2_world ( player ); Sort_obj_list (); Draw_obj_list ( cam_mat ); SW_UPDATE; Game_overlay (); /* * Before acknowledging flags make sure ALL explosions * are finished: * gameover flag has precedence over newlevel flag * since it is possible for a player to have killed * all the aliens but then get killed by an alien bomb * resulting in both a newlevel and gameover condition!! */ if ( Explosions_count() == 0 ) { if ( player->active == FALSE ) { /* reduce player life and check for gameover */ gv->plives--; if ( gv->plives <= 0 ) gv->gameover = TRUE; Player_init (); SW_RESET; Game_actionfn = Game_ready; } if ( gv->gameover ) { if ( gv->pscore > gv->hi_score ) gv->hi_score = gv->pscore; SW_RESET; Game_actionfn = Game_gameover; } else { if ( gv->new_level && ( Objlist_count ( abombs ) == 0 ) ) { SW_RESET; Game_actionfn = Game_newlevel; } } } } /*================================================================*/ void Object_update_zone ( OBJECT *obj ) { obj->zone = (int) floor ( (double)obj->pos[ZPOS]/-ZONE_WIDTH ); obj->zheight = (int) floor ( (double)obj->pos[YPOS]/ZONE_HEIGHT ); } /*================================================================*/ static void Draw_vector_font ( int *s[], int x, int y, unsigned int color ) { int i, j, X, segments; int *letter; i = 0; X = x; letter = s[0]; do { /* first integer of pointer array always is # of line segments */ segments = *letter; letter++; for ( j=0; jgobjcount; if ( i < MAX_OBJECTS-1 ) { gv->gobjs[i] = obj; gv->gobjcount++; } } void Clear_obj_list ( void ) { gv->gobjcount = 0; } void Sort_obj_list ( void ) { qsort ( gv->gobjs, gv->gobjcount, sizeof ( OBJECT * ), Z_compare ); } int Z_compare ( const void *obj0, const void *obj1 ) { OBJECT *o0, *o1; o0 = ( OBJECT * ) obj0; o1 = ( OBJECT * ) obj1; if ( o0->pos[ZPOS] < o1->pos[ZPOS] ) return -1; else if ( o0->pos[ZPOS] > o1->pos[ZPOS] ) return 1; else return 0; } void Draw_obj_list ( MAT r ) { int i; OBJECT *obj; if ( gv->gobjcount > 0 ) { i = 0; while ( i < gv->gobjcount ) { obj = gv->gobjs[i]; obj->drawfn ( obj, r ); i++; } } } /*================================================================*/ float Dist_pt_2_line ( VEC p, VEC l0, VEC l1 ) { VEC l0_p; VEC l0_l1; VEC q; float n, d, w, t, dist; /* * calc adjusted position of projectile along the * line segment formed by old_pos to new_pos * use this for calculating distance between moving * objects. This must be done since movement is * not in discreet amounts due to varying framerates. * * routine uses the properties of the unit vector * and dot product. see ``Computer Graphics: * principles and practice'' appendix for * explaination. Then checks to see if generated * line falls within the line segment l0l1 * */ Vector_sub ( p, l0, l0_p ); Vector_sub ( l1, l0, l0_l1 ); /* * don't try to take Vector_norm if division by zero * will result. TBB * * check using Vec_mag_squared instead of * xpos == 0 && ypos == 0 && zpos == 0 * Don */ if ( Vector_mag_squared ( l0_l1 ) < 1.0f ) { q[XPOS] = l0[XPOS]; q[YPOS] = l0[YPOS]; q[ZPOS] = l0[ZPOS]; dist = Vector_dist_squared ( q, p ); } else { d = l1[ZPOS] - l0[ZPOS]; /* l0 and l1 are very close */ if ( (d > -0.025 ) && ( d < 0.025 ) ) { q[XPOS] = l0[XPOS]; q[YPOS] = l0[YPOS]; q[ZPOS] = l0[ZPOS]; dist = Vector_dist_squared ( q, p ); } else { Vector_norm ( l0_l1 ); w = Vector_dot ( l0_p, l0_l1 ); q[XPOS] = l0[XPOS] + ( l0_l1[XPOS] * w ); q[YPOS] = l0[YPOS] + ( l0_l1[YPOS] * w ); q[ZPOS] = l0[ZPOS] + ( l0_l1[ZPOS] * w ); n = q[ZPOS] - l0[ZPOS]; t = n / d; if ( ( t > -0.025f ) && ( t < 1.5f ) ) dist = Vector_dist_squared ( q, p ); else dist = 1000000.0f; } } return dist; } xinvaders3d-1.31/game.h000066400000000000000000000113410704743046400147620ustar00rootroot00000000000000/*------------------------------------------------------------------ game.h: Game main header XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #ifndef GAME_MAIN_HEADER #define GAME_MAIN_HEADER /*------------------------------------------------------------------ * * Standard Includes * ------------------------------------------------------------------*/ #include #include #include #include #include /*------------------------------------------------------------------ * * Vector, Matrix, and Camera functions * ------------------------------------------------------------------*/ #include "vec4x1.h" #include "mat4x4.h" #include "camera.h" /*------------------------------------------------------------------ * * System specific Functions, Graphics primitives, and Timming * ------------------------------------------------------------------*/ #include "system.h" /*------------------------------------------------------------------ * * Game Defines * ------------------------------------------------------------------*/ #include "defines.h" /*------------------------------------------------------------------ * * Object Managment Struct & Funtions : object.c * ------------------------------------------------------------------*/ #include "object.h" /*------------------------------------------------------------------ * * Game-Logic Funtions : game.c * ------------------------------------------------------------------*/ extern void Game_main ( void ); /* initialization functions */ extern int Game_init ( float, float ); extern void Game_init_vars ( int ); extern void Game_init_keys ( void ); /* Game action function(s) */ extern void (*Game_actionfn)(); extern void Game_newlevel ( void ); extern void Game_gameover ( void ); extern void Game_paused_toggle ( void ); extern void Game_paused ( void ); extern void Game_reset ( void ); extern void Game_menu ( void ); extern void Game_ready ( void ); extern void Game_run ( void ); extern void Game_overlay ( void ); /* misc game related functions */ extern void Object_update_zone ( OBJECT *obj ); /*------------------------------------------------------------------ * * Player's Functions : player.c * ------------------------------------------------------------------*/ extern void Player_init ( void ); extern void Player_blink ( OBJECT *, MAT ); extern void Player_draw ( OBJECT *, MAT ); extern void Player_update ( OBJECT * ); extern void Player_missile_update ( OBJECT * ); extern void Player_missile_draw ( OBJECT *, MAT ); /*------------------------------------------------------------------ * * Aliens' Functions : aliens.c * ------------------------------------------------------------------*/ extern void Aliens_init ( void ); extern void Aliens_update ( void ); extern void Update_fcolumn ( OBJECT * ); extern void Aliens_draw ( OBJECT *, MAT ); extern void Alien_missile_draw ( OBJECT *, MAT ); extern void Ufo_spawn ( void ); extern void Ufo_draw ( OBJECT *, MAT ); /*------------------------------------------------------------------ * * Special-Effects Functions : effects.c * ------------------------------------------------------------------*/ /* stars */ extern void Stars_init ( void ); extern void Stars_draw ( MAT ); /* explosions */ extern void Explosions_add ( OBJECT * ); extern void Explosions_clear ( void ); extern void Explosions_draw ( MAT ); extern int Explosions_count ( void ); /* jump-gate */ extern void Jumpgate_init ( void ); extern void Jumpgate_open ( VEC, int ); extern void Jumpgate_animate ( MAT ); /* one-up */ extern void One_up_init ( void ); extern void One_up_add ( OBJECT * ); extern void One_up_draw ( MAT ); /*------------------------------------------------------------------ * * Game Variables * ------------------------------------------------------------------*/ #include "externs.h" #endif xinvaders3d-1.31/main-dos.c000066400000000000000000000127660704743046400155670ustar00rootroot00000000000000/*------------------------------------------------------------------ main-dos.c: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #include #include "game.h" /* ahh the simplicity of DOS!!! */ BITMAP *buffer; PALETTE pal; /*================================================================*/ /*------------------------------------------------------------------ * main * * ------------------------------------------------------------------*/ int main ( int argc, char **argv ) { int i; if ( !Graphics_init ( WIN_WIDTH, WIN_HEIGHT ) ) { fprintf ( stderr, "Error: could not initialize graphics!\n" ); exit ( -1 ); } if ( !Game_init ( WIN_WIDTH, WIN_HEIGHT ) ) { fprintf ( stderr, "Error: could not initialize game data!\n" ); exit ( -1 ); } Game_main (); Graphics_shutdown (); /* print contact information */ i = 0; while ( game_about_info[i] ) { printf ( "%s\n", game_about_info[i] ); i++; } return 0; } END_OF_MAIN(); /*================================================================*/ int Graphics_init ( unsigned int win_width, unsigned int win_height ) { int i, j; allegro_init (); install_keyboard (); if ( set_gfx_mode ( GFX_AUTODETECT, 640, 480, 0, 0 ) != 0 ) { set_gfx_mode ( GFX_TEXT, 0, 0, 0, 0 ); return FALSE; } buffer = create_bitmap ( win_width, win_height ); set_clip ( buffer, 0, 0, win_width-1, win_height-1 ); clear ( buffer ); /* load default color scheme */ /* red */ for ( i=0, j=0; i<64; i++, j++ ) { pal[i].r = j; pal[i].g = pal[i].b = 0; } /* green */ for ( i=64, j=0; i<128; i++, j++ ) { pal[i].g = j; pal[i].r = pal[i].b = 0; } /* blue */ for ( i=128, j=0; i<192; i++, j++ ) { pal[i].b = j; pal[i].r = pal[i].g = 0; } /* white */ for ( i=192, j=0; i<256; i++, j++ ) { pal[i].r = pal[i].g = pal[i].b = j; } /* yellow */ pal[192].r = 63; pal[192].g = 63; pal[192].b = 32; set_palette ( pal ); return TRUE; } /*================================================================*/ void Graphics_shutdown ( void ) { destroy_bitmap ( buffer ); set_gfx_mode ( GFX_TEXT, 0, 0, 0, 0 ); } /*================================================================*/ int Update_display ( void ) { vsync (); blit ( buffer, screen, 0, 0, 0, 0, WIN_WIDTH, WIN_HEIGHT ); clear ( buffer ); return TRUE; } /*================================================================*/ int Handle_events ( void ) { gv->key_UP = ( key[KEY_UP] ) ? TRUE : FALSE; gv->key_DOWN = ( key[KEY_DOWN] ) ? TRUE : FALSE; gv->key_LEFT = ( key[KEY_LEFT] ) ? TRUE : FALSE; gv->key_RIGHT = ( key[KEY_RIGHT] ) ? TRUE : FALSE; gv->key_FIRE = ( key[KEY_SPACE] ) ? TRUE : FALSE; if ( key[KEY_F] ) gv->display_fps ^= TRUE; if ( key[KEY_P] ) Game_paused_toggle (); if ( key[KEY_Q] ) Game_reset (); if ( key[KEY_ESC] ) return FALSE; return TRUE; } /*================================================================*/ void Draw_line ( int x0, int y0, int x1, int y1, unsigned int color ) { line ( buffer, x0, y0, x1, y1, color ); } /*================================================================*/ void Draw_point ( int x0, int y0, unsigned int color ) { rectfill ( buffer, x0-1, y0-1, x0+1, y0+1, color ); } /*================================================================*/ void Draw_text ( char *message, int x0, int y0, unsigned int color ) { textout ( buffer, font, message, x0, y0-10, color ); } /*================================================================*/ /*------------------------------------------------------------------ * * System msec & sec Timer functions * ------------------------------------------------------------------*/ void Timer_init ( TIMER *t ) { t->init_time_stamp = time ( NULL ); while ( gettimeofday ( &(t->t0), NULL ) < 0 ); while ( gettimeofday ( &(t->t1), NULL ) < 0 ); } /*================================================================*/ CLOCK_T Timer_ticks ( void ) { return clock (); } /*================================================================*/ double Timer_sec ( TIMER *t ) { return difftime ( time(NULL), t->init_time_stamp ); } /*================================================================*/ long Timer_msec ( TIMER *t ) { long msec; if ( gettimeofday ( &(t->t1), NULL ) < 0 ) return -1; msec = ((t->t1.tv_sec-t->t0.tv_sec)*1000L)+ ((t->t1.tv_usec-t->t0.tv_usec)/1000L); t->t0.tv_sec = t->t1.tv_sec; t->t0.tv_usec = t->t1.tv_usec; return msec; } /*================================================================*/ xinvaders3d-1.31/main-w.c000066400000000000000000000315170704743046400152430ustar00rootroot00000000000000/*------------------------------------------------------------------ main-w.c: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis WIN32 port by Thomas Boutell This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #include #include #include "game.h" /*================================================================*/ /* WIN32 globals */ HINSTANCE hInst; HWND win; HPEN color_table_pens [MAX_COLORS]; HBRUSH color_table_brushes [MAX_COLORS]; unsigned short color_data [MAX_COLORS][3]; HPEN blackPen; HBRUSH blackBrush; /* Menu item IDs for the message boxes */ #define aboutItemId 1000 #define rulesItemId 1001 /* window buffers */ HDC double_buffer_dc; HBITMAP double_buffer; HBITMAP double_buffer_old_bitmap; /* misc window info */ char *window_name = "3d"; unsigned int window_width, window_height, display_width, display_height; static void showGameInfo(char **gameInfo, char *title, char *append); /*================================================================*/ int PASCAL WinMain(HINSTANCE hInstCurrent, HINSTANCE hInstPrevious, LPSTR lpszCmdLine, int nCmdShow) { hInst = hInstCurrent; if ( !Graphics_init ( WIN_WIDTH, WIN_HEIGHT ) ) { MessageBox(0, "Error: could not initialize graphics!\n", "XInvaders 3D Error", MB_ICONEXCLAMATION); exit ( -1 ); } if ( !Game_init ( WIN_WIDTH, WIN_HEIGHT ) ) { MessageBox(0, "Error: could not initialize game data!\n", "XInvaders 3D Error", MB_ICONEXCLAMATION); exit ( -1 ); } /* run the game until ESC key is pressed */ while ( Handle_events () ) { /* get start-time of current frame */ gv->msec = Timer_msec ( gt ); gv->ftime = (double)gv->msec/1000L; gv->fps = 1.0 / gv->ftime; gv->fadjust = gv->rfps / gv->fps; /* do game */ (*Game_actionfn)(); /* get end-time of current frame, msec elapsed, and calc fps */ /* update display */ Update_display (); } Graphics_shutdown (); showGameInfo(game_about_info, "About XInvaders 3D", "Ported to Windows by Thomas Boutell"); return 0; } long FAR PASCAL winv3dWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); /*================================================================*/ int Graphics_init ( unsigned int win_width, unsigned int win_height ) { int i, j, width, height; HDC hdc; HPEN oldPen; HBRUSH oldBrush; WNDCLASS wc; MENUITEMINFO menuitem; HMENU menu; int count; width = win_width; height = (int) win_height; window_width = win_width; window_height = win_height; /* Create a window class */ wc.style = 0; wc.lpfnWndProc = winv3dWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = 0; /* LoadIcon(hInst, MAKEINTRESOURCE(WINV3D_ICON)); */ wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = 0; wc.lpszMenuName = 0; wc.lpszClassName = "xinv3d"; if (!RegisterClass(&wc)) { return FALSE; } /* create a simple window*/ win = CreateWindow( "xinv3d", "xinv3d", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, window_width, window_height, HWND_DESKTOP, 0, hInst, 0); /* Get the system menu, so that we can install an about option that explains how to play */ menu = GetSystemMenu(win, FALSE); count = GetMenuItemCount(menu); memset(&menuitem, 0, sizeof(menuitem)); menuitem.fType = MFT_STRING; menuitem.fMask = MIIM_TYPE | MIIM_ID; menuitem.wID = aboutItemId; menuitem.dwTypeData = (DWORD) "&About xinv3d"; menuitem.cch = strlen("&About xinv3d"); menuitem.cbSize = sizeof(menuitem); InsertMenuItem(menu, count, TRUE, &menuitem); memset(&menuitem, 0, sizeof(menuitem)); menuitem.fType = MFT_STRING; menuitem.fMask = MIIM_TYPE | MIIM_ID; menuitem.wID = rulesItemId; menuitem.dwTypeData = (DWORD) "&How to Play"; menuitem.cch = strlen("&How to Play"); menuitem.cbSize = sizeof(menuitem); InsertMenuItem(menu, count, TRUE, &menuitem); /* load default color scheme */ /* red */ for ( i=0, j=0; i<64; i++, j++ ) { color_data[i][0] = 1024 * j; color_data[i][1] = color_data[i][2] = 0; } /* green */ for ( i=64, j=0; i<128; i++, j++ ) { color_data[i][1] = 1024 * j; color_data[i][0] = color_data[i][2] = 0; } /* blue */ for ( i=128, j=0; i<192; i++, j++ ) { color_data[i][2] = 1024 * j; color_data[i][0] = color_data[i][1] = 0; } /* white */ for ( i=192, j=0; i<256; i++, j++ ) { color_data[i][0] = color_data[i][1] = color_data[i][2] = j * 1024; } /* yellow */ color_data[192][0] = 63 * 1024; color_data[192][1] = 63 * 1024; color_data[192][2] = 32 * 1024; for ( i=0; i> 8, color_data[i][1] >> 8, color_data[i][2] >> 8)); color_table_brushes[i] = CreateSolidBrush( RGB(color_data[i][0] >> 8, color_data[i][1] >> 8, color_data[i][2] >> 8)); } blackPen = color_table_pens[BLACK]; blackBrush = color_table_brushes[BLACK]; /* create double buffer */ hdc = GetDC(win); double_buffer = CreateCompatibleBitmap( hdc, window_width, window_height); double_buffer_dc = CreateCompatibleDC(hdc); double_buffer_old_bitmap = SelectObject( double_buffer_dc, double_buffer); SetBkColor(double_buffer_dc, RGB(0, 0, 0)); ReleaseDC(win, hdc); oldPen = SelectObject(double_buffer_dc, blackPen); oldBrush = SelectObject(double_buffer_dc, blackBrush); Rectangle(double_buffer_dc, 0, 0, window_width, window_height); SelectObject(double_buffer_dc, oldPen); SelectObject(double_buffer_dc, oldBrush); /* display the window */ ShowWindow(win, SW_SHOW); return TRUE; } /*================================================================*/ void Graphics_shutdown ( void ) { int i; SelectObject(double_buffer_dc, double_buffer_old_bitmap); DeleteDC(double_buffer_dc); DeleteObject(double_buffer); for ( i=0; i> 8, color_data[color][1] >> 8, color_data[color][2] >> 8)); /* draw text */ TextOut(double_buffer_dc, x0, y0, message, strlen(message)); } /*================================================================*/ long FAR PASCAL winv3dWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { /* * Process whatever messages you want here and send the * rest to DefWindowProc. */ case WM_KEYDOWN: if (lParam & 0x4000000) { /* Repeat */ break; } /* Not Repeat */ switch (wParam) { case VK_SPACE: gv->key_FIRE = TRUE; break; case VK_UP: gv->key_UP = TRUE; break; case VK_DOWN: gv->key_DOWN = TRUE; break; case VK_LEFT: gv->key_LEFT = TRUE; break; case VK_RIGHT: gv->key_RIGHT = TRUE; break; case VK_ESCAPE: /* quit! */ PostMessage(win, WM_QUIT, 0, 0L); return FALSE; break; default: break; } break; case WM_CHAR: switch (wParam) { case 'f': /* display frames per second */ gv->display_fps ^= TRUE; break; case 'p': /* pause */ Game_paused_toggle (); break; case 'q': Game_reset (); break; default: break; } break; case WM_KEYUP: switch (wParam) { case VK_SPACE: gv->key_FIRE = FALSE; break; case VK_UP: gv->key_UP = FALSE; break; case VK_DOWN: gv->key_DOWN = FALSE; break; case VK_LEFT: gv->key_LEFT = FALSE; break; case VK_RIGHT: gv->key_RIGHT = FALSE; break; default: break; } break; case WM_SYSCOMMAND: switch (wParam) { case SC_CLOSE: PostMessage(win, WM_QUIT, 0, 0L); break; case aboutItemId: showGameInfo(game_about_info, "About XInvaders 3D", "Ported to Windows by Thomas Boutell"); break; case rulesItemId: showGameInfo(game_rules_info, "How to Play XInvaders 3D", 0); break; default: /* Inherit default behavior */ return (DefWindowProc(hwnd, msg, wParam, lParam)); } default: /* Inherit default behavior */ return (DefWindowProc(hwnd, msg, wParam, lParam)); } return 0L; } static void showGameInfo(char **gameInfo, char *title, char *append) { /* Must be less than 16K to work properly. */ char message[16384]; strcpy(message, ""); while (*gameInfo) { strcat(message, *gameInfo); strcat(message, "\r\n"); gameInfo++; } if (append) { strcat(message, append); } MessageBox(win, message, title ? title : "XInvaders 3D", MB_ICONINFORMATION); } void Timer_init ( TIMER *t ) { long msec; t->init_time_stamp = time ( NULL ); msec = GetTickCount(); t->t0.tv_sec = msec / 1000; t->t0.tv_usec = (msec % 1000) * 1000; t->t1 = t->t0; } /*================================================================*/ CLOCK_T Timer_ticks ( void ) { return clock (); } /*================================================================*/ double Timer_sec ( TIMER *t ) { return difftime ( time(NULL), t->init_time_stamp ); } /*================================================================*/ long Timer_msec ( TIMER *t ) { long msec = GetTickCount(); t->t1.tv_sec = msec / 1000; t->t1.tv_usec = (msec % 1000) * 1000; msec = ((t->t1.tv_sec-t->t0.tv_sec)*1000L)+ ((t->t1.tv_usec-t->t0.tv_usec)/1000L); t->t0.tv_sec = t->t1.tv_sec; t->t0.tv_usec = t->t1.tv_usec; return msec; } xinvaders3d-1.31/main-x11.c000066400000000000000000000303560704743046400154060ustar00rootroot00000000000000/*------------------------------------------------------------------ main-x11.c: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #include #include #include #include #ifdef __FreeBSD__ #include #endif #include "game.h" /*================================================================*/ /* window structs */ Display *display; int screen_num; Window win; Screen *screen_ptr; XFontStruct *font_info; /* gc's & color data */ GC black_gc, color_gc, text_gc; XGCValues gc_values; unsigned long gc_valuemask = 0; XColor color_info; unsigned int color_table [MAX_COLORS]; unsigned short color_data [MAX_COLORS][3]; /* window buffers */ Pixmap double_buffer; /* misc window info */ char *display_name = NULL; char *window_name = "XInvaders 3D"; XTextProperty wname; char *font_name = "10x20"; unsigned int window_width, window_height, display_width, display_height; /*------------------------------------------------------------------ * main * * ------------------------------------------------------------------*/ int main ( int argc, char **argv ) { int i; #ifdef __FreeBSD__ fpsetmask(0); #endif if ( !Graphics_init ( WIN_WIDTH, WIN_HEIGHT ) ) { fprintf ( stderr, "Error: could not initialize graphics!\n" ); exit ( -1 ); } if ( !Game_init ( WIN_WIDTH, WIN_HEIGHT ) ) { fprintf ( stderr, "Error: could not initialize game data!\n" ); exit ( -1 ); } Game_main (); Graphics_shutdown (); /* print contact information */ i = 0; while ( game_about_info[i] ) { fprintf ( stderr, "%s\n", game_about_info[i] ); i++; } return 0; } /*================================================================*/ int Graphics_init ( unsigned int win_width, unsigned int win_height ) { int i, j; window_width = win_width; window_height = win_height; display = XOpenDisplay ( display_name ); if ( !display ) return FALSE; screen_num = DefaultScreen ( display ); screen_ptr = DefaultScreenOfDisplay ( display ); win = XCreateSimpleWindow ( display, RootWindow ( display, screen_num ), 0, 0, window_width, window_height, 1, BlackPixel ( display, screen_num ), WhitePixel ( display, screen_num ) ); XSelectInput ( display, win, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask ); XStringListToTextProperty ( &window_name, 1, &wname ); XSetWMProperties ( display, win, &wname, NULL, NULL, 0, NULL, NULL, NULL ); /* create GCs for clearing, text, & drawing */ black_gc = XCreateGC ( display, win, gc_valuemask, &gc_values ); color_gc = XCreateGC ( display, win, gc_valuemask, &gc_values ); text_gc = XCreateGC ( display, win, gc_valuemask, &gc_values ); /* load default font */ font_info = XLoadQueryFont ( display, font_name ); if ( !font_info ) perror ( "WARNING: could not load default font.\n" ); else XSetFont ( display, text_gc, font_info->fid ); /* load default color scheme */ /* red */ for ( i=0, j=0; i<64; i++, j++ ) { color_data[i][0] = 1024 * j; color_data[i][1] = color_data[i][2] = 0; } /* green */ for ( i=64, j=0; i<128; i++, j++ ) { color_data[i][1] = 1024 * j; color_data[i][0] = color_data[i][2] = 0; } /* blue */ for ( i=128, j=0; i<192; i++, j++ ) { color_data[i][2] = 1024 * j; color_data[i][0] = color_data[i][1] = 0; } /* white */ for ( i=192, j=0; i<256; i++, j++ ) { color_data[i][0] = color_data[i][1] = color_data[i][2] = j * 1024; } /* yellow */ color_data[192][0] = 63 * 1024; color_data[192][1] = 63 * 1024; color_data[192][2] = 32 * 1024; for ( i=0; ifid ); XFreeGC ( display, black_gc ); XFreeGC ( display, color_gc ); XFreeGC ( display, text_gc ); XAutoRepeatOn ( display ); XCloseDisplay ( display ); } /*================================================================*/ int Update_display ( void ) { XCopyArea ( display, double_buffer, win, black_gc, 0, 0, window_width, window_height, 0, 0 ); XFillRectangle ( display, double_buffer, black_gc, 0, 0, window_width, window_height ); return TRUE; } /*================================================================*/ int Handle_events ( void ) { XEvent event; KeySym keysym; XSync ( display, False ); while ( XPending ( display ) ) { XNextEvent ( display, &event ); switch ( event.type ) { case Expose: break; case EnterNotify: /* turn off auto-repeat */ XAutoRepeatOff ( display ); break; case LeaveNotify: /* turn on auto-repeat */ XAutoRepeatOn ( display ); break; case KeyPress: keysym = XLookupKeysym ( &(event.xkey), 0 ); switch ( keysym ) { case XK_space: gv->key_FIRE = TRUE; break; case XK_Up: case XK_KP_Up: gv->key_UP = TRUE; break; case XK_Down: case XK_KP_Down: gv->key_DOWN = TRUE; break; case XK_Left: case XK_KP_Left: gv->key_LEFT = TRUE; break; case XK_Right: case XK_KP_Right: gv->key_RIGHT = TRUE; break; case XK_f: case XK_F: /* display frames per second */ gv->display_fps ^= TRUE; break; case XK_p: case XK_P: /* pause */ Game_paused_toggle (); break; case XK_q: case XK_Q: Game_reset (); break; case XK_Escape: /* quit! */ return FALSE; break; default: break; } break; case KeyRelease: keysym = XLookupKeysym ( &(event.xkey), 0 ); switch ( keysym ) { case XK_space: gv->key_FIRE = FALSE; break; case XK_Up: case XK_KP_Up: gv->key_UP = FALSE; break; case XK_Down: case XK_KP_Down: gv->key_DOWN = FALSE; break; case XK_Left: case XK_KP_Left: gv->key_LEFT = FALSE; break; case XK_Right: case XK_KP_Right: gv->key_RIGHT = FALSE; break; default: break; } break; default: break; } } return TRUE; } /*================================================================*/ void Draw_line ( int x0, int y0, int x1, int y1, unsigned int color ) { XSetForeground ( display, color_gc, color_table[color] ); XDrawLine ( display, double_buffer, color_gc, x0, y0, x1, y1 ); } /*================================================================*/ void Draw_point ( int x0, int y0, unsigned int color ) { XSetForeground ( display, color_gc, color_table[color] ); XFillRectangle ( display, double_buffer, color_gc, x0-3, y0+3, 3, 3 ); } /*================================================================*/ void Draw_text ( char *message, int x0, int y0, unsigned int color ) { XSetForeground ( display, text_gc, color_table[color] ); XDrawString ( display, double_buffer, text_gc, x0, y0, message, strlen ( message ) ); } /*================================================================*/ /*------------------------------------------------------------------ * * System msec & sec Timer functions * ------------------------------------------------------------------*/ void Timer_init ( TIMER *t ) { t->init_time_stamp = time ( NULL ); gettimeofday ( &(t->t0), NULL ); gettimeofday ( &(t->t1), NULL ); } /*================================================================*/ CLOCK_T Timer_ticks ( void ) { return clock (); } /*================================================================*/ double Timer_sec ( TIMER *t ) { return difftime ( time(NULL), t->init_time_stamp ); } /*================================================================*/ long Timer_msec ( TIMER *t ) { long msec; if ( gettimeofday ( &(t->t1), NULL ) < 0 ) return -1; msec = ((t->t1.tv_sec-t->t0.tv_sec)*1000L)+ ((t->t1.tv_usec-t->t0.tv_usec)/1000L); t->t0.tv_sec = t->t1.tv_sec; t->t0.tv_usec = t->t1.tv_usec; return msec; } /*================================================================*/ xinvaders3d-1.31/mat4x4.c000066400000000000000000000150400704743046400151650ustar00rootroot00000000000000/*------------------------------------------------------------------ mat4x4.c: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #include #include #include #include #include "mat4x4.h" /*================================================================*/ void Matrix_id ( MAT a ) { memset ( a, 0, sizeof ( MAT ) ); a[0][0] = a[1][1] = a[2][2] = a[3][3] = 1.0f; } /*================================================================*/ void Matrix_zero ( MAT a ) { memset ( a, 0, sizeof (MAT ) ); } /*================================================================*/ void Matrix_copy ( MAT a, MAT b ) { memcpy ( b, a, sizeof ( MAT ) ); } /*================================================================*/ void Matrix_print ( MAT a ) { int i, j; for ( i=0; i<4; i++ ) { for (j=0; j<4; j++ ) fprintf ( stderr, "%5.5f ", a[i][j] ); fprintf ( stderr, "\n" ); } } /*================================================================*/ void Matrix_mult ( MAT a, MAT b, MAT c ) { int i; for ( i=0; i<4; i++ ) { c[i][0] = ( a[i][0] * b[0][0] ) + ( a[i][1] * b[1][0] ) + ( a[i][2] * b[2][0] ) + ( a[i][3] * b[3][0] ); c[i][1] = ( a[i][0] * b[0][1] ) + ( a[i][1] * b[1][1] ) + ( a[i][2] * b[2][1] ) + ( a[i][3] * b[3][1] ); c[i][2] = ( a[i][0] * b[0][2] ) + ( a[i][1] * b[1][2] ) + ( a[i][2] * b[2][2] ) + ( a[i][3] * b[3][2] ); c[i][3] = ( a[i][0] * b[0][3] ) + ( a[i][1] * b[1][3] ) + ( a[i][2] * b[2][3] ) + ( a[i][3] * b[3][3] ); } } /*================================================================*/ void Matrix_transpose ( MAT a, MAT b ) { b[0][0] = a[0][0]; b[0][1] = a[1][0]; b[0][2] = a[2][0]; b[0][3] = b[3][0]; b[1][0] = a[0][1]; b[1][1] = a[1][1]; b[1][2] = a[2][1]; b[1][3] = b[3][1]; b[2][0] = a[0][2]; b[2][1] = a[1][2]; b[2][2] = a[2][2]; b[2][3] = b[3][2]; b[3][0] = a[0][3]; b[3][1] = a[1][3]; b[3][2] = a[2][3]; b[3][3] = b[3][3]; } /*================================================================*/ void Matrix_vec_mult ( MAT a, VEC b, VEC c ) { c[0] = ( a[0][0] * b[0] ) + ( a[0][1] * b[1] ) + ( a[0][2] * b[2] ) + ( a[0][3] * b[3] ); c[1] = ( a[1][0] * b[0] ) + ( a[1][1] * b[1] ) + ( a[1][2] * b[2] ) + ( a[1][3] * b[3] ); c[2] = ( a[2][0] * b[0] ) + ( a[2][1] * b[1] ) + ( a[2][2] * b[2] ) + ( a[2][3] * b[3] ); c[3] = ( a[3][0] * b[0] ) + ( a[3][1] * b[1] ) + ( a[3][2] * b[2] ) + ( a[3][3] * b[3] ); } /*================================================================*/ void Matrix_vec_multn ( MAT a, VEC b[], VEC c[], int num ) { int i; for ( i=0; i #include #include #include "mat4x4.h" #include "vec4x1.h" #include "defines.h" #include "object.h" /*================================================================*/ void Objlist_clear ( OBJLIST *lst ) { lst->obj_count = 0; lst->head = NULL; lst->tail = NULL; } /*================================================================*/ void Objlist_add ( OBJLIST *lst, OBJECT *obj ) { OBJECT *tmp; if ( lst->head ) { tmp = lst->tail; lst->tail->next = obj; /* move tail forward */ lst->tail = lst->tail->next; lst->tail->prev = tmp; lst->tail->next = NULL; } /* empty list so initialize head and tail */ else { lst->head = lst->tail = obj; lst->head->prev = lst->tail->prev = NULL; lst->head->next = lst->tail->next = NULL; } lst->obj_count++; } /*================================================================*/ void Objlist_del ( OBJLIST *lst, OBJECT *obj ) { if ( lst->head ) { /* is the object at the head of the list */ if ( obj->prev == NULL ) { /* is object both at head and tail */ if ( obj->next == NULL ) { lst->head = lst->tail = NULL; obj->next = obj->prev = NULL; } else { lst->head = obj->next; lst->head->prev = NULL; } } /* is the object at the end of the list */ else if ( obj->next == NULL ) { lst->tail = obj->prev; lst->tail->next = NULL; } /* otherwise object somewhere in the list */ else { obj->prev->next = obj->next; obj->next->prev = obj->prev; } obj->next = obj->prev = NULL; lst->obj_count--; } } /*================================================================*/ int Objlist_count ( OBJLIST *lst ) { return lst->obj_count; } /*================================================================*/ OBJECT * Object_new ( void ) { OBJECT *obj; obj = ( OBJECT * ) malloc ( sizeof ( OBJECT ) ); return obj; } /*================================================================*/ void Object_delete ( OBJECT *obj ) { free ( obj ); obj = NULL; } /*================================================================*/ void Object_init ( OBJECT *obj ) { obj->active = FALSE; obj->frame = 0L; obj->delay = 0L; obj->max_frame = 0L; obj->zone = 0L; obj->zheight = 0L; Vector_init ( obj->pos ); Vector_init ( obj->old_pos ); Vector_init ( obj->dir ); Vector_init ( obj->thrust ); obj->actionfn = NULL; obj->drawfn = NULL; obj->next = NULL; obj->prev = NULL; } /*================================================================*/ void Object_set_actionfn ( OBJECT *obj, PFV1 actionfn ) { obj->actionfn = actionfn; } /*================================================================*/ void Object_set_drawfn ( OBJECT *obj, PFV2 drawfn ) { obj->drawfn = drawfn; } /*================================================================*/ void Object_set_model ( OBJECT *obj, MODEL *model ) { obj->model = model; } /*================================================================*/ void Object_set_pos ( OBJECT *obj, VEC pos ) { Vector_copy ( pos, obj->pos ); } /*================================================================*/ void Object_get_pos ( OBJECT *obj, VEC pos ) { Vector_copy ( obj->pos, pos ); } /*================================================================*/ void Object_set_dir ( OBJECT *obj, VEC dir ) { Vector_copy ( dir, obj->dir ); } /*================================================================*/ void Object_get_dir ( OBJECT *obj, VEC dir ) { Vector_copy ( obj->dir, dir ); } /*================================================================*/ void Object_draw ( OBJECT *obj ) { } /*================================================================*/ xinvaders3d-1.31/object.h000066400000000000000000000060000704743046400153130ustar00rootroot00000000000000/*------------------------------------------------------------------ object.h: Model Data, Object, and Object-List managment struct & functions XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #ifndef OBJECT_HEADER #define OBJECT_HEADER typedef struct MODELSTRUCT MODEL; typedef struct OBJECTSTRUCT OBJECT; typedef struct OBJLISTSTRUCT OBJLIST; typedef void (*PFV1) ( OBJECT * ); typedef void (*PFV2) ( OBJECT *, MAT ); /*------------------------------------------------------------------ * MODEL: * Model data management Struct & Funtions * ------------------------------------------------------------------*/ struct MODELSTRUCT { int num_vertex; int num_polys; }; /*------------------------------------------------------------------ * OBJECT: * Object Managment Struct & Funtions * ------------------------------------------------------------------*/ struct OBJECTSTRUCT { int active; long frame; long delay; long max_frame; int zone; int zheight; int vpos; float radius; float radius_squared; double rot; VEC pos; VEC old_pos; VEC dir; VEC thrust; PFV1 actionfn; PFV2 drawfn; MODEL *model; OBJECT *next; OBJECT *prev; }; extern OBJECT * Object_new ( void ); extern void Object_delete ( OBJECT * ); extern void Object_init ( OBJECT * ); extern void Object_set_actionfn ( OBJECT *, PFV1 ); extern void Object_set_drawfn ( OBJECT *, PFV2 ); extern void Object_set_model ( OBJECT *, MODEL * ); extern void Object_set_pos ( OBJECT *, VEC ); extern void Object_get_pos ( OBJECT *, VEC ); extern void Object_set_dir ( OBJECT *, VEC ); extern void Object_get_dir ( OBJECT *, VEC ); extern void Object_draw ( OBJECT * ); /*------------------------------------------------------------------ * OBJLIST: * gobject list managment struct & routines * ------------------------------------------------------------------*/ struct OBJLISTSTRUCT { int obj_count; OBJECT *head; OBJECT *tail; }; extern void Objlist_clear ( OBJLIST * ); extern void Objlist_add ( OBJLIST *, OBJECT * ); extern void Objlist_del ( OBJLIST *, OBJECT * ); extern int Objlist_count ( OBJLIST * ); #endif xinvaders3d-1.31/player.c000066400000000000000000000234060704743046400153450ustar00rootroot00000000000000/*------------------------------------------------------------------ player.c: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #include "game.h" /*================================================================*/ #define PLAYER_RADIUS 20.0f #define PLAYER_RADIUS_SQUARED 400.0f #define MISSLE_RADIUS 20.0f #define MISSLE_RADIUS_SQUARED 400.0f #define MAX_X 550.0f #define MIN_X -550.0f #define MAX_Y 450.0f #define MIN_Y 50.0f #define ROT_Z 0.087266463 /* 5 degrees per frame */ #define MAX_ROT 0.785398163 /* max of 45 degrees */ enum player_enum { PLAYER_BLINK = TRUE, PLAYER_BLINK_TIME = 5000 /* 5.0 sec */ }; OBJECT player_1, *player; OBJECT player_missile, *pm; static VEC start_pos = { 0.0f, 250.0f, -25.0f, 1.0f }; static VEC start_dir = { 0.0f, 0.0f, -1.0f, 1.0f }; static VEC thrust_up = { 0.0f, 10.0f, 0.0f, 1.0f }; static VEC thrust_down = { 0.0f, -10.0f, 0.0f, 1.0f }; static VEC thrust_left = { -10.0f, 0.0f, 0.0f, 1.0f }; static VEC thrust_right = { 10.0f, 0.0f, 0.0f, 1.0f }; static VEC missile_offset = { 0.0f, 0.0f, 0.0f, 1.0f }; static VEC missile_thrust = { 0.0f, 0.0f, -50.0f, 1.0f }; static int pcolor; /* Player color */ /*================================================================*/ void Player_init ( void ) { gv->pblinking = TRUE; player = &player_1; Object_init ( player ); Object_set_actionfn ( player, Player_update ); Object_set_drawfn ( player, Player_blink ); Object_set_pos ( player, start_pos ); Object_set_dir ( player, start_dir ); player->active = TRUE; player->radius = PLAYER_RADIUS; player->radius_squared = PLAYER_RADIUS_SQUARED; player->frame = 0; player->rot = 0.0; pcolor = RED; Object_update_zone ( player ); pm = &player_missile; Object_init ( pm ); pm->radius = MISSLE_RADIUS; pm->radius_squared = MISSLE_RADIUS_SQUARED; Object_set_actionfn ( pm, Player_missile_update ); Object_set_drawfn ( pm, Player_missile_draw ); } /*================================================================*/ void Player_update ( OBJECT *obj ) { if ( gv->key_UP ) { obj->pos[YPOS] += thrust_up[YPOS] * gv->fadjust; Object_update_zone ( obj ); if ( obj->pos[YPOS] > MAX_Y ) obj->pos[YPOS] = MAX_Y; } if ( gv->key_DOWN ) { obj->pos[YPOS] += thrust_down[YPOS] * gv->fadjust; Object_update_zone ( obj ); if ( obj->pos[YPOS] < MIN_Y ) obj->pos[YPOS] = MIN_Y; } if ( gv->key_LEFT ) { obj->pos[XPOS] += thrust_left[XPOS] * gv->fadjust; player->rot += ROT_Z * gv->fadjust; if ( obj->pos[XPOS] < MIN_X ) obj->pos[XPOS] = MIN_X; if ( player->rot > MAX_ROT ) player->rot = MAX_ROT; } if ( gv->key_RIGHT ) { obj->pos[XPOS] += thrust_right[XPOS] * gv->fadjust; player->rot -= ROT_Z * gv->fadjust; if ( obj->pos[XPOS] > MAX_X ) obj->pos[XPOS] = MAX_X; if ( player->rot < -MAX_ROT ) player->rot = -MAX_ROT; } if ( (gv->key_LEFT == FALSE) && (gv->key_RIGHT == FALSE) ) { /* please re-do this major hackyness */ if ( ( player->rot < -0.03 ) || ( player->rot > 0.03 ) ) { if ( player->rot < -0.03 ) { player->rot += ROT_Z * gv->fadjust; if ( player->rot > 0.0 ) player->rot = 0.0; } else { if ( player->rot > 0.03 ) { player->rot -= ROT_Z * gv->fadjust; if ( player->rot < 0.0 ) player->rot = 0.0; } } } } if ( gv->key_FIRE && !pm->active ) { pm->active = TRUE; pm->zone = obj->zone; pm->zheight = obj->zheight; Vector_init ( pm->pos ); Vector_copy ( obj->pos, pm->pos ); Vector_copy ( obj->pos, pm->old_pos ); Vector_addd ( pm->pos, missile_offset ); } } void Player_blink ( OBJECT *obj, MAT r ) { static long blink = 0; static int color = 0; blink += gv->msec; if ( blink > 50 ) { blink -= 250; color++; if ( color == 3 ) color = 0; } pcolor = RED - ( color * 15 ); obj->frame += gv->msec; if ( obj->frame > PLAYER_BLINK_TIME ) { pcolor = RED; gv->pblinking = FALSE; Object_set_drawfn ( obj, Player_draw ); } Player_draw ( obj, r ); } void Player_draw ( OBJECT *obj, MAT r ) { int p[32]; VEC tmp[16], rot_vert[16]; MAT tmp_mat, rot_mat; VEC offset; VEC player_vert [16] = { { -5.0f, 0.0f, 15.0f, 1.0f }, /*body*/ { -10.0f, 0.0f, -20.0f, 1.0f }, { 10.0f, 0.0f, -20.0f, 1.0f }, { 5.0f, 0.0f, 15.0f, 1.0f }, { -5.0f, 10.0f, -18.0f, 1.0f }, { 5.0f, 10.0f, -18.0f, 1.0f }, { -5.0f, 0.0f, 20.0f, 1.0f }, /* left e*/ { -10.0f, 0.0f, -15.0f, 1.0f }, { -12.0f, 0.0f, -12.0f, 1.0f }, { -10.0f, 0.0f, 25.0f, 1.0f }, { 5.0f, 0.0f, 20.0f, 1.0f }, /* re */ { 10.0f, 0.0f, -15.0f, 1.0f }, { 12.0f, 0.0f, -12.0f, 1.0f }, { 10.0f, 0.0f, 25.0f, 1.0f }, { -20.0f, -5.0f, 35.0f, 1.0f }, /*lw*/ { 20.0f, -5.0f, 35.0f, 1.0f } }; /*rw*/ VEC cross_hairs[4] = { { -15.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 15.0f, 0.0f, 1.0f }, { 15.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, -15.0f, 0.0f, 1.0f } }; Matrix_vec_mult ( r, obj->pos, tmp[0] ); Matrix_copy ( r, tmp_mat ); Matrix_set_trans ( tmp_mat, tmp[0] ); Matrix_z_rot ( rot_mat, player->rot ); Matrix_vec_multn ( rot_mat, player_vert, rot_vert, 16 ); Matrix_vec_multn ( tmp_mat, rot_vert, tmp, 16 ); Camera_project_points ( tmp, p, 16 ); /* body bottom */ Draw_line ( p[0], p[1], p[2], p[3], pcolor ); Draw_line ( p[2], p[3], p[4], p[5], pcolor ); Draw_line ( p[4], p[5], p[6], p[7], pcolor ); Draw_line ( p[6], p[7], p[0], p[1], pcolor ); /* body top */ Draw_line ( p[0], p[1], p[8], p[9], pcolor ); Draw_line ( p[8], p[9], p[2], p[3], pcolor ); Draw_line ( p[4], p[5], p[10], p[11], pcolor ); Draw_line ( p[10], p[11], p[6], p[7], pcolor ); Draw_line ( p[8], p[9], p[10], p[11], pcolor ); /* left e*/ Draw_line ( p[12], p[13], p[14], p[15], pcolor ); Draw_line ( p[14], p[15], p[16], p[17], pcolor ); Draw_line ( p[16], p[17], p[18], p[19], pcolor ); Draw_line ( p[18], p[19], p[12], p[13], pcolor ); /* right e */ Draw_line ( p[20], p[21], p[22], p[23], pcolor ); Draw_line ( p[22], p[23], p[24], p[25], pcolor ); Draw_line ( p[24], p[25], p[26], p[27], pcolor ); Draw_line ( p[26], p[27], p[20], p[21], pcolor ); /* left wing */ Draw_line ( p[28], p[29], p[16], p[17], pcolor ); Draw_line ( p[28], p[29], p[18], p[19], pcolor ); /* right wing */ Draw_line ( p[30], p[31], p[24], p[25], pcolor ); Draw_line ( p[30], p[31], p[26], p[27], pcolor ); /* update cross-hairs */ Vector_copy ( obj->pos, tmp[0] ); Vector_init ( offset ); offset[ZPOS] = -((gv->formation_zone * 100.0f) + 50.0f); Vector_addd ( tmp[0], offset ); Matrix_vec_mult ( r, tmp[0], tmp[1] ); Matrix_copy ( r, tmp_mat ); Matrix_set_trans ( tmp_mat, tmp[1] ); Matrix_vec_multn ( rot_mat, cross_hairs, rot_vert, 4 ); Matrix_vec_multn ( tmp_mat, rot_vert, tmp, 4 ); Camera_project_points ( tmp, p, 4 ); Draw_line ( p[0], p[1], p[2], p[3], WHITE ); Draw_line ( p[2], p[3], p[4], p[5], WHITE ); Draw_line ( p[4], p[5], p[6], p[7], WHITE ); Draw_line ( p[6], p[7], p[0], p[1], WHITE ); } /*================================================================*/ void Player_missile_update ( OBJECT *obj ) { Vector_copy ( obj->pos, obj->old_pos ); obj->pos[ZPOS] += missile_thrust[ZPOS] * gv->fadjust; Object_update_zone ( obj ); if ( obj->zone > ZONE_9 ) obj->active = FALSE; } void Player_missile_draw ( OBJECT *obj, MAT r ) { VEC tmp[4]; MAT tmp_mat; int p[8]; VEC missile_vert[4] = { {-10.0f, 0.0f, -5.0f, 1.0f}, {0.0f, 0.0f, -10.0f, 1.0f}, {10.0f, 0.0f, -5.0f, 1.0f}, {0.0f, 0.0f, 20.0f, 1.0f}}; Matrix_vec_mult ( r, obj->pos, tmp[0] ); Matrix_copy ( r, tmp_mat ); Matrix_set_trans ( tmp_mat, tmp[0] ); Matrix_vec_multn ( tmp_mat, missile_vert, tmp, 4 ); Camera_project_points ( tmp, p, 4 ); Draw_line ( p[0], p[1], p[2], p[3], YELLOW ); Draw_line ( p[2], p[3], p[4], p[5], YELLOW ); Draw_line ( p[4], p[5], p[6], p[7], YELLOW ); Draw_line ( p[6], p[7], p[0], p[1], YELLOW ); } /*================================================================*/ xinvaders3d-1.31/system.h000066400000000000000000000047120704743046400154010ustar00rootroot00000000000000/*------------------------------------------------------------------ system.h: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #ifndef GAME_SYSTEM_FUNCTIONS #define GAME_SYSTEM_FUNCTIONS /*------------------------------------------------------------------ * * Misc Functions & Graphics primitives: * LINUX/X11 : main-x11.c * ------------------------------------------------------------------*/ #define WIN_WIDTH 640 #define WIN_HEIGHT 480 #define MAX_COLORS 256 extern int Graphics_init ( unsigned int, unsigned int ); extern void Graphics_shutdown ( void ); extern int Update_display ( void ); extern int Handle_events ( void ); extern void Draw_line ( int, int, int, int, unsigned int ); extern void Draw_point ( int, int, unsigned int ); extern void Draw_text ( char *, int, int, unsigned int ); /*------------------------------------------------------------------ * * System msec & sec Timer functions: * LINUX/X11 : main-x11.c * ------------------------------------------------------------------*/ #ifdef GAME_LINUX_X11 #include #include #include #define TIME_T time_t #define TIMEVAL struct timeval #define CLOCK_T clock_t #endif #ifdef GAME_WIN32 #include #define TIME_T time_t #define TIMEVAL struct timeval #define CLOCK_T clock_t #endif #ifdef GAME_DOS_DJGPP #endif typedef struct TIMERSTRUCT TIMER; struct TIMERSTRUCT { TIME_T init_time_stamp; TIMEVAL t0; TIMEVAL t1; }; extern void Timer_init ( TIMER * ); extern CLOCK_T Timer_ticks ( void ); extern double Timer_sec ( TIMER * ); extern long Timer_msec ( TIMER * ); #endif xinvaders3d-1.31/vec4x1.c000066400000000000000000000074740704743046400151720ustar00rootroot00000000000000/*------------------------------------------------------------------ vec4x1.c: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #include #include #include #include #include "vec4x1.h" /*================================================================*/ void Vector_init ( VEC a ) { a[0] = a[1] = a[2] = 0.0f; a[3] = 1.0f; } /*================================================================*/ void Vector_set ( VEC a, float x, float y, float z ) { a[0] = x; a[1] = y; a[2] = z; a[3] = 1.0f; } /*================================================================*/ void Vector_copy ( VEC a, VEC b ) { memcpy ( b, a, sizeof ( VEC ) ); } /*================================================================*/ void Vector_print ( VEC a ) { fprintf ( stderr, "%5.5f %5.5f %5.5f\n", a[0], a[1], a[2] ); } /*================================================================*/ void Vector_negate ( VEC a ) { a[0] *= -1.0f; a[1] *= -1.0f; a[2] *= -1.0f; } /*================================================================*/ void Vector_add ( VEC a, VEC b, VEC c ) { c[0] = a[0] + b[0]; c[1] = a[1] + b[1]; c[2] = a[2] + b[2]; } void Vector_addd ( VEC a, VEC b ) { a[0] = a[0] + b[0]; a[1] = a[1] + b[1]; a[2] = a[2] + b[2]; } /*================================================================*/ void Vector_sub ( VEC a, VEC b, VEC c ) { c[0] = a[0] - b[0]; c[1] = a[1] - b[1]; c[2] = a[2] - b[2]; } void Vector_subb ( VEC a, VEC b ) { a[0] = a[0] - b[0]; a[1] = a[1] - b[1]; a[2] = a[2] - b[2]; } /*================================================================*/ void Vector_cross ( VEC a, VEC b, VEC c ) { c[0] = ( a[1] * b[2] ) - ( a[2] * b[1] ); c[1] = ( a[2] * b[0] ) - ( a[0] * b[2] ); c[2] = ( a[0] * b[1] ) - ( a[1] * b[0] ); } /*================================================================*/ float Vector_mag ( VEC a ) { return (float) sqrt ( ( a[0] * a[0] + a[1] * a[1] + a[2] * a[2] ) ); } float Vector_mag_squared ( VEC a ) { return ( a[0] * a[0] + a[1] * a[1] + a[2] * a[2] ); } /*================================================================*/ float Vector_dist ( VEC a, VEC b ) { float x, y, z; x = b[0] - a[0]; y = b[1] - a[1]; z = b[2] - a[2]; return (float) sqrt ( (x*x) + (y*y) + (z*z) ); } /*================================================================*/ float Vector_dist_squared ( VEC a, VEC b ) { float x, y, z; x = b[0] - a[0]; y = b[1] - a[1]; z = b[2] - a[2]; return ( (x*x) + (y*y) + (z*z) ); } /*================================================================*/ float Vector_dot ( VEC a, VEC b ) { return ( (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]) ); } /*================================================================*/ void Vector_norm ( VEC a ) { float len; len = (float) sqrt ( (a[0] * a[0]) + (a[1] * a[1]) + (a[2] * a[2]) ); a[0] /= len; a[1] /= len; a[2] /= len; } /*================================================================*/ xinvaders3d-1.31/vec4x1.h000066400000000000000000000032560704743046400151710ustar00rootroot00000000000000/*------------------------------------------------------------------ vec4x1.h: XINVADERS 3D - 3d Shoot'em up Copyright (C) 2000 Don Llopis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------*/ #ifndef VEC4x1_DEF #define VEC4x1_DEF typedef float VEC [4]; extern void Vector_init ( VEC ); extern void Vector_set ( VEC, float, float, float ); extern void Vector_copy ( VEC, VEC ); extern void Vector_print ( VEC ); extern void Vector_negate ( VEC ); extern void Vector_add ( VEC, VEC, VEC ); extern void Vector_addd ( VEC, VEC ); extern void Vector_sub ( VEC, VEC, VEC ); extern void Vector_subb ( VEC, VEC ); extern void Vector_cross ( VEC, VEC, VEC ); extern float Vector_mag ( VEC ); extern float Vector_mag_squared ( VEC ); extern float Vector_dist ( VEC, VEC ); extern float Vector_dist_squared ( VEC, VEC ); extern float Vector_dot ( VEC, VEC ); extern void Vector_norm ( VEC ); #endif