Remove unnecessary projects and libs

This commit is contained in:
Miguel Horta
2022-06-17 12:02:21 +01:00
parent 8c03645bce
commit e4939e3f3f
8360 changed files with 0 additions and 3346261 deletions

77
.gitmodules vendored
View File

@@ -1,38 +1,3 @@
[submodule "project/jni/application/NewRAW"]
path = project/jni/application/NewRAW
url = https://github.com/usineur/android-newraw.git
[submodule "project/jni/boost/src"]
path = project/jni/boost/src
url = https://github.com/moritz-wundke/Boost-for-Android.git
branch = master
update = merge
[submodule "project/jni/application/commandergenius/commandergenius"]
path = project/jni/application/commandergenius/commandergenius
url = https://github.com/gerstrong/Commander-Genius.git
[submodule "project/jni/application/openarena/engine"]
path = project/jni/application/openarena/engine
url = https://github.com/pelya/openarena-engine.git
[submodule "project/jni/application/openarena/vm"]
path = project/jni/application/openarena/vm
url = https://github.com/pelya/openarena-vm
[submodule "project/jni/application/teeworlds/src"]
path = project/jni/application/teeworlds/src
url = https://github.com/pelya/teeworlds.git
[submodule "project/jni/application/xserver/xserver"]
path = project/jni/application/xserver/xserver
url = https://github.com/pelya/xserver.git
branch = xsdl-1.20
update = merge
[submodule "android-shmem"]
path = project/jni/shmem
url = https://github.com/pelya/android-shmem.git
branch = master
update = merge
[submodule "project/jni/application/hid-pc-keyboard/src"]
path = project/jni/application/hid-pc-keyboard/src
url = https://github.com/pelya/android-keyboard-gadget.git
branch = master
update = merge
[submodule "project/jni/iconv/src"]
path = project/jni/iconv/src
url = https://github.com/pelya/libiconv-libicu-android.git
@@ -42,48 +7,6 @@
path = project/jni/application/openttd/src
url = https://github.com/n-ice-community/openttd-android.git
branch = 12
[submodule "project/jni/application/uae4all2"]
path = project/jni/application/uae4all2
url = https://github.com/lubomyr/uae4all2.git
[submodule "project/jni/application/basiliskii/basiliskii"]
path = project/jni/application/basiliskii/basiliskii
url = https://github.com/pelya/BasiliskII-android.git
[submodule "project/jni/vncserver/src"]
path = project/jni/vncserver/src
url = https://github.com/LibVNC/libvncserver.git
[submodule "project/jni/application/vice/vice"]
path = project/jni/application/vice/vice
url = https://github.com/lubomyr/vice-2.4.git
[submodule "project/jni/application/xserver/pulseaudio"]
path = project/jni/application/xserver/pulseaudio
url = https://github.com/pelya/pulseaudio-android.git
branch = master
[submodule "project/jni/application/supertux/supertux"]
path = project/jni/application/supertux/supertux
url = https://github.com/pelya/supertux.git
[submodule "project/jni/application/fheroes2/fheroes2"]
path = project/jni/application/fheroes2/fheroes2
url = https://github.com/gerstrong/fheroes2plus.git
[submodule "project/jni/application/ninslash/src"]
path = project/jni/application/ninslash/src
url = https://github.com/pelya/Ninslash.git
branch = master
update = merge
[submodule "project/jni/application/openttd-jgrpp/src"]
path = project/jni/application/openttd-jgrpp/src
url = https://github.com/pelya/OpenTTD-JGR-patchpack.git
branch = android-desktop
[submodule "project/jni/application/liero/src"]
path = project/jni/application/liero/src
url = https://github.com/pelya/liero-android.git
[submodule "project/jni/application/openlierox/src"]
path = project/jni/application/openlierox/src
url = https://github.com/albertz/openlierox.git
branch = half-assed-android-port
[submodule "project/jni/application/xserver-debian/debian-image"]
path = project/jni/application/xserver-debian/debian-image
url = https://github.com/pelya/debian-noroot
branch = master
[submodule "project/jni/sdl2"]
path = project/jni/sdl2
url = https://github.com/libsdl-org/SDL.git

View File

@@ -1,34 +0,0 @@
# The application settings for Android libSDL port
AppSettingVersion=16
LibSdlVersion=1.2
AppName="REminiscence"
AppFullName=fr.freecyxdown.sdl
ScreenOrientation=h
InhibitSuspend=n
AppDataDownloadUrl="Data files size is 1 Mb|http://anddev.at.ua/data/reminiscence-data.zip?attredirects=0&d=1"
SdlVideoResize=y
SdlVideoResizeKeepAspect=n
NeedDepthBuffer=n
AppUsesMouse=n
AppNeedsTwoButtonMouse=n
AppNeedsArrowKeys=y
AppNeedsTextInput=y
AppUsesJoystick=n
AppHandlesJoystickSensitivity=n
AppUsesMultitouch=n
NonBlockingSwapBuffers=n
RedefinedKeys="RSHIFT RETURN BACKSPACE RETURN SPACE"
AppTouchscreenKeyboardKeysAmount=3
AppTouchscreenKeyboardKeysAmountAutoFire=0
RedefinedKeysScreenKb="RSHIFT RETURN BACKSPACE RETURN SPACE"
MultiABI=n
AppVersionCode=01901
AppVersionName="0.1.9"
CompiledLibraries="jpeg png"
CustomBuildScript=n
AppCflags='-Dmain=SDL_main -DBYPASS_PROTECTION'
AppLdflags=''
AppSubdirsBuild=''
AppUseCrystaXToolchain=n
AppCmdline=''
ReadmeText='^You may press "Home" now - the data will be downloaded in background'

View File

@@ -1,20 +0,0 @@
#!/bin/sh
LOCAL_PATH=`dirname $0`
LOCAL_PATH=`cd $LOCAL_PATH && pwd`
# Hacks for broken configure scripts
#rm -rf $LOCAL_PATH/../../obj/local/armeabi/libSDL_*.so
#rm -rf $LOCAL_PATH/../../obj/local/armeabi/libsdl_main.so
# Uncomment if your configure expects SDL libraries in form "libSDL_name.so"
#if [ -e $LOCAL_PATH/../../obj/local/armeabi/libsdl_mixer.so ] ; then
# ln -sf libsdl_mixer.so $LOCAL_PATH/../../obj/local/armeabi/libSDL_Mixer.so
#fi
#for F in $LOCAL_PATH/../../obj/local/armeabi/libsdl_*.so; do
# LIBNAME=`echo $F | sed "s@$LOCAL_PATH/../../obj/local/armeabi/libsdl_\(.*\)[.]so@\1@"`
# ln -sf libsdl_$LIBNAME.so $LOCAL_PATH/../../obj/local/armeabi/libSDL_$LIBNAME.so
#done
../setEnvironment.sh make -C REminiscence-0.1.9 -j2 && cp -f REminiscence-0.1.9/rs libapplication.so

View File

@@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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) year 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.
<signature of Ty Coon>, 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.

View File

@@ -1,29 +0,0 @@
SDL_CFLAGS = `sdl-config --cflags` -Dmain=SDL_main -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -I/home/lubomyr/src/endless_space/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/include -I/home/lubomyr/project/jni/sdl-1.2/include
SDL_LIBS = `sdl-config --libs` -nostdlib -Wl,-soname,libapplication.so -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive /home/lubomyr/src/endless_space/android-ndk-r4-crystax/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /home/lubomyr/src/endless_space/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/lib/libc.a -L/home/lubomyr/project/obj/local/armeabi -lsdl-1.2 -lm -llog -lgcc -L/home/lubomyr/src/endless_space/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/lib
DEFINES = -DBYPASS_PROTECTION
#DEFINES = -DBYPASS_PROTECTION -DNDEBUG
CXX = arm-eabi-g++
CXXFLAGS:= -g -Wall -Wuninitialized -Wno-unknown-pragmas -Wshadow -Wimplicit
CXXFLAGS+= -Wundef -Wreorder -Wwrite-strings -Wnon-virtual-dtor -Wno-multichar
CXXFLAGS+= $(SDL_CFLAGS) $(DEFINES)
SRCS = collision.cpp cutscene.cpp file.cpp game.cpp graphics.cpp main.cpp menu.cpp \
mixer.cpp mod_player.cpp piege.cpp resource.cpp scaler.cpp sfx_player.cpp \
staticres.cpp systemstub_sdl.cpp unpack.cpp util.cpp video.cpp
OBJS = $(SRCS:.cpp=.o)
DEPS = $(SRCS:.cpp=.d)
rs: $(OBJS)
$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(SDL_LIBS) -lz
.cpp.o:
$(CXX) $(CXXFLAGS) -MMD -c $< -o $*.o
clean:
rm -f *.o *.d
-include $(DEPS)

View File

@@ -1,138 +0,0 @@
REminiscence README
Release version: 0.1.9 (Mar 16 2007)
-------------------------------------------------------------------------------
About:
------
REminiscence is a re-implementation of the engine used in the game Flashback
made by Delphine Software and released in 1992. More informations about the
game can be found at [1], [2] and [3].
Supported Versions:
-------------------
Only the PC DOS versions are supported. The engine has been reported to work
with english, french, german and spanish versions of the game.
Compiling:
----------
Tweak the Makefile if needed and type make (only gcc3 has been tested so far).
The SDL and zlib libraries are required.
Data Files:
-----------
You will need the original files, here is the required list :
FB_TXT.FNT
GLOBAL.ICN
GLOBAL.FIB
GLOBAL.SPC
*.OFF
*.SPR
*.MAP
*.PAL
*.ANI
*.CT
*.MBK
*.OBJ
*.PGE
*.RP
*.TBN
*.CMD
*.POL
*CINE.*
If you have a version distributed by SSI, you'll have to rename some files :
logosssi.cmd -> logos.cmd
logosssi.pol -> logos.pol
menu1ssi.map -> menu1.map
menu1ssi.pal -> menu1.pal
In order to hear music, you'll need the original music files (.mod) of the
amiga version. Copy them to the DATA directory and rename them like this :
mod.flashback-ascenseur
mod.flashback-ceinturea
mod.flashback-chute
mod.flashback-desintegr
mod.flashback-donneobjt
mod.flashback-fin
mod.flashback-fin2
mod.flashback-game_over
mod.flashback-holocube
mod.flashback-introb
mod.flashback-jungle
mod.flashback-logo
mod.flashback-memoire
mod.flashback-missionca
mod.flashback-options1
mod.flashback-options2
mod.flashback-reunion
mod.flashback-taxi
mod.flashback-teleport2
mod.flashback-teleporta
mod.flashback-voyage
Running:
--------
By default, the engine will try to load the game data files from the 'DATA'
directory (as the original game did). The savestates are saved in the current
directory. These paths can be changed using command line switches :
Usage: rs [OPTIONS]...
--datapath=PATH Path to data files (default 'DATA')
--savepath=PATH Path to save files (default '.')
In-game hotkeys :
Arrow Keys move Conrad
Enter use the current inventory object
Shift talk / use / run / shoot
Escape display the options
Backspace display the inventory
Alt Enter toggle windowed/fullscreen mode
Alt + and - change video scaler
Ctrl S save game state
Ctrl L load game state
Ctrl + and - change game state slot
Ctrl R toggle input keys record
Ctrl P toggle input keys replay
Debug hotkeys :
Ctrl F toggle fast mode
Ctrl I set Conrad life counter to 32767
Ctrl B toggle display of updated dirty blocks
Ctrl M mirror mode (just a hack, really)
Credits:
--------
Delphine Software, obviously, for making another great game.
Yaz0r, Pixel and gawd for sharing information they gathered on the game.
Contact:
--------
Gregory Montoir, cyx@users.sourceforge.net
URLs:
-----
[1] http://www.mobygames.com/game/flashback-the-quest-for-identity
[2] http://en.wikipedia.org/wiki/Flashback:_The_Quest_for_Identity
[3] http://ramal.free.fr/fb_en.htm

View File

@@ -1,523 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "game.h"
#include "resource.h"
void Game::col_prepareRoomState() {
memset(_col_activeCollisionSlots, 0xFF, sizeof(_col_activeCollisionSlots));
_col_currentLeftRoom = _res._ctData[CT_LEFT_ROOM + _currentRoom];
_col_currentRightRoom = _res._ctData[CT_RIGHT_ROOM + _currentRoom];
for (int i = 0; i != _col_curPos; ++i) {
CollisionSlot *_di = _col_slotsTable[i];
uint8 room = _di->ct_pos / 64;
if (room == _currentRoom) {
_col_activeCollisionSlots[0x30 + (_di->ct_pos & 0x3F)] = i;
} else if (room == _col_currentLeftRoom) {
_col_activeCollisionSlots[0x00 + (_di->ct_pos & 0x3F)] = i;
} else if (room == _col_currentRightRoom) {
_col_activeCollisionSlots[0x60 + (_di->ct_pos & 0x3F)] = i;
}
}
#ifdef DEBUG_COLLISION
printf("---\n");
for (int y = 0; y < 7; ++y) {
for (int x = 0; x < 16; ++x) {
printf("%d", _res._ctData[0x100 + _currentRoom * 0x70 + y * 16 + x]);
}
printf("\n");
}
#endif
}
void Game::col_clearState() {
_col_curPos = 0;
_col_curSlot = _col_slots;
}
void Game::col_preparePiegeState(LivePGE *pge) {
debug(DBG_COL, "Game::col_preparePiegeState() pge_num=%d", pge - &_pgeLive[0]);
CollisionSlot *ct_slot1, *ct_slot2;
if (pge->init_PGE->unk1C == 0) {
pge->collision_slot = 0xFF;
return;
}
int i = 0;
ct_slot1 = 0;
for (int c = 0; c < pge->init_PGE->unk1C; ++c) {
ct_slot2 = _col_curSlot;
if (ct_slot2 + 1 > &_col_slots[255])
return;
_col_curSlot = ct_slot2 + 1;
int16 pos = col_getGridPos(pge, i);
if (pos < 0) {
if (ct_slot1 == 0) {
pge->collision_slot = 0xFF;
} else {
ct_slot1->index = 0xFFFF;
}
return;
}
ct_slot2->ct_pos = pos;
ct_slot2->live_pge = pge;
ct_slot2->index = 0xFFFF;
int16 _ax = col_findSlot(pos);
if (_ax >= 0) {
ct_slot2->prev_slot = _col_slotsTable[_ax];
_col_slotsTable[_ax] = ct_slot2;
if (ct_slot1 == 0) {
pge->collision_slot = _ax;
} else {
ct_slot1->index = _ax;
}
LivePGE *temp_pge = ct_slot2->live_pge;
if (temp_pge->flags & 0x80) {
_pge_liveTable2[temp_pge->index] = temp_pge;
temp_pge->flags |= 4;
}
if (ct_slot2->prev_slot) {
temp_pge = ct_slot2->prev_slot->live_pge;
if (temp_pge->flags & 0x80) {
_pge_liveTable2[temp_pge->index] = temp_pge;
temp_pge->flags |= 4;
}
}
} else {
ct_slot2->prev_slot = 0;
_col_slotsTable[_col_curPos] = ct_slot2;
if (ct_slot1 == 0) {
pge->collision_slot = _col_curPos;
} else {
ct_slot1->index = _col_curPos;
}
_col_curPos++;
}
ct_slot1 = ct_slot2;
i += 0x10;
}
}
uint16 Game::col_getGridPos(LivePGE *pge, int16 dx) {
int16 x = pge->pos_x + dx;
int16 y = pge->pos_y;
int8 c = pge->room_location;
if (c < 0) return 0xFFFF;
if (x < 0) {
c = _res._ctData[CT_LEFT_ROOM + c];
if (c < 0) return 0xFFFF;
x += 256;
} else if (x >= 256) {
c = _res._ctData[CT_RIGHT_ROOM + c];
if (c < 0) return 0xFFFF;
x -= 256;
} else if (y < 0) {
c = _res._ctData[CT_UP_ROOM + c];
if (c < 0) return 0xFFFF;
y += 216;
} else if (y >= 216) {
c = _res._ctData[CT_DOWN_ROOM + c];
if (c < 0) return 0xFFFF;
y -= 216;
}
x = (x + 8) >> 4;
y = (y - 8) / 72;
if (x < 0 || x > 15 || y < 0 || y > 2) {
return 0xFFFF;
} else {
return y * 16 + x + c * 64;
}
}
int16 Game::col_findSlot(int16 pos) {
for (uint16 i = 0; i < _col_curPos; ++i) {
if (_col_slotsTable[i]->ct_pos == pos)
return i;
}
return -1;
}
int16 Game::col_getGridData(LivePGE *pge, int16 dy, int16 dx) {
if (_pge_currentPiegeFacingDir) {
dx = -dx;
}
const int16 pge_grid_y = _col_currentPiegeGridPosY + dy;
const int16 pge_grid_x = _col_currentPiegeGridPosX + dx;
const int8 *room_ct_data;
int8 next_room;
if (pge_grid_x < 0) {
room_ct_data = &_res._ctData[CT_LEFT_ROOM];
next_room = room_ct_data[pge->room_location];
if (next_room < 0) return 1;
room_ct_data += pge_grid_x + 16 + pge_grid_y * 16 + next_room * 0x70;
return (int16)room_ct_data[0x40];
} else if (pge_grid_x >= 16) {
room_ct_data = &_res._ctData[CT_RIGHT_ROOM];
next_room = room_ct_data[pge->room_location];
if (next_room < 0) return 1;
room_ct_data += pge_grid_x - 16 + pge_grid_y * 16 + next_room * 0x70;
return (int16)room_ct_data[0x80];
} else if (pge_grid_y < 1) {
room_ct_data = &_res._ctData[CT_UP_ROOM];
next_room = room_ct_data[pge->room_location];
if (next_room < 0) return 1;
room_ct_data += pge_grid_x + (pge_grid_y + 6) * 16 + next_room * 0x70;
return (int16)room_ct_data[0x100];
} else if (pge_grid_y >= 7) {
room_ct_data = &_res._ctData[CT_DOWN_ROOM];
next_room = room_ct_data[pge->room_location];
if (next_room < 0) return 1;
room_ct_data += pge_grid_x + (pge_grid_y - 6) * 16 + next_room * 0x70;
return (int16)room_ct_data[0xC0];
} else {
room_ct_data = &_res._ctData[0x100];
room_ct_data += pge_grid_x + pge_grid_y * 16 + pge->room_location * 0x70;
return (int16)room_ct_data[0];
}
}
LivePGE *Game::col_findPiege(LivePGE *pge, uint16 arg2) {
if (pge->collision_slot != 0xFF) {
CollisionSlot *slot = _col_slotsTable[pge->collision_slot];
while (slot) {
if (slot->live_pge == pge) {
slot = slot->prev_slot;
} else {
if (arg2 == 0xFFFF || arg2 == slot->live_pge->init_PGE->object_type) {
return slot->live_pge;
} else {
slot = slot->prev_slot;
}
}
}
}
return 0;
}
uint8 Game::col_findCurrentCollidingObject(LivePGE *pge, uint8 n1, uint8 n2, uint8 n3, LivePGE **pge_out) {
if (pge_out) {
*pge_out = pge;
}
if (pge->collision_slot != 0xFF) {
CollisionSlot *cs = _col_slotsTable[pge->collision_slot];
while (cs) {
LivePGE *col_pge = cs->live_pge;
if (pge_out) {
*pge_out = col_pge;
}
if (col_pge->init_PGE->object_type == n1 ||
col_pge->init_PGE->object_type == n2 ||
col_pge->init_PGE->object_type == n3) {
return col_pge->init_PGE->colliding_icon_num;
} else {
cs = cs->prev_slot;
}
}
}
return 0;
}
int16 Game::col_detectHit(LivePGE *pge, int16 arg2, int16 arg4, col_Callback1 callback1, col_Callback2 callback2, int16 argA, int16 argC) {
debug(DBG_COL, "col_detectHit()");
int16 pos_dx, pos_dy, var8, varA;
int16 collision_score = 0;
int8 pge_room = pge->room_location;
if (pge_room < 0 || pge_room >= 0x40) {
return 0;
}
int16 thr = pge->init_PGE->counter_values[0];
if (thr > 0) {
pos_dx = -1;
pos_dy = -1;
} else {
pos_dx = 1;
pos_dy = 1;
thr = -thr;
}
if (_pge_currentPiegeFacingDir) {
pos_dx = -pos_dx;
}
int16 grid_pos_x = (pge->pos_x + 8) >> 4;
int16 grid_pos_y = (pge->pos_y / 72);
if (grid_pos_y >= 0 && grid_pos_y <= 2) {
grid_pos_y *= 16;
collision_score = 0;
var8 = 0;
varA = 0;
if (argA != 0) {
var8 = pos_dy;
grid_pos_x += pos_dx;
varA = 1;
}
while (varA <= thr) {
if (grid_pos_x < 0) {
pge_room = _res._ctData[CT_LEFT_ROOM + pge_room];
if (pge_room < 0) break;
grid_pos_x += 16;
}
if (grid_pos_x >= 16) {
pge_room = _res._ctData[CT_RIGHT_ROOM + pge_room];
if (pge_room < 0) break;
grid_pos_x -= 16;
}
int16 slot = col_findSlot(grid_pos_y + grid_pos_x + pge_room * 64);
if (slot >= 0) {
CollisionSlot *cs = _col_slotsTable[slot];
while (cs) {
collision_score += (this->*callback1)(cs->live_pge, pge, arg2, arg4);
cs = cs->prev_slot;
}
}
if ((this->*callback2)(pge, var8, varA, arg2) != 0) {
break;
}
grid_pos_x += pos_dx;
++varA;
var8 += pos_dy;
}
}
if (argC == -1) {
return collision_score;
} else {
return 0;
}
}
int Game::col_detectHitCallback1(LivePGE *pge, int16 dy, int16 unk1, int16 unk2) {
if (col_getGridData(pge, 1, dy) != 0) {
return 1;
} else {
return 0;
}
}
int Game::col_detectHitCallback6(LivePGE *pge, int16 dy, int16 unk1, int16 unk2) {
return 0;
}
int Game::col_detectHitCallback2(LivePGE *pge1, LivePGE *pge2, int16 unk1, int16 unk2) {
if (pge1 != pge2 && (pge1->flags & 4)) {
if (pge1->init_PGE->object_type == unk2) {
if ((pge1->flags & 1) == (pge2->flags & 1)) {
if (col_detectHitCallbackHelper(pge1, unk1) == 0) {
return 1;
}
}
}
}
return 0;
}
int Game::col_detectHitCallback3(LivePGE *pge1, LivePGE *pge2, int16 unk1, int16 unk2) {
if (pge1 != pge2 && (pge1->flags & 4)) {
if (pge1->init_PGE->object_type == unk2) {
if ((pge1->flags & 1) != (pge2->flags & 1)) {
if (col_detectHitCallbackHelper(pge1, unk1) == 0) {
return 1;
}
}
}
}
return 0;
}
int Game::col_detectHitCallback4(LivePGE *pge1, LivePGE *pge2, int16 unk1, int16 unk2) {
if (pge1 != pge2 && (pge1->flags & 4)) {
if (pge1->init_PGE->object_type == unk2) {
if ((pge1->flags & 1) != (pge2->flags & 1)) {
if (col_detectHitCallbackHelper(pge1, unk1) == 0) {
pge_updateGroup(pge2->index, pge1->index, unk1);
return 1;
}
}
}
}
return 0;
}
int Game::col_detectHitCallback5(LivePGE *pge1, LivePGE *pge2, int16 unk1, int16 unk2) {
if (pge1 != pge2 && (pge1->flags & 4)) {
if (pge1->init_PGE->object_type == unk2) {
if ((pge1->flags & 1) == (pge2->flags & 1)) {
if (col_detectHitCallbackHelper(pge1, unk1) == 0) {
pge_updateGroup(pge2->index, pge1->index, unk1);
return 1;
}
}
}
}
return 0;
}
int Game::col_detectHitCallbackHelper(LivePGE *pge, int16 groupId) {
InitPGE *init_pge = pge->init_PGE;
assert(init_pge->obj_node_number < _res._numObjectNodes);
ObjectNode *on = _res._objectNodesMap[init_pge->obj_node_number];
Object *obj = &on->objects[pge->first_obj_number];
int i = pge->first_obj_number;
while (pge->obj_type == obj->type && on->last_obj_number > i) {
if (obj->opcode2 == 0x6B) { // pge_op_isInGroupSlice
if (obj->opcode_arg2 == 0) {
if (groupId == 1 || groupId == 2) return 0xFFFF;
}
if (obj->opcode_arg2 == 1) {
if (groupId == 3 || groupId == 4) return 0xFFFF;
}
} else if (obj->opcode2 == 0x22) { // pge_op_isInGroup
if (obj->opcode_arg2 == groupId) return 0xFFFF;
}
if (obj->opcode1 == 0x6B) { // pge_op_isInGroupSlice
if (obj->opcode_arg1 == 0) {
if (groupId == 1 || groupId == 2) return 0xFFFF;
}
if (obj->opcode_arg1 == 1) {
if (groupId == 3 || groupId == 4) return 0xFFFF;
}
} else if (obj->opcode1 == 0x22) { // pge_op_isInGroup
if (obj->opcode_arg1 == groupId) return 0xFFFF;
}
++obj;
++i;
}
return 0;
}
int Game::col_detectGunHitCallback1(LivePGE *pge, int16 arg2, int16 arg4, int16 arg6) {
int16 _ax = col_getGridData(pge, 1, arg2);
if (_ax != 0) {
if (!(_ax & 2) || (arg6 != 1)) {
return _ax;
}
}
return 0;
}
int Game::col_detectGunHitCallback2(LivePGE *pge1, LivePGE *pge2, int16 arg4, int16) {
if (pge1 != pge2 && (pge1->flags & 4)) {
if (pge1->init_PGE->object_type == 1 || pge1->init_PGE->object_type == 10) {
uint8 id;
if ((pge1->flags & 1) != (pge2->flags & 1)) {
id = 4;
if (arg4 == 0) {
id = 3;
}
} else {
id = 2;
if (arg4 == 0) {
id = 1;
}
}
if (col_detectHitCallbackHelper(pge1, id) != 0) {
pge_updateGroup(pge2->index, pge1->index, id);
return 1;
}
}
}
return 0;
}
int Game::col_detectGunHitCallback3(LivePGE *pge1, LivePGE *pge2, int16 arg4, int16) {
if (pge1 != pge2 && (pge1->flags & 4)) {
if (pge1->init_PGE->object_type == 1 || pge1->init_PGE->object_type == 12 || pge1->init_PGE->object_type == 10) {
uint8 id;
if ((pge1->flags & 1) != (pge2->flags & 1)) {
id = 4;
if (arg4 == 0) {
id = 3;
}
} else {
id = 2;
if (arg4 == 0) {
id = 1;
}
}
if (col_detectHitCallbackHelper(pge1, id) != 0) {
pge_updateGroup(pge2->index, pge1->index, id);
return 1;
}
}
}
return 0;
}
int Game::col_detectGunHit(LivePGE *pge, int16 arg2, int16 arg4, col_Callback1 callback1, col_Callback2 callback2, int16 argA, int16 argC) {
int8 pge_room = pge->room_location;
if (pge_room < 0 || pge_room >= 0x40) return 0;
int16 thr, pos_dx, pos_dy;
if (argC == -1) {
thr = pge->init_PGE->counter_values[0];
} else {
thr = pge->init_PGE->counter_values[3];
}
if (thr > 0) {
pos_dx = -1;
pos_dy = -1;
} else {
pos_dx = 1;
pos_dy = 1;
thr = -thr;
}
if (_pge_currentPiegeFacingDir) {
pos_dx = -pos_dx;
}
int16 grid_pos_x = (pge->pos_x + 8) >> 4;
int16 grid_pos_y = (pge->pos_y - 8) / 72;
if (grid_pos_y >= 0 && grid_pos_y <= 2) {
grid_pos_y *= 16;
int16 var8 = 0;
int16 varA = 0;
if (argA != 0) {
var8 = pos_dy;
grid_pos_x += pos_dx;
varA = 1;
}
while (varA <= thr) {
if (grid_pos_x < 0) {
pge_room = _res._ctData[CT_LEFT_ROOM + pge_room];
if (pge_room < 0) return 0;
grid_pos_x += 0x10;
}
if (grid_pos_x >= 0x10) {
pge_room = _res._ctData[CT_RIGHT_ROOM + pge_room];
if (pge_room < 0) return 0;
grid_pos_x -= 0x10;
}
int16 slot = col_findSlot(pge_room * 64 + grid_pos_x + grid_pos_y);
if (slot >= 0) {
CollisionSlot *cs = _col_slotsTable[slot];
while (cs) {
int r = (this->*callback1)(cs->live_pge, pge, arg2, arg4);
if (r != 0) return r;
cs = cs->prev_slot;
}
}
if ((this->*callback2)(pge, var8, varA, arg2) != 0) {
break;
}
grid_pos_x += pos_dx;
++varA;
var8 += pos_dy;
}
}
return 0;
}

View File

@@ -1,138 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __CUTSCENE_H__
#define __CUTSCENE_H__
#include "intern.h"
#include "graphics.h"
struct ModPlayer;
struct Resource;
struct SystemStub;
struct Video;
struct Cutscene {
typedef void (Cutscene::*OpcodeStub)();
enum {
NUM_OPCODES = 15,
TIMER_SLICE = 15
};
static const OpcodeStub _opcodeTable[];
static const char *_namesTable[];
static const uint16 _offsetsTable[];
static const uint16 _cosTable[];
static const uint16 _sinTable[];
static const uint8 _creditsData[];
static const uint16 _creditsCutSeq[];
static const uint8 _musicTable[];
static const uint8 _protectionShapeData[];
Graphics _gfx;
ModPlayer *_ply;
Resource *_res;
SystemStub *_stub;
Video *_vid;
Version _ver;
uint16 _id;
uint16 _deathCutsceneId;
bool _interrupted;
bool _stop;
uint8 *_polPtr;
uint8 *_cmdPtr;
uint8 *_cmdPtrBak;
uint32 _tstamp;
uint8 _frameDelay;
bool _newPal;
uint8 _palBuf[0x20 * 2];
uint16 _startOffset;
bool _creditsSequence;
uint32 _rotData[4];
uint8 _primitiveColor;
uint8 _clearScreen;
Point _vertices[0x80];
bool _hasAlphaColor;
uint8 _varText;
uint8 _varKey;
int16 _shape_ix;
int16 _shape_iy;
int16 _shape_ox;
int16 _shape_oy;
int16 _shape_cur_x;
int16 _shape_cur_y;
int16 _shape_prev_x;
int16 _shape_prev_y;
uint16 _shape_count;
uint32 _shape_cur_x16;
uint32 _shape_cur_y16;
uint32 _shape_prev_x16;
uint32 _shape_prev_y16;
uint8 _textSep[0x14];
uint8 _textBuf[500];
const uint8 *_textCurPtr;
uint8 *_textCurBuf;
uint8 _textUnk2;
uint8 _creditsTextPosX;
uint8 _creditsTextPosY;
int16 _creditsTextCounter;
uint8 *_page0, *_page1, *_pageC;
Cutscene(ModPlayer *player, Resource *res, SystemStub *stub, Video *vid, Version ver);
void sync();
void copyPalette(const uint8 *pal, uint16 num);
void updatePalette();
void setPalette();
void initRotationData(uint16 a, uint16 b, uint16 c);
uint16 findTextSeparators(const uint8 *p);
void drawText(int16 x, int16 y, const uint8 *p, uint16 color, uint8 *page, uint8 n);
void swapLayers();
void drawCreditsText();
void drawProtectionShape(uint8 shapeNum, int16 zoom);
void drawShape(const uint8 *data, int16 x, int16 y);
void drawShapeScale(const uint8 *data, int16 zoom, int16 b, int16 c, int16 d, int16 e, int16 f, int16 g);
void drawShapeScaleRotate(const uint8 *data, int16 zoom, int16 b, int16 c, int16 d, int16 e, int16 f, int16 g);
void op_markCurPos();
void op_refreshScreen();
void op_waitForSync();
void op_drawShape();
void op_setPalette();
void op_drawStringAtBottom();
void op_nop();
void op_skip3();
void op_refreshAll();
void op_drawShapeScale();
void op_drawShapeScaleRotate();
void op_drawCreditsText();
void op_drawStringAtPos();
void op_handleKeys();
uint8 fetchNextCmdByte();
uint16 fetchNextCmdWord();
void mainLoop(uint16 offset);
void load(uint16 cutName);
void prepare();
void startCredits();
void play();
};
#endif // __CUTSCENE_H__

View File

@@ -1,222 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "zlib.h"
#include "file.h"
struct File_impl {
bool _ioErr;
File_impl() : _ioErr(false) {}
virtual bool open(const char *path, const char *mode) = 0;
virtual void close() = 0;
virtual uint32 size() = 0;
virtual void seek(int32 off) = 0;
virtual void read(void *ptr, uint32 len) = 0;
virtual void write(void *ptr, uint32 len) = 0;
};
struct stdFile : File_impl {
FILE *_fp;
stdFile() : _fp(0) {}
bool open(const char *path, const char *mode) {
_ioErr = false;
_fp = fopen(path, mode);
return (_fp != 0);
}
void close() {
if (_fp) {
fclose(_fp);
_fp = 0;
}
}
uint32 size() {
uint32 sz = 0;
if (_fp) {
int pos = ftell(_fp);
fseek(_fp, 0, SEEK_END);
sz = ftell(_fp);
fseek(_fp, pos, SEEK_SET);
}
return sz;
}
void seek(int32 off) {
if (_fp) {
fseek(_fp, off, SEEK_SET);
}
}
void read(void *ptr, uint32 len) {
if (_fp) {
uint32 r = fread(ptr, 1, len, _fp);
if (r != len) {
_ioErr = true;
}
}
}
void write(void *ptr, uint32 len) {
if (_fp) {
uint32 r = fwrite(ptr, 1, len, _fp);
if (r != len) {
_ioErr = true;
}
}
}
};
struct zlibFile : File_impl {
gzFile _fp;
zlibFile() : _fp(0) {}
bool open(const char *path, const char *mode) {
_ioErr = false;
_fp = gzopen(path, mode);
return (_fp != 0);
}
void close() {
if (_fp) {
gzclose(_fp);
_fp = 0;
}
}
uint32 size() {
uint32 sz = 0;
if (_fp) {
int pos = gztell(_fp);
gzseek(_fp, 0, SEEK_END);
sz = gztell(_fp);
gzseek(_fp, pos, SEEK_SET);
}
return sz;
}
void seek(int32 off) {
if (_fp) {
gzseek(_fp, off, SEEK_SET);
}
}
void read(void *ptr, uint32 len) {
if (_fp) {
uint32 r = gzread(_fp, ptr, len);
if (r != len) {
_ioErr = true;
}
}
}
void write(void *ptr, uint32 len) {
if (_fp) {
uint32 r = gzwrite(_fp, ptr, len);
if (r != len) {
_ioErr = true;
}
}
}
};
File::File(bool gzipped) {
if (gzipped) {
_impl = new zlibFile;
} else {
_impl = new stdFile;
}
}
File::~File() {
_impl->close();
delete _impl;
}
bool File::open(const char *filename, const char *directory, const char *mode) {
_impl->close();
char buf[512];
sprintf(buf, "%s/%s", directory, filename);
char *p = buf + strlen(directory) + 1;
string_lower(p);
bool opened = _impl->open(buf, mode);
if (!opened) { // let's try uppercase
string_upper(p);
opened = _impl->open(buf, mode);
}
return opened;
}
void File::close() {
_impl->close();
}
bool File::ioErr() const {
return _impl->_ioErr;
}
uint32 File::size() {
return _impl->size();
}
void File::seek(int32 off) {
_impl->seek(off);
}
void File::read(void *ptr, uint32 len) {
_impl->read(ptr, len);
}
uint8 File::readByte() {
uint8 b;
read(&b, 1);
return b;
}
uint16 File::readUint16LE() {
uint8 lo = readByte();
uint8 hi = readByte();
return (hi << 8) | lo;
}
uint32 File::readUint32LE() {
uint16 lo = readUint16LE();
uint16 hi = readUint16LE();
return (hi << 16) | lo;
}
uint16 File::readUint16BE() {
uint8 hi = readByte();
uint8 lo = readByte();
return (hi << 8) | lo;
}
uint32 File::readUint32BE() {
uint16 hi = readUint16BE();
uint16 lo = readUint16BE();
return (hi << 16) | lo;
}
void File::write(void *ptr, uint32 len) {
_impl->write(ptr, len);
}
void File::writeByte(uint8 b) {
write(&b, 1);
}
void File::writeUint16BE(uint16 n) {
writeByte(n >> 8);
writeByte(n & 0xFF);
}
void File::writeUint32BE(uint32 n) {
writeUint16BE(n >> 16);
writeUint16BE(n & 0xFFFF);
}

View File

@@ -1,49 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __FILE_H__
#define __FILE_H__
#include "intern.h"
struct File_impl;
struct File {
File(bool gzipped = false);
~File();
File_impl *_impl;
bool open(const char *filename, const char *directory, const char *mode);
void close();
bool ioErr() const;
uint32 size();
void seek(int32 off);
void read(void *ptr, uint32 len);
uint8 readByte();
uint16 readUint16LE();
uint32 readUint32LE();
uint16 readUint16BE();
uint32 readUint32BE();
void write(void *ptr, uint32 size);
void writeByte(uint8 b);
void writeUint16BE(uint16 n);
void writeUint32BE(uint32 n);
};
#endif // __FILE_H__

View File

@@ -1,391 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __GAME_H__
#define __GAME_H__
#include "intern.h"
#include "cutscene.h"
#include "menu.h"
#include "mixer.h"
#include "mod_player.h"
#include "resource.h"
#include "sfx_player.h"
#include "video.h"
struct File;
struct SystemStub;
struct Game {
typedef int (Game::*pge_OpcodeProc)(ObjectOpcodeArgs *args);
typedef int (Game::*pge_ZOrderCallback)(LivePGE *, LivePGE *, uint8, uint8);
typedef int (Game::*col_Callback1)(LivePGE *, LivePGE *, int16, int16);
typedef int (Game::*col_Callback2)(LivePGE *, int16, int16, int16);
enum {
CT_UP_ROOM = 0x00,
CT_DOWN_ROOM = 0x40,
CT_RIGHT_ROOM = 0x80,
CT_LEFT_ROOM = 0xC0
};
static const Level _gameLevels[];
static const uint16 _scoreTable[];
static const uint8 _monsterListLevel1[];
static const uint8 _monsterListLevel2[];
static const uint8 _monsterListLevel3[];
static const uint8 _monsterListLevel4_1[];
static const uint8 _monsterListLevel4_2[];
static const uint8 _monsterListLevel5_1[];
static const uint8 _monsterListLevel5_2[];
static const uint8 *_monsterListLevels[];
static const uint8 _monsterPals[4][32];
static const char *_monsterNames[];
static const pge_OpcodeProc _pge_opcodeTable[];
static const uint8 _pge_modKeysTable[];
static const uint8 _protectionCodeData[];
static const uint8 _protectionPal[];
Cutscene _cut;
Menu _menu;
Mixer _mix;
ModPlayer _modPly;
Resource _res;
SfxPlayer _sfxPly;
Video _vid;
SystemStub *_stub;
const char *_savePath;
const uint8 *_stringsTable;
const char **_textsTable;
uint8 _currentLevel;
uint8 _skillLevel;
uint32 _score;
uint8 _currentRoom;
uint8 _currentIcon;
bool _loadMap;
uint8 _printLevelCodeCounter;
uint32 _randSeed;
uint16 _currentInventoryIconNum;
uint16 _curMonsterFrame;
uint16 _curMonsterNum;
uint8 _blinkingConradCounter;
uint16 _textToDisplay;
bool _eraseBackground;
AnimBufferState _animBuffer0State[41];
AnimBufferState _animBuffer1State[6]; // Conrad
AnimBufferState _animBuffer2State[42];
AnimBufferState _animBuffer3State[12];
AnimBuffers _animBuffers;
uint8 _bankData[0x7000];
uint8 *_firstBankData;
uint8 *_lastBankData;
BankSlot _bankSlots[49];
BankSlot *_curBankSlot;
const uint8 *_bankDataPtrs;
uint16 _deathCutsceneCounter;
bool _saveStateCompleted;
Game(SystemStub *, const char *dataPath, const char *savePath, Version ver);
void run();
void resetGameState();
void mainLoop();
void updateTiming();
void playCutscene(int id = -1);
void loadLevelMap();
void loadLevelData();
void start();
void drawIcon(uint8 iconNum, int16 x, int16 y, uint8 colMask);
void drawCurrentInventoryItem();
void printLevelCode();
void showFinalScore();
bool handleConfigPanel();
bool handleContinueAbort();
bool handleProtectionScreen();
void printSaveStateCompleted();
void drawLevelTexts();
void drawStoryTexts();
void prepareAnims();
void prepareAnimsHelper(LivePGE *pge, int16 dx, int16 dy);
void drawAnims();
void drawAnimBuffer(uint8 stateNum, AnimBufferState *state);
void drawObject(const uint8 *dataPtr, int16 x, int16 y, uint8 flags);
void drawObjectFrame(const uint8 *dataPtr, int16 x, int16 y, uint8 flags);
void decodeCharacterFrame(const uint8 *dataPtr, uint8 *dstPtr);
void drawCharacter(const uint8 *dataPtr, int16 x, int16 y, uint8 a, uint8 b, uint8 flags);
uint8 *loadBankData(uint16 MbkEntryNum);
int loadMonsterSprites(LivePGE *pge);
void playSound(uint8 sfxId, uint8 softVol);
uint16 getRandomNumber();
void changeLevel();
uint16 getLineLength(const uint8 *str) const;
void handleInventory();
uint8 *findBankData(uint16 entryNum);
// pieges
bool _pge_playAnimSound;
GroupPGE _pge_groups[256];
GroupPGE *_pge_groupsTable[256];
GroupPGE *_pge_nextFreeGroup;
LivePGE *_pge_liveTable2[256]; // active pieges list (index = pge number)
LivePGE *_pge_liveTable1[256]; // pieges list by room (index = room)
LivePGE _pgeLive[256];
uint8 _pge_currentPiegeRoom;
bool _pge_currentPiegeFacingDir; // (false == left)
bool _pge_processOBJ;
uint8 _pge_inpKeysMask;
uint16 _pge_opTempVar1;
uint16 _pge_opTempVar2;
uint16 _pge_compareVar1;
uint16 _pge_compareVar2;
void pge_resetGroups();
void pge_removeFromGroup(uint8 idx);
int pge_isInGroup(LivePGE *pge_dst, uint16 group_id, uint16 counter);
void pge_loadForCurrentLevel(uint16 idx);
void pge_process(LivePGE *pge);
void pge_setupNextAnimFrame(LivePGE *pge, GroupPGE *le);
void pge_playAnimSound(LivePGE *pge, uint16 arg2);
void pge_setupAnim(LivePGE *pge);
int pge_execute(LivePGE *live_pge, InitPGE *init_pge, const Object *obj);
void pge_prepare();
void pge_setupDefaultAnim(LivePGE *pge);
uint16 pge_processOBJ(LivePGE *pge);
void pge_setupOtherPieges(LivePGE *pge, InitPGE *init_pge);
void pge_addToCurrentRoomList(LivePGE *pge, uint8 room);
void pge_getInput();
int pge_op_isInpUp(ObjectOpcodeArgs *args);
int pge_op_isInpBackward(ObjectOpcodeArgs *args);
int pge_op_isInpDown(ObjectOpcodeArgs *args);
int pge_op_isInpForward(ObjectOpcodeArgs *args);
int pge_op_isInpUpMod(ObjectOpcodeArgs *args);
int pge_op_isInpBackwardMod(ObjectOpcodeArgs *args);
int pge_op_isInpDownMod(ObjectOpcodeArgs *args);
int pge_op_isInpForwardMod(ObjectOpcodeArgs *args);
int pge_op_isInpIdle(ObjectOpcodeArgs *args);
int pge_op_isInpNoMod(ObjectOpcodeArgs *args);
int pge_op_getCollision0u(ObjectOpcodeArgs *args);
int pge_op_getCollision00(ObjectOpcodeArgs *args);
int pge_op_getCollision0d(ObjectOpcodeArgs *args);
int pge_op_getCollision1u(ObjectOpcodeArgs *args);
int pge_op_getCollision10(ObjectOpcodeArgs *args);
int pge_op_getCollision1d(ObjectOpcodeArgs *args);
int pge_op_getCollision2u(ObjectOpcodeArgs *args);
int pge_op_getCollision20(ObjectOpcodeArgs *args);
int pge_op_getCollision2d(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide0u(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide00(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide0d(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide1u(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide10(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide1d(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide2u(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide20(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide2d(ObjectOpcodeArgs *args);
int pge_op_collides0o0d(ObjectOpcodeArgs *args);
int pge_op_collides2o2d(ObjectOpcodeArgs *args);
int pge_op_collides0o0u(ObjectOpcodeArgs *args);
int pge_op_collides2o2u(ObjectOpcodeArgs *args);
int pge_op_collides2u2o(ObjectOpcodeArgs *args);
int pge_op_isInGroup(ObjectOpcodeArgs *args);
int pge_op_updateGroup0(ObjectOpcodeArgs *args);
int pge_op_updateGroup1(ObjectOpcodeArgs *args);
int pge_op_updateGroup2(ObjectOpcodeArgs *args);
int pge_op_updateGroup3(ObjectOpcodeArgs *args);
int pge_op_isPiegeDead(ObjectOpcodeArgs *args);
int pge_op_collides1u2o(ObjectOpcodeArgs *args);
int pge_op_collides1u1o(ObjectOpcodeArgs *args);
int pge_op_collides1o1u(ObjectOpcodeArgs *args);
int pge_o_unk0x2B(ObjectOpcodeArgs *args);
int pge_o_unk0x2C(ObjectOpcodeArgs *args);
int pge_o_unk0x2D(ObjectOpcodeArgs *args);
int pge_op_nop(ObjectOpcodeArgs *args);
int pge_op_pickupObject(ObjectOpcodeArgs *args);
int pge_op_addItemToInventory(ObjectOpcodeArgs *args);
int pge_op_copyPiege(ObjectOpcodeArgs *args);
int pge_op_canUseCurrentInventoryItem(ObjectOpcodeArgs *args);
int pge_op_removeItemFromInventory(ObjectOpcodeArgs *args);
int pge_o_unk0x34(ObjectOpcodeArgs *args);
int pge_op_isInpMod(ObjectOpcodeArgs *args);
int pge_op_setCollisionState1(ObjectOpcodeArgs *args);
int pge_op_setCollisionState0(ObjectOpcodeArgs *args);
int pge_op_isInGroup1(ObjectOpcodeArgs *args);
int pge_op_isInGroup2(ObjectOpcodeArgs *args);
int pge_op_isInGroup3(ObjectOpcodeArgs *args);
int pge_op_isInGroup4(ObjectOpcodeArgs *args);
int pge_o_unk0x3C(ObjectOpcodeArgs *args);
int pge_o_unk0x3D(ObjectOpcodeArgs *args);
int pge_op_setPiegeCounter(ObjectOpcodeArgs *args);
int pge_op_decPiegeCounter(ObjectOpcodeArgs *args);
int pge_o_unk0x40(ObjectOpcodeArgs *args);
int pge_op_wakeUpPiege(ObjectOpcodeArgs *args);
int pge_op_removePiege(ObjectOpcodeArgs *args);
int pge_op_removePiegeIfNotNear(ObjectOpcodeArgs *args);
int pge_op_loadPiegeCounter(ObjectOpcodeArgs *args);
int pge_o_unk0x45(ObjectOpcodeArgs *args);
int pge_o_unk0x46(ObjectOpcodeArgs *args);
int pge_o_unk0x47(ObjectOpcodeArgs *args);
int pge_o_unk0x48(ObjectOpcodeArgs *args);
int pge_o_unk0x49(ObjectOpcodeArgs *args);
int pge_o_unk0x4A(ObjectOpcodeArgs *args);
int pge_op_killPiege(ObjectOpcodeArgs *args);
int pge_op_isInCurrentRoom(ObjectOpcodeArgs *args);
int pge_op_isNotInCurrentRoom(ObjectOpcodeArgs *args);
int pge_op_scrollPosY(ObjectOpcodeArgs *args);
int pge_op_playDefaultDeathCutscene(ObjectOpcodeArgs *args);
int pge_o_unk0x50(ObjectOpcodeArgs *args);
int pge_o_unk0x52(ObjectOpcodeArgs *args);
int pge_o_unk0x53(ObjectOpcodeArgs *args);
int pge_op_isPiegeNear(ObjectOpcodeArgs *args);
int pge_op_setLife(ObjectOpcodeArgs *args);
int pge_op_incLife(ObjectOpcodeArgs *args);
int pge_op_setPiegeDefaultAnim(ObjectOpcodeArgs *args);
int pge_op_setLifeCounter(ObjectOpcodeArgs *args);
int pge_op_decLifeCounter(ObjectOpcodeArgs *args);
int pge_op_playCutscene(ObjectOpcodeArgs *args);
int pge_op_isTempVar2Set(ObjectOpcodeArgs *args);
int pge_op_playDeathCutscene(ObjectOpcodeArgs *args);
int pge_o_unk0x5D(ObjectOpcodeArgs *args);
int pge_o_unk0x5E(ObjectOpcodeArgs *args);
int pge_o_unk0x5F(ObjectOpcodeArgs *args);
int pge_op_findAndCopyPiege(ObjectOpcodeArgs *args);
int pge_op_isInRandomRange(ObjectOpcodeArgs *args);
int pge_o_unk0x62(ObjectOpcodeArgs *args);
int pge_o_unk0x63(ObjectOpcodeArgs *args);
int pge_o_unk0x64(ObjectOpcodeArgs *args);
int pge_op_addToCredits(ObjectOpcodeArgs *args);
int pge_op_subFromCredits(ObjectOpcodeArgs *args);
int pge_o_unk0x67(ObjectOpcodeArgs *args);
int pge_op_setCollisionState2(ObjectOpcodeArgs *args);
int pge_op_saveState(ObjectOpcodeArgs *args);
int pge_o_unk0x6A(ObjectOpcodeArgs *args);
int pge_op_isInGroupSlice(ObjectOpcodeArgs *args);
int pge_o_unk0x6C(ObjectOpcodeArgs *args);
int pge_op_isCollidingObject(ObjectOpcodeArgs *args);
int pge_o_unk0x6E(ObjectOpcodeArgs *args);
int pge_o_unk0x6F(ObjectOpcodeArgs *args);
int pge_o_unk0x70(ObjectOpcodeArgs *args);
int pge_o_unk0x71(ObjectOpcodeArgs *args);
int pge_o_unk0x72(ObjectOpcodeArgs *args);
int pge_o_unk0x73(ObjectOpcodeArgs *args);
int pge_op_collides4u(ObjectOpcodeArgs *args);
int pge_op_doesNotCollide4u(ObjectOpcodeArgs *args);
int pge_op_isBelowConrad(ObjectOpcodeArgs *args);
int pge_op_isAboveConrad(ObjectOpcodeArgs *args);
int pge_op_isNotFacingConrad(ObjectOpcodeArgs *args);
int pge_op_isFacingConrad(ObjectOpcodeArgs *args);
int pge_op_collides2u1u(ObjectOpcodeArgs *args);
int pge_op_displayText(ObjectOpcodeArgs *args);
int pge_o_unk0x7C(ObjectOpcodeArgs *args);
int pge_op_playSound(ObjectOpcodeArgs *args);
int pge_o_unk0x7E(ObjectOpcodeArgs *args);
int pge_o_unk0x7F(ObjectOpcodeArgs *args);
int pge_op_setPiegePosX(ObjectOpcodeArgs *args);
int pge_op_setPiegePosModX(ObjectOpcodeArgs *args);
int pge_op_changeRoom(ObjectOpcodeArgs *args);
int pge_op_hasInventoryItem(ObjectOpcodeArgs *args);
int pge_op_changeLevel(ObjectOpcodeArgs *args);
int pge_op_shakeScreen(ObjectOpcodeArgs *args);
int pge_o_unk0x86(ObjectOpcodeArgs *args);
int pge_op_playSoundGroup(ObjectOpcodeArgs *args);
int pge_op_adjustPos(ObjectOpcodeArgs *args);
int pge_op_setTempVar1(ObjectOpcodeArgs *args);
int pge_op_isTempVar1Set(ObjectOpcodeArgs *args);
int pge_setCurrentInventoryObject(LivePGE *pge);
void pge_updateInventory(LivePGE *pge1, LivePGE *pge2);
void pge_reorderInventory(LivePGE *pge);
LivePGE *pge_getInventoryItemBefore(LivePGE *pge, LivePGE *last_pge);
void pge_addToInventory(LivePGE *pge1, LivePGE *pge2, LivePGE *pge3);
int pge_updateCollisionState(LivePGE *pge, int16 pge_dy, uint8 var8);
int pge_ZOrder(LivePGE *pge, int16 num, pge_ZOrderCallback compare, uint16 unk);
void pge_updateGroup(uint8 idx, uint8 unk1, int16 unk2);
void pge_removeFromInventory(LivePGE *pge1, LivePGE *pge2, LivePGE *pge3);
int pge_ZOrderByAnimY(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
int pge_ZOrderByAnimYIfType(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
int pge_ZOrderIfIndex(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
int pge_ZOrderByIndex(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
int pge_ZOrderByObj(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
int pge_ZOrderIfDifferentDirection(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
int pge_ZOrderIfSameDirection(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
int pge_ZOrderIfTypeAndSameDirection(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
int pge_ZOrderIfTypeAndDifferentDirection(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
int pge_ZOrderByNumber(LivePGE *pge1, LivePGE *pge2, uint8 comp, uint8 comp2);
// collision
CollisionSlot _col_slots[256];
uint8 _col_curPos;
CollisionSlot *_col_slotsTable[256];
CollisionSlot *_col_curSlot;
CollisionSlot2 _col_slots2[256];
CollisionSlot2 *_col_slots2Cur;
CollisionSlot2 *_col_slots2Next;
uint8 _col_activeCollisionSlots[0x30 * 3]; // left, current, right
uint8 _col_currentLeftRoom;
uint8 _col_currentRightRoom;
int16 _col_currentPiegeGridPosX;
int16 _col_currentPiegeGridPosY;
void col_prepareRoomState();
void col_clearState();
LivePGE *col_findPiege(LivePGE *pge, uint16 arg2);
int16 col_findSlot(int16 pos);
void col_preparePiegeState(LivePGE *dst_pge);
uint16 col_getGridPos(LivePGE *pge, int16 dx);
int16 col_getGridData(LivePGE *pge, int16 dy, int16 dx);
uint8 col_findCurrentCollidingObject(LivePGE *pge, uint8 n1, uint8 n2, uint8 n3, LivePGE **pge_out);
int16 col_detectHit(LivePGE *pge, int16 arg2, int16 arg4, col_Callback1 callback1, col_Callback2 callback2, int16 argA, int16 argC);
int col_detectHitCallback2(LivePGE *pge1, LivePGE *pge2, int16 unk1, int16 unk2);
int col_detectHitCallback3(LivePGE *pge1, LivePGE *pge2, int16 unk1, int16 unk2);
int col_detectHitCallback4(LivePGE *pge1, LivePGE *pge2, int16 unk1, int16 unk2);
int col_detectHitCallback5(LivePGE *pge1, LivePGE *pge2, int16 unk1, int16 unk2);
int col_detectHitCallback1(LivePGE *pge, int16 dy, int16 unk1, int16 unk2);
int col_detectHitCallback6(LivePGE *pge, int16 dy, int16 unk1, int16 unk2);
int col_detectHitCallbackHelper(LivePGE *pge, int16 unk1);
int col_detectGunHitCallback1(LivePGE *pge, int16 arg2, int16 arg4, int16 arg6);
int col_detectGunHitCallback2(LivePGE *pge1, LivePGE *pge2, int16 arg4, int16);
int col_detectGunHitCallback3(LivePGE *pge1, LivePGE *pge2, int16 arg4, int16);
int col_detectGunHit(LivePGE *pge, int16 arg2, int16 arg4, col_Callback1 callback1, col_Callback2 callback2, int16 argA, int16 argC);
// input
uint8 _inp_lastKeysHit;
uint8 _inp_lastKeysHitLeftRight;
bool _inp_replay;
bool _inp_record;
File *_inp_demo;
void inp_handleSpecialKeys();
void inp_update();
// save/load state
uint8 _stateSlot;
bool _validSaveState;
void makeGameDemoName(char *buf);
void makeGameStateName(uint8 slot, char *buf);
bool saveGameState(uint8 slot);
bool loadGameState(uint8 slot);
void saveState(File *f);
void loadState(File *f);
};
#endif // __GAME_H__

View File

@@ -1,718 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "graphics.h"
void Graphics::setClippingRect(int16 rx, int16 ry, int16 rw, int16 rh) {
debug(DBG_VIDEO, "Graphics::setClippingRect(%d, %d, %d, %d)", rx, ry, rw, rh);
_crx = rx;
_cry = ry;
_crw = rw;
_crh = rh;
}
void Graphics::drawPoint(uint8 color, const Point *pt) {
debug(DBG_VIDEO, "Graphics::drawPoint() col=0x%X x=%d, y=%d", color, pt->x, pt->y);
if (pt->x >= 0 && pt->x < _crw && pt->y >= 0 && pt->y < _crh) {
*(_layer + (pt->y + _cry) * 256 + pt->x + _crx) = color;
}
}
void Graphics::drawLine(uint8 color, const Point *pt1, const Point *pt2) {
debug(DBG_VIDEO, "Graphics::drawLine()");
int16 dxincr1 = 1;
int16 dyincr1 = 1;
int16 dx = pt2->x - pt1->x;
if (dx < 0) {
dxincr1 = -1;
dx = -dx;
}
int16 dy = pt2->y - pt1->y;
if (dy < 0) {
dyincr1 = -1;
dy = -dy;
}
int16 dxincr2, dyincr2, delta1, delta2;
if (dx < dy) {
dxincr2 = 0;
dyincr2 = 1;
delta1 = dx;
delta2 = dy;
if (dyincr1 < 0) {
dyincr2 = -1;
}
} else {
dxincr2 = 1;
dyincr2 = 0;
delta1 = dy;
delta2 = dx;
if (dxincr1 < 0) {
dxincr2 = -1;
}
}
Point pt;
pt.x = pt1->x;
pt.y = pt1->y;
int16 octincr1 = delta1 * 2 - delta2 * 2;
int16 octincr2 = delta1 * 2;
int16 oct = delta1 * 2 - delta2;
if (delta2 >= 0) {
drawPoint(color, &pt);
while (--delta2 >= 0) {
if (oct >= 0) {
pt.x += dxincr1;
pt.y += dyincr1;
oct += octincr1;
} else {
pt.x += dxincr2;
pt.y += dyincr2;
oct += octincr2;
}
drawPoint(color, &pt);
}
}
}
void Graphics::addEllipseRadius(int16 y, int16 x1, int16 x2) {
debug(DBG_VIDEO, "Graphics::addEllipseRadius()");
if (y >= 0 && y <= _crh) {
y = (y - _areaPoints[0]) * 2;
if (x1 < 0) {
x1 = 0;
}
if (x2 >= _crw) {
x2 = _crw - 1;
}
_areaPoints[y + 1] = x1;
_areaPoints[y + 2] = x2;
}
}
void Graphics::drawEllipse(uint8 color, bool hasAlpha, const Point *pt, int16 rx, int16 ry) {
debug(DBG_VIDEO, "Graphics::drawEllipse()");
bool flag = false;
int16 y = pt->y - ry;
if (y < 0) {
y = 0;
}
if (y < _crh) {
if (pt->y + ry >= 0) {
_areaPoints[0] = y;
int32 dy = 0;
int32 rxsq = rx * rx;
int32 rxsq2 = rx * rx * 2;
int32 rxsq4 = rx * rx * 4;
int32 rysq = ry * ry;
int32 rysq2 = ry * ry * 2;
int32 rysq4 = ry * ry * 4;
int32 dx = 0;
int32 b = rx * ((rysq2 & 0xFFFF) + (rysq2 >> 16));
int32 a = 2 * b;
int32 ny1, ny2, nx1, nx2;
ny1 = ny2 = rysq4 / 2 - a + rxsq;
nx1 = nx2 = rxsq2 - b + rysq;
while (ny2 < 0) {
int16 x2 = pt->x + rx;
int16 x1 = pt->x - rx;
int16 by = pt->y + dy;
int16 ty = pt->y - dy;
if (x1 != x2) {
addEllipseRadius(by, x1, x2);
if (ty < by) {
addEllipseRadius(ty, x1, x2);
}
}
dy += 1;
dx += rxsq4;
nx1 = dx;
if (nx2 < 0) {
nx2 += nx1 + rxsq2;
ny2 += nx1;
} else {
--rx;
a -= rysq4;
ny1 = a;
nx2 += nx1 + rxsq2 - ny1;
ny2 += nx1 + rysq2 - ny1;
}
}
while (rx >= 0) {
bool flag2 = false;
int16 x2 = pt->x + rx;
int16 x1 = pt->x - rx;
int16 by = pt->y + dy;
int16 ty = pt->y - dy;
if (!flag && x1 != x2) {
flag2 = true;
addEllipseRadius(by, x1, x2);
if (ty < by) {
addEllipseRadius(ty, x1, x2);
}
}
if (flag2) {
flag = true;
}
--rx;
a -= rysq4;
nx1 = a;
if (ny2 < 0) {
++dy;
flag = false;
dx += rxsq4;
ny2 += dx - nx1 + rysq2;
ny1 = dx - nx1 + rysq2;
} else {
ny2 += rysq2 - nx1;
ny1 = rysq2 - nx1;
}
}
if (flag) {
++dy;
}
while (dy <= ry) {
int16 ty = pt->y - dy;
int16 by = pt->y + dy;
if (ty < by) {
addEllipseRadius(ty, pt->x, pt->x);
}
addEllipseRadius(by, pt->x, pt->x);
++dy;
}
y = pt->y + ry + 1;
if (y > _crh) {
y = _crh;
}
y = (y - _areaPoints[0]) * 2;
_areaPoints[y + 1] = -1;
fillArea(color, hasAlpha);
}
}
}
void Graphics::fillArea(uint8 color, bool hasAlpha) {
debug(DBG_VIDEO, "Graphics::fillArea()");
int16 *pts = _areaPoints;
uint8 *dst = _layer + (_cry + *pts++) * 256 + _crx;
int16 x1 = *pts++;
if (x1 >= 0) {
if (hasAlpha && color > 0xC7) {
do {
int16 x2 = *pts++;
if (x2 < _crw && x2 >= x1) {
int len = x2 - x1 + 1;
for (int i = 0; i < len; ++i) {
*(dst + x1 + i) |= color & 8; // XXX 0x88
}
}
dst += 256;
x1 = *pts++;
} while (x1 >= 0);
} else {
do {
int16 x2 = *pts++;
if (x2 < _crw && x2 >= x1) {
int len = x2 - x1 + 1;
memset(dst + x1, color, len);
}
dst += 256;
x1 = *pts++;
} while (x1 >= 0);
}
}
}
void Graphics::drawSegment(uint8 color, bool hasAlpha, int16 ys, const Point *pts, uint8 numPts) {
debug(DBG_VIDEO, "Graphics::drawSegment()");
int16 xmin, xmax, ymin, ymax;
xmin = xmax = pts[0].x;
ymin = ymax = pts[0].y;
for (int i = 1; i < numPts; ++i) {
int16 x = pts[i].x;
int16 y = pts[i].y;
if ((xmin << 16) + ymin > (x << 16) + y) {
xmin = x;
ymin = y;
}
if ((xmax << 16) + ymax < (x << 16) + y) {
xmax = x;
ymax = y;
}
}
if (xmin < 0) {
xmin = 0;
}
if (xmax >= _crw) {
xmax = _crw - 1;
}
_areaPoints[0] = ys;
_areaPoints[1] = xmin;
_areaPoints[2] = xmax;
_areaPoints[3] = -1;
fillArea(color, hasAlpha);
}
void Graphics::drawPolygonOutline(uint8 color, const Point *pts, uint8 numPts) {
debug(DBG_VIDEO, "Graphics::drawPolygonOutline()");
assert(numPts >= 2);
int i;
for (i = 0; i < numPts - 1; ++i) {
drawLine(color, &pts[i], &pts[i + 1]);
}
drawLine(color, &pts[i], &pts[0]);
}
static int32 calcPolyStep1(int16 dx, int16 dy) {
debug(DBG_VIDEO, "Graphics::calcPolyStep1()");
assert(dy != 0);
int32 a = dx * 256;
if ((a >> 16) < dy) {
a = ((int16)(a / dy)) * 256;
} else {
a = ((a / 256) / dy) & 0xFFFF0000;
}
return a;
}
static int32 calcPolyStep2(int16 dx, int16 dy) {
debug(DBG_VIDEO, "Graphics::calcPolyStep2()");
assert(dy != 0);
int32 a = dx * 256;
if ((a >> 16) < dy) {
a = ((int16)(a / dy)) * 256;
} else {
a = ((a / 256) / dy) << 16;
}
return a;
}
static void drawPolygonHelper1(int32 &x, int16 &y, int32 &step, int16 *&pts, int16 *&start) {
bool first = true;
x = pts[0];
y = pts[1];
int16 dy, dx;
do {
if (first) {
first = false;
} else {
x = *pts;
}
--pts;
dy = *pts - y;
--pts;
dx = *pts - x;
} while (dy <= 0 && start < pts);
x <<= 16;
if (dy > 0) {
step = calcPolyStep1(dx, dy);
}
}
static void drawPolygonHelper2(int32 &x, int16 &y, int32 &step, int16 *&pts, int16 *&start) {
bool first = true;
x = *start++;
y = *start++;
int16 dy, dx;
do {
if (first) {
first = false;
} else {
x = *start;
start += 2;
}
dy = start[1] - y;
dx = start[0] - x;
} while (dy <= 0 && start < pts);
x <<= 16;
if (dy > 0) {
step = calcPolyStep2(dx, dy);
}
}
void Graphics::drawPolygon(uint8 color, bool hasAlpha, const Point *pts, uint8 numPts) {
debug(DBG_VIDEO, "Graphics::drawPolygon()");
assert(numPts * 4 < 0x100);
int16 *apts1 = &_areaPoints[0x100];
int16 *apts2 = &_areaPoints[0x100 + numPts * 2];
int16 xmin, xmax, ymin, ymax;
xmin = xmax = pts[0].x;
ymin = ymax = pts[0].y;
int16 *spts = apts1;
*apts1++ = *apts2++ = pts[0].x;
*apts1++ = *apts2++ = pts[0].y;
for (int p = 1; p < numPts; ++p) {
int16 x = pts[p].x;
int16 y = pts[p].y;
if (ymin > y) {
ymin = y;
spts = apts1;
}
if (ymax < y) {
ymax = y;
}
*apts1++ = *apts2++ = x;
*apts1++ = *apts2++ = y;
if (xmin > x) {
xmin = x;
}
if (xmax < x) {
xmax = x;
}
}
int16 *rpts = _areaPoints;
if (xmax < 0 || xmin >= _crw || ymax < 0 || ymin >= _crh) {
return;
}
if (numPts == 2) {
drawLine(color, &pts[0], &pts[1]);
return;
}
if (ymax == ymin) {
drawSegment(color, hasAlpha, ymax, pts, numPts);
return;
}
int16 x, dx, y, dy;
int32 a, b, d, f;
int32 xstep1 = 0;
int32 xstep2 = 0;
apts1 = &spts[numPts * 2];
xmax = _crw - 1;
ymax = _crh - 1;
int32 l1 = 65536;
int32 l2 = -65536;
if (ymin < 0) {
int16 x0, y0;
do {
--apts1;
y0 = *apts1;
--apts1;
x0 = *apts1;
} while (y0 < 0);
x = apts1[2];
y = apts1[3];
dy = y0 - y;
dx = x0 - x;
xstep1 = (dy << 16) | dx;
assert(dy != 0);
a = y * dx / dy;
b = (x - a) << 16;
d = xstep1 = calcPolyStep1(dx, dy);
if (d < 0) {
d = -d;
}
if (d < l1) {
d = l2;
}
d /= 2;
b -= d;
do {
x0 = *spts++;
y0 = *spts++;
} while (*(spts + 1) < 0);
dy = spts[1] - y0;
dx = spts[0] - x0;
xstep2 = (dy << 16) | dx;
assert(dy != 0);
a = y0 * dx / dy;
f = (x0 - a) << 16;
d = xstep2 = calcPolyStep2(dx, dy);
if (d < 0) {
d = -d;
}
if (d < l1) {
d = l1;
}
d /= 2;
f += d;
ymin = 0;
*rpts++ = 0;
goto gfx_startLine;
}
*rpts++ = ymin;
gfx_startNewLine:
drawPolygonHelper2(f, ymin, xstep2, apts1, spts);
if (spts >= apts1) {
b = apts1[0] << 16;
dy = apts1[1];
if (dy <= ymax) goto gfx_endLine;
goto gfx_fillArea;
}
drawPolygonHelper1(b, ymin, xstep1, apts1, spts);
d = xstep1;
if (d < 0) {
if (d >= l2) {
d = l1;
}
d /= 2;
b += d;
}
d = xstep2;
if (d >= 0) {
if (d <= l1) {
d = l1;
}
d /= 2;
f += d;
}
d = b;
if (d < 0) {
d = 0;
}
x = f >> 16;
if (x > xmax) {
x = xmax;
}
*rpts++ = d >> 16;
*rpts++ = x;
++ymin;
d = xstep1;
if (d >= 0) {
if (d <= l1) {
d = l1;
}
d /= 2;
}
b += d;
d = xstep2;
if (d < 0) {
if (d >= l2) {
d = l1;
}
d /= 2;
}
f += d;
gfx_startLine:
while (1) {
dy = apts1[1];
if (spts >= apts1) {
break;
} else if (dy > spts[1]) {
dy = spts[1];
if (dy > ymax) {
goto gfx_drawPolygonEnd;
}
dy -= ymin;
if (dy > 0) {
--dy;
do {
a = b;
if (a < 0) {
a = 0;
}
x = f >> 16;
if (x > xmax) {
x = xmax;
}
*rpts++ = a >> 16;
*rpts++ = x;
b += xstep1;
f += xstep2;
--dy;
} while (dy >= 0);
}
drawPolygonHelper2(f, ymin, xstep2, apts1, spts);
d = xstep2;
if (d >= 0) {
if (d <= l1) {
d = l1;
}
d /= 2;
f += d;
} else {
d = b;
if (d < 0) {
d = 0;
}
x = f >> 16;
if (x > xmax) {
x = xmax;
}
*rpts++ = d >> 16;
*rpts++ = x;
++ymin;
d = xstep2;
if (d >= l2) {
d = l1;
}
d /= 2;
f += d;
b += xstep1;
}
} else if (dy == spts[1]) {
if (dy > ymax) goto gfx_drawPolygonEnd;
dy -= ymin;
if (dy > 0) {
--dy;
do {
a = b;
if (a < 0) {
a = 0;
}
x = f >> 16;
if (x > xmax) {
x = xmax;
}
*rpts++ = a >> 16;
*rpts++ = x;
b += xstep1;
f += xstep2;
--dy;
} while (dy >= 0);
}
goto gfx_startNewLine;
} else if (dy > ymax) {
goto gfx_drawPolygonEnd;
} else {
dy -= ymin;
if (dy > 0) {
--dy;
do {
a = b;
if (a < 0) {
a = 0;
}
x = f >> 16;
if (x > xmax) {
x = xmax;
}
*rpts++ = a >> 16;
*rpts++ = x;
b += xstep1;
f += xstep2;
--dy;
} while (dy >= 0);
}
drawPolygonHelper1(b, ymin, xstep1, apts1, spts);
d = xstep1;
if (d < 0) {
if (d >= l2) {
d = l1;
}
d /= 2;
b += d;
} else {
d = b;
if (d < 0) {
d = 0;
}
x = f >> 16;
if (x > xmax) {
x = xmax;
}
*rpts++ = d >> 16;
*rpts++ = x;
++ymin;
d = xstep1;
if (d <= l1) {
d = l1;
}
d /= 2;
b += d;
f += xstep2;
}
}
}
if (dy > ymax) goto gfx_drawPolygonEnd;
dy -= ymin;
if (dy < 0) goto gfx_fillArea;
if (dy > 0) {
--dy;
do {
a = b;
if (a < 0) {
a = 0;
}
x = f >> 16;
if (x > xmax) {
x = xmax;
}
*rpts++ = a >> 16;
*rpts++ = x;
b += xstep1;
f += xstep2;
--dy;
} while (dy >= 0);
}
b = f = (apts1[0] << 16) | apts1[1];
gfx_endLine:
d = xstep1;
if (d >= 0) {
if (d >= l1) {
d /= 2;
b -= d;
}
}
d = xstep2;
if (d < 0) {
d /= 2;
f -= d;
}
a = b;
if (a < 0) {
a = 0;
}
x = f >> 16;
if (x > xmax) {
x = xmax;
}
*rpts++ = a >> 16;
*rpts++ = x;
goto gfx_fillArea;
gfx_drawPolygonEnd:
dy = ymax - ymin;
if (dy >= 0) {
do {
a = b;
if (a < 0) {
a = 0;
}
x = f >> 16;
if (x > xmax) {
x = xmax;
}
*rpts++ = a >> 16;
*rpts++ = x;
b += xstep1;
f += xstep2;
--dy;
} while (dy >= 0);
}
gfx_fillArea:
*rpts++ = -1;
fillArea(color, hasAlpha);
}

View File

@@ -1,40 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __GRAPHICS_H__
#define __GRAPHICS_H__
#include "intern.h"
struct Graphics {
uint8 *_layer;
int16 _areaPoints[0x200];
int16 _crx, _cry, _crw, _crh;
void setClippingRect(int16 vx, int16 vy, int16 vw, int16 vh);
void drawPoint(uint8 color, const Point *pt);
void drawLine(uint8 color, const Point *pt1, const Point *pt2);
void addEllipseRadius(int16 y, int16 x1, int16 x2);
void drawEllipse(uint8 color, bool hasAlpha, const Point *pt, int16 rx, int16 ry);
void fillArea(uint8 color, bool hasAlpha);
void drawSegment(uint8 color, bool hasAlpha, int16 ys, const Point *pts, uint8 numPts);
void drawPolygonOutline(uint8 color, const Point *pts, uint8 numPts);
void drawPolygon(uint8 color, bool hasAlpha, const Point *pts, uint8 numPts);
};
#endif // __GRAPHICS_H__

View File

@@ -1,193 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __INTERN_H__
#define __INTERN_H__
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include "sys.h"
#include "util.h"
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
template<typename T>
inline void SWAP(T &a, T &b) {
T tmp = a;
a = b;
b = tmp;
}
enum Version {
VER_FR,
VER_EN,
VER_DE,
VER_SP
};
struct Color {
uint8 r;
uint8 g;
uint8 b;
};
struct Point {
int16 x;
int16 y;
};
struct Level {
const char *name;
const char *name2;
uint16 cutscene_id;
};
struct InitPGE {
uint16 type;
int16 pos_x;
int16 pos_y;
uint16 obj_node_number;
uint16 life;
int16 counter_values[4];
uint8 object_type;
uint8 init_room;
uint8 room_location;
uint8 init_flags;
uint8 colliding_icon_num;
uint8 icon_num;
uint8 object_id;
uint8 skill;
uint8 mirror_x;
uint8 flags;
uint8 unk1C; // collidable, collision_data_len
uint8 text_num;
};
struct LivePGE {
uint16 obj_type;
int16 pos_x;
int16 pos_y;
uint8 anim_seq;
uint8 room_location;
int16 life;
int16 counter_value;
uint8 collision_slot;
uint8 next_inventory_PGE;
uint8 current_inventory_PGE;
uint8 unkF; // unk_inventory_PGE
uint16 anim_number;
uint8 flags;
uint8 index;
uint16 first_obj_number;
LivePGE *next_PGE_in_room;
InitPGE *init_PGE;
};
struct GroupPGE {
GroupPGE *next_entry;
uint16 index;
uint16 group_id;
};
struct Object {
uint16 type;
int8 dx;
int8 dy;
uint16 init_obj_type;
uint8 opcode2;
uint8 opcode1;
uint8 flags;
uint8 opcode3;
uint16 init_obj_number;
int16 opcode_arg1;
int16 opcode_arg2;
int16 opcode_arg3;
};
struct ObjectNode {
uint16 last_obj_number;
Object *objects;
uint16 num_objects;
};
struct ObjectOpcodeArgs {
LivePGE *pge; // arg0
int16 a; // arg2
int16 b; // arg4
};
struct AnimBufferState {
int16 x;
int16 y;
const uint8 *dataPtr;
LivePGE *pge;
};
struct AnimBuffers {
AnimBufferState *_states[4];
uint8 _curPos[4];
void addState(uint8 stateNum, int16 x, int16 y, const uint8 *dataPtr, LivePGE *pge);
};
struct CollisionSlot {
int16 ct_pos;
CollisionSlot *prev_slot;
LivePGE *live_pge;
uint16 index;
};
struct MbkEntry {
uint16 offset;
uint16 len;
};
struct BankSlot {
uint16 entryNum;
uint8 *ptr;
};
struct CollisionSlot2 {
CollisionSlot2 *next_slot;
int8 *unk2;
uint8 data_size;
uint8 data_buf[0x10]; // XXX check size
};
struct InventoryItem {
uint8 icon_num;
InitPGE *init_pge;
LivePGE *live_pge;
};
struct SoundFx {
uint32 offset;
uint16 len;
uint8 *data;
};
#endif // __INTERN_H__

View File

@@ -1,50 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2006 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "locale.h"
Locale::Locale(Version ver)
: _ver(ver) {
switch (_ver) {
case VER_FR:
_stringsTable = _stringsTableFR;
_textsTable = _textsTableFR;
break;
case VER_EN:
_stringsTable = _stringsTableEN;
_textsTable = _textsTableEN;
break;
case VER_DE:
_stringsTable = _stringsTableDE;
_textsTable = _textsTableDE;
break;
case VER_SP:
_stringsTable = _stringsTableSP;
_textsTable = _textsTableSP;
break;
}
}
const char *Locale::get(int id) const {
const char *text = 0;
if (id >= 0 && id < LI_NUM) {
text = _textsTable[id];
}
return text;
}

View File

@@ -1,69 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2006 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __LOCALE_H__
#define __LOCALE_H__
#include "intern.h"
struct Locale {
enum Id {
LI_01_CONTINUE_OR_ABORT = 0,
LI_02_TIME,
LI_03_CONTINUE,
LI_04_ABORT,
LI_05_COMPLETED,
LI_06_LEVEL,
LI_07_START,
LI_08_SKILL,
LI_09_PASSWORD,
LI_10_INFO,
LI_11_QUIT,
LI_12_SKILL_LEVEL,
LI_13_EASY,
LI_14_NORMAL,
LI_15_EXPERT,
LI_16_ENTER_PASSWORD1,
LI_17_ENTER_PASSWORD2,
LI_18_RESUME_GAME,
LI_19_ABORT_GAME,
LI_20_LOAD_GAME,
LI_21_SAVE_GAME,
LI_22_SAVE_SLOT,
LI_NUM
};
static const char *_textsTableFR[];
static const char *_textsTableEN[];
static const char *_textsTableDE[];
static const char *_textsTableSP[];
static const uint8 _stringsTableFR[];
static const uint8 _stringsTableEN[];
static const uint8 _stringsTableDE[];
static const uint8 _stringsTableSP[];
Version _ver;
const char **_textsTable;
const uint8 *_stringsTable;
Locale(Version ver);
const char *get(int id) const;
};
#endif // __LOCALE_H__

View File

@@ -1,85 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "file.h"
#include "game.h"
#include "systemstub.h"
static const char *USAGE =
"REminiscence - Flashback Interpreter\n"
"Usage: rs [OPTIONS]...\n"
" --datapath=PATH Path to data files (default 'DATA')\n"
" --savepath=PATH Path to save files (default '.')";
static bool parseOption(const char *arg, const char *longCmd, const char **opt) {
bool handled = false;
if (arg[0] == '-' && arg[1] == '-') {
if (strncmp(arg + 2, longCmd, strlen(longCmd)) == 0) {
*opt = arg + 2 + strlen(longCmd);
handled = true;
}
}
return handled;
}
static Version detectVersion(const char *dataPath) {
static struct {
const char *filename;
Version ver;
} checkTable[] = {
{ "ENGCINE.BIN", VER_EN },
{ "FR_CINE.BIN", VER_FR },
{ "GERCINE.BIN", VER_DE },
{ "SPACINE.BIN", VER_SP }
};
for (uint8 i = 0; i < ARRAYSIZE(checkTable); ++i) {
File f;
if (f.open(checkTable[i].filename, dataPath, "rb")) {
return checkTable[i].ver;
}
}
error("Unable to find data files, check that all required files are present");
return VER_EN;
}
#undef main
#include <SDL.h>
int main(int argc, char *argv[]) {
const char *dataPath = "DATA";
const char *savePath = ".";
for (int i = 1; i < argc; ++i) {
bool opt = false;
if (strlen(argv[i]) >= 2) {
opt |= parseOption(argv[i], "datapath=", &dataPath);
opt |= parseOption(argv[i], "savepath=", &savePath);
}
if (!opt) {
printf(USAGE);
return 0;
}
}
Version ver = detectVersion(dataPath);
g_debugMask = DBG_INFO; // DBG_CUT | DBG_VIDEO | DBG_RES | DBG_MENU | DBG_PGE | DBG_GAME | DBG_UNPACK | DBG_COL | DBG_MOD | DBG_SFX;
SystemStub *stub = SystemStub_SDL_create();
Game *g = new Game(stub, dataPath, savePath, ver);
g->run();
delete g;
delete stub;
return 0;
}

View File

@@ -1,316 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "game.h"
#include "mod_player.h"
#include "resource.h"
#include "systemstub.h"
#include "video.h"
#include "menu.h"
Menu::Menu(ModPlayer *ply, Resource *res, SystemStub *stub, Video *vid)
: _ply(ply), _res(res), _stub(stub), _vid(vid) {
}
void Menu::drawString(const char *str, int16 y, int16 x, uint8 color) {
debug(DBG_MENU, "Menu::drawString()");
uint8 v1b = _vid->_charFrontColor;
uint8 v2b = _vid->_charTransparentColor;
uint8 v3b = _vid->_charShadowColor;
switch (color) {
case 0:
_vid->_charFrontColor = _charVar1;
_vid->_charTransparentColor = _charVar2;
_vid->_charShadowColor = _charVar2;
break;
case 1:
_vid->_charFrontColor = _charVar2;
_vid->_charTransparentColor = _charVar1;
_vid->_charShadowColor = _charVar1;
break;
case 2:
_vid->_charFrontColor = _charVar3;
_vid->_charTransparentColor = 0xFF;
_vid->_charShadowColor = _charVar1;
break;
case 3:
_vid->_charFrontColor = _charVar4;
_vid->_charTransparentColor = 0xFF;
_vid->_charShadowColor = _charVar1;
break;
case 4:
_vid->_charFrontColor = _charVar2;
_vid->_charTransparentColor = 0xFF;
_vid->_charShadowColor = _charVar1;
break;
case 5:
_vid->_charFrontColor = _charVar2;
_vid->_charTransparentColor = 0xFF;
_vid->_charShadowColor = _charVar5;
break;
}
drawString2(str, y, x);
_vid->_charFrontColor = v1b;
_vid->_charTransparentColor = v2b;
_vid->_charShadowColor = v3b;
}
void Menu::drawString2(const char *str, int16 y, int16 x) {
debug(DBG_MENU, "Menu::drawString2()");
int len = 0;
while (*str) {
_vid->drawChar((uint8)*str, y, x + len);
++str;
++len;
}
_vid->markBlockAsDirty(x * 8, y * 8, len * 8, 8);
}
void Menu::loadPicture(const char *prefix) {
debug(DBG_MENU, "Menu::loadPicture('%s')", prefix);
_res->load_MAP_menu(prefix, _res->_memBuf);
for (int i = 0; i < 4; ++i) {
for (int y = 0; y < 224; ++y) {
for (int x = 0; x < 64; ++x) {
_vid->_frontLayer[i + x * 4 + 256 * y] = _res->_memBuf[0x3800 * i + x + 64 * y];
}
}
}
_res->load_PAL_menu(prefix, _res->_memBuf);
_stub->setPalette(_res->_memBuf, 256);
}
void Menu::handleInfoScreen() {
debug(DBG_MENU, "Menu::handleInfoScreen()");
_vid->fadeOut();
switch (_res->_ver) {
case VER_FR:
loadPicture("instru_f");
break;
case VER_EN:
case VER_DE:
case VER_SP:
loadPicture("instru_e");
break;
}
_vid->fullRefresh();
_vid->updateScreen();
do {
_stub->sleep(EVENTS_DELAY);
_stub->processEvents();
if (_stub->_pi.enter) {
_stub->_pi.enter = false;
break;
}
} while (!_stub->_pi.quit);
}
void Menu::handleSkillScreen(uint8 &new_skill) {
debug(DBG_MENU, "Menu::handleSkillScreen()");
static const uint8 option_colors[3][3] = { { 2, 3, 3 }, { 3, 2, 3}, { 3, 3, 2 } };
_vid->fadeOut();
loadPicture("menu3");
_vid->fullRefresh();
drawString(_res->getMenuString(LocaleData::LI_12_SKILL_LEVEL), 12, 4, 3);
int skill_level = new_skill;
do {
drawString(_res->getMenuString(LocaleData::LI_13_EASY), 15, 14, option_colors[skill_level][0]);
drawString(_res->getMenuString(LocaleData::LI_14_NORMAL), 17, 14, option_colors[skill_level][1]);
drawString(_res->getMenuString(LocaleData::LI_15_EXPERT), 19, 14, option_colors[skill_level][2]);
_vid->updateScreen();
_stub->sleep(EVENTS_DELAY);
_stub->processEvents();
if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
_stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
if (skill_level != 0) {
--skill_level;
} else {
skill_level = 2;
}
}
if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
_stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
if (skill_level != 2) {
++skill_level;
} else {
skill_level = 0;
}
}
if (_stub->_pi.enter) {
_stub->_pi.enter = false;
new_skill = skill_level;
return;
}
} while (!_stub->_pi.quit);
new_skill = 1;
}
bool Menu::handlePasswordScreen(uint8 &new_skill, uint8 &new_level) {
debug(DBG_MENU, "Menu::handlePasswordScreen()");
_vid->fadeOut();
_vid->_charShadowColor = _charVar1;
_vid->_charTransparentColor = 0xFF;
_vid->_charFrontColor = _charVar4;
_vid->fullRefresh();
char password[7];
int len = 0;
do {
loadPicture("menu2");
drawString2(_res->getMenuString(LocaleData::LI_16_ENTER_PASSWORD1), 15, 3);
drawString2(_res->getMenuString(LocaleData::LI_17_ENTER_PASSWORD2), 17, 3);
for (int i = 0; i < len; ++i) {
_vid->drawChar((uint8)password[i], 21, i + 15);
}
_vid->drawChar(0x20, 21, len + 15);
_vid->markBlockAsDirty(15 * 8, 21 * 8, (len + 1) * 8, 8);
_vid->updateScreen();
_stub->sleep(EVENTS_DELAY);
_stub->processEvents();
char c = _stub->_pi.lastChar;
if (c != 0) {
_stub->_pi.lastChar = 0;
if (len < 6) {
if (c >= 'a' && c <= 'z') {
c &= ~0x20;
}
if ((c >= 'A' && c <= 'Z') || (c == 0x20)) {
password[len] = c;
++len;
}
}
}
if (_stub->_pi.backspace) {
_stub->_pi.backspace = false;
if (len > 0) {
--len;
}
}
if (_stub->_pi.enter) {
_stub->_pi.enter = false;
password[len] = '\0';
for (int level = 0; level < 8; ++level) {
for (int skill = 0; skill < 3; ++skill) {
if (strcmp(_passwords[level][skill], password) == 0) {
new_level = level;
new_skill = skill;
return true;
}
}
}
return false;
}
} while (!_stub->_pi.quit);
return false;
}
bool Menu::handleTitleScreen(uint8 &new_skill, uint8 &new_level) {
debug(DBG_MENU, "Menu::handleTitleScreen()");
bool quit_loop = false;
int menu_entry = 0;
bool reinit_screen = true;
bool continue_game = true;
_charVar1 = 0;
_charVar2 = 0;
_charVar3 = 0;
_charVar4 = 0;
_charVar5 = 0;
_ply->play(1);
while (!quit_loop) {
if (reinit_screen) {
_vid->fadeOut();
loadPicture("menu1");
_vid->fullRefresh();
_charVar3 = 1;
_charVar4 = 2;
menu_entry = 0;
reinit_screen = false;
}
int selected_menu_entry = -1;
for (int i = 0; i < 5; ++i) {
int color = (i == menu_entry) ? 2 : 3;
drawString(_res->getMenuString(LocaleData::LI_07_START + i), 16 + i * 2, 20, color);
}
_vid->updateScreen();
_stub->sleep(EVENTS_DELAY);
_stub->processEvents();
if (_stub->_pi.dirMask & PlayerInput::DIR_UP) {
_stub->_pi.dirMask &= ~PlayerInput::DIR_UP;
if (menu_entry != 0) {
--menu_entry;
} else {
menu_entry = 4;
}
}
if (_stub->_pi.dirMask & PlayerInput::DIR_DOWN) {
_stub->_pi.dirMask &= ~PlayerInput::DIR_DOWN;
if (menu_entry != 4) {
++menu_entry;
} else {
menu_entry = 0;
}
}
if (_stub->_pi.enter) {
_stub->_pi.enter = false;
selected_menu_entry = menu_entry;
}
if (selected_menu_entry != -1) {
switch (selected_menu_entry) {
case MENU_OPTION_ITEM_START:
new_level = 0;
quit_loop = true;
break;
case MENU_OPTION_ITEM_SKILL:
handleSkillScreen(new_skill);
reinit_screen = true;
break;
case MENU_OPTION_ITEM_PASSWORD:
if (handlePasswordScreen(new_skill, new_level)) {
quit_loop = true;
} else {
reinit_screen = true;
}
break;
case MENU_OPTION_ITEM_INFO:
handleInfoScreen();
reinit_screen = true;
break;
case MENU_OPTION_ITEM_QUIT:
continue_game = false;
quit_loop = true;
break;
}
}
if (_stub->_pi.quit) {
continue_game = false;
quit_loop = true;
break;
}
}
_ply->stop();
return continue_game;
}

View File

@@ -1,67 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MENU_H__
#define __MENU_H__
#include "intern.h"
struct ModPlayer;
struct Resource;
struct SystemStub;
struct Video;
struct Menu {
enum {
MENU_OPTION_ITEM_START = 0,
MENU_OPTION_ITEM_SKILL,
MENU_OPTION_ITEM_PASSWORD,
MENU_OPTION_ITEM_INFO,
MENU_OPTION_ITEM_QUIT
};
enum {
EVENTS_DELAY = 80
};
static const char *_passwords[8][3];
ModPlayer *_ply;
Resource *_res;
SystemStub *_stub;
Video *_vid;
const char **_textOptions;
uint8 _charVar1;
uint8 _charVar2;
uint8 _charVar3;
uint8 _charVar4;
uint8 _charVar5;
Menu(ModPlayer *ply, Resource *res, SystemStub *stub, Video *vid);
void drawString(const char *str, int16 y, int16 x, uint8 color);
void drawString2(const char *str, int16 y, int16 x);
void loadPicture(const char *prefix);
void handleInfoScreen();
void handleSkillScreen(uint8 &new_skill);
bool handlePasswordScreen(uint8 &new_skill, uint8 &new_level);
bool handleTitleScreen(uint8 &new_skill, uint8 &new_level);
};
#endif // __MENU_H__

View File

@@ -1,124 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "mixer.h"
#include "systemstub.h"
Mixer::Mixer(SystemStub *stub)
: _stub(stub) {
}
void Mixer::init() {
memset(_channels, 0, sizeof(_channels));
_premixHook = 0;
_mutex = _stub->createMutex();
_stub->startAudio(Mixer::mixCallback, this);
}
void Mixer::free() {
stopAll();
_stub->stopAudio();
_stub->destroyMutex(_mutex);
}
void Mixer::setPremixHook(PremixHook premixHook, void *userData) {
debug(DBG_SND, "Mixer::setPremixHook()");
MutexStack(_stub, _mutex);
_premixHook = premixHook;
_premixHookData = userData;
}
void Mixer::play(const MixerChunk *mc, uint16 freq, uint8 volume) {
debug(DBG_SND, "Mixer::play(%d, %d)", freq, volume);
MutexStack(_stub, _mutex);
MixerChannel *ch = 0;
for (int i = 0; i < NUM_CHANNELS; ++i) {
MixerChannel *cur = &_channels[i];
if (cur->active) {
if (cur->chunk.data == mc->data) {
cur->chunkPos = 0;
return;
}
} else {
ch = cur;
break;
}
}
if (ch) {
ch->active = true;
ch->volume = volume;
ch->chunk = *mc;
ch->chunkPos = 0;
ch->chunkInc = (freq << FRAC_BITS) / _stub->getOutputSampleRate();
}
}
uint32 Mixer::getSampleRate() const {
return _stub->getOutputSampleRate();
}
void Mixer::stopAll() {
debug(DBG_SND, "Mixer::stopAll()");
MutexStack(_stub, _mutex);
for (uint8 i = 0; i < NUM_CHANNELS; ++i) {
_channels[i].active = false;
}
}
inline void addclamp(int16& a, int b) {
int add = a + b;
if (add < -32767) {
add = -32767;
} else if (add > 32767) {
add = 32767;
}
a = add;
}
void Mixer::mix(int8 *buf1, int len) {
int16 *buf = (int16 *)buf1;
MutexStack(_stub, _mutex);
memset(buf, 0, len);
len /= 2;
if (_premixHook) {
if (!_premixHook(_premixHookData, buf, len)) {
_premixHook = 0;
_premixHookData = 0;
}
}
for (uint8 i = 0; i < NUM_CHANNELS; ++i) {
MixerChannel *ch = &_channels[i];
if (ch->active) {
for (int pos = 0; pos < len; ++pos) {
if ((ch->chunkPos >> FRAC_BITS) >= (ch->chunk.len - 1)) {
ch->active = false;
break;
}
int out = resampleLinear(&ch->chunk, ch->chunkPos, ch->chunkInc, FRAC_BITS);
addclamp(buf[pos], out * Mixer::MIX_AMPLIFICATIION * ch->volume / Mixer::MAX_VOLUME );
ch->chunkPos += ch->chunkInc;
}
}
}
}
void Mixer::mixCallback(void *param, uint8 *buf, int len) {
((Mixer *)param)->mix((int8 *)buf, len);
}

View File

@@ -1,96 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MIXER_H__
#define __MIXER_H__
#include "intern.h"
struct MixerChunk {
uint8 *data;
uint32 len;
int8 getPCM(int offset) const {
if (offset < 0) {
offset = 0;
} else if (offset >= (int)len) {
offset = len - 1;
}
return (int8)data[offset];
}
};
struct MixerChannel {
uint8 active;
uint8 volume;
MixerChunk chunk;
uint32 chunkPos;
uint32 chunkInc;
};
struct SystemStub;
struct Mixer {
typedef bool (*PremixHook)(void *userData, int16 *buf, int len);
enum {
NUM_CHANNELS = 4,
FRAC_BITS = 12,
MAX_VOLUME = 64,
MIX_AMPLIFICATIION = 64 // TODO: edit here to tweak sound
};
void *_mutex;
SystemStub *_stub;
MixerChannel _channels[NUM_CHANNELS];
PremixHook _premixHook;
void *_premixHookData;
Mixer(SystemStub *stub);
void init();
void free();
void setPremixHook(PremixHook premixHook, void *userData);
void play(const MixerChunk *mc, uint16 freq, uint8 volume);
void stopAll();
uint32 getSampleRate() const;
void mix(int8 *buf, int len);
//static void addclamp(int16 &a, int b);
static void mixCallback(void *param, uint8 *buf, int len);
};
template <class T>
int resampleLinear(T *sample, int pos, int step, int fracBits) {
const int inputPos = pos >> fracBits;
const int inputFrac = (1 << fracBits) - 1;
int out = sample->getPCM(inputPos);
out += (sample->getPCM(inputPos + 1) - out) * inputFrac >> fracBits;
return out;
}
template <class T>
int resample3Pt(T *sample, int pos, int step, int fracBits) {
const int inputPos = pos >> fracBits;
const int inputFrac = (1 << fracBits) - 1;
int out = sample->getPCM(inputPos) >> 1;
out += sample->getPCM(inputPos + ((inputFrac - (step >> 1)) >> fracBits)) >> 2;
out += sample->getPCM(inputPos + ((inputFrac + (step >> 1)) >> fracBits)) >> 2;
return out;
}
#endif // __MIXER_H__

View File

@@ -1,533 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "file.h"
#include "mixer.h"
#include "mod_player.h"
ModPlayer::ModPlayer(Mixer *mixer, const char *dataPath)
: _playing(false), _mix(mixer), _dataPath(dataPath) {
memset(&_modInfo, 0, sizeof(_modInfo));
}
uint16 ModPlayer::findPeriod(uint16 period, uint8 fineTune) const {
for (int p = 0; p < 36; ++p) {
if (_periodTable[p] == period) {
return fineTune * 36 + p;
}
}
error("Invalid period=%d", period);
return 0;
}
void ModPlayer::load(File *f) {
f->read(_modInfo.songName, 20);
_modInfo.songName[20] = 0;
debug(DBG_MOD, "songName = '%s'", _modInfo.songName);
for (int s = 0; s < NUM_SAMPLES; ++s) {
SampleInfo *si = &_modInfo.samples[s];
f->read(si->name, 22);
si->name[22] = 0;
si->len = f->readUint16BE() * 2;
si->fineTune = f->readByte();
si->volume = f->readByte();
si->repeatPos = f->readUint16BE() * 2;
si->repeatLen = f->readUint16BE() * 2;
si->data = 0;
assert(si->len == 0 || si->repeatPos + si->repeatLen <= si->len);
debug(DBG_MOD, "sample=%d name='%s' len=%d vol=%d", s, si->name, si->len, si->volume);
}
_modInfo.numPatterns = f->readByte();
assert(_modInfo.numPatterns < NUM_PATTERNS);
f->readByte(); // 0x7F
f->read(_modInfo.patternOrderTable, NUM_PATTERNS);
f->readUint32BE(); // 'M.K.', Protracker, 4 channels
uint16 n = 0;
for (int i = 0; i < NUM_PATTERNS; ++i) {
if (_modInfo.patternOrderTable[i] != 0) {
n = MAX(n, _modInfo.patternOrderTable[i]);
}
}
debug(DBG_MOD, "numPatterns=%d",n + 1);
n = (n + 1) * 64 * 4 * 4; // 64 lines of 4 notes per channel
_modInfo.patternsTable = (uint8 *)malloc(n);
assert(_modInfo.patternsTable);
f->read(_modInfo.patternsTable, n);
for (int s = 0; s < NUM_SAMPLES; ++s) {
SampleInfo *si = &_modInfo.samples[s];
if (si->len != 0) {
si->data = (int8 *)malloc(si->len);
if (si->data) {
f->read(si->data, si->len);
}
}
}
}
void ModPlayer::unload() {
if (_modInfo.songName[0]) {
free(_modInfo.patternsTable);
for (int s = 0; s < NUM_SAMPLES; ++s) {
free(_modInfo.samples[s].data);
}
memset(&_modInfo, 0, sizeof(_modInfo));
}
}
void ModPlayer::play(uint8 num) {
if (!_playing && num < _modulesFilesCount) {
File f;
bool found = false;
for (uint8 i = 0; i < ARRAYSIZE(_modulesFiles[num]); ++i) {
if (f.open(_modulesFiles[num][i], _dataPath, "rb")) {
found = true;
break;
}
}
if (!found) {
warning("Can't find music file %d", num);
} else {
load(&f);
_currentPatternOrder = 0;
_currentPatternPos = 0;
_currentTick = 0;
_patternDelay = 0;
_songSpeed = 6;
_songTempo = 125;
_patternLoopPos = 0;
_patternLoopCount = -1;
_samplesLeft = 0;
_songNum = num;
_introSongHack = false;
memset(_tracks, 0, sizeof(_tracks));
_mix->setPremixHook(mixCallback, this);
_playing = true;
}
}
}
void ModPlayer::stop() {
if (_playing) {
_mix->setPremixHook(0, 0);
_playing = false;
}
unload();
}
void ModPlayer::handleNote(int trackNum, uint32 noteData) {
Track *tk = &_tracks[trackNum];
uint16 sampleNum = ((noteData >> 24) & 0xF0) | ((noteData >> 12) & 0xF);
uint16 samplePeriod = (noteData >> 16) & 0xFFF;
uint16 effectData = noteData & 0xFFF;
debug(DBG_MOD, "ModPlayer::handleNote(%d) p=%d/%d sampleNumber=0x%X samplePeriod=0x%X effectData=0x%X tk->period=%d", trackNum, _currentPatternPos, _currentPatternOrder, sampleNum, samplePeriod, effectData, tk->period);
if (sampleNum != 0) {
tk->sample = &_modInfo.samples[sampleNum - 1];
tk->volume = tk->sample->volume;
tk->pos = 0;
}
if (samplePeriod != 0) {
tk->periodIndex = findPeriod(samplePeriod, tk->sample->fineTune);
if ((effectData >> 8) != 0x3 && (effectData >> 8) != 0x5) {
tk->period = _periodTable[tk->periodIndex];
tk->freq = PAULA_FREQ / tk->period;
} else {
tk->portamento = _periodTable[tk->periodIndex];
}
tk->vibratoAmp = 0;
tk->vibratoSpeed = 0;
tk->vibratoPos = 0;
}
tk->effectData = effectData;
}
void ModPlayer::applyVolumeSlide(int trackNum, int amount) {
debug(DBG_MOD, "ModPlayer::applyVolumeSlide(%d, %d)", trackNum, amount);
Track *tk = &_tracks[trackNum];
int vol = tk->volume + amount;
if (vol < 0) {
vol = 0;
} else if (vol > 64) {
vol = 64;
}
tk->volume = vol;
}
void ModPlayer::applyVibrato(int trackNum) {
debug(DBG_MOD, "ModPlayer::applyVibrato(%d)", trackNum);
Track *tk = &_tracks[trackNum];
int vib = tk->vibratoAmp * _sineWaveTable[tk->vibratoPos] / 128;
if (tk->period + vib != 0) {
tk->freq = PAULA_FREQ / (tk->period + vib);
}
tk->vibratoPos += tk->vibratoSpeed;
if (tk->vibratoPos >= 64) {
tk->vibratoPos = 0;
}
}
void ModPlayer::applyPortamento(int trackNum) {
debug(DBG_MOD, "ModPlayer::applyPortamento(%d)", trackNum);
Track *tk = &_tracks[trackNum];
if (tk->period < tk->portamento) {
tk->period = MIN(tk->period + tk->portamentoSpeed, tk->portamento);
} else if (tk->period > tk->portamento) {
tk->period = MAX(tk->period - tk->portamentoSpeed, tk->portamento);
}
if (tk->period != 0) {
tk->freq = PAULA_FREQ / tk->period;
}
}
void ModPlayer::handleEffect(int trackNum, bool tick) {
Track *tk = &_tracks[trackNum];
uint8 effectNum = tk->effectData >> 8;
uint8 effectXY = tk->effectData & 0xFF;
uint8 effectX = effectXY >> 4;
uint8 effectY = effectXY & 0xF;
debug(DBG_MOD, "ModPlayer::handleEffect(%d) effectNum=0x%X effectXY=0x%X", trackNum, effectNum, effectXY);
switch (effectNum) {
case 0x0: // arpeggio
if (tick && effectXY != 0) {
uint16 period = tk->period;
switch (_currentTick & 3) {
case 1:
period = _periodTable[tk->periodIndex + effectX];
break;
case 2:
period = _periodTable[tk->periodIndex + effectY];
break;
}
tk->freq = PAULA_FREQ / period;
}
break;
case 0x1: // portamento up
if (tick) {
tk->period -= effectXY;
if (tk->period < 113) { // note B-3
tk->period = 113;
}
tk->freq = PAULA_FREQ / tk->period;
}
break;
case 0x2: // portamento down
if (tick) {
tk->period += effectXY;
if (tk->period > 856) { // note C-1
tk->period = 856;
}
tk->freq = PAULA_FREQ / tk->period;
}
break;
case 0x3: // tone portamento
if (!tick) {
if (effectXY != 0) {
tk->portamentoSpeed = effectXY;
}
} else {
applyPortamento(trackNum);
}
break;
case 0x4: // vibrato
if (!tick) {
if (effectX != 0) {
tk->vibratoSpeed = effectX;
}
if (effectY != 0) {
tk->vibratoAmp = effectY;
}
} else {
applyVibrato(trackNum);
}
break;
case 0x5: // tone portamento + volume slide
if (tick) {
applyPortamento(trackNum);
applyVolumeSlide(trackNum, effectX - effectY);
}
break;
case 0x6: // vibrato + volume slide
if (tick) {
applyVibrato(trackNum);
applyVolumeSlide(trackNum, effectX - effectY);
}
break;
case 0x9: // set sample offset
if (!tick) {
tk->pos = effectXY << (8 + FRAC_BITS);
}
break;
case 0xA: // volume slide
if (tick) {
applyVolumeSlide(trackNum, effectX - effectY);
}
break;
case 0xB: // position jump
if (!tick) {
_currentPatternOrder = effectXY;
_currentPatternPos = 0;
assert(_currentPatternOrder < _modInfo.numPatterns);
}
break;
case 0xC: // set volume
if (!tick) {
assert(effectXY <= 64);
tk->volume = effectXY;
}
break;
case 0xD: // pattern break
if (!tick) {
_currentPatternPos = effectX * 10 + effectY;
assert(_currentPatternPos < 64);
++_currentPatternOrder;
debug(DBG_MOD, "_currentPatternPos = %d _currentPatternOrder = %d", _currentPatternPos, _currentPatternOrder);
}
break;
case 0xE: // extended effects
switch (effectX) {
case 0x0: // set filter, ignored
break;
case 0x1: // fineslide up
if (!tick) {
tk->period -= effectY;
if (tk->period < 113) { // B-3 note
tk->period = 113;
}
tk->freq = PAULA_FREQ / tk->period;
}
break;
case 0x2: // fineslide down
if (!tick) {
tk->period += effectY;
if (tk->period > 856) { // C-1 note
tk->period = 856;
}
tk->freq = PAULA_FREQ / tk->period;
}
break;
case 0x6: // loop pattern
if (!tick) {
if (effectY == 0) {
_patternLoopPos = _currentPatternPos | (_currentPatternOrder << 8);
debug(DBG_MOD, "_patternLoopPos=%d/%d", _currentPatternPos, _currentPatternOrder);
} else {
if (_patternLoopCount == -1) {
_patternLoopCount = effectY;
_currentPatternPos = _patternLoopPos & 0xFF;
_currentPatternOrder = _patternLoopPos >> 8;
} else {
--_patternLoopCount;
if (_patternLoopCount != 0) {
_currentPatternPos = _patternLoopPos & 0xFF;
_currentPatternOrder = _patternLoopPos >> 8;
} else {
_patternLoopCount = -1;
}
}
debug(DBG_MOD, "_patternLoopCount=%d", _patternLoopCount);
}
}
break;
case 0x9: // retrigger sample
if (tick) {
tk->retriggerCounter = effectY;
} else {
if (tk->retriggerCounter == 0) {
tk->pos = 0;
tk->retriggerCounter = effectY;
debug(DBG_MOD, "retrigger sample=%d _songSpeed=%d", effectY, _songSpeed);
}
--tk->retriggerCounter;
}
break;
case 0xA: // fine volume slide up
if (!tick) {
applyVolumeSlide(trackNum, effectY);
}
break;
case 0xB: // fine volume slide down
if (!tick) {
applyVolumeSlide(trackNum, -effectY);
}
break;
case 0xC: // cut sample
if (!tick) {
tk->cutCounter = effectY;
} else {
--tk->cutCounter;
if (tk->cutCounter == 0) {
tk->volume = 0;
}
}
case 0xD: // delay sample
if (!tick) {
tk->delayCounter = effectY;
} else {
if (tk->delayCounter != 0) {
--tk->delayCounter;
}
}
break;
case 0xE: // delay pattern
if (!tick) {
debug(DBG_MOD, "ModPlayer::handleEffect() _currentTick=%d delay pattern=%d", _currentTick, effectY);
_patternDelay = effectY;
}
break;
default:
warning("Unhandled extended effect 0x%X params=0x%X", effectX, effectY);
break;
}
break;
case 0xF: // set speed
if (!tick) {
if (effectXY < 0x20) {
_songSpeed = effectXY;
} else {
_songTempo = effectXY;
}
}
break;
default:
warning("Unhandled effect 0x%X params=0x%X", effectNum, effectXY);
break;
}
}
void ModPlayer::handleTick() {
if (!_playing) {
return;
}
// if (_patternDelay != 0) {
// --_patternDelay;
// return;
// }
if (_currentTick == 0) {
debug(DBG_MOD, "_currentPatternOrder=%d _currentPatternPos=%d", _currentPatternOrder, _currentPatternPos);
uint8 currentPattern = _modInfo.patternOrderTable[_currentPatternOrder];
const uint8 *p = _modInfo.patternsTable + (currentPattern * 64 + _currentPatternPos) * 16;
for (int i = 0; i < NUM_TRACKS; ++i) {
uint32 noteData = READ_BE_UINT32(p);
handleNote(i, noteData);
p += 4;
}
++_currentPatternPos;
if (_currentPatternPos == 64) {
++_currentPatternOrder;
_currentPatternPos = 0;
debug(DBG_MOD, "ModPlayer::handleTick() _currentPatternOrder = %d/%d", _currentPatternOrder, _modInfo.numPatterns);
// On the amiga version, the introduction cutscene is shorter than the PC version ;
// so the music module doesn't synchronize at all with the PC datafiles, here we
// add a hack to let the music play longer
if (_songNum == 0 && _currentPatternOrder == 3 && !_introSongHack) {
_currentPatternOrder = 1;
_introSongHack = true;
// warning("Introduction module synchronization hack");
}
}
}
for (int i = 0; i < NUM_TRACKS; ++i) {
handleEffect(i, (_currentTick != 0));
}
++_currentTick;
if (_currentTick == _songSpeed) {
_currentTick = 0;
}
if (_currentPatternOrder == _modInfo.numPatterns) {
debug(DBG_MOD, "ModPlayer::handleEffect() _currentPatternOrder == _modInfo.numPatterns");
_playing = false;
}
}
inline void addclamp(int16& a, int b) {
int add = a + b;
if (add < -32767) {
add = -32767;
} else if (add > 32767) {
add = 32767;
}
a = add;
}
void ModPlayer::mixSamples(int16 *buf, int samplesLen) {
for (int i = 0; i < NUM_TRACKS; ++i) {
Track *tk = &_tracks[i];
if (tk->sample != 0 && tk->delayCounter == 0) {
int16 *mixbuf = buf;
SampleInfo *si = tk->sample;
int len = si->len << FRAC_BITS;
int loopLen = si->repeatLen << FRAC_BITS;
int loopPos = si->repeatPos << FRAC_BITS;
int deltaPos = (tk->freq << FRAC_BITS) / _mix->getSampleRate();
int curLen = samplesLen;
int pos = tk->pos;
while (curLen != 0) {
int count;
if (loopLen > (2 << FRAC_BITS)) {
if (pos >= loopPos + loopLen) {
pos -= loopLen;
}
count = MIN(curLen, (loopPos + loopLen - pos - 1) / deltaPos + 1);
curLen -= count;
} else {
if (pos >= len) {
count = 0;
} else {
count = MIN(curLen, (len - pos - 1) / deltaPos + 1);
}
curLen = 0;
}
while (count--) {
int out = resample3Pt(si, pos, deltaPos, FRAC_BITS);
addclamp(*mixbuf++, out * Mixer::MIX_AMPLIFICATIION * tk->volume / 64);
pos += deltaPos;
}
}
tk->pos = pos;
}
}
}
bool ModPlayer::mix(int16 *buf, int len) {
if (_playing) {
memset(buf, 0, len*2);
const int samplesPerTick = _mix->getSampleRate() / (50 * _songTempo / 125);
while (len != 0) {
if (_samplesLeft == 0) {
handleTick();
_samplesLeft = samplesPerTick;
}
int count = _samplesLeft;
if (count > len) {
count = len;
}
_samplesLeft -= count;
len -= count;
mixSamples(buf, count);
buf += count;
}
}
return _playing;
}
bool ModPlayer::mixCallback(void *param, int16 *buf, int len) {
return ((ModPlayer *)param)->mix(buf, len);
}

View File

@@ -1,122 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MOD_PLAYER_H__
#define __MOD_PLAYER_H__
#include "intern.h"
struct File;
struct Mixer;
struct ModPlayer {
enum {
NUM_SAMPLES = 31,
NUM_TRACKS = 4,
NUM_PATTERNS = 128,
FRAC_BITS = 12,
PAULA_FREQ = 3546897
};
struct SampleInfo {
char name[23];
uint16 len;
uint8 fineTune;
uint8 volume;
uint16 repeatPos;
uint16 repeatLen;
int8 *data;
int8 getPCM(int offset) const {
if (offset < 0) {
offset = 0;
} else if (offset >= (int)len) {
offset = len - 1;
}
return data[offset];
}
};
struct ModuleInfo {
char songName[21];
SampleInfo samples[NUM_SAMPLES];
uint8 numPatterns;
uint8 patternOrderTable[NUM_PATTERNS];
uint8 *patternsTable;
};
struct Track {
SampleInfo *sample;
uint8 volume;
int pos;
int freq;
uint16 period;
uint16 periodIndex;
uint16 effectData;
int vibratoSpeed;
int vibratoAmp;
int vibratoPos;
int portamento;
int portamentoSpeed;
int retriggerCounter;
int delayCounter;
int cutCounter;
};
static const int8 _sineWaveTable[];
static const uint16 _periodTable[];
static const char *_modulesFiles[][2];
static const int _modulesFilesCount;
ModuleInfo _modInfo;
uint8 _currentPatternOrder;
uint8 _currentPatternPos;
uint8 _currentTick;
uint8 _songSpeed;
uint8 _songTempo;
int _patternDelay;
int _patternLoopPos;
int _patternLoopCount;
int _samplesLeft;
uint8 _songNum;
bool _introSongHack;
bool _playing;
Track _tracks[NUM_TRACKS];
Mixer *_mix;
const char *_dataPath;
ModPlayer(Mixer *mixer, const char *dataPath);
uint16 findPeriod(uint16 period, uint8 fineTune) const;
void load(File *f);
void unload();
void play(uint8 num);
void stop();
void handleNote(int trackNum, uint32 noteData);
void handleTick();
void applyVolumeSlide(int trackNum, int amount);
void applyVibrato(int trackNum);
void applyPortamento(int trackNum);
void handleEffect(int trackNum, bool tick);
void mixSamples(int16 *buf, int len);
bool mix(int16 *buf, int len);
static bool mixCallback(void *param, int16 *buf, int len);
};
#endif // __MOD_PLAYER_H__

View File

@@ -1,742 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "file.h"
#include "unpack.h"
#include "resource.h"
Resource::Resource(const char *dataPath, Version ver) {
memset(this, 0, sizeof(Resource));
_dataPath = dataPath;
_ver = ver;
_memBuf = (uint8 *)malloc(0xE000);
}
Resource::~Resource() {
clearLevelRes();
free(_fnt);
free(_icn);
free(_tab);
free(_spr1);
free(_memBuf);
free(_cmd);
free(_pol);
free(_cine_off);
free(_cine_txt);
for (int i = 0; i < _numSfx; ++i) {
free(_sfxList[i].data);
}
free(_sfxList);
free(_voiceBuf);
}
void Resource::clearLevelRes() {
free(_tbn); _tbn = 0;
free(_mbk); _mbk = 0;
free(_mbkData); _mbkData = 0;
free(_pal); _pal = 0;
free(_map); _map = 0;
free(_spc); _spc = 0;
free(_ani); _ani = 0;
free_OBJ();
}
void Resource::load_FIB(const char *fileName) {
debug(DBG_RES, "Resource::load_FIB('%s')", fileName);
static const uint8 fibonacciTable[] = {
0xDE, 0xEB, 0xF3, 0xF8, 0xFB, 0xFD, 0xFE, 0xFF,
0x00, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15
};
sprintf(_entryName, "%s.FIB", fileName);
File f;
if (f.open(_entryName, _dataPath, "rb")) {
_numSfx = f.readUint16LE();
_sfxList = (SoundFx *)malloc(_numSfx * sizeof(SoundFx));
if (!_sfxList) {
error("Unable to allocate SoundFx table");
}
int i;
for (i = 0; i < _numSfx; ++i) {
SoundFx *sfx = &_sfxList[i];
sfx->offset = f.readUint32LE();
sfx->len = f.readUint16LE();
sfx->data = 0;
}
for (i = 0; i < _numSfx; ++i) {
SoundFx *sfx = &_sfxList[i];
if (sfx->len == 0) {
continue;
}
f.seek(sfx->offset);
uint8 *data = (uint8 *)malloc(sfx->len * 2);
if (!data) {
error("Unable to allocate SoundFx data buffer");
}
sfx->data = data;
uint8 c = f.readByte();
*data++ = c;
*data++ = c;
uint16 sz = sfx->len - 1;
while (sz--) {
uint8 d = f.readByte();
c += fibonacciTable[d >> 4];
*data++ = c;
c += fibonacciTable[d & 15];
*data++ = c;
}
sfx->len *= 2;
}
if (f.ioErr()) {
error("I/O error when reading '%s'", _entryName);
}
} else {
error("Can't open '%s'", _entryName);
}
}
void Resource::load_MAP_menu(const char *fileName, uint8 *dstPtr) {
debug(DBG_RES, "Resource::load_MAP_menu('%s')", fileName);
sprintf(_entryName, "%s.MAP", fileName);
File f;
if (f.open(_entryName, _dataPath, "rb")) {
if (f.size() != 0x3800 * 4) {
error("Wrong file size for '%s', %d", _entryName, f.size());
}
f.read(dstPtr, 0x3800 * 4);
if (f.ioErr()) {
error("I/O error when reading '%s'", _entryName);
}
} else {
error("Can't open '%s'", _entryName);
}
}
void Resource::load_PAL_menu(const char *fileName, uint8 *dstPtr) {
debug(DBG_RES, "Resource::load_PAL_menu('%s')", fileName);
sprintf(_entryName, "%s.PAL", fileName);
File f;
if (f.open(_entryName, _dataPath, "rb")) {
if (f.size() != 768) {
error("Wrong file size for '%s', %d", _entryName, f.size());
}
f.read(dstPtr, 768);
if (f.ioErr()) {
error("I/O error when reading '%s'", _entryName);
}
} else {
error("Can't open '%s'", _entryName);
}
}
void Resource::load_SPR_OFF(const char *fileName, uint8 *sprData) {
debug(DBG_RES, "Resource::load_SPR_OFF('%s')", fileName);
sprintf(_entryName, "%s.OFF", fileName);
File f;
if (f.open(_entryName, _dataPath, "rb")) {
int len = f.size();
uint8 *offData = (uint8 *)malloc(len);
if (!offData) {
error("Unable to allocate sprite offsets");
}
f.read(offData, len);
if (f.ioErr()) {
error("I/O error when reading '%s'", _entryName);
}
const uint8 *p = offData;
uint16 pos;
while ((pos = READ_LE_UINT16(p)) != 0xFFFF) {
uint32 off = READ_LE_UINT32(p + 2);
if (off == 0xFFFFFFFF) {
_spr_off[pos] = 0;
} else {
_spr_off[pos] = sprData + off;
}
p += 6;
}
free(offData);
} else {
error("Can't open '%s'", _entryName);
}
}
void Resource::load_CINE() {
const char *baseName = 0;
switch (_ver) {
case VER_FR:
baseName = "FR_CINE";
break;
case VER_EN:
baseName = "ENGCINE";
break;
case VER_DE:
baseName = "GERCINE";
break;
case VER_SP:
baseName = "SPACINE";
break;
}
debug(DBG_RES, "Resource::load_CINE('%s')", baseName);
if (_cine_off == 0) {
sprintf(_entryName, "%s.BIN", baseName);
File f;
if (f.open(_entryName, _dataPath, "rb")) {
int len = f.size();
_cine_off = (uint8 *)malloc(len);
if (!_cine_off) {
error("Unable to allocate cinematics offsets");
}
f.read(_cine_off, len);
if (f.ioErr()) {
error("I/O error when reading '%s'", _entryName);
}
} else {
error("Can't open '%s'", _entryName);
}
}
if (_cine_txt == 0) {
sprintf(_entryName, "%s.TXT", baseName);
File f;
if (f.open(_entryName, _dataPath, "rb")) {
int len = f.size();
_cine_txt = (uint8 *)malloc(len);
if (!_cine_txt) {
error("Unable to allocate cinematics text data");
}
f.read(_cine_txt, len);
if (f.ioErr()) {
error("I/O error when reading '%s'", _entryName);
}
} else {
error("Can't open '%s'", _entryName);
}
}
}
void Resource::load_TEXT() {
File f;
// Load game strings
_stringsTable = 0;
if (f.open("STRINGS.TXT", _dataPath, "rb")) {
const int sz = f.size();
_extStringsTable = (uint8 *)malloc(sz);
if (_extStringsTable) {
f.read(_extStringsTable, sz);
_stringsTable = _extStringsTable;
}
f.close();
}
if (!_stringsTable) {
switch (_ver) {
case VER_FR:
_stringsTable = LocaleData::_stringsTableFR;
break;
case VER_EN:
_stringsTable = LocaleData::_stringsTableEN;
break;
case VER_DE:
_stringsTable = LocaleData::_stringsTableDE;
break;
case VER_SP:
_stringsTable = LocaleData::_stringsTableSP;
break;
}
}
// Load menu strings
_textsTable = 0;
if (f.open("MENUS.TXT", _dataPath, "rb")) {
const int offs = LocaleData::LI_NUM * sizeof(char *);
const int sz = f.size() + 1;
_extTextsTable = (char **)malloc(offs + sz);
if (_extTextsTable) {
char *textData = (char *)_extTextsTable + offs;
f.read(textData, sz);
textData[sz] = 0;
int textsCount = 0;
for (char *eol; (eol = strpbrk(textData, "\r\n")) != 0; ) {
*eol++ = 0;
if (*eol == '\r' || *eol == '\n') {
*eol++ = 0;
}
if (textsCount < LocaleData::LI_NUM && textData[0] != 0) {
_extTextsTable[textsCount] = textData;
++textsCount;
}
textData = eol;
}
if (textsCount < LocaleData::LI_NUM && textData[0] != 0) {
_extTextsTable[textsCount] = textData;
++textsCount;
}
if (textsCount < LocaleData::LI_NUM) {
free(_extTextsTable);
_extTextsTable = 0;
} else {
_textsTable = (const char **)_extTextsTable;
}
}
}
if (!_textsTable) {
switch (_ver) {
case VER_FR:
_textsTable = LocaleData::_textsTableFR;
break;
case VER_EN:
_textsTable = LocaleData::_textsTableEN;
break;
case VER_DE:
_textsTable = LocaleData::_textsTableDE;
break;
case VER_SP:
_textsTable = LocaleData::_textsTableSP;
break;
}
}
}
void Resource::free_TEXT() {
if (_extTextsTable) {
free(_extTextsTable);
_extTextsTable = 0;
}
_stringsTable = 0;
if (_extStringsTable) {
free(_extStringsTable);
_extStringsTable = 0;
}
_textsTable = 0;
}
void Resource::load(const char *objName, int objType) {
debug(DBG_RES, "Resource::load('%s', %d)", objName, objType);
LoadStub loadStub = 0;
switch (objType) {
case OT_MBK:
debug(DBG_RES, "chargement bank (mbk)");
sprintf(_entryName, "%s.MBK", objName);
loadStub = &Resource::load_MBK;
break;
case OT_PGE:
debug(DBG_RES, "chargement piege (pge)");
sprintf(_entryName, "%s.PGE", objName);
loadStub = &Resource::load_PGE;
break;
case OT_PAL:
debug(DBG_RES, "chargement palettes (pal)");
sprintf(_entryName, "%s.PAL", objName);
loadStub = &Resource::load_PAL;
break;
case OT_CT:
debug(DBG_RES, "chargement collision (ct)");
sprintf(_entryName, "%s.CT", objName);
loadStub = &Resource::load_CT;
break;
case OT_MAP:
debug(DBG_RES, "ouverture map (map)");
sprintf(_entryName, "%s.MAP", objName);
loadStub = &Resource::load_MAP;
break;
case OT_SPC:
debug(DBG_RES, "chargement sprites caracteres (spc)");
strcpy(_entryName, "GLOBAL.SPC");
loadStub = &Resource::load_SPC;
break;
case OT_RP:
debug(DBG_RES, "chargement positions des banks pour sprite_car (rp)");
sprintf(_entryName, "%s.RP", objName);
loadStub = &Resource::load_RP;
break;
case OT_SPR:
debug(DBG_RES, "chargement des sprites (spr)");
sprintf(_entryName, "%s.SPR", objName);
loadStub = &Resource::load_SPR;
break;
case OT_SPRM:
debug(DBG_RES, "chargement des sprites monstre (spr)");
sprintf(_entryName, "%s.SPR", objName);
loadStub = &Resource::load_SPRM;
break;
case OT_ICN:
debug(DBG_RES, "chargement des icones (icn)");
sprintf(_entryName, "%s.ICN", objName);
loadStub = &Resource::load_ICN;
break;
case OT_FNT:
debug(DBG_RES, "chargement de la font (fnt)");
sprintf(_entryName, "%s.FNT", objName);
loadStub = &Resource::load_FNT;
break;
case OT_OBJ:
debug(DBG_RES, "chargement objets (obj)");
sprintf(_entryName, "%s.OBJ", objName);
loadStub = &Resource::load_OBJ;
break;
case OT_ANI:
debug(DBG_RES, "chargement animations (ani)");
sprintf(_entryName, "%s.ANI", objName);
loadStub = &Resource::load_ANI;
break;
case OT_TBN:
debug(DBG_RES, "chargement des textes (tbn)");
sprintf(_entryName, "%s.TBN", objName);
loadStub = &Resource::load_TBN;
break;
case OT_CMD:
debug(DBG_RES, "chargement des commandes (cmd)");
sprintf(_entryName, "%s.CMD", objName);
loadStub = &Resource::load_CMD;
break;
case OT_POL:
debug(DBG_RES, "chargement des polygones (pol)");
sprintf(_entryName, "%s.POL", objName);
loadStub = &Resource::load_POL;
break;
default:
error("Unimplemented Resource::load() type %d", objType);
break;
}
if (loadStub) {
File f;
if (f.open(_entryName, _dataPath, "rb")) {
(this->*loadStub)(&f);
if (f.ioErr()) {
error("I/O error when reading '%s'", _entryName);
}
} else {
error("Can't open '%s'", _entryName);
}
}
}
void Resource::load_CT(File *pf) {
debug(DBG_RES, "Resource::load_CT()");
int len = pf->size();
uint8 *tmp = (uint8 *)malloc(len);
if (!tmp) {
error("Unable to allocate CT buffer");
} else {
pf->read(tmp, len);
if (!delphine_unpack((uint8 *)_ctData, tmp, len)) {
error("Bad CRC for collision data");
}
free(tmp);
}
}
void Resource::load_FNT(File *f) {
debug(DBG_RES, "Resource::load_FNT()");
int len = f->size();
_fnt = (uint8 *)malloc(len);
if (!_fnt) {
error("Unable to allocate FNT buffer");
} else {
f->read(_fnt, len);
}
}
void Resource::load_MBK(File *f) {
debug(DBG_RES, "Resource::load_MBK()");
uint8 num = f->readByte();
int dataSize = f->size() - num * 6;
_mbk = (MbkEntry *)malloc(sizeof(MbkEntry) * num);
if (!_mbk) {
error("Unable to allocate MBK buffer");
}
f->seek(0);
for (int i = 0; i < num; ++i) {
f->readUint16BE(); /* unused */
_mbk[i].offset = f->readUint16BE() - num * 6;
_mbk[i].len = f->readUint16BE();
debug(DBG_RES, "dataSize=0x%X entry %d off=0x%X len=0x%X", dataSize, i, _mbk[i].offset + num * 6, _mbk[i].len);
assert(_mbk[i].offset <= dataSize);
}
_mbkData = (uint8 *)malloc(dataSize);
if (!_mbkData) {
error("Unable to allocate MBK data buffer");
}
f->read(_mbkData, dataSize);
}
void Resource::load_ICN(File *f) {
debug(DBG_RES, "Resource::load_ICN()");
int len = f->size();
_icn = (uint8 *)malloc(len);
if (!_icn) {
error("Unable to allocate ICN buffer");
} else {
f->read(_icn, len);
}
}
void Resource::load_SPR(File *f) {
debug(DBG_RES, "Resource::load_SPR()");
int len = f->size() - 12;
_spr1 = (uint8 *)malloc(len);
if (!_spr1) {
error("Unable to allocate SPR buffer");
} else {
f->seek(12);
f->read(_spr1, len);
}
}
void Resource::load_SPRM(File *f) {
debug(DBG_RES, "Resource::load_SPRM()");
int len = f->size() - 12;
f->seek(12);
f->read(_sprm, len);
}
void Resource::load_RP(File *f) {
debug(DBG_RES, "Resource::load_RP()");
f->read(_rp, 0x4A);
}
void Resource::load_SPC(File *f) {
debug(DBG_RES, "Resource::load_SPC()");
int len = f->size();
_spc = (uint8 *)malloc(len);
if (!_spc) {
error("Unable to allocate SPC buffer");
} else {
f->read(_spc, len);
_numSpc = READ_BE_UINT16(_spc) / 2;
}
}
void Resource::load_PAL(File *f) {
debug(DBG_RES, "Resource::load_PAL()");
int len = f->size();
_pal = (uint8 *)malloc(len);
if (!_pal) {
error("Unable to allocate PAL buffer");
} else {
f->read(_pal, len);
}
}
void Resource::load_MAP(File *f) {
debug(DBG_RES, "Resource::load_MAP()");
int len = f->size();
_map = (uint8 *)malloc(len);
if (!_map) {
error("Unable to allocate MAP buffer");
} else {
f->read(_map, len);
}
}
void Resource::load_OBJ(File *f) {
debug(DBG_RES, "Resource::load_OBJ()");
uint16 i;
_numObjectNodes = f->readUint16LE();
assert(_numObjectNodes < 255);
uint32 offsets[256];
for (i = 0; i < _numObjectNodes; ++i) {
offsets[i] = f->readUint32LE();
}
offsets[i] = f->size() - 2;
int numObjectsCount = 0;
uint16 objectsCount[256];
for (i = 0; i < _numObjectNodes; ++i) {
int diff = offsets[i + 1] - offsets[i];
if (diff != 0) {
objectsCount[numObjectsCount] = (diff - 2) / 0x12;
debug(DBG_RES, "i=%d objectsCount[numObjectsCount]=%d", i, objectsCount[numObjectsCount]);
++numObjectsCount;
}
}
uint32 prevOffset = 0;
ObjectNode *prevNode = 0;
int iObj = 0;
for (i = 0; i < _numObjectNodes; ++i) {
if (prevOffset != offsets[i]) {
ObjectNode *on = (ObjectNode *)malloc(sizeof(ObjectNode));
if (!on) {
error("Unable to allocate ObjectNode num=%d", i);
}
f->seek(offsets[i] + 2);
on->last_obj_number = f->readUint16LE();
on->num_objects = objectsCount[iObj];
debug(DBG_RES, "last=%d num=%d", on->last_obj_number, on->num_objects);
on->objects = (Object *)malloc(sizeof(Object) * on->num_objects);
for (uint16 j = 0; j < on->num_objects; ++j) {
Object *obj = &on->objects[j];
obj->type = f->readUint16LE();
obj->dx = f->readByte();
obj->dy = f->readByte();
obj->init_obj_type = f->readUint16LE();
obj->opcode2 = f->readByte();
obj->opcode1 = f->readByte();
obj->flags = f->readByte();
obj->opcode3 = f->readByte();
obj->init_obj_number = f->readUint16LE();
obj->opcode_arg1 = f->readUint16LE();
obj->opcode_arg2 = f->readUint16LE();
obj->opcode_arg3 = f->readUint16LE();
debug(DBG_RES, "obj_node=%d obj=%d op1=0x%X op2=0x%X op3=0x%X", i, j, obj->opcode2, obj->opcode1, obj->opcode3);
}
++iObj;
prevOffset = offsets[i];
prevNode = on;
}
_objectNodesMap[i] = prevNode;
}
}
void Resource::free_OBJ() {
debug(DBG_RES, "Resource::free_OBJ()");
ObjectNode *prevNode = 0;
for (int i = 0; i < _numObjectNodes; ++i) {
if (_objectNodesMap[i] != prevNode) {
ObjectNode *curNode = _objectNodesMap[i];
free(curNode->objects);
_objectNodesMap[i] = 0;
prevNode = curNode;
}
}
}
void Resource::load_PGE(File *f) {
debug(DBG_RES, "Resource::load_PGE()");
int len = f->size() - 2;
_pgeNum = f->readUint16LE();
memset(_pgeInit, 0, sizeof(_pgeInit));
debug(DBG_RES, "len=%d _pgeNum=%d", len, _pgeNum);
for (uint16 i = 0; i < _pgeNum; ++i) {
InitPGE *pge = &_pgeInit[i];
pge->type = f->readUint16LE();
pge->pos_x = f->readUint16LE();
pge->pos_y = f->readUint16LE();
pge->obj_node_number = f->readUint16LE();
pge->life = f->readUint16LE();
for (int lc = 0; lc < 4; ++lc) {
pge->counter_values[lc] = f->readUint16LE();
}
pge->object_type = f->readByte();
pge->init_room = f->readByte();
pge->room_location = f->readByte();
pge->init_flags = f->readByte();
pge->colliding_icon_num = f->readByte();
pge->icon_num = f->readByte();
pge->object_id = f->readByte();
pge->skill = f->readByte();
pge->mirror_x = f->readByte();
pge->flags = f->readByte();
pge->unk1C = f->readByte();
f->readByte();
pge->text_num = f->readByte();
f->readByte();
}
}
void Resource::load_ANI(File *f) {
debug(DBG_RES, "Resource::load_ANI()");
int size = f->size() - 2;
_ani = (uint8 *)malloc(size);
if (!_ani) {
error("Unable to allocate ANI buffer");
} else {
f->seek(2);
f->read(_ani, size);
}
}
void Resource::load_TBN(File *f) {
debug(DBG_RES, "Resource::load_TBN()");
int len = f->size();
_tbn = (uint8 *)malloc(len);
if (!_tbn) {
error("Unable to allocate TBN buffer");
} else {
f->read(_tbn, len);
}
}
void Resource::load_CMD(File *pf) {
debug(DBG_RES, "Resource::load_CMD()");
free(_cmd);
int len = pf->size();
_cmd = (uint8 *)malloc(len);
if (!_cmd) {
error("Unable to allocate CMD buffer");
} else {
pf->read(_cmd, len);
}
}
void Resource::load_POL(File *pf) {
debug(DBG_RES, "Resource::load_POL()");
free(_pol);
int len = pf->size();
_pol = (uint8 *)malloc(len);
if (!_pol) {
error("Unable to allocate POL buffer");
} else {
pf->read(_pol, len);
}
}
void Resource::load_VCE(int num, int segment, uint8 **buf, uint32 *bufSize) {
*buf = 0;
int offset = _voicesOffsetsTable[num];
if (offset != 0xFFFF) {
const uint16 *p = _voicesOffsetsTable + offset / 2;
offset = (*p++) * 2048;
int count = *p++;
if (segment < count) {
File f;
if (f.open("VOICE.VCE", _dataPath, "rb")) {
int voiceSize = p[segment] * 2048 / 5;
free(_voiceBuf);
_voiceBuf = (uint8 *)malloc(voiceSize);
if (_voiceBuf) {
uint8 *dst = _voiceBuf;
offset += 0x2000;
for (int s = 0; s < count; ++s) {
int len = p[s] * 2048;
for (int i = 0; i < len / (0x2000 + 2048); ++i) {
if (s == segment) {
f.seek(offset);
int n = 2048;
while (n--) {
int v = f.readByte();
if (v & 0x80) {
v = -(v & 0x7F);
}
*dst++ = (uint8)(v & 0xFF);
}
}
offset += 0x2000 + 2048;
}
if (s == segment) {
break;
}
}
*buf = _voiceBuf;
*bufSize = voiceSize;
}
}
}
}
}

View File

@@ -1,169 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __RESOURCE_H__
#define __RESOURCE_H__
#include "intern.h"
struct File;
struct LocaleData {
enum Id {
LI_01_CONTINUE_OR_ABORT = 0,
LI_02_TIME,
LI_03_CONTINUE,
LI_04_ABORT,
LI_05_COMPLETED,
LI_06_LEVEL,
LI_07_START,
LI_08_SKILL,
LI_09_PASSWORD,
LI_10_INFO,
LI_11_QUIT,
LI_12_SKILL_LEVEL,
LI_13_EASY,
LI_14_NORMAL,
LI_15_EXPERT,
LI_16_ENTER_PASSWORD1,
LI_17_ENTER_PASSWORD2,
LI_18_RESUME_GAME,
LI_19_ABORT_GAME,
LI_20_LOAD_GAME,
LI_21_SAVE_GAME,
LI_22_SAVE_SLOT,
LI_NUM
};
static const char *_textsTableFR[];
static const char *_textsTableEN[];
static const char *_textsTableDE[];
static const char *_textsTableSP[];
static const uint8 _stringsTableFR[];
static const uint8 _stringsTableEN[];
static const uint8 _stringsTableDE[];
static const uint8 _stringsTableSP[];
};
struct Resource {
typedef void (Resource::*LoadStub)(File *);
enum ObjectType {
OT_MBK = 0x00,
OT_PGE = 0x01,
OT_PAL = 0x02,
OT_CT = 0x03,
OT_MAP = 0x04,
OT_SGD = 0x05,
OT_SPC = 0x06,
OT_RP = 0x07,
OT_DEMO = 0x08,
OT_ANI = 0x09,
OT_OBJ = 0x0A,
OT_TBN = 0x0B,
OT_SPR = 0x0C,
OT_TAB = 0x0D,
OT_ICN = 0x0E,
OT_FNT = 0x0F,
OT_TXTBIN = 0x10,
OT_CMD = 0x11,
OT_POL = 0x12,
OT_SPRM = 0x13,
OT_OFF = 0x14,
OT_NUM = 0x15
};
static const uint16 _voicesOffsetsTable[];
const char *_dataPath;
Version _ver;
char _entryName[30];
uint8 *_fnt;
MbkEntry *_mbk;
uint8 *_mbkData;
uint8 *_icn;
uint8 *_tab;
uint8 *_spc; // BE
uint16 _numSpc;
uint8 _rp[0x4A];
uint8 *_pal; // BE
uint8 *_ani;
uint8 *_tbn;
int8 _ctData[0x1D00];
uint8 *_spr1;
uint8 *_spr_off[1287]; // 0-0x22F + 0x28E-0x2E9 ... conrad, 0x22F-0x28D : junkie
uint8 _sprm[0x8411]; // MERCENAI.SPR size
uint16 _pgeNum;
InitPGE _pgeInit[256];
uint8 *_map;
uint16 _numObjectNodes;
ObjectNode *_objectNodesMap[255];
uint8 *_memBuf;
SoundFx *_sfxList;
uint8 _numSfx;
uint8 *_cmd;
uint8 *_pol;
uint8 *_cine_off;
uint8 *_cine_txt;
uint8 *_voiceBuf;
char **_extTextsTable;
const char **_textsTable;
uint8 *_extStringsTable;
const uint8 *_stringsTable;
Resource(const char *dataPath, Version ver);
~Resource();
void clearLevelRes();
void load_FIB(const char *fileName);
void load_MAP_menu(const char *fileName, uint8 *dstPtr);
void load_PAL_menu(const char *fileName, uint8 *dstPtr);
void load_SPR_OFF(const char *fileName, uint8 *sprData);
void load_CINE();
void load_TEXT();
void free_TEXT();
void load(const char *objName, int objType);
void load_CT(File *pf);
void load_FNT(File *pf);
void load_MBK(File *pf);
void load_ICN(File *pf);
void load_SPR(File *pf);
void load_SPRM(File *pf);
void load_RP(File *pf);
void load_SPC(File *pf);
void load_PAL(File *pf);
void load_MAP(File *pf);
void load_OBJ(File *pf);
void free_OBJ();
void load_PGE(File *pf);
void load_ANI(File *pf);
void load_TBN(File *pf);
void load_CMD(File *pf);
void load_POL(File *pf);
void load_VCE(int num, int segment, uint8 **buf, uint32 *bufSize);
const uint8 *getGameString(int num) {
return _stringsTable + READ_LE_UINT16(_stringsTable + num * 2);
}
const char *getMenuString(int num) {
return (num >= 0 && num < LocaleData::LI_NUM) ? _textsTable[num] : "";
}
};
#endif // __RESOURCE_H__

View File

@@ -1,142 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "scaler.h"
const Scaler _scalers[] = {
{ "point1x", &point1x, 1 },
{ "point2x", &point2x, 2 },
{ "scale2x", &scale2x, 2 },
{ "point3x", &point3x, 3 },
{ "scale3x", &scale3x, 3 }
};
void point1x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h) {
dstPitch >>= 1;
while (h--) {
memcpy(dst, src, w * 2);
dst += dstPitch;
src += srcPitch;
}
}
void point2x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h) {
dstPitch >>= 1;
while (h--) {
uint16 *p = dst;
for (int i = 0; i < w; ++i, p += 2) {
uint16 c = *(src + i);
*(p) = c;
*(p + 1) = c;
*(p + dstPitch) = c;
*(p + dstPitch + 1) = c;
}
dst += dstPitch * 2;
src += srcPitch;
}
}
void point3x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h) {
dstPitch >>= 1;
while (h--) {
uint16 *p = dst;
for (int i = 0; i < w; ++i, p += 3) {
uint16 c = *(src + i);
*(p) = c;
*(p + 1) = c;
*(p + 2) = c;
*(p + dstPitch) = c;
*(p + dstPitch + 1) = c;
*(p + dstPitch + 2) = c;
*(p + 2 * dstPitch) = c;
*(p + 2 * dstPitch + 1) = c;
*(p + 2 * dstPitch + 2) = c;
}
dst += dstPitch * 3;
src += srcPitch;
}
}
void scale2x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h) {
dstPitch >>= 1;
while (h--) {
uint16 *p = dst;
for (int i = 0; i < w; ++i, p += 2) {
uint16 B = *(src + i - srcPitch);
uint16 D = *(src + i - 1);
uint16 E = *(src + i);
uint16 F = *(src + i + 1);
uint16 H = *(src + i + srcPitch);
if (B != H && D != F) {
*(p) = D == B ? D : E;
*(p + 1) = B == F ? F : E;
*(p + dstPitch) = D == H ? D : E;
*(p + dstPitch + 1) = H == F ? F : E;
} else {
*(p) = E;
*(p + 1) = E;
*(p + dstPitch) = E;
*(p + dstPitch + 1) = E;
}
}
dst += dstPitch * 2;
src += srcPitch;
}
}
void scale3x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h) {
dstPitch >>= 1;
while (h--) {
uint16 *p = dst;
for (int i = 0; i < w; ++i, p += 3) {
uint16 A = *(src + i - srcPitch - 1);
uint16 B = *(src + i - srcPitch);
uint16 C = *(src + i - srcPitch + 1);
uint16 D = *(src + i - 1);
uint16 E = *(src + i);
uint16 F = *(src + i + 1);
uint16 G = *(src + i + srcPitch - 1);
uint16 H = *(src + i + srcPitch);
uint16 I = *(src + i + srcPitch + 1);
if (B != H && D != F) {
*(p) = D == B ? D : E;
*(p + 1) = (D == B && E != C) || (B == F && E != A) ? B : E;
*(p + 2) = B == F ? F : E;
*(p + dstPitch) = (D == B && E != G) || (D == B && E != A) ? D : E;
*(p + dstPitch + 1) = E;
*(p + dstPitch + 2) = (B == F && E != I) || (H == F && E != C) ? F : E;
*(p + 2 * dstPitch) = D == H ? D : E;
*(p + 2 * dstPitch + 1) = (D == H && E != I) || (H == F && E != G) ? H : E;
*(p + 2 * dstPitch + 2) = H == F ? F : E;
} else {
*(p) = E;
*(p + 1) = E;
*(p + 2) = E;
*(p + dstPitch) = E;
*(p + dstPitch + 1) = E;
*(p + dstPitch + 2) = E;
*(p + 2 * dstPitch) = E;
*(p + 2 * dstPitch + 1) = E;
*(p + 2 * dstPitch + 2) = E;
}
}
dst += dstPitch * 3;
src += srcPitch;
}
}

View File

@@ -1,44 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __SCALER_H__
#define __SCALER_H__
#include "intern.h"
typedef void (*ScaleProc)(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h);
enum {
NUM_SCALERS = 5
};
struct Scaler {
const char *name;
ScaleProc proc;
uint8 factor;
};
extern const Scaler _scalers[];
void point1x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h);
void point2x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h);
void point3x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h);
void scale2x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h);
void scale3x(uint16 *dst, uint16 dstPitch, const uint16 *src, uint16 srcPitch, uint16 w, uint16 h);
#endif // __SCALER_H__

View File

@@ -1,185 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "mixer.h"
#include "sfx_player.h"
SfxPlayer::SfxPlayer(Mixer *mixer)
: _mod(0), _playing(false), _mix(mixer) {
}
void SfxPlayer::play(uint8 num) {
debug(DBG_SFX, "SfxPlayer::play(%d)", num);
if (!_playing) {
if (num >= 68 && num <= 75) {
static const Module *modTable[] = {
&_module68, &_module68, &_module70, &_module70,
&_module72, &_module73, &_module74, &_module75
};
_mod = modTable[num - 68];
_curOrder = 0;
_numOrders = READ_BE_UINT16(_mod->moduleData);
_orderDelay = 0;
_modData = _mod->moduleData + 0x22;
memset(_samples, 0, sizeof(_samples));
_samplesLeft = 0;
_mix->setPremixHook(mixCallback, this);
_playing = true;
}
}
}
void SfxPlayer::stop() {
if (_playing) {
_mix->setPremixHook(0, 0);
_playing = false;
}
}
void SfxPlayer::playSample(int channel, const uint8 *sampleData, uint16 period) {
assert(channel < NUM_CHANNELS);
SampleInfo *si = &_samples[channel];
si->len = READ_BE_UINT16(sampleData); sampleData += 2;
si->vol = READ_BE_UINT16(sampleData); sampleData += 2;
si->loopPos = READ_BE_UINT16(sampleData); sampleData += 2;
si->loopLen = READ_BE_UINT16(sampleData); sampleData += 2;
si->freq = PAULA_FREQ / period;
si->pos = 0;
si->data = sampleData;
}
void SfxPlayer::handleTick() {
if (!_playing) {
return;
}
if (_orderDelay != 0) {
--_orderDelay;
// check for end of song
if (_orderDelay == 0 && _modData == 0) {
_playing = false;
}
} else {
_orderDelay = READ_BE_UINT16(_mod->moduleData + 2);
debug(DBG_SFX, "curOrder=%d/%d _orderDelay=%d\n", _curOrder, _numOrders, _orderDelay);
int16 period = 0;
for (int ch = 0; ch < 3; ++ch) {
const uint8 *sampleData = 0;
uint8 b = *_modData++;
if (b != 0) {
--b;
assert(b < 5);
period = READ_BE_UINT16(_mod->moduleData + 4 + b * 2);
sampleData = _mod->sampleData[b];
}
b = *_modData++;
if (b != 0) {
int16 per = period + (b - 1);
if (per >= 0 && per < 40) {
per = _periodTable[per];
} else if (per == -3) {
per = 0xA0;
} else {
per = 0x71;
}
playSample(ch, sampleData, per);
}
}
++_curOrder;
if (_curOrder >= _numOrders) {
debug(DBG_SFX, "End of song");
_orderDelay += 20;
_modData = 0;
}
}
}
inline void addclamp(int16& a, int b) {
int add = a + b;
if (add < -32767) {
add = -32767;
} else if (add > 32767) {
add = 32767;
}
a = add;
}
void SfxPlayer::mixSamples(int16 *buf, int samplesLen) {
for (int i = 0; i < NUM_CHANNELS; ++i) {
SampleInfo *si = &_samples[i];
if (si->data) {
int16 *mixbuf = buf;
int len = si->len << FRAC_BITS;
int loopLen = si->loopLen << FRAC_BITS;
int loopPos = si->loopPos << FRAC_BITS;
int deltaPos = (si->freq << FRAC_BITS) / _mix->getSampleRate();
int curLen = samplesLen;
int pos = si->pos;
while (curLen != 0) {
int count;
if (loopLen > (2 << FRAC_BITS)) {
assert(si->loopPos + si->loopLen <= si->len);
if (pos >= loopPos + loopLen) {
pos -= loopLen;
}
count = MIN(curLen, (loopPos + loopLen - pos - 1) / deltaPos + 1);
curLen -= count;
} else {
if (pos >= len) {
count = 0;
} else {
count = MIN(curLen, (len - pos - 1) / deltaPos + 1);
}
curLen = 0;
}
while (count--) {
int out = resample3Pt(si, pos, deltaPos, FRAC_BITS);
addclamp(*mixbuf++, out * Mixer::MIX_AMPLIFICATIION * si->vol / 64);
pos += deltaPos;
}
}
si->pos = pos;
}
}
}
bool SfxPlayer::mix(int16 *buf, int len) {
if (_playing) {
memset(buf, 0, len*2);
const int samplesPerTick = _mix->getSampleRate() / 50;
while (len != 0) {
if (_samplesLeft == 0) {
handleTick();
_samplesLeft = samplesPerTick;
}
int count = _samplesLeft;
if (count > len) {
count = len;
}
_samplesLeft -= count;
len -= count;
mixSamples(buf, count);
buf += count;
}
}
return _playing;
}
bool SfxPlayer::mixCallback(void *param, int16 *buf, int len) {
return ((SfxPlayer *)param)->mix(buf, len);
}

View File

@@ -1,102 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __SFX_PLAYER_H__
#define __SFX_PLAYER_H__
#include "intern.h"
struct Mixer;
struct SfxPlayer {
enum {
NUM_SAMPLES = 5,
NUM_CHANNELS = 3,
FRAC_BITS = 12,
PAULA_FREQ = 3546897
};
struct Module {
const uint8 *sampleData[NUM_SAMPLES];
const uint8 *moduleData;
};
struct SampleInfo {
uint16 len;
uint16 vol;
uint16 loopPos;
uint16 loopLen;
int freq;
int pos;
const uint8 *data;
int8 getPCM(int offset) const {
if (offset < 0) {
offset = 0;
} else if (offset >= (int)len) {
offset = len - 1;
}
return (int8)data[offset];
}
};
static const uint8 _musicData68[];
static const uint8 _musicData70[];
static const uint8 _musicData72[];
static const uint8 _musicData73[];
static const uint8 _musicData74[];
static const uint8 _musicData75[];
static const uint8 _musicDataSample1[];
static const uint8 _musicDataSample2[]; // tick
static const uint8 _musicDataSample3[]; // bell
static const uint8 _musicDataSample4[];
static const uint8 _musicDataSample5[];
static const uint8 _musicDataSample6[];
static const uint8 _musicDataSample7[];
static const uint8 _musicDataSample8[];
static const Module _module68;
static const Module _module70;
static const Module _module72;
static const Module _module73;
static const Module _module74;
static const Module _module75;
static const uint16 _periodTable[];
const Module *_mod;
bool _playing;
int _samplesLeft;
uint16 _curOrder;
uint16 _numOrders;
uint16 _orderDelay;
const uint8 *_modData;
SampleInfo _samples[NUM_CHANNELS];
Mixer *_mix;
SfxPlayer(Mixer *mixer);
void play(uint8 num);
void stop();
void playSample(int channel, const uint8 *sampleData, uint16 period);
void handleTick();
bool mix(int16 *buf, int len);
void mixSamples(int16 *buf, int samplesLen);
static bool mixCallback(void *param, int16 *buf, int len);
};
#endif // __SFX_PLAYER_H__

View File

@@ -1,49 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __SYS_H__
#define __SYS_H__
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned long uint32;
typedef signed long int32;
inline uint16 READ_BE_UINT16(const void *ptr) {
const uint8 *b = (const uint8 *)ptr;
return (b[0] << 8) | b[1];
}
inline uint32 READ_BE_UINT32(const void *ptr) {
const uint8 *b = (const uint8 *)ptr;
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
}
inline uint16 READ_LE_UINT16(const void *ptr) {
const uint8 *b = (const uint8 *)ptr;
return (b[1] << 8) | b[0];
}
inline uint32 READ_LE_UINT32(const void *ptr) {
const uint8 *b = (const uint8 *)ptr;
return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
}
#endif // __SYS_H__

View File

@@ -1,106 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __SYSTEMSTUB_H__
#define __SYSTEMSTUB_H__
#include "intern.h"
struct PlayerInput {
enum {
DIR_UP = 1 << 0,
DIR_DOWN = 1 << 1,
DIR_LEFT = 1 << 2,
DIR_RIGHT = 1 << 3
};
enum {
DF_FASTMODE = 1 << 0,
DF_DBLOCKS = 1 << 1,
DF_SETLIFE = 1 << 2
};
uint8 dirMask;
bool enter;
bool space;
bool shift;
bool backspace;
bool escape;
char lastChar;
bool save;
bool load;
int stateSlot;
bool inpRecord;
bool inpReplay;
bool mirrorMode;
uint8 dbgMask;
bool quit;
};
struct SystemStub {
typedef void (*AudioCallback)(void *param, uint8 *stream, int len);
PlayerInput _pi;
virtual ~SystemStub() {}
virtual void init(const char *title, uint16 w, uint16 h) = 0;
virtual void destroy() = 0;
virtual void setPalette(const uint8 *pal, uint16 n) = 0;
virtual void setPaletteEntry(uint8 i, const Color *c) = 0;
virtual void getPaletteEntry(uint8 i, Color *c) = 0;
virtual void setOverscanColor(uint8 i) = 0;
virtual void copyRect(int16 x, int16 y, uint16 w, uint16 h, const uint8 *buf, uint32 pitch) = 0;
virtual void updateScreen(uint8 shakeOffset) = 0;
virtual void processEvents() = 0;
virtual void sleep(uint32 duration) = 0;
virtual uint32 getTimeStamp() = 0;
virtual void startAudio(AudioCallback callback, void *param) = 0;
virtual void stopAudio() = 0;
virtual uint32 getOutputSampleRate() = 0;
virtual void *createMutex() = 0;
virtual void destroyMutex(void *mutex) = 0;
virtual void lockMutex(void *mutex) = 0;
virtual void unlockMutex(void *mutex) = 0;
};
struct MutexStack {
SystemStub *_stub;
void *_mutex;
MutexStack(SystemStub *stub, void *mutex)
: _stub(stub), _mutex(mutex) {
_stub->lockMutex(_mutex);
}
~MutexStack() {
_stub->unlockMutex(_mutex);
}
};
extern SystemStub *SystemStub_SDL_create();
extern SystemStub *SystemStub_Win32_create();
#endif // __SYSTEMSTUB_H__

View File

@@ -1,582 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <SDL.h>
#include "scaler.h"
#include "systemstub.h"
struct SystemStub_SDL : SystemStub {
enum {
MAX_BLIT_RECTS = 200,
SOUND_SAMPLE_RATE = 11025,
JOYSTICK_COMMIT_VALUE = 3200
};
uint8 *_offscreen;
SDL_Surface *_screen;
SDL_Surface *_sclscreen;
bool _fullscreen;
uint8 _scaler;
uint8 _overscanColor;
uint16 _pal[256];
uint16 _screenW, _screenH;
SDL_Joystick *_joystick;
SDL_Rect _blitRects[MAX_BLIT_RECTS];
uint16 _numBlitRects;
virtual ~SystemStub_SDL() {}
virtual void init(const char *title, uint16 w, uint16 h);
virtual void destroy();
virtual void setPalette(const uint8 *pal, uint16 n);
virtual void setPaletteEntry(uint8 i, const Color *c);
virtual void getPaletteEntry(uint8 i, Color *c);
virtual void setOverscanColor(uint8 i);
virtual void copyRect(int16 x, int16 y, uint16 w, uint16 h, const uint8 *buf, uint32 pitch);
virtual void updateScreen(uint8 shakeOffset);
virtual void processEvents();
virtual void sleep(uint32 duration);
virtual uint32 getTimeStamp();
virtual void startAudio(AudioCallback callback, void *param);
virtual void stopAudio();
virtual uint32 getOutputSampleRate();
virtual void *createMutex();
virtual void destroyMutex(void *mutex);
virtual void lockMutex(void *mutex);
virtual void unlockMutex(void *mutex);
void prepareGfxMode();
void cleanupGfxMode();
void switchGfxMode(bool fullscreen, uint8 scaler);
void flipGfx();
void forceGfxRedraw();
void drawRect(SDL_Rect *rect, uint8 color, uint16 *dst, uint16 dstPitch);
};
SystemStub *SystemStub_SDL_create() {
return new SystemStub_SDL();
}
void SystemStub_SDL::init(const char *title, uint16 w, uint16 h) {
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
SDL_ShowCursor(SDL_DISABLE);
SDL_WM_SetCaption(title, NULL);
memset(&_pi, 0, sizeof(_pi));
_screenW = w;
_screenH = h;
// allocate some extra bytes for the scaling routines
int size_offscreen = (w + 2) * (h + 2) * 2;
_offscreen = (uint8 *)malloc(size_offscreen);
if (!_offscreen) {
error("SystemStub_SDL::init() Unable to allocate offscreen buffer");
}
memset(_offscreen, 0, size_offscreen);
_fullscreen = false;
_scaler = 0;
memset(_pal, 0, sizeof(_pal));
prepareGfxMode();
_joystick = NULL;
if (SDL_NumJoysticks() > 0) {
_joystick = SDL_JoystickOpen(0);
}
}
void SystemStub_SDL::destroy() {
cleanupGfxMode();
if (SDL_JoystickOpened(0)) {
SDL_JoystickClose(_joystick);
}
SDL_Quit();
}
void SystemStub_SDL::setPalette(const uint8 *pal, uint16 n) {
assert(n <= 256);
for (int i = 0; i < n; ++i) {
uint8 r = pal[i * 3 + 0];
uint8 g = pal[i * 3 + 1];
uint8 b = pal[i * 3 + 2];
_pal[i] = SDL_MapRGB(_screen->format, r, g, b);
}
}
void SystemStub_SDL::setPaletteEntry(uint8 i, const Color *c) {
uint8 r = (c->r << 2) | (c->r & 3);
uint8 g = (c->g << 2) | (c->g & 3);
uint8 b = (c->b << 2) | (c->b & 3);
_pal[i] = SDL_MapRGB(_screen->format, r, g, b);
}
void SystemStub_SDL::getPaletteEntry(uint8 i, Color *c) {
SDL_GetRGB(_pal[i], _screen->format, &c->r, &c->g, &c->b);
c->r >>= 2;
c->g >>= 2;
c->b >>= 2;
}
void SystemStub_SDL::setOverscanColor(uint8 i) {
_overscanColor = i;
}
void SystemStub_SDL::copyRect(int16 x, int16 y, uint16 w, uint16 h, const uint8 *buf, uint32 pitch) {
if (_numBlitRects >= MAX_BLIT_RECTS) {
warning("SystemStub_SDL::copyRect() Too many blit rects, you may experience graphical glitches");
} else {
// extend the dirty region by 1 pixel for scalers accessing 'outer' pixels
--x;
--y;
w += 2;
h += 2;
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
if (x + w > _screenW) {
w = _screenW - x;
}
if (y + h > _screenH) {
h = _screenH - y;
}
SDL_Rect *br = &_blitRects[_numBlitRects];
br->x = _pi.mirrorMode ? _screenW - (x + w) : x;
br->y = y;
br->w = w;
br->h = h;
++_numBlitRects;
uint16 *p = (uint16 *)_offscreen + (br->y + 1) * _screenW + (br->x + 1);
buf += y * pitch + x;
if (_pi.mirrorMode) {
while (h--) {
for (int i = 0; i < w; ++i) {
p[i] = _pal[buf[w - 1 - i]];
}
p += _screenW;
buf += pitch;
}
} else {
while (h--) {
for (int i = 0; i < w; ++i) {
p[i] = _pal[buf[i]];
}
p += _screenW;
buf += pitch;
}
}
if (_pi.dbgMask & PlayerInput::DF_DBLOCKS) {
drawRect(br, 0xE7, (uint16 *)_offscreen + _screenW + 1, _screenW * 2);
}
}
}
void SystemStub_SDL::updateScreen(uint8 shakeOffset) {
//SDL_Flip(_screen);
const int mul = _scalers[_scaler].factor;
if (shakeOffset == 0) {
for (int i = 0; i < _numBlitRects; ++i) {
SDL_Rect *br = &_blitRects[i];
int16 dx = br->x * mul;
int16 dy = br->y * mul;
SDL_LockSurface(_sclscreen);
uint16 *dst = (uint16 *)_sclscreen->pixels + dy * _sclscreen->pitch / 2 + dx;
const uint16 *src = (uint16 *)_offscreen + (br->y + 1) * _screenW + (br->x + 1);
(*_scalers[_scaler].proc)(dst, _sclscreen->pitch, src, _screenW, br->w, br->h);
SDL_UnlockSurface(_sclscreen);
br->x *= mul;
br->y *= mul;
br->w *= mul;
br->h *= mul;
SDL_BlitSurface(_sclscreen, br, _screen, br);
}
SDL_UpdateRects(_screen, _numBlitRects, _blitRects);
} else {
SDL_LockSurface(_sclscreen);
uint16 w = _screenW;
uint16 h = _screenH - shakeOffset;
uint16 *dst = (uint16 *)_sclscreen->pixels;
const uint16 *src = (uint16 *)_offscreen + _screenW + 1;
(*_scalers[_scaler].proc)(dst, _sclscreen->pitch, src, _screenW, w, h);
SDL_UnlockSurface(_sclscreen);
SDL_Rect bsr, bdr;
bdr.x = 0;
bdr.y = 0;
bdr.w = _screenW * mul;
bdr.h = shakeOffset * mul;
SDL_FillRect(_screen, &bdr, _pal[_overscanColor]);
bsr.x = 0;
bsr.y = 0;
bsr.w = _screenW * mul;
bsr.h = (_screenH - shakeOffset) * mul;
bdr.x = 0;
bdr.y = shakeOffset * mul;
bdr.w = bsr.w;
bdr.h = bsr.h;
SDL_BlitSurface(_sclscreen, &bsr, _screen, &bdr);
bdr.x = 0;
bdr.y = 0;
bdr.w = _screenW * mul;
bdr.h = _screenH * mul;
SDL_UpdateRects(_screen, 1, &bdr);
}
_numBlitRects = 0;
}
void SystemStub_SDL::processEvents() {
SDL_Event ev;
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_QUIT:
_pi.quit = true;
break;
case SDL_JOYHATMOTION:
_pi.dirMask = 0;
if (ev.jhat.value & SDL_HAT_UP) {
_pi.dirMask |= PlayerInput::DIR_UP;
}
if (ev.jhat.value & SDL_HAT_DOWN) {
_pi.dirMask |= PlayerInput::DIR_DOWN;
}
if (ev.jhat.value & SDL_HAT_LEFT) {
_pi.dirMask |= PlayerInput::DIR_LEFT;
}
if (ev.jhat.value & SDL_HAT_RIGHT) {
_pi.dirMask |= PlayerInput::DIR_RIGHT;
}
break;
case SDL_JOYAXISMOTION:
switch (ev.jaxis.axis) {
case 0:
if (ev.jaxis.value > JOYSTICK_COMMIT_VALUE) {
_pi.dirMask |= PlayerInput::DIR_RIGHT;
if (_pi.dirMask & PlayerInput::DIR_LEFT) {
_pi.dirMask &= ~PlayerInput::DIR_LEFT;
}
} else if (ev.jaxis.value < -JOYSTICK_COMMIT_VALUE) {
_pi.dirMask |= PlayerInput::DIR_LEFT;
if (_pi.dirMask & PlayerInput::DIR_RIGHT) {
_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
}
} else {
_pi.dirMask &= ~(PlayerInput::DIR_RIGHT | PlayerInput::DIR_LEFT);
}
break;
case 1:
if (ev.jaxis.value > JOYSTICK_COMMIT_VALUE) {
_pi.dirMask |= PlayerInput::DIR_DOWN;
if (_pi.dirMask & PlayerInput::DIR_UP) {
_pi.dirMask &= ~PlayerInput::DIR_UP;
}
} else if (ev.jaxis.value < -JOYSTICK_COMMIT_VALUE) {
_pi.dirMask |= PlayerInput::DIR_UP;
if (_pi.dirMask & PlayerInput::DIR_DOWN) {
_pi.dirMask &= ~PlayerInput::DIR_DOWN;
}
} else {
_pi.dirMask = 0;
}
break;
}
break;
case SDL_JOYBUTTONDOWN:
switch (ev.jbutton.button) {
case 0:
_pi.space = true;
break;
case 1:
_pi.shift = true;
break;
case 2:
_pi.enter = true;
break;
case 3:
_pi.backspace = true;
break;
}
break;
case SDL_JOYBUTTONUP:
switch (ev.jbutton.button) {
case 0:
_pi.space = false;
break;
case 1:
_pi.shift = false;
break;
case 2:
_pi.enter = false;
break;
case 3:
_pi.backspace = false;
break;
}
break;
case SDL_KEYUP:
switch (ev.key.keysym.sym) {
case SDLK_LEFT:
_pi.dirMask &= ~PlayerInput::DIR_LEFT;
break;
case SDLK_RIGHT:
_pi.dirMask &= ~PlayerInput::DIR_RIGHT;
break;
case SDLK_UP:
_pi.dirMask &= ~PlayerInput::DIR_UP;
break;
case SDLK_DOWN:
_pi.dirMask &= ~PlayerInput::DIR_DOWN;
break;
case SDLK_SPACE:
_pi.space = false;
break;
case SDLK_RSHIFT:
case SDLK_LSHIFT:
_pi.shift = false;
break;
case SDLK_RETURN:
_pi.enter = false;
break;
case SDLK_ESCAPE:
_pi.escape = false;
break;
default:
break;
}
break;
case SDL_KEYDOWN:
if (ev.key.keysym.mod & KMOD_ALT) {
if (ev.key.keysym.sym == SDLK_RETURN) {
switchGfxMode(!_fullscreen, _scaler);
} else if (ev.key.keysym.sym == SDLK_KP_PLUS) {
uint8 s = _scaler + 1;
if (s < NUM_SCALERS) {
switchGfxMode(_fullscreen, s);
}
} else if (ev.key.keysym.sym == SDLK_KP_MINUS) {
int8 s = _scaler - 1;
if (_scaler > 0) {
switchGfxMode(_fullscreen, s);
}
}
break;
} else if (ev.key.keysym.mod & KMOD_CTRL) {
if (ev.key.keysym.sym == SDLK_f) {
_pi.dbgMask ^= PlayerInput::DF_FASTMODE;
} else if (ev.key.keysym.sym == SDLK_b) {
_pi.dbgMask ^= PlayerInput::DF_DBLOCKS;
} else if (ev.key.keysym.sym == SDLK_i) {
_pi.dbgMask ^= PlayerInput::DF_SETLIFE;
} else if (ev.key.keysym.sym == SDLK_m) {
_pi.mirrorMode = !_pi.mirrorMode;
flipGfx();
} else if (ev.key.keysym.sym == SDLK_s) {
_pi.save = true;
} else if (ev.key.keysym.sym == SDLK_l) {
_pi.load = true;
} else if (ev.key.keysym.sym == SDLK_KP_PLUS) {
_pi.stateSlot = 1;
} else if (ev.key.keysym.sym == SDLK_KP_MINUS) {
_pi.stateSlot = -1;
} else if (ev.key.keysym.sym == SDLK_r) {
_pi.inpRecord = true;
} else if (ev.key.keysym.sym == SDLK_p) {
_pi.inpReplay = true;
}
}
_pi.lastChar = ev.key.keysym.sym;
switch (ev.key.keysym.sym) {
case SDLK_LEFT:
_pi.dirMask |= PlayerInput::DIR_LEFT;
break;
case SDLK_RIGHT:
_pi.dirMask |= PlayerInput::DIR_RIGHT;
break;
case SDLK_UP:
_pi.dirMask |= PlayerInput::DIR_UP;
break;
case SDLK_DOWN:
_pi.dirMask |= PlayerInput::DIR_DOWN;
break;
case SDLK_BACKSPACE:
case SDLK_TAB:
_pi.backspace = true;
break;
case SDLK_SPACE:
_pi.space = true;
break;
case SDLK_RSHIFT:
case SDLK_LSHIFT:
_pi.shift = true;
break;
case SDLK_RETURN:
_pi.enter = true;
break;
case SDLK_ESCAPE:
_pi.escape = true;
break;
default:
break;
}
break;
default:
break;
}
}
}
void SystemStub_SDL::sleep(uint32 duration) {
SDL_Delay(duration);
}
uint32 SystemStub_SDL::getTimeStamp() {
return SDL_GetTicks();
}
void SystemStub_SDL::startAudio(AudioCallback callback, void *param) {
SDL_AudioSpec desired;
memset(&desired, 0, sizeof(desired));
desired.freq = SOUND_SAMPLE_RATE;
desired.format = AUDIO_S16;
desired.channels = 1;
desired.samples = 2048;
desired.callback = callback;
desired.userdata = param;
if (SDL_OpenAudio(&desired, NULL) == 0) {
SDL_PauseAudio(0);
} else {
error("SystemStub_SDL::startAudio() Unable to open sound device");
}
}
void SystemStub_SDL::stopAudio() {
SDL_CloseAudio();
}
uint32 SystemStub_SDL::getOutputSampleRate() {
return SOUND_SAMPLE_RATE;
}
void *SystemStub_SDL::createMutex() {
return SDL_CreateMutex();
}
void SystemStub_SDL::destroyMutex(void *mutex) {
SDL_DestroyMutex((SDL_mutex *)mutex);
}
void SystemStub_SDL::lockMutex(void *mutex) {
SDL_mutexP((SDL_mutex *)mutex);
}
void SystemStub_SDL::unlockMutex(void *mutex) {
SDL_mutexV((SDL_mutex *)mutex);
}
void SystemStub_SDL::prepareGfxMode() {
int w = _screenW * _scalers[_scaler].factor;
int h = _screenH * _scalers[_scaler].factor;
//_screen = SDL_SetVideoMode(w, h, 16, _fullscreen ? (SDL_FULLSCREEN | SDL_HWSURFACE) : SDL_HWSURFACE);
debug(DBG_INFO, "Requesting video %dx%d", w, h);
_screen = SDL_SetVideoMode(w, h, 16, SDL_SWSURFACE);
if (!_screen) {
error("SystemStub_SDL::prepareGfxMode() Unable to allocate _screen buffer");
}
const SDL_PixelFormat *pf = _screen->format;
// Android TODO: get rid of filthy scaler and draw directly to Android surface
_sclscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 16, pf->Rmask, pf->Gmask, pf->Bmask, pf->Amask);
//_sclscreen = _screen; // Android hack
if (!_sclscreen) {
error("SystemStub_SDL::prepareGfxMode() Unable to allocate _sclscreen buffer");
}
forceGfxRedraw();
}
void SystemStub_SDL::cleanupGfxMode() {
if (_offscreen) {
free(_offscreen);
_offscreen = 0;
}
if (_sclscreen) {
SDL_FreeSurface(_sclscreen);
_sclscreen = 0;
}
if (_screen) {
// freed by SDL_Quit()
_screen = 0;
}
}
void SystemStub_SDL::switchGfxMode(bool fullscreen, uint8 scaler) {
SDL_Surface *prev_sclscreen = _sclscreen;
SDL_FreeSurface(_screen);
_fullscreen = fullscreen;
_scaler = scaler;
prepareGfxMode();
SDL_BlitSurface(prev_sclscreen, NULL, _sclscreen, NULL);
SDL_FreeSurface(prev_sclscreen);
}
void SystemStub_SDL::flipGfx() {
uint16 scanline[256];
assert(_screenW <= 256);
uint16 *p = (uint16 *)_offscreen + _screenW + 1;
for (int y = 0; y < _screenH; ++y) {
p += _screenW;
for (int x = 0; x < _screenW; ++x) {
scanline[x] = *--p;
}
memcpy(p, scanline, _screenW * sizeof(uint16));
p += _screenW;
}
forceGfxRedraw();
}
void SystemStub_SDL::forceGfxRedraw() {
_numBlitRects = 1;
_blitRects[0].x = 0;
_blitRects[0].y = 0;
_blitRects[0].w = _screenW;
_blitRects[0].h = _screenH;
}
void SystemStub_SDL::drawRect(SDL_Rect *rect, uint8 color, uint16 *dst, uint16 dstPitch) {
dstPitch >>= 1;
int x1 = rect->x;
int y1 = rect->y;
int x2 = rect->x + rect->w - 1;
int y2 = rect->y + rect->h - 1;
assert(x1 >= 0 && x2 < _screenW && y1 >= 0 && y2 < _screenH);
for (int i = x1; i <= x2; ++i) {
*(dst + y1 * dstPitch + i) = *(dst + y2 * dstPitch + i) = _pal[color];
}
for (int j = y1; j <= y2; ++j) {
*(dst + j * dstPitch + x1) = *(dst + j * dstPitch + x2) = _pal[color];
}
}

View File

@@ -1,103 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "unpack.h"
static int rcr(UnpackCtx *uc, int CF) {
int rCF = (uc->chk & 1);
uc->chk >>= 1;
if (CF) {
uc->chk |= 0x80000000;
}
return rCF;
}
static int next_chunk(UnpackCtx *uc) {
int CF = rcr(uc, 0);
if (uc->chk == 0) {
uc->chk = READ_BE_UINT32(uc->src); uc->src -= 4;
uc->crc ^= uc->chk;
CF = rcr(uc, 1);
}
return CF;
}
static uint16 get_code(UnpackCtx *uc, uint8 num_chunks) {
uint16 c = 0;
while (num_chunks--) {
c <<= 1;
if (next_chunk(uc)) {
c |= 1;
}
}
return c;
}
static void dec_unk1(UnpackCtx *uc, uint8 num_chunks, uint8 add_count) {
uint16 count = get_code(uc, num_chunks) + add_count + 1;
uc->datasize -= count;
while (count--) {
*uc->dst = (uint8)get_code(uc, 8);
--uc->dst;
}
}
static void dec_unk2(UnpackCtx *uc, uint8 num_chunks) {
uint16 i = get_code(uc, num_chunks);
uint16 count = uc->size + 1;
uc->datasize -= count;
while (count--) {
*uc->dst = *(uc->dst + i);
--uc->dst;
}
}
bool delphine_unpack(uint8 *dst, const uint8 *src, int len) {
UnpackCtx uc;
uc.src = src + len - 4;
uc.datasize = READ_BE_UINT32(uc.src); uc.src -= 4;
uc.dst = dst + uc.datasize - 1;
uc.size = 0;
uc.crc = READ_BE_UINT32(uc.src); uc.src -= 4;
uc.chk = READ_BE_UINT32(uc.src); uc.src -= 4;
debug(DBG_UNPACK, "delphine_unpack() crc=0x%X datasize=0x%X", uc.crc, uc.datasize);
uc.crc ^= uc.chk;
do {
if (!next_chunk(&uc)) {
uc.size = 1;
if (!next_chunk(&uc)) {
dec_unk1(&uc, 3, 0);
} else {
dec_unk2(&uc, 8);
}
} else {
uint16 c = get_code(&uc, 2);
if (c == 3) {
dec_unk1(&uc, 8, 8);
} else if (c < 2) {
uc.size = c + 2;
dec_unk2(&uc, c + 9);
} else {
uc.size = get_code(&uc, 8);
dec_unk2(&uc, 12);
}
}
} while (uc.datasize > 0);
return uc.crc == 0;
}

View File

@@ -1,36 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __UNPACK_H__
#define __UNPACK_H__
#include "intern.h"
struct UnpackCtx {
int size, datasize;
uint32 crc;
uint32 chk;
uint8 *dst;
const uint8 *src;
};
extern bool delphine_unpack(uint8 *dst, const uint8 *src, int len);
#endif // __UNPACK_H__

View File

@@ -1,74 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <cstdarg>
#include "util.h"
#include <android/log.h>
uint16 g_debugMask;
void debug(uint16 cm, const char *msg, ...) {
char buf[1024];
if (cm & g_debugMask) {
va_list va;
va_start(va, msg);
vsprintf(buf, msg, va);
va_end(va);
printf("%s\n", buf);
fflush(stdout);
__android_log_print(ANDROID_LOG_INFO, "REminiscence", "%s", buf);
}
}
void error(const char *msg, ...) {
char buf[1024];
va_list va;
va_start(va, msg);
vsprintf(buf, msg, va);
va_end(va);
fprintf(stderr, "ERROR: %s!\n", buf);
__android_log_print(ANDROID_LOG_INFO, "REminiscence", "ERROR: %s", buf);
exit(-1);
}
void warning(const char *msg, ...) {
char buf[1024];
va_list va;
va_start(va, msg);
vsprintf(buf, msg, va);
va_end(va);
fprintf(stderr, "WARNING: %s!\n", buf);
__android_log_print(ANDROID_LOG_INFO, "REminiscence", "WARNING: %s", buf);
}
void string_lower(char *p) {
for (; *p; ++p) {
if (*p >= 'A' && *p <= 'Z') {
*p += 'a' - 'A';
}
}
}
void string_upper(char *p) {
for (; *p; ++p) {
if (*p >= 'a' && *p <= 'z') {
*p += 'A' - 'a';
}
}
}

View File

@@ -1,48 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __UTIL_H__
#define __UTIL_H__
#include "intern.h"
enum {
DBG_INFO = 1 << 0,
DBG_RES = 1 << 1,
DBG_MENU = 1 << 2,
DBG_UNPACK = 1 << 3,
DBG_PGE = 1 << 4,
DBG_VIDEO = 1 << 5,
DBG_GAME = 1 << 6,
DBG_COL = 1 << 7,
DBG_SND = 1 << 8,
DBG_CUT = 1 << 9,
DBG_MOD = 1 << 10,
DBG_SFX = 1 << 11
};
extern uint16 g_debugMask;
extern void debug(uint16 cm, const char *msg, ...);
extern void error(const char *msg, ...);
extern void warning(const char *msg, ...);
extern void string_lower(char *p);
extern void string_upper(char *p);
#endif // __UTIL_H__

View File

@@ -1,411 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "resource.h"
#include "systemstub.h"
#include "video.h"
Video::Video(Resource *res, SystemStub *stub)
: _res(res), _stub(stub) {
_frontLayer = (uint8 *)malloc(GAMESCREEN_W * GAMESCREEN_H);
memset(_frontLayer, 0, GAMESCREEN_W * GAMESCREEN_H);
_backLayer = (uint8 *)malloc(GAMESCREEN_W * GAMESCREEN_H);
memset(_backLayer, 0, GAMESCREEN_W * GAMESCREEN_H);
_tempLayer = (uint8 *)malloc(GAMESCREEN_W * GAMESCREEN_H);
memset(_tempLayer, 0, GAMESCREEN_W * GAMESCREEN_H);
_tempLayer2 = (uint8 *)malloc(GAMESCREEN_W * GAMESCREEN_H);
memset(_tempLayer2, 0, GAMESCREEN_W * GAMESCREEN_H);
_screenBlocks = (uint8 *)malloc((GAMESCREEN_W / SCREENBLOCK_W) * (GAMESCREEN_H / SCREENBLOCK_H));
memset(_screenBlocks, 0, (GAMESCREEN_W / SCREENBLOCK_W) * (GAMESCREEN_H / SCREENBLOCK_H));
_fullRefresh = true;
_shakeOffset = 0;
_charFrontColor = 0;
_charTransparentColor = 0;
_charShadowColor = 0;
}
Video::~Video() {
free(_frontLayer);
free(_backLayer);
free(_tempLayer);
free(_tempLayer2);
free(_screenBlocks);
}
void Video::markBlockAsDirty(int16 x, int16 y, uint16 w, uint16 h) {
debug(DBG_VIDEO, "Video::markBlockAsDirty(%d, %d, %d, %d)", x, y, w, h);
assert(x >= 0 && x + w <= GAMESCREEN_W && y >= 0 && y + h <= GAMESCREEN_H);
int bx1 = x / SCREENBLOCK_W;
int by1 = y / SCREENBLOCK_H;
int bx2 = (x + w - 1) / SCREENBLOCK_W;
int by2 = (y + h - 1) / SCREENBLOCK_H;
assert(bx2 < GAMESCREEN_W / SCREENBLOCK_W && by2 < GAMESCREEN_H / SCREENBLOCK_H);
for (; by1 <= by2; ++by1) {
for (int i = bx1; i <= bx2; ++i) {
_screenBlocks[by1 * (GAMESCREEN_W / SCREENBLOCK_W) + i] = 2;
}
}
}
void Video::updateScreen() {
debug(DBG_VIDEO, "Video::updateScreen()");
// _fullRefresh = true;
if (_fullRefresh) {
_stub->copyRect(0, 0, Video::GAMESCREEN_W, Video::GAMESCREEN_H, _frontLayer, 256);
_stub->updateScreen(_shakeOffset);
_fullRefresh = false;
} else {
int i, j;
int count = 0;
uint8 *p = _screenBlocks;
for (j = 0; j < GAMESCREEN_H / SCREENBLOCK_H; ++j) {
uint16 nh = 0;
for (i = 0; i < GAMESCREEN_W / SCREENBLOCK_W; ++i) {
if (p[i] != 0) {
--p[i];
++nh;
} else if (nh != 0) {
int16 x = (i - nh) * SCREENBLOCK_W;
_stub->copyRect(x, j * SCREENBLOCK_H, nh * SCREENBLOCK_W, SCREENBLOCK_H, _frontLayer, 256);
nh = 0;
++count;
}
}
if (nh != 0) {
int16 x = (i - nh) * SCREENBLOCK_W;
_stub->copyRect(x, j * SCREENBLOCK_H, nh * SCREENBLOCK_W, SCREENBLOCK_H, _frontLayer, 256);
++count;
}
p += GAMESCREEN_W / SCREENBLOCK_W;
}
if (count != 0) {
_stub->updateScreen(_shakeOffset);
}
}
if (_shakeOffset != 0) {
_shakeOffset = 0;
_fullRefresh = true;
}
}
void Video::fullRefresh() {
debug(DBG_VIDEO, "Video::fullRefresh()");
_fullRefresh = true;
memset(_screenBlocks, 0, (GAMESCREEN_W / SCREENBLOCK_W) * (GAMESCREEN_H / SCREENBLOCK_H));
}
void Video::fadeOut() {
debug(DBG_VIDEO, "Video::fadeOut()");
for (int step = 16; step >= 0; --step) {
for (int c = 0; c < 256; ++c) {
Color col;
_stub->getPaletteEntry(c, &col);
col.r = col.r * step >> 4;
col.g = col.g * step >> 4;
col.b = col.b * step >> 4;
_stub->setPaletteEntry(c, &col);
}
fullRefresh();
updateScreen();
_stub->sleep(50);
}
}
void Video::setPaletteSlotBE(int palSlot, int palNum) {
debug(DBG_VIDEO, "Video::setPaletteSlotBE()");
const uint8 *p = _res->_pal + palNum * 0x20;
for (int i = 0; i < 16; ++i) {
uint16 color = READ_BE_UINT16(p); p += 2;
uint8 t = (color == 0) ? 0 : 3;
Color c;
c.r = ((color & 0x00F) << 2) | t;
c.g = ((color & 0x0F0) >> 2) | t;
c.b = ((color & 0xF00) >> 6) | t;
_stub->setPaletteEntry(palSlot * 0x10 + i, &c);
}
}
void Video::setPaletteSlotLE(int palSlot, const uint8 *palData) {
debug(DBG_VIDEO, "Video::setPaletteSlotLE()");
for (int i = 0; i < 16; ++i) {
uint16 color = READ_LE_UINT16(palData); palData += 2;
Color c;
c.b = (color & 0x00F) << 2;
c.g = (color & 0x0F0) >> 2;
c.r = (color & 0xF00) >> 6;
_stub->setPaletteEntry(palSlot * 0x10 + i, &c);
}
}
void Video::setTextPalette() {
debug(DBG_VIDEO, "Video::setTextPalette()");
const uint8 *p = _textPal;
for (int i = 0; i < 16; ++i) {
uint16 color = READ_LE_UINT16(p); p += 2;
Color c;
c.b = (color & 0x00F) << 2;
c.g = (color & 0x0F0) >> 2;
c.r = (color & 0xF00) >> 6;
_stub->setPaletteEntry(0xE0 + i, &c);
}
}
void Video::setPalette0xF() {
debug(DBG_VIDEO, "Video::setPalette0xF()");
const uint8 *p = _palSlot0xF;
for (int i = 0; i < 16; ++i) {
Color c;
c.r = *p++ >> 2;
c.g = *p++ >> 2;
c.b = *p++ >> 2;
_stub->setPaletteEntry(0xF0 + i, &c);
}
}
void Video::copyLevelMap(uint16 room) {
debug(DBG_VIDEO, "Video::copyLevelMap(%d)", room);
assert(room < 0x40);
int32 off = READ_LE_UINT32(_res->_map + room * 6);
if (off == 0) {
error("Invalid room %d", room);
}
bool packed = true;
if (off < 0) {
off = -off;
packed = false;
}
const uint8 *p = _res->_map + off;
_mapPalSlot1 = *p++;
_mapPalSlot2 = *p++;
_mapPalSlot3 = *p++;
_mapPalSlot4 = *p++;
if (packed) {
uint8 *vid = _frontLayer;
for (int i = 0; i < 4; ++i) {
uint16 sz = READ_LE_UINT16(p); p += 2;
decodeLevelMap(sz, p, _res->_memBuf); p += sz;
memcpy(vid, _res->_memBuf, 256 * 56);
vid += 256 * 56;
}
} else {
for (int i = 0; i < 4; ++i) {
for (int y = 0; y < 224; ++y) {
for (int x = 0; x < 64; ++x) {
_frontLayer[i + x * 4 + 256 * y] = p[256 * 56 * i + x + 64 * y];
}
}
}
}
memcpy(_backLayer, _frontLayer, Video::GAMESCREEN_W * Video::GAMESCREEN_H);
}
void Video::decodeLevelMap(uint16 sz, const uint8 *src, uint8 *dst) {
debug(DBG_VIDEO, "Video::decodeLevelMap() sz = 0x%X", sz);
const uint8 *end = src + sz;
while (src < end) {
int16 code = (int8)*src++;
if (code < 0) {
int len = 1 - code;
memset(dst, *src++, len);
dst += len;
} else {
++code;
memcpy(dst, src, code);
src += code;
dst += code;
}
}
}
void Video::setLevelPalettes() {
debug(DBG_VIDEO, "Video::setLevelPalettes()");
if (_unkPalSlot2 == 0) {
_unkPalSlot2 = _mapPalSlot3;
}
if (_unkPalSlot1 == 0) {
_unkPalSlot1 = _mapPalSlot3;
}
setPaletteSlotBE(0x0, _mapPalSlot1);
setPaletteSlotBE(0x1, _mapPalSlot2);
setPaletteSlotBE(0x2, _mapPalSlot3);
setPaletteSlotBE(0x3, _mapPalSlot4);
if (_unkPalSlot1 == _mapPalSlot3) {
setPaletteSlotLE(4, _conradPal1);
} else {
setPaletteSlotLE(4, _conradPal2);
}
// slot 5 is monster palette
setPaletteSlotBE(0x8, _mapPalSlot1);
setPaletteSlotBE(0x9, _mapPalSlot2);
setPaletteSlotBE(0xA, _unkPalSlot2);
setPaletteSlotBE(0xB, _mapPalSlot4);
// slots 0xC and 0xD are cutscene palettes
setTextPalette();
}
void Video::drawSpriteSub1(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask) {
debug(DBG_VIDEO, "Video::drawSpriteSub1(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
while (h--) {
for (int i = 0; i < w; ++i) {
if (src[i] != 0) {
dst[i] = src[i] | colMask;
}
}
src += pitch;
dst += 256;
}
}
void Video::drawSpriteSub2(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask) {
debug(DBG_VIDEO, "Video::drawSpriteSub2(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
while (h--) {
for (int i = 0; i < w; ++i) {
if (src[-i] != 0) {
dst[i] = src[-i] | colMask;
}
}
src += pitch;
dst += 256;
}
}
void Video::drawSpriteSub3(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask) {
debug(DBG_VIDEO, "Video::drawSpriteSub3(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
while (h--) {
for (int i = 0; i < w; ++i) {
if (src[i] != 0 && !(dst[i] & 0x80)) {
dst[i] = src[i] | colMask;
}
}
src += pitch;
dst += 256;
}
}
void Video::drawSpriteSub4(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask) {
debug(DBG_VIDEO, "Video::drawSpriteSub4(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
while (h--) {
for (int i = 0; i < w; ++i) {
if (src[-i] != 0 && !(dst[i] & 0x80)) {
dst[i] = src[-i] | colMask;
}
}
src += pitch;
dst += 256;
}
}
void Video::drawSpriteSub5(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask) {
debug(DBG_VIDEO, "Video::drawSpriteSub5(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
while (h--) {
for (int i = 0; i < w; ++i) {
if (src[i * pitch] != 0 && !(dst[i] & 0x80)) {
dst[i] = src[i * pitch] | colMask;
}
}
++src;
dst += 256;
}
}
void Video::drawSpriteSub6(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask) {
debug(DBG_VIDEO, "Video::drawSpriteSub6(0x%X, 0x%X, 0x%X, 0x%X)", pitch, w, h, colMask);
while (h--) {
for (int i = 0; i < w; ++i) {
if (src[-i * pitch] != 0 && !(dst[i] & 0x80)) {
dst[i] = src[-i * pitch] | colMask;
}
}
++src;
dst += 256;
}
}
void Video::drawChar(uint8 c, int16 y, int16 x) {
debug(DBG_VIDEO, "Video::drawChar(0x%X, %d, %d)", c, y, x);
y *= 8;
x *= 8;
const uint8 *src = _res->_fnt + (c - 32) * 32;
uint8 *dst = _frontLayer + x + 256 * y;
for (int h = 0; h < 8; ++h) {
for (int i = 0; i < 4; ++i) {
uint8 c1 = (*src & 0xF0) >> 4;
uint8 c2 = (*src & 0x0F) >> 0;
++src;
if (c1 != 0) {
if (c1 != 2) {
*dst = _charFrontColor;
} else {
*dst = _charShadowColor;
}
} else if (_charTransparentColor != 0xFF) {
*dst = _charTransparentColor;
}
++dst;
if (c2 != 0) {
if (c2 != 2) {
*dst = _charFrontColor;
} else {
*dst = _charShadowColor;
}
} else if (_charTransparentColor != 0xFF) {
*dst = _charTransparentColor;
}
++dst;
}
dst += 256 - 8;
}
}
const char *Video::drawString(const char *str, int16 x, int16 y, uint8 col) {
debug(DBG_VIDEO, "Video::drawString('%s', %d, %d, 0x%X)", str, x, y, col);
int len = 0;
int offset = y * 256 + x;
uint8 *dst = _frontLayer + offset;
while (1) {
uint8 c = *str++;
if (c == 0 || c == 0xB || c == 0xA) {
break;
}
uint8 *dst_char = dst;
const uint8 *src = _res->_fnt + (c - 32) * 32;
for (int h = 0; h < 8; ++h) {
for (int w = 0; w < 4; ++w) {
uint8 c1 = (*src & 0xF0) >> 4;
uint8 c2 = (*src & 0x0F) >> 0;
++src;
if (c1 != 0) {
*dst_char = (c1 == 0xF) ? col : (0xE0 + c1);
}
++dst_char;
if (c2 != 0) {
*dst_char = (c2 == 0xF) ? col : (0xE0 + c2);
}
++dst_char;
}
dst_char += 256 - 8;
}
dst += 8; // character width
++len;
}
markBlockAsDirty(x, y, len * 8, 8);
return str - 1;
}

View File

@@ -1,82 +0,0 @@
/* REminiscence - Flashback interpreter
* Copyright (C) 2005-2007 Gregory Montoir
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __VIDEO_H__
#define __VIDEO_H__
#include "intern.h"
struct Resource;
struct SystemStub;
struct Video {
enum {
GAMESCREEN_W = 256,
GAMESCREEN_H = 224,
SCREENBLOCK_W = 8,
SCREENBLOCK_H = 8,
CHAR_W = 8,
CHAR_H = 8
};
static const uint8 _conradPal1[];
static const uint8 _conradPal2[];
static const uint8 _textPal[];
static const uint8 _palSlot0xF[];
Resource *_res;
SystemStub *_stub;
uint8 *_frontLayer;
uint8 *_backLayer;
uint8 *_tempLayer;
uint8 *_tempLayer2;
uint8 _unkPalSlot1, _unkPalSlot2;
uint8 _mapPalSlot1, _mapPalSlot2, _mapPalSlot3, _mapPalSlot4;
uint8 _charFrontColor;
uint8 _charTransparentColor;
uint8 _charShadowColor;
uint8 *_screenBlocks;
bool _fullRefresh;
uint8 _shakeOffset;
Video(Resource *res, SystemStub *stub);
~Video();
void markBlockAsDirty(int16 x, int16 y, uint16 w, uint16 h);
void updateScreen();
void fullRefresh();
void fadeOut();
void setPaletteSlotBE(int palSlot, int palNum);
void setPaletteSlotLE(int palSlot, const uint8 *palData);
void setTextPalette();
void setPalette0xF();
void copyLevelMap(uint16 room);
void decodeLevelMap(uint16 sz, const uint8 *src, uint8 *dst);
void setLevelPalettes();
void drawSpriteSub1(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask);
void drawSpriteSub2(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask);
void drawSpriteSub3(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask);
void drawSpriteSub4(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask);
void drawSpriteSub5(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask);
void drawSpriteSub6(const uint8 *src, uint8 *dst, int pitch, int h, int w, uint8 colMask);
void drawChar(uint8 c, int16 y, int16 x);
const char *drawString(const char *str, int16 x, int16 y, uint8 col);
};
#endif // __VIDEO_H__

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1,259 +0,0 @@
# The application settings for Android libSDL port
# Specify application name (e.x. My Application)
AppName="Alien Blaster"
# Specify reversed site name of application (e.x. com.mysite.myapp)
AppFullName=de.schwardtnet.alienblaster
# Application version code (integer)
AppVersionCode=110014
# Application user-visible version name (string)
AppVersionName="1.1.0.14"
# Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...'
# If you'll start Description with '!' symbol it will be enabled by default, other downloads should be selected by user from startup config menu
# If the URL in in the form ':dir/file.dat:http://URL/' it will be downloaded as binary BLOB to the application dir and not unzipped
# If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir -
# these files are put inside .apk package by build system
# Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS
AppDataDownloadUrl="!Game data|alienblaster110_data1.zip^!Game data|alienblaster110_data2.zip^!Game data|alienblaster110_data3.zip"
# Reset SDL config when updating application to the new version (y) / (n)
ResetSdlConfigForThisVersion=n
# Delete application data files when upgrading (specify file/dir paths separated by spaces)
DeleteFilesOnUpgrade="%"
# Here you may type readme text, which will be shown during startup. Format is:
# Text in English, use \\\\n to separate lines (that's four backslashes)^de:Text in Deutsch^ru:Text in Russian^button:Button that will open some URL:http://url-to-open/
ReadmeText='^You can press "Home" now - the data will be downloaded in background^In game press "Menu" for secondary fire, "Volume Up/Down" to cycle weapons'
# libSDL version to use (1.2/1.3/2.0)
LibSdlVersion=1.3
# Specify screen orientation: (v)ertical/(p)ortrait or (h)orizontal/(l)andscape
ScreenOrientation=h
# Video color depth - 16 BPP is the fastest and supported for all modes, 24 bpp is supported only
# with SwVideoMode=y, SDL_OPENGL mode supports everything. (16)/(24)/(32)
VideoDepthBpp=16
# Enable OpenGL depth buffer (needed only for 3-d applications, small speed decrease) (y) or (n)
NeedDepthBuffer=n
# Enable OpenGL stencil buffer (needed only for 3-d applications, small speed decrease) (y) or (n)
NeedStencilBuffer=n
# Try to use GLES 2.x context - will revert to GLES 1.X if unsupported by device
# you need this option only if you're developing 3-d app (y) or (n)
NeedGles2=n
# Application uses software video buffer - you're calling SDL_SetVideoMode() without SDL_HWSURFACE and without SDL_OPENGL,
# this will allow small speed optimization. Enable this even when you're using SDL_HWSURFACE. (y) or (n)
SwVideoMode=n
# Application video output will be resized to fit into native device screen (y)/(n)
SdlVideoResize=y
# Application resizing will keep 4:3 aspect ratio, with black bars at sides (y)/(n)
SdlVideoResizeKeepAspect=n
# Do not allow device to sleep when the application is in foreground, set this for video players or apps which use accelerometer
InhibitSuspend=n
# Create Android service, so the app is less likely to be killed while in background
CreateService=
# Application does not call SDL_Flip() or SDL_UpdateRects() appropriately, or draws from non-main thread -
# enabling the compatibility mode will force screen update every 100 milliseconds, which is laggy and inefficient (y) or (n)
CompatibilityHacksForceScreenUpdate=
# Application does not call SDL_Flip() or SDL_UpdateRects() after mouse click (ScummVM and all Amiga emulators do that) -
# force screen update by moving mouse cursor a little after each click (y) or (n)
CompatibilityHacksForceScreenUpdateMouseClick=y
# Application initializes SDL audio/video inside static constructors (which is bad, you won't be able to run ndk-gdb) (y)/(n)
CompatibilityHacksStaticInit=n
# On-screen Android soft text input emulates hardware keyboard, this will only work with Hackers Keyboard app (y)/(n)
CompatibilityHacksTextInputEmulatesHwKeyboard=n
# Hack for broken devices: prevent audio chopping, by sleeping a bit after pushing each audio chunk (y)/(n)
CompatibilityHacksPreventAudioChopping=
# Hack for broken apps: application ignores audio buffer size returned by SDL (y)/(n)
CompatibilityHacksAppIgnoresAudioBufferSize=
# Hack for VCMI: preload additional shared libraries before aplication start
CompatibilityHacksAdditionalPreloadedSharedLibraries=""
# Hack for Free Heroes 2, which redraws the screen inside SDL_PumpEvents(): slow and compatible SDL event queue -
# do not use it with accelerometer/gyroscope, or your app may freeze at random (y)/(n)
CompatibilityHacksSlowCompatibleEventQueue=
# Save and restore OpenGL state when drawing on-screen keyboard for apps that use SDL_OPENGL
CompatibilityHacksTouchscreenKeyboardSaveRestoreOpenGLState=
# Application uses SDL_UpdateRects() properly, and does not draw in any region outside those rects.
# This improves drawing speed, but I know only one application that does that, and it's written by me (y)/(n)
CompatibilityHacksProperUsageOfSDL_UpdateRects=
# Application uses mouse (y) or (n), this will show mouse emulation dialog to the user
AppUsesMouse=n
# Application needs two-button mouse, will also enable advanced point-and-click features (y) or (n)
AppNeedsTwoButtonMouse=n
# Right mouse button can do long-press/drag&drop action, necessary for some games (y) or (n)
# If you disable it, swiping with two fingers will send mouse wheel events
RightMouseButtonLongPress=
# Show SDL mouse cursor, for applications that do not draw cursor at all (y) or (n)
ShowMouseCursor=n
# Generate more touch events, by default SDL generates one event per one video frame, this is useful for drawing apps (y) or (n)
GenerateSubframeTouchEvents=
# Force relative (laptop) mouse movement mode, useful when both on-screen keyboard and mouse are needed (y) or (n)
ForceRelativeMouseMode=n
# Show on-screen dpad/joystick, that will act as arrow keys (y) or (n)
AppNeedsArrowKeys=y
# On-screen dpad/joystick will appear under finger when it touches the screen (y) or (n)
# Joystick always follows finger, so moving mouse requires touching the screen with other finger
FloatingScreenJoystick=y
# Application needs text input (y) or (n), enables button for text input on screen
AppNeedsTextInput=y
# Application uses joystick (y) or (n), the on-screen DPAD will be used as joystick 0 axes 0-1
# This will disable AppNeedsArrowKeys option
AppUsesJoystick=n
# Application uses second on-screen joystick, as SDL joystick 0 axes 2-3 (y)/(n)
AppUsesSecondJoystick=n
# Application uses third on-screen joystick, as SDL joystick 0 axes 20-21 (y)/(n)
AppUsesThirdJoystick=
# Application uses accelerometer (y) or (n), the accelerometer will be used as joystick 1 axes 0-1 and 5-7
AppUsesAccelerometer=
# Application uses gyroscope (y) or (n), the gyroscope will be used as joystick 1 axes 2-4
AppUsesGyroscope=
# Use gyroscope to move mouse cursor (y) or (n), it eats battery, and can be disabled in settings, do not use with AppUsesGyroscope setting
MoveMouseWithGyroscope=
# Application uses multitouch (y) or (n), multitouch events are passed as SDL_JOYBALLMOTION events for the joystick 0
AppUsesMultitouch=n
# Application records audio (it will use any available source, such a s microphone)
# API is defined in file SDL_android.h: int SDL_ANDROID_OpenAudioRecording(SDL_AudioSpec *spec); void SDL_ANDROID_CloseAudioRecording(void);
# This option will add additional permission to Android manifest (y)/(n)
AppRecordsAudio=
# Application needs to access SD card. If your data files are bigger than 5 Mb, enable it. (y) / (n)
AccessSdCard=
# Application needs Internet access. If you disable it, you'll have to bundle all your data files inside .apk (y) / (n)
AccessInternet=
# Immersive mode - Android will hide on-screen Home/Back keys. Looks bad if you invoke Android keyboard. (y) / (n)
ImmersiveMode=
# Application implements Android-specific routines to put to background, and will not draw anything to screen
# between SDL_ACTIVEEVENT lost / gained notifications - you should check for them
# rigth after SDL_Flip(), if (n) then SDL_Flip() will block till app in background (y) or (n)
# This option is reported to be buggy, sometimes failing to restore video state
NonBlockingSwapBuffers=n
# Redefine common hardware keys to SDL keysyms
# BACK hardware key is available on all devices, MENU is available on pre-ICS devices, other keys may be absent
# SEARCH and CALL by default return same keycode as DPAD_CENTER - one of those keys is available on most devices
# Use word NO_REMAP if you want to preserve native functionality for certain key (volume keys are 3-rd and 4-th)
# Keys: TOUCHSCREEN (works only when AppUsesMouse=n), DPAD_CENTER/SEARCH, VOLUMEUP, VOLUMEDOWN, MENU, BACK, CAMERA
RedefinedKeys="RETURN LCTRL NO_REMAP NO_REMAP LCTRL"
# Number of virtual keyboard keys (currently 6 is maximum)
AppTouchscreenKeyboardKeysAmount=4
# Redefine on-screen keyboard keys to SDL keysyms - 6 keyboard keys + 4 multitouch gestures (zoom in/out and rotate left/right)
RedefinedKeysScreenKb="RETURN LCTRL PAGEUP PAGEDOWN LCTRL"
# Names for on-screen keyboard keys, such as Fire, Jump, Run etc, separated by spaces, they are used in SDL config menu
RedefinedKeysScreenKbNames=""
# On-screen keys theme
# 0 = Ultimate Droid by Sean Stieber (green, with gamepad joystick)
# 1 = Simple Theme by Beholder (white, with gamepad joystick)
# 2 = Sun by Sirea (yellow, with round joystick)
# 3 = Keen by Gerstrong (multicolor, with round joystick)
TouchscreenKeysTheme=2
# Redefine gamepad keys to SDL keysyms, button order is:
# A B X Y L1 R1 L2 R2 LThumb RThumb
RedefinedKeysGamepad=""
# How long to show startup menu button, in msec, 0 to disable startup menu
StartupMenuButtonTimeout=3000
# Menu items to hide from startup menu, available menu items:
# SettingsMenu.OkButton SettingsMenu.DummyMenu SettingsMenu.MainMenu SettingsMenuMisc.DownloadConfig SettingsMenuMisc.OptionalDownloadConfig SettingsMenuMisc.AudioConfig SettingsMenuMisc.VideoSettingsConfig SettingsMenuMisc.ShowReadme SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.ResetToDefaultsConfig SettingsMenuMouse.MouseConfigMainMenu SettingsMenuMouse.DisplaySizeConfig SettingsMenuMouse.LeftClickConfig SettingsMenuMouse.RightClickConfig SettingsMenuMouse.AdditionalMouseConfig SettingsMenuMouse.JoystickMouseConfig SettingsMenuMouse.TouchPressureMeasurementTool SettingsMenuMouse.CalibrateTouchscreenMenu SettingsMenuKeyboard.KeyboardConfigMainMenu SettingsMenuKeyboard.ScreenKeyboardSizeConfig SettingsMenuKeyboard.ScreenKeyboardDrawSizeConfig SettingsMenuKeyboard.ScreenKeyboardThemeConfig SettingsMenuKeyboard.ScreenKeyboardTransparencyConfig SettingsMenuKeyboard.RemapHwKeysConfig SettingsMenuKeyboard.RemapScreenKbConfig SettingsMenuKeyboard.ScreenGesturesConfig SettingsMenuKeyboard.CustomizeScreenKbLayout
HiddenMenuOptions='OptionalDownloadConfig'
# Menu items to show at startup - this is Java code snippet, leave empty for default
# new SettingsMenuMisc.ShowReadme(), (AppUsesMouse \&\& \! ForceRelativeMouseMode \? new SettingsMenuMouse.DisplaySizeConfig(true) : new SettingsMenu.DummyMenu()), new SettingsMenuMisc.OptionalDownloadConfig(true), new SettingsMenuMisc.GyroscopeCalibration()
# Available menu items:
# SettingsMenu.OkButton SettingsMenu.DummyMenu SettingsMenu.MainMenu SettingsMenuMisc.DownloadConfig SettingsMenuMisc.OptionalDownloadConfig SettingsMenuMisc.AudioConfig SettingsMenuMisc.VideoSettingsConfig SettingsMenuMisc.ShowReadme SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.ResetToDefaultsConfig SettingsMenuMouse.MouseConfigMainMenu SettingsMenuMouse.DisplaySizeConfig SettingsMenuMouse.LeftClickConfig SettingsMenuMouse.RightClickConfig SettingsMenuMouse.AdditionalMouseConfig SettingsMenuMouse.JoystickMouseConfig SettingsMenuMouse.TouchPressureMeasurementTool SettingsMenuMouse.CalibrateTouchscreenMenu SettingsMenuKeyboard.KeyboardConfigMainMenu SettingsMenuKeyboard.ScreenKeyboardSizeConfig SettingsMenuKeyboard.ScreenKeyboardDrawSizeConfig SettingsMenuKeyboard.ScreenKeyboardThemeConfig SettingsMenuKeyboard.ScreenKeyboardTransparencyConfig SettingsMenuKeyboard.RemapHwKeysConfig SettingsMenuKeyboard.RemapScreenKbConfig SettingsMenuKeyboard.ScreenGesturesConfig SettingsMenuKeyboard.CustomizeScreenKbLayout
FirstStartMenuOptions=''
# Specify architectures to compile, 'all' or 'y' to compile for all architectures.
# Available architectures: armeabi armeabi-v7a armeabi-v7a-hard x86 mips
MultiABI='n'
# Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower
AppMinimumRAM=
# Optional shared libraries to compile - removing some of them will save space
# MP3 support by libMAD is encumbered by patents and libMAD is GPL-ed
# Available libraries: mad (GPL-ed!) sdl_mixer sdl_image sdl_ttf sdl_net sdl_blitpool sdl_gfx sdl_sound intl xml2 lua jpeg png ogg flac tremor vorbis freetype xerces curl theora fluidsynth lzma lzo2 mikmod openal timidity zzip bzip2 yaml-cpp python boost_date_time boost_filesystem boost_iostreams boost_program_options boost_regex boost_signals boost_system boost_thread glu avcodec avdevice avfilter avformat avresample avutil swscale swresample bzip2
CompiledLibraries="sdl_mixer sdl_image"
# Application uses custom build script AndroidBuild.sh instead of Android.mk (y) or (n)
CustomBuildScript=n
# Aditional CFLAGS for application
AppCflags='-O3'
# Additional LDFLAGS for application
AppLdflags=''
# If application has headers with the same name as system headers, this option tries to fix compiler flags to make it compilable
AppOverlapsSystemHeaders=
# Build only following subdirs (empty will build all dirs, ignored with custom script)
AppSubdirsBuild=''
# Exclude these files from build
AppBuildExclude=''
# Application command line parameters, including app name as 0-th param
AppCmdline=''
# Screen size is used by Google Play to prevent an app to be installed on devices with smaller screens
# Minimum screen size that application supports: (s)mall / (m)edium / (l)arge
MinimumScreenSize=
# Your AdMob Publisher ID, (n) if you don't want advertisements
AdmobPublisherId=
# Your AdMob test device ID, to receive a test ad
AdmobTestDeviceId=
# Your AdMob banner size (BANNER/FULL_BANNER/LEADERBOARD/MEDIUM_RECTANGLE/SMART_BANNER/WIDE_SKYSCRAPER/FULL_WIDTH:Height/Width:AUTO_HEIGHT/Width:Height)
AdmobBannerSize=

View File

@@ -1,66 +0,0 @@
# game name
GAME_NAME=alienBlaster
# the compiler to use
COMPILER=g++
# include path
INCLUDE_PATH=-I.
#OPTIMIZATION=-g -pg -fprofile-arcs
#OPTIMIZATION=-O3
OPTIMIZATION=-g
#OPTIMIZATION=
# SDL library
SDL_LIBS=$(shell sdl-config --libs)
SDL_FLAGS=$(shell sdl-config --cflags)
# game flags
GAME_FLAGS=-D_GNU_SOURCE -Wall -Winline -finline-functions $(SDL_FLAGS) $(OPTIMIZATION)
GAME_LIBS=-lSDL_mixer $(SDL_LIBS) $(OPTIMIZATION)
# all objectfiles
OBJECT_FILES=main.o surfaceDB.o soundDB.o options.o geometry.o video.o game.o \
racer.o racers.o shots.o shot.o boundingBox.o items.o item.o font.o \
explosion.o explosions.o mixer.o enemys.o enemy.o wrecks.o wreck.o \
settings.o intro.o setDifficulty.o global.o formation.o infoscreen.o \
menuArcadeMode.o sonic.o banners.o banner.o smokePuff.o smokePuffs.o \
shieldGlow.o background.o input.o
.PHONY: all game clean realclean rebuild tgz
all: depend $(GAME_NAME)
clean:
rm -f *.o *.da
realclean:
rm -f *.o *.da *~ Makefile.dep
rebuild: realclean game
.SUFFIXES: .cpp
# How to compile a c++ programm
$(GAME_NAME): $(OBJECT_FILES)
@echo ""
@echo ""
@echo "Linking $@"
@$(COMPILER) $(GAME_LIBS) -o $(GAME_NAME) $(OBJECT_FILES)
mv $(GAME_NAME) ../
%.o: %.cpp
@echo ""
@echo ""
@echo "Compiling $<"
@$(COMPILER) $(GAME_FLAGS) $(INCLUDE_PATH) -c $< -o $@
depend: dep
dep:
-touch Makefile.dep
-makedepend $(INCLUDE_PATH) -Y -f Makefile.dep *.cpp 2> /dev/null
-rm -f Makefile.dep.bak
-include Makefile.dep

View File

@@ -1,146 +0,0 @@
/*
Compatibility wrapper to compile the same code on both SDL 1.2 and 1.3 without many #ifdefs
*/
#ifndef __SDL_FORWARD_COMPAT_H__
#define __SDL_FORWARD_COMPAT_H__
#include <SDL.h>
#include <SDL_video.h>
#include <SDL_version.h>
#ifndef __cplusplus
#error "This header is for C++ only, you're unlucky, sorry"
#endif
#if SDL_VERSION_ATLEAST(1,3,0)
struct SdlCompat_AcceleratedSurface
{
SDL_Texture * t;
int w, h;
SDL_PixelFormat * format;
};
enum { SDL_SRCALPHA = 8, SDL_SRCCOLORKEY = 16 }; // Some dummy non-zero values
typedef SDL_Keycode SDLKey;
extern SDL_Renderer * SDL_global_renderer;
static inline SdlCompat_AcceleratedSurface * SdlCompat_CreateAcceleratedSurface(SDL_Surface * surface)
{
SdlCompat_AcceleratedSurface * ret = new SdlCompat_AcceleratedSurface();
// Allocate accelerated surface even if that means loss of color quality
Uint32 format;
Uint32 colorkey;
Uint8 alpha;
ret->w = surface->w;
ret->h = surface->h;
ret->format = new SDL_PixelFormat();
memcpy(ret->format, surface->format, sizeof(SDL_PixelFormat));
format = SDL_PIXELFORMAT_RGB565;
if( SDL_GetColorKey(surface, &colorkey) == 0 )
{
format = SDL_PIXELFORMAT_RGBA4444;
}
ret->t = SDL_CreateTextureFromSurface(SDL_global_renderer, surface);
if( ! ret->t )
{
SDL_SetError("SdlCompat_CreateAcceleratedSurface: Cannot allocate HW texture, W %d H %d format %x surface->flags %x", ret->w, ret->h, format, surface->flags );
return ret;
}
SDL_SetTextureBlendMode( ret->t, SDL_BLENDMODE_BLEND );
//SDL_SetTextureAlphaMod( ret->t, SDL_ALPHA_OPAQUE );
SDL_SetTextureAlphaMod( ret->t, 128 );
if( SDL_GetSurfaceAlphaMod(surface, &alpha) == 0 )
SDL_SetTextureAlphaMod( ret->t, alpha );
return ret;
};
static inline int SDL_BlitSurface( SdlCompat_AcceleratedSurface * src, SDL_Rect * srcR, SdlCompat_AcceleratedSurface * unused, SDL_Rect * destR )
{
return SDL_RenderCopy(SDL_global_renderer, src->t, srcR, destR);
};
static inline void SDL_FreeSurface(SdlCompat_AcceleratedSurface * surface)
{
SDL_DestroyTexture(surface->t);
delete surface->format;
delete surface;
};
static inline void SDL_FillRect( SdlCompat_AcceleratedSurface * unused, const SDL_Rect* rect, Uint32 color )
{
Uint8 r = color & 0xff, g = (color >> 8) & 0xff, b = (color >> 16) & 0xff;
SDL_SetRenderDrawColor(SDL_global_renderer, r, g, b, SDL_ALPHA_OPAQUE /* a */);
SDL_RenderFillRect(SDL_global_renderer, rect);
};
static inline int SDL_Flip(SdlCompat_AcceleratedSurface * unused)
{
SDL_RenderPresent(SDL_global_renderer);
return 0;
};
static inline int SDL_SetAlpha(SdlCompat_AcceleratedSurface * surface, Uint32 flag, Uint8 alpha)
{
if( ! flag )
alpha = SDL_ALPHA_OPAQUE;
return SDL_SetTextureAlphaMod(surface->t, alpha);
};
static inline void SdlCompat_ReloadSurfaceToVideoMemory(SdlCompat_AcceleratedSurface * surface, SDL_Surface * src)
{
// Allocate accelerated surface even if that means loss of color quality
Uint32 format;
int access, w, h;
SDL_QueryTexture(surface->t, &format, &access, &w, &h);
int bpp;
Uint32 r,g,b,a;
SDL_PixelFormatEnumToMasks(format, &bpp, &r, &g, &b, &a);
SDL_Surface * formatsurf = SDL_CreateRGBSurface(0, 1, 1, bpp, r, g, b, a);
SDL_Surface * converted = SDL_ConvertSurface( src, formatsurf->format, 0 );
SDL_LockSurface(converted);
SDL_UpdateTexture( surface->t, NULL, converted->pixels, converted->pitch );
SDL_UnlockSurface(converted);
SDL_FreeSurface(converted);
SDL_FreeSurface(formatsurf);
if( src->flags & SDL_SRCALPHA )
{
SDL_SetTextureBlendMode( surface->t, SDL_BLENDMODE_BLEND );
Uint8 alpha = 128;
if( SDL_GetSurfaceAlphaMod( src, &alpha ) < 0 )
alpha = 128;
SDL_SetTextureAlphaMod( surface->t, alpha );
}
};
#else
typedef SDL_Surface SdlCompat_AcceleratedSurface;
static inline SdlCompat_AcceleratedSurface * SdlCompat_CreateAcceleratedSurface(SDL_Surface * surface)
{
return SDL_ConvertSurface(surface, surface->format, surface->flags | SDL_HWSURFACE);
};
static inline void SdlCompat_ReloadSurfaceToVideoMemory(SDL_Surface * surface, SDL_Surface * src)
{
};
#endif
#endif

View File

@@ -1,33 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 _AS_STRING_H_
#define _AS_STRING_H_
#include <sstream>
template<typename T> std::string asString(const T& obj) {
std::ostringstream t;
t << obj;
std::string res(t.str());
return res;
}
#endif

View File

@@ -1,138 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 "background.h"
#include "global.h"
#include "surfaceDB.h"
#include "SDL.h"
#include <iostream>
using namespace std;
Background::Background() {
minTileWidth = 9999999;
minTileHeight = 9999999;
tilesPerLine = 0;
tilesPerColumn = 0;
step = 0;
}
void Background::clearTileList() {
tileNames.clear();
tilesPerLine = 0;
tilesPerColumn = 0;
}
void Background::addTile( string tilename ) {
tileNames.push_back( tilename );
}
void Background::generateBackground( int length ) {
tileSurfaces.clear();
minTileWidth = 9999999;
minTileHeight = 9999999;
// load all tiles
vector< SdlCompat_AcceleratedSurface* > tmpTiles;
for(int i=tileNames.size()-1; i>=0; i--) {
SdlCompat_AcceleratedSurface *tile = surfaceDB.loadSurface( tileNames[i] );
if (tile != NULL) {
tmpTiles.push_back( tile );
if (tile->w < minTileWidth) {
minTileWidth = tile->w;
}
if (tile->h < minTileHeight) {
minTileHeight = tile->h;
}
}
}
// calculate tiles per line and tiles per row
tilesPerLine = SCREEN_WIDTH / minTileWidth;
if (SCREEN_WIDTH % minTileWidth) {
tilesPerLine++;
}
tilesPerColumn = SCREEN_HEIGHT / minTileHeight;
if (SCREEN_HEIGHT % minTileHeight) {
tilesPerColumn++;
}
int rows = length / minTileHeight;
if (length % minTileHeight) {
rows++;
}
// cout << "Background: minTileWidth=" << minTileWidth << " minTileHeight=" << minTileHeight << " rows=" << rows << endl;
// generate random background
for(int i=rows*tilesPerLine; i; i--) {
tileSurfaces.push_back( tmpTiles[ rand() % tmpTiles.size() ] );
}
}
void Background::draw( SdlCompat_AcceleratedSurface* screen ) {
step = (step+1) % (tilesPerColumn*minTileHeight);
draw( screen, step );
}
void Background::draw( SdlCompat_AcceleratedSurface* screen, int step ) {
if (step < 0) {
step *= -1;
}
int startLine = (step / minTileHeight);
int offset = (step % minTileHeight);
SDL_Rect srcRect;
srcRect.x = 0;
srcRect.y = 0;
SDL_Rect dstRect;
for(int y = 0; y < tilesPerColumn+1; y++) {
for(int x = 0; x < tilesPerLine; x++) {
int diffX = SCREEN_WIDTH - x * minTileWidth;
if ( diffX >= minTileWidth ) {
srcRect.w = minTileWidth;
} else {
srcRect.w = diffX;
}
dstRect.w = srcRect.w;
if (y==0) {
int diffY = -(offset - minTileHeight);
srcRect.h = diffY;
} else {
srcRect.h = minTileHeight;
}
dstRect.h = srcRect.h;
dstRect.x = x * minTileWidth;
dstRect.y = SCREEN_HEIGHT + offset - (y+1) * minTileHeight;
SDL_BlitSurface( tileSurfaces[ ((y+startLine)*tilesPerLine+x) % tileSurfaces.size()] , &srcRect, screen, &dstRect );
}
}
}

View File

@@ -1,50 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 _BACKGROUND_H_
#define _BACKGROUND_H_
#include <vector>
#include <string>
#include "SdlForwardCompat.h"
class Background {
public:
Background();
void clearTileList();
void addTile( std::string tilename );
void generateBackground( int length );
void draw( SdlCompat_AcceleratedSurface* screen );
void draw( SdlCompat_AcceleratedSurface* screen, int step );
private:
int minTileWidth;
int minTileHeight;
int tilesPerLine;
int tilesPerColumn;
int step;
std::vector< std::string > tileNames;
std::vector< SdlCompat_AcceleratedSurface* > tileSurfaces;
};
#endif

View File

@@ -1,122 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 "banner.h"
#include "surfaceDB.h"
#include <iostream>
Banner::Banner( BannerTexts text, BannerModes mode, BannerBoni bonus ) {
sprite = surfaceDB.loadSurface( FN_BANNER_TEXTS[ text ], true );
this->mode = mode;
if ( this->mode == BANNER_MODE_RANDOM ) {
this->mode = (BannerModes)(rand() % NR_BANNER_MODES);
}
this->bonus = bonus;
if ( this->bonus != BANNER_BONUS_NONE ) {
spriteBonus = surfaceDB.loadSurface( FN_BANNER_BONUS[ bonus ], true );
}
pos = Vector2D( -1000, -1000 );
if ( mode == BANNER_MODE_ITEM_COLLECTED_SINGLE_PLAYER ) {
pos = Vector2D( 10, SCREEN_HEIGHT - 20 - sprite->h );
} else if ( mode == BANNER_MODE_ITEM_COLLECTED_PLAYER_ONE ) {
pos = Vector2D( 10, SCREEN_HEIGHT - 20 - sprite->h );
} else if ( mode == BANNER_MODE_ITEM_COLLECTED_PLAYER_TWO ) {
pos = Vector2D( SCREEN_WIDTH - sprite->w - 10,
SCREEN_HEIGHT - 20 - sprite->h );
}
timeLived = 0;
}
Banner::~Banner() {}
bool Banner::isExpired() {
return timeLived > BANNER_MODE_LIFETIME[ mode ];
}
void Banner::update( int dT ) {
timeLived += dT;
switch ( mode ) {
case BANNER_MODE_FLY_FROM_LEFT:
{
if ( timeLived < 1000 ) {
pos = Vector2D( -(sprite->w) + ((SCREEN_WIDTH + sprite->w)/ 2) * (timeLived / 1000.0),
200 - sprite->h / 2 );
} else if ( 1000 < timeLived && timeLived < 3000 ) {
pos = Vector2D( ( SCREEN_WIDTH - sprite->w ) / 2,
200 - sprite->h / 2 );
} else {
pos = Vector2D( ((SCREEN_WIDTH - sprite->w)/2) +
((SCREEN_WIDTH + sprite->w)/2)*((timeLived-3000)/2000.0),
200 - sprite->h / 2 );
}
break;
}
case BANNER_MODE_FROM_TOP:
{
if ( timeLived < 1000 ) {
pos = Vector2D( (SCREEN_WIDTH - sprite->w)/2,
-(sprite->h) + (200 + sprite->h/2) * (timeLived / 1000.0) );
} else if ( 1000 < timeLived && timeLived < 3000 ) {
pos = Vector2D( (SCREEN_WIDTH - sprite->w)/2,
200 - (sprite->h / 2 ) );
} else {
pos = Vector2D( (SCREEN_WIDTH - sprite->w)/2,
200 - (sprite->h / 2) +
(200 + (sprite->h / 2))*((timeLived-3000)/2000.0) );
}
break;
}
case BANNER_MODE_ITEM_COLLECTED_SINGLE_PLAYER:
case BANNER_MODE_ITEM_COLLECTED_PLAYER_ONE:
case BANNER_MODE_ITEM_COLLECTED_PLAYER_TWO:
{
break;
}
default:
{
break;
}
}
}
bool Banner::movingAway() {
return ( 3000 <= timeLived );
}
void Banner::draw(SdlCompat_AcceleratedSurface *screen) {
SDL_Rect r;
r.x = lroundf(pos.getX());
r.y = lroundf(pos.getY());
r.w = sprite->w;
r.h = sprite->h;
SDL_BlitSurface( sprite, 0, screen, &r );
if ( bonus != BANNER_BONUS_NONE &&
1000 < timeLived && timeLived < 3000 ) {
r.x = SCREEN_WIDTH / 2 - spriteBonus->w / 2;
r.y = 250;
r.w = spriteBonus->w;
r.h = spriteBonus->h;
SDL_BlitSurface( spriteBonus, 0, screen, &r );
}
}

View File

@@ -1,50 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 BANNER_H
#define BANNER_H
#include "SDL.h"
#include <string>
#include "geometry.h"
#include "global.h"
class Banner {
SdlCompat_AcceleratedSurface *sprite;
SdlCompat_AcceleratedSurface *spriteBonus;
int sound;
Vector2D pos;
int timeLived;
BannerModes mode;
BannerBoni bonus;
public:
Banner( BannerTexts text, BannerModes mode, BannerBoni bonus );
~Banner();
void update( int dT );
void draw( SdlCompat_AcceleratedSurface *screen );
bool isExpired();
bool movingAway();
};
#endif

View File

@@ -1,90 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 "banners.h"
#include "banner.h"
using namespace std;
Banners::Banners() {}
Banners::~Banners() {
vector<Banner *>::iterator i;
for (i = banners.begin(); i != banners.end(); ++i) {
delete *i;
}
}
void Banners::addBanner( BannerTexts bannerText, BannerModes mode,
BannerBoni bonus ) {
Banner *newBanner = new Banner( bannerText, mode, bonus );
banners.push_back( newBanner );
}
void Banners::expireBanners() {
unsigned int i = 0;
while ( i < banners.size() ) {
if ( banners[i]->isExpired() ) {
delete banners[i];
banners.erase(banners.begin() + i);
} else {
i++;
}
}
}
void Banners::deleteAllBanners() {
unsigned int i = 0;
while ( i < banners.size() ) {
delete banners[i];
i++;
}
banners.clear();
}
void Banners::update( int dT ) {
switch ( banners.size() ) {
case 0: break;
case 1: banners[0]->update( dT ); break;
default:
{
banners[0]->update( dT );
if ( banners[0]->movingAway() ) {
banners[1]->update( dT );
}
break;
}
}
}
void Banners::draw(SdlCompat_AcceleratedSurface *screen) {
switch ( banners.size() ) {
case 0: break;
case 1: banners[0]->draw( screen ); break;
default:
{
banners[0]->draw( screen );
if ( banners[0]->movingAway() ) {
banners[1]->draw( screen );
}
break;
}
}
}

View File

@@ -1,46 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 BANNERS_H
#define BANNERS_H
#include "SDL.h"
#include "global.h"
#include <vector>
#include <string>
class Banner;
class Banners {
std::vector<Banner *> banners;
public:
Banners();
~Banners();
void addBanner( BannerTexts bannerText, BannerModes mode=BANNER_MODE_RANDOM,
BannerBoni bonus=ARCADE_BONUS_FOR_FORMATION_DESTRUCTION );
void expireBanners();
void deleteAllBanners();
void update( int dT );
void draw(SdlCompat_AcceleratedSurface *screen);
};
#endif

View File

@@ -1,123 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 "boundingBox.h"
/*
void setX(Uint16 newX) {box.x = newX;}
void setY(Uint16 newY) {box.y = newY;}
void setWidth(Uint16 newWidth) {box.w = newWidth;}
void setHeight(Uint16 newHeight) {box.h = newHeight;}
*/
BoundingBox::BoundingBox(int x, int y, int width, int height) {
box.x = x;
box.y = y;
box.w = width;
box.h = height;
}
int BoundingBox::getUpperBound() {
return box.y;
}
int BoundingBox::getLowerBound() {
return box.y + box.h;
}
int BoundingBox::getLeftBound() {
return box.x;
}
int BoundingBox::getRightBound() {
return box.x + box.w;
}
bool BoundingBox::overlaps(BoundingBox *other) {
return ( !(getUpperBound() > other->getLowerBound()) &&
!(getLowerBound() < other-> getUpperBound()) &&
!(getLeftBound() > other->getRightBound()) &&
!(getRightBound() < other->getLeftBound()) );
}
bool BoundingBox::overlaps(const Vector2D &startOfLine, const Vector2D &endOfLine) {
// FIXME: optimize me!
RectangleGeo rect( Vector2D( box.x, box.y ),
Vector2D( box.x + box.w, box.y + box.h ) );
// FIXME: optimize me!
bool overlaps = false;
overlaps = rect.isInside( endOfLine );
if ( overlaps ) return true;
overlaps = rect.isInside( startOfLine );
if ( overlaps ) return true;
// check some points between the two end points
Vector2D delta((endOfLine.getX() - startOfLine.getX()) / 4.0,
(endOfLine.getY() - startOfLine.getY()) / 4.0);
Vector2D actPoint = startOfLine + delta;
int i = 1;
while (!overlaps && i <= 3 ) {
overlaps = rect.isInside(actPoint);
actPoint += delta;
i++;
}
return overlaps;
}
bool BoundingBox::overlaps(const Circle &circle) {
RectangleGeo rect( Vector2D( box.x, box.y ),
Vector2D( box.x + box.w, box.y + box.h ) );
return (rect.isInside(circle.getCenter()) ||
circle.isInside(rect.getPosLeftTop()) ||
circle.isInside(rect.getPosRightBottom()) ||
circle.isInside(Vector2D( box.x, box.y + box.h )) ||
circle.isInside(Vector2D( box.x + box.w, box.y )));
}
void BoundingBox::modifyX(int value) {
box.x += value;
}
void BoundingBox::modifyY(int value) {
box.y += value;
}
void BoundingBox::moveUpperBound(int upperBound) {
box.y = upperBound;
}
void BoundingBox::moveLowerBound(int lowerBound) {
box.y = lowerBound - box.h;
}
void BoundingBox::moveLeftBound(int leftBound) {
box.x = leftBound;
}
void BoundingBox::moveRightBound(int rightBound) {
box.x = rightBound - box.w;
}
/*
SDL_Rect *BoundingBox::getRect() {
return &box;
}
*/

View File

@@ -1,54 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 BOUNDING_BOX_H
#define BOUNDING_BOX_H
#include "SDL.h"
#include "geometry.h"
struct MyRect {
int x, y, w, h;
};
class BoundingBox {
private:
//SDL_Rect box;
MyRect box;
public:
BoundingBox(int x, int y, int width, int height);
int getUpperBound();
int getLowerBound();
int getLeftBound();
int getRightBound();
bool overlaps(BoundingBox *other);
bool overlaps(const Vector2D &startOfLine, const Vector2D &endOfLine);
bool overlaps(const Circle &circle);
void modifyX(int value);
void modifyY(int value);
void moveUpperBound(int upperBound);
void moveLowerBound(int lowerBound);
void moveLeftBound(int leftBound);
void moveRightBound(int rightBound);
// SDL_Rect *getRect();
};
#endif

View File

@@ -1,537 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 "enemy.h"
#include "SDL.h"
#include "surfaceDB.h"
#include "boundingBox.h"
#include "mixer.h"
#include "shots.h"
#include "shot.h"
#include "racers.h"
#include "racer.h"
#include "items.h"
#include "item.h"
#include "wrecks.h"
#include "wreck.h"
#include "global.h"
#include "explosions.h"
#include "explosion.h"
#include "options.h"
Enemy::Enemy( Vector2D pos, Vector2D vel, EnemyTypes whichEnemyType,
bool isInFormation, bool fireByFormation ) {
this->isInFormation = isInFormation;
this->fireByFormation = fireByFormation;
enemyType = whichEnemyType;
hitpoints = ENEMY_HITPOINTS[ enemyType ];
this->pos = pos;
this->vel = vel;
relTargetPos = Vector2D(0,0);
switch ( enemyType ) {
case FIGHTER:
{
string fn = LVL_ENEMY_FIGHTER;
levelConf->getStr( LVL_ENEMY_FIGHTER, fn );
spriteEnemy = surfaceDB.loadSurface( fn );
fn = LVL_ENEMY_FIGHTER_SHADOW;
levelConf->getStr( LVL_ENEMY_FIGHTER_SHADOW, fn );
spriteShadow = surfaceDB.loadSurface( fn, true );
break;
}
case BOMBER:
{
string fn = LVL_ENEMY_BOMBER;
levelConf->getStr( LVL_ENEMY_BOMBER, fn );
spriteEnemy = surfaceDB.loadSurface( fn );
fn = LVL_ENEMY_BOMBER_SHADOW;
levelConf->getStr( LVL_ENEMY_BOMBER_SHADOW, fn );
spriteShadow = surfaceDB.loadSurface( fn, true );
break;
}
case TANK:
{
string fn = LVL_ENEMY_TANK;
levelConf->getStr( LVL_ENEMY_TANK, fn );
spriteEnemy = surfaceDB.loadSurface( fn );
break;
}
case BOSS_1_MAIN_GUN:
{
string fn = LVL_ENEMY_BOSS_1_MAIN_GUN;
levelConf->getStr( LVL_ENEMY_BOSS_1_MAIN_GUN, fn );
spriteEnemy = surfaceDB.loadSurface( fn );
break;
}
case BOSS_1_ROCKET_LAUNCHER:
{
string fn = LVL_ENEMY_BOSS_1_ROCKET_LAUNCHER;
levelConf->getStr( LVL_ENEMY_BOSS_1_ROCKET_LAUNCHER, fn );
spriteEnemy = surfaceDB.loadSurface( fn );
break;
}
case BOSS_1_SHOT_BATTERY_LEFT:
{
string fn = LVL_ENEMY_BOSS_1_SHOT_BATTERY_LEFT;
levelConf->getStr( LVL_ENEMY_BOSS_1_SHOT_BATTERY_LEFT, fn );
spriteEnemy = surfaceDB.loadSurface( fn );
break;
}
case BOSS_1_SHOT_BATTERY_RIGHT:
{
string fn = LVL_ENEMY_BOSS_1_SHOT_BATTERY_RIGHT;
levelConf->getStr( LVL_ENEMY_BOSS_1_SHOT_BATTERY_RIGHT, fn );
spriteEnemy = surfaceDB.loadSurface( fn );
break;
}
case BOSS_2:
{
spriteEnemy = surfaceDB.loadSurface( FN_ENEMY_BOSS_2 );
spriteShadow = surfaceDB.loadSurface( FN_ENEMY_BOSS_2_SHADOW, true );
boss2PointReached = false;
boss2TargetPos = Vector2D(SCREEN_WIDTH / 2, 100);
break;
}
default:
{
string fn = LVL_ENEMY_FIGHTER;
levelConf->getStr( LVL_ENEMY_FIGHTER, fn );
spriteEnemy = surfaceDB.loadSurface( fn );
break;
}
}
boundingBox = new BoundingBox( lroundf(pos.getX() - spriteEnemy->w * 0.45),
lroundf(pos.getY() - spriteEnemy->h * 0.45),
lroundf(spriteEnemy->w * 0.9),
lroundf(spriteEnemy->h * 0.9) );
nextShotPrimary = rand() % (ENEMY_RAND_WAIT_PRIMARY[ enemyType ]+1);
nextShotSecondary = rand() % (ENEMY_RAND_WAIT_SECONDARY[ enemyType ]+1);
sndShotPrimary = Mixer::mixer().loadSample( FN_SOUND_SHOT_PRIMARY );
sndShotSecondary = Mixer::mixer().loadSample( FN_SOUND_SHOT_SECONDARY );
}
Enemy::~Enemy() {
delete boundingBox;
}
bool Enemy::isExpired() {
return ( hitpoints <= 0 ||
pos.getY() < -500 ||
pos.getY() > SCREEN_HEIGHT + 500 ||
pos.getX() < -500 ||
pos.getX() > SCREEN_WIDTH + 500 );
}
void Enemy::expire() {
hitpoints = -1;
}
Circle Enemy::getBoundingCircle() {
return Circle( pos, min(spriteEnemy->w / 2, spriteEnemy->h / 2) );
}
BoundingBox *Enemy::getBoundingBox() {
return boundingBox;
}
bool Enemy::collidesWith( const Vector2D &shotPosOld, const Vector2D &shotPosNew ) {
return boundingBox->overlaps(shotPosOld, shotPosNew);
}
bool Enemy::collidesWith( BoundingBox *box ) {
return boundingBox->overlaps( box );
}
bool Enemy::collidesWith( const Circle &circle ) {
return boundingBox->overlaps( circle );
}
bool Enemy::collidesWithAsCircle( const Circle &circle ) {
return ( circle.getRadius() + spriteEnemy->w / 2 > circle.getCenter().distanceTo( pos ) );
}
bool Enemy::collidesWithAsCircle( BoundingBox *box ) {
return ( box->overlaps( Circle( pos, min( spriteEnemy->h / 2, spriteEnemy->w / 2 ) ) ) );
}
void Enemy::update( int dT ) {
move( dT );
if ( !fireByFormation ) {
shootPrimary( dT );
shootSecondary( dT );
}
}
void Enemy::move( int dT ) {
switch ( enemyType ) {
case FIGHTER:
case BOMBER:
{
if ( scrollingOn ) pos += vel * dT / 1000.0;
else pos += (vel - SCROLL_SPEED) * dT / 1000.0;
if ( isInFormation && relTargetPos != Vector2D(0,0) ) {
Vector2D addMovement =
Vector2D( 40, relTargetPos.getDirection(), POLAR ) * dT / 1000.0;
if ( addMovement.getLength() > relTargetPos.getLength() ) {
addMovement.setLength( relTargetPos.getLength() );
}
pos += addMovement;
relTargetPos -= addMovement;
}
updateBoundingBox();
break;
}
case TANK: {
if ( scrollingOn ) pos += vel * dT / 1000.0;
updateBoundingBox();
break;
}
case BOSS_1_MAIN_GUN:
case BOSS_1_ROCKET_LAUNCHER:
case BOSS_1_SHOT_BATTERY_LEFT:
case BOSS_1_SHOT_BATTERY_RIGHT: {
if ( scrollingOn ) {
pos += Vector2D( 0, SCROLL_SPEED * dT / 1000.0 );
updateBoundingBox();
if ( pos.getY() >= BOSS_1_END_Y ) {
scrollingOn = false;
pos.setY( BOSS_1_END_Y );
}
}
break;
}
case BOSS_2: {
if ( boss2PointReached ) {
boss2TargetPos = Vector2D( (rand() % (SCREEN_WIDTH - spriteEnemy->w)) + spriteEnemy->w / 2, rand() % 100 + spriteEnemy->h );
boss2PointReached = false;
} else {
pos += (boss2TargetPos - pos) / 50;
}
if ( pos.distanceTo(boss2TargetPos) < 15.0 ) boss2PointReached = true;
updateBoundingBox();
break;
}
default: cout << "enemys.cc::move(): unknown enemyType" << endl; break;
}
}
void Enemy::updateBoundingBox() {
boundingBox->moveUpperBound( lroundf(pos.getY() - spriteEnemy->h * 0.45) );
boundingBox->moveLeftBound( lroundf(pos.getX() - spriteEnemy->w * 0.45) );
}
void Enemy::firePrimary() {
switch (enemyType) {
case FIGHTER:
{
Shot *shot =
new Shot( ENEMY_SHOT_NORMAL, 666,
pos + Vector2D( 0, spriteEnemy->h / 2 ),
90 );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotPrimary, 0 );
break;
}
case BOMBER:
{
Shot *shot =
new Shot( ENEMY_SHOT_NORMAL, 666,
pos + Vector2D( -7, spriteEnemy->h / 2 ),
100 );
shots->addShot( shot );
shot =
new Shot( ENEMY_SHOT_NORMAL, 666,
pos + Vector2D( +7, spriteEnemy->h / 2 ),
80 );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotPrimary, 0 );
break;
}
case TANK:
{
Shot *shot =
new Shot( ENEMY_SHOT_NORMAL, 666,
pos,
(rand() % 360) - 180 );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotPrimary, 0 );
break;
}
case BOSS_1_MAIN_GUN:
{
Shot *shot =
new Shot( ENEMY_SHOT_NORMAL, 666,
pos,
(rand() % 20) + 80 );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotPrimary, 0 );
break;
}
case BOSS_1_SHOT_BATTERY_LEFT:
{
Shot *shot =
new Shot( ENEMY_SHOT_NORMAL, 666,
pos,
(rand() % 120) + 30 );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotPrimary, 0 );
break;
}
case BOSS_1_SHOT_BATTERY_RIGHT:
{
Shot *shot =
new Shot( ENEMY_SHOT_NORMAL, 666,
pos,
(rand() % 120) + 30 );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotPrimary, 0 );
break;
}
case BOSS_1_ROCKET_LAUNCHER:
{
unsigned int racerIdx = rand() % racers->getNrRacers();
float angle = (racers->getRacer( racerIdx )->getPos() - pos).getDirection();
Shot *shot =
new Shot( ENEMY_SHOT_TANK_ROCKET, 666, pos, angle );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotSecondary, 0 );
break;
}
case BOSS_2:
{
unsigned int racerIdx = rand() % racers->getNrRacers();
float angle = (racers->getRacer( racerIdx )->getPos() - pos).getDirection();
Shot *shot = new Shot( ENEMY_SHOT_NORMAL, 666, pos, angle );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotPrimary, 0 );
break;
}
default:
{
break;
}
}
}
void Enemy::shootPrimary( int dT ) {
nextShotPrimary -= dT;
if ( nextShotPrimary < 0 ) {
firePrimary();
nextShotPrimary =
(rand() % (ENEMY_RAND_WAIT_PRIMARY[ enemyType ]+1)) + ENEMY_COOLDOWN_PRIMARY[ enemyType ];
}
}
void Enemy::fireSecondary() {
switch (enemyType) {
case TANK:
{
unsigned int racerIdx = rand() % racers->getNrRacers();
float angle = (racers->getRacer( racerIdx )->getPos() - pos).getDirection();
Shot *shot =
new Shot( ENEMY_SHOT_TANK_ROCKET, 666, pos, angle );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotSecondary, 0 );
break;
}
case BOSS_2:
{
unsigned int racerIdx = rand() % racers->getNrRacers();
float angle = (racers->getRacer( racerIdx )->getPos() - pos).getDirection();
Shot *shot = new Shot( ENEMY_SHOT_TANK_ROCKET, 666, pos - Vector2D(-80,0), angle );
shots->addShot( shot );
shot = new Shot( ENEMY_SHOT_TANK_ROCKET, 666, pos - Vector2D(+80,0), angle );
shots->addShot( shot );
Mixer::mixer().playSample( sndShotSecondary, 0 );
break;
}
default:
{
break;
}
}
}
void Enemy::shootSecondary( int dT ) {
nextShotSecondary -= dT;
if ( nextShotSecondary < 0 ) {
fireSecondary();
nextShotSecondary =
(rand() % (ENEMY_RAND_WAIT_SECONDARY[ enemyType ]+1)) +
ENEMY_COOLDOWN_SECONDARY[ enemyType ];
}
}
void Enemy::doDamage( ShotTypes shotType, int fromWhichPlayer ) {
bool allreadyDead = isExpired();
switch (shotType) {
case SHOT_NORMAL: hitpoints -= DAMAGE_SHOT_NORMAL; break;
case SHOT_NORMAL_HEAVY: hitpoints -= DAMAGE_SHOT_NORMAL_HEAVY; break;
case SHOT_DOUBLE: hitpoints -= DAMAGE_SHOT_DOUBLE; break;
case SHOT_DOUBLE_HEAVY: hitpoints -= DAMAGE_SHOT_DOUBLE_HEAVY; break;
case SHOT_TRIPLE: hitpoints -= DAMAGE_SHOT_TRIPLE; break;
case SHOT_HF_NORMAL: hitpoints -= DAMAGE_SHOT_HF_NORMAL; break;
case SHOT_HF_DOUBLE: hitpoints -= DAMAGE_SHOT_HF_DOUBLE; break;
case SHOT_HF_TRIPLE: hitpoints -= DAMAGE_SHOT_HF_TRIPLE; break;
case SHOT_HF_QUATTRO: hitpoints -= DAMAGE_SHOT_HF_QUATTRO; break;
case SHOT_HF_QUINTO: hitpoints -= DAMAGE_SHOT_HF_QUINTO; break;
case SHOT_DUMBFIRE: hitpoints -= DAMAGE_SHOT_DUMBFIRE; break;
case SHOT_DUMBFIRE_DOUBLE: hitpoints -= DAMAGE_SHOT_DUMBFIRE_DOUBLE; break;
case SHOT_KICK_ASS_ROCKET: hitpoints -= DAMAGE_SHOT_KICK_ASS_ROCKET; break;
case SHOT_HELLFIRE: hitpoints -= DAMAGE_SHOT_HELLFIRE; break;
case SHOT_MACHINE_GUN: hitpoints -= DAMAGE_SHOT_MACHINE_GUN; break;
case SHOT_ENERGY_BEAM: hitpoints -= DAMAGE_SHOT_ENERGY_BEAM; break;
case SHOT_HF_DUMBFIRE: hitpoints -= DAMAGE_SHOT_HF_DUMBFIRE; break;
case SHOT_HF_DUMBFIRE_DOUBLE: hitpoints -= DAMAGE_SHOT_HF_DUMBFIRE_DOUBLE; break;
case SHOT_HF_KICK_ASS_ROCKET: hitpoints -= DAMAGE_SHOT_HF_KICK_ASS_ROCKET; break;
case SHOT_HF_LASER: hitpoints -= DAMAGE_SHOT_HF_LASER; break;
case SPECIAL_SHOT_HEATSEEKER: hitpoints -= DAMAGE_SPECIAL_SHOT_HEATSEEKER; break;
case SPECIAL_SHOT_NUKE: hitpoints -= DAMAGE_SPECIAL_SHOT_NUKE; break;
default:
{
cout << "Enemy::doDamage: unexpected shotType: " << shotType << endl;
break;
}
}
if ( enemyType < NR_ENEMY_TYPES_NORMAL ) {
// the enemy just died -> explode, generate item,
if ( (!allreadyDead) && isExpired() ) {
// the player gets points, who did the final shot
if ( 0 <= fromWhichPlayer && fromWhichPlayer < (int)racers->getNrRacers() ) {
racers->getRacer( fromWhichPlayer )->receivePoints( ENEMY_POINTS_FOR_DEST[ enemyType ]);
}
// explode
Explosion *newExplosion =
new Explosion( FN_EXPLOSION_ENEMY, pos, vel, EXPLOSION_NORMAL_AIR );
explosions->addExplosion( newExplosion );
// generate wreck
Wreck *newWreck = new Wreck( pos, WRECK_FOR_ENEMYTYPE[ enemyType ]);
wrecks->addWreck( newWreck );
// generate item
if ( rand() % ENEMY_DIES_ITEM_APPEAR_CHANCE[ enemyType ] == 0 ) {
items->generateItemNow( pos, vel / 10.0 );
}
}
}
// it's a boss!!!
else {
if ( (!allreadyDead) && isExpired() ) {
// explode
Explosion *newExplosion;
for(int i = 0; i < 10; i++){
newExplosion = new Explosion(
FN_EXPLOSION_ENEMY,
pos + Vector2D(rand() % spriteEnemy->w - spriteEnemy->w / 2, rand() % spriteEnemy->h - spriteEnemy->h / 2),
vel + Vector2D(rand() % 100 - 50, rand() % 100 - 50) / 5.0,
EXPLOSION_NORMAL_GROUND );
explosions->addExplosion( newExplosion );
}
// generate wreck
Wreck *newWreck = new Wreck( pos, WRECK_FOR_ENEMYTYPE[ enemyType ]);
wrecks->addWreck( newWreck );
}
}
}
void Enemy::drawGroundEnemy( SdlCompat_AcceleratedSurface *screen ) {
if ( ENEMY_FLYING[ enemyType ] ) return;
SDL_Rect destR;
destR.x = lroundf(pos.getX()) - spriteEnemy->w / 2;
destR.y = lroundf(pos.getY()) - spriteEnemy->h / 2;
destR.w = spriteEnemy->w;
destR.h = spriteEnemy->h;
SDL_BlitSurface( spriteEnemy, 0, screen, &destR );
}
void Enemy::drawAirEnemy( SdlCompat_AcceleratedSurface *screen ) {
if ( !ENEMY_FLYING[ enemyType ] ) return;
SDL_Rect destR;
destR.x = lroundf(pos.getX()) - spriteEnemy->w / 2;
destR.y = lroundf(pos.getY()) - spriteEnemy->h / 2;
destR.w = spriteEnemy->w;
destR.h = spriteEnemy->h;
SDL_BlitSurface( spriteEnemy, 0, screen, &destR );
}
void Enemy::drawShadow( SdlCompat_AcceleratedSurface *screen ) {
if ( !ENEMY_FLYING[ enemyType ] ) return;
SDL_Rect destR;
destR.x = lroundf(pos.getX()) - spriteShadow->w / 2 - ENEMY_FLYING_HEIGHT[ enemyType ];
destR.y = lroundf(pos.getY()) - spriteShadow->h / 2 + ENEMY_FLYING_HEIGHT[ enemyType ];
destR.w = spriteShadow->w;
destR.h = spriteShadow->h;
SDL_BlitSurface( spriteShadow, 0, screen, &destR );
}
void Enemy::drawStats( SdlCompat_AcceleratedSurface *screen ) {
// draw status of the bosses
float pixPerHP = spriteEnemy->w / (float)(ENEMY_HITPOINTS[ enemyType ]);
SDL_Rect destR;
// draw damage
destR.x = lroundf(pos.getX()) - spriteEnemy->w / 2;
destR.y = lroundf(pos.getY()) - spriteEnemy->h / 2 - 4;
float damageToDraw = min( (float)ENEMY_HITPOINTS[ enemyType ] / 2, hitpoints );
destR.w = lroundf(pixPerHP * damageToDraw);
destR.h = 3;
SDL_FillRect( screen, &destR, SDL_MapRGB(screen->format, 255, 0, 0) );
// draw shields
destR.x = lroundf(pos.getX());
destR.y = lroundf(pos.getY()) - spriteEnemy->h / 2 - 4;
float shieldToDraw = min( (float)ENEMY_HITPOINTS[ enemyType ] / 2,
hitpoints - ENEMY_HITPOINTS[ enemyType ] / 2 );
if ( shieldToDraw < 1 ) destR.w = 0;
else destR.w = lroundf(pixPerHP * shieldToDraw);
destR.h = 3;
SDL_FillRect(screen, &destR, SDL_MapRGB(screen->format, 0, 255, 0) );
}

View File

@@ -1,124 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 ENEMY_HH
#define ENEMY_HH
#include "SDL.h"
#include "geometry.h"
#include <string>
#include "shot.h"
#include "global.h"
class Shot;
class Shots;
class BoundingBox;
class Enemy {
private:
SdlCompat_AcceleratedSurface *spriteEnemy;
SdlCompat_AcceleratedSurface *spriteShadow;
// for collision with racers or shots.
// A rectangle with racersize * 0.9 is used.
BoundingBox *boundingBox;
// Movement-System
Vector2D pos; // absolute position
Vector2D vel; // the velocity vector
Vector2D relTargetPos;
// needed for cooldown
int nextShotPrimary;
int nextShotSecondary;
int sndShotPrimary;
int sndShotSecondary;
float hitpoints;
EnemyTypes enemyType;
bool isInFormation;
bool fireByFormation;
bool boss2PointReached;
Vector2D boss2TargetPos;
public:
Enemy( Vector2D pos, Vector2D vel, EnemyTypes whichEnemyType, bool isInFormation=false,
bool fireByFormation=false );
~Enemy();
bool isExpired();
void expire();
bool isDead() { return ( hitpoints <= 0 ); }
EnemyTypes getType() { return enemyType; }
void update( int dT );
void firePrimary();
void fireSecondary();
// The enemy will make an additional movement of newRelTargetPos.
// This is used, when the enemy is part of a formation and should move
// to another position in the formation.
void setNewRelTargetPos( Vector2D newRelTargetPos ) { relTargetPos = newRelTargetPos; }
void setPos(Vector2D newPos);
Vector2D getPos() { return pos; }
Vector2D getVel() { return vel; }
Vector2D setVel(Vector2D newVel); // returns old vel
private:
// fire the Guns!
void shootPrimary( int dT );
void shootSecondary( int dT );
// moves the enemy according to his velocity
void move( int dT );
// move the boundingBox accordingly to the movement
void updateBoundingBox();
public:
void drawGroundEnemy( SdlCompat_AcceleratedSurface *screen );
void drawAirEnemy( SdlCompat_AcceleratedSurface *screen );
void drawShadow( SdlCompat_AcceleratedSurface *screen );
void drawStats( SdlCompat_AcceleratedSurface *screen );
// collision system
// return if the line between the two points collides with the boundingBox
bool collidesWith( const Vector2D &shotPosOld, const Vector2D &shotPosNew );
// return if the racers boundingBox overlaps with box
bool collidesWith( BoundingBox *box );
// return if the racers boundingBox overlaps with circle
bool collidesWith( const Circle &circle );
// returns if a inner circle around the racer overlaps with circle
bool collidesWithAsCircle( const Circle &circle );
// returns if a inner circle around the racer overlaps with circle
bool collidesWithAsCircle( BoundingBox *box );
// returns the boundingBox of the racer
BoundingBox *getBoundingBox();
Circle getBoundingCircle();
// the enemy got hit -> do the damage according to the shotType
void doDamage( ShotTypes shotType, int fromWhichPlayer );
};
#endif

View File

@@ -1,374 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include <iostream>
#include <math.h>
#include "global.h"
#include "enemys.h"
#include "enemy.h"
#include "racers.h"
#include "racer.h"
#include "wrecks.h"
#include "wreck.h"
#include "surfaceDB.h"
#include "formation.h"
#include "banners.h"
#include "options.h"
Enemys::Enemys() {
timeToNextEnemy = GENERATE_ENEMY_DELAY + (rand() % (GENERATE_ENEMY_RAND_DELAY+1));
timeToNextFormation =
GENERATE_FORMATION_DELAY + (rand() % (GENERATE_FORMATION_RAND_DELAY + 1));
bossActive = 0;
enemysKilled = 0;
enemysGenerated = 0;
}
Enemys::~Enemys() {
vector<Enemy *>::iterator i;
for (i = enemys.begin(); i != enemys.end(); ++i) {
delete *i;
}
vector<Formation *>::iterator f;
for (f = formations.begin(); f != formations.end(); ++f) {
delete *f;
}
}
void Enemys::addEnemy( Enemy *newEnemy ) {
if ( newEnemy ) {
enemys.push_back( newEnemy );
enemysGenerated++;
}
}
bool Enemys::minibossDead(){
for ( unsigned int i = 0; i < enemys.size(); i++ ) {
if ( enemys[ i ]->getType() == BOSS_2 ) return false;
}
return true;
}
bool Enemys::bossDead() {
bool dead = true;
for ( unsigned int i = 0; i < enemys.size(); i++ ) {
if ( enemys[ i ]->getType() >= NR_ENEMY_TYPES_NORMAL ) {
dead = false;
break;
}
}
if (dead) bossActive = 0;
return dead;
}
void Enemys::bossTime( int bossNr ) {
bossActive = bossNr;
Enemy *boss;
Wreck *wreck;
switch (bossNr) {
// Final boss
case 1:
{
wreck = new Wreck( Vector2D( SCREEN_WIDTH / 2 , -120 ), WRECK_BOSS_1_BACKGROUND );
wrecks->addWreck( wreck );
boss = new Enemy( Vector2D( 321, -102 ), Vector2D( 0, SCROLL_SPEED ), BOSS_1_MAIN_GUN );
addEnemy( boss );
boss = new Enemy( Vector2D( 248, -73 ), Vector2D( 0, SCROLL_SPEED ),
BOSS_1_SHOT_BATTERY_LEFT );
addEnemy( boss );
boss = new Enemy( Vector2D( 393, -73 ), Vector2D( 0, SCROLL_SPEED ),
BOSS_1_SHOT_BATTERY_RIGHT );
addEnemy( boss );
boss = new Enemy( Vector2D( 50, -85 ), Vector2D( 0, SCROLL_SPEED ),
BOSS_1_ROCKET_LAUNCHER );
addEnemy( boss );
boss = new Enemy( Vector2D( 590, -85 ), Vector2D( 0, SCROLL_SPEED ),
BOSS_1_ROCKET_LAUNCHER );
addEnemy( boss );
break;
}
// Miniboss
case 2:
{
boss = new Enemy( Vector2D( SCREEN_WIDTH / 2 , -100 ),
Vector2D( 0, SCROLL_SPEED ), BOSS_2 );
addEnemy( boss );
break;
}
default:
{
cout << "Enemys::bossTime: unexpected bossNr: " << bossNr << endl;
break;
}
}
}
void Enemys::generateEnemys( int dT ) {
if ( bossActive != 0 ) return;
timeToNextFormation -= dT;
if ( timeToNextFormation < 0 ) {
FormationTypes whichFormation = (FormationTypes)(rand() % NR_FORMATION_TYPES);
int flags = 0;
if ( rand() % 2 == 0 ) flags = flags | FORMATION_CHANGE_ON_KILL;
if ( rand() % 2 == 0 ) {
flags = flags | FORMATION_CHANGE_SPONTANEOUS;
if ( rand() % 2 == 0 ) flags = flags | FORMATION_CHANGE_OFTEN;
else flags = flags | FORMATION_CHANGE_SELDOM;
}
FormationShotPatterns shotPattern =
(FormationShotPatterns)getRandValue( FORMATION_SP_CHANCES, NR_FORMATION_SP );
Formation *newV =
new Formation( whichFormation,
Vector2D( 80 + (rand() % (SCREEN_WIDTH - 160)), -100 ),
Vector2D( 0, 40 ),
FORMATION_MAX_NR_ENEMYS[ whichFormation ] - (rand() % 3),
(FormationEnemySets)(rand() % NR_FORMATION_ENEMY_SETS),
flags, shotPattern );
formations.push_back( newV );
timeToNextFormation =
GENERATE_FORMATION_DELAY + (rand() % (GENERATE_FORMATION_RAND_DELAY + 1));
}
timeToNextEnemy -= dT;
if ( timeToNextEnemy < 0 ) {
int enemyType = getRandValue( ENEMY_APPEAR_CHANCES, NR_ENEMY_TYPES_NORMAL );
Enemy *newOne = 0;
switch ((EnemyTypes)enemyType) {
case FIGHTER:
{
bool collides;
float xpos;
for ( int i = 0; i < 10; i++ ) {
collides = false;
xpos = 20 + rand() % (SCREEN_WIDTH - 40);
// check if collides with a formation
for ( unsigned int f = 0; f < formations.size(); f++ ) {
Vector2D formationCenter = formations[ f ]->getCenter();
collides =
formationCenter.getY() < 150 &&
fabs(xpos - formationCenter.getX()) < 150;
if (collides) break;
}
}
if ( !collides ) {
newOne = new Enemy( Vector2D( xpos, -20 ), // position
Vector2D( (rand() % 5) - 2, rand() % 7 + 3 ) * 10, // velocity
FIGHTER );
}
break;
}
case BOMBER:
{
bool collides;
float xpos;
for ( int i = 0; i < 10; i++ ) {
collides = false;
xpos = 20 + rand() % (SCREEN_WIDTH - 40);
// check if collides with a formation
for ( unsigned int f = 0; f < formations.size(); f++ ) {
Vector2D formationCenter = formations[ f ]->getCenter();
collides =
formationCenter.getY() < 150 &&
fabs(xpos - formationCenter.getX()) < 150;
if (collides) break;
}
}
if ( !collides ) {
newOne = new Enemy( Vector2D( xpos, -20 ), // position
Vector2D( (rand() % 5) - 2, rand() % 3 + 3 ) * 10, // velocity
BOMBER );
}
break;
}
case TANK:
{
// SdlCompat_AcceleratedSurface *spriteTank = surfaceDB.loadSurface( FN_ENEMY_TANK );
// SdlCompat_AcceleratedSurface *spriteTankWreck = surfaceDB.loadSurface( FN_WRECK_TANK );
string fn1, fn2;
levelConf->getStr( LVL_ENEMY_TANK, fn1 );
levelConf->getStr( LVL_WRECK_TANK, fn2 );
SdlCompat_AcceleratedSurface *spriteTank = surfaceDB.loadSurface( fn1 );
SdlCompat_AcceleratedSurface *spriteTankWreck = surfaceDB.loadSurface( fn2 );
int halfWidthTank = spriteTank->w / 2;
int halfHeightTank = spriteTank->h / 2;
int halfWidthTankWreck = spriteTankWreck->w / 2;
int halfHeightTankWreck = spriteTankWreck->h / 2;
int xPos;
for ( int i = 0; i < 10; i++ ) {
bool collides = false;
xPos = halfWidthTank + rand() % (SCREEN_WIDTH - spriteTank->w);
// check if collides with another tank
for ( unsigned int t = 0; t < enemys.size(); t++ ) {
if ( enemys[ t ]->getType() == TANK ) {
Vector2D enemyTankPos = enemys[ t ]->getPos();
collides =
!(enemyTankPos.getX() - halfWidthTank > xPos + halfWidthTank) &&
!(enemyTankPos.getX() + halfWidthTank < xPos - halfWidthTank) &&
!(enemyTankPos.getY() - halfHeightTank > 0);
if (collides) break;
}
}
if (!collides) {
// check if collides with an old wreck
for ( unsigned int w = 0; w < wrecks->getNrWrecks(); w++ ) {
if ( wrecks->getWreck( w )->getType() == WRECK_TANK ) {
Vector2D wreckPos = wrecks->getWreck(w)->getPos();
collides =
!(wreckPos.getX() - halfWidthTankWreck > xPos + halfWidthTank) &&
!(wreckPos.getX() + halfWidthTankWreck < xPos - halfWidthTank) &&
!(wreckPos.getY() - halfHeightTankWreck > 0);
if (collides) break;
}
}
}
// no collision -> generate this enemy
if ( !collides ) {
// the tank and the background have to be at the same pixel-fraction
// to avoid a waggle-effect
float correlateToBackground = actBackgroundPos - truncf(actBackgroundPos);
newOne = new Enemy( Vector2D( xPos, -halfHeightTank - correlateToBackground ),
Vector2D (0, SCROLL_SPEED), // tanks are not moving
TANK );
break;
}
}
break;
}
default:
{
cout << "generateEnemys(): unexpected enemyType: " << enemyType << endl;
break;
}
}
addEnemy( newOne );
// +1 for security
timeToNextEnemy = GENERATE_ENEMY_DELAY + (rand() % (GENERATE_ENEMY_RAND_DELAY+1));
}
}
void Enemys::updateEnemys( int dT ) {
vector<Formation *>::iterator f;
for (f = formations.begin(); f != formations.end(); ++f) {
(*f)->update( dT );
}
vector<Enemy *>::iterator i;
for (i = enemys.begin(); i != enemys.end(); ++i) {
(*i)->update( dT );
}
}
void Enemys::doNukeDamage() {
vector<Enemy *>::iterator i;
for (i = enemys.begin(); i != enemys.end(); ++i) {
(*i)->doDamage( SPECIAL_SHOT_NUKE, -1 );
}
}
void Enemys::deleteExpiredEnemys() {
unsigned int i = 0;
while ( i < enemys.size() ) {
if ( enemys[i]->isExpired() ) {
if ( enemys[i]->isDead() ) {
enemysKilled++;
if ( arcadeGame ) {
if ( enemysKilled % 50 == 0 ) {
banners->addBanner( BANNER_ENEMYS_KILLED,
BANNER_MODE_RANDOM,
ARCADE_BONUS_FOR_ENEMYS_KILLED );
racers->receivePointsArcade( ARCADE_POINTS_FOR_ENEMYS_KILLED );
}
}
}
for ( unsigned int f = 0; f < formations.size(); f++ ) {
formations[f]->enemyKilled( enemys[i] );
}
delete enemys[i];
enemys.erase(enemys.begin() + i);
} else {
i++;
}
}
unsigned int f = 0;
while ( f < formations.size() ) {
if ( formations[f]->isExpired() ) {
// assert, that the formation is not deleted, because all
// enemys in the formation flew out of the screen
if ( arcadeGame && formations[f]->getCenter().getY() < SCREEN_HEIGHT + 400 ) {
banners->addBanner( (BannerTexts)(rand() % NR_BANNER_TEXTS),
BANNER_MODE_RANDOM,
ARCADE_BONUS_FOR_FORMATION_DESTRUCTION );
racers->receivePointsArcade( ARCADE_POINTS_FOR_FORMATION_DESTRUCTION );
}
delete formations[f];
formations.erase(formations.begin() + f);
} else {
f++;
}
}
}
void Enemys::drawGroundEnemys(SdlCompat_AcceleratedSurface *screen) {
vector<Enemy *>::iterator i;
for (i = enemys.begin(); i != enemys.end(); ++i) {
(*i)->drawGroundEnemy(screen);
}
}
void Enemys::drawAirEnemys(SdlCompat_AcceleratedSurface *screen) {
vector<Enemy *>::iterator i;
for (i = enemys.begin(); i != enemys.end(); ++i) {
(*i)->drawAirEnemy(screen);
}
}
void Enemys::drawShadows(SdlCompat_AcceleratedSurface *screen) {
vector<Enemy *>::iterator i;
for (i = enemys.begin(); i != enemys.end(); ++i) {
(*i)->drawShadow(screen);
}
}
void Enemys::drawBossStats( SdlCompat_AcceleratedSurface *screen ) {
for ( unsigned int i = 0; i < enemys.size(); i++ ) {
if ( enemys[ i ]->getType() >= NR_ENEMY_TYPES_NORMAL ) {
enemys[ i ]->drawStats( screen );
}
}
}
void Enemys::drawAllStats( SdlCompat_AcceleratedSurface *screen ) {
for ( unsigned int i = 0; i < enemys.size(); i++ ) {
enemys[ i ]->drawStats( screen );
}
}

View File

@@ -1,77 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 ENEMYS_H
#define ENEMYS_H
#include <vector>
#include "SDL.h"
class Enemy;
class Formation;
class Enemys {
std::vector<Enemy *> enemys;
std::vector<Formation *> formations;
int timeToNextEnemy;
int timeToNextFormation;
// if != 0, only the enemys for this boss are generated
int bossActive;
int enemysGenerated;
int enemysKilled;
public:
Enemys();
~Enemys();
void addEnemy( Enemy *newEnemy );
bool minibossDead();
bool bossDead();
void bossTime( int bossNr );
void generateEnemys( int dT );
void deleteExpiredEnemys();
inline Enemy *getEnemy(unsigned int i) { return enemys[i]; }
inline unsigned int getNrEnemys() { return enemys.size(); }
inline int getNrEnemysKilled() { return enemysKilled; }
inline int getNrEnemysGenerated() { return enemysGenerated; }
// move and shoot
void updateEnemys( int dT );
// a nuke exploded -> damage all enemys
void doNukeDamage();
// draws the enemys.
void drawGroundEnemys( SdlCompat_AcceleratedSurface *screen );
void drawAirEnemys( SdlCompat_AcceleratedSurface *screen );
void drawShadows( SdlCompat_AcceleratedSurface *screen );
void drawBossStats( SdlCompat_AcceleratedSurface *screen );
void drawAllStats( SdlCompat_AcceleratedSurface *screen );
};
#endif

View File

@@ -1,109 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include "explosion.h"
#include "surfaceDB.h"
#include "mixer.h"
#include "global.h"
Explosion::Explosion(string fn, const Vector2D &position,
const Vector2D &velocity, const ExplosionTypes &explosionType) {
sprite = surfaceDB.loadSurface(fn, true);
nrAnimStages = sprite->w / sprite->h;
expired = false;
sndExplosion = Mixer::mixer().loadSample( FN_SOUND_EXPLOSION_NORMAL );
Mixer::mixer().playSample( sndExplosion, 0 );
this->explosionType = explosionType;
pos = position;
vel = velocity;
switch (explosionType) {
case EXPLOSION_NORMAL_AIR:
case EXPLOSION_NORMAL_GROUND:
{
timePerStage = LIFETIME_EXPL_NORMAL / nrAnimStages;
break;
}
default:
{
timePerStage = 0;
actAnimStage = nrAnimStages;
break;
}
}
actAnimStage = 0;
timeLived = 0;
timeNextAnimStage = timePerStage;
}
Explosion::~Explosion() {}
void Explosion::update( int dT ) {
if ( scrollingOn ) pos += vel * dT / 1000.0;
timeLived += dT;
if ( timeLived > timeNextAnimStage ) {
timeNextAnimStage += timePerStage;
actAnimStage++;
if (actAnimStage == nrAnimStages) expired = true;
}
}
void Explosion::drawAirExplosion(SdlCompat_AcceleratedSurface *screen) {
if (expired) return;
if ( ! ( explosionType == EXPLOSION_NORMAL_AIR ) ) return;
SDL_Rect dest;
dest.x = lroundf(pos.getX()) - sprite->w / (2*nrAnimStages);
dest.y = lroundf(pos.getY()) - sprite->h / 2;
dest.w = sprite->w / nrAnimStages;
dest.h = sprite->h;
SDL_Rect src;
src.x = actAnimStage * sprite->w / nrAnimStages;
src.y = 0;
src.w = sprite->w / nrAnimStages;
src.h = sprite->h;
SDL_BlitSurface( sprite, &src, screen, &dest );
}
void Explosion::drawGroundExplosion(SdlCompat_AcceleratedSurface *screen) {
if (expired) return;
if ( ! ( explosionType == EXPLOSION_NORMAL_GROUND ) ) return;
SDL_Rect dest;
dest.x = lroundf(pos.getX()) - sprite->w / (2*nrAnimStages);
dest.y = lroundf(pos.getY()) - sprite->h / 2;
dest.w = sprite->w / nrAnimStages;
dest.h = sprite->h;
SDL_Rect src;
src.x = actAnimStage * sprite->w / nrAnimStages;
src.y = 0;
src.w = sprite->w / nrAnimStages;
src.h = sprite->h;
SDL_BlitSurface( sprite, &src, screen, &dest );
}

View File

@@ -1,65 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 EXPLOSION_H
#define EXPLOSION_H
#include "SDL.h"
#include "geometry.h"
#include <string>
#include "global.h"
class Explosion {
// a sprite, that contains horizontally all animationframes of the explosion.
// it is assumed, that every frame is quadratic.
SdlCompat_AcceleratedSurface *sprite;
// how many frames does this explosion have?
int nrAnimStages;
// which frame is now?
int actAnimStage;
// how long should one frame last (ms)
int timePerStage;
// how long is the current explosion already active
int timeLived;
// at what timeLived starts the next frame?
int timeNextAnimStage;
// the explosion can be deleted
bool expired;
int sndExplosion;
Vector2D pos;
Vector2D vel; // the explosion moves - yeah
ExplosionTypes explosionType;
public:
Explosion(string fn, const Vector2D &position,
const Vector2D &velocity, const ExplosionTypes &explosionType);
~Explosion();
// updates the position and the counters
void update( int dT );
void drawAirExplosion(SdlCompat_AcceleratedSurface *screen);
void drawGroundExplosion(SdlCompat_AcceleratedSurface *screen);
bool isExpired() { return expired; }
};
#endif

View File

@@ -1,72 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include "explosions.h"
#include "explosion.h"
Explosions::Explosions() {
}
Explosions::~Explosions() {
vector<Explosion *>::iterator i;
for (i = explosions.begin(); i != explosions.end(); ++i) {
delete *i;
}
}
void Explosions::addExplosion(Explosion *explosion) {
if (explosion) {
explosions.push_back(explosion);
}
}
void Explosions::drawAirExplosions(SdlCompat_AcceleratedSurface *screen) {
vector<Explosion *>::iterator i;
for (i = explosions.begin(); i != explosions.end(); ++i) {
(*i)->drawAirExplosion(screen);
}
}
void Explosions::drawGroundExplosions(SdlCompat_AcceleratedSurface *screen) {
vector<Explosion *>::iterator i;
for (i = explosions.begin(); i != explosions.end(); ++i) {
(*i)->drawGroundExplosion(screen);
}
}
void Explosions::updateExplosions( int dT ) {
vector<Explosion *>::iterator i;
for (i = explosions.begin(); i != explosions.end(); ++i) {
(*i)->update( dT );
}
}
void Explosions::expireExplosions() {
unsigned int i = 0;
while ( i < explosions.size() ) {
if ( explosions[i]->isExpired() ) {
delete explosions[i];
explosions.erase(explosions.begin() + i);
} else {
i++;
}
}
}

View File

@@ -1,49 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 EXPLOSIONS_H
#define EXPLOSIONS_H
#include <vector>
#include "SDL.h"
#include "SdlForwardCompat.h"
class Explosion;
/* manages the explosion-objects */
class Explosions {
vector<Explosion *> explosions;
public:
Explosions();
~Explosions();
inline unsigned int getNrExplosions() { return explosions.size(); }
void addExplosion( Explosion *explosion );
// moves the explosions and updates the counters
void updateExplosions( int dT );
// deletes the explosions, that have timed out
void expireExplosions();
// draws all explosions
void drawAirExplosions( SdlCompat_AcceleratedSurface *screen );
void drawGroundExplosions( SdlCompat_AcceleratedSurface *screen );
};
#endif

View File

@@ -1,158 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include "font.h"
#include "global.h"
#include "surfaceDB.h"
#include <iostream>
Font::Font(string fn) {
sprites[0] = surfaceDB.loadSurface( fn + "-1.bmp" );
sprites[1] = surfaceDB.loadSurface( fn + "-2.bmp" );
sprites[2] = surfaceDB.loadSurface( fn + "-3.bmp" );
charset = " ABCDEFGHIJKLMNOPQRSTUVWXYZÜÄÖabcdefghijklmnopqrstuvwxyzüäöß0123456789!\"§$%&/()=?*+'#,.-;:_@°\\";
// 94 Zeichen
charWidth = sprites[0]->w / MAX_CHARS_PER_TEXTURE;
charHeight = sprites[0]->h;
}
Font::~Font() {
;
}
void Font::setCharWidth(int width) {
charWidth = width;
}
int Font::getCharWidth() {
return charWidth;
}
int Font::getCharHeight() {
return sprites[0]->h;
}
void Font::drawInt(SdlCompat_AcceleratedSurface *screen, int posx, int posy, int val, int alignDigitCnt, int flags) {
int indent = 0;
int digitCnt = 1;
int i=1;
while ( val >= i*10 ) {
digitCnt++;
i *= 10;
}
// cout << endl << "drawInt.val=" << val << endl;
// cout << "drawInt.digitCnt=" << digitCnt << endl;
// cout << "drawInt.alignDigitCnt-old=" << alignDigitCnt << endl;
if (alignDigitCnt < digitCnt) {
alignDigitCnt = digitCnt;
}
// cout << "drawInt.alignDigitCnt-new=" << alignDigitCnt << endl;
if (flags & FONT_ALIGN_CENTERED) {
indent = -(alignDigitCnt * charWidth) / 2;
}
if (flags & FONT_ALIGN_RIGHT) {
indent = -(alignDigitCnt * charWidth);
}
SDL_Rect destR;
SDL_Rect srcR;
while (alignDigitCnt > 0) {
if ((digitCnt > 0) ||
((flags & FONT_ALIGN_FILL_ZERO) != 0)) {
destR.x = indent + posx + (alignDigitCnt-1) * charWidth;
destR.y = posy;
destR.w = charWidth;
destR.h = charHeight;
unsigned int charsetpos = charset.find( (char)((val % 10) + '0') );
if (charsetpos == string::npos )
charsetpos = 0; // Space
srcR.x = (charsetpos % MAX_CHARS_PER_TEXTURE) * charWidth;
// srcR.x = (1 + 2*26 + (val % 10)) * charWidth;
srcR.y = 0;
srcR.w = charWidth;
srcR.h = charHeight;
SDL_BlitSurface( sprites[charsetpos / MAX_CHARS_PER_TEXTURE], &srcR, screen, &destR );
}
val /= 10;
digitCnt--;
alignDigitCnt--;
}
}
void Font::drawStr(SdlCompat_AcceleratedSurface *screen, int posx, int posy, const string &text, int flags) {
int indent = 0;
if ( flags & (FONT_ALIGN_CENTERED | FONT_ALIGN_RIGHT) ) {
for(unsigned int i=0; i < text.size(); ++i) {
if (!(flags & FONT_MONOSPACE) && text[i] == ' ') {
indent += ((charWidth * 2) / 3);
} else {
indent += charWidth;
}
}
if (flags & FONT_ALIGN_CENTERED) {
indent = -indent / 2;
} else {
indent = -indent;
}
}
SDL_Rect destR;
SDL_Rect srcR;
int x = 0;
unsigned int charsetpos;
for(unsigned int i=0; i < text.size(); ++i) {
x = 0;
charsetpos = charset.find(text[i]);
if (charsetpos == string::npos )
charsetpos = 0; // Space
x = (charsetpos % MAX_CHARS_PER_TEXTURE) * charWidth;
destR.x = posx + indent;
destR.y = posy;
destR.w = charWidth;
destR.h = sprites[0]->h;
srcR.x = x;
srcR.y = 0;
srcR.w = charWidth;
srcR.h = sprites[0]->h;
SDL_BlitSurface( sprites[charsetpos / MAX_CHARS_PER_TEXTURE], &srcR, screen, &destR );
if (!(flags & FONT_MONOSPACE) && text[i] == ' ') {
posx += ((charWidth * 2) / 3);
} else {
posx += charWidth;
}
}
}

View File

@@ -1,79 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 FONT_H
#define FONT_H
#include "SDL.h"
#include <string>
#include "SdlForwardCompat.h"
// *** Code ***
//
// font->drawStr( screen, 150, 260, "Zeile 1" );
// font->drawStr( screen, 150, 290, "Zeile 2", FONT_ALIGN_CENTERED );
// font->drawStr( screen, 150, 320, "Zeile 3", FONT_ALIGN_RIGHT );
// font->drawInt( screen, 150, 350, 123, 0 );
// font->drawInt( screen, 150, 380, 123, 0, FONT_ALIGN_FILL_ZERO );
// font->drawInt( screen, 150, 410, 123, 6 );
// font->drawInt( screen, 150, 440, 123, 6, FONT_ALIGN_FILL_ZERO );
// font->drawInt( screen, 150, 400, 123, 6, FONT_ALIGN_CENTERED );
// font->drawInt( screen, 150, 425, 123, 6, FONT_ALIGN_CENTERED | FONT_ALIGN_FILL_ZERO );
// font->drawInt( screen, 150, 350, 123, 6, FONT_ALIGN_RIGHT );
// font->drawInt( screen, 150, 375, 123, 6, FONT_ALIGN_RIGHT | FONT_ALIGN_FILL_ZERO );
//
// *** Result ***
//
// Zeile 1
// Zeile 2
// Zeile 3
// 123
// 123
// 123
// 000123
// 123
// 000123
// 123
// 000123
const int FONT_ALIGN_FILL_ZERO = (1<<0); // fill with leading zeros
const int FONT_ALIGN_CENTERED = (1<<1); // text centered around posx/posy
const int FONT_ALIGN_RIGHT = (1<<2); // text aligned right (on the left side of posx)
const int FONT_MONOSPACE = (1<<3);
class Font {
private:
enum { MAX_CHARS_PER_TEXTURE = 32 }; // OpenGL ES does not allow textures wider than 1024 bytes, so we have to split it
SdlCompat_AcceleratedSurface *sprites[3]; // Our font has only 94 letters
int charWidth;
int charHeight;
std::string charset;
public:
Font(std::string fn);
~Font();
void setCharWidth(int width);
int getCharWidth();
int getCharHeight();
void drawInt(SdlCompat_AcceleratedSurface *screen, int posx, int posy, int val, int alignDigitCnt, int flags = 0);
void drawStr(SdlCompat_AcceleratedSurface *screen, int posx, int posy, const std::string &text, int flags = 0);
};
#endif

View File

@@ -1,645 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 "formation.h"
#include "enemy.h"
#include "enemys.h"
#include <iostream>
using namespace std;
Formation::Formation( FormationTypes whichFormation, Vector2D centerAtStart,
Vector2D startVel, int nrEnemys,
FormationEnemySets enemyTypes,
int flagsFormationChangePolicy,
FormationShotPatterns shotPattern ) {
formationType = whichFormation;
formationCenter = centerAtStart;
formationSpeed = startVel;
changeOnKill = flagsFormationChangePolicy & FORMATION_CHANGE_ON_KILL;
changeSpontaneous = flagsFormationChangePolicy & FORMATION_CHANGE_SPONTANEOUS;
changeOften = flagsFormationChangePolicy & FORMATION_CHANGE_OFTEN;
changeSeldom = flagsFormationChangePolicy & FORMATION_CHANGE_SELDOM;
if ( changeSpontaneous && !changeSeldom && !changeOften ) changeSeldom = true;
if ( changeOften ) {
nextFormationChange =
FORMATION_CHANGE_OFTEN_DELAY +
rand() % (FORMATION_CHANGE_OFTEN_RAND_DELAY+1);
} else if ( changeSeldom ) {
nextFormationChange =
FORMATION_CHANGE_SELDOM_DELAY +
rand() % (FORMATION_CHANGE_SELDOM_RAND_DELAY+1);
}
if ( nrEnemys > FORMATION_MAX_NR_ENEMYS[ formationType ] )
nrInvolved = FORMATION_MAX_NR_ENEMYS[ formationType ];
else if ( nrEnemys < 0 ) nrInvolved = 0;
else nrInvolved = nrEnemys;
this->shotPattern = shotPattern;
actShootingEnemy = 0;
if ( shotPattern == FORMATION_SP_NONE ) formationFires = false;
else formationFires = true;
vector<Vector2D> targetPos;
fillTargetPos( targetPos );
for ( int i = 0; i < nrInvolved; i++ ) {
Enemy *newOne;
switch ( enemyTypes ) {
case FORMATION_ENEMY_SET_DEFAULT:
case FORMATION_ENEMY_SET_FIGHTER:
{
newOne = new Enemy( formationCenter + targetPos[ i ], formationSpeed, FIGHTER,
true, formationFires );
break;
}
case FORMATION_ENEMY_SET_BOMBER:
{
newOne = new Enemy( formationCenter + targetPos[ i ], formationSpeed, BOMBER,
true, formationFires );
break;
}
case FORMATION_ENEMY_SET_FIGHTER_BOMBER:
{
newOne =
new Enemy( formationCenter + targetPos[ i ], formationSpeed,
(EnemyTypes)(FIGHTER + (i % 2)),
true, formationFires );
break;
}
}
enemys->addEnemy( newOne );
involvedEnemys.push_back( newOne );
}
enemyWasKilled = false;
// wait at least 100 ms before the first shot
nextFirePrimary = 100;
nextFireSecondary = 100;
// cout << "Type: " << formationType << " SP: " << shotPattern << endl;
}
Formation::~Formation() {}
void Formation::enemyKilled( Enemy *killedEnemy ) {
for ( int i = 0; i < nrInvolved; i++ ) {
if ( involvedEnemys[i] == killedEnemy ) {
enemyWasKilled = true;
involvedEnemys.erase( involvedEnemys.begin() + i );
nrInvolved--;
break;
}
}
}
void Formation::update( int dT ) {
if ( changeSpontaneous ) handleSpontaneousFormationChange( dT );
if ( enemyWasKilled ) {
// change the formation?
if ( changeOnKill && (rand() % 100 < 70) ) chooseNewFormationType();
moveEnemyInFormation();
enemyWasKilled = false;
}
formationCenter += formationSpeed * dT / 1000.0;
shoot( dT );
}
void Formation::handleSpontaneousFormationChange( int dT ) {
nextFormationChange -= dT;
if ( changeSpontaneous && nextFormationChange < 0 ) {
chooseNewFormationType();
moveEnemyInFormation();
if ( changeOften ) {
nextFormationChange =
FORMATION_CHANGE_OFTEN_DELAY +
rand() % (FORMATION_CHANGE_OFTEN_RAND_DELAY+1);
} else if ( changeSeldom ) {
nextFormationChange =
FORMATION_CHANGE_SELDOM_DELAY +
rand() % (FORMATION_CHANGE_SELDOM_RAND_DELAY+1);
}
}
}
void Formation::moveEnemyInFormation() {
// calc the target positions in the new formation (relative to the center of the formation)
vector<Vector2D> targetPos;
fillTargetPos( targetPos );
// choose the best mapping from enemy to targetPosition
// (shortest way for enemy to its position is best)
vector<Vector2D> relPosForEnemies;
getBestMapping( targetPos, relPosForEnemies );
// give the enemy its order
for ( int i = 0; i < nrInvolved; i++ ) {
involvedEnemys[i]->setNewRelTargetPos( relPosForEnemies[ i ] );
}
}
void Formation::chooseNewFormationType() {
bool found = false;
int i = 0;
while ( i < 10 && !found ) {
FormationTypes newFormationType = (FormationTypes)(rand() % (NR_FORMATION_TYPES-1));
if ( formationType == newFormationType ) {
newFormationType = (FormationTypes)(NR_FORMATION_TYPES - 1);
}
if ( nrInvolved <= FORMATION_MAX_NR_ENEMYS[ newFormationType ] ) {
formationType = newFormationType;
found = true;
}
i++;
}
}
void Formation::fillTargetPos( vector<Vector2D> &targetPos ) {
switch ( formationType ) {
case FORMATION_V:
{
fillTargetPosFormationV( targetPos );
break;
}
case FORMATION_REVERSE_V:
{
fillTargetPosFormationReverseV( targetPos );
break;
}
case FORMATION_BLOCK:
{
fillTargetPosFormationBlock( targetPos );
break;
}
case FORMATION_LINE:
{
fillTargetPosFormationLine( targetPos );
break;
}
default:
{
for ( int i = 0; i < nrInvolved; i++ ) {
targetPos.push_back( Vector2D(0,0) );
}
break;
}
}
}
void Formation::fillTargetPosFormationV( vector<Vector2D> &targetPos ) {
switch ( nrInvolved ) {
case 1:
{
targetPos.push_back( Vector2D(0,0) );
break;
}
case 2:
{
targetPos.push_back( Vector2D(-30,0) );
targetPos.push_back( Vector2D(30,0) );
break;
}
case 3:
{
targetPos.push_back( Vector2D(-50,25) );
targetPos.push_back( Vector2D(0,-25) );
targetPos.push_back( Vector2D(50,25) );
break;
}
case 4:
{
targetPos.push_back( Vector2D(-80,25) );
targetPos.push_back( Vector2D(-30,-25) );
targetPos.push_back( Vector2D(30,-25) );
targetPos.push_back( Vector2D(80,25) );
break;
}
case 5:
{
targetPos.push_back( Vector2D(-100,50) );
targetPos.push_back( Vector2D(-50,0) );
targetPos.push_back( Vector2D(0,-50) );
targetPos.push_back( Vector2D(50,0) );
targetPos.push_back( Vector2D(100,50) );
break;
}
case 6:
{
targetPos.push_back( Vector2D(-130,50) );
targetPos.push_back( Vector2D(-80,0) );
targetPos.push_back( Vector2D(-30,-50) );
targetPos.push_back( Vector2D(30,-50) );
targetPos.push_back( Vector2D(80,0) );
targetPos.push_back( Vector2D(130,50) );
break;
}
case 7:
{
targetPos.push_back( Vector2D(-150,75) );
targetPos.push_back( Vector2D(-100,25) );
targetPos.push_back( Vector2D(-50,-25) );
targetPos.push_back( Vector2D(0,-75) );
targetPos.push_back( Vector2D(50,-25) );
targetPos.push_back( Vector2D(100,25) );
targetPos.push_back( Vector2D(150,75) );
break;
}
default:
{
cout << "fillTargetPosFormationV: too many enemys involved: " << nrInvolved << endl;
for ( int i = 0; i < nrInvolved; i++ ) {
targetPos.push_back( Vector2D(0,0) );
}
break;
}
}
}
void Formation::fillTargetPosFormationReverseV( vector<Vector2D> &targetPos ) {
switch ( nrInvolved ) {
case 1:
{
targetPos.push_back( Vector2D(0,0) );
break;
}
case 2:
{
targetPos.push_back( Vector2D(-30,0) );
targetPos.push_back( Vector2D(30,0) );
break;
}
case 3:
{
targetPos.push_back( Vector2D(-50,-25) );
targetPos.push_back( Vector2D(0,25) );
targetPos.push_back( Vector2D(50,-25) );
break;
}
case 4:
{
targetPos.push_back( Vector2D(-80,-25) );
targetPos.push_back( Vector2D(-30,25) );
targetPos.push_back( Vector2D(30,25) );
targetPos.push_back( Vector2D(80,-25) );
break;
}
case 5:
{
targetPos.push_back( Vector2D(-100,-50) );
targetPos.push_back( Vector2D(-50,0) );
targetPos.push_back( Vector2D(0,50) );
targetPos.push_back( Vector2D(50,0) );
targetPos.push_back( Vector2D(100,-50) );
break;
}
case 6:
{
targetPos.push_back( Vector2D(-130,-50) );
targetPos.push_back( Vector2D(-80,0) );
targetPos.push_back( Vector2D(-30,50) );
targetPos.push_back( Vector2D(30,50) );
targetPos.push_back( Vector2D(80,0) );
targetPos.push_back( Vector2D(130,-50) );
break;
}
case 7:
{
targetPos.push_back( Vector2D(-150,-75) );
targetPos.push_back( Vector2D(-100,-25) );
targetPos.push_back( Vector2D(-50,25) );
targetPos.push_back( Vector2D(0,75) );
targetPos.push_back( Vector2D(50,25) );
targetPos.push_back( Vector2D(100,-25) );
targetPos.push_back( Vector2D(150,-75) );
break;
}
default:
{
cout << "fillTargetPosFormationReverseV: too many enemys involved: "
<< nrInvolved << endl;
for ( int i = 0; i < nrInvolved; i++ ) {
targetPos.push_back( Vector2D(0,0) );
}
break;
}
}
}
void Formation::fillTargetPosFormationBlock( vector<Vector2D> &targetPos ) {
switch ( nrInvolved ) {
case 1:
{
targetPos.push_back( Vector2D(0,0) );
break;
}
case 2:
{
targetPos.push_back( Vector2D(-30,0) );
targetPos.push_back( Vector2D(30,0) );
break;
}
case 3:
{
targetPos.push_back( Vector2D(-30,25) );
targetPos.push_back( Vector2D(0,-25) );
targetPos.push_back( Vector2D(30,25) );
break;
}
case 4:
{
targetPos.push_back( Vector2D(-30,-25) );
targetPos.push_back( Vector2D(-30,25) );
targetPos.push_back( Vector2D(30,-25) );
targetPos.push_back( Vector2D(30,25) );
break;
}
case 5:
{
targetPos.push_back( Vector2D(-40,-30) );
targetPos.push_back( Vector2D(-40,30) );
targetPos.push_back( Vector2D(0,0) );
targetPos.push_back( Vector2D(40,-30) );
targetPos.push_back( Vector2D(40,30) );
break;
}
case 6:
{
targetPos.push_back( Vector2D(-60,-30) );
targetPos.push_back( Vector2D(-60,30) );
targetPos.push_back( Vector2D(0,-30) );
targetPos.push_back( Vector2D(0,30) );
targetPos.push_back( Vector2D(60,-30) );
targetPos.push_back( Vector2D(60,30) );
break;
}
case 7:
{
targetPos.push_back( Vector2D(-60,-50) );
targetPos.push_back( Vector2D(-60,0) );
targetPos.push_back( Vector2D(0,-50) );
targetPos.push_back( Vector2D(0,0) );
targetPos.push_back( Vector2D(0,50) );
targetPos.push_back( Vector2D(60,-50) );
targetPos.push_back( Vector2D(60,0) );
break;
}
default:
{
cout << "fillTargetPosFormationBlock: too many enemys involved: " << nrInvolved << endl;
for ( int i = 0; i < nrInvolved; i++ ) {
targetPos.push_back( Vector2D(0,0) );
}
break;
}
}
}
void Formation::fillTargetPosFormationLine( vector<Vector2D> &targetPos ) {
switch ( nrInvolved ) {
case 1:
{
targetPos.push_back( Vector2D(0,0) );
break;
}
case 2:
{
targetPos.push_back( Vector2D(-30,0) );
targetPos.push_back( Vector2D(30,0) );
break;
}
case 3:
{
targetPos.push_back( Vector2D(-60,0) );
targetPos.push_back( Vector2D(0,0) );
targetPos.push_back( Vector2D(60,0) );
break;
}
case 4:
{
targetPos.push_back( Vector2D(-90,0) );
targetPos.push_back( Vector2D(-30,0) );
targetPos.push_back( Vector2D(30,0) );
targetPos.push_back( Vector2D(90,0) );
break;
}
case 5:
{
targetPos.push_back( Vector2D(-120,0) );
targetPos.push_back( Vector2D(-60,0) );
targetPos.push_back( Vector2D(0,0) );
targetPos.push_back( Vector2D(60,0) );
targetPos.push_back( Vector2D(120,0) );
break;
}
case 6:
{
targetPos.push_back( Vector2D(-150,0) );
targetPos.push_back( Vector2D(-90,0) );
targetPos.push_back( Vector2D(-30,0) );
targetPos.push_back( Vector2D(30,0) );
targetPos.push_back( Vector2D(90,0) );
targetPos.push_back( Vector2D(150,0) );
break;
}
default:
{
cout << "fillTargetPosFormationLine: too many enemys involved: " << nrInvolved << endl;
for ( int i = 0; i < nrInvolved; i++ ) {
targetPos.push_back( Vector2D(0,0) );
}
break;
}
}
}
///////////////////////////////////////////////
void Formation::getBestMapping( vector<Vector2D> &targetPos,
vector<Vector2D> &relPosForFighters ) {
int actPerm[nrInvolved];
vector<Vector2D> *bestMapping = new vector<Vector2D>();
vector<Vector2D> *testMapping = new vector<Vector2D>();
for ( int i = 0; i < nrInvolved; i++ ) {
bestMapping->push_back( Vector2D( 0,0 ) );
testMapping->push_back( Vector2D( 0,0 ) );
actPerm[ i ] = i;
}
float mapCost = 1000000;
int nrPerm = factorial( nrInvolved );
for ( int perm = 0; perm < nrPerm; perm++ ) {
calcNextPerm( actPerm );
float testMappingCost = calcTestMapping( actPerm, targetPos, testMapping );
if ( mapCost > testMappingCost ) {
vector<Vector2D> *tmpMapping = bestMapping;
bestMapping = testMapping;
testMapping = tmpMapping;
mapCost = testMappingCost;
}
}
for ( int e = 0; e < nrInvolved; e++ ) {
relPosForFighters.push_back( (*bestMapping)[e] );
}
delete bestMapping;
delete testMapping;
}
void Formation::calcNextPerm( int *perm ) {
int n = nrInvolved;
int i = n-1;
int j = n;
int tmp;
while ( i != 0 && perm[ i-1 ] >= perm[ i ] ) {
i--;
}
if ( i == 0 ) {
for ( int k = 0; k < n/2; k++ ) {
tmp = perm[ k ];
perm[ k ] = perm[ n - k - 1 ];
perm[ n - k - 1 ] = tmp;
}
return;
}
while ( perm[ j-1 ] <= perm[ i-1 ] ) {
--j;
}
tmp = perm[ i-1 ];
perm[ i-1 ] = perm[ j-1 ];
perm[ j-1 ] = tmp;
i++;
j = n;
while ( i < j ) {
tmp = perm[ i-1 ];
perm[ i-1 ] = perm[ j-1 ];
perm[ j-1 ] = tmp;
i++;
j--;
}
}
float Formation::calcTestMapping( int *perm, vector<Vector2D> &targetPos,
vector<Vector2D> *mapping ) {
float cost = 0;
for ( int i = 0; i < nrInvolved; i++ ) {
// enemy i shall fly to the position targetPos[perm[i]]
// save the vector from its actual pos to its new targetpos in mapping
(*mapping)[ i ] =
targetPos[ perm[i] ] + formationCenter -
involvedEnemys[ i ]->getPos();
if ( cost < (*mapping)[ i ].getLength() ) {
cost = (*mapping)[ i ].getLength();
}
}
return cost;
}
int Formation::factorial( int n ) {
int result = 1;
for ( int i = 2; i <= n; i++ ) {
result *= i;
}
return result;
}
void Formation::shoot( int dT ) {
if ( shotPattern == FORMATION_SP_NONE ) return;
nextFirePrimary -= dT;
// nextFireSecondary -= dT;
float enemyRatio = FORMATION_MAX_NR_ENEMYS[ formationType ] / (float)nrInvolved;
while ( nextFirePrimary < 0 ) {
switch ( shotPattern ) {
case FORMATION_SP_VOLLEY_FAST:
case FORMATION_SP_VOLLEY_MEDIUM:
case FORMATION_SP_VOLLEY_SLOW:
{
for ( int i = 0; i < nrInvolved; i++ ) {
involvedEnemys[ i ]->firePrimary();
}
break;
}
case FORMATION_SP_RAND_FAST:
case FORMATION_SP_RAND_MEDIUM:
case FORMATION_SP_RAND_SLOW:
{
involvedEnemys[ rand() % nrInvolved ]->firePrimary();
break;
}
case FORMATION_SP_LEFT_RIGHT_FAST:
case FORMATION_SP_LEFT_RIGHT_MEDIUM:
{
actShootingEnemy = (actShootingEnemy + 1) % nrInvolved;
involvedEnemys[ actShootingEnemy ]->firePrimary();
break;
}
case FORMATION_SP_RIGHT_LEFT_FAST:
case FORMATION_SP_RIGHT_LEFT_MEDIUM:
{
actShootingEnemy--;
if ( actShootingEnemy < 0 ) actShootingEnemy = nrInvolved-1;
involvedEnemys[ actShootingEnemy ]->firePrimary();
break;
}
default:
{
break;
}
}
nextFirePrimary +=
lroundf( (FORMATION_SP_PRIMARY_DELAY[ shotPattern ] +
rand() % (FORMATION_SP_PRIMARY_RAND_DELAY[ shotPattern ] + 1)) * enemyRatio );
}
}

View File

@@ -1,85 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 FORMATION_H
#define FORMATION_H
#include <vector>
#include "global.h"
#include "geometry.h"
class Enemy;
class Formation {
private:
std::vector<Enemy *> involvedEnemys;
int nrInvolved;
FormationTypes formationType;
Vector2D formationCenter;
Vector2D formationSpeed;
bool enemyWasKilled;
bool formationFires;
int nextFirePrimary;
int nextFireSecondary;
bool changeOnKill, changeSpontaneous, changeOften, changeSeldom;
int nextFormationChange;
FormationShotPatterns shotPattern;
int actShootingEnemy;
void chooseNewFormationType();
void handleSpontaneousFormationChange( int dT );
void moveEnemyInFormation();
void fillTargetPos( vector<Vector2D> &targetPos );
void fillTargetPosFormationV( vector<Vector2D> &targetPos );
void fillTargetPosFormationReverseV( vector<Vector2D> &targetPos );
void fillTargetPosFormationBlock( vector<Vector2D> &targetPos );
void fillTargetPosFormationLine( vector<Vector2D> &targetPos );
void getBestMapping( vector<Vector2D> &targetPos,
vector<Vector2D> &relPosForFighters );
void calcNextPerm( int *perm );
float calcTestMapping( int *perm, vector<Vector2D> &targetPos,
vector<Vector2D> *mapping );
int factorial( int n );
void shoot( int dT );
public:
Formation( FormationTypes whichFormation, Vector2D centerAtStart,
Vector2D startVel, int nrEnemys=66,
FormationEnemySets enemyTypes=FORMATION_ENEMY_SET_DEFAULT,
int flagsFormationChangePolicy=0,
FormationShotPatterns shotPattern=FORMATION_SP_NONE );
~Formation();
Vector2D getCenter() { return formationCenter; }
void enemyKilled( Enemy *killedEnemy );
void update( int dT );
bool isExpired() { return (nrInvolved == 0); }
};
#endif

View File

@@ -1,963 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sstream>
#include <android/log.h>
#include "SDL.h"
#include "mixer.h"
#include "game.h"
#include "surfaceDB.h"
#include "racers.h"
#include "racer.h"
#include "video.h"
#include "shots.h"
#include "shot.h"
#include "items.h"
#include "explosions.h"
#include "explosion.h"
#include "enemys.h"
#include "font.h"
#include "mixer.h"
#include "input.h"
#include "wrecks.h"
#include "wreck.h"
#include "global.h"
#include "settings.h"
#include "intro.h"
#include "setDifficulty.h"
#include "menuArcadeMode.h"
#include "asstring.h"
#include "sonic.h"
#include "banners.h"
#include "banner.h"
#include "smokePuffs.h"
#include "background.h"
#include "options.h"
Racers *racers = NULL;
Enemys *enemys = NULL;
Shots *shots = NULL;
Explosions *explosions = NULL;
Items *items = NULL;
Wrecks *wrecks = NULL;
Banners *banners = NULL;
SmokePuffs *smokePuffs = NULL;
Options *levelConf = NULL;
bool scrollingOn;
bool nukeIsInPlace;
bool playMusicOn;
bool onePlayerGame;
bool arcadeGame;
int difficultyLevel;
float actBackgroundPos;
Game::Game() {
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 1");
videoserver = new Video();
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 2");
screen = 0;
screen = videoserver->init();
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 3");
settings = new Settings();
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 4");
intro = new Intro( screen );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 5");
setDifficulty = new SetDifficulty( screen );
menuArcadeMode = new MenuArcadeMode( screen );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 6");
pauseSprite = surfaceDB.loadSurface( FN_PAUSED );
youLoseSprite = surfaceDB.loadSurface( FN_YOU_LOSE );
youWinSprite = surfaceDB.loadSurface( FN_YOU_WIN );
// for arcadeMode
gameOverSprite = surfaceDB.loadSurface( FN_GAME_OVER );
nukeEffectSurface = surfaceDB.loadSurface( FN_NUKE_EFFECT );
bossAlarm = Mixer::mixer().loadSample( FN_SOUND_BOSS_ALARM, 60 );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 7");
fontTime = new Font( FN_FONT_NUMBERS_TIME );
fontSizeTime = fontTime->getCharWidth();
racers = 0;
explosions = 0;
enemys = 0;
shots = 0;
items = 0;
wrecks = 0;
banners = 0;
smokePuffs = 0;
// needed for calculating fps
frameCnt = 0;
tickCnt = 0;
gameState = GS_INTRO;
paused = true;
sdlTicks = SDL_GetTicks();
gameActRuntime = 0;
timeNukeEnd = 0;
timePauseOn = 0;
timeMinibossOn = 0;
scrollingOn = true;
showAllShipStats = false;
playMusicOn = true;
onePlayerGame = false;
arcadeGame = false;
difficultyLevel = 1;
sonic1 = new Sonic();
sonic2 = new Sonic();
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 8");
background = new Background();
loadLevel( FN_LEVEL_ONE_PLAYER );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 9");
SdlCompat_AcceleratedSurface *loadingSprite = surfaceDB.loadSurface( FN_LOADING );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 10");
SDL_Rect dest;
dest.x = (SCREEN_WIDTH - loadingSprite->w ) / 2;
dest.y = (SCREEN_HEIGHT - loadingSprite->h ) / 2;
dest.w = loadingSprite->w;
dest.h = loadingSprite->h;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 11");
SDL_BlitSurface( loadingSprite, 0, screen, &dest );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 12");
SDL_Flip( screen );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 13");
initAllSurfaces();
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 14");
}
Game::~Game(){
if (videoserver) delete videoserver;
if (settings) delete settings;
if (intro) delete intro;
if (setDifficulty) delete setDifficulty;
if (racers) delete racers;
if (shots) delete shots;
if (explosions) delete explosions;
if (enemys) delete enemys;
if (items) delete items;
if (wrecks) delete wrecks;
if (fontTime) delete fontTime;
if (sonic1) delete sonic1;
if (sonic2) delete sonic2;
if (banners) delete banners;
if (smokePuffs) delete smokePuffs;
}
void Game::initNewGame() {
parseGlobalConfigValues( difficultyLevel );
if (racers) delete racers;
if (shots) delete shots;
if (explosions) delete explosions;
if (enemys) delete enemys;
if (items) delete items;
if (wrecks) delete wrecks;
if (sonic1) delete sonic1;
if (sonic2) delete sonic2;
if (banners) delete banners;
if (smokePuffs) delete smokePuffs;
banners = new Banners();
smokePuffs = new SmokePuffs();
racers = new Racers();
Racer *racer;
if ( !arcadeGame ) {
if ( onePlayerGame ) {
loadLevel( FN_LEVEL_ONE_PLAYER );
if ( setDifficulty->getPlayerOneLightFighter() ) {
racer = new Racer( FN_LIGHT_FIGHTER_1, 0,
Vector2D(320,350), LIGHT_FIGHTER );
} else {
racer = new Racer( FN_HEAVY_FIGHTER_1, 0,
Vector2D(320,350), HEAVY_FIGHTER );
}
racers->addRacer(racer);
}
// two players
else {
loadLevel( FN_LEVEL_TWO_PLAYER );
if ( setDifficulty->getPlayerOneLightFighter() ) {
racer = new Racer( FN_LIGHT_FIGHTER_1, 0,
Vector2D(250,350), LIGHT_FIGHTER );
} else {
racer = new Racer( FN_HEAVY_FIGHTER_1, 0,
Vector2D(250,350), HEAVY_FIGHTER );
}
racers->addRacer(racer);
if ( setDifficulty->getPlayerTwoLightFighter() ) {
racer = new Racer( FN_LIGHT_FIGHTER_2, 1,
Vector2D(390,350), LIGHT_FIGHTER );
} else {
racer = new Racer( FN_HEAVY_FIGHTER_2, 1,
Vector2D(390,350), HEAVY_FIGHTER );
}
racers->addRacer(racer);
}
}
// arcade game
else {
loadLevel( FN_LEVEL_ARCADEMODE );
if ( menuArcadeMode->getPlayerOneLightFighter() ) {
racer = new Racer( FN_LIGHT_FIGHTER_1, 0,
Vector2D(320,350), LIGHT_FIGHTER );
} else {
racer = new Racer( FN_HEAVY_FIGHTER_1, 0,
Vector2D(320,350), HEAVY_FIGHTER );
}
racers->addRacer(racer);
}
racers->getKeyActionMaps();
explosions = new Explosions();
enemys = new Enemys();
shots = new Shots();
items = new Items();
wrecks = new Wrecks();
gameActRuntime = 0;
paused = true;
bossTime = false;
bossNukeEffect = false;
bossExplosion = Mixer::mixer().loadSample( FN_SOUND_EXPLOSION_BOSS );
minibossAlreadyKilled = false;
minibossTime = false;
timeMinibossOn = SDL_GetTicks();
timeLastUpdate = SDL_GetTicks();
timeNukeEnd = SDL_GetTicks();
timePauseOn = SDL_GetTicks();
actBackgroundPos = 0;
scrollingOn = true;
nukeIsInPlace = false;
sonic1 = new Sonic();
sonic2 = new Sonic();
sonic1->setActive( false );
sonic2->setActive( false );
}
void Game::run(){
while( gameState != GS_QUIT ) {
switch (gameState) {
case GS_SCREENSHOTS:
{
intro->showScreenshots();
gameState = GS_INTRO;
break;
}
case GS_INTRO:
{
intro->run( gameState );
break;
}
case GS_SET_DIFFICULTY:
{
setDifficulty->run( gameState, onePlayerGame);
break;
}
case GS_ARCADE_MODE_SETUP:
{
menuArcadeMode->run( gameState );
break;
}
case GS_ARCADE_MODE_FINISHED:
{
menuArcadeMode->run( gameState, racers->getPointsArcadeMode() );
break;
}
case GS_OPTIONS:
{
options();
break;
}
case GS_ROUNDFINISHED:
{
roundFinished();
break;
}
case GS_BOSS_KILLED:
{
bossKilled();
break;
}
case GS_PLAYON:
{
initNewGame();
if ( playMusicOn ) Mixer::mixer().playMusic( MUSIC_PLAYON, -1, 1000 );
playOn();
break;
}
default: break;
}
}
}
/*********************************/
/**** PlayOn *********************/
/*********************************/
void Game::playOn() {
int A = SDL_GetTicks();
frameCnt = 0;
tickCnt = 0;
{
std::ostringstream logout;
logout << "frameCnt: " << frameCnt << " tickCnt: " << tickCnt
<< " SDL_GetTicks()=" << A;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", logout.str().c_str());
}
while ( gameState == GS_PLAYON ) {
handleEventsPlayOn();
if (!paused) {
updateGameState();
}
drawPlayOn();
// miniboss
if ( minibossTime && enemys->minibossDead() ) minibossAlreadyKilled = true;
if (!minibossAlreadyKilled && !arcadeGame && !paused && !minibossTime &&
(unsigned int)GAME_LENGTH / 2 <= gameActRuntime) {
generateMiniboss();
}
if ( minibossTime && enemys->bossDead() ) minibossKilled();
// endboss
if (!arcadeGame && !paused && !bossTime && !minibossTime &&
(unsigned int)GAME_LENGTH < gameActRuntime) {
enemys->bossTime(1); // generates the boss
bossTime = true;
Mixer::mixer().playSample( bossAlarm , 0, true );
if ( playMusicOn ) Mixer::mixer().playMusic( MUSIC_BOSS1, -1, 0 );
}
if ( bossTime && enemys->bossDead() ) gameState = GS_BOSS_KILLED;
if ( racers->bothPlayersLost() ) gameState = GS_ROUNDFINISHED;
}
{
std::ostringstream logout;
int B = SDL_GetTicks();
logout << "frameCnt: " << frameCnt << " tickCnt: " << tickCnt
<< " SDL_GetTicks()=" << B << endl;
logout << "Milliseconds: " << B-A << endl;
logout << "Frames/sec : " << (float)frameCnt / ((float)(B-A) / 1000.0) << endl;
logout << "ms/Frame : " << (float)tickCnt / (float)frameCnt << endl;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", logout.str().c_str());
}
}
void Game::pause() {
if (paused) {
Uint32 timePaused = SDL_GetTicks() - timePauseOn;
timeLastUpdate += timePaused;
} else {
timePauseOn = SDL_GetTicks();
}
paused = !paused;
}
void Game::handleEventsPlayOn() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_JOYBUTTONDOWN:
case SDL_KEYDOWN:
case SDL_MOUSEBUTTONDOWN: {
if (paused) pause();
racers->handleEvent(input.translate(event), input.isPressed(event));
break;
}
case SDL_KEYUP: {
switch(event.key.keysym.sym) {
case SDLK_F10: {
pause();
break;
}
case SDLK_F5: {
videoserver->toggleFullscreen();
break;
}
case SDLK_F6: {
showAllShipStats = !showAllShipStats;
break;
}
case SDLK_ESCAPE: {
gameState = GS_INTRO;
break;
}
case SDLK_F1: {
if (!paused) pause();
settings->settingsDialog(screen);
racers->getKeyActionMaps();
pause();
break;
}
case SDLK_F7: {
if ( playMusicOn ) {
playMusicOn = false;
Mixer::mixer().stopMusic();
} else {
playMusicOn = true;
if ( bossTime ) Mixer::mixer().playMusic( MUSIC_BOSS1, -1, 1000 );
else Mixer::mixer().playMusic( MUSIC_PLAYON, -1, 1000 );
}
break;
}
default: break;
}
}
case SDL_JOYAXISMOTION:
case SDL_JOYBUTTONUP:
case SDL_MOUSEBUTTONUP:
racers->handleEvent(input.translate(event), input.isPressed(event));
break;
case SDL_QUIT: {
gameState = GS_QUIT;
break;
}
default: break;
}
}
}
// what to do in one tick
void Game::updateGameState() {
int dT = SDL_GetTicks() - timeLastUpdate;
timeLastUpdate += dT;
if ( !minibossTime ) gameActRuntime += dT;
if ( nukeIsInPlace ) handleNuke();
enemys->generateEnemys( dT );
explosions->updateExplosions( dT );
smokePuffs->update( dT );
shots->moveAndCollide( dT );
wrecks->updateWrecks( dT );
enemys->updateEnemys( dT );
if ( !arcadeGame ) items->generate( dT );
items->update( dT );
racers->moveAndCollide( dT );
racers->pickUpItems();
racers->shoot();
if ( !arcadeGame ) racers->rechargeShield( dT );
enemys->deleteExpiredEnemys();
shots->expireShots();
items->expireItems();
explosions->expireExplosions();
wrecks->expireWrecks();
racers->expireRacers();
smokePuffs->expireSmokePuffs();
sonicDeflectorEffect();
banners->update( dT );
banners->expireBanners();
if ( scrollingOn ) actBackgroundPos -= SCROLL_SPEED * dT / 1000.0;
if ( arcadeGame ) {
racers->receivePointsArcade( ARCADE_POINTS_PER_TEN_SECONDS * dT / 10000.0 );
}
}
void Game::handleNuke() {
sonic1->setActive( false );
sonic2->setActive( false );
enemys->doNukeDamage();
shots->deleteAllShots();
timeNukeEnd = SDL_GetTicks() + NUKE_EFFECT_DURATION;
nukeIsInPlace = false;
}
void Game::sonicDeflectorEffect() {
for ( unsigned int i = 0; i < racers->getNrRacers(); i++) {
if ( racers->getRacer(i)->getShipType() == LIGHT_FIGHTER ) {
Shot* nearestRocket = shots->getNearestRocket( racers->getRacer(i)->getPos() );
// a rocket exists and it is in range of the sonic
if ( nearestRocket != NULL &&
(nearestRocket->getPos() - racers->getRacer(i)->getPos()).getLength() <
RACER_SONIC_ACTIVATION_DIST ) {
// activate the correct sonic
if (i == 0) {
sonic1->setPos( racers->getRacer(i)->getPos(), nearestRocket->getPos() );
nearestRocket->deflectedBySonicFromPlayer1 = true;
} else {
sonic2->setPos( racers->getRacer(i)->getPos(), nearestRocket->getPos() );
nearestRocket->deflectedBySonicFromPlayer2 = true;
}
// no rocket is in sonic-range
} else {
// deactivate the sonic
if (i == 0) {
sonic1->setActive( false );
} else {
sonic2->setActive( false );
}
}
}
}
}
void Game::drawPlayOn() {
drawBackground();
wrecks->draw(screen);
enemys->drawGroundEnemys(screen);
shots->drawShadows(screen);
racers->drawShadows(screen);
enemys->drawShadows(screen);
explosions->drawGroundExplosions(screen);
smokePuffs->draw(screen);
sonic1->draw(screen);
sonic2->draw(screen);
shots->drawGroundShots(screen);
shots->drawGroundAirShots(screen);
items->draw(screen);
enemys->drawAirEnemys(screen);
racers->drawRacers(screen);
shots->drawAirShots(screen);
explosions->drawAirExplosions(screen);
if ( showAllShipStats ) enemys->drawAllStats(screen);
else {
if ( bossTime ) {
enemys->drawBossStats(screen);
fontTime->drawStr( screen, (screen->w / 2), 5, "BOSS", FONT_ALIGN_CENTERED );
}
}
if ( SDL_GetTicks() < timeNukeEnd ) {
drawNukeEffect();
}
racers->drawStats(screen);
banners->draw(screen);
if ( !arcadeGame && !bossTime && !minibossTime ) drawTime();
else {
if ( bossTime || minibossTime ) {
fontTime->drawStr( screen, (screen->w / 2), 5, "BOSS", FONT_ALIGN_CENTERED );
}
else {
drawPointsArcadeMode();
}
}
if (paused) drawPaused();
SDL_Flip( screen );
frameCnt++;
}
void Game::drawBackground() {
background->draw(screen, (int) (actBackgroundPos + 0.5) );
}
void Game::drawTime() {
Uint32 timeToDraw;
timeToDraw = (GAME_LENGTH - gameActRuntime) / 1000;
if ( timeToDraw > 0 ) {
int digitCnt = 1;
Uint32 i=1;
while ( timeToDraw >= i*10 ) {
digitCnt++;
i *= 10;
}
fontTime->drawInt(screen, (screen->w / 2) - (fontSizeTime * digitCnt) / 2, 5,
timeToDraw, digitCnt, 0);
}
}
void Game::drawPointsArcadeMode() {
int pointsToDraw = racers->getPointsArcadeMode();
if ( pointsToDraw < 0 ) return;
int digitCnt = 1;
int i=1;
while ( pointsToDraw >= i*10 ) {
digitCnt++;
i *= 10;
}
fontTime->drawInt( screen, (screen->w / 2) - (fontSizeTime * digitCnt) / 2, 10,
pointsToDraw, digitCnt, 0);
}
void Game::drawPaused() {
SDL_Rect r;
r.x = screen->w/2 - pauseSprite->w/2;
r.y = screen->h/2 - pauseSprite->h/2;
r.w = pauseSprite->w;
r.h = pauseSprite->h;
SDL_BlitSurface( pauseSprite, 0, screen, &r );
}
void Game::drawNukeEffect() {
// effect-process: transparent -> nearly opaque -> transparent
int timeFromMaximum = (NUKE_EFFECT_DURATION / 2) - (timeNukeEnd - SDL_GetTicks());
timeFromMaximum = abs(timeFromMaximum);
SDL_SetAlpha( nukeEffectSurface, SDL_SRCALPHA,
lroundf(((NUKE_EFFECT_DURATION / 2) - timeFromMaximum) * 128.0 /
(NUKE_EFFECT_DURATION / 2)) );
SDL_BlitSurface( nukeEffectSurface, 0, screen, 0 );
/*
int randRange = (int)
(( ((NUKE_EFFECT_DURATION / 2.0) - timeFromMaximum) * NUKE_QUAKE_EFFECT /
(NUKE_EFFECT_DURATION / 2.0 ) ) + 0.5);
int randX, randY;
if ( randRange == 0 ) randRange = 1;
randX = (rand() % randRange) - randRange / 2;
randY = (rand() % randRange) - randRange / 2;
SDL_Rect src, dest;
if ( randX < 0 ) {
src.x = -randX;
src.w = screen->w + randX;
dest.x = 0;
dest.w = screen->w + randX;
} else {
src.x = 0;
src.w = screen->w - randX;
dest.x = randX;
dest.w = screen->w - randX;
}
if ( randY < 0 ) {
src.y = -randY;
src.h = screen->h + randY;
dest.y = 0;
dest.h = screen->h + randY;
} else {
src.y = 0;
src.h = screen->h - randY;
dest.y = randY;
dest.h = screen->h - randY;
}
SDL_BlitSurface( screen, &src, screen, &dest );
*/
}
// not in use - not needed anymore
void Game::timeManagement() {
Uint32 sdlTicksNew = SDL_GetTicks();
tickCnt += sdlTicksNew - sdlTicks;
// 25 Frames per Second is wanted
// we needed less than 40 ms -> wait till the 40 ms are over
while ( sdlTicks + 40 > sdlTicksNew ) {
sdlTicksNew = SDL_GetTicks();
}
sdlTicks = sdlTicksNew;
}
/***********************************/
/** Options ************************/
/***********************************/
void Game::options() {}
/************************************/
/** Round Finished ******************/
/************************************/
void Game::roundFinished() {
drawRoundFinished();
SDL_Flip( screen );
while (gameState == GS_ROUNDFINISHED ) {
handleEventsRoundFinished();
}
}
void Game::handleEventsRoundFinished() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYUP:
{
switch(event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_SPACE:
case SDLK_RETURN:
{
if ( arcadeGame ) gameState = GS_ARCADE_MODE_FINISHED;
else gameState = GS_INTRO;
break;
}
case SDLK_F5:
{
videoserver->toggleFullscreen();
break;
}
default:
{
break;
}
}
break;
}
case SDL_QUIT:
{
if ( arcadeGame ) gameState = GS_ARCADE_MODE_FINISHED;
else gameState = GS_INTRO;
break;
}
default: break;
}
}
}
void Game::drawRoundFinished() {
SDL_Rect r;
if ( arcadeGame ) {
r.x = screen->w/2 - gameOverSprite->w / 2;
r.y = screen->h/2 - gameOverSprite->h / 2;
r.w = gameOverSprite->w;
r.h = gameOverSprite->h;
SDL_BlitSurface( gameOverSprite, 0, screen, &r );
fontTime->drawStr( screen, screen->w/2, screen->h/2 + gameOverSprite->h/2 + 50,
"SCORE: " + asString( racers->getPointsArcadeMode() ),
FONT_ALIGN_CENTERED );
fontTime->drawStr( screen, screen->w/2, screen->h/2 + gameOverSprite->h/2 + 100,
"Kill Rate: " + asString(enemys->getNrEnemysKilled())
+ "/" + asString(enemys->getNrEnemysGenerated()),
FONT_ALIGN_CENTERED );
}
// normal game
else {
if ( racers->bothPlayersLost() ) {
r.x = screen->w/2 - youLoseSprite->w / 2;
r.y = screen->h/2 - youLoseSprite->h / 2;
r.w = youLoseSprite->w;
r.h = youLoseSprite->h;
SDL_BlitSurface( youLoseSprite, 0, screen, &r );
} else {
r.x = screen->w/2 - youWinSprite->w / 2;
r.y = screen->h/2 - youWinSprite->h / 2;
r.w = youWinSprite->w;
r.h = youWinSprite->h;
SDL_BlitSurface( youWinSprite, 0, screen, &r );
fontTime->drawStr(screen, screen->w/2, screen->h/2 + youWinSprite->h/2 + 50,
"Kill Rate: " + asString(enemys->getNrEnemysKilled())
+ ":" + asString(enemys->getNrEnemysGenerated()),
FONT_ALIGN_CENTERED);
}
}
}
/************************************/
/** Miniboss ***********************/
/************************************/
void Game::generateMiniboss() {
scrollingOn = false;
minibossTime = true;
enemys->bossTime(2); // generates the miniboss
Mixer::mixer().playSample( bossAlarm , 0, true );
if ( playMusicOn ) Mixer::mixer().playMusic( MUSIC_BOSS1, -1, 0 );
}
void Game::minibossKilled() {
scrollingOn = true;
minibossTime = false;
if ( playMusicOn ) Mixer::mixer().playMusic( MUSIC_PLAYON, -1, 0 );
}
/************************************/
/** Boss Killed *********************/
/************************************/
void Game::bossKilled() {
int BOSS_EXPLOSION_DURATION = 3000;
int startOfBossExplosion = SDL_GetTicks();
int actualTime;
bool bossExplosionSound = false;
timeNukeEnd = SDL_GetTicks() + BOSS_EXPLOSION_DURATION + NUKE_EFFECT_DURATION;
while ( gameState == GS_BOSS_KILLED ) {
actualTime = SDL_GetTicks();
updateBossKilled();
if ( (actualTime - startOfBossExplosion) < BOSS_EXPLOSION_DURATION ) {
// explosions
Explosion *newExplosion =
new Explosion( FN_EXPLOSION_ENEMY,
Vector2D( rand() % SCREEN_WIDTH, rand() % 150 ),
Vector2D( 0, 0 ),
EXPLOSION_NORMAL_GROUND );
explosions->addExplosion( newExplosion );
}
else if ( (actualTime - startOfBossExplosion) < (BOSS_EXPLOSION_DURATION + NUKE_EFFECT_DURATION) ) {
// nuke effect
if ( !bossExplosionSound ) {
Mixer::mixer().playSample( bossExplosion, 0, true );
bossExplosionSound = false;
enemys->doNukeDamage();
enemys->deleteExpiredEnemys();
shots->deleteAllShots();
items->deleteAllItems();
wrecks->deleteAllWrecks();
Wreck *newWreck = new Wreck( Vector2D( SCREEN_WIDTH / 2, 70 ), WRECK_BOSS_1_DESTROYED);
wrecks->addWreck( newWreck );
bossNukeEffect = true;
}
}
else {
bossNukeEffect = false;
}
if ( (actualTime - startOfBossExplosion) > (BOSS_EXPLOSION_DURATION + NUKE_EFFECT_DURATION + 4000) ) {
gameState = GS_ROUNDFINISHED;
}
drawBossKilled();
handleEventsBossKilled();
}
}
void Game::handleEventsBossKilled() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYUP: {
switch(event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_SPACE:
case SDLK_RETURN:
{
gameState = GS_INTRO;
break;
}
case SDLK_F5:
{
videoserver->toggleFullscreen();
break;
}
default: break;
}
break;
}
case SDL_QUIT:
{
gameState = GS_INTRO;
break;
}
default: break;
}
}
}
void Game::drawBossKilled() {
drawBackground();
wrecks->draw(screen);
enemys->drawGroundEnemys(screen);
shots->drawShadows(screen);
racers->drawShadows(screen);
enemys->drawShadows(screen);
explosions->drawGroundExplosions(screen);
shots->drawGroundShots(screen);
shots->drawGroundAirShots(screen);
items->draw(screen);
enemys->drawAirEnemys(screen);
racers->drawRacers(screen);
shots->drawAirShots(screen);
explosions->drawAirExplosions(screen);
if ( bossNukeEffect ) drawNukeEffect();
racers->drawStats(screen);
SDL_Flip( screen );
}
void Game::updateBossKilled() {
int dT = SDL_GetTicks() - timeLastUpdate;
timeLastUpdate += dT;
explosions->updateExplosions( dT );
explosions->expireExplosions();
}
void Game::loadLevel( string fn ) {
if (levelConf) {
delete levelConf;
}
levelConf = new Options( fn );
// load background tiles
background->clearTileList();
int cnt = 0;
if (!levelConf->getInt( LVL_BACKG_TILE_CNT, cnt )) {
cout << "ERROR: " << fn << " contains no '" << LVL_BACKG_TILE_CNT << "' keyword!" << endl;
exit(0);
}
for(int i=0; i < cnt; i++) {
string tilename;
if (levelConf->getStr( LVL_BACKG_TILE + asString( i ), tilename ) ) {
background->addTile( tilename );
}
}
int len = SCREEN_WIDTH;
levelConf->getInt( LVL_BACKG_LENGTH, len );
background->generateBackground( len );
}

View File

@@ -1,144 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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_HH
#define GAME_HH
#include "SDL.h"
#include "SdlForwardCompat.h"
#include <string>
class Video;
class SurfaceDB;
class Racers;
class Shots;
class Explosions;
class Enemys;
class Items;
class Font;
class Intro;
class SetDifficulty;
class MenuArcadeMode;
class Sonic;
class Background;
class Options;
enum GameStates { GS_QUIT, GS_SCREENSHOTS, GS_INTRO, GS_SET_DIFFICULTY,
GS_OPTIONS, GS_ARCADE_MODE_SETUP, GS_ARCADE_MODE_FINISHED,
GS_PLAYON, GS_ROUNDFINISHED, GS_BOSS_KILLED };
/* The big class, that has to control the gamelogic and keep track of all the
game objects and their dependencies. */
class Game {
// Video system
SdlCompat_AcceleratedSurface *screen;
SdlCompat_AcceleratedSurface *pauseSprite;
SdlCompat_AcceleratedSurface *youLoseSprite;
SdlCompat_AcceleratedSurface *youWinSprite;
SdlCompat_AcceleratedSurface *gameOverSprite;
SdlCompat_AcceleratedSurface *nukeEffectSurface;
SdlCompat_AcceleratedSurface *hud;
// Time system
Font *fontTime;
int fontSizeTime;
Uint32 frameCnt;
Uint32 tickCnt;
Uint32 sdlTicks;
Uint32 gameActRuntime;
Uint32 timePauseOn;
Uint32 timeMinibossOn;
Uint32 timeLastUpdate;
Uint32 timeNukeEnd;
bool paused;
bool showAllShipStats;
Background *background;
// is the game in playon or in intro or somewhere else?
GameStates gameState;
Intro *intro;
SetDifficulty *setDifficulty;
MenuArcadeMode *menuArcadeMode;
// boss specific
bool bossTime;
bool minibossTime;
bool minibossAlreadyKilled;
bool bossNukeEffect;
int bossExplosion;
int bossAlarm;
Sonic *sonic1;
Sonic *sonic2;
public:
// for access from main()
Game();
~Game();
// the outer game loop
void run();
private:
// starts a new game
void initNewGame();
/* Methods for GS_PLAYON */
// the inner loop when the race is going on
void playOn();
void handleEventsPlayOn();
// toggles the pause state (takes into account the corresponding time problems)
void pause();
void updateGameState();
void handleNuke();
void sonicDeflectorEffect();
void drawPlayOn();
void drawBackground();
void drawTime();
void drawPointsArcadeMode();
void drawPaused();
void drawNukeEffect();
void timeManagement(); // not needed and used any more
/* Methods for GS_OPTIONS (not implemented by now) */
void options();
void loadLevel( std::string fn );
/* Methods for GS_ROUNDFINISHED (the time is up -> display the winner) */
void roundFinished();
void drawRoundFinished();
void handleEventsRoundFinished();
void generateMiniboss();
void minibossKilled();
void bossKilled();
void updateBossKilled();
void drawBossKilled();
void handleEventsBossKilled();
};
#endif //#ifndef GAME_HH

View File

@@ -1,793 +0,0 @@
/*
Copyright (c) 2000,2001, Jelle Kok, University of Amsterdam
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University of Amsterdam nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************************
* goemetry.cc
*
* implements:
* class Vector2D
* namespace Geometry
* class Line
* class Circle
* class Rectangle
*
* requires:
*
* Maintainer: wenns
*
* Changelog:
*
*************************************************************************************/
//Furthermore it contains some goniometric functions to work with sine, cosine
//and tangent functions using degrees and some utility functions to return
//the maximum and the minimum of two values.
#include "geometry.h"
#include <algorithm> // max and min
#include <stdio.h> // needed for sprintf
AngDeg Rad2Deg ( AngRad x ) { return ( x * 180 / M_PI ); }
AngRad Deg2Rad ( AngDeg x ) { return ( x * M_PI / 180 ); }
float cosDeg ( AngDeg x ) { return ( cos( Deg2Rad( x ) ) ); }
float sinDeg ( AngDeg x ) { return ( sin( Deg2Rad( x ) ) ); }
float tanDeg ( AngDeg x ) { return ( tan( Deg2Rad( x ) ) ); }
AngDeg atanDeg ( float x ) { return ( Rad2Deg( atan( x ) ) ); }
float atan2Deg( float x, float y ){
if( fabs( x ) < EPSILON && fabs( y ) < EPSILON )
return ( 0.0 );
return ( Rad2Deg( atan2( x, y ) ) );
}
AngDeg acosDeg( float x ){
if( x >= 1 )
return ( 0.0 );
else if( x <= -1 )
return ( 180.0 );
return ( Rad2Deg( acos( x ) ) );
}
AngDeg asinDeg( float x ){
if( x >= 1 )
return ( 90.0 );
else if ( x <= -1 )
return ( -90.0 );
return ( Rad2Deg( asin( x ) ) );
}
float normalizeTo180Deg(float angle){
while( angle > 180.0 ) angle -= 360.0;
while( angle < -180.0 ) angle += 360.0;
return ( angle );
}
bool isAngInInterval( AngDeg ang, AngDeg angMin, AngDeg angMax ){
// convert all angles to interval 0..360
if( ( ang + 360 ) < 360 ) ang += 360;
if( ( angMin + 360 ) < 360 ) angMin += 360;
if( ( angMax + 360 ) < 360 ) angMax += 360;
if( angMin < angMax ) // 0 ---false-- angMin ---true-----angMax---false--360
return angMin < ang && ang < angMax ;
else // 0 ---true--- angMax ---false----angMin---true---360
return !( angMax < ang && ang < angMin );
}
AngDeg getBisectorTwoAngles( AngDeg angMin, AngDeg angMax ){
// separate sine and cosine part to circumvent boundary problem
//return Vector2D::normalizeAngle(
return normalizeTo180Deg( //wenns changed
atan2Deg( (sinDeg( angMin) + sinDeg( angMax ) )/2.0,
(cosDeg( angMin) + cosDeg( angMax ) )/2.0 ) );
}
AngDeg getAngleDifference( AngDeg ang1, AngDeg ang2 ){
return (normalizeTo180Deg( ang1 - ang2 ));
}
AngDeg getAbsAngleDifference( AngDeg ang1, AngDeg ang2 ){
return fabs(normalizeTo180Deg( ang1 - ang2 ));
}
/******************************************************************************/
/******************** CLASS VECTOR2D **************************************/
/******************************************************************************/
Vector2D::Vector2D( float x, float y, CoordSystemT cs ){
setVector2D( x, y, cs );
}
ostream& operator <<( ostream &os, Vector2D v ){
return ( os << "( " << v.x << ", " << v.y << " )" );
}
void Vector2D::show( CoordSystemT cs ){
if( cs == CARTESIAN )
cout << *this << endl;
else
cout << "( r: " << getLength( ) << ", phi: " << getDirection( ) << " )";
}
/*
bool Vector2D::isInvalid() const {
return (isUndefined(x) || (isUndefined(y))
// || (fabs(x) >= 100000.0) || (fabs(y) >= 100000.0)
|| isinf(x) || isinf(y) || isnan(x) || isnan(y));
}
*/
void Vector2D::setVector2D( float dX, float dY, CoordSystemT cs){
if( cs == CARTESIAN ) { x = dX; y = dY; }
else *this = getVector2DFromPolar( dX, dY );
}
Vector2D Vector2D::setLength( float d ){
if( getLength( ) > EPSILON )
( *this ) *= ( d / getLength( ) );
return ( *this );
}
Vector2D Vector2D::rotate( AngDeg angle ){
// determine the polar representation of the current Vector2D
float dMag = this->getLength( );
float dNewDir = this->getDirection( ) + angle; // add rotation angle to phi
setVector2D( dMag, dNewDir, POLAR ); // convert back to Cartesian
return ( *this );
}
Vector2D Vector2D::globalToRelative( Vector2D origin, AngDeg ang ){
// convert global coordinates into relative coordinates by aligning relative
// frame and world frame. First perform translation to make origins of both
// frames coincide. Then perform rotation to make axes of both frames coincide
// (use negative angle since you rotate relative frame to world frame).
*this -= origin;
return ( rotate( -ang ) );
}
Vector2D Vector2D::relativeToGlobal( Vector2D origin, AngDeg ang ){
// convert relative coordinates into global coordinates by aligning world
// frame and relative frame. First perform rotation to make axes of both
// frames coincide (use positive angle since you rotate world frame to
// relative frame). Then perform translation to make origins of both frames
// coincide.
rotate( ang );
*this += origin;
return ( *this );
}
Vector2D Vector2D::getVector2DOnLineFraction( Vector2D &p,
float dFrac ){
// determine point on line that lies at fraction dFrac of whole line
// example: this --- 0.25 --------- p
// formula: this + dFrac * ( p - this ) = this - dFrac * this + dFrac * p =
// ( 1 - dFrac ) * this + dFrac * p
return ( ( *this ) * ( 1.0 - dFrac ) + ( p * dFrac ) );
}
Vector2D Vector2D::getVector2DFromPolar( float dMag, AngDeg ang ){
// cos(phi) = x/r <=> x = r*cos(phi); sin(phi) = y/r <=> y = r*sin(phi)
return ( Vector2D( dMag * cosDeg( ang ), dMag * sinDeg( ang ) ) );
}
/******************************************************************************/
/*********************** NAMESPACE GEOMETRY ***************************************/
/******************************************************************************/
float Geometry::getLengthGeomSeries( float dFirst, float dRatio, float dSum ){
if( dRatio < 0 )
cerr << "(Geometry:getLengthGeomSeries): negative ratio" << endl;
// s = a + ar + ar^2 + .. + ar^n-1 and thus sr = ar + ar^2 + .. + ar^n
// subtract: sr - s = - a + ar^n) => s(1-r)/a + 1 = r^n = temp
// log r^n / n = n log r / log r = n = length
float temp = (dSum * ( dRatio - 1 ) / dFirst) + 1;
if( temp <= 0 )
return -1.0;
return log( temp ) / log( dRatio ) ;
}
float Geometry::getSumGeomSeries( float dFirst, float dRatio, float dLength){
// s = a + ar + ar^2 + .. + ar^n-1 and thus sr = ar + ar^2 + .. + ar^n
// subtract: s - sr = a - ar^n) => s = a(1-r^n)/(1-r)
return dFirst * ( 1 - pow( dRatio, dLength ) ) / ( 1 - dRatio ) ;
}
float Geometry::getSumInfGeomSeries( float dFirst, float dRatio ){
if( dRatio > 1 )
cerr << "(Geometry:CalcLengthGeomSeries): series does not converge" << endl;
// s = a(1-r^n)/(1-r) with n->inf and 0<r<1 => r^n = 0
return dFirst / ( 1 - dRatio );
}
float Geometry::getFirstGeomSeries( float dSum, float dRatio, float dLength){
// s = a + ar + ar^2 + .. + ar^n-1 and thus sr = ar + ar^2 + .. + ar^n
// subtract: s - sr = a - ar^n) => s = a(1-r^n)/(1-r) => a = s*(1-r)/(1-r^n)
return dSum * ( 1 - dRatio )/( 1 - pow( dRatio, dLength ) ) ;
}
float Geometry::getFirstInfGeomSeries( float dSum, float dRatio ){
if( dRatio > 1 )
cerr << "(Geometry:getFirstInfGeomSeries):series does not converge" << endl;
// s = a(1-r^n)/(1-r) with r->inf and 0<r<1 => r^n = 0 => a = s ( 1 - r)
return dSum * ( 1 - dRatio );
}
int Geometry::abcFormula(float a, float b, float c, float *s1, float *s2){
float dDiscr = b*b - 4*a*c; // discriminant is b^2 - 4*a*c
if (fabs(dDiscr) < EPSILON ) // if discriminant = 0
{
*s1 = -b / (2 * a); // only one solution
return 1;
}
else if (dDiscr < 0) // if discriminant < 0
return 0; // no solutions
else // if discriminant > 0
{
dDiscr = sqrt(dDiscr); // two solutions
*s1 = (-b + dDiscr ) / (2 * a);
*s2 = (-b - dDiscr ) / (2 * a);
return 2;
}
}
/******************************************************************************/
/********************** CLASS CIRCLE ******************************************/
/******************************************************************************/
Circle::Circle( Vector2D pos, float dR ){
setCircle( pos, dR );
}
Circle::Circle( ){
setCircle( Vector2D(-1000.0,-1000.0), 0);
}
void Circle::show( ostream& os) const {
os << "c:" << posCenter << ", r:" << radius;
}
bool Circle::setCircle( const Vector2D &pos, float dR ){
setCenter( pos );
return setRadius( dR );
}
bool Circle::setRadius( float dR ){
if( dR > 0 ){
radius = dR;
return true;
}
else{
radius = 0.0;
return false;
}
}
int Circle::getIntersectionPoints( const Circle &c, Vector2D *p1,
Vector2D *p2) const {
float x0, y0, r0;
float x1, y1, r1;
x0 = getCenter( ).getX();
y0 = getCenter( ).getY();
r0 = getRadius( );
x1 = c.getCenter( ).getX();
y1 = c.getCenter( ).getY();
r1 = c.getRadius( );
float d, dx, dy, h, a, x, y, p2_x, p2_y;
// first calculate distance between two centers circles P0 and P1.
dx = x1 - x0;
dy = y1 - y0;
d = sqrt(dx*dx + dy*dy);
// normalize differences
dx /= d; dy /= d;
// a is distance between p0 and point that is the intersection point P2
// that intersects P0-P1 and the line that crosses the two intersection
// points P3 and P4.
// Define two triangles: P0,P2,P3 and P1,P2,P3.
// with distances a, h, r0 and b, h, r1 with d = a + b
// We know a^2 + h^2 = r0^2 and b^2 + h^2 = r1^2 which then gives
// a^2 + r1^2 - b^2 = r0^2 with d = a + b ==> a^2 + r1^2 - (d-a)^2 = r0^2
// ==> r0^2 + d^2 - r1^2 / 2*d
a = (r0*r0 + d*d - r1*r1) / (2.0 * d);
// h is then a^2 + h^2 = r0^2 ==> h = sqrt( r0^2 - a^2 )
float arg = r0*r0 - a*a;
h = (arg > 0.0) ? sqrt(arg) : 0.0;
// First calculate P2
p2_x = x0 + a * dx;
p2_y = y0 + a * dy;
// and finally the two intersection points
x = p2_x - h * dy;
y = p2_y + h * dx;
p1->setVector2D( x, y );
x = p2_x + h * dy;
y = p2_y - h * dx;
p2->setVector2D( x, y );
return (arg < 0.0) ? 0 : ((arg == 0.0 ) ? 1 : 2);
}
float Circle::getIntersectionArea( const Circle &c ) const {
Vector2D pos1, pos2, pos3;
float d, h, dArea;
AngDeg ang;
d = getCenter().distanceTo( c.getCenter() ); // dist between two centers
if( d > c.getRadius() + getRadius() ) // larger than sum radii
return 0.0; // circles do not intersect
if( d <= fabs(c.getRadius() - getRadius() ) ) // one totally in the other
{
float dR = min( c.getRadius(), getRadius() );// return area smallest circle
return M_PI*dR*dR;
}
int iNrSol = getIntersectionPoints( c, &pos1, &pos2 );
if( iNrSol != 2 )
return 0.0;
// the intersection area of two circles can be divided into two segments:
// left and right of the line between the two intersection points p1 and p2.
// The outside area of each segment can be calculated by taking the part
// of the circle pie excluding the triangle from the center to the
// two intersection points.
// The pie equals pi*r^2 * rad(2*ang) / 2*pi = 0.5*rad(2*ang)*r^2 with ang
// the angle between the center c of the circle and one of the two
// intersection points. Thus the angle between c and p1 and c and p3 where
// p3 is the point that lies halfway between p1 and p2.
// This can be calculated using ang = asin( d / r ) with d the distance
// between p1 and p3 and r the radius of the circle.
// The area of the triangle is 2*0.5*h*d.
pos3 = pos1.getVector2DOnLineFraction( pos2, 0.5 );
d = pos1.distanceTo( pos3 );
h = pos3.distanceTo( getCenter() );
ang = asin( d / getRadius() );
dArea = ang*getRadius()*getRadius();
dArea = dArea - d*h;
// and now for the other segment the same story
h = pos3.distanceTo( c.getCenter() );
ang = asin( d / c.getRadius() );
dArea = dArea + ang*c.getRadius()*c.getRadius();
dArea = dArea - d*h;
return dArea;
}
bool Circle::calcTangentIntersectionPoints(const Vector2D startPoint, Vector2D &point1, Vector2D &point2){
if(isInside(startPoint)){
// Startpoint is inside circle -> there are no tangent interception points
return(false);
}
//float d = posCenter.getLength()-startPoint.getLength();
float d = (posCenter-startPoint).getLength();
float r = radius;
float alphaRad = asin(r/d);
float p = sqrt(d*d-r*r);
point1.setX(cos(alphaRad)*p);
point1.setY(sin(alphaRad)*p);
point2.setX(cos(-alphaRad)*p);
point2.setY(sin(-alphaRad)*p);
point1=point1.rotate((posCenter-startPoint).getDirection());
point2=point2.rotate((posCenter-startPoint).getDirection());
point1+=startPoint;
point2+=startPoint;
return(true);
}
/******************************************************************************/
/*********************** CLASS LINE *******************************************/
/******************************************************************************/
Line::Line( float dA, float dB, float dC ){
a = dA;
b = dB;
c = dC;
}
Line::Line() {
a = 666.66;
b = 666.66;
c = 666.66;
}
ostream& operator <<(ostream & os, Line l){
float a = l.getACoefficient();
float b = l.getBCoefficient();
float c = l.getCCoefficient();
// ay + bx + c = 0 -> y = -b/a x - c/a
if( a == 0 )
os << "x = " << -c/b;
else{
os << "y = ";
if( b != 0 )
os << -b/a << "x ";
if( c > 0 )
os << "- " << fabs(c/a);
else if( c < 0 )
os << "+ " << fabs(c/a);
}
return os;
}
void Line::show( ostream& os){
os << *this;
}
Vector2D Line::getIntersection( Line line ){
Vector2D pos(666.66,666.66);
float x, y;
if( (b == line.getBCoefficient())&&(b!=-a) ) { // lines are parallel, no intersection
return pos;
}
if( a == 0 ){ // bx + c = 0 and a2*y + b2*x + c2 = 0 ==> x = -c/b
x = -c/b; // calculate x using the current line
y = line.getYGivenX(x); // and calculate the y using the second line
}
// ay + bx + c = 0 and b2*x + c2 = 0 ==> x = -c2/b2
// calculate x using 2nd line and calculate y using current line
else if( line.getACoefficient() == 0 ){
x = -line.getCCoefficient()/line.getBCoefficient();
y = getYGivenX(x);
}
// ay + bx + c = 0 and a2y + b2*x + c2 = 0
// y = (-b2/a2)x - c2/a2
// bx = -a*y - c => bx = -a*(-b2/a2)x -a*(-c2/a2) - c ==>
// ==> a2*bx = a*b2*x + a*c2 - a2*c ==> x = (a*c2 - a2*c)/(a2*b - a*b2)
// calculate x using the above formula and the y using the current line
else{
x = (a*line.getCCoefficient() - line.getACoefficient()*c)/
(line.getACoefficient()*b - a*line.getBCoefficient());
y = getYGivenX(x);
}
return Vector2D( x, y );
}
int Line::getCircleIntersectionPoints( Circle circle,
Vector2D *posSolution1, Vector2D *posSolution2 ){
int iSol;
float dSol1, dSol2;
float h = circle.getCenter().getX();
float k = circle.getCenter().getY();
// line: x = -c/b (if a = 0)
// circle: (x-h)^2 + (y-k)^2 = r^2, with h = center.x and k = center.y
// fill in:(-c/b-h)^2 + y^2 -2ky + k^2 - r^2 = 0
// y^2 -2ky + (-c/b-h)^2 + k^2 - r^2 = 0
// and determine solutions for y using abc-formula
if( fabs(a) < EPSILON ){
iSol = Geometry::abcFormula( 1, -2*k, ((-c/b) - h)*((-c/b) - h)
+ k*k - circle.getRadius()*circle.getRadius(), &dSol1, &dSol2);
posSolution1->setVector2D( (-c/b), dSol1 );
posSolution2->setVector2D( (-c/b), dSol2 );
return iSol;
}
// ay + bx + c = 0 => y = -b/a x - c/a, with da = -b/a and db = -c/a
// circle: (x-h)^2 + (y-k)^2 = r^2, with h = center.x and k = center.y
// fill in:x^2 -2hx + h^2 + (da*x-db)^2 -2k(da*x-db) + k^2 - r^2 = 0
// x^2 -2hx + h^2 + da^2*x^2 + 2da*db*x + db^2 -2k*da*x -2k*db
// + k^2 - r^2 = 0
// (1+da^2)*x^2 + 2(da*db-h-k*da)*x + h2 + db^2 -2k*db + k^2 - r^2 = 0
// and determine solutions for x using abc-formula
// fill in x in original line equation to get y coordinate
float da = -b/a;
float db = -c/a;
float dA = 1 + da*da;
float dB = 2*( da*db - h - k*da );
float dC = h*h + db*db - 2*k*db + k*k - circle.getRadius()*circle.getRadius();
iSol = Geometry::abcFormula( dA, dB, dC, &dSol1, &dSol2 );
posSolution1->setVector2D( dSol1, da*dSol1 + db );
posSolution2->setVector2D( dSol2, da*dSol2 + db );
return iSol;
}
Line Line::getTangentLine( Vector2D pos ){ // Senkrechte errichten, nix mit Tangente
// ay + bx + c = 0 -> y = (-b/a)x + (-c/a)
// tangent: y = (a/b)*x + C1 -> by - ax + C2 = 0 => C2 = ax - by
// with pos.y = y, pos.x = x
return Line( b, -a, a*pos.getX() - b*pos.getY() );
}
Vector2D Line::getPointOnLineClosestTo( Vector2D pos ){
Line l2 = getTangentLine( pos ); // get tangent line
return getIntersection( l2 ); // and intersection between the two lines
}
float Line::distanceToPoint( Vector2D pos ){
return pos.distanceTo( getPointOnLineClosestTo( pos ) );
}
bool Line::isInBetween( Vector2D pos, Vector2D point1, Vector2D point2){
pos = getPointOnLineClosestTo( pos ); // get closest point
float dDist = point1.distanceTo( point2 ); // get distance between 2 pos
// if the distance from both points to the projection is smaller than this
// dist, the pos lies in between.
return pos.distanceTo( point1 ) <= dDist &&
pos.distanceTo( point2 ) <= dDist;
}
float Line::getYGivenX( float x ){
if( a == 0 ){
cerr << "(Line::getYGivenX) Cannot calculate Y coordinate: " ;
show( cerr );
cerr << endl;
return 0;
}
// ay + bx + c = 0 ==> ay = -(b*x + c)/a
return -(b*x+c)/a;
}
float Line::getXGivenY( float y ){
if( b == 0 ){
cerr << "(Line::getXGivenY) Cannot calculate X coordinate\n" ;
return 0;
}
// ay + bx + c = 0 ==> bx = -(a*y + c)/a
return -(a*y+c)/b;
}
Line Line::makeLineFromTwoPoints( Vector2D pos1, Vector2D pos2 ){
// 1*y + bx + c = 0 => y = -bx - c
// with -b the direction coefficient (or slope)
// and c = - y - bx
float dA=1.0, dB, dC;
float dTemp = pos2.getX() - pos1.getX(); // determine the slope
if( fabs(dTemp) < EPSILON ){
// ay + bx + c = 0 with vertical slope=> a = 0, b = 1
dA = 0.0;
dB = 1.0;
}
else{
// y = (-b)x -c with -b the slope of the line
dA = 1.0;
dB = -(pos2.getY() - pos1.getY())/dTemp;
}
// ay + bx + c = 0 ==> c = -a*y - b*x
dC = - dA*pos2.getY() - dB * pos2.getX();
return Line( dA, dB, dC );
}
Line Line::makeLineFromPositionAndAngle( Vector2D vec, AngDeg angle ){
// calculate point somewhat further in direction 'angle' and make
// line from these two points.
return makeLineFromTwoPoints( vec, vec+Vector2D(1,angle,POLAR));
}
/******************************************************************************/
/********************** CLASS RECTANGLE ***************************************/
/******************************************************************************/
RectangleGeo::RectangleGeo( Vector2D pos, Vector2D pos2 ){
setRectanglePoints( pos, pos2 );
}
void RectangleGeo::setRectanglePoints( Vector2D pos1, Vector2D pos2 ){
posLeftTop.setX ( min( pos1.getX(), pos2.getX() ) );
posLeftTop.setY ( min( pos1.getY(), pos2.getY() ) );
posRightBottom.setX( max( pos1.getX(), pos2.getX() ) );
posRightBottom.setY( max( pos1.getY(), pos2.getY() ) );
}
void RectangleGeo::show( ostream& os ) const {
os << "rect(" << posLeftTop << " " << posRightBottom << ")";
}
bool RectangleGeo::isInside( Vector2D pos ) const {
return ( (getPosLeftTop().getX() <= pos.getX()) &&
(pos.getX() <= getPosRightBottom().getX()) &&
(getPosLeftTop().getY() <= pos.getY()) &&
(pos.getY() <= getPosRightBottom().getY()) );
}
/******************************************************************************/
/********************** CLASS CONE ********************************************/
/******************************************************************************/
Cone::Cone( Vector2D peak,
float fstAngle, float sndAngle,
float maxDistance, float minDistance ) {
setPeak( peak );
setAngles( fstAngle, sndAngle );
setMaxDistance( maxDistance );
setMinDistance( minDistance );
}
void Cone::show( ostream& os ) const {
os << "(p:" << peak << " fst:" << fstAngle << " snd:" << sndAngle
<< " maxDist:" << maxDistance << " minDist:" << minDistance << ")";
}
bool Cone::isInside( Vector2D pos ) const {
float dist = pos.distanceTo( peak );
float angle = (pos - peak).getDirection();
return ( ( minDistance <= dist && dist <= maxDistance &&
isAngInInterval( angle, fstAngle, sndAngle ) ) ||
( dist == 0 && minDistance == 0) );
}
/******************************************************************************/
/********************** TESTING PURPOSES *************************************/
/******************************************************************************/
/*
#include<iostream.h>
int main( void ){
float dFirst = 1.0;
float dRatio = 2.5;
float dSum = 63.4375;
float dLength = 4.0;
printf( "sum: %f\n", Geometry::getSumGeomSeries( dFirst, dRatio, dLength));
printf( "length: %f\n", Geometry::getLengthGeomSeries( dFirst, dRatio, dSum));
}
int main( void ){
Line l1(1,-1,3 );
Line l2(1,-0.2,10 );
Line l3 = Line::makeLineFromTwoPoints( Vector2D(1,-1), Vector2D(2,-2) );
l3.show();
cout << endl;
l1.show();
l2.show();
l1.getIntersection( l2 ).show();
}
int main( void ){
Line l( 1, -1, 0 );
Vector2D s1, s2;
int i = l.getCircleIntersectionPoints( Circle( Vector2D(1,1), 1 ), &s1, &s2 );
printf( "number of solutions: %d\n", i );
if( i == 2 ){
cout << s1 << " " << s2 ;
}
else if( i == 1 ){
cout << s1;
}
cout << "line: " << l << endl;
}
int main( void ){
Circle c11( Vector2D( 10, 0 ), 10);
Circle c12( Vector2D( 40, 3 ), 40 );
Circle c21( Vector2D( 0,0 ), 5);
Circle c22( Vector2D( 3,0 ), 40 );
Vector2D p1, p2;
cout << c11.getIntersectionArea( c21 ) << endl;
cout << c12.getIntersectionArea( c21 ) << endl;
cout << c22.getIntersectionArea( c11 ) << endl;
cout << c12.getIntersectionArea( c22 ) << endl;
return 0;
}
int main( void ){
cout << getBisectorTwoAngles( -155.3, 179.0 ) << endl;
cout << getBisectorTwoAngles( -179.3, 179.0 ) << endl;
}
int main( ) {
Vector2D pos = Vector2D::getVector2DFromPolar(10, 45);
cout << pos << endl;
cout << pos.getDirection() << endl;
cout << pos.getLength() << endl;
//Vector2D pos = Vector2D(10, 0);
//cout << pos << endl;
//cout << pos.getDirection() << endl;
//pos.rotate(90);
//cout << pos << endl;
//cout << pos.getDirection() << endl;
}
int main( ) {
Cone c( Vector2D(-10,-10), -170, -150, 50 );
c.show();
cout << endl
<< "isInside( Vector2D(0,0)): " << c.isInside( Vector2D(0,0) ) << endl
<< "isInside( Vector2D(0,-5)): " << c.isInside( Vector2D(0,-5) ) << endl
<< "isInside( Vector2D(-12,-11)): " << c.isInside( Vector2D(-12,-11) ) << endl;
}
*/

View File

@@ -1,864 +0,0 @@
/*
Copyright (c) 2000,2001, Jelle Kok, University of Amsterdam
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University of Amsterdam nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************************
* geometry.hh
*
* implements:
* class Vector2D
* namespace Geometry
* class Line
* class Circle
* class Rectangle
* class Cone
*
* requires:
*
* Maintainer: wenns, pagra
*
* Changelog:
*
* Note:
*************************************************************************************/
#ifndef GEOMETRY_HH
#define GEOMETRY_HH
#include <math.h> // needed for M_PI constant
#include <vector> // To fix include dependencies
#include <iostream>
using namespace std;
const float EPSILON = 0.001;
typedef float AngRad; /**< Type definition for angles in degrees. */
typedef float AngDeg; /**< Type definition for angles in radians. */
/**
* Converts an angle in radians to the corresponding angle in degrees.
* @param x an angle in radians
* @return the corresponding angle in degrees
*/
AngDeg Rad2Deg ( AngRad x );
/**
* Converts an angle in degrees to the corresponding angle in radians.
* @param x an angle in degrees
* @return the corresponding angle in radians
*/
AngRad Deg2Rad ( AngDeg x );
/**
* Returns the cosine of a given angle in degrees using the
* built-in cosine function that works with angles in radians.
* @param x an angle in degrees
* @return the cosine of the given angle
*/
float cosDeg ( AngDeg x );
/**
* Returns the sine of a given angle in degrees using the
* built-in sine function that works with angles in radians.
* @param x an angle in degrees
* @return the sine of the given angle
*/
float sinDeg ( AngDeg x );
/**
* Returns the tangent of a given angle in degrees using the
* built-in tangent function that works with angles in radians.
* @param x an angle in degrees
* @return the tangent of the given angle
*/
float tanDeg ( AngDeg x );
/**
* Rreturns the principal value of the arc tangent of x in degrees
* using the built-in arc tangent function which returns this value in radians.
* @param x a float value
* @return the arc tangent of the given value in degrees
*/
AngDeg atanDeg ( float x );
/**
* Returns the principal value of the arc tangent of y/x in
* degrees using the signs of both arguments to determine the quadrant of the
* return value. For this the built-in 'atan2' function is used which returns
* this value in radians.
* @param x a float value
* @param y a float value
* @return the arc tangent of y/x in degrees taking the signs of x and y into
* account
*/
float atan2Deg ( float x, float y );
/**
* Returns the principal value of the arc cosine of x in degrees
* using the built-in arc cosine function which returns this value in radians.
* @param x a float value
* @return the arc cosine of the given value in degrees
*/
AngDeg acosDeg ( float x );
/**
* Returns the principal value of the arc sine of x in degrees
* using the built-in arc sine function which returns this value in radians.
* @param x a float value
* @return the arc sine of the given value in degrees
*/
AngDeg asinDeg ( float x );
/**
* Returns a boolean value which indicates whether the value
* 'ang' (from interval [-180..180] lies in the interval [angMin..angMax].
* Examples: isAngInInterval( -100, 4, -150) returns false
* isAngInInterval( 45, 4, -150) returns true
* @param ang angle that should be checked
* @param angMin minimum angle in interval
* @param angMax maximum angle in interval
* @return boolean indicating whether ang lies in [angMin..angMax]
*/
bool isAngInInterval ( AngDeg ang, AngDeg angMin, AngDeg angMax );
/**
* Returns the bisector (average) of two angles. It deals
* with the boundary problem, thus when 'angMin' equals 170 and 'angMax'
* equals -100, -145 is returned.
* @param angMin minimum angle [-180,180]
* @param angMax maximum angle [-180,180]
* @return average of angMin and angMax.
*/
AngDeg getBisectorTwoAngles( AngDeg angMin, AngDeg angMax );
/**
* Returns the difference of two angles in degrees [-180,180]
* @param ang1 first angle [-180,180]
* @param ang2 second angle [-180,180]
*/
AngDeg getAngleDifference( AngDeg ang1, AngDeg ang2 );
/**
* Returns the absolute difference of two angles in degrees [0,180]
* @param ang1 first angle [-180,180]
* @param ang2 second angle [-180,180]
*/
AngDeg getAbsAngleDifference( AngDeg ang1, AngDeg ang2 );
/**
* Normalizes an arbitrary angle in 180 Deg System
* @param angle: the angle to normalize
* @return float (-180..180]
*/
float normalizeTo180Deg(float angle);
/**
* CoordSystem is an enumeration of the different specified coordinate systems.
* The two possibilities are CARTESIAN or POLAR. These values are for instance
* used in the initializing a Vector2D. The CoordSystem indicates whether
* the supplied arguments represent the position in cartesian or in polar
* coordinates.
*/
enum CoordSystemT {
CARTESIAN,
POLAR
};
/******************************************************************************/
/******************** CLASS VECTOR2D **************************************/
/******************************************************************************/
/**
* This class contains an x- and y-coordinate of a position (x,y) as member
* data and methods which operate on this position. The standard arithmetic
* operators are overloaded and can thus be applied to positions (x,y). It is
* also possible to represent a position in polar coordinates (r,phi), since
* the class contains a method to convert these into cartesian coordinates (x,y).
*/
class Vector2D {
private:
float x; /**< x-coordinate of this position */
float y; /**< y-coordinate of this position */
public:
/**
* Constructor for the Vector2D class. When the supplied Coordinate System
* type equals CARTESIAN, the arguments x and y denote the x- and y-coordinates
* of the new position. When it equals POLAR however, the arguments x and y
* denote the polar coordinates of the new position; in this case x is thus
* equal to the distance r from the origin and y is equal to the angle phi that
* the polar vector makes with the x-axis.
* @param x the x-coordinate of the new position when cs == CARTESIAN; the
* distance of the new position from the origin when cs = POLAR
* @param y the y-coordinate of the new position when cs = CARTESIAN; the
* angle that the polar vector makes with the x-axis when cs = POLAR
* @param cs a CoordSystemT indicating whether x and y denote cartesian
* coordinates or polar coordinates
* @return the Vector2D corresponding to the given arguments
*/
Vector2D ( float x = 0,
float y = 0,
CoordSystemT cs = CARTESIAN);
//////////////////// overloaded arithmetic operators /////////////////////////////
/*
* Note: all operators parametrized with float values apply these values to both
* coordinates of the vector
*/
/**
* Overloaded version of unary minus operator for Vector2Ds. The current Vector2D
* itself is left unchanged.
* @return a negated version of the current Vector2D
*/
Vector2D operator - ( ) { return ( Vector2D( -x, -y ) ); }
Vector2D operator + ( const float &d ) const { return ( Vector2D( x + d, y + d ) ); }
Vector2D operator + ( const Vector2D &p ) const { return ( Vector2D( x + p.x, y + p.y ) ); }
Vector2D operator - ( const float &d ) const { return ( Vector2D( x - d, y - d ) ); }
Vector2D operator - ( const Vector2D &p ) const { return ( Vector2D( x - p.x, y - p.y ) ); }
Vector2D operator * ( const float &d ) const { return ( Vector2D( x * d, y * d ) ); }
Vector2D operator * ( const Vector2D &p ) const { return ( Vector2D( x * p.x, y * p.y ) ); }
Vector2D operator / ( const float &d ) const { return ( Vector2D( x / d, y / d ) ); }
Vector2D operator / ( const Vector2D &p ) const { return ( Vector2D( x / p.x, y / p.y ) ); }
void operator = ( const float &d ) { x = d; y = d; }
void operator += ( const Vector2D &p ) { x += p.x; y += p.y; }
void operator += ( const float &d ) { x += d; y += d; }
void operator -= ( const Vector2D &p ) { x -= p.x; y -= p.y; }
void operator -= ( const float &d ) { x -= d; y -= d; }
void operator *= ( const Vector2D &p ) { x *= p.x; y *= p.y; }
void operator *= ( const float &d ) { x *= d; y *= d; }
void operator /= ( const Vector2D &p ) { x /= p.x; y /= p.y; }
void operator /= ( const float &d ) { x /= d; y /= d; }
bool operator != ( const Vector2D &p ) const { return ( ( x != p.x ) || ( y != p.y ) ); }
bool operator != ( const float &d ) const { return ( ( x != d ) || ( y != d ) ); }
bool operator == ( const Vector2D &p ) const { return ( ( x == p.x ) && ( y == p.y ) ); }
bool operator == ( const float &d ) const { return ( ( x == d ) && ( y == d ) ); }
//////////////////////// methods for producing output ////////////////////////////
friend ostream& operator << ( ostream &os,
Vector2D p );
/**
* Writes the current Vector2D to standard output. It can also print a polar
* representation of the current Vector2D.
* @param cs a CoordSystemtT indicating whether a POLAR or CARTESIAN
* representation of the current Vector2D should be printed
*/
void show ( CoordSystemT cs = CARTESIAN );
// accessors
void setX ( float newX ) { x = newX; }
float getX ( ) const { return x; }
void setY ( float newY ) { y = newY; }
float getY ( ) const { return y; }
/**
* decides if the Vector2D is invalid
* @return true, if the Vector2D is invalid, false otherwise
*/
bool isInvalid() const;
/**
* (re)sets the coordinates of the current Vector2D. The given
* coordinates can either be polar or Cartesian coordinates.
* @param newX a float value indicating either a new Cartesian x-coordinate when
* cs=CARTESIAN or a new polar r-coordinate (distance) when cs=POLAR
* @param newY a float value indicating either a new Cartesian y-coordinate when
* cs=CARTESIAN or a new polar phi-coordinate (angle) when cs=POLAR
* @param cs a CoordSystemT indicating whether x and y denote cartesian
* coordinates or polar coordinates
*/
void setVector2D ( float newX = 0,
float newY = 0,
CoordSystemT cs = CARTESIAN);
//wenns: temp workaround
//void setVector2D_Orig( float dX, float dY, CoordSystemT cs);
/**
* Determines the distance between the current Vector2D and a
* given Vector2D.
* @param p a Vector2D
* @return the distance between the current Vector2D and the given
* Vector2D
*/
inline float distanceTo ( const Vector2D &p ) const
{ return ( ( *this - p ).getLength( ) ); }
/**
* Adjusts the coordinates of the current Vector2D in such a way
* that the length of the corresponding vector equals the float value which
* is supplied as an argument.
* @param f a float value representing a new length
* @return the result of scaling the vector corresponding with the current
* Vector2D to the given length thus yielding a different Vector2D
*/
Vector2D setLength ( float f );
/**
* This method determines the length of Vector2D using the formula of Pythagoras.
* @return the length of the Vector2D
*/
inline float getLength ( ) const { return ( sqrt( x * x + y * y ) ); }
/**
* This method determines the direction of the current Vector2D (the phi-coordinate
* in polar representation)
* @return the direction in degrees of the current Vector2D
*/
inline AngDeg getDirection ( ) const { return ( atan2Deg( y, x ) ); }
/////////////////////// comparison methods for positions ///////////////////////////
/**
* Determines whether the current Vector2D is in front of a
* given Vector2D, i.e. whether the x-coordinate of the current Vector2D
* is larger than the x-coordinate of the given Vector2D.
* @param p a Vector2D to which the current Vector2D must be compared
* @return true when the current Vector2D is in front of the given
* Vector2D; false otherwise
*/
bool isInFrontOf ( const Vector2D &p )
{ return ( ( x > p.getX( ) ) ? true : false ); }
/**< similar as above */
bool isInFrontOf ( const float &d ) { return ( ( x > d ) ? true : false ); }
/**
* Determines whether the current Vector2D is behind a given
* Vector2D, i.e. whether the x-coordinate of the current Vector2D is
* smaller than the x-coordinate of the given Vector2D.
* @param p a Vector2D to which the current Vector2D must be compared
* @return true when the current Vector2D is behind the given Vector2D;
* false otherwise
*/
bool isBehindOf ( const Vector2D &p )
{ return ( ( x < p.getX( ) ) ? true : false ); }
/**< similar as above */
bool isBehindOf ( const float &d ) { return ( ( x < d ) ? true : false ); }
/**
* Determines whether the current Vector2D is to the left of a
* given Vector2D, i.e. whether the y-coordinate of the current Vector2D
* is smaller than the y-coordinate of the given Vector2D.
* @param p a Vector2D to which the current Vector2D must be compared
* @return true when the current Vector2D is to the left of the given
* Vector2D; false otherwise
*/
bool isLeftOf ( const Vector2D &p )
{ return ( ( y < p.getY( ) ) ? true : false ); }
/**< similar as above */
bool isLeftOf ( const float &d ) { return ( ( y < d ) ? true : false ); }
/**
* This method determines whether the current Vector2D is to the right of a
* given Vector2D, i.e. whether the y-coordinate of the current Vector2D
* is larger than the y-coordinate of the given Vector2D.
* @param p a Vector2D to which the current Vector2D must be compared
* @return true when the current Vector2D is to the right of the given
* Vector2D; false otherwise
*/
bool isRightOf ( const Vector2D &p )
{ return ( ( y > p.getY( ) ) ? true : false ); }
/**< similar as above */
bool isRightOf ( const float &d ) { return ( ( y > d ) ? true : false ); }
/**
* Determines whether the current Vector2D is in between two
* given Vector2Ds when looking in the x-direction, i.e. whether the current
* Vector2D is in front of the first argument and behind the second.
* @param p1 a Vector2D to which the current Vector2D must be compared
* @param p2 a Vector2D to which the current Vector2D must be compared
* @return true when the current Vector2D is in between the two given
* Vector2Ds when looking in the x-direction; false otherwise
*/
inline bool isBetweenX ( const Vector2D &p1,
const Vector2D &p2 )
{ return ( ( isInFrontOf( p1 ) && isBehindOf( p2 ) ) ? true : false ); }
/**< similar as above */
inline bool isBetweenX ( const float &d1,
const float &d2 )
{ return ( ( isInFrontOf( d1 ) && isBehindOf( d2 ) ) ? true : false ); }
/**
* Determines whether the current Vector2D is in between two
* given Vector2Ds when looking in the y-direction, i.e. whether the current
* Vector2D is to the right of the first argument and to the left of the
* second.
* @param p1 a Vector2D to which the current Vector2D must be compared
* @param p2 a Vector2D to which the current Vector2D must be compared
* @return true when the current Vector2D is in between the two given
* Vector2Ds when looking in the y-direction; false otherwise
*/
bool isBetweenY ( const Vector2D &p1,
const Vector2D &p2 )
{ return ( ( isRightOf( p1 ) && isLeftOf( p2 ) ) ? true : false ); }
/**< similar as above */
bool isBetweenY ( const float &d1,
const float &d2 )
{ return ( ( isRightOf( d1 ) && isLeftOf( d2 ) ) ? true : false ); }
/////////////////// conversion methods for positions ////////////////////////////
/**
* Normalizes a Vector2D by setting the length of the
* corresponding vector to 1.
* @return the result of normalizing the current Vector2D
*/
inline Vector2D normalize ( ) { return ( setLength( 1.0 ) ); }
/**
* Rotates the current Vector2D over a given angle .
* @param angle an angle in degrees over which the current Vector2D must be rotated
* @return the result of rotating the current Vector2D over the given angle
*/
Vector2D rotate ( AngDeg angle );
/**
* Converts the coordinates of the current Vector2D (which are represented in an
* global coordinate system with the origin at (0,0)) into relative coordinates
* in a different coordinate system (e.g. relative to a player). The new coordinate
* system is defined by the arguments to the method.
* @param origin the origin of the relative coordinate frame
* @param ang the angle between the world frame and the relative frame
* (reasoning from the world frame)
* @return the result of converting the current global Vector2D into a
* relative Vector2D
*/
Vector2D globalToRelative ( Vector2D orig,
AngDeg ang );
/**< similar to above */
Vector2D relativeToGlobal ( Vector2D orig,
AngDeg ang );
/**
* Returns a Vector2D that lies somewhere on the vector between
* the current Vector2D and a given Vector2D. The desired position is
* specified by a given fraction of this vector (e.g. 0.5 means exactly in
* the middle of the vector).
* @param p a Vector2D which defines the vector to the current Vector2D
* @param dFrac float representing the fraction of the connecting vector at
* which the desired Vector2D lies.
* @return the Vector2D which lies at fraction dFrac on the vector
* connecting p and the current Vector2D
*/
Vector2D getVector2DOnLineFraction( Vector2D &p,
float dFrac );
/**
* Converts a polar representation of a Vector2D into a Cartesian.
* @param dMag a float representing the polar r-coordinate, i.e. the distance
* from the point to the origin
* @param ang the angle that the polar vector makes with the x-axis, i.e. the
* polar phi-coordinate
* @return the result of converting the given polar representation into a
* Cartesian representation thus yielding a Cartesian Vector2D
*/
//static Vector2D getVector2DFromPolar( float dMag,
// AngDeg ang );
//wenns: temp workaround
static Vector2D getVector2DFromPolar/*_Orig*/( float dMag, AngDeg ang );
};
/******************************************************************************/
/********************* NAMESPACE GEOMETRY *********************************/
/******************************************************************************/
namespace Geometry {
///////////////////////////// geometric series //////////////////////////////////
/*
* A geometric series is one in which there is a constant ratio between each
* element and the one preceding it.
* Normally: s = a + ar + ar^2 + ... + ar^n
* Now: Sum = First + First*Ratio + First*Ratio^2 + .. + Fist*Ratio^n
*/
/**
* Determines the length of a geometric series given its first element, the sum
* of the elements in the series and the constant ratio between the elements.
* @param first first term of the series
* @param ratio ratio with which the the first term is multiplied
* @param sum the total sum of all the serie
* @return the length(n in above example) of the series
*/
float getLengthGeomSeries (float first, float ratio, float sum );
/**
* Determines the sum of a geometric series given its first element, the ratio and
* the number of steps in the series
* @param first first term of the series
* @param ratio ratio with which the the first term is multiplied
* @param length the number of steps to be taken into account
* @return the sum of the series
*/
float getSumGeomSeries ( float first, float ratio, float length );
/**
* Determines the sum of an infinite geometric series given its first element and
* the constant ratio between the elements. Note that such an infinite series will
* only converge when 0<r<1.
* @param first first term of the series
* @param ratio ratio with which the the first term is multiplied
* @return the sum of the series
*/
float getSumInfGeomSeries ( float first, float ratio );
/**
* Determines the first element of a geometric series given its element, the ratio
* and the number of steps in the series
* @param sum sum of the series
* @param ratio ratio with which the the first term is multiplied
* @param length the number of steps to be taken into account
* @return the first element (a) of a serie
*/
float getFirstGeomSeries ( float sum, float ratio, float length );
/**
* Determines the first element of an infinite geometric series given its first
* element and the constant ratio between the elements. Note that such an infinite
* series will only converge when 0<r<1.
* @param sum sum of the series
* @param ratio ratio with which the the first term is multiplied
* @return the first term of the series
*/
float getFirstInfGeomSeries ( float sum, float ratio );
/////////////////////////////// Pythagoras' Theorem ////////////////////////////////
/**
* Performs the abc formula (Pythagoras' Theorem) on the given parameters and puts
* the result in *s1 en *s2. It returns the number of found coordinates.
* @param a a parameter in abc formula
* @param b b parameter in abc formula
* @param c c parameter in abc formula
* @param *s1 first result of abc formula
* @param *s2 second result of abc formula
* @return number of found x-coordinates
*/
int abcFormula ( float a, float b, float c, float *s1, float *s2 );
};
/******************************************************************************/
/********************** CLASS CIRCLE ******************************************/
/******************************************************************************/
/**
* This class represents a circle. A circle is defined by one Vector2D
* (which denotes the center) and its radius.
*/
class Circle{
Vector2D posCenter; /**< Center of the circle */
float radius; /**< Radius of the circle */
public:
Circle( );
Circle( Vector2D pos, float r );
void show ( ostream& os = cout ) const;
// accessors
/**
* Sets the values of the circle.
* @param pos new center of the circle
* @param r new radius of the circle ( > 0 )
* @return bool indicating whether radius was set
*/
bool setCircle ( const Vector2D &pos, float r );
/**
* Sets the radius of the circle.
* @param r new radius of the circle ( > 0 )
* @return bool indicating whether radius was set
*/
bool setRadius ( const float r );
void setCenter ( const Vector2D &pos ) { posCenter = pos; }
float getRadius () const { return radius; }
Vector2D getCenter () const { return posCenter; }
float getCircumference () const { return 2.0*M_PI*getRadius(); }
float getArea () const { return M_PI*getRadius()*getRadius(); }
/**
* Returns a boolean that indicates whether 'pos' is located inside the circle.
* @param pos position of which should be checked whether it is located in the
* circle
* @return bool indicating whether pos lies inside the circle
*/
bool isInside ( const Vector2D &pos ) const
{ return posCenter.distanceTo( pos ) < getRadius(); }
/**
* Returns the two possible intersection points between two circles. This method
* returns the number of solutions that were found.
* @param c circle with which intersection should be found
* @param p1 will be filled with first solution
* @param p2 will be filled with second solution
* @return number of solutions.
*/
int getIntersectionPoints ( const Circle &c, Vector2D *p1, Vector2D *p2) const;
/**
* Returns the size of the intersection area of two circles.
* @param c circle with which intersection should be determined
* @return size of the intersection area.
*/
float getIntersectionArea ( const Circle &c ) const ;
bool calcTangentIntersectionPoints(const Vector2D, Vector2D &point1, Vector2D &point2);
};
/******************************************************************************/
/*********************** CLASS LINE *******************************************/
/******************************************************************************/
/**
* This class contains the representation of a line. A line is defined
* by the formula ay + bx + c = 0. The coefficients a, b and c are stored
* and used in the calculations.
*/
class Line {
// a line is defined by the formula: ay + bx + c = 0
float a; /**< This is the a coefficient in the line ay + bx + c = 0 */
float b; /**< This is the b coefficient in the line ay + bx + c = 0 */
float c; /**< This is the c coefficient in the line ay + bx + c = 0 */
public:
Line( float a, float b, float c );
Line();
//accessors
float getACoefficient ( ) const { return a; }
float getBCoefficient ( ) const { return b; }
float getCCoefficient ( ) const { return c; }
// print methods
void show( ostream& os = cout );
friend ostream& operator << (ostream & os, Line l);
/**
* Returns the intersection point between the current Line and the specified line.
* @param line line with which the intersection should be calculated.
* @return Vector2D position that is the intersection point.
*/
Vector2D getIntersection ( Line line );
/**
* This method calculates the intersection points between the current line
* and the circle specified with as center 'posCenter' and radius 'radius'.
* The number of solutions are returned and the corresponding points are put
* in the third and fourth argument of the method
* @param c circle with which intersection points should be found
* @param posSolution1 first intersection (if any)
* @param posSolution2 second intersection (if any)
*/
int getCircleIntersectionPoints( Circle circle,
Vector2D *posSolution1,
Vector2D *posSolution2 );
/**
* Returns the tangent line to a Vector2D. This is the line between the specified
* position and the closest point on the line to this position.
* @param pos Vector2D point with which tangent line is calculated.
* @return Line line tangent to this position
*/
Line getTangentLine ( Vector2D pos );
/**
* Returns the closest point on a line to a given position.
* @param pos point to which closest point should be determined
* @return Vector2D closest point on line to 'pos'.
*/
Vector2D getPointOnLineClosestTo ( Vector2D pos );
/**
* Returns the distance between a specified position and the closest point on
* the given line.
* @param pos position to which distance should be calculated
* @return float indicating the distance to the line.
*/
float distanceToPoint ( Vector2D pos );
/**
* Determines whether the projection of a point on the current line lies between
* two other points ('point1' and 'point2') that lie on the same line.
* @param pos point of which projection is checked.
* @param point1 first point on line
* @param point2 second point on line
* @return true when projection of 'pos' lies between 'point1' and 'point2'.
*/
bool isInBetween ( Vector2D pos,
Vector2D point1,
Vector2D point2 );
/**
* Calculates the y coordinate given the x coordinate
* @param x coordinate
* @return y coordinate on this line
*/
float getYGivenX ( float x );
/**
* Calculates the x coordinate given the y coordinate
* @param y coordinate
* @return x coordinate on this line
*/
float getXGivenY ( float y );
/////// static methods to make a line using an easier representation ////////
/**
* Creates a line given two points.
* @param pos1 first point
* @param pos2 second point
* @return line that passes through the two specified points.
*/
static Line makeLineFromTwoPoints ( Vector2D pos1,
Vector2D pos2 );
/**
* Creates a line given a position and an angle.
* @param vec position through which the line passes
* @param angle direction of the line.
* @return line that goes through position 'vec' with angle 'angle'.
*/
static Line makeLineFromPositionAndAngle ( Vector2D vec,
AngDeg angle );
};
/******************************************************************************/
/********************** CLASS RECTANGLE ***************************************/
/******************************************************************************/
/**
* This class represents a rectangle. A rectangle is defined by two Vector2Ds
* the one at the upper left corner and the one at the right bottom.
*/
class RectangleGeo {
Vector2D posLeftTop; /**< top left position of the rectangle */
Vector2D posRightBottom; /**< bottom right position of the rectangle */
public:
/**
* This is the constructor of a Rectangle. Two points will be given. The
* order does not matter as long as two opposite points are given (left
* top and right bottom or right top and left bottom).
* @param pos first point that defines corner of rectangle
* @param pos2 second point that defines other corner of rectangle
* @return rectangle with 'pos' and 'pos2' as opposite corners.
*/
RectangleGeo ( Vector2D pos, Vector2D pos2 );
void show ( ostream& os = cout ) const;
/**
* Determines whether the given position lies inside the current rectangle.
* @param pos position which is checked whether it lies in rectangle
* @return true when 'pos' lies in the rectangle, false otherwise
*/
bool isInside ( Vector2D pos ) const;
/**
* Sets the upper left and right bottom point of the current rectangle.
* @param pos first point that defines corner of rectangle
* @param pos2 second point that defines other corner of rectangle
*/
void setRectanglePoints( Vector2D pos1,
Vector2D pos2 );
void setPosLeftTop ( Vector2D pos ) { posLeftTop = pos; }
void setPosRightBottom ( Vector2D pos ) { posRightBottom = pos; }
Vector2D getPosLeftTop () const { return posLeftTop; }
Vector2D getPosRightBottom () const { return posRightBottom; }
};
/******************************************************************************/
/********************** CLASS CONE **** ***************************************/
/******************************************************************************/
/**
* This class represents a cone. A cone is defined by one point,
* two angles (-180 to 180), a maximum and a minimum distance.
* The point gives the peak of the cone. A point that lies in the cone
* is at least minimum distance and at most maximum distance away from
* the peak. Additionally the point must lie in the segment between
* the first angle (the left edge) and the second angle (the other edge).
* The area is defined by rotating the first edge (given by the first angle)
* clockwise (mit dem Uhrzeigersinn) till the second angle is reached.
*/
class Cone {
Vector2D peak; /**< peak of the cone */
float fstAngle; /**< the left edge. Start of clockwise rotation. */
float sndAngle; /**< the right edge. End of clockwise rotation. */
float maxDistance; /**< the max. distance a point on the cone can be away from the peak. */
float minDistance; /**< the min. distance a point on the cone must be away from the peak. */
public:
/**
* This is the constructor of a Cone. The cone lies between fstAngle and sndAngle,
* where sndAngle is interpreted as being clockwise rotated in relation
* to fstAngle.
* @param peak first point that defines top of the cone
* @param fstAngle absolute angle of the first edge
* @param sndAngle absolute angle of the second edge.
* @param maxDistance max. distance a point on the cone can be away from the peak
* @param minDistance min. distance a point on the cone must be away from the peak
*/
Cone( Vector2D peak,
float fstAngle, float sndAngle,
float maxDistance, float minDistance = 0 );
void show( ostream& os = cout ) const;
/**
* Determines whether the given position lies inside the current cone.
* @param pos position which is checked whether it lies in cone
* @return true when 'pos' lies in the cone, false otherwise
*/
bool isInside( Vector2D pos ) const;
inline void setPeak( Vector2D newPeak ) { peak = newPeak; }
inline void setAngles( float newFstAngle, float newSndAngle ) {
fstAngle = newFstAngle, sndAngle = newSndAngle;
}
inline void setFstAngle( float newFstAngle ) { fstAngle = newFstAngle; }
inline void setSndAngle( float newSndAngle ) { sndAngle = newSndAngle; }
inline void setMaxDistance( float newMaxDistance) { maxDistance = newMaxDistance; }
inline void setMinDistance( float newMinDistance) { minDistance = newMinDistance; }
};
#endif //Geometry.hh

View File

@@ -1,380 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 "global.h"
#include "options.h"
#include "asstring.h"
#include <iostream>
#include "SDL.h"
#include "surfaceDB.h"
using namespace std;
int GAME_LENGTH = 300000; // ms
int ITEM_LIFETIME = 20000; // ms
int ITEM_APPEAR_DELAY = 10000; // ms
int ITEM_APPEAR_RAND_DELAY = 20000; // ms
int ITEM_HEALTH_REPAIR_AMOUNT = 100;
int ITEM_HEATSEEKER_AMMO = 70;
int ITEM_NUKE_AMMO = 2;
int ITEM_DEFLECTOR_AMMO = 1;
int ITEM_DEFLECTOR_ACTIVATION_DIST = 200;
int ITEM_DEFLECTOR_POWER = 100;
int ITEM_DEFLECTOR_DURATION = 15000;
int ITEM_APPEAR_CHANCES[] = { 50, 20, 30, 30, 30, 50, 20, 20, 30, 20, 20 };
int GENERATE_ENEMY_DELAY = 100;
int GENERATE_ENEMY_RAND_DELAY = 2000;
int LIGHT_FIGHTER_MAX_SHIELD = 200;
int HEAVY_FIGHTER_MAX_SHIELD = 500;
int LIGHT_FIGHTER_MAX_DAMAGE = 200;
int HEAVY_FIGHTER_MAX_DAMAGE = 500;
int LIGHT_FIGHTER_SHIELD_RECHARGE = 80;
int HEAVY_FIGHTER_SHIELD_RECHARGE = 110;
int RACER_DEFLECTOR_ACTIVATION_DIST = 150;
int RACER_DEFLECTOR_POWER = 50;
int RACER_SONIC_ACTIVATION_DIST = 200;
int RACER_SONIC_POWER = 50;
int ENEMY_HITPOINTS[] = { 80, 120, 150, 2000, 1500, 1000, 1000, 3000 };
int ENEMY_COLLISION_DAMAGE[] = {20, 40, 0, 0, 0, 0, 0, 2000};
int ENEMY_DIES_ITEM_APPEAR_CHANCE[] = {15, 12, 8, 0, 0, 0, 0, 1};
int ENEMY_APPEAR_CHANCES[] = {40, 40, 10, 0, 0, 0, 0, 0};
int ENEMY_COOLDOWN_PRIMARY[] = {400, 400, 400, 50, 500, 100, 100, 300};
int ENEMY_COOLDOWN_SECONDARY[] = {0, 0, 2000, 0, 0, 0, 0, 600};
int ENEMY_RAND_WAIT_PRIMARY[] = {1500, 1000, 300, 80, 1000, 200, 200, 2000};
int ENEMY_RAND_WAIT_SECONDARY[] = {0, 0, 10000, 0, 0, 0, 0, 400};
int GENERATE_FORMATION_DELAY = 5000;
int GENERATE_FORMATION_RAND_DELAY = 20000;
int FORMATION_MAX_NR_ENEMYS[] = {7,7,7,6};
int FORMATION_SP_CHANCES[] = { 10, 10, 5, 5, 20, 10, 5, 20, 10, 20, 10 };
int FORMATION_SP_PRIMARY_DELAY[] = {0, 80, 120, 160,
500, 800, 1100,
150, 250, 150, 250};
int FORMATION_SP_PRIMARY_RAND_DELAY[] = { 0, 80, 120, 160,
1000, 1500, 2000,
0, 0, 0, 0 };
void parseGlobalConfigValues( int difficultyLevel ) {
Options *op = 0;
op = new Options( FN_DIFFICULTY_CONFIG +
asString(difficultyLevel) +
FN_DIFFICULTY_CONFIG_SUFFIX );
op->getInt( "GAME_LENGTH", GAME_LENGTH );
op->getInt( "ITEM_LIFETIME", ITEM_LIFETIME );
op->getInt( "ITEM_APPEAR_DELAY", ITEM_APPEAR_DELAY );
op->getInt( "ITEM_APPEAR_RAND_DELAY", ITEM_APPEAR_RAND_DELAY );
op->getInt( "ITEM_HEALTH_REPAIR_AMOUNT", ITEM_HEALTH_REPAIR_AMOUNT );
op->getInt( "ITEM_HEATSEEKER_AMMO", ITEM_HEATSEEKER_AMMO );
op->getInt( "ITEM_NUKE_AMMO", ITEM_NUKE_AMMO );
op->getInt( "ITEM_DEFLECTOR_AMMO", ITEM_DEFLECTOR_AMMO );
op->getInt( "ITEM_DEFLECTOR_DURATION", ITEM_DEFLECTOR_DURATION );
op->getInt( "ITEM_DEFLECTOR_ACTIVATION_DIST", ITEM_DEFLECTOR_ACTIVATION_DIST );
op->getInt( "ITEM_DEFLECTOR_POWER", ITEM_DEFLECTOR_POWER );
op->getInt( "GENERATE_ENEMY_DELAY", GENERATE_ENEMY_DELAY );
op->getInt( "GENERATE_ENEMY_RAND_DELAY", GENERATE_ENEMY_RAND_DELAY );
op->getInt( "LIGHT_FIGHTER_MAX_SHIELD", LIGHT_FIGHTER_MAX_SHIELD );
op->getInt( "HEAVY_FIGHTER_MAX_SHIELD", HEAVY_FIGHTER_MAX_SHIELD );
op->getInt( "LIGHT_FIGHTER_MAX_DAMAGE", LIGHT_FIGHTER_MAX_DAMAGE );
op->getInt( "HEAVY_FIGHTER_MAX_DAMAGE", HEAVY_FIGHTER_MAX_DAMAGE );
op->getInt( "LIGHT_FIGHTER_SHIELD_RECHARGE", LIGHT_FIGHTER_SHIELD_RECHARGE );
op->getInt( "HEAVY_FIGHTER_SHIELD_RECHARGE", HEAVY_FIGHTER_SHIELD_RECHARGE );
op->getInt( "HEAVY_FIGHTER_DEFLECTOR_ACTIVATION_DIST",
RACER_DEFLECTOR_ACTIVATION_DIST );
op->getInt( "HEAVY_FIGHTER_DEFLECTOR_POWER",
RACER_DEFLECTOR_POWER );
op->getInt( "FIGHTER_HITPOINTS", ENEMY_HITPOINTS[ FIGHTER ] );
op->getInt( "BOMBER_HITPOINTS", ENEMY_HITPOINTS[ BOMBER ] );
op->getInt( "TURRET_HITPOINTS", ENEMY_HITPOINTS[ TANK ] );
op->getInt( "BOSS1_MAIN_GUN_HITPOINTS", ENEMY_HITPOINTS[ BOSS_1_MAIN_GUN ] );
op->getInt( "BOSS1_ROCKET_LAUNCHER_HITPOINTS", ENEMY_HITPOINTS[ BOSS_1_ROCKET_LAUNCHER ] );
op->getInt( "BOSS1_SHOT_BATTERY_LEFT_HITPOINTS",
ENEMY_HITPOINTS[ BOSS_1_SHOT_BATTERY_LEFT ] );
op->getInt( "BOSS1_SHOT_BATTERY_RIGHT_HITPOINTS",
ENEMY_HITPOINTS[ BOSS_1_SHOT_BATTERY_RIGHT ] );
op->getInt( "COLLISION_DAMAGE_FIGHTER", ENEMY_COLLISION_DAMAGE[ FIGHTER ] );
op->getInt( "COLLISION_DAMAGE_BOMBER", ENEMY_COLLISION_DAMAGE[ BOMBER ] );
op->getInt( "ENEMY_DIES_ITEM_APPEAR_CHANCE_FIGHTER",
ENEMY_DIES_ITEM_APPEAR_CHANCE[ FIGHTER ] );
op->getInt( "ENEMY_DIES_ITEM_APPEAR_CHANCE_BOMBER",
ENEMY_DIES_ITEM_APPEAR_CHANCE[ BOMBER ] );
op->getInt( "ENEMY_DIES_ITEM_APPEAR_CHANCE_TURRET",
ENEMY_DIES_ITEM_APPEAR_CHANCE[ TANK ] );
op->getInt( "ENEMY_APPEAR_CHANCE_FIGHTER",
ENEMY_APPEAR_CHANCES[ FIGHTER ] );
op->getInt( "ENEMY_APPEAR_CHANCE_BOMBER",
ENEMY_APPEAR_CHANCES[ BOMBER ] );
op->getInt( "ENEMY_APPEAR_CHANCE_TURRET",
ENEMY_APPEAR_CHANCES[ TANK ] );
op->getInt( "ENEMY_COOLDOWN_FIGHTER",
ENEMY_COOLDOWN_PRIMARY[ FIGHTER ] );
op->getInt( "ENEMY_COOLDOWN_BOMBER",
ENEMY_COOLDOWN_PRIMARY[ BOMBER ] );
op->getInt( "ENEMY_COOLDOWN_TURRET",
ENEMY_COOLDOWN_PRIMARY[ TANK ] );
op->getInt( "ENEMY_COOLDOWN_BOSS1_MAIN_GUN",
ENEMY_COOLDOWN_PRIMARY[ BOSS_1_MAIN_GUN ] );
op->getInt( "ENEMY_COOLDOWN_BOSS1_ROCKET_LAUNCHER",
ENEMY_COOLDOWN_PRIMARY[ BOSS_1_ROCKET_LAUNCHER] );
op->getInt( "ENEMY_COOLDOWN_BOSS1_SHOT_BATTERY_LEFT",
ENEMY_COOLDOWN_PRIMARY[ BOSS_1_SHOT_BATTERY_LEFT] );
op->getInt( "ENEMY_COOLDOWN_BOSS1_SHOT_BATTERY_RIGHT",
ENEMY_COOLDOWN_PRIMARY[ BOSS_1_SHOT_BATTERY_RIGHT ] );
op->getInt( "ENEMY_COOLDOWN_SECONDARY_TURRET", ENEMY_COOLDOWN_SECONDARY[ TANK ] );
op->getInt( "ENEMY_RAND_WAIT_FIGHTER",
ENEMY_RAND_WAIT_PRIMARY[ FIGHTER ] );
op->getInt( "ENEMY_RAND_WAIT_BOMBER",
ENEMY_RAND_WAIT_PRIMARY[ BOMBER ] );
op->getInt( "ENEMY_RAND_WAIT_TURRET",
ENEMY_RAND_WAIT_PRIMARY[ TANK ] );
op->getInt( "ENEMY_RAND_WAIT_BOSS1_MAIN_GUN",
ENEMY_RAND_WAIT_PRIMARY[ BOSS_1_MAIN_GUN ] );
op->getInt( "ENEMY_RAND_WAIT_BOSS1_ROCKET_LAUNCHER",
ENEMY_RAND_WAIT_PRIMARY[ BOSS_1_ROCKET_LAUNCHER ] );
op->getInt( "ENEMY_RAND_WAIT_BOSS1_SHOT_BATTERY_LEFT",
ENEMY_RAND_WAIT_PRIMARY[ BOSS_1_SHOT_BATTERY_LEFT ] );
op->getInt( "ENEMY_RAND_WAIT_BOSS1_SHOT_BATTERY_RIGHT",
ENEMY_RAND_WAIT_PRIMARY[ BOSS_1_SHOT_BATTERY_RIGHT ] );
op->getInt( "ENEMY_RAND_WAIT_SECONDARY_TURRET",
ENEMY_RAND_WAIT_SECONDARY[ TANK ] );
op->getInt( "ITEM_APPEAR_CHANCE_PRIMARY_UPGRADE",
ITEM_APPEAR_CHANCES[ ITEM_PRIMARY_UPGRADE ] );
op->getInt( "ITEM_APPEAR_CHANCE_DUMBRIFE_DOUBLE",
ITEM_APPEAR_CHANCES[ ITEM_DUMBFIRE_DOUBLE ] );
op->getInt( "ITEM_APPEAR_CHANCE_KICK_ASS_ROCKET",
ITEM_APPEAR_CHANCES[ ITEM_KICK_ASS_ROCKET ] );
op->getInt( "ITEM_APPEAR_CHANCE_HELLFIRE",
ITEM_APPEAR_CHANCES[ ITEM_HELLFIRE ] );
op->getInt( "ITEM_APPEAR_CHANCE_MACHINE_GUN",
ITEM_APPEAR_CHANCES[ ITEM_MACHINE_GUN ] );
op->getInt( "ITEM_APPEAR_CHANCE_HEALTH",
ITEM_APPEAR_CHANCES[ ITEM_HEALTH ] );
op->getInt( "ITEM_APPEAR_CHANCE_HEATSEEKER",
ITEM_APPEAR_CHANCES[ ITEM_HEATSEEKER ] );
op->getInt( "ITEM_APPEAR_CHANCE_NUKE",
ITEM_APPEAR_CHANCES[ ITEM_NUKE ] );
op->getInt( "ITEM_APPEAR_CHANCE_DEFLECTOR",
ITEM_APPEAR_CHANCES[ ITEM_DEFLECTOR ] );
op->getInt( "ITEM_APPEAR_CHANCE_ENERGY_BEAM",
ITEM_APPEAR_CHANCES[ ITEM_ENERGY_BEAM ] );
op->getInt( "ITEM_APPEAR_CHANCE_LASER",
ITEM_APPEAR_CHANCES[ ITEM_LASER ] );
op->getInt( "GENERATE_FORMATION_DELAY", GENERATE_FORMATION_DELAY );
op->getInt( "GENERATE_FORMATION_RAND_DELAY", GENERATE_FORMATION_RAND_DELAY );
op->getInt( "FORMATION_MAX_NR_ENEMYS_V",
FORMATION_MAX_NR_ENEMYS[ FORMATION_V ] );
op->getInt( "FORMATION_MAX_NR_ENEMYS_REVERSE_V",
FORMATION_MAX_NR_ENEMYS[ FORMATION_REVERSE_V ] );
op->getInt( "FORMATION_MAX_NR_ENEMYS_BLOCK",
FORMATION_MAX_NR_ENEMYS[ FORMATION_BLOCK ] );
op->getInt( "FORMATION_MAX_NR_ENEMYS_LINE",
FORMATION_MAX_NR_ENEMYS[ FORMATION_LINE ] );
for ( int i = 0; i < NR_FORMATION_TYPES; i++ ) {
if ( FORMATION_MAX_NR_ENEMYS[ i ] > FORMATION_MAX_NR_ENEMYS_HARD_LIMIT[ i ] )
FORMATION_MAX_NR_ENEMYS[ i ] = FORMATION_MAX_NR_ENEMYS_HARD_LIMIT[ i ];
}
op->getInt( "FORMATION_SP_CHANCE_NONE",
FORMATION_SP_CHANCES[ FORMATION_SP_NONE ] );
op->getInt( "FORMATION_SP_CHANCE_RAND_FAST",
FORMATION_SP_CHANCES[ FORMATION_SP_RAND_FAST ] );
op->getInt( "FORMATION_SP_CHANCE_RAND_MEDIUM",
FORMATION_SP_CHANCES[ FORMATION_SP_RAND_MEDIUM ] );
op->getInt( "FORMATION_SP_CHANCE_RAND_SLOW",
FORMATION_SP_CHANCES[ FORMATION_SP_RAND_SLOW ] );
op->getInt( "FORMATION_SP_CHANCE_VOLLEY_FAST",
FORMATION_SP_CHANCES[ FORMATION_SP_VOLLEY_FAST ] );
op->getInt( "FORMATION_SP_CHANCE_VOLLEY_MEDIUM",
FORMATION_SP_CHANCES[ FORMATION_SP_VOLLEY_MEDIUM ] );
op->getInt( "FORMATION_SP_CHANCE_VOLLEY_SLOW",
FORMATION_SP_CHANCES[ FORMATION_SP_VOLLEY_SLOW ] );
op->getInt( "FORMATION_SP_CHANCE_LEFT_RIGHT_FAST",
FORMATION_SP_CHANCES[ FORMATION_SP_LEFT_RIGHT_FAST ] );
op->getInt( "FORMATION_SP_CHANCE_LEFT_RIGHT_MEDIUM",
FORMATION_SP_CHANCES[ FORMATION_SP_LEFT_RIGHT_MEDIUM ] );
op->getInt( "FORMATION_SP_CHANCE_RIGHT_LEFT_FAST",
FORMATION_SP_CHANCES[ FORMATION_SP_RIGHT_LEFT_FAST ] );
op->getInt( "FORMATION_SP_CHANCE_RIGHT_LEFT_MEDIUM",
FORMATION_SP_CHANCES[ FORMATION_SP_RIGHT_LEFT_MEDIUM ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_RAND_FAST",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_RAND_FAST ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_RAND_MEDIUM",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_RAND_MEDIUM ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_RAND_SLOW",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_RAND_SLOW ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_VOLLEY_FAST",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_VOLLEY_FAST ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_VOLLEY_MEDIUM",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_VOLLEY_MEDIUM ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_VOLLEY_SLOW",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_VOLLEY_SLOW ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_LEFT_RIGHT_FAST",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_LEFT_RIGHT_FAST ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_LEFT_RIGHT_MEDIUM",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_LEFT_RIGHT_MEDIUM ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_RIGHT_LEFT_FAST",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_RIGHT_LEFT_FAST ] );
op->getInt( "FORMATION_SP_PRIM_DELAY_RIGHT_LEFT_MEDIUM",
FORMATION_SP_PRIMARY_DELAY[ FORMATION_SP_RIGHT_LEFT_MEDIUM ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_RAND_FAST",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_RAND_FAST ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_RAND_MEDIUM",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_RAND_MEDIUM ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_RAND_SLOW",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_RAND_SLOW ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_VOLLEY_FAST",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_VOLLEY_FAST ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_VOLLEY_MEDIUM",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_VOLLEY_MEDIUM ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_VOLLEY_SLOW",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_VOLLEY_SLOW ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_LEFT_RIGHT_FAST",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_LEFT_RIGHT_FAST ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_LEFT_RIGHT_MEDIUM",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_LEFT_RIGHT_MEDIUM ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_RIGHT_LEFT_FAST",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_RIGHT_LEFT_FAST ] );
op->getInt( "FORMATION_SP_PRIM_RAND_DELAY_RIGHT_LEFT_MEDIUM",
FORMATION_SP_PRIMARY_RAND_DELAY[ FORMATION_SP_RIGHT_LEFT_MEDIUM ] );
delete op;
}
/////////////////////
int getRandValue( const int *choicesWeights, int nrChoices, int sumWeights ) {
int sum = 0;
if ( sumWeights != 0 ) sum = sumWeights;
else for ( int i = 0; i < nrChoices; i++ ) sum += choicesWeights[ i ];
if ( sum == 0 ) {
cout << "Error in getRandValue: sum==0!" << endl;
exit(1);
}
int val = rand() % sum;
int idx = 0;
int tmpSum = 0;
while ( idx < nrChoices ) {
tmpSum += choicesWeights[ idx ];
if ( val < tmpSum ) {
return idx;
}
idx++;
}
cout << "Error in getRandValue: val: " << val << endl;
exit(1);
}
/////////////////////////////
void initAllSurfaces() {
surfaceDB.loadSurface("./images/fighter.bmp" );
surfaceDB.loadSurface("./images/fighterShadow.bmp", true);
surfaceDB.loadSurface("./images/bomber.bmp");
surfaceDB.loadSurface("./images/bomberShadow.bmp", true);
surfaceDB.loadSurface("./images/tank.bmp");
surfaceDB.loadSurface("./images/boss1MainGun.bmp");
surfaceDB.loadSurface("./images/boss1RocketLauncher.bmp");
surfaceDB.loadSurface("./images/boss1ShotBatteryLeft.bmp");
surfaceDB.loadSurface("./images/boss1ShotBatteryRight.bmp");
surfaceDB.loadSurface("./images/wreckFighter.bmp");
surfaceDB.loadSurface("./images/wreckBomber.bmp");
surfaceDB.loadSurface("./images/wreckTank.bmp");
surfaceDB.loadSurface("./images/wreckBoss1.bmp");
surfaceDB.loadSurface("./images/wreckBossBackground.bmp");
surfaceDB.loadSurface("./images/boss.bmp");
surfaceDB.loadSurface("./images/normalShot.bmp");
surfaceDB.loadSurface("./images/heavyShot.bmp");
surfaceDB.loadSurface("./images/normalShotHF.bmp");
surfaceDB.loadSurface("./images/dumbfire.bmp");
surfaceDB.loadSurface("./images/kickAssRocket.bmp");
surfaceDB.loadSurface("./images/kickAssRocketShadow.bmp", true);
surfaceDB.loadSurface("./images/hellfire.bmp");
surfaceDB.loadSurface("./images/hellfireShadow.bmp", true);
surfaceDB.loadSurface("./images/machineGun.bmp");
surfaceDB.loadSurface("./images/energyBeam.bmp", true);
surfaceDB.loadSurface("./images/laser.bmp");
surfaceDB.loadSurface("./images/enemyShotNormal.bmp");
surfaceDB.loadSurface("./images/tankRocket.bmp");
surfaceDB.loadSurface("./images/tankRocketShadow.bmp", true);
surfaceDB.loadSurface("./images/heatseeker.bmp");
surfaceDB.loadSurface("./images/shotNuke.bmp");
surfaceDB.loadSurface("./images/shotNukeShadow.bmp", true);
surfaceDB.loadSurface("./images/nukeEffect.bmp");
surfaceDB.loadSurface("./images/sonic.bmp");
surfaceDB.loadSurface("./images/itemPrimaryUpgrade.bmp");
surfaceDB.loadSurface("./images/itemDumbfireDouble.bmp");
surfaceDB.loadSurface("./images/itemKickAssRocket.bmp");
surfaceDB.loadSurface("./images/itemHellfire.bmp");
surfaceDB.loadSurface("./images/itemMachineGun.bmp");
surfaceDB.loadSurface("./images/itemHealth.bmp");
surfaceDB.loadSurface("./images/itemHeatseeker.bmp");
surfaceDB.loadSurface("./images/itemNuke.bmp");
surfaceDB.loadSurface("./images/itemDeflector.bmp");
surfaceDB.loadSurface("./images/itemEnergyBeam.bmp");
surfaceDB.loadSurface("./images/itemLaser.bmp");
surfaceDB.loadSurface("./images/background.bmp");
surfaceDB.loadSurface("./images/lightFighterShieldDamaged.bmp");
surfaceDB.loadSurface("./images/heavyFighterShieldDamaged.bmp");
surfaceDB.loadSurface("./images/heavyFighterDeflector.bmp", true);
//surfaceDB.loadSurface("./images/font-20red");
//surfaceDB.loadSurface("./images/font-20blue");
surfaceDB.loadSurface("./images/explosion.bmp", true);
surfaceDB.loadSurface("./images/explosionEnemy.bmp", true);
surfaceDB.loadSurface("./images/bannerExcellent.bmp", true);
surfaceDB.loadSurface("./images/bannerYouRule.bmp", true);
surfaceDB.loadSurface("./images/bannerHeiho.bmp", true);
surfaceDB.loadSurface("./images/bannerHealth.bmp", true);
surfaceDB.loadSurface("./images/bannerEnemysKilled.bmp", true);
surfaceDB.loadSurface("./images/bannerBonus100.bmp", true);
surfaceDB.loadSurface("./images/bannerBonus200.bmp", true);
}

View File

@@ -1,692 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 GLOBAL_H
#define GLOBAL_H
#include <string>
#include "SdlForwardCompat.h"
class Racers;
class Enemys;
class Shots;
class Explosions;
class Items;
class Wrecks;
class Banners;
class SmokePuffs;
class Options;
extern Racers *racers;
extern Enemys *enemys;
extern Shots *shots;
extern Explosions *explosions;
extern Items *items;
extern Wrecks *wrecks;
extern Banners *banners;
extern SmokePuffs *smokePuffs;
extern Options *levelConf;
extern int GAME_LENGTH;
extern bool scrollingOn;
extern bool nukeIsInPlace;
extern bool playMusicOn;
extern bool onePlayerGame;
extern bool arcadeGame;
extern int difficultyLevel;
extern float actBackgroundPos;
void parseGlobalConfigValues( int difficultyLevel );
int getRandValue( const int *choicesWeights, int nrChoices, int sumWeights=0 );
void initAllSurfaces();
// screen options
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int BIT_DEPTH = 16;
const int MAX_PLAYER_CNT = 2;
// the speed of the background scrolling
const float SCROLL_SPEED = 20;
// where is the absolute border of no return for the heatseeker?
// they have a chance to return within SCREEN_BORDER pixels outside the screen...
// outside this area shots are deleted
const int SHOT_SCREEN_BORDER = 50;
/********************************* ARCADE MODE ***********************************/
const int ARCADE_DIFFICULTY_LEVEL = 4;
const int ARCADE_POINTS_PER_TEN_SECONDS = 30;
// BANNER_RANDOM: no real mode, just the value to choose one randomly
enum BannerModes { BANNER_MODE_FLY_FROM_LEFT=0,
BANNER_MODE_FROM_TOP,
BANNER_MODE_ITEM_COLLECTED_SINGLE_PLAYER,
BANNER_MODE_ITEM_COLLECTED_PLAYER_ONE,
BANNER_MODE_ITEM_COLLECTED_PLAYER_TWO,
BANNER_MODE_RANDOM=1000 };
const int BANNER_MODE_LIFETIME[] = { 5000, 5000, 2000, 2000, 2000 };
const int NR_BANNER_MODES = 2;
enum BannerTexts { BANNER_EXCELLENT=0, BANNER_YOU_RULE, BANNER_HEIHO,
BANNER_HEALTH, BANNER_ENEMYS_KILLED,
BANNER_ITEM_HEALTH_COLLECTED,
BANNER_ITEM_PRIMARY_UPGRADE_COLLECTED,
BANNER_ITEM_DUMBFIRE_DOUBLE_COLLECTED,
BANNER_ITEM_KICK_ASS_ROCKET_COLLECTED,
BANNER_ITEM_HELLFIRE_COLLECTED,
BANNER_ITEM_MACHINE_GUN_COLLECTED,
BANNER_ITEM_HEATSEEKER_COLLECTED,
BANNER_ITEM_NUKE_COLLECTED,
BANNER_ITEM_DEFLECTOR_COLLECTED,
BANNER_ITEM_ENERGY_BEAM_COLLECTED,
BANNER_ITEM_LASER_COLLECTED };
const std::string FN_BANNER_TEXTS[] =
{ "./images/bannerExcellent.bmp",
"./images/bannerYouRule.bmp",
"./images/bannerHeiho.bmp",
"./images/bannerHealth.bmp",
"./images/bannerEnemysKilled.bmp",
"./images/bannerItemHealthCollected.bmp",
"./images/bannerItemPrimaryUpgradeCollected.bmp",
"./images/bannerItemDumbfireDoubleCollected.bmp",
"./images/bannerItemKickAssRocketCollected.bmp",
"./images/bannerItemHellfireCollected.bmp",
"./images/bannerItemMachineGunCollected.bmp",
"./images/bannerItemHeatseekerCollected.bmp",
"./images/bannerItemNukeCollected.bmp",
"./images/bannerItemDeflectorCollected.bmp",
"./images/bannerItemEnergyBeamCollected.bmp",
"./images/bannerItemLaserCollected.bmp" };
const int NR_BANNER_TEXTS = 3;
enum BannerBoni { BANNER_BONUS_100=0,
BANNER_BONUS_200,
BANNER_BONUS_NONE=1000 };
const std::string FN_BANNER_BONUS[] =
{ "./images/bannerBonus100.bmp",
"./images/bannerBonus200.bmp" };
const int NR_BANNER_BONI = 2;
const float ARCADE_POINTS_FOR_FORMATION_DESTRUCTION = 100;
const BannerBoni ARCADE_BONUS_FOR_FORMATION_DESTRUCTION = BANNER_BONUS_100;
const float ARCADE_POINTS_FOR_ENEMYS_KILLED = 200;
const BannerBoni ARCADE_BONUS_FOR_ENEMYS_KILLED = BANNER_BONUS_200;
const int NR_ARCACE_POINTS_FOR_HEALTH_ITEM = 7;
const float ARCADE_POINTS_FOR_HEALTH_ITEM[ NR_ARCACE_POINTS_FOR_HEALTH_ITEM ] =
{ 2000, 5000, 10000, 15000, 25000, 35000, 50000 };
/********************************** ITEMS ****************************************/
enum ItemTypes { ITEM_PRIMARY_UPGRADE=0,
ITEM_DUMBFIRE_DOUBLE,
ITEM_KICK_ASS_ROCKET,
ITEM_HELLFIRE,
ITEM_MACHINE_GUN,
ITEM_HEALTH,
ITEM_HEATSEEKER,
ITEM_NUKE,
ITEM_DEFLECTOR,
ITEM_LASER,
ITEM_ENERGY_BEAM };
const int NR_ITEM_TYPES = 11;
extern int ITEM_LIFETIME; // ms
extern int ITEM_APPEAR_DELAY; // ms
extern int ITEM_APPEAR_RAND_DELAY; // ms
// ITEM_HEALTH_REPAIR_AMOUNT points are restored, if collected
extern int ITEM_HEALTH_REPAIR_AMOUNT;
// if collected by heavy fighter the amount will be multiplied by this factor
const float ITEM_HEALTH_REPAIR_FACTOR_HEAVY_FIGHTER = 2.0;
// if collected ITEM_HEATSEEKER_AMMO rockets can be fired
extern int ITEM_HEATSEEKER_AMMO;
extern int ITEM_NUKE_AMMO;
extern int ITEM_DEFLECTOR_AMMO;
extern int ITEM_DEFLECTOR_DURATION;
extern int ITEM_DEFLECTOR_ACTIVATION_DIST;
extern int ITEM_DEFLECTOR_POWER;
// the items have different probabilities to appear.
// bigger number -> greater chance
extern int ITEM_APPEAR_CHANCES[];
enum ExplosionTypes { EXPLOSION_NORMAL_AIR=0, EXPLOSION_NORMAL_GROUND };
const int NR_EXPLOSION_TYPES = 2;
const int LIFETIME_EXPL_NORMAL = 1500;
const int NUKE_EFFECT_DURATION = 1000;
const int NUKE_QUAKE_EFFECT = 40;
enum ShipTypes { LIGHT_FIGHTER=0, HEAVY_FIGHTER };
const int NR_SHIPS = 2;
/*********************************** SHOTS ********************************/
enum ShotTypes { SHOT_NORMAL=0,
SHOT_NORMAL_HEAVY,
SHOT_DOUBLE,
SHOT_DOUBLE_HEAVY,
SHOT_TRIPLE,
SHOT_HF_NORMAL,
SHOT_HF_DOUBLE,
SHOT_HF_TRIPLE,
SHOT_HF_QUATTRO,
SHOT_HF_QUINTO,
SHOT_DUMBFIRE=100,
SHOT_DUMBFIRE_DOUBLE,
SHOT_KICK_ASS_ROCKET,
SHOT_HELLFIRE,
SHOT_MACHINE_GUN,
SHOT_ENERGY_BEAM,
SHOT_HF_DUMBFIRE,
SHOT_HF_DUMBFIRE_DOUBLE,
SHOT_HF_KICK_ASS_ROCKET,
SHOT_HF_LASER,
ENEMY_SHOT_NORMAL=1000,
ENEMY_SHOT_TANK_ROCKET,
SPECIAL_SHOT_HEATSEEKER=10000,
SPECIAL_SHOT_NUKE };
const int NR_SECONDARY_WEAPONS = 10;
enum SpecialTypes { SPECIAL_NONE=0, SPECIAL_NUKE, SPECIAL_HEATSEEKER, SPECIAL_DEFLECTOR };
const int NR_SPECIALS = 4;
// after that many ms the shot is expired
const int LIFETIME_SHOT_NORMAL = 5000;
const int LIFETIME_SHOT_NORMAL_HEAVY = 5000;
const int LIFETIME_SHOT_DOUBLE = 5000;
const int LIFETIME_SHOT_DOUBLE_HEAVY = 5000;
const int LIFETIME_SHOT_TRIPLE = 5000;
const int LIFETIME_SHOT_HF_NORMAL = 6000;
const int LIFETIME_SHOT_HF_DOUBLE = 6000;
const int LIFETIME_SHOT_HF_TRIPLE = 6000;
const int LIFETIME_SHOT_HF_QUATTRO = 6000;
const int LIFETIME_SHOT_HF_QUINTO = 6000;
const int LIFETIME_SHOT_DUMBFIRE = 6000;
const int LIFETIME_SHOT_DUMBFIRE_DOUBLE = 6000;
const int LIFETIME_SHOT_KICK_ASS_ROCKET = 7000;
const int LIFETIME_SHOT_HELLFIRE = 6000;
const int LIFETIME_SHOT_MACHINE_GUN = 5000;
const int LIFETIME_SHOT_ENERY_BEAM = 5000;
const int LIFETIME_SHOT_HF_DUMBFIRE = 6000;
const int LIFETIME_SHOT_HF_DUMBFIRE_DOUBLE = 6000;
const int LIFETIME_SHOT_HF_KICK_ASS_ROCKET = 7000;
const int LIFETIME_SHOT_HF_LASER = 2000;
const int LIFETIME_SPECIAL_SHOT_HEATSEEKER = 10000;
const int LIFETIME_SPECIAL_SHOT_NUKE = 10000;
const int VEL_SHOT_NORMAL = 150;
const int VEL_SHOT_NORMAL_HEAVY = 150;
const int VEL_SHOT_DOUBLE = 150;
const int VEL_SHOT_DOUBLE_HEAVY = 150;
const int VEL_SHOT_TRIPLE = 150;
const int VEL_SHOT_HF_NORMAL = 180;
const int VEL_SHOT_HF_DOUBLE = 180;
const int VEL_SHOT_HF_TRIPLE = 180;
const int VEL_SHOT_HF_QUATTRO = 180;
const int VEL_SHOT_HF_QUINTO = 180;
const int VEL_SHOT_DUMBFIRE = 100;
const int VEL_SHOT_DUMBFIRE_DOUBLE = 100;
const int VEL_SHOT_KICK_ASS_ROCKET = 80;
const int VEL_SHOT_HELLFIRE = 110;
const int VEL_SHOT_MACHINE_GUN = 130;
const int VEL_SHOT_ENERGY_BEAM = 105;
const int VEL_SHOT_HF_DUMBFIRE = 160;
const int VEL_SHOT_HF_DUMBFIRE_DOUBLE = 160;
const int VEL_SHOT_HF_KICK_ASS_ROCKET = 80;
const int VEL_SHOT_HF_LASER = 600;
const int VEL_SPECIAL_SHOT_HEATSEEKER = 130;
const int VEL_SPECIAL_SHOT_NUKE = 180;
const float DAMAGE_SHOT_NORMAL = 5;
const float DAMAGE_SHOT_NORMAL_HEAVY = 8;
const float DAMAGE_SHOT_DOUBLE = 5;
const float DAMAGE_SHOT_DOUBLE_HEAVY = 8;
const float DAMAGE_SHOT_TRIPLE = 7;
const int DAMAGE_SHOT_HF_NORMAL = 20;
const int DAMAGE_SHOT_HF_DOUBLE = 20;
const int DAMAGE_SHOT_HF_TRIPLE = 20;
const int DAMAGE_SHOT_HF_QUATTRO = 20;
const int DAMAGE_SHOT_HF_QUINTO = 20;
const float DAMAGE_SHOT_DUMBFIRE = 40;
const float DAMAGE_SHOT_DUMBFIRE_DOUBLE = 30;
const float DAMAGE_SHOT_KICK_ASS_ROCKET = 151; // should kill a tank/turret with one shot
const float DAMAGE_SHOT_HELLFIRE = 50;
const float DAMAGE_SHOT_MACHINE_GUN = 8;
const float DAMAGE_SHOT_ENERGY_BEAM = 80;
const int DAMAGE_SHOT_HF_DUMBFIRE = 40;
const int DAMAGE_SHOT_HF_DUMBFIRE_DOUBLE = 40;
const int DAMAGE_SHOT_HF_KICK_ASS_ROCKET = 151;
const int DAMAGE_SHOT_HF_LASER = 70;
const float DAMAGE_SPECIAL_SHOT_HEATSEEKER = 20;
const float DAMAGE_SPECIAL_SHOT_NUKE = 250;
const int SPREAD_ANGLE_SHOT_NORMAL = 6;
const int LIFETIME_ENEMY_SHOT_NORMAL = 6000;
const int LIFETIME_ENEMY_SHOT_TANK_ROCKET = 10000;
const int VEL_ENEMY_SHOT_NORMAL = 130;
const int VEL_ENEMY_SHOT_TANK_ROCKET = 70;
const float DAMAGE_ENEMY_SHOT_NORMAL = 8;
const float DAMAGE_ENEMY_SHOT_TANK_ROCKET = 25;
/***************************** SMOKE PUFFS ***************************/
enum SmokePuffTypes { SMOKE_PUFF_SMALL=0, SMOKE_PUFF_MEDIUM };
const int NR_SMOKE_PUFF_TYPES = 2;
const std::string FN_SMOKE_PUFF[ NR_SMOKE_PUFF_TYPES ] =
{ "./images/smokePuffSmall.bmp",
"./images/smokePuffMedium.bmp" };
const int LIFETIME_SMOKE_PUFF[ NR_SMOKE_PUFF_TYPES ] = { 500, 1000 };
const int SMOKE_PUFF_DELAY_TO_NEXT_PUFF[ NR_SMOKE_PUFF_TYPES ] = { 100, 100 };
const float SMOKE_PUFF_VELOCITY_FACTOR = 0.3;
const bool SMOKE_PUFF_ALPHA_BLENDING = true;
/********************************** ENEMIES ********************************/
enum EnemyTypes {
FIGHTER=0,
BOMBER,
TANK,
BOSS_1_MAIN_GUN,
BOSS_1_ROCKET_LAUNCHER,
BOSS_1_SHOT_BATTERY_RIGHT,
BOSS_1_SHOT_BATTERY_LEFT,
BOSS_2};
const int NR_ENEMY_TYPES = 8;
const int NR_ENEMY_TYPES_NORMAL = 3;
const int NR_ENEMY_TYPES_BOSS_1 = 4;
const float BOSS_1_END_Y = 110;
enum WreckTypes {
WRECK_FIGHTER=0,
WRECK_BOMBER,
WRECK_TANK,
WRECK_BOSS_1_MAIN_GUN,
WRECK_BOSS_1_ROCKET_LAUNCHER,
WRECK_BOSS_1_BATTERY_RIGHT,
WRECK_BOSS_1_BATTERY_LEFT,
WRECK_BOSS_1_BACKGROUND,
WRECK_BOSS_1_DESTROYED,
WRECK_BOSS_2_DESTROYED };
const int NR_WRECK_TYPES = 10;
const WreckTypes WRECK_FOR_ENEMYTYPE[] = {
WRECK_FIGHTER,
WRECK_BOMBER,
WRECK_TANK,
WRECK_BOSS_1_MAIN_GUN,
WRECK_BOSS_1_ROCKET_LAUNCHER,
WRECK_BOSS_1_BATTERY_RIGHT,
WRECK_BOSS_1_BATTERY_LEFT,
WRECK_BOSS_2_DESTROYED };
extern int GENERATE_ENEMY_DELAY;
extern int GENERATE_ENEMY_RAND_DELAY;
extern int ENEMY_HITPOINTS[];
//const float ENEMY_HITPOINTS[] = { 80, 120, 150, 10, 10, 10, 10 };
const bool ENEMY_FLYING[] = {true, true, false, false, false, false, false, true};
// determines the difference between shadow and enemy plane
const int ENEMY_FLYING_HEIGHT[] = {10, 15, 0, 0, 0, 0, 0, 10};
const int ENEMY_POINTS_FOR_DEST[] = {10,20,20,0,0,0,0,0};
extern int ENEMY_COLLISION_DAMAGE[];
// the enemys have different probabilities to appear in the different levels.
// bigger number -> greater chance
extern int ENEMY_APPEAR_CHANCES[];
// on average one of that many enemys carries an item
extern int ENEMY_DIES_ITEM_APPEAR_CHANCE[];
// minimal waittime (ms) between two shots
extern int ENEMY_COOLDOWN_PRIMARY[];
extern int ENEMY_COOLDOWN_SECONDARY[];
// random additional waittime between two shots
extern int ENEMY_RAND_WAIT_PRIMARY[];
extern int ENEMY_RAND_WAIT_SECONDARY[];
/******************************** FORMATION ***************************************/
enum FormationTypes { FORMATION_V=0, FORMATION_REVERSE_V,
FORMATION_BLOCK,
FORMATION_LINE };
const int NR_FORMATION_TYPES = 4;
const int FORMATION_MAX_NR_ENEMYS_HARD_LIMIT[] = {7,7,7,6};
extern int FORMATION_MAX_NR_ENEMYS[];
enum FormationEnemySets { FORMATION_ENEMY_SET_DEFAULT=0,
FORMATION_ENEMY_SET_FIGHTER,
FORMATION_ENEMY_SET_BOMBER,
FORMATION_ENEMY_SET_FIGHTER_BOMBER };
const int NR_FORMATION_ENEMY_SETS = 4;
const int FORMATION_CHANGE_ON_KILL = 1;
const int FORMATION_CHANGE_SPONTANEOUS = 2;
const int FORMATION_CHANGE_SELDOM = 4;
const int FORMATION_CHANGE_OFTEN = 8;
const int FORMATION_CHANGE_OFTEN_DELAY = 3000;
const int FORMATION_CHANGE_OFTEN_RAND_DELAY = 8000;
const int FORMATION_CHANGE_SELDOM_DELAY = 4000;
const int FORMATION_CHANGE_SELDOM_RAND_DELAY = 15000;
enum FormationShotPatterns { FORMATION_SP_NONE=0,
FORMATION_SP_RAND_FAST,
FORMATION_SP_RAND_MEDIUM,
FORMATION_SP_RAND_SLOW,
FORMATION_SP_VOLLEY_FAST,
FORMATION_SP_VOLLEY_MEDIUM,
FORMATION_SP_VOLLEY_SLOW,
FORMATION_SP_LEFT_RIGHT_FAST,
FORMATION_SP_LEFT_RIGHT_MEDIUM,
FORMATION_SP_RIGHT_LEFT_FAST,
FORMATION_SP_RIGHT_LEFT_MEDIUM };
const int NR_FORMATION_SP = 11;
extern int FORMATION_SP_CHANCES[];
extern int FORMATION_SP_PRIMARY_DELAY[];
extern int FORMATION_SP_PRIMARY_RAND_DELAY[];
extern int GENERATE_FORMATION_DELAY;
extern int GENERATE_FORMATION_RAND_DELAY;
/************************* RACER *********************************/
// max speed of the racer in pixels per second
const float LIGHT_FIGHTER_VEL_MAX = 90;
const float HEAVY_FIGHTER_VEL_MAX = 60;
// shield recharge points per 100 seconds
extern int LIGHT_FIGHTER_SHIELD_RECHARGE;
extern int HEAVY_FIGHTER_SHIELD_RECHARGE;
// Cooldown rates (in ms) of the weapons
const int RACER_COOLDOWN_SHOT_NORMAL = 100;
const int RACER_COOLDOWN_SHOT_NORMAL_HEAVY = 100;
const int RACER_COOLDOWN_SHOT_DOUBLE = 130;
const int RACER_COOLDOWN_SHOT_DOUBLE_HEAVY = 130;
const int RACER_COOLDOWN_SHOT_TRIPLE = 130;
const int RACER_COOLDOWN_SHOT_HF_NORMAL = 300;
const int RACER_COOLDOWN_SHOT_HF_DOUBLE = 300;
const int RACER_COOLDOWN_SHOT_HF_TRIPLE = 300;
const int RACER_COOLDOWN_SHOT_HF_QUATTRO = 350;
const int RACER_COOLDOWN_SHOT_HF_QUINTO = 400;
const int RACER_COOLDOWN_DUMBFIRE = 600;
const int RACER_COOLDOWN_DUMBFIRE_DOUBLE = 300;
const int RACER_COOLDOWN_KICK_ASS_ROCKET = 1500;
const int RACER_COOLDOWN_HELLFIRE = 600;
const int RACER_COOLDOWN_MACHINE_GUN = 150;
const int RACER_COOLDOWN_ENERGY_BEAM = 500;
const int RACER_COOLDOWN_HF_DUMBFIRE = 600;
const int RACER_COOLDOWN_HF_DUMBFIRE_DOUBLE = 300;
const int RACER_COOLDOWN_HF_KICK_ASS_ROCKET = 1300;
const int RACER_COOLDOWN_HF_LASER = 700;
const int RACER_COOLDOWN_SPECIAL_HEATSEEKER = 400;
const int RACER_COOLDOWN_SPECIAL_NUKE = 3000;
extern int RACER_DEFLECTOR_ACTIVATION_DIST;
extern int RACER_DEFLECTOR_POWER;
extern int RACER_SONIC_ACTIVATION_DIST;
extern int RACER_SONIC_POWER;
// how long (in ms) does the shield glow, when the racer is hit
const int RACER_SHIELD_DAMAGE_LIFETIME = 200;
// shields
extern int LIGHT_FIGHTER_MAX_SHIELD;
extern int HEAVY_FIGHTER_MAX_SHIELD;
// hitpoints
extern int LIGHT_FIGHTER_MAX_DAMAGE;
extern int HEAVY_FIGHTER_MAX_DAMAGE;
const std::string FN_SOUND_SHOT_PRIMARY = "./sound/shotPrimary.wav";
const std::string FN_SOUND_SHOT_SECONDARY = "./sound/shotSecondary.wav";
const std::string FN_SOUND_EXPLOSION_NORMAL = "./sound/explosion.wav";
const std::string FN_SOUND_EXPLOSION_BOSS = "./sound/explosionBoss.wav";
const std::string FN_SOUND_BOSS_ALARM = "./sound/alarm.wav";
const std::string FN_SOUND_ARCADE_CONFIRM = "./sound/alarm.wav";
const std::string FN_SOUND_ARCADE_CHOOSE = "./sound/choose.wav";
const std::string FN_SOUND_INTRO_CONFIRM = "./sound/confirm.wav";
const std::string FN_SOUND_INTRO_CHOOSE = "./sound/choose.wav";
const std::string FN_ENEMY_FIGHTER = "./images/fighter.bmp";
const std::string FN_ENEMY_FIGHTER_SHADOW = "./images/fighterShadow.bmp";
const std::string FN_ENEMY_BOMBER = "./images/bomber.bmp";
const std::string FN_ENEMY_BOMBER_SHADOW = "./images/bomberShadow.bmp";
const std::string FN_ENEMY_TANK = "./images/tank.bmp";
const std::string FN_ENEMY_BOSS_1_MAIN_GUN = "./images/boss1MainGun.bmp";
const std::string FN_ENEMY_BOSS_1_ROCKET_LAUNCHER = "./images/boss1RocketLauncher.bmp";
const std::string FN_ENEMY_BOSS_1_SHOT_BATTERY_LEFT = "./images/boss1ShotBatteryLeft.bmp";
const std::string FN_ENEMY_BOSS_1_SHOT_BATTERY_RIGHT = "./images/boss1ShotBatteryRight.bmp";
const std::string FN_ENEMY_BOSS_2 = "./images/boss2.bmp";
const std::string FN_ENEMY_BOSS_2_SHADOW = "./images/boss2Shadow.bmp";
const std::string FN_WRECK_FIGHTER = "./images/wreckFighter.bmp";
const std::string FN_WRECK_BOMBER = "./images/wreckBomber.bmp";
const std::string FN_WRECK_TANK = "./images/wreckTank.bmp";
const std::string FN_WRECK_BOSS_1 = "./images/wreckBoss1.bmp";
const std::string FN_WRECK_BOSS_1_BACKGROUND = "./images/wreckBossBackground.bmp";
const std::string FN_WRECK_BOSS_1_DESTROYED = "./images/boss.bmp";
const std::string FN_WRECK_BOSS_2_DESTROYED = "./images/wreckBoss2.bmp";
const std::string FN_SHOT_NORMAL = "./images/normalShot.bmp";
const std::string FN_SHOT_NORMAL_HEAVY = "./images/heavyShot.bmp";
const std::string FN_SHOT_DOUBLE = "./images/normalShot.bmp";
const std::string FN_SHOT_DOUBLE_HEAVY = "./images/heavyShot.bmp";
const std::string FN_SHOT_TRIPLE = "./images/heavyShot.bmp";
const std::string FN_SHOT_HF_NORMAL = "./images/normalShotHF.bmp";
const std::string FN_SHOT_HF_DOUBLE = "./images/normalShotHF.bmp";
const std::string FN_SHOT_HF_TRIPLE = "./images/normalShotHF.bmp";
const std::string FN_SHOT_HF_QUATTRO = "./images/normalShotHF.bmp";
const std::string FN_SHOT_HF_QUINTO = "./images/normalShotHF.bmp";
const std::string FN_SHOT_DUMBFIRE = "./images/dumbfire.bmp";
const std::string FN_SHOT_DUMBFIRE_DOUBLE = "./images/dumbfire.bmp";
const std::string FN_SHOT_KICK_ASS_ROCKET = "./images/kickAssRocket.bmp";
const std::string FN_SHOT_KICK_ASS_ROCKET_SHADOW = "./images/kickAssRocketShadow.bmp";
const std::string FN_SHOT_HELLFIRE = "./images/hellfire.bmp";
const std::string FN_SHOT_HELLFIRE_SHADOW = "./images/hellfireShadow.bmp";
const std::string FN_SHOT_MACHINE_GUN = "./images/machineGun.bmp";
const std::string FN_SHOT_ENERGY_BEAM = "./images/energyBeam.bmp";
const std::string FN_SHOT_HF_DUMBFIRE = "./images/dumbfire.bmp";
const std::string FN_SHOT_HF_DUMBFIRE_DOUBLE = "./images/dumbfire.bmp";
const std::string FN_SHOT_HF_KICK_ASS_ROCKET = "./images/kickAssRocket.bmp";
const std::string FN_SHOT_HF_KICK_ASS_ROCKET_SHADOW = "./images/kickAssRocketShadow.bmp";
const std::string FN_SHOT_HF_LASER = "./images/laser.bmp";
const std::string FN_ENEMY_SHOT_NORMAL = "./images/enemyShotNormal.bmp";
const std::string FN_ENEMY_SHOT_TANK_ROCKET = "./images/tankRocket.bmp";
const std::string FN_ENEMY_SHOT_TANK_ROCKET_SHADOW = "./images/tankRocketShadow.bmp";
const std::string FN_SPECIAL_SHOT_HEATSEEKER = "./images/heatseeker.bmp";
const std::string FN_SPECIAL_SHOT_NUKE = "./images/shotNuke.bmp";
const std::string FN_SPECIAL_SHOT_NUKE_SHADOW = "./images/shotNukeShadow.bmp";
const std::string FN_NUKE_EFFECT = "./images/nukeEffect.bmp";
const std::string FN_SONIC_EFFECT = "./images/sonic.bmp";
const std::string FN_ITEM_PRIMARY_UPGRADE = "./images/itemPrimaryUpgrade.bmp";
const std::string FN_ITEM_DUMBFIRE_DOUBLE = "./images/itemDumbfireDouble.bmp";
const std::string FN_ITEM_KICK_ASS_ROCKET = "./images/itemKickAssRocket.bmp";
const std::string FN_ITEM_HELLFIRE = "./images/itemHellfire.bmp";
const std::string FN_ITEM_MACHINE_GUN = "./images/itemMachineGun.bmp";
const std::string FN_ITEM_HEALTH = "./images/itemHealth.bmp";
const std::string FN_ITEM_HEATSEEKER = "./images/itemHeatseeker.bmp";
const std::string FN_ITEM_NUKE = "./images/itemNuke.bmp";
const std::string FN_ITEM_DEFLECTOR = "./images/itemDeflector.bmp";
const std::string FN_ITEM_ENERGY_BEAM = "./images/itemEnergyBeam.bmp";
const std::string FN_ITEM_LASER = "./images/itemLaser.bmp";
const std::string FN_ALIENBLASTER_INTRO = "./images/alienblasterintro.bmp";
const std::string FN_ALIENBLASTER_ICON = "./images/alienblastericon.bmp";
const std::string FN_BACKGROUND = "./images/background.bmp";
const std::string FN_PAUSED = "./images/paused.bmp";
const std::string FN_YOU_LOSE = "./images/youLose.bmp";
const std::string FN_YOU_WIN = "./images/youWin.bmp";
const std::string FN_GAME_OVER = "./images/gameOver.bmp";
const std::string FN_ARCADE_LOGO = "./images/arcadeLogo.bmp";
// numbers of images (animation-frames) per racer
const int RACER_IMAGE_CNT = 9;
const std::string FN_LIGHT_FIGHTER_1 = "./images/lightFighter1.bmp";
const std::string FN_LIGHT_FIGHTER_2 = "./images/lightFighter2.bmp";
const std::string FN_LIGHT_FIGHTER_SHADOW = "./images/lightFighterShadow.bmp";
const std::string FN_LIGHT_FIGHTER_SHIELD_DAMAGED = "./images/lightFighterShieldDamaged.bmp";
const std::string FN_LIGHT_FIGHTER_1_ICON = "./images/lightFighter1Icon.bmp";
const std::string FN_LIGHT_FIGHTER_2_ICON = "./images/lightFighter2Icon.bmp";
const std::string FN_LIGHT_FIGHTER_1_SMALL = "./images/lightFighter1Small.bmp";
const std::string FN_LIGHT_FIGHTER_2_SMALL = "./images/lightFighter2Small.bmp";
const std::string FN_HEAVY_FIGHTER_1 = "./images/heavyFighter1.bmp";
const std::string FN_HEAVY_FIGHTER_2 = "./images/heavyFighter2.bmp";
const std::string FN_HEAVY_FIGHTER_SHADOW = "./images/heavyFighterShadow.bmp";
const std::string FN_HEAVY_FIGHTER_SHIELD_DAMAGED = "./images/heavyFighterShieldDamaged.bmp";
const std::string FN_HEAVY_FIGHTER_DEFLECTOR = "./images/heavyFighterDeflector.bmp";
const std::string FN_HEAVY_FIGHTER_1_ICON = "./images/heavyFighter1Icon.bmp";
const std::string FN_HEAVY_FIGHTER_2_ICON = "./images/heavyFighter2Icon.bmp";
const std::string FN_HEAVY_FIGHTER_1_SMALL = "./images/heavyFighter1Small.bmp";
const std::string FN_HEAVY_FIGHTER_2_SMALL = "./images/heavyFighter2Small.bmp";
const std::string FN_ICONS_SPECIALS = "./images/iconsSpecials.bmp";
const std::string FN_ICONS_SECONDARY_WEAPONS = "./images/iconsSecondaryWeapons.bmp";
const std::string FN_HITPOINTS_STAT = "./images/hpStat.bmp";
const std::string FN_INTRO_SHOW_CHOICE = "./images/menuIcon.bmp";
const std::string FN_FONT_PATH = "./images/";
const std::string FN_FONT_SUFFIX_SURFACE = ".bmp";
const std::string FN_FONT_INTRO = "./images/font-20white";
const std::string FN_FONT_INTRO_HIGHLIGHTED = "./images/font-20lightblue";
const std::string FN_FONT_NUMBERS_TIME = "./images/font-20red";
const std::string FN_FONT_NUMBERS_LEFT = "./images/font-20red";
const std::string FN_FONT_NUMBERS_RIGHT = "./images/font-20blue";
const std::string FN_FONT_SETTINGS = "./images/font-20white";
const std::string FN_FONT_SETTINGS_HIGHLIGHTED = "./images/font-20lightblue";
const std::string FN_FONT_SETTINGS_SMALL = "./images/font-14white";
const std::string FN_FONT_SETTINGS_SMALL_BLUE = "./images/font-14lightblue";
const std::string FN_FONT_SETTINGS_SMALL_HIGHLIGHTED = "./images/font-14red";
const std::string FN_SETTINGS_BLUE = "./images/bluePlain.bmp";
const std::string FN_SETTINGS_WHITE = "./images/whitePlain.bmp";
const std::string FN_EXPLOSION_NORMAL = "./images/explosion.bmp";
const std::string FN_EXPLOSION_ENEMY = "./images/explosionEnemy.bmp";
const std::string FN_LOADING = "./images/loading.bmp";
const std::string FN_SETTINGS = "./cfg/alienBlaster.cfg";
const std::string FN_DIFFICULTY_CONFIG = "./cfg/alienBlasterDifficulty";
const std::string FN_DIFFICULTY_CONFIG_SUFFIX = ".cfg";
const std::string FN_HIGHSCORE = "./cfg/highscore.dat";
enum MusicTracks { MUSIC_INTRO=0, MUSIC_PLAYON, MUSIC_BOSS1, MUSIC_NONE };
const int NR_MUSIC_TRACKS = 3;
const std::string FN_MUSIC[] = { "./sound/intro.wav",
"./sound/playon.wav",
"./sound/intro.wav" };
const std::string FN_LEVEL_ONE_PLAYER = "./cfg/level1.cfg";
const std::string FN_LEVEL_TWO_PLAYER = "./cfg/level2.cfg";
const std::string FN_LEVEL_ARCADEMODE = "./cfg/levelArcade.cfg";
const std::string FN_SCREENSHOT0 = "./intro/HellShot0.bmp";
const std::string FN_SCREENSHOT1 = "./intro/HellShot1.bmp";
const std::string FN_SCREENSHOT2 = "./intro/HellShot2.bmp";
const std::string FN_SCREENSHOT3 = "./intro/HellShot3.bmp";
const std::string FN_SCREENSHOT4 = "./intro/HellShot5.bmp";
const std::string FN_SCREENSHOT5 = "./intro/HellShot4.bmp";
const std::string FN_SCREENSHOT6 = "./intro/HellShot6.bmp";
const std::string FN_SCREENSHOT7 = "./intro/HellShot7.bmp";
const std::string FN_SCREENSHOT8 = "./intro/HellShot8.bmp";
const std::string FN_SCREENSHOT9 = "./intro/HellShot9.bmp";
const std::string LVL_BACKG_TILE_CNT = "BACKG_TILES";
const std::string LVL_BACKG_TILE = "BACKG_TILE";
const std::string LVL_BACKG_LENGTH = "BACKG_LENGTH";
const std::string LVL_ENEMY_FIGHTER = "ENEMY_FIGHTER";
const std::string LVL_ENEMY_BOMBER = "ENEMY_BOMBER";
const std::string LVL_ENEMY_TANK = "ENEMY_TANK";
const std::string LVL_ENEMY_BOSS_BACKGROUND = "ENEMY_BOSS_BACKGROUND";
const std::string LVL_ENEMY_BOSS_DESTROYED = "ENEMY_BOSS_DESTROYED";
const std::string LVL_WRECK_FIGHTER = "WRECK_FIGHTER";
const std::string LVL_WRECK_BOMBER = "WRECK_BOMBER";
const std::string LVL_WRECK_TANK = "WRECK_TANK";
const std::string LVL_WRECK_BOSS_BACKGROUND = "WRECK_BOSS_BACKGROUND";
const std::string LVL_WRECK_BOSS_DESTROYED = "WRECK_BOSS_DESTROYED";
const std::string LVL_ENEMY_BOSS_1_SHOT_BATTERY_RIGHT = "ENEMY_BOSS_1_SHOT_BATTERY_RIGHT";
const std::string LVL_ENEMY_BOSS_1_SHOT_BATTERY_LEFT = "ENEMY_BOSS_1_SHOT_BATTERY_LEFT";
const std::string LVL_ENEMY_BOSS_1_ROCKET_LAUNCHER = "ENEMY_BOSS_1_ROCKET_LAUNCHER";
const std::string LVL_ENEMY_BOSS_1_MAIN_GUN = "ENEMY_BOSS_1_MAIN_GUN";
const std::string LVL_ENEMY_FIGHTER_SHADOW = "ENEMY_FIGHTER_SHADOW";
const std::string LVL_ENEMY_BOMBER_SHADOW = "ENEMY_BOMBER_SHADOW";
#endif

View File

@@ -1,340 +0,0 @@
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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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) year 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.
<signature of Ty Coon>, 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,389 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include "infoscreen.h"
#include "global.h"
#include "surfaceDB.h"
#include "mixer.h"
#include "video.h"
#include "font.h"
#include "items.h"
#include "item.h"
Items *infoscreenItems;
Infoscreen::Infoscreen( SdlCompat_AcceleratedSurface *scr ) {
screen = scr;
font = new Font( FN_FONT_INTRO );
fontHighlighted = new Font( FN_FONT_INTRO_HIGHLIGHTED );
activeChoiceSprite = surfaceDB.loadSurface( FN_INTRO_SHOW_CHOICE );
lightFighterIcon1 = surfaceDB.loadSurface( FN_LIGHT_FIGHTER_1_ICON );
lightFighterIcon2 = surfaceDB.loadSurface( FN_LIGHT_FIGHTER_2_ICON );
heavyFighterIcon1 = surfaceDB.loadSurface( FN_HEAVY_FIGHTER_1_ICON );
heavyFighterIcon2 = surfaceDB.loadSurface( FN_HEAVY_FIGHTER_2_ICON );
choose = Mixer::mixer().loadSample( FN_SOUND_INTRO_CHOOSE, 100 );
confirm = Mixer::mixer().loadSample( FN_SOUND_INTRO_CONFIRM, 100 );
if (infoscreenItems) delete infoscreenItems;
infoscreenItems = new Items();
activeChoice = 0;
}
Infoscreen::~Infoscreen() {
if (infoscreenItems) delete infoscreenItems;
}
void Infoscreen::run() {
draw();
quitInfoscreen = false;
activeChoice = 0;
while ( !quitInfoscreen ) {
handleEvents();
draw();
SDL_Delay( 50 );
}
}
void Infoscreen::putBitmapAtPosition( int x, int y, SdlCompat_AcceleratedSurface* bitmap ) {
SDL_Rect d;
d.x = x - bitmap->w / 2;
d.y = y - bitmap->h / 2;
d.w = bitmap->w;
d.h = bitmap->h;
SDL_BlitSurface( bitmap, 0, screen, &d );
}
void Infoscreen::draw() {
// clear the screen
videoserver->clearScreen();
// draw vertical green line
SDL_Rect r;
r.x = 250;
r.y = 0;
r.w = 2;
r.h = screen->h;
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0, 255, 0) );
for ( int i = 0; i < NR_INFOSCREEN_CHOICES; i++ ) {
int ypos = 30 + i * 25;
if ( i == INFO_CREDITS ) ypos += 15;
if ( i == INFO_BACK_TO_MAIN_MENU ) ypos += 30;
if( activeChoice == i ) {
putBitmapAtPosition( 15, ypos + 8, activeChoiceSprite );
fontHighlighted->drawStr( screen, 30, ypos, SET_INFOSCREEN_CHOICES[ i ] );
} else {
font->drawStr( screen, 30, ypos, SET_INFOSCREEN_CHOICES[ i ] );
}
}
switch ( activeChoice ) {
case INFO_LIGHT_FIGHTER:
{
putBitmapAtPosition( 386, 50, lightFighterIcon1 );
putBitmapAtPosition( 502, 50, lightFighterIcon2 );
font->drawStr( screen, 270, 100, "The Light Fighter is more");
font->drawStr( screen, 270, 130, "vulnerable but smaller and");
font->drawStr( screen, 270, 160, "faster than the Heavy Fighter.");
font->drawStr( screen, 270, 200, "Possible Updates:");
newItem = new Item( Vector2D ( 270, 240 ) , Vector2D(0,0), ITEM_PRIMARY_UPGRADE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 230, "Primary Weapon Upgrade");
newItem = new Item( Vector2D ( 270, 270 ) , Vector2D(0,0), ITEM_MACHINE_GUN );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 260, "Machinegun");
newItem = new Item( Vector2D ( 270, 300 ) , Vector2D(0,0), ITEM_DUMBFIRE_DOUBLE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 290, "Double Dumbfire");
newItem = new Item( Vector2D ( 270, 330 ) , Vector2D(0,0), ITEM_KICK_ASS_ROCKET );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 320, "Kick-Ass Rocket");
newItem = new Item( Vector2D ( 270, 360 ) , Vector2D(0,0), ITEM_HELLFIRE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 350, "Hellfire Rocket");
newItem = new Item( Vector2D ( 270, 390 ) , Vector2D(0,0), ITEM_HEATSEEKER );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 380, "Heatseeker");
newItem = new Item( Vector2D ( 270, 420 ) , Vector2D(0,0), ITEM_NUKE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 410, "The Great Nuke");
newItem = new Item( Vector2D ( 270, 450 ) , Vector2D(0,0), ITEM_ENERGY_BEAM );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 440, "Energy Beam");
infoscreenItems->draw( screen );
break;
}
case INFO_HEAVY_FIGHTER:
{
putBitmapAtPosition( 386, 50, heavyFighterIcon1 );
putBitmapAtPosition( 502, 50, heavyFighterIcon2 );
font->drawStr( screen, 270, 100, "The Heavy Fighter has superior");
font->drawStr( screen, 270, 130, "firepower and an energyweapon");
font->drawStr( screen, 270, 160, "deflector. He lacks agility.");
font->drawStr( screen, 270, 200, "Possible Updates:");
newItem = new Item( Vector2D ( 270, 240 ) , Vector2D(0,0), ITEM_PRIMARY_UPGRADE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 230, "Primary Weapon Upgrade");
newItem = new Item( Vector2D ( 270, 270 ) , Vector2D(0,0), ITEM_KICK_ASS_ROCKET );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 260, "Kick-Ass Rocket");
newItem = new Item( Vector2D ( 270, 300 ) , Vector2D(0,0), ITEM_HEATSEEKER );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 290, "Heatseeker");
newItem = new Item( Vector2D ( 270, 330 ) , Vector2D(0,0), ITEM_NUKE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 320, "The Great Nuke");
newItem = new Item( Vector2D ( 270, 360 ) , Vector2D(0,0), ITEM_DEFLECTOR );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 350, "Energyweapon Deflector");
newItem = new Item( Vector2D ( 270, 390 ) , Vector2D(0,0), ITEM_LASER );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 380, "Heavy Laser");
infoscreenItems->draw( screen );
break;
}
case INFO_PRIMARY_WEAPON:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_PRIMARY_UPGRADE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Primary Weapon Upgrade");
font->drawStr( screen, 270, 100, "The Primary Weapon Upgrade can");
font->drawStr( screen, 270, 130, "be used multiple times and each");
font->drawStr( screen, 270, 160, "time the primary weapon will");
font->drawStr( screen, 270, 190, "gain one extra shot or improve");
font->drawStr( screen, 270, 220, "its damage. The maximum for the");
font->drawStr( screen, 270, 250, "light fighter are three heavy");
font->drawStr( screen, 270, 280, "shots and for the heavy figher");
font->drawStr( screen, 270, 310, "five shots.");
infoscreenItems->draw( screen );
break;
}
case INFO_MACHINE_GUN:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_MACHINE_GUN );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Machine Gun");
font->drawStr( screen, 270, 100, "The Machine Gun fires a");
font->drawStr( screen, 270, 130, "massive amount of steel per");
font->drawStr( screen, 270, 160, "minute at the enemy on the");
font->drawStr( screen, 270, 190, "ground and in the air.");
font->drawStr( screen, 270, 220, "It has the ability to aim in a");
font->drawStr( screen, 270, 250, "small angle at nearby enemys.");
font->drawStr( screen, 270, 280, "This makes it useful to");
font->drawStr( screen, 270, 310, "attack formations from the");
font->drawStr( screen, 270, 340, "side.");
infoscreenItems->draw( screen );
break;
}
case INFO_DUMBFIRE_DOUBLE:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_DUMBFIRE_DOUBLE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Double Dumbfire Rocket");
font->drawStr( screen, 270, 100, "With this upgrade, you get one");
font->drawStr( screen, 270, 130, "extra dumbfire missile for the");
font->drawStr( screen, 270, 160, "light fighter. These rockets");
font->drawStr( screen, 270, 190, "hit targets on the ground and");
font->drawStr( screen, 270, 220, "in the air.");
infoscreenItems->draw( screen );
break;
}
case INFO_KICK_ASS_ROCKET:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_KICK_ASS_ROCKET );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Kick-Ass Rocket");
font->drawStr( screen, 270, 100, "This is the strongest air to");
font->drawStr( screen, 270, 130, "ground rocket. It takes only");
font->drawStr( screen, 270, 160, "one shot to let a turret");
font->drawStr( screen, 270, 190, "explode but reloading takes");
font->drawStr( screen, 270, 220, "longer.");
infoscreenItems->draw( screen );
break;
}
case INFO_HELLFIRE:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_HELLFIRE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Hellfire Rocket");
font->drawStr( screen, 270, 100, "Medium air to ground missiles");
font->drawStr( screen, 270, 130, "that are fired in pairs and");
font->drawStr( screen, 270, 160, "look much better than the");
font->drawStr( screen, 270, 190, "fat clumsy Kick-Ass-Rocket.");
infoscreenItems->draw( screen );
break;
}
// heatseaker (für Paul :-)
case INFO_HEATSEEKER:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_HEATSEEKER );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Heatseaker Rocket");
font->drawStr( screen, 270, 100, "Just hit the trigger and this");
font->drawStr( screen, 270, 130, "missile will find the enemy");
font->drawStr( screen, 270, 160, "itself. Ground targets as well");
font->drawStr( screen, 270, 190, "as air targets will be hit.");
font->drawStr( screen, 270, 220, "Each item gives 70 of these.");
infoscreenItems->draw( screen );
break;
}
case INFO_NUKE:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_NUKE );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "The Great Nuke");
font->drawStr( screen, 270, 100, "Not much is known about this");
font->drawStr( screen, 270, 130, "weapon because everyone who");
font->drawStr( screen, 270, 160, "saw it exploding was dead in");
font->drawStr( screen, 270, 190, "just that moment.");
infoscreenItems->draw( screen );
break;
}
case INFO_DEFLECTOR:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_DEFLECTOR );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Energyweapon Deflector");
font->drawStr( screen, 270, 100, "This is a very useful");
font->drawStr( screen, 270, 130, "equipment for the heavy");
font->drawStr( screen, 270, 160, "fighter. It amplifies the");
font->drawStr( screen, 270, 190, "builtin deflector, so that");
font->drawStr( screen, 270, 220, "it is very hard to be hit");
font->drawStr( screen, 270, 250, "by an energy weapon.");
infoscreenItems->draw( screen );
break;
}
case INFO_ENERGY_BEAM:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_ENERGY_BEAM );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Energy Beam");
font->drawStr( screen, 270, 100, "The Energy Beam was built");
font->drawStr( screen, 270, 130, "for the light fighter and");
font->drawStr( screen, 270, 160, "its devastating power");
font->drawStr( screen, 270, 190, "makes it the best choice");
font->drawStr( screen, 270, 220, "against air targets. In");
font->drawStr( screen, 270, 250, "addition its really hard");
font->drawStr( screen, 270, 280, "to evade this weapon.");
infoscreenItems->draw( screen );
break;
}
case INFO_LASER:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_LASER );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Heavy Laser");
font->drawStr( screen, 270, 100, "This is the newest type");
font->drawStr( screen, 270, 130, "of equipment for the heavy");
font->drawStr( screen, 270, 160, "fighter. A skilled pilot");
font->drawStr( screen, 270, 190, "can take down two air");
font->drawStr( screen, 270, 220, "enemies at once with this");
font->drawStr( screen, 270, 250, "heavy laser.");
infoscreenItems->draw( screen );
break;
}
case INFO_SHIELD_UP:
{
newItem = new Item( Vector2D ( 270, 50 ) , Vector2D(0,0), ITEM_HEALTH );
infoscreenItems->addItem( newItem );
font->drawStr( screen, 300, 40, "Health Powerup");
font->drawStr( screen, 270, 100, "If your shield goes down");
font->drawStr( screen, 270, 130, "this powerup is especially");
font->drawStr( screen, 270, 160, "useful for instant repairs.");
font->drawStr( screen, 270, 190, "Try to get it as often as");
font->drawStr( screen, 270, 220, "you can.");
infoscreenItems->draw( screen );
break;
}
case INFO_CREDITS:
{
font->drawStr( screen, 445, 40, "Alien Blaster", FONT_ALIGN_CENTERED );
font->drawStr( screen, 270, 100, "Programming:");
font->drawStr( screen, 280, 130, "Arne Hormann, Daniel Kühn,");
font->drawStr( screen, 280, 160, "Paul Grathwohl, Sönke Schwardt");
font->drawStr( screen, 270, 210, "Art Work: Arne Hormann", FONT_MONOSPACE);
font->drawStr( screen, 270, 240, "Music: Paul Grathwohl", FONT_MONOSPACE);
font->drawStr( screen, 620, 440, "Contact: AlienBlaster@gmx.de", FONT_ALIGN_RIGHT);
break;
}
case INFO_BACK_TO_MAIN_MENU:
{
font->drawStr( screen, 445, 220, "GO AND FIGHT !", FONT_ALIGN_CENTERED );
break;
}
}
SDL_Flip( screen );
}
void Infoscreen::handleEvents() {
SDL_Event event;
while ( SDL_PollEvent(&event) ) {
switch(event.type) {
case SDL_KEYDOWN: {
switch ( event.key.keysym.sym ) {
case SDLK_F5: {
videoserver->toggleFullscreen();
break;
}
case SDLK_F7: {
if ( playMusicOn ) {
playMusicOn = false;
Mixer::mixer().stopMusic();
} else {
playMusicOn = true;
Mixer::mixer().playMusic( MUSIC_INTRO, -1, 1000 );
}
break;
}
case SDLK_UP: {
Mixer::mixer().playSample( choose, 0 );
infoscreenItems->deleteAllItems();
activeChoice--;
if ( activeChoice < 0 ) activeChoice = NR_INFOSCREEN_CHOICES - 1;
break;
}
case SDLK_DOWN: {
Mixer::mixer().playSample( choose, 0 );
infoscreenItems->deleteAllItems();
activeChoice = (activeChoice + 1) % NR_INFOSCREEN_CHOICES;
break;
}
case SDLK_ESCAPE: {
quitInfoscreen = true;
break;
}
case SDLK_RETURN: {
Mixer::mixer().playSample( confirm, 0 );
switch (activeChoice) {
case INFO_BACK_TO_MAIN_MENU: {
quitInfoscreen = true;
break;
}
}
break;
}
default: break;
}
break;
}
default: break;
}
}
}

View File

@@ -1,96 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 INFOSCREEN_H
#define INFOSCREEN_H
#include "SDL.h"
#include <string>
#include "item.h"
class Font;
class Items;
enum INFOSCREEN_CHOICES {
INFO_LIGHT_FIGHTER,
INFO_HEAVY_FIGHTER,
INFO_PRIMARY_WEAPON,
INFO_MACHINE_GUN,
INFO_DUMBFIRE_DOUBLE,
INFO_KICK_ASS_ROCKET,
INFO_HELLFIRE,
INFO_HEATSEEKER,
INFO_NUKE,
INFO_DEFLECTOR,
INFO_ENERGY_BEAM,
INFO_LASER,
INFO_SHIELD_UP,
INFO_CREDITS,
INFO_BACK_TO_MAIN_MENU
};
const std::string SET_INFOSCREEN_CHOICES[] = {
"Light Fighter",
"Heavy Fighter",
"Primary Weapon",
"Machine Gun",
"Double Dumbfire",
"Kick-Ass Rocket",
"Hellfire Rocket",
"Heatseaker Rocket",
"The Great Nuke",
"Deflector",
"Energy Beam",
"Heavy Laser",
"Health Powerup",
"Credits",
"Back To Main Menu"
};
const int NR_INFOSCREEN_CHOICES = 15;
class Infoscreen {
private:
SdlCompat_AcceleratedSurface *screen;
SdlCompat_AcceleratedSurface *activeChoiceSprite;
SdlCompat_AcceleratedSurface *lightFighterIcon1;
SdlCompat_AcceleratedSurface *lightFighterIcon2;
SdlCompat_AcceleratedSurface *heavyFighterIcon1;
SdlCompat_AcceleratedSurface *heavyFighterIcon2;
Font *font;
Font *fontHighlighted;
Item *newItem;
int activeChoice;
bool quitInfoscreen;
// sounds
int choose, confirm;
public:
Infoscreen( SdlCompat_AcceleratedSurface *scr );
~Infoscreen();
void run();
private:
void handleEvents();
void draw();
void putBitmapAtPosition( int x, int y, SdlCompat_AcceleratedSurface* bitmap );
};
#endif

View File

@@ -1,112 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include <vector>
#include "input.h"
#include "SDL.h"
#include "settings.h"
Input input;
const int initialSensitivity = 4096;
Input::Input(){
joystick = 0;
getJoystick();
}
Input::~Input(){
freeJoystick();
joystick = 0;
}
void Input::getJoystick() {
if (joystick) return;
if (!SDL_InitSubSystem(SDL_INIT_JOYSTICK)) {
SDL_JoystickEventState(SDL_ENABLE);
if (SDL_NumJoysticks() > 0) {
joystick = SDL_JoystickOpen(0);
} else {
freeJoystick();
}
}
}
void Input::freeJoystick() {
if (joystick) {
SDL_JoystickClose(joystick);
joystick = 0;
}
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
}
#ifdef DEBUG
const bool pressed(const SDL_Event& event) {
if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_KEYDOWN) return true;
if (event.type == SDL_JOYAXISMOTION) return event.jaxis.value / 3200;
return false;
}
void debugEvent(const SDL_Event& event, const SDLKey code) {
if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP) {
printf("Joystick button%d event: %s (%d)\n",
event.jbutton.button, (pressed(event)) ? "pressed" : "released", code);
} else if (event.type == SDL_JOYAXISMOTION && pressed(event)) {
printf("Joystick axis%d event: %s (%d)\n",
event.jaxis.axis, (event.jaxis.value > 0) ? "raised" : "lowered", code);
}
}
const SDLKey translateEvent(const SDL_Event& event) {
if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
return event.key.keysym.sym;
}
if (event.type == SDL_JOYAXISMOTION) {
return (SDLKey) (1024 + event.jaxis.axis * 2 + ((event.jaxis.value > 0) ? 1 : 0));
}
if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP) {
return (SDLKey) (1040 + event.jbutton.button);
}
return (SDLKey) 0;
}
#endif
const SDLKey Input::translate(const SDL_Event& event) {
#ifdef DEBUG
debugEvent(event, translateEvent(event));
#endif
if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
return event.key.keysym.sym;
}
if (event.type == SDL_JOYAXISMOTION) {
return (SDLKey) (1024 + event.jaxis.axis * 2 + ((event.jaxis.value > 0) ? 1 : 0));
}
if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP) {
return (SDLKey) (1040 + event.jbutton.button);
}
return (SDLKey) 0;
}
const bool Input::isPressed(const SDL_Event& event) {
if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_KEYDOWN || event.type == SDL_MOUSEBUTTONDOWN) return true;
if (event.type == SDL_JOYAXISMOTION) return event.jaxis.value / initialSensitivity;
return false;
}

View File

@@ -1,47 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 INPUT_H
#define INPUT_H
#include "SDL.h"
#include "SdlForwardCompat.h"
class Input;
extern Input input;
class Input {
private:
Uint16 currentJoystick;
SDL_Joystick *joystick;
public:
Input();
~Input();
void getJoystick();
void freeJoystick();
const SDLKey translate(const SDL_Event& event);
const bool isPressed(const SDL_Event& event);
static const Input input();
};
#endif //#ifndef INPUT_H

View File

@@ -1,250 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include <android/log.h>
#include "intro.h"
#include "global.h"
#include "surfaceDB.h"
#include "mixer.h"
#include "video.h"
#include "font.h"
#include "settings.h"
#include "infoscreen.h"
Intro::Intro( SdlCompat_AcceleratedSurface *scr ) {
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 1");
screen = scr;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 2");
introSprite = surfaceDB.loadSurface( FN_ALIENBLASTER_INTRO );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 3");
activeChoiceSprite = surfaceDB.loadSurface( FN_INTRO_SHOW_CHOICE );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 4");
font = new Font( FN_FONT_INTRO );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 5");
fontHighlighted = new Font( FN_FONT_INTRO_HIGHLIGHTED );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 6");
activeChoice = 0;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 7");
choose = Mixer::mixer().loadSample( FN_SOUND_INTRO_CHOOSE, 100 );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 8");
confirm = Mixer::mixer().loadSample( FN_SOUND_INTRO_CONFIRM, 100 );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 9");
infoscreen = new Infoscreen( screen );
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Intro() 10");
}
Intro::~Intro() {}
void Intro::run( GameStates &gameState ) {
if ( playMusicOn && Mixer::mixer().whichMusicPlaying() != MUSIC_INTRO ) {
Mixer::mixer().playMusic( MUSIC_INTRO, -1, 1000 );
}
draw();
while ( gameState == GS_INTRO ) {
handleEvents( gameState );
draw();
SDL_Delay( 50 );
}
}
void Intro::draw() {
videoserver->clearScreen();
SDL_Rect r;
r.x = screen->w / 2 - introSprite->w / 2;
r.y = 0;
r.w = introSprite->w;
r.h = introSprite->h;
SDL_BlitSurface( introSprite, 0, screen, &r );
for ( int i = 0; i < NR_INTRO_CHOICES; i++ ) {
if ( activeChoice == i ) {
r.x = 230 - activeChoiceSprite->w - 8;
r.y = 258 + i * 35;
r.w = activeChoiceSprite->w;
r.h = activeChoiceSprite->h;
SDL_BlitSurface(activeChoiceSprite, 0, screen, &r );
fontHighlighted->drawStr( screen, 230, 260 + i * 35, INTRO_CHOICES[ i ] );
} else {
font->drawStr( screen, 230, 260 + i * 35, INTRO_CHOICES[ i ] );
}
}
SDL_Flip( screen );
}
void Intro::handleEvents( GameStates &gameState ) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYDOWN: {
switch(event.key.keysym.sym) {
case SDLK_F5: {
videoserver->toggleFullscreen();
break;
}
case SDLK_F7: {
if ( playMusicOn ) {
playMusicOn = false;
Mixer::mixer().stopMusic();
} else {
playMusicOn = true;
Mixer::mixer().playMusic( MUSIC_INTRO, -1, 1000 );
}
break;
}
case SDLK_UP: {
Mixer::mixer().playSample( choose, 0 );
activeChoice--;
if ( activeChoice < 0 ) activeChoice = NR_INTRO_CHOICES - 1;
break;
}
case SDLK_DOWN: {
Mixer::mixer().playSample( choose, 0 );
activeChoice = (activeChoice + 1) % NR_INTRO_CHOICES;
break;
}
case SDLK_ESCAPE: {
gameState = GS_QUIT;
break;
}
case SDLK_RETURN: {
Mixer::mixer().playSample( confirm, 0 );
switch (activeChoice) {
case ONE_PLAYER_GAME: {
onePlayerGame = true;
arcadeGame = false;
gameState = GS_SET_DIFFICULTY;
break;
}
case TWO_PLAYER_GAME: {
onePlayerGame = false;
arcadeGame = false;
gameState = GS_SET_DIFFICULTY;
break;
}
case ARCADE_GAME: {
onePlayerGame = true;
arcadeGame = true;
gameState = GS_ARCADE_MODE_SETUP;
break;
}
case CONFIGURE_KEYS: {
settings->settingsDialog(screen);
draw();
break;
}
case INFOSCREEN: {
infoscreen->run();
break;
}
case QUIT_AND_DIE: {
gameState = GS_QUIT;
break;
}
}
break;
}
default: break;
}
break;
}
case SDL_QUIT: {
gameState = GS_QUIT;
break;
}
default: break;
}
}
}
void Intro::showScreenshots() {
if ( playMusicOn && Mixer::mixer().whichMusicPlaying() != MUSIC_INTRO ) {
Mixer::mixer().playMusic( MUSIC_INTRO, -1, 1000 );
}
// TODO: Too lazy to fix that
/*
SdlCompat_AcceleratedSurface *surfS = SDL_LoadBMP( FN_ALIENBLASTER_INTRO.c_str() );
SdlCompat_AcceleratedSurface *surf0 = SDL_LoadBMP( FN_SCREENSHOT0.c_str() );
SdlCompat_AcceleratedSurface *surf1 = SDL_LoadBMP( FN_SCREENSHOT1.c_str() );
SdlCompat_AcceleratedSurface *surf2 = SDL_LoadBMP( FN_SCREENSHOT2.c_str() );
SdlCompat_AcceleratedSurface *surf3 = SDL_LoadBMP( FN_SCREENSHOT3.c_str() );
SdlCompat_AcceleratedSurface *surf4 = SDL_LoadBMP( FN_SCREENSHOT4.c_str() );
SdlCompat_AcceleratedSurface *surf5 = SDL_LoadBMP( FN_SCREENSHOT5.c_str() );
SdlCompat_AcceleratedSurface *surf6 = SDL_LoadBMP( FN_SCREENSHOT6.c_str() );
SdlCompat_AcceleratedSurface *surf7 = SDL_LoadBMP( FN_SCREENSHOT7.c_str() );
SdlCompat_AcceleratedSurface *surf8 = SDL_LoadBMP( FN_SCREENSHOT8.c_str() );
SdlCompat_AcceleratedSurface *surf9 = SDL_LoadBMP( FN_SCREENSHOT9.c_str() );
SDL_BlitSurface( surfS, 0, screen, 0 );
SDL_Flip(screen);
SDL_Delay(3000);
int sps = 50; // steps per second
if (blendImages( screen, surfS, 0, surf0, 0, sps ))
if (blendImages( screen, surf0, 0, surf1, 0, sps ))
if (blendImages( screen, surf1, 0, surf2, 0, sps ))
if (blendImages( screen, surf2, 0, surf3, 0, sps ))
if (blendImages( screen, surf3, 0, surf4, 0, sps ))
if (blendImages( screen, surf4, 0, surf5, 0, sps ))
if (blendImages( screen, surf5, 0, surf6, 0,sps ))
if (blendImages( screen, surf6, 0, surf7, 0, sps ))
if (blendImages( screen, surf7, 0, surf8, 0, sps ))
blendImages( screen, surf8, 0, surf9, 0, sps );
*/
}
// TODO: Too lazy to fix that
/*
bool Intro::blendImages( SdlCompat_AcceleratedSurface *screen, SdlCompat_AcceleratedSurface *surf0, SDL_Rect *r1, SdlCompat_AcceleratedSurface *surf1, SDL_Rect *r2, int sps ) {
SDL_Event event;
int i = 0;
int t = SDL_GetTicks();
while (i < 255) {
if (i>255) i=255;
SDL_SetAlpha( surf0, SDL_SRCALPHA, 255-i );
SDL_SetAlpha( surf1, SDL_SRCALPHA, i );
SDL_BlitSurface( surf0, 0, screen, r1 );
SDL_BlitSurface( surf1, 0, screen, r2 );
SDL_Flip( screen );
int t2 = SDL_GetTicks();
int dt= SDL_GetTicks() - t;
t = t2;
i += (dt * sps / 1000);
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYDOWN: {
return false;
}
default:
break;
}
}
}
return true;
}
*/

View File

@@ -1,65 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 INTRO_H
#define INTRO_H
#include <string>
#include "SDL.h"
#include "SdlForwardCompat.h"
#include "game.h"
class Font;
class Infoscreen;
enum IntroChoices { ONE_PLAYER_GAME, TWO_PLAYER_GAME, ARCADE_GAME,
CONFIGURE_KEYS, INFOSCREEN, QUIT_AND_DIE };
const std::string INTRO_CHOICES[] = { "1-Player Action", "2-Player Fight",
"Arcade",
"Configure Keys", "Infoscreen", "Quit and Die" };
const int NR_INTRO_CHOICES = 6;
class Intro {
private:
SdlCompat_AcceleratedSurface *screen;
SdlCompat_AcceleratedSurface *introSprite;
SdlCompat_AcceleratedSurface *activeChoiceSprite;
Font *font;
Font *fontHighlighted;
Infoscreen *infoscreen;
int activeChoice;
// sound
int choose;
int confirm;
public:
Intro( SdlCompat_AcceleratedSurface *scr );
~Intro();
void run( GameStates &gameState );
void showScreenshots();
// bool blendImages( SdlCompat_AcceleratedSurface *screen, SdlCompat_AcceleratedSurface *surf0, SDL_Rect *r1, SdlCompat_AcceleratedSurface *surf1, SDL_Rect *r2, int sps );
private:
void handleEvents( GameStates &gameState );
void draw();
};
#endif

View File

@@ -1,136 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 <iostream>
#include "item.h"
#include "boundingBox.h"
#include "surfaceDB.h"
#include "global.h"
Item::Item(const Vector2D &position, const Vector2D &velocity, ItemTypes itemType) {
this->itemType = itemType;
pos = position;
vel = velocity;
timeLived = 0;
switch (itemType) {
case ITEM_PRIMARY_UPGRADE:
{
sprite = surfaceDB.loadSurface( FN_ITEM_PRIMARY_UPGRADE );
break;
}
case ITEM_DUMBFIRE_DOUBLE:
{
sprite = surfaceDB.loadSurface( FN_ITEM_DUMBFIRE_DOUBLE );
break;
}
case ITEM_KICK_ASS_ROCKET:
{
sprite = surfaceDB.loadSurface( FN_ITEM_KICK_ASS_ROCKET );
break;
}
case ITEM_HELLFIRE:
{
sprite = surfaceDB.loadSurface( FN_ITEM_HELLFIRE );
break;
}
case ITEM_MACHINE_GUN:
{
sprite = surfaceDB.loadSurface( FN_ITEM_MACHINE_GUN );
break;
}
case ITEM_HEALTH:
{
sprite = surfaceDB.loadSurface( FN_ITEM_HEALTH );
break;
}
case ITEM_HEATSEEKER:
{
sprite = surfaceDB.loadSurface( FN_ITEM_HEATSEEKER );
break;
}
case ITEM_NUKE:
{
sprite = surfaceDB.loadSurface( FN_ITEM_NUKE );
break;
}
case ITEM_DEFLECTOR:
{
sprite = surfaceDB.loadSurface( FN_ITEM_DEFLECTOR );
break;
}
case ITEM_LASER:
{
sprite = surfaceDB.loadSurface( FN_ITEM_LASER );
break;
}
case ITEM_ENERGY_BEAM:
{
sprite = surfaceDB.loadSurface( FN_ITEM_ENERGY_BEAM );
break;
}
default:
{
cout << "Item(): unexpected itemType: " << itemType << endl;
sprite = surfaceDB.loadSurface( FN_ITEM_PRIMARY_UPGRADE );
break;
}
}
boundingBox = new BoundingBox( lroundf(pos.getX() - sprite->w / 2.0),
lroundf(pos.getY() - sprite->h / 2.0),
sprite->w, sprite->h );
}
Item::~Item() {
delete boundingBox;
}
void Item::update( int dT ) {
pos += vel * dT / 1000.0;
updateBoundingBox();
timeLived += dT;
}
void Item::deleteItem() {
timeLived = ITEM_LIFETIME;
}
void Item::updateBoundingBox() {
boundingBox->moveUpperBound( lroundf(pos.getY() - sprite->h * 0.5) );
boundingBox->moveLeftBound( lroundf(pos.getX() - sprite->w * 0.5) );
}
void Item::draw(SdlCompat_AcceleratedSurface *screen) {
SDL_Rect r;
r.x = lroundf(pos.getX()) - sprite->w / 2;
r.y = lroundf(pos.getY()) - sprite->h / 2;
r.w = sprite->w;
r.h = sprite->h;
SDL_BlitSurface( sprite, 0, screen, &r );
}
BoundingBox *Item::getBoundingBox() {
return boundingBox;
}

View File

@@ -1,60 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 ITEM_H
#define ITEM_H
#include "SDL.h"
#include "geometry.h"
#include <string>
#include "global.h"
class BoundingBox;
class Item {
SdlCompat_AcceleratedSurface *sprite;
BoundingBox *boundingBox;
Vector2D pos;
Vector2D vel;
ItemTypes itemType;
int timeLived;
void updateBoundingBox();
public:
Item( const Vector2D &position, const Vector2D &velocity, ItemTypes itemType );
~Item();
void update( int dT );
void deleteItem();
void draw(SdlCompat_AcceleratedSurface *screen);
inline bool isExpired() { return (timeLived >= ITEM_LIFETIME); }
inline Vector2D getPos() { return pos; }
inline Vector2D getVel() { return vel; }
inline void pickedUp() { timeLived = ITEM_LIFETIME; }
inline ItemTypes getType() { return itemType; }
BoundingBox *getBoundingBox();
};
#endif

View File

@@ -1,131 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 "item.h"
#include "items.h"
#include "surfaceDB.h"
#include "geometry.h"
#include "global.h"
#include "racers.h"
Items::Items() {
timeNextItemAppear =
ITEM_APPEAR_DELAY +
(rand() % ITEM_APPEAR_RAND_DELAY);
}
Items::~Items() {
vector<Item *>::iterator i;
for (i = items.begin(); i != items.end(); ++i) {
delete *i;
}
}
void Items::addItem(Item *item) {
if (item) {
items.push_back(item);
}
}
void Items::expireItems() {
unsigned int i = 0;
while ( i < items.size() ) {
if ( items[i]->isExpired() ) {
delete items[i];
items.erase(items.begin() + i);
} else {
i++;
}
}
}
void Items::update( int dT ) {
vector<Item *>::iterator i;
for (i = items.begin(); i != items.end(); ++i) {
(*i)->update( dT );
}
}
void Items::draw(SdlCompat_AcceleratedSurface *screen) {
vector<Item *>::iterator i;
for (i = items.begin(); i != items.end(); ++i) {
(*i)->draw(screen);
}
}
Item *Items::getItem(unsigned int idx) {
return items[idx];
}
void Items::generateItemNow( Vector2D pos, Vector2D vel ) {
if ( pos.getX() < 10 ) pos.setX( 10 );
if ( pos.getX() > SCREEN_WIDTH-10 ) pos.setX( SCREEN_WIDTH-10 );
if ( pos.getY() < 100 && vel.getY() < 5 ) vel.setY( 5 );
int itemType;
// 10 tries for a correct item
for ( int i = 0; i < 10; i++ ) {
itemType = getRandValue( ITEM_APPEAR_CHANCES, NR_ITEM_TYPES );
if ( ( racers->isShipTypeActive( LIGHT_FIGHTER ) &&
racers->isShipTypeActive( HEAVY_FIGHTER ) ) ||
( racers->isShipTypeActive( LIGHT_FIGHTER ) &&
( itemType == ITEM_PRIMARY_UPGRADE ||
itemType == ITEM_DUMBFIRE_DOUBLE ||
itemType == ITEM_KICK_ASS_ROCKET ||
itemType == ITEM_HELLFIRE ||
itemType == ITEM_MACHINE_GUN ||
itemType == ITEM_HEALTH ||
itemType == ITEM_HEATSEEKER ||
itemType == ITEM_NUKE ||
itemType == ITEM_ENERGY_BEAM ) ) ||
( racers->isShipTypeActive( HEAVY_FIGHTER ) &&
( itemType == ITEM_PRIMARY_UPGRADE ||
itemType == ITEM_DUMBFIRE_DOUBLE ||
itemType == ITEM_KICK_ASS_ROCKET ||
itemType == ITEM_HEALTH ||
itemType == ITEM_HEATSEEKER ||
itemType == ITEM_NUKE ||
itemType == ITEM_DEFLECTOR ||
itemType == ITEM_LASER ) ) ) {
Item *item = new Item( pos, vel, (ItemTypes)itemType );
addItem( item );
break;
}
}
}
void Items::generate( int dT ) {
timeNextItemAppear -= dT;
if ( timeNextItemAppear < 0 ) {
timeNextItemAppear = ITEM_APPEAR_DELAY + (rand() % ITEM_APPEAR_RAND_DELAY);
generateItemNow( Vector2D( 150 + (rand() % 340), -20 ),
Vector2D( (rand() % lroundf(SCROLL_SPEED)) - SCROLL_SPEED / 2,
SCROLL_SPEED + (rand() % lroundf(SCROLL_SPEED)) ) );
}
}
void Items::deleteAllItems() {
vector<Item *>::iterator i;
for (i = items.begin(); i != items.end(); ++i) {
(*i)->deleteItem();
}
expireItems();
}

View File

@@ -1,51 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 ITEMS_H
#define ITEMS_H
#include "SDL.h"
#include <vector>
class Item;
class Vector2D;
class Items {
vector<Item *> items;
int timeNextItemAppear;
public:
Items();
~Items();
void addItem(Item *item);
void generateItemNow( Vector2D pos, Vector2D vel );
void generate( int dT );
void expireItems();
void update( int dT );
void draw(SdlCompat_AcceleratedSurface *screen);
void deleteAllItems();
inline unsigned int getNrItems() { return items.size(); }
Item *getItem(unsigned int idx);
};
#endif

View File

@@ -1,51 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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"
#include "surfaceDB.h"
#include "SDL.h"
#include <stdlib.h>
#include <android/log.h>
using namespace std;
static void appPutToBackground()
{
SDL_ANDROID_PauseAudioPlayback();
}
static void appPutToForeground()
{
surfaceDB.reloadAllSurfacesToVideoMemory();
SDL_ANDROID_ResumeAudioPlayback();
}
int main(int argc, char *argv[]) {
SDL_ANDROID_SetApplicationPutToBackgroundCallback(&appPutToBackground, &appPutToForeground);
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 0");
SDL_Init(0);
srand(0);
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 1");
Game game;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 2");
game.run();
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 3");
SDL_Quit();
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "main() 4");
return 0;
}

View File

@@ -1,366 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include "menuArcadeMode.h"
#include "global.h"
#include "surfaceDB.h"
#include "mixer.h"
#include "video.h"
#include "font.h"
#include "racer.h"
#include "racers.h"
#include "asstring.h"
#include "options.h"
#include <iostream>
#include <fstream>
MenuArcadeMode::MenuArcadeMode( SdlCompat_AcceleratedSurface *scr ) {
screen = scr;
arcadeSprite = surfaceDB.loadSurface( FN_ARCADE_LOGO );
activeChoiceSprite = surfaceDB.loadSurface( FN_INTRO_SHOW_CHOICE );
font = new Font( FN_FONT_INTRO );
fontHighlighted = new Font( FN_FONT_INTRO_HIGHLIGHTED );
lightFighterIcon1 = surfaceDB.loadSurface( FN_LIGHT_FIGHTER_1_ICON );
heavyFighterIcon1 = surfaceDB.loadSurface( FN_HEAVY_FIGHTER_1_ICON );
choose = Mixer::mixer().loadSample( FN_SOUND_ARCADE_CHOOSE, 100 );
confirm = Mixer::mixer().loadSample( FN_SOUND_ARCADE_CONFIRM, 60 );
activeChoice = 0;
playerOneLightFighter = true;
op = new Options( FN_HIGHSCORE );
// check, if the highscore is open
int highscoreTest;
if ( !op->getInt( "POINTS_1", highscoreTest ) ) {
cout << "Creating the highscore..." << endl;
op->setStr( "ALIENBLASTER", "NAME_1" );
op->setInt( 1666, "POINTS_1" );
op->setStr( "GNOSTICAL", "NAME_2" );
op->setInt( 1000, "POINTS_2" );
op->setStr( "SLOBJOK", "NAME_3" );
op->setInt( 1000, "POINTS_3" );
op->setStr( "SNOWBALL", "NAME_4" );
op->setInt( 1000, "POINTS_4" );
op->setStr( "THUNDERBIRD", "NAME_5" );
op->setInt( 1000, "POINTS_5" );
op->setStr( "KaoT", "NAME_6" );
op->setInt( 666, "POINTS_6" );
op->setStr( "SDL", "NAME_7" );
op->setInt( 500, "POINTS_7" );
op->setStr( "DEBIAN", "NAME_8" );
op->setInt( 400, "POINTS_8" );
op->setStr( "DEV-CPP", "NAME_9" );
op->setInt( 300, "POINTS_9" );
op->setStr( "I RULE", "NAME_10" );
op->setInt( 200, "POINTS_10" );
op->saveFile( FN_HIGHSCORE );
}
}
MenuArcadeMode::~MenuArcadeMode() {
op->saveFile( FN_HIGHSCORE );
delete op;
}
void MenuArcadeMode::run( GameStates &gameState, int points ) {
activeChoice = 0;
if ( GS_ARCADE_MODE_FINISHED ) {
updateHighScore( points );
gameState = GS_ARCADE_MODE_SETUP;
}
draw();
while ( gameState == GS_ARCADE_MODE_SETUP ) {
handleEvents( gameState );
draw();
SDL_Delay( 50 );
}
}
bool MenuArcadeMode::getPlayerOneLightFighter() {
return playerOneLightFighter;
}
void MenuArcadeMode::draw() {
videoserver->clearScreen();
SDL_Rect r;
r.x = screen->w / 2 - arcadeSprite->w / 2;
r.y = 0;
r.w = arcadeSprite->w;
r.h = arcadeSprite->h;
SDL_BlitSurface( arcadeSprite, 0, screen, &r );
string name = "UNKNOWN";
int points = 0;
op->getStr( "NAME_1", name );
op->getInt( "POINTS_1", points );
fontHighlighted->drawStr( screen, 230, 60, "1. " + name + ": " + asString(points) );
for ( int i = 2; i <= 10; i++ ) {
op->getStr( "NAME_" + asString( i ), name );
op->getInt( "POINTS_" + asString( i ), points );
font->drawStr( screen, 230, 40 + i * 25,
asString( i ) + ". " + name + ": " + asString(points) );
}
for ( int i = 0; i < NR_MENU_ARCADE_CHOICES; i++ ) {
if ( activeChoice == i ) {
r.x = 230 - activeChoiceSprite->w - 8;
r.y = 338 + i * 40;
r.w = activeChoiceSprite->w;
r.h = activeChoiceSprite->h;
SDL_BlitSurface( activeChoiceSprite, 0, screen, &r );
fontHighlighted->drawStr( screen, 230, 340 + i * 40, STRINGS_MENU_ARCADE_CHOICES[ i ] );
} else {
font->drawStr( screen, 230, 340 + i * 40, STRINGS_MENU_ARCADE_CHOICES[ i ] );
}
}
font->drawStr( screen, 50, 270, "Player 1" );
if ( playerOneLightFighter ) {
r.x = 100 - lightFighterIcon1->w / 2;
r.y = 340 - lightFighterIcon1->h / 2;
r.w = lightFighterIcon1->w;
r.h = lightFighterIcon1->h;
SDL_BlitSurface( lightFighterIcon1, 0, screen, &r );
} else {
r.x = 100 - heavyFighterIcon1->w / 2;
r.y = 340 - heavyFighterIcon1->h / 2;
r.w = heavyFighterIcon1->w;
r.h = heavyFighterIcon1->h;
SDL_BlitSurface( heavyFighterIcon1, 0, screen, &r );
}
fontHighlighted->drawStr( screen, 100, 400, "Press \"Volume Up\"", FONT_ALIGN_CENTERED );
fontHighlighted->drawStr( screen, 100, 430, "To Change", FONT_ALIGN_CENTERED );
SDL_Flip( screen );
}
void MenuArcadeMode::handleEvents( GameStates &gameState ) {
SDL_Event event;
while ( SDL_PollEvent(&event) ) {
switch(event.type) {
case SDL_KEYDOWN: {
switch ( event.key.keysym.sym ) {
case SDLK_PAGEUP: {
playerOneLightFighter = !playerOneLightFighter;
break;
}
case SDLK_F5: {
videoserver->toggleFullscreen();
break;
}
case SDLK_F7: {
if ( playMusicOn ) {
playMusicOn = false;
Mixer::mixer().stopMusic();
} else {
playMusicOn = true;
Mixer::mixer().playMusic( MUSIC_INTRO, -1, 1000 );
}
break;
}
case SDLK_UP: {
Mixer::mixer().playSample( choose, 0 );
activeChoice--;
if ( activeChoice < 0 ) activeChoice = NR_MENU_ARCADE_CHOICES - 1;
break;
}
case SDLK_DOWN: {
Mixer::mixer().playSample( choose, 0 );
activeChoice = (activeChoice + 1) % NR_MENU_ARCADE_CHOICES;
break;
}
case SDLK_ESCAPE: {
gameState = GS_INTRO;
break;
}
case SDLK_RETURN: {
switch (activeChoice) {
case ARCADE_FIGHT: {
Mixer::mixer().playSample( confirm, 0 );
difficultyLevel = ARCADE_DIFFICULTY_LEVEL;
gameState = GS_PLAYON;
break;
}
case ARCADE_BACK_TO_MAIN_MENU: {
gameState = GS_INTRO;
break;
}
}
break;
}
default: break;
}
break;
}
case SDL_QUIT: {
gameState = GS_QUIT;
break;
}
default: break;
}
}
}
/**************** read the new name for the highscore ***********************/
void MenuArcadeMode::updateHighScore( int points ) {
int pointTenth = -1;
op->getInt( "POINTS_10", pointTenth );
// the player made it in the hall of fame!
if ( points >= pointTenth ) {
int pointsOfEntry = -1;
int newPos = -1;
for ( int i = 1; i <= 10; i++ ) {
op->getInt( "POINTS_" + asString( i ), pointsOfEntry );
if ( pointsOfEntry <= points ) {
newPos = i;
break;
}
}
if ( newPos != -1 ) {
// move the positions after newPos one position further down
int pointsPrev;
string namePrev;
for ( int i = 10; i > newPos; i-- ) {
op->getInt( "POINTS_" + asString( i-1 ), pointsPrev );
op->getStr( "NAME_" + asString( i-1 ), namePrev );
op->setInt( pointsPrev, "POINTS_" + asString ( i ) );
op->setStr( namePrev, "NAME_" + asString( i ) );
}
op->setInt( points, "POINTS_" + asString( newPos ) );
op->setStr( "? ? ? ?", "NAME_" + asString( newPos ) );
readHighScoreName( newPos );
}
op->saveFile( FN_HIGHSCORE );
}
}
void MenuArcadeMode::readHighScoreName( int pos ) {
videoserver->clearScreen();
SDL_Rect r;
r.x = screen->w / 2 - arcadeSprite->w / 2;
r.y = 0;
r.w = arcadeSprite->w;
r.h = arcadeSprite->h;
SDL_BlitSurface( arcadeSprite, 0, screen, &r );
string name = "UNKNOWN";
int points = 0;
for ( int i = 1; i <= 10; i++ ) {
op->getStr( "NAME_" + asString( i ), name );
op->getInt( "POINTS_" + asString( i ), points );
if ( pos == i ) {
fontHighlighted->drawStr( screen, 230, 40 + i * 25,
asString( i ) + ". " + name + ": " + asString(points) );
} else {
font->drawStr( screen, 230, 40 + i * 25,
asString( i ) + ". " + name + ": " + asString(points) );
}
}
fontHighlighted->drawStr( screen, 320, 340, "CONGRATULATION - Enter your worthy name!",
FONT_ALIGN_CENTERED );
string newName = "";
while ( handleEventsReadName( newName ) ) {
drawReadName( newName );
SDL_Flip( screen );
SDL_Delay( 50 );
}
op->setStr( newName, "NAME_" + asString( pos ) );
}
bool MenuArcadeMode::handleEventsReadName( string &newName ) {
bool moreToRead = true;
SDL_Event event;
while ( SDL_PollEvent(&event) ) {
if ( event.type == SDL_KEYDOWN ) {
switch ( event.key.keysym.sym ) {
case SDLK_F5: {
videoserver->toggleFullscreen();
break;
}
case SDLK_F7:
{
if ( playMusicOn ) {
playMusicOn = false;
Mixer::mixer().stopMusic();
} else {
playMusicOn = true;
Mixer::mixer().playMusic( MUSIC_INTRO, -1, 1000 );
}
break;
}
case SDLK_RETURN:
{
moreToRead = false;
break;
}
case SDLK_BACKSPACE:
{
if ( newName.length() > 0 ) {
newName.resize( newName.length() - 1 );
}
break;
}
default:
{
if ( newName.length() <= 15 ) {
if ( SDLK_a <= event.key.keysym.sym &&
event.key.keysym.sym <= SDLK_z ) {
if ( ((SDL_GetModState()) & KMOD_LSHIFT != 0 ) ||
((SDL_GetModState()) & KMOD_RSHIFT != 0 ) ) {
newName += asString( (char)('A' + event.key.keysym.sym - SDLK_a ) );
} else {
newName += asString( (char)('a' + event.key.keysym.sym - SDLK_a ) );
}
} else if ( event.key.keysym.sym == SDLK_SPACE ) {
newName += " ";
}
}
break;
}
}
}
}
return moreToRead;
}
void MenuArcadeMode::drawReadName( string &name ) {
SDL_Rect r;
r.x = 150;
r.y = 380;
r.w = 400;
r.h = 40;
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 0, 0, 0) );
fontHighlighted->drawStr( screen, 320, 380, name, FONT_ALIGN_CENTERED );
}

View File

@@ -1,72 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 MENU_ARCADE_MODE_H
#define MENU_ARCADE_MODE_H
#include "SDL.h"
#include "game.h"
#include <string>
class Font;
class Options;
enum MENU_ARCADE_CHOICES { ARCADE_FIGHT, ARCADE_BACK_TO_MAIN_MENU };
const std::string STRINGS_MENU_ARCADE_CHOICES[] =
{ "FIGHT",
"Back to Main Menu" };
const int NR_MENU_ARCADE_CHOICES = 2;
class MenuArcadeMode {
private:
SdlCompat_AcceleratedSurface *screen;
SdlCompat_AcceleratedSurface *arcadeSprite;
SdlCompat_AcceleratedSurface *activeChoiceSprite;
SdlCompat_AcceleratedSurface *lightFighterIcon1;
SdlCompat_AcceleratedSurface *heavyFighterIcon1;
Font *font;
Font *fontHighlighted;
Options *op;
int activeChoice;
// sounds
int choose;
int confirm;
bool playerOneLightFighter;
public:
MenuArcadeMode( SdlCompat_AcceleratedSurface *scr );
~MenuArcadeMode();
void run( GameStates &gameState, int points=-1 );
bool getPlayerOneLightFighter();
private:
void updateHighScore( int points );
void readHighScoreName( int pos );
void drawReadName( string &newName );
bool handleEventsReadName( string &newName );
void handleEvents( GameStates &gameState );
void draw();
};
#endif

View File

@@ -1,242 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include "mixer.h"
#include "SDL_mixer.h"
#include <string>
#include <fstream>
#include <iostream>
#ifdef ANDROID
#include <android/log.h>
#endif
Mixer * mixerInstance = NULL;
Mixer & Mixer::mixer()
{
if( mixerInstance == NULL )
mixerInstance = new Mixer();
return *mixerInstance;
}
Mixer::Mixer() {
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio");
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
printf("Couldn't initialize SDL audio subsystem: %s\n", SDL_GetError());
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", "Couldn't initialize SDL audio subsystem: %s", SDL_GetError());
exit(1);
}
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio 2");
mixChunks = MixChunks(0);
musics = Musics(0);
enabled = false;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio 3");
initMixer();
lastUsedReservedChannel = 0;
reservedChannels = 0;
musicPlaying = MUSIC_NONE;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio done");
}
Mixer::~Mixer() {
if (enabled) {
freeMixer();
}
}
void Mixer::initMixer() {
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio 4");
enabled = (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 1, 1024) >= 0);
if (enabled) {
Mix_AllocateChannels(MIXER_NUMBER_CHANNELS);
reservedChannels = Mix_ReserveChannels( MIXER_RESERVED_CHANNELS );
if ( MIXER_RESERVED_CHANNELS != reservedChannels )
cout << "reserve channels not successfull: reserved: " << reservedChannels << endl;
lastUsedReservedChannel = 0;
fn2snd.clear();
fn2mus.clear();
playsOn.clear();
}
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Initializing audio 5");
}
void Mixer::freeMixer() {
if (enabled) {
Mix_ExpireChannel(-1, 0);
for (unsigned int index = 0; index < mixChunks.size(); index++) {
Mix_FreeChunk(mixChunks[index]);
}
for (unsigned int index = 0; index < musics.size(); index++) {
Mix_FreeMusic(musics[index]);
}
}
}
int Mixer::loadSample(string fileName, int volume) {
if (enabled) {
if (fn2snd.find(fileName) == fn2snd.end()) {
string fn = fileName;
string fn1 = fn;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", (string( "Loading sound " ) + fn).c_str() );
// Check if file exist
FILE * inputFile = fopen( fn1.c_str(), "rb");
if (!inputFile) {
if( fn1.size() > 4 && fn1.find(".wav") != string::npos ) {
fn1 = fn1.substr( 0, fn1.size() - 4 ) + ".ogg";
inputFile = fopen( fn1.c_str(), "rb");
}
if (!inputFile) {
cout << "ERROR: file " << fn1 << " does not exist!" << endl;
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load sound " ) + fn1).c_str() );
#endif
exit(1);
}
}
fclose(inputFile);
// TODO: error-handling
Mix_Chunk *newSound = Mix_LoadWAV(fn1.c_str());
if( !newSound ) {
cout << "ERROR: file " << fn1 << " cannot be loaded!" << endl;
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load sound " ) + fn1).c_str() );
#endif
exit(1);
}
mixChunks.push_back(newSound);
fn2snd[ fileName ] = mixChunks.size() - 1;
if ( 0 <= volume && volume < 128 ) {
Mix_VolumeChunk( mixChunks[ mixChunks.size() - 1 ], volume );
}
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", (string( "Loading sound " ) + fn1 + " done").c_str() );
return mixChunks.size() - 1;
}
return fn2snd[ fileName ];
}
return 0;
}
bool Mixer::playSample( int sampleId, int loop, bool withPriority ) {
int ret = -1;
if (enabled) {
if ( !withPriority || reservedChannels == 0 ) {
ret = Mix_PlayChannel(-1, mixChunks[sampleId], loop);
playsOn[ sampleId ] = ret;
} else {
lastUsedReservedChannel = (lastUsedReservedChannel+1) % reservedChannels;
ret = Mix_PlayChannel( lastUsedReservedChannel, mixChunks[sampleId], loop );
playsOn[ sampleId ] = ret;
}
//if ( ret == -1 ) cout << "playSample: error: " << Mix_GetError() << endl;
return ret != -1;
}
return true;
}
bool Mixer::stopSample(int sampleId) {
if (enabled) {
return Mix_HaltChannel( playsOn[sampleId] ) != -1;
}
return true;
}
void Mixer::reset() {
freeMixer();
if (enabled) {
initMixer();
}
}
void Mixer::fadeOut(int mSecs) {
if (enabled) {
Mix_FadeOutChannel(-1, mSecs);
}
}
int Mixer::loadMusic( string fn ) {
if (enabled) {
if (fn2mus.find(fn) == fn2mus.end()) {
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", (string( "Loading music " ) + fn).c_str() );
string fn1 = fn;
// Check if file exist
FILE * inputFile = fopen( fn1.c_str(), "rb");
if (!inputFile) {
if( fn1.size() > 4 && fn1.find(".wav") != string::npos ) {
fn1 = fn1.substr( 0, fn1.size() - 4 ) + ".ogg";
inputFile = fopen( fn1.c_str(), "rb");
}
if (!inputFile) {
cout << "ERROR: file " << fn1 << " does not exist!" << endl;
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load sound " ) + fn1).c_str() );
#endif
exit(1);
}
}
fclose(inputFile);
// TODO: error-handling
Mix_Music *newSound = Mix_LoadMUS(fn1.c_str());
if( !newSound ) {
cout << "ERROR: file " << fn1 << " cannot be loaded!" << endl;
#ifdef ANDROID
__android_log_print(ANDROID_LOG_ERROR, "Alien Blaster", (string( "Cannot load sound " ) + fn1).c_str() );
#endif
exit(1);
}
musics.push_back(newSound);
fn2mus[ fn ] = musics.size() - 1;
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", (string( "Loading music " ) + fn1 + " done").c_str() );
return musics.size() - 1;
}
return fn2mus[ fn ];
}
return 0;
}
void Mixer::playMusic( MusicTracks musNum, int loop, int fadeInTime ) {
if (enabled) {
if ( musNum < NR_MUSIC_TRACKS ) {
Mix_FadeInMusic( musics[ loadMusic( FN_MUSIC[ (int)musNum ] ) ], loop, fadeInTime );
musicPlaying = musNum;
}
}
}
void Mixer::stopMusic( int fadeOutTime ) {
if (enabled) {
Mix_FadeOutMusic( fadeOutTime );
}
}
MusicTracks Mixer::whichMusicPlaying() {
return musicPlaying;
}

View File

@@ -1,104 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 MIXER_HH
#define MIXER_HH
#include "SDL.h"
#include "SDL_mixer.h"
#include <vector>
#include <map>
#include <string>
#include "global.h"
typedef vector<Mix_Chunk*> MixChunks;
typedef vector<Mix_Music*> Musics;
class Mixer;
const int MIXER_NUMBER_CHANNELS = 32;
// reserved for samples, which should play with priority
const int MIXER_RESERVED_CHANNELS = 8;
class Mixer {
private:
MixChunks mixChunks;
Musics musics;
void initMixer();
void freeMixer();
map< string, int > fn2mus;
map< string, int > fn2snd;
map< int, int > playsOn;
bool enabled;
int reservedChannels;
int lastUsedReservedChannel;
MusicTracks musicPlaying;
public:
Mixer();
~Mixer();
/*
Loads a sample, returns an id used for playSample
0 as a return value indicates an error on loading
param volume: use with care: if the sound is loaded
for the first time, its volumevalue will be set to
volume, else it will be ignored. (0..127)
*/
int loadSample(string fileName, int volume=10);
/*
plays the sample with the given id
if withPriority==true the sample will be played in one of the reserved channels
returns true if successfull, false otherwise
*/
bool playSample(int sampleId, int loop, bool withPriority=false);
bool stopSample(int sampleId);
/*
resets the Mixer (frees all samples and channels, inits new ones).
Use with care:
- samples still playing will be apruptly halted
- keep in mind that there is only one mixer
=> it is resetted globally!!!
*/
void reset();
/*
fades out all channels
*/
void fadeOut(int mSecs);
int loadMusic( string fileName );
void playMusic( MusicTracks musNum, int loop, int fadeInTime=0 );
void stopMusic( int fadeOutTime=0 );
MusicTracks whichMusicPlaying();
static Mixer & mixer();
};
#endif //#define MIXER_HH

View File

@@ -1,183 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
using namespace std;
#include "options.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <sstream>
Options::Options(const string lFilename) {
if (lFilename == "") {
cout << "Options: no filename given!" << endl;
filename = string("config");
} else {
// save the filename for later use
filename = lFilename;
}
// open the file for reading
ifstream inputFile (filename.c_str(), ios::in);
// TODO FIXME ordentliches Filelocking machen
// fcntl(inputFile.rdbuf()->fd(), F_SETLKW, fileLock(F_RDLCK));
if (inputFile.good()) {
// while still data there
while (!inputFile.eof()) {
string newLine;
getline( inputFile, newLine );
// search delimiter
unsigned int pos = newLine.find("=");
// comment line or no delimiter found
if (( newLine[0] != '#' ) && ( pos != string::npos )) {
string key = newLine.substr(0,pos);
string val = newLine.substr(pos+1);
keymap[ key ] = val;
}
}
}
else {
cout << "Options: Error while opening " << filename << endl;
}
// TODO FIXME ordentliches Filelocking machen
// fcntl(inputFile.rdbuf()->fd(), F_SETLKW, fileLock(F_UNLCK));
inputFile.close();
// if (inputFile.fail()) {
// cout << "Options: Error while closing " << filename << endl;
// }
}
Options::~Options() {
;
}
// flock* Options::fileLock(const short type) {
// static flock ret ;
// ret.l_type = type ;
// ret.l_start = 0 ;
// ret.l_whence = SEEK_SET ;
// ret.l_len = 0 ;
// ret.l_pid = getpid() ;
// return &ret ;
// }
int Options::saveFile( const string lFilename ) {
// alternative filename given ?
if (lFilename != "") {
filename = lFilename;
}
// delete original options-file
remove(filename.c_str());
ofstream outputFile( filename.c_str(), ios::out );
// TODO FIXME ordentliches Filelocking machen
// fcntl(outputFile.rdbuf()->fd(), F_SETLKW, fileLock(F_WRLCK));
if (outputFile.good()) {
map< string, string >::const_iterator iter;
for(iter = keymap.begin(); iter != keymap.end(); iter++){
outputFile << iter->first << "=" << iter->second << endl;
}
}
else {
cout << "Options::saveFile(): error while opening file " << filename << endl;
return -1;
}
// TODO FIXME ordentliches Filelocking machen
// fcntl(outputFile.rdbuf()->fd(), F_SETLKW, fileLock(F_UNLCK));
outputFile.close();
if (!outputFile.good()) {
cout << "Options::saveFile(): error while closing file " << filename << endl;
return -2;
}
return 0; // everything's fine
}
bool Options::exist(const string keyword) {
return (keymap.find(keyword) != keymap.end());
}
bool Options::getStr(const string keyword, string &val) {
if (exist(keyword)) {
val = keymap[keyword];
return true;
}
return false;
}
bool Options::getInt(const string keyword, int &val) {
if (exist(keyword)) {
val = atoi( keymap[keyword].c_str() );
return true;
}
return false;
}
bool Options::getUInt(const string keyword, unsigned int &val) {
if (exist(keyword)) {
val = atoll( keymap[keyword].c_str() );
return true;
}
return false;
}
bool Options::setStr(const string newValue, const string keyword) {
keymap[keyword] = newValue;
return true;
}
bool Options::setInt(const int newValue, const string keyword) {
keymap[keyword] = asString( newValue );
return true;
}
bool Options::setUInt(const unsigned int newValue, const string keyword) {
keymap[keyword] = asString( newValue );
return true;
}
void Options::printall() {
map< string, string >::const_iterator iter;
for(iter = keymap.begin(); iter != keymap.end(); iter++){
cout << iter->first << "=" << iter->second << endl;
}
}

View File

@@ -1,84 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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.
***************************************************************************/
/**
* @file Options.h
* @brief The Options-class can manage a configuration file.
* @date 23.06.02
* The Options-class can manage a configuration file of this style:
* KEYWORD=value
* Provides easy-access functions for the keywords.
* $Id: options.h,v 1.2 2003/12/08 18:21:21 schwardt Exp $
*/
#ifndef __OPTIONS_H__
#define __OPTIONS_H__
#include <map>
#include <string>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>
#include "asstring.h"
class Options {
private:
std::map< std::string, std::string > keymap;
std::string filename;
public:
/// Constructor. Reads the configurationfile specified by lFilename.
Options( const std::string lFilename );
/// Destructor. Frees all memory allocated.
~Options();
/// Returns structure used for filelocking
// flock* Options::fileLock(const short type); // FIXME
/// Returns true if the given keyword exist
bool exist(const std::string keyword);
/// Returns the int value of keyword.
/// If keyword is not found returns 0.
bool getInt( const std::string keyword, int &val );
/// Returns the unsigned int value of keyword.
/// If keyword is not found returns 0.
bool getUInt( const std::string keyword, unsigned int &val );
/// Returns a copy of the char* value of keyword.
/// If keyword is not found returns NULL.
bool getStr( const std::string keyword, std::string &val );
/// sets the value of the given keyword to newValue
bool setInt( const int newValue, const std::string keyword );
/// sets the value of the given keyword to newValue
bool setUInt( const unsigned int newValue, const std::string keyword );
/// sets the value of the given keyword to newValue
bool setStr( const std::string newValue, const std::string keyword );
/// Stores the config-File to disk (filename as specified in the constructor).
/// You should call this function after changing a value.
int saveFile( const std::string lFilename );
/// Prints all lines of the actual configuration to cout.
void printall();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,195 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 RACER_HH
#define RACER_HH
#include "SDL.h"
#include "geometry.h"
#include <string>
#include "global.h"
#include "settings.h"
class SurfaceDB;
class Gate;
class Track;
class Shot;
class Shots;
class Items;
class Font;
class BoundingBox;
class ShieldGlow;
/* The Racer is the vehicle, that the player can steer. */
class Racer {
SdlCompat_AcceleratedSurface *spriteRacerBase;
SDL_Rect drawRectBase;
SdlCompat_AcceleratedSurface *spriteShadow;
SdlCompat_AcceleratedSurface *spriteDeflector;
SDL_Rect drawRectDeflector;
SdlCompat_AcceleratedSurface *spriteHPStat;
SdlCompat_AcceleratedSurface *spriteFighterIcon;
// for collision with other racers or shots.
// A rectangle with racersize * 0.9 is used.
BoundingBox *boundingBox;
int playerNr;
int shipType;
Font *font; // font used for displaying ammo and lapcnt
int fontSize;
SdlCompat_AcceleratedSurface *spriteSecondaryWeapons;
SdlCompat_AcceleratedSurface *spriteSpecials;
int sndShotPrimary;
int sndShotSecondary;
float points;
// Movement-System
Vector2D pos; // absolute position
float shipAngle; // the orientation
Vector2D vel; // the velocity vector
// the boundary of the world (i.e. the reachable section of the screen)
RectangleGeo *boundaryRect;
// Weapon-System
ShotTypes primaryShotType;
Uint32 timeLastShotPrimary;
ShotTypes activeSecondary;
Uint32 timeLastShotSecondary;
bool secondaryWeaponsAvailability[ NR_SECONDARY_WEAPONS ];
bool lastDumbfireWasLeft;
SpecialTypes activeSpecial;
int specialsAvailability[ NR_SPECIALS ];
Uint32 timeLastNukeUsed;
Uint32 timeLastHeatseekerUsed;
bool lastHeatseekerWasLeft;
bool deflectorActive;
int deflectorTimeLeft;
// Damage-System
float shield;
float damage;
float pixPerHP;
float maxShield;
float maxDamage;
// not used at the moment:
// returns the maximum reachable velocity.
// if damage < 100 the reachable velocity will be reduced linearly
float getActVelMax();
float maxVel;
// needed for displaying the shield glow, when hit
Uint32 shieldDamageEndTime;
bool shieldDamageActive;
ShieldGlow *shieldGlow;
Uint32 timeLastMove;
void repair( float amount );
bool thrust;
bool backwards;
bool left;
bool right;
bool fireWeapons;
bool useSpecial;
void addBannerItemCollected( BannerTexts text );
public:
// Input-System - which keys are pressed at the moment
void handlePlayerEvent( PlayerEvent pEvent, bool keyDown );
Racer( string fnSprite, int whichPlayer, Vector2D startpos, int newShipType );
~Racer();
bool isDeflectorSpecialActive() { return deflectorActive; }
inline int getPlayerNr() { return playerNr; }
inline int getShipType() { return shipType; }
void setPos( const Vector2D &newPos );
inline Vector2D getPos() { return pos; }
inline Vector2D getVel() { return vel; }
Vector2D setVel( const Vector2D &newVel ); // returns old vel
// moves the racer according to his velocity and the pressed keys.
// Already collides with the boundaryRect (the border of the world)
Vector2D move( int dT );
void clipWorld();
// move the boundingBox accordingly to the movement
void updateBoundingBox();
// fire the Guns!
void shootPrimary();
void shootSecondary();
void shootSpecial();
// switch to the next available weapon
// void switchPrimary();
void switchSecondary();
void switchSpecials();
// use the active special, if it should be used _once_ when keyDown-Event occurs
void specialKeyDown();
// switch special, if the activespecial is out of ammo
void specialKeyUp();
void drawRacer( SdlCompat_AcceleratedSurface *screen );
void drawShadow( SdlCompat_AcceleratedSurface *screen );
void drawStats( SdlCompat_AcceleratedSurface *screen );
// collision system
// return if the line between the two points collides with the boundingBox
bool collidesWith( const Vector2D &shotPosOld, const Vector2D &shotPosNew );
// return if the racers boundingBox overlaps with box
bool collidesWith( BoundingBox *box );
// return if the racers boundingBox overlaps with circle
bool collidesWith( const Circle &circle );
// returns if a inner circle around the racer overlaps with circle
bool collidesWithAsCircle( const Circle &circle );
// returns if a inner circle around the racer overlaps with circle
bool collidesWithAsCircle( BoundingBox *box );
// returns the boundingBox of the racer
BoundingBox *getBoundingBox();
// the racer got hit -> do the damage according to the shotType
void doDamage( ShotTypes shotType );
// recharge the shield
void rechargeShield( int dT );
// the racer was hit
void receiveDamage( float amount );
bool isDead();
void receivePoints( float amount );
// picks up items, if flown over
void pickUpItems();
// returns the number of laps completed by the racer
int getPoints() { return (int)(points + 0.5); }
};
#endif

View File

@@ -1,204 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 <iostream>
#include "racer.h"
#include "racers.h"
#include "shots.h"
#include "items.h"
#include "enemys.h"
#include "enemy.h"
#include "explosions.h"
#include "explosion.h"
#include "global.h"
Racers::Racers() {
pointsInArcadeMode = 0;
}
Racers::~Racers() {
vector<Racer *>::iterator i;
for ( i = racers.begin(); i != racers.end(); ++i ) {
delete *i;
}
}
bool Racers::isShipTypeActive( int shipType ) {
vector<Racer *>::iterator i;
for ( i = racers.begin(); i != racers.end(); ++i ) {
if ( (*i)->getShipType() == shipType ) {
return true;
}
}
return false;
}
Racer *Racers::getRacer( unsigned int i ) {
return racers[i];
}
void Racers::addRacer( Racer *racer ) {
if (racer) {
racers.push_back(racer);
}
}
void Racers::deleteRacers() {
racers.clear();
}
void Racers::collideWithEnemys() {
for ( unsigned int i = 0; i < racers.size(); ++i ) {
for ( unsigned int j = 0; j < enemys->getNrEnemys(); ++j ) {
// wurde noch nicht von einem anderen Racer gerammt und fliegt ebenfalls
if ( !(enemys->getEnemy( j )->isExpired()) &&
ENEMY_FLYING[ enemys->getEnemy( j )->getType() ] ) {
// kollidiert
if ( racers[i]->collidesWithAsCircle( enemys->getEnemy( j )->getBoundingCircle() ) ) {
// explosion
Explosion *newExplosion =
new Explosion( FN_EXPLOSION_ENEMY, enemys->getEnemy( j )->getPos(), enemys->getEnemy( j )->getVel(), EXPLOSION_NORMAL_AIR );
explosions->addExplosion( newExplosion );
enemys->getEnemy( j )->expire();
racers[i]->receiveDamage( ENEMY_COLLISION_DAMAGE[ enemys->getEnemy( j )->getType() ]);
}
}
}
}
}
void Racers::moveAndCollide( int dT ) {
for ( unsigned int i = 0; i < racers.size(); ++i ) {
racers[i]->move( dT );
collideWithEnemys();
}
}
void Racers::pickUpItems() {
vector<Racer *>::iterator i;
for ( i = racers.begin(); i != racers.end(); ++i ) {
(*i)->pickUpItems();
}
}
void Racers::shoot() {
for ( unsigned int i = 0; i < racers.size(); i++ ) {
racers[i]->shootPrimary();
racers[i]->shootSecondary();
racers[i]->shootSpecial();
}
}
void Racers::rechargeShield( int dT ) {
vector<Racer *>::iterator i;
for (i = racers.begin(); i != racers.end(); ++i) {
(*i)->rechargeShield( dT );
}
}
void Racers::drawRacers( SdlCompat_AcceleratedSurface *screen ) {
vector<Racer *>::iterator i;
for (i = racers.begin(); i != racers.end(); ++i) {
(*i)->drawRacer(screen);
}
}
void Racers::drawShadows( SdlCompat_AcceleratedSurface *screen ) {
vector<Racer *>::iterator i;
for (i = racers.begin(); i != racers.end(); ++i) {
(*i)->drawShadow(screen);
}
}
void Racers::drawStats( SdlCompat_AcceleratedSurface *screen ) {
vector<Racer *>::iterator i;
for (i = racers.begin(); i != racers.end(); ++i) {
(*i)->drawStats(screen);
}
}
bool Racers::bothPlayersLost() {
bool allLost = true;
for ( unsigned int i = 0; i < racers.size(); ++i) {
if ( !racers[i]->isDead() ) {
allLost = false;
}
}
return allLost;
}
void Racers::receivePointsArcade( float amount ) {
for ( unsigned int i = 0; i < racers.size(); ++i) {
racers[i]->receivePoints( amount );
}
}
int Racers::getPointsArcadeMode() {
if (!arcadeGame) return -1;
if (!racers.empty()) {
return racers[0]->getPoints();
}
else return pointsInArcadeMode;
}
void Racers::expireRacers() {
unsigned int i = 0;
while ( i < racers.size() ) {
if ( racers[i]->isDead() ) {
// explode
Explosion *newExplosion =
new Explosion( FN_EXPLOSION_ENEMY, racers[i]->getPos(),
racers[i]->getVel(), EXPLOSION_NORMAL_AIR );
explosions->addExplosion( newExplosion );
if ( arcadeGame ) pointsInArcadeMode = racers[i]->getPoints();
delete racers[i];
racers.erase(racers.begin() + i);
} else {
i++;
}
}
}
void Racers::getKeyActionMaps() {
playerKeys0 = settings->getPlayerKeys( 0 );
playerKeys1 = settings->getPlayerKeys( 1 );
}
void Racers::handleEvent( const SDLKey key, const bool pressed ) {
PlayerEvent pEvent0 = playerKeys0[ key ];
if ( pEvent0 != PE_UNKNOWN ) {
handlePlayerEvent( pEvent0, 0, pressed );
}
PlayerEvent pEvent1 = playerKeys1[ key ];
if ( pEvent1 != PE_UNKNOWN ) {
handlePlayerEvent( pEvent1, 1, pressed );
}
}
void Racers::handlePlayerEvent( PlayerEvent pEvent, int playerNr, bool keyDown ) {
for ( unsigned int i = 0; i < racers.size(); i++ )
if ( racers[i]->getPlayerNr() == playerNr )
racers[i]->handlePlayerEvent( pEvent, keyDown );
}

View File

@@ -1,92 +0,0 @@
/***************************************************************************
alienBlaster
Copyright (C) 2004
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
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, 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 RACER_H
#define RACER_H
#include <vector>
#include "SDL.h"
#include "settings.h"
class Racer;
class Shots;
class Items;
class Enemys;
class Explosions;
/* A class, that manages the individual racers.
It is used for everything, that the racers are capable of doing.
*/
class Racers {
vector<Racer *> racers;
// points reached by racer 0 in arcade mode
int pointsInArcadeMode;
void collideWithEnemys();
PlayerKeys playerKeys0;
PlayerKeys playerKeys1;
public:
Racers();
~Racers();
bool isShipTypeActive( int shipType );
void addRacer( Racer *racer );
void deleteRacers();
Racer *getRacer(unsigned int i);
unsigned int getNrRacers() { return racers.size(); }
// Moves the racers. Calculates collisions between the racers and
// collisions between a racer and enemies.
void moveAndCollide( int dT );
// Checks if a racer has picked up an item by flying over it.
void pickUpItems();
// Checks if a racer was at his pitstop and is being repaired.
// void repair( PitStops *pitStops );
// Lets the racers shoot, if they want to.
void shoot();
// recharge the shields
void rechargeShield( int dT );
// draws the racers.
void drawRacers( SdlCompat_AcceleratedSurface *screen );
void drawShadows( SdlCompat_AcceleratedSurface *screen );
void drawStats( SdlCompat_AcceleratedSurface *screen );
// returns, which racer has shot more enemys
//int getWinner();
void expireRacers();
bool bothPlayersLost();
void receivePointsArcade( float amount );
int getPointsArcadeMode();
void getKeyActionMaps();
void handleEvent( const SDLKey key, const bool pressed );
private:
void handlePlayerEvent( PlayerEvent pEvent, int playerNr, bool keyDown );
};
#endif

Some files were not shown because too many files have changed in this diff Show More