forked from KolibriOS/kolibrios
Added port HydraCastleLabyrinth.
git-svn-id: svn://kolibrios.org@9566 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
cb09ffbbd3
commit
74e4f2673b
339
contrib/games/hydracastlelabyrinth/LICENSE
Normal file
339
contrib/games/hydracastlelabyrinth/LICENSE
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
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 Lesser 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.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
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 Lesser General
|
||||
Public License instead of this License.
|
94
contrib/games/hydracastlelabyrinth/Makefile
Normal file
94
contrib/games/hydracastlelabyrinth/Makefile
Normal file
@ -0,0 +1,94 @@
|
||||
CC = kos32-gcc
|
||||
LD = kos32-ld
|
||||
OBJCOPY = kos32-objcopy
|
||||
KPACK = kpack
|
||||
STRIP = kos32-strip
|
||||
|
||||
HCL = hcl
|
||||
|
||||
SDK_DIR = $(abspath ../../sdk)
|
||||
|
||||
CFLAGS = -c -O2 -std=c11 -mpreferred-stack-boundary=2 -fno-ident -fomit-frame-pointer -fno-stack-check \
|
||||
-fno-stack-protector -mno-stack-arg-probe -fno-exceptions -fno-asynchronous-unwind-tables \
|
||||
-ffast-math -mno-ms-bitfields -march=pentium-mmx \
|
||||
-U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -D_KOLIBRI \
|
||||
-D_GNU_SOURCE=1 -Wno-missing-field-initializers -D_SDL -DUSE_SDL=1 -DOGG_MUSIC
|
||||
|
||||
LDFLAGS = -static -S -nostdlib -T $(SDK_DIR)/sources/newlib/app.lds -Map=output.map --image-base 0 --subsystem native
|
||||
|
||||
INCLUDES = -I$(SDK_DIR)/sources/newlib/libc/include -I$(SDK_DIR)/sources/SDL-1.2.2_newlib/include -I$(SDK_DIR)/sources/SDL_mixer-1.2.12 -Isrc
|
||||
LIBPATH = -L$(SDK_DIR)/lib
|
||||
|
||||
GAME_OBJS = \
|
||||
src/collision.o \
|
||||
src/effect.o \
|
||||
src/enemy.o \
|
||||
src/game.o \
|
||||
src/hero.o \
|
||||
src/ini.o \
|
||||
src/inventory.o \
|
||||
src/main.o \
|
||||
src/object.o \
|
||||
src/options.o \
|
||||
src/PHL.o \
|
||||
src/platform.o \
|
||||
src/qda.o \
|
||||
src/stagedata.o \
|
||||
src/text.o \
|
||||
src/titlescreen.o \
|
||||
src/weapon.o \
|
||||
src/enemies/batboss.o \
|
||||
src/enemies/bat.o \
|
||||
src/enemies/bee.o \
|
||||
src/enemies/boar.o \
|
||||
src/enemies/boomknight.o \
|
||||
src/enemies/crab.o \
|
||||
src/enemies/devil.o \
|
||||
src/enemies/dodo.o \
|
||||
src/enemies/dog.o \
|
||||
src/enemies/firewheel.o \
|
||||
src/enemies/fish.o \
|
||||
src/enemies/garm.o \
|
||||
src/enemies/gas.o \
|
||||
src/enemies/ghoul.o \
|
||||
src/enemies/golem.o \
|
||||
src/enemies/gyra.o \
|
||||
src/enemies/heads.o \
|
||||
src/enemies/hydra.o \
|
||||
src/enemies/jellyfish.o \
|
||||
src/enemies/knight.o \
|
||||
src/enemies/lolidra.o \
|
||||
src/enemies/pendulum.o \
|
||||
src/enemies/podoboo.o \
|
||||
src/enemies/poisonknight.o \
|
||||
src/enemies/pumpkin.o \
|
||||
src/enemies/seal.o \
|
||||
src/enemies/skeleton.o \
|
||||
src/enemies/skull.o \
|
||||
src/enemies/slime.o \
|
||||
src/enemies/slug.o \
|
||||
src/enemies/thwomp.o \
|
||||
src/enemies/waterjumper.o \
|
||||
src/enemies/wizard.o
|
||||
|
||||
SDL_OBJS = src/sdl/audio.o \
|
||||
src/sdl/input.o \
|
||||
src/sdl/graphics.o \
|
||||
src/sdl/system.o \
|
||||
src/sdl/joystick_stub.o
|
||||
|
||||
MISC_OBJS = src/misc.o
|
||||
|
||||
LIBS = -lSDL_mixer -lvorbis -logg -lSDLn -lsound -lgcc -lc.dll
|
||||
|
||||
$(HCL): $(GAME_OBJS) $(SDL_OBJS) $(MISC_OBJS)
|
||||
$(LD) $(LDFLAGS) $(LIBPATH) $(GAME_OBJS) $(SDL_OBJS) $(MISC_OBJS) -o $(HCL) $(LIBS)
|
||||
$(STRIP) -S $(HCL)
|
||||
$(OBJCOPY) $(HCL) -O binary
|
||||
$(KPACK) --nologo $(HCL)
|
||||
|
||||
%.o : %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm $(GAME_OBJS) $(SDL_OBJS)
|
71
contrib/games/hydracastlelabyrinth/README.md
Normal file
71
contrib/games/hydracastlelabyrinth/README.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Hydra Castle Labyrinth
|
||||
|
||||
![HCL build status](https://api.travis-ci.org/ptitSeb/hydracastlelabyrinth.png "HCL build status")
|
||||
|
||||
This version of Hydra Castle Labyrinth is based on the 3DS port (see below for original notice)
|
||||
|
||||
This version use SDL (either 1.2 or 2.0) and build on Linux, OpenPandora, PocketCHIP and ODROID.
|
||||
|
||||
You'll need SDL and SDL_mixer to build, either version 1.2 or 2.0.
|
||||
The SDL2 version use SDL Renderer and so is hardware accelerated.
|
||||
The SDL1.2 version use plain bitmap (no OpenGL or GLES needed).
|
||||
|
||||
On Debian and friend, to prepare and build, you can do (if you never build anything before, start with `sudo apt install build-essential git`):
|
||||
For SDL1.2
|
||||
```
|
||||
sudo apt install libsdl-dev libsdl-mixer1.2-dev cmake
|
||||
cd ~
|
||||
git clone https://github.com/ptitSeb/hydracastlelabyrinth.git
|
||||
cd hydracastlelabyrinth
|
||||
cmake .
|
||||
make
|
||||
```
|
||||
For SDL2.0
|
||||
```
|
||||
sudo apt install libsdl2-2.0-dev libsdl2-mixer2.0-dev cmake
|
||||
cd ~
|
||||
git clone https://github.com/ptitSeb/hydracastlelabyrinth.git
|
||||
cd hydracastlelabyrinth
|
||||
cmake . -DUSE_SDL2=ON
|
||||
make
|
||||
```
|
||||
|
||||
To hear music, you can optionnaly use timidity, but it will play OGG track by default.
|
||||
```
|
||||
sudo apt install timidity
|
||||
```
|
||||
And launch the game with
|
||||
```
|
||||
./hcl
|
||||
```
|
||||
To start windowed 640x480 game. You can have fullscreen with `./hcl -f` or `./hcl -d` to have fullscreen at current desktop resolution.
|
||||
|
||||
![sreenshot on Pandora](screenshot.png "screenshot on Pandora")
|
||||
|
||||
# Web Version
|
||||
|
||||
You can play an Emscripten version directly on your browser here: https://ptitseb.github.io/hydracastlelabyrinth/
|
||||
|
||||
# Original Notice
|
||||
|
||||
|
||||
|
||||
**This work has been done by an anon from /hbg/ on 4chan.org/vg/ and not me!**
|
||||
|
||||
|
||||
|
||||
|
||||
I've asked the original author about what license to use and he allowed me to use the GPLv2.
|
||||
Therefore consider each file to be licensed under the GPLv2, even if there is no disclaimer inside of each file.
|
||||
You will have gotten a copy of the license as part of the git and if not, get a copy from `https://www.gnu.org/licenses/gpl-2.0.html`.
|
||||
|
||||
Original author notes:
|
||||
Source code for the fan-made port of Hydra Castle Labyrinth for 3DS
|
||||
|
||||
Anything related to the PSP and Wii are unfinished.
|
||||
|
||||
(Yes, it does look like a 3rd grader programmed this.)
|
||||
|
||||
|
||||
The game's originally done by E.Hashimoto (a.k.a. Buster).
|
||||
You can download some of his works under this [link](http://hp.vector.co.jp/authors/VA025956/).
|
2
contrib/games/hydracastlelabyrinth/compile_flags.txt
Normal file
2
contrib/games/hydracastlelabyrinth/compile_flags.txt
Normal file
@ -0,0 +1,2 @@
|
||||
-D_SDL
|
||||
-D_KOLIBRI
|
BIN
contrib/games/hydracastlelabyrinth/icon.png
Normal file
BIN
contrib/games/hydracastlelabyrinth/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 450 B |
85
contrib/games/hydracastlelabyrinth/src/PHL.c
Normal file
85
contrib/games/hydracastlelabyrinth/src/PHL.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include "PHL.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "qda.h"
|
||||
#include "game.h"
|
||||
|
||||
int WHITE, RED, YELLOW;
|
||||
|
||||
void PHL_Init()
|
||||
{
|
||||
PHL_GraphicsInit();
|
||||
PHL_AudioInit(); // DBG
|
||||
|
||||
#ifdef _3DS
|
||||
Result rc = romfsInit();
|
||||
/*if (rc) {
|
||||
printf("romfsInit: %08lX\n", rc);
|
||||
//while(1){}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\nromfs Init Successful!\n");
|
||||
}*/
|
||||
#endif
|
||||
|
||||
WHITE = 0;
|
||||
RED = 1;
|
||||
YELLOW = 2;
|
||||
}
|
||||
|
||||
void PHL_Deinit()
|
||||
{
|
||||
PHL_AudioClose();
|
||||
PHL_GraphicsExit();
|
||||
|
||||
#ifdef _3DS
|
||||
romfsExit();
|
||||
#endif
|
||||
}
|
||||
|
||||
//Extracts bmps from the bmp.qda archive file
|
||||
PHL_Surface PHL_LoadQDA(char* fname)
|
||||
{
|
||||
PHL_Surface surf;
|
||||
|
||||
int numofsheets = 29;
|
||||
|
||||
for (int i = 0; i < numofsheets; i++)
|
||||
{
|
||||
if (strcmp(fname, (char*)headers[i].fileName) == 0) { //Match found
|
||||
//printf("\nMatch Found: %s", fname);
|
||||
surf = PHL_LoadBMP(i);
|
||||
i = numofsheets; //End search
|
||||
}
|
||||
}
|
||||
|
||||
return surf;
|
||||
}
|
||||
|
||||
void PHL_DrawTextBold(char* txt, int dx, int dy, int col)
|
||||
{
|
||||
int i, cx, cy;
|
||||
|
||||
for (i = 0; i < strlen(txt); i++)
|
||||
{
|
||||
cx = (txt[i] - 32) * 16;
|
||||
cy = 32 * col;
|
||||
|
||||
while (cx >= 512) {
|
||||
cx -= 512;
|
||||
cy += 16;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(dx + (16 * i), dy, cx, cy, 16, 16, images[imgBoldFont]);
|
||||
}
|
||||
}
|
||||
|
||||
void PHL_DrawTextBoldCentered(char* txt, int dx, int dy, int col)
|
||||
{
|
||||
if (dy < 640 && dy > -16) {
|
||||
int stringW = strlen(txt) * 16;
|
||||
|
||||
PHL_DrawTextBold(txt, dx - (stringW / 2), dy, col);
|
||||
}
|
||||
}
|
56
contrib/games/hydracastlelabyrinth/src/PHL.h
Normal file
56
contrib/games/hydracastlelabyrinth/src/PHL.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
PHL stands for Portable Homebrew Library
|
||||
*/
|
||||
#ifndef PHL_H
|
||||
#define PHL_H
|
||||
|
||||
#ifdef _3DS
|
||||
#include "3ds/system.h"
|
||||
#include "3ds/graphics.h"
|
||||
#include "3ds/input.h"
|
||||
#include "3ds/audio.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WII
|
||||
#include "wii/system.h"
|
||||
#include "wii/graphics.h"
|
||||
#include "wii/input.h"
|
||||
#include "wii/audio.h"
|
||||
#endif
|
||||
|
||||
#ifdef _PSP
|
||||
#include "psp/system.h"
|
||||
#include "psp/graphics.h"
|
||||
#include "psp/input.h"
|
||||
#include "psp/audio.h"
|
||||
#endif
|
||||
|
||||
#ifdef _SDL
|
||||
#ifdef _SDL2
|
||||
#include "sdl2/system.h"
|
||||
#include "sdl2/graphics.h"
|
||||
#include "sdl2/input.h"
|
||||
#include "sdl2/audio.h"
|
||||
#else
|
||||
#include "sdl/system.h"
|
||||
#include "sdl/graphics.h"
|
||||
#include "sdl/input.h"
|
||||
#include "sdl/audio.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
int x, y, w, h;
|
||||
} PHL_Rect;
|
||||
|
||||
void PHL_Init();
|
||||
void PHL_Deinit();
|
||||
|
||||
extern int WHITE, RED, YELLOW;
|
||||
|
||||
PHL_Surface PHL_LoadQDA(char* fname);
|
||||
void PHL_DrawTextBold(char* txt, int dx, int dy, int col);
|
||||
void PHL_DrawTextBoldCentered(char* txt, int dx, int dy, int col);
|
||||
|
||||
#endif
|
15
contrib/games/hydracastlelabyrinth/src/amigaos.h
Normal file
15
contrib/games/hydracastlelabyrinth/src/amigaos.h
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
inline void littleBigEndian (void *x, int sz) {
|
||||
unsigned char *toConvert = (unsigned char *)(x);
|
||||
unsigned char tmp;
|
||||
for (size_t i = 0; i < sz/2; ++i) {
|
||||
tmp = toConvert[i];
|
||||
toConvert[i] = toConvert[sz - i - 1];
|
||||
toConvert[sz - i - 1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
inline void BE16(uint16_t* w) {littleBigEndian(w, 2);}
|
||||
inline void BE32(uint32_t* i) {littleBigEndian(i, 4);}
|
336
contrib/games/hydracastlelabyrinth/src/collision.c
Normal file
336
contrib/games/hydracastlelabyrinth/src/collision.c
Normal file
@ -0,0 +1,336 @@
|
||||
#include "collision.h"
|
||||
#include "math.h"
|
||||
#include "game.h"
|
||||
#include "PHL.h"
|
||||
#include "object.h"
|
||||
|
||||
int checkMix(Mask r, Mask c);
|
||||
int checkRect(Mask r1, Mask r2);
|
||||
int checkCircle(Mask c1, Mask c2);
|
||||
|
||||
int checkCollision(Mask m1, Mask m2)
|
||||
{
|
||||
if (m1.unused != 1 && m2.unused != 1) {
|
||||
if (m1.circle == 0 && m2.circle == 0) {
|
||||
return checkRect(m1, m2);
|
||||
}else if (m1.circle == 1 && m2.circle == 1) {
|
||||
return checkCircle(m1, m2);
|
||||
}else if (m1.circle == 1 && m2.circle == 0) {
|
||||
return checkMix(m2, m1);
|
||||
}else if (m1.circle == 0 && m2.circle == 1) {
|
||||
return checkMix(m1, m2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkCollisionXY(Mask m, int x, int y)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (m.unused != 1) {
|
||||
if (m.circle == 1) {
|
||||
if (sqrt( pow(x - m.x, 2) + pow(y - m.y, 2) ) <= m.w) {
|
||||
result = 1;
|
||||
}
|
||||
}else{
|
||||
if (x < m.x || x > m.x + m.w || y < m.y || y > m.y + m.h) {
|
||||
}else{
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//Returns 1 or 0 depending on if there is a collision with a type of tile
|
||||
int checkTileCollision(int type, Mask m)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (m.x < 0) {
|
||||
m.x = 0;
|
||||
}else if (m.x + m.w > 640) {
|
||||
m.x = 640 - m.w;
|
||||
}
|
||||
|
||||
if (m.y < 0) {
|
||||
m.y = 0;
|
||||
}else if (m.y + m.h > 480) {
|
||||
m.y = 480 - m.h;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
int tileX = (int)m.x / 40;
|
||||
int tileY = (int)m.y / 40;
|
||||
|
||||
if (i == 1) {
|
||||
tileX = (int)((m.x + m.w - 1) / 40);
|
||||
}else if (i == 2) {
|
||||
tileY = (int)((m.y + m.h - 1) / 40);
|
||||
}else if (i == 3) {
|
||||
tileX = (int)((m.x + m.w - 1) / 40);
|
||||
tileY = (int)((m.y + m.h - 1) / 40);
|
||||
}
|
||||
|
||||
if (collisionTiles[tileX][tileY] == type) {
|
||||
result = 1;
|
||||
i = 4;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//Returns a tile's demension. Overkill for a lot of situations.
|
||||
PHL_Rect getTileCollision(int type, Mask m)
|
||||
{
|
||||
PHL_Rect result;
|
||||
result.x = -1;
|
||||
result.y = -1;
|
||||
result.w = 40;
|
||||
result.h = 40;
|
||||
|
||||
//updateMask();
|
||||
|
||||
if (m.x < 0) {
|
||||
m.x = 0;
|
||||
}else if (m.x + m.w > 640) {
|
||||
m.x = 640 - m.w;
|
||||
}
|
||||
|
||||
if (m.y < 0) {
|
||||
m.y = 0;
|
||||
}else if (m.y + m.h > 480) {
|
||||
m.y = 480 - m.h;
|
||||
}
|
||||
|
||||
//PHL_DrawRect(mask.x, mask.y, mask.w, mask.h, PHL_NewRGB(0x00, 0x00, 0xFF));
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
int tileX = (int)m.x / 40;
|
||||
int tileY = (int)m.y / 40;
|
||||
|
||||
if (i == 1) {
|
||||
tileX = (int)((m.x + m.w - 1) / 40);
|
||||
}else if (i == 2) {
|
||||
tileY = (int)((m.y + m.h - 1) / 40);
|
||||
}else if (i == 3) {
|
||||
tileX = (int)((m.x + m.w - 1) / 40);
|
||||
tileY = (int)((m.y + m.h - 1) / 40);
|
||||
}
|
||||
|
||||
if (collisionTiles[tileX][tileY] == type) {
|
||||
result.x = tileX * 40;
|
||||
result.y = tileY * 40;
|
||||
i = 4;
|
||||
//PHL_DrawRect(result.x, result.y, 40, 40, PHL_NewRGB(0xFF, 0x00, 0x00));
|
||||
}
|
||||
//PHL_DrawRect(tileX * 40, tileY * 40, 40, 40, PHL_NewRGB(0x00, 0xFF, 0x00));
|
||||
}
|
||||
|
||||
//updateMask();
|
||||
return result;
|
||||
}
|
||||
|
||||
int checkTileCollisionXY(int type, int x, int y)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}else if (x > 640) {
|
||||
x = 640;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}else if (y > 480) {
|
||||
y = 480;
|
||||
}
|
||||
|
||||
int tileX = (int)x / 40;
|
||||
int tileY = (int)y / 40;
|
||||
|
||||
if (collisionTiles[tileX][tileY] == type) {
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PHL_Rect getTileCollisionXY(int type, int x, int y)
|
||||
{
|
||||
PHL_Rect result;
|
||||
result.x = -1;
|
||||
result.y = -1;
|
||||
result.w = 40;
|
||||
result.h = 40;
|
||||
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}else if (x > 640) {
|
||||
x = 640;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}else if (y > 480) {
|
||||
y = 480;
|
||||
}
|
||||
|
||||
int tileX = (int)x / 40;
|
||||
int tileY = (int)y / 40;
|
||||
|
||||
if (collisionTiles[tileX][tileY] == type) {
|
||||
result.x = tileX * 40;
|
||||
result.y = tileY * 40;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PHL_DrawMask(Mask m)
|
||||
{
|
||||
if (m.circle == 0) {
|
||||
PHL_DrawRect(m.x, m.y, m.w, m.h, PHL_NewRGB(255, 255, 255));
|
||||
}else if (m.circle == 1) {
|
||||
PHL_DrawRect(m.x - m.w, m.y - m.w, m.w * 2, m.w * 2, PHL_NewRGB(255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
int checkMix(Mask r, Mask c)
|
||||
{
|
||||
int insidex = 0, insidey = 0;
|
||||
|
||||
if (c.x >= r.x && c.x <= r.x + r.w) {
|
||||
insidex = 1;
|
||||
}
|
||||
if (c.y >= r.y && c.y <= r.y + r.h) {
|
||||
insidey = 1;
|
||||
}
|
||||
|
||||
//Check if circle center is inside rectangle
|
||||
if (insidex == 1 && insidey == 1) {
|
||||
}
|
||||
else if (insidex == 1) {
|
||||
if ((c.y < r.y && r.y - c.y <= c.w) ||
|
||||
(c.y > (r.y + r.h) && c.y - (r.y + r.h) <= c.w)) {
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}else if (insidey == 1) {
|
||||
if ((c.x < r.x && r.x - c.x <= c.w) ||
|
||||
(c.x > (r.x + r.w) && c.x - (r.x + r.w) <= c.w)) {
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}else{
|
||||
//Check points
|
||||
if (sqrt( pow(r.x - c.x, 2) + pow(r.y - c.y, 2) ) <= c.w) {
|
||||
}else if (sqrt( pow(r.x + r.w - c.x, 2) + pow(r.y - c.y, 2) ) <= c.w) {
|
||||
}else if (sqrt( pow(r.x - c.x, 2) + pow(r.y + r.h - c.y, 2) ) <= c.w) {
|
||||
}else if (sqrt( pow(r.x + r.w - c.x, 2) + pow( r.y + r.h - c.y, 2) ) <= c.w) {
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int checkRect(Mask r1, Mask r2)
|
||||
{
|
||||
if (r1.x > r2.x + r2.w ||
|
||||
r1.x + r1.w < r2.x ||
|
||||
r1.y > r2.y + r2.h ||
|
||||
r1.y + r1.h < r2.y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int checkCircle(Mask c1, Mask c2)
|
||||
{
|
||||
int maxdis = c1.w + c2.w;
|
||||
int dis = sqrt(pow(c2.x - c1.x, 2) + pow(c2.y - c1.y, 2));
|
||||
|
||||
if (dis <= maxdis) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Heavier tile collision that omits destroyable blocks
|
||||
PHL_Rect getTileCollisionWeapon(int type, Mask m)
|
||||
{
|
||||
PHL_Rect result;
|
||||
result.x = -1;
|
||||
result.y = -1;
|
||||
result.w = 40;
|
||||
result.h = 40;
|
||||
|
||||
//updateMask();
|
||||
|
||||
if (m.x < 0) {
|
||||
m.x = 0;
|
||||
}else if (m.x + m.w > 640) {
|
||||
m.x = 640 - m.w;
|
||||
}
|
||||
|
||||
if (m.y < 0) {
|
||||
m.y = 0;
|
||||
}else if (m.y + m.h > 480) {
|
||||
m.y = 480 - m.h;
|
||||
}
|
||||
|
||||
//PHL_DrawRect(mask.x, mask.y, mask.w, mask.h, PHL_NewRGB(0x00, 0x00, 0xFF));
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
int tileX = (int)m.x / 40;
|
||||
int tileY = (int)m.y / 40;
|
||||
|
||||
if (i == 1) {
|
||||
tileX = (int)((m.x + m.w - 1) / 40);
|
||||
}else if (i == 2) {
|
||||
tileY = (int)((m.y + m.h - 1) / 40);
|
||||
}else if (i == 3) {
|
||||
tileX = (int)((m.x + m.w - 1) / 40);
|
||||
tileY = (int)((m.y + m.h - 1) / 40);
|
||||
}
|
||||
|
||||
if (collisionTiles[tileX][tileY] == type) {
|
||||
result.x = tileX * 40;
|
||||
result.y = tileY * 40;
|
||||
|
||||
//Check if destroyable block
|
||||
int a;
|
||||
for (a = 0; a < MAX_OBJECTS; a++) {
|
||||
if (objects[a] != NULL) {
|
||||
if (objects[a]->type == 3) {
|
||||
Destroyable* d = objects[a]->data;
|
||||
if (result.x == d->x && result.y == d->y) {
|
||||
result.x = -1;
|
||||
result.y = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.x != -1) {
|
||||
i = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//updateMask();
|
||||
return result;
|
||||
}
|
27
contrib/games/hydracastlelabyrinth/src/collision.h
Normal file
27
contrib/games/hydracastlelabyrinth/src/collision.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef COLLISION_H
|
||||
#define COLLISION_H
|
||||
|
||||
#include "PHL.h"
|
||||
|
||||
typedef struct {
|
||||
int circle; //1 if circle, 0 is rectangle
|
||||
int x, y;
|
||||
int w, h; //width is the radius if it's a circle
|
||||
int unused;
|
||||
} Mask;
|
||||
|
||||
void PHL_DrawMask(Mask m);
|
||||
|
||||
int checkCollision(Mask m1, Mask m2);
|
||||
|
||||
int checkTileCollision(int type, Mask m);
|
||||
PHL_Rect getTileCollision(int type, Mask m);
|
||||
|
||||
int checkCollisionXY(Mask m, int x, int y);
|
||||
|
||||
int checkTileCollisionXY(int type, int x, int y);
|
||||
PHL_Rect getTileCollisionXY(int type, int x, int y);
|
||||
|
||||
PHL_Rect getTileCollisionWeapon(int type, Mask m);
|
||||
|
||||
#endif
|
384
contrib/games/hydracastlelabyrinth/src/effect.c
Normal file
384
contrib/games/hydracastlelabyrinth/src/effect.c
Normal file
@ -0,0 +1,384 @@
|
||||
#include "effect.h"
|
||||
#include "game.h"
|
||||
#include "PHL.h"
|
||||
#include "hero.h"
|
||||
#include "collision.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void createEffect(int type, int x, int y)
|
||||
{
|
||||
createEffectExtra(type, x, y, 0, 0, 0);
|
||||
}
|
||||
|
||||
void createEffectExtra(int t, int x, int y, double hsp, double vsp, int val)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_EFFECTS; i++) {
|
||||
if (effects[i] == NULL) {
|
||||
Effect* e = malloc(sizeof *e);
|
||||
|
||||
e->id = i;
|
||||
e->type = t;
|
||||
|
||||
e->x = x;
|
||||
e->y = y;
|
||||
|
||||
e->vsp = vsp;
|
||||
e->hsp = hsp;
|
||||
e->grav = 0;
|
||||
|
||||
e->imageIndex = 0;
|
||||
e->imageSpeed = 0;
|
||||
|
||||
e->cropx = 0;
|
||||
e->cropy = 0;
|
||||
|
||||
e->width = 40;
|
||||
e->height = 40;
|
||||
|
||||
e->image = imgMisc20;
|
||||
e->timer = 60;
|
||||
|
||||
|
||||
e->visible = 1;
|
||||
e->val1 = 0;
|
||||
|
||||
e->loop = 0;
|
||||
e->frames = 0;
|
||||
|
||||
e->depth = 1;
|
||||
|
||||
//Sword collision
|
||||
if (e->type == 1) {
|
||||
e->cropx = 440;
|
||||
e->cropy = 40;
|
||||
e->imageSpeed = 0.25;
|
||||
e->timer = 19;
|
||||
}
|
||||
|
||||
//Enemy poof
|
||||
else if (e->type == 2) {
|
||||
PHL_PlaySound(sounds[sndBom01], CHN_EFFECTS);
|
||||
e->width = 64;
|
||||
e->height = 64;
|
||||
e->imageSpeed = 0.33;
|
||||
e->timer = 30;
|
||||
e->image = imgMisc32;
|
||||
}
|
||||
|
||||
//Dust after landing from a fall - left/right
|
||||
else if (e->type == 3) {
|
||||
e->cropx = 320;
|
||||
e->cropy = 80;
|
||||
e->hsp = -1;
|
||||
if (hsp > 0) {
|
||||
e->hsp = 1;
|
||||
e->cropx = 0;
|
||||
}
|
||||
e->imageSpeed = 0.33;
|
||||
e->timer = 8 * (1 / e->imageSpeed);
|
||||
}
|
||||
|
||||
//Block destroy/debris
|
||||
else if (e->type == 4) {
|
||||
e->grav = 0.2;
|
||||
e->loop = 1;
|
||||
e->frames = 4;
|
||||
e->timer = 60;
|
||||
|
||||
//Set flash offset
|
||||
if ((e->hsp > 0 && val == 0) || (e->hsp > 0 && val == 1)) {
|
||||
e->timer -= 1;
|
||||
}
|
||||
|
||||
e->imageSpeed = 0.34;
|
||||
|
||||
int size = (rand() % 2) + 1;
|
||||
|
||||
e->cropx = 0;
|
||||
if (e->hsp < 0) {
|
||||
e->cropx = 160;
|
||||
}
|
||||
if (size == 1) { //Big
|
||||
e->cropy = 40;
|
||||
}else{ //Small
|
||||
e->cropy = 440;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Chest sparkle
|
||||
else if (e->type == 5) {
|
||||
/*e->x -= 20;
|
||||
e->y -= 20;
|
||||
e->x += -20 + (rand() % 40) + 1;
|
||||
e->y += -20 + (rand() % 40) + 1;
|
||||
*/
|
||||
e->x -= 20;
|
||||
e->y -= 20;
|
||||
e->cropx = 440;
|
||||
e->cropy = 120;
|
||||
e->imageSpeed = 0.3;
|
||||
e->timer = 16;
|
||||
e->depth = 0;
|
||||
}
|
||||
|
||||
//Charge orbs
|
||||
else if (e->type == 6) {
|
||||
e->x -= 20;
|
||||
e->y -= 20;
|
||||
e->cropx = 0;
|
||||
e->cropy = 200;
|
||||
|
||||
e->val1 = (rand() % 360) + 1;
|
||||
e->imageSpeed = 0.3;
|
||||
e->timer = 20;
|
||||
e->depth = 0;
|
||||
}
|
||||
|
||||
//Poison bubble
|
||||
else if (e->type == 7) {
|
||||
PHL_PlaySound(sounds[sndPi02], CHN_EFFECTS);
|
||||
e->x -= 30;
|
||||
e->x += (rand() % 20) + 1;
|
||||
e->cropx = 280;
|
||||
e->cropy = 120;
|
||||
e->timer = 35;
|
||||
|
||||
e->vsp = -2;
|
||||
e->imageIndex = 0;
|
||||
e->imageSpeed = 0.16;
|
||||
e->depth = 0;
|
||||
}
|
||||
|
||||
//Stone break free
|
||||
else if (e->type == 8) {
|
||||
e->image = imgMisc32;
|
||||
e->cropy = 64;
|
||||
e->width = 64;
|
||||
e->height = 64;
|
||||
|
||||
e->imageSpeed = 0.32;
|
||||
e->timer = 18;
|
||||
}
|
||||
|
||||
//Tiny stone debris
|
||||
else if (e->type == 9) {
|
||||
e->x -= 20;
|
||||
e->y -= 20;
|
||||
e->image = imgMisc20;
|
||||
e->cropy = 40;
|
||||
e->cropx = 320 + ((rand() % 3) * 40);
|
||||
e->imageSpeed = 0;
|
||||
|
||||
e->vsp = -2 - (0.25 * (rand() % 8));
|
||||
e->hsp = -1 + (0.25 * (rand() % 8));
|
||||
e->grav = 0.1;
|
||||
|
||||
e->timer = 60;
|
||||
e->depth = 0;
|
||||
}
|
||||
|
||||
//Lava top animation
|
||||
else if (e->type == 10) {
|
||||
e->cropy = 40;
|
||||
e->cropx = 80;
|
||||
|
||||
e->imageSpeed = 0.125;
|
||||
e->depth = -1;
|
||||
e->loop = 1;
|
||||
e->frames = 3;
|
||||
e->timer = 100;
|
||||
|
||||
e->image = imgTiles;
|
||||
}
|
||||
|
||||
//Water top animation
|
||||
else if (e->type == 11) {
|
||||
e->cropy = 40;
|
||||
e->cropx = 240;
|
||||
|
||||
e->imageSpeed = 0.125;
|
||||
e->depth = -1;
|
||||
e->loop = 1;
|
||||
e->frames = 4;
|
||||
e->timer = 100;
|
||||
|
||||
e->image = imgTiles;
|
||||
}
|
||||
|
||||
//Hero Air Bubble
|
||||
else if (e->type == 12) {
|
||||
e->x -= 20;
|
||||
e->val1 = e->x; //Start x
|
||||
e->y -= 20;
|
||||
e->cropx = 440;
|
||||
e->loop = 1;
|
||||
e->frames = 2;
|
||||
e->imageSpeed = 0.2;
|
||||
e->timer = 120;
|
||||
e->vsp = -0.5;
|
||||
e->depth = 0;
|
||||
}
|
||||
|
||||
//Water splash
|
||||
else if (e->type == 13) {
|
||||
e->cropx = 200;
|
||||
e->imageSpeed = 0.1;
|
||||
e->timer = 55;
|
||||
e->grav = 0.1;
|
||||
}
|
||||
|
||||
//Lava splash
|
||||
else if (e->type == 14) {
|
||||
e->cropx = 400;
|
||||
e->cropy = 200;
|
||||
e->imageSpeed = 0.1;
|
||||
e->timer = 55;
|
||||
e->grav = 0.1;
|
||||
}
|
||||
|
||||
effects[i] = e;
|
||||
i = MAX_EFFECTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void effectStep(Effect* e)
|
||||
{
|
||||
e->x += e->hsp;
|
||||
e->y += e->vsp;
|
||||
e->vsp += e->grav;
|
||||
e->imageIndex += e->imageSpeed;
|
||||
|
||||
if (e->loop == 1) {
|
||||
if (e->imageIndex >= e->frames) {
|
||||
e->imageIndex -= e->frames;
|
||||
}
|
||||
}
|
||||
|
||||
if (e->type == 12) { //Hero Air Bubble
|
||||
e->x = e->val1 + 5 * sin((e->timer * 5) * 3.14159 / 180);
|
||||
if (checkTileCollisionXY(4, e->x + 20, e->y + 20) == 0) {
|
||||
e->timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (e->type == 10 || e->type == 11) { //Lava top
|
||||
e->timer = 100;
|
||||
}
|
||||
|
||||
if (e->type == 4 || e->type == 9 || e->type == 12) { //Stone Rubble
|
||||
if (e->timer <= 30 && e->timer % 2 != 0) {
|
||||
e->visible = 0;
|
||||
}else{
|
||||
e->visible = 1;
|
||||
}
|
||||
}
|
||||
else if (e->type == 6) { //Charge orb
|
||||
if (e->timer % 2 == 0) {
|
||||
e->visible = 1;
|
||||
e->x = herox + ((e->timer * 3) * sin(e->val1 * 3.14159 / 180)) - 20;
|
||||
e->y = heroy + ((e->timer * 3) * cos(e->val1 * 3.14159 / 180));
|
||||
}else{
|
||||
e->visible = 0;
|
||||
}
|
||||
}
|
||||
|
||||
e->timer -= 1;
|
||||
if (e->timer <= 0) {
|
||||
effectDestroy(e->id);
|
||||
}
|
||||
}
|
||||
|
||||
void effectDraw(Effect* e)
|
||||
{
|
||||
//if (e->type != 4 || (e->timer > 30 || e->timer % 2 == 0)) {
|
||||
if (e->visible == 1) {
|
||||
if (e->type == 7) { //Poison Bubble
|
||||
int animation[6] = {0, 1, 2, 1, 0, 3};
|
||||
PHL_DrawSurfacePart(e->x, e->y, e->cropx + (e->width * (animation[(int)e->imageIndex])), e->cropy, e->width, e->height, images[e->image]);
|
||||
}else{
|
||||
PHL_DrawSurfacePart(e->x, e->y, e->cropx + (e->width * ((int)e->imageIndex)), e->cropy, e->width, e->height, images[e->image]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void effectDestroy(int id)
|
||||
{
|
||||
if (effects[id] != NULL) {
|
||||
free(effects[id]);
|
||||
}
|
||||
effects[id] = NULL;
|
||||
}
|
||||
|
||||
void createRockSmash(int x, int y)
|
||||
{
|
||||
x -= 20;
|
||||
|
||||
int randvsp = (rand() % 3) + 1;
|
||||
createEffectExtra(4, x, y, -1.5, -2 - randvsp, 0);
|
||||
|
||||
randvsp = (rand() % 3) + 1;
|
||||
createEffectExtra(4, x, y, -1, -5 - randvsp, 1);
|
||||
|
||||
randvsp = (rand() % 3) + 1;
|
||||
createEffectExtra(4, x, y, 1.5, -2 - randvsp, 0);
|
||||
|
||||
randvsp = (rand() % 3) + 1;
|
||||
createEffectExtra(4, x, y, 1, -5 - randvsp, 1);
|
||||
PHL_PlaySound(sounds[sndBom02], 2);
|
||||
}
|
||||
|
||||
void createSplash(int x, int y)
|
||||
{
|
||||
double chsp = 0,
|
||||
cvsp = 0;
|
||||
|
||||
x -= 20;
|
||||
|
||||
chsp = -0.25 - ((rand() % 9) * 0.25);
|
||||
cvsp = -1.5 - ((rand() % 9) * 0.25);
|
||||
createEffectExtra(13, x, y, chsp, cvsp, 0);
|
||||
|
||||
chsp = 0.25 + ((rand() % 9) * 0.25);
|
||||
cvsp = -1.5 - ((rand() % 9) * 0.25);
|
||||
createEffectExtra(13, x, y, chsp, cvsp, 0);
|
||||
|
||||
chsp = -0.25 - ((rand() % 9) * 0.25);
|
||||
cvsp = -0.5 - ((rand() % 4) * 0.25);
|
||||
createEffectExtra(13, x, y, chsp, cvsp, 0);
|
||||
|
||||
chsp = 0.25 + ((rand() % 9) * 0.25);
|
||||
cvsp = -0.5 - ((rand() % 4) * 0.25);
|
||||
createEffectExtra(13, x, y, chsp, cvsp, 0);
|
||||
|
||||
PHL_PlaySound(sounds[sndWater01], CHN_EFFECTS);
|
||||
}
|
||||
|
||||
void createLavaSplash(int x, int y)
|
||||
{
|
||||
double chsp = 0,
|
||||
cvsp = 0;
|
||||
|
||||
x -= 20;
|
||||
|
||||
chsp = -0.25 - ((rand() % 9) * 0.25);
|
||||
cvsp = -1.5 - ((rand() % 9) * 0.25);
|
||||
createEffectExtra(14, x, y, chsp, cvsp, 0);
|
||||
|
||||
chsp = 0.25 + ((rand() % 9) * 0.25);
|
||||
cvsp = -1.5 - ((rand() % 9) * 0.25);
|
||||
createEffectExtra(14, x, y, chsp, cvsp, 0);
|
||||
|
||||
chsp = -0.25 - ((rand() % 9) * 0.25);
|
||||
cvsp = -0.5 - ((rand() % 4) * 0.25);
|
||||
createEffectExtra(14, x, y, chsp, cvsp, 0);
|
||||
|
||||
chsp = 0.25 + ((rand() % 9) * 0.25);
|
||||
cvsp = -0.5 - ((rand() % 4) * 0.25);
|
||||
createEffectExtra(14, x, y, chsp, cvsp, 0);
|
||||
|
||||
PHL_PlaySound(sounds[sndShot07], CHN_EFFECTS);
|
||||
}
|
31
contrib/games/hydracastlelabyrinth/src/effect.h
Normal file
31
contrib/games/hydracastlelabyrinth/src/effect.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef EFFECTS_H
|
||||
#define EFFECTS_H
|
||||
|
||||
typedef struct {
|
||||
int id, type;
|
||||
double x, y,
|
||||
vsp, hsp, grav,
|
||||
imageIndex, imageSpeed;
|
||||
|
||||
int cropx, cropy;
|
||||
int width, height;
|
||||
int image, timer;
|
||||
|
||||
int visible;
|
||||
int val1;
|
||||
int loop, frames;
|
||||
int depth;
|
||||
} Effect;
|
||||
|
||||
void createEffect(int type, int x, int y);
|
||||
void createEffectExtra(int t, int x, int y, double hsp, double vsp, int val);
|
||||
|
||||
void effectStep(Effect* e);
|
||||
void effectDraw(Effect* e);
|
||||
void effectDestroy(int id);
|
||||
|
||||
void createRockSmash(int x, int y);
|
||||
void createSplash(int x, int y);
|
||||
void createLavaSplash(int x, int y);
|
||||
|
||||
#endif
|
172
contrib/games/hydracastlelabyrinth/src/enemies/bat.c
Normal file
172
contrib/games/hydracastlelabyrinth/src/enemies/bat.c
Normal file
@ -0,0 +1,172 @@
|
||||
#include "bat.h"
|
||||
#include "../game.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void batStep(Bat* b);
|
||||
void batDraw(Bat* b);
|
||||
|
||||
void createBat(int x, int y, int type)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* result = /*(Enemy*)*/malloc(sizeof *result);
|
||||
Bat* b = /*(Bat*)*/malloc(sizeof *b);
|
||||
b->id = i;
|
||||
|
||||
b->x = b->xstart = x;
|
||||
b->y = b->ystart = y;
|
||||
b->type = type;
|
||||
|
||||
b->imageIndex = 5;
|
||||
b->counter = 0;
|
||||
b->timer = 0;
|
||||
b->state = 0;
|
||||
b->dir = 1;
|
||||
|
||||
result->data = b;
|
||||
result->enemyStep = batStep;
|
||||
result->enemyDraw = batDraw;
|
||||
result->type = 1;
|
||||
|
||||
enemies[i] = result;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void batStep(Bat* b)
|
||||
{
|
||||
//Wait
|
||||
if (b->state == 0)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
b->imageIndex = 5;
|
||||
}
|
||||
|
||||
//wait for hero to get near
|
||||
{
|
||||
if (b->timer <= 0) {
|
||||
Mask area;
|
||||
area.circle = 0;
|
||||
area.unused = 0;
|
||||
area.x = b->xstart - 60;
|
||||
area.y = b->ystart;
|
||||
area.w = 160; area.h = 100;
|
||||
|
||||
if (checkCollisionXY(area, herox, heroy + 20)) {
|
||||
PHL_PlaySound(sounds[sndPi07], CHN_ENEMIES);
|
||||
b->state = 1;
|
||||
b->timer = 270;
|
||||
if (b->type == 1) {
|
||||
b->counter = 1;
|
||||
if (herox < b->x + 20) {
|
||||
b->dir = -1;
|
||||
}else{
|
||||
b->dir = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
b->timer -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Fly
|
||||
else if (b->state == 1)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
b->imageIndex += 0.25;
|
||||
if (b->imageIndex >= 5) {
|
||||
b->imageIndex -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
//Rotation angle
|
||||
{
|
||||
b->timer += 4;
|
||||
if (b->timer >= 360) {
|
||||
b->timer -= 360;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
b->y = b->ystart + 30 + (30 * sin(b->timer * 3.14159 / 180));
|
||||
//Red bat
|
||||
if (b->type == 1) {
|
||||
b->x += 2 * b->dir;
|
||||
}
|
||||
}
|
||||
|
||||
//Return to perch
|
||||
{
|
||||
if (b->timer == 270) {
|
||||
if (b->type == 1 && b->counter > 0) {
|
||||
b->dir *= -1;
|
||||
b->timer = 270;
|
||||
b->counter -= 1;
|
||||
}else{
|
||||
b->state = 0;
|
||||
b->timer = 70;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 32;
|
||||
mask.h = 28;
|
||||
mask.x = b->x + ((40 - mask.w) / 2);
|
||||
mask.y = b->y;
|
||||
}
|
||||
|
||||
//Hit Player
|
||||
{
|
||||
if (checkCollision(mask, heroMask)) {
|
||||
heroHit(10, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
//Death
|
||||
createEffect(2, b->x - 12, b->y - 6);
|
||||
spawnCollectable(b->x + 20, b->y);
|
||||
enemyDestroy(b->id);
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void batDraw(Bat* b)
|
||||
{
|
||||
int cropX = 0,
|
||||
cropY = 120;
|
||||
|
||||
if (b->type == 1) {
|
||||
cropX = 400;
|
||||
cropY = 280;
|
||||
}
|
||||
|
||||
cropX += (int)b->imageIndex * 40;
|
||||
|
||||
PHL_DrawSurfacePart(b->x, b->y - 4, cropX, cropY, 40, 40, images[imgEnemies]);
|
||||
}
|
16
contrib/games/hydracastlelabyrinth/src/enemies/bat.h
Normal file
16
contrib/games/hydracastlelabyrinth/src/enemies/bat.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef BAT_H
|
||||
#define BAT_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
int xstart, ystart;
|
||||
int type; //0 = gray | 1 = red
|
||||
int dir;
|
||||
double imageIndex;
|
||||
int counter, timer, state;
|
||||
} Bat;
|
||||
|
||||
void createBat(int x, int y, int type);
|
||||
|
||||
#endif
|
319
contrib/games/hydracastlelabyrinth/src/enemies/batboss.c
Normal file
319
contrib/games/hydracastlelabyrinth/src/enemies/batboss.c
Normal file
@ -0,0 +1,319 @@
|
||||
#include "batboss.h"
|
||||
#include "../game.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include "heads.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
int boss2flag = 5;
|
||||
|
||||
//void updateBatMask(Batboss* b);
|
||||
void batbossStep(Batboss* b);
|
||||
void batbossDraw(Batboss* b);
|
||||
|
||||
void createBatboss(int x, int y)
|
||||
{
|
||||
if (flags[boss2flag] == 0) { //have not beaten boss 2
|
||||
PHL_FreeSurface(images[imgBoss]);
|
||||
images[imgBoss] = PHL_LoadQDA("boss03.bmp");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
setBossRoom();
|
||||
|
||||
Enemy* e = /*(Enemy*)*/malloc(sizeof *e);
|
||||
Batboss* b = /*(Batboss*)*/malloc(sizeof *b);
|
||||
b->id = i;
|
||||
|
||||
b->x = x;
|
||||
b->y = y;
|
||||
|
||||
b->vsp = 0;
|
||||
b->hsp = 0;
|
||||
b->grav = 0.1;
|
||||
|
||||
b->imageIndex = 0;
|
||||
|
||||
b->ypos = y;
|
||||
b->rot = 0;
|
||||
|
||||
b->hp = 35;
|
||||
|
||||
b->invincible = 0;
|
||||
b->state = 0;
|
||||
b->timer = 0;
|
||||
b->mode = 0; //0 for flame, 1 for tornado stomp
|
||||
|
||||
/*
|
||||
b->mask.unused = b->mask.circle = 0;
|
||||
b->mask.w = 100;
|
||||
b->mask.h = 68;
|
||||
updateBatMask(b);
|
||||
*/
|
||||
//Setup phase
|
||||
b->state = 0;
|
||||
b->hsp = 2;
|
||||
b->ypos = b->y - 24;
|
||||
b->timer = 60;
|
||||
|
||||
e->data = b;
|
||||
e->enemyStep = batbossStep;
|
||||
e->enemyDraw = batbossDraw;
|
||||
e->type = 41;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void batbossStep(Batboss* b)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Animate
|
||||
{
|
||||
//Wing flap
|
||||
if (b->state == 0 || b->state == 1 || b->state == 2 || b->state == 5 || b->state == 6) {
|
||||
b->imageIndex += 0.1;
|
||||
if (b->imageIndex >= 2) {
|
||||
b->imageIndex -= 2;
|
||||
}
|
||||
}
|
||||
//Twister
|
||||
if (b->state == 3 || b->state == 4) {
|
||||
b->imageIndex += 0.2;
|
||||
if (b->imageIndex >= 5) {
|
||||
b->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Counters
|
||||
{
|
||||
if (b->timer > 0) {
|
||||
b->timer -= 1;
|
||||
}
|
||||
|
||||
if (b->invincible > 0) {
|
||||
b->invincible -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Large vertical movement
|
||||
{
|
||||
if (b->state == 0 || b->state == 1) {
|
||||
b->rot += 2;
|
||||
if (b->rot >= 360) { b->rot -= 360; }
|
||||
|
||||
b->y = b->ypos - (40 * sin(b->rot * 3.14159 / 180));
|
||||
}
|
||||
}
|
||||
|
||||
//Small vertical movement
|
||||
{
|
||||
if (b->state == 2) {
|
||||
b->rot += 2;
|
||||
if (b->rot >= 360) { b->rot -= 360; }
|
||||
|
||||
b->y = b->ypos - (20 * sin(b->rot * 3.14159 / 180));
|
||||
}
|
||||
}
|
||||
|
||||
//Horizontal movement
|
||||
if (b->state == 0) {
|
||||
b->x += b->hsp;
|
||||
|
||||
if (b->x >= 520 || b->x <= 120) { //Hit walls
|
||||
b->hsp *= -1;
|
||||
}
|
||||
|
||||
if (b->timer <= 0) {
|
||||
b->state = 1;
|
||||
}
|
||||
}
|
||||
//Slow to halt
|
||||
else if (b->state == 1) {
|
||||
b->x += b->hsp;
|
||||
|
||||
if (b->x >= 520 || b->x <= 120) { //Hit walls
|
||||
b->hsp *= -1;
|
||||
}
|
||||
|
||||
double rate = 0.03;
|
||||
if (b->hsp > 0) {
|
||||
b->hsp -= rate;
|
||||
if (b->hsp <= 0) { b->hsp = 0; }
|
||||
}
|
||||
else if (b->hsp < 0) {
|
||||
b->hsp += rate;
|
||||
if (b->hsp >= 0) { b->hsp = 0; }
|
||||
}
|
||||
|
||||
if (b->hsp == 0 && b->rot <= 2) {
|
||||
b->state = 2;
|
||||
b->timer = 60;
|
||||
}
|
||||
}
|
||||
else if (b->state == 2) {
|
||||
if (b->timer == 1) {
|
||||
//Shoot flame
|
||||
int fx = b->x;
|
||||
int fy = b->y + 24;
|
||||
int fangle = (atan2(heroy - fy, fx - (herox - 20)) * 180 / 3.14159) + 270;
|
||||
createFireball(fx, fy, fangle, b->id);
|
||||
createFireball(fx, fy, fangle - 15, b->id);
|
||||
createFireball(fx, fy, fangle + 15, b->id);
|
||||
PHL_PlaySound(sounds[sndShot03], CHN_ENEMIES);
|
||||
}
|
||||
|
||||
if (b->timer <= 0 && b->rot <= 2) {
|
||||
if (b->mode == 0) {
|
||||
b->state = 0;
|
||||
b->timer = 60;
|
||||
b->hsp = 2;
|
||||
b->mode = 1;
|
||||
}
|
||||
else{
|
||||
b->mode = 0;
|
||||
b->state = 3;
|
||||
b->imageIndex = 2;
|
||||
b->vsp = -4;
|
||||
PHL_PlaySound(sounds[sndShot06], CHN_ENEMIES);
|
||||
}
|
||||
|
||||
if (herox < b->x) {
|
||||
b->hsp *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Stomp
|
||||
else if (b->state == 3) {
|
||||
b->y += b->vsp;
|
||||
b->vsp += b->grav;
|
||||
if (b->vsp >= 6) { b->vsp = 6; }
|
||||
|
||||
//Hit floor
|
||||
if (b->y >= 480 - 176) {
|
||||
b->y = 480 - 176;
|
||||
b->state = 4;
|
||||
b->timer = 120;
|
||||
quakeTimer = 30;
|
||||
PHL_PlaySound(sounds[sndHit04], CHN_ENEMIES);
|
||||
b->hsp = 1;
|
||||
if (b->x > herox) {
|
||||
b->hsp *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Chase
|
||||
else if (b->state == 4) {
|
||||
b->x += b->hsp;
|
||||
|
||||
if (b->timer <= 0 || b->x >= 520 || b->x <= 120) {
|
||||
b->state = 5;
|
||||
b->timer = 80 + (rand() % 61);
|
||||
}
|
||||
}
|
||||
//Rise
|
||||
else if (b->state == 5) {
|
||||
b->y -= 1;
|
||||
|
||||
if (b->timer <= 0) {
|
||||
b->state = 0;
|
||||
b->ypos = b->y;
|
||||
b->rot = 0;
|
||||
b->timer = 60;
|
||||
|
||||
b->hsp = 2;
|
||||
if (b->x > herox) {
|
||||
b->hsp *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Death
|
||||
else if (b->state == 6) {
|
||||
b->y += 0.2;
|
||||
|
||||
if (b->timer % 12 == 0) {
|
||||
createEffect(2, b->x - 64 + (rand() % 100), b->y + (rand() % 80));
|
||||
}
|
||||
|
||||
if (b->timer <= 0) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (b->state != 6) {
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = mask.circle = 0;
|
||||
if (b->state == 3 || b->state == 4) {
|
||||
mask.w = 64;
|
||||
mask.h = 96;
|
||||
mask.y = b->y;
|
||||
}else{
|
||||
mask.w = 100;
|
||||
mask.h = 68;
|
||||
mask.y = b->y + 18;
|
||||
}
|
||||
mask.x = b->x - (mask.w / 2);
|
||||
}
|
||||
|
||||
//Hit Player
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(30, b->x);
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
//Hit
|
||||
b->invincible = 15;
|
||||
b->hp -= 1;
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (b->hp <= 0) {
|
||||
b->state = 6;
|
||||
b->timer = 180;
|
||||
b->invincible = 200;
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy object
|
||||
{
|
||||
if (dead == 1) {
|
||||
enemyDestroy(b->id);
|
||||
bossDefeatedFlag = 1;
|
||||
roomSecret = 1;
|
||||
|
||||
flags[boss2flag] = 1;
|
||||
PHL_StopMusic();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void batbossDraw(Batboss* b)
|
||||
{
|
||||
if (b->invincible % 2 == 0) {
|
||||
PHL_DrawSurfacePart(b->x - 64, b->y, (int)b->imageIndex * 128, 0, 128, 96, images[imgBoss]);
|
||||
}
|
||||
}
|
18
contrib/games/hydracastlelabyrinth/src/enemies/batboss.h
Normal file
18
contrib/games/hydracastlelabyrinth/src/enemies/batboss.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef BATBOSS_H
|
||||
#define BATBOSS_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double hsp, vsp, grav;
|
||||
double imageIndex;
|
||||
double ypos;
|
||||
double rot;
|
||||
int hp;
|
||||
int state, timer, mode;
|
||||
int invincible;
|
||||
} Batboss;
|
||||
|
||||
void createBatboss(int x, int y);
|
||||
|
||||
#endif
|
214
contrib/games/hydracastlelabyrinth/src/enemies/bee.c
Normal file
214
contrib/games/hydracastlelabyrinth/src/enemies/bee.c
Normal file
@ -0,0 +1,214 @@
|
||||
#include "bee.h"
|
||||
#include "../enemy.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void beeStep(Bee* b);
|
||||
void beeDraw(Bee* b);
|
||||
|
||||
void createBee(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = /*(Enemy*)*/malloc(sizeof *e);
|
||||
Bee* b = /*(Bee*)*/malloc(sizeof *b);
|
||||
b->id = i;
|
||||
|
||||
b->x = x;
|
||||
b->y = y;
|
||||
b->xstart = b->x;
|
||||
b->ystart = b->y;
|
||||
|
||||
b->hsp = 0;
|
||||
b->vsp = 0;
|
||||
|
||||
b->timer = 0;
|
||||
b->imageIndex = 0;
|
||||
b->dir = 1;
|
||||
b->state = 0;
|
||||
|
||||
b->hoverdir = 180;
|
||||
|
||||
if (dir == 1) {
|
||||
b->hoverdir = 0;
|
||||
b->dir = -1;
|
||||
}
|
||||
|
||||
e->data = b;
|
||||
e->enemyStep = beeStep;
|
||||
e->enemyDraw = beeDraw;
|
||||
e->type = 24;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void beeStep(Bee* b)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
b->imageIndex += 0.33;
|
||||
if (b->imageIndex >= 3) {
|
||||
b->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
//Mindless hovering
|
||||
if (b->state == 0)
|
||||
{
|
||||
b->hoverdir += 2.6;
|
||||
if (b->hoverdir >= 360) {
|
||||
b->hoverdir -= 360;
|
||||
}
|
||||
|
||||
b->dir = 1;
|
||||
if (b->hoverdir <= 180) {
|
||||
b->dir = -1;
|
||||
}
|
||||
|
||||
b->x = b->xstart + (20 * cos(b->hoverdir * 3.14159 /180));
|
||||
|
||||
//If player is within range
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.x = b->x - 80;
|
||||
area.y = b->y;
|
||||
area.w = 200;
|
||||
area.h = 100;
|
||||
|
||||
if (checkCollision(area, getHeroMask())) {
|
||||
b->state = 1;
|
||||
|
||||
b->dir = 1;
|
||||
if (b->x + 20 > herox) {
|
||||
b->dir = -1;
|
||||
}
|
||||
|
||||
b->hsp = -5.5 * b->dir;
|
||||
|
||||
PHL_PlaySound(sounds[sndBee01], CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
//Fly backwards
|
||||
else if (b->state == 1)
|
||||
{
|
||||
b->hsp += 0.25 * b->dir;
|
||||
|
||||
if ((b->dir == 1 && b->hsp >= 0) || (b->dir == -1 && b->hsp <= 0)) {
|
||||
b->hsp = 0;
|
||||
b->state = 2;
|
||||
b->vsp = 3.75;
|
||||
}
|
||||
}
|
||||
//Fly downwards
|
||||
else if (b->state == 2)
|
||||
{
|
||||
b->vsp -= 0.1;
|
||||
if (b->vsp <= 0) {
|
||||
b->state = 3;
|
||||
b->vsp = 0;
|
||||
|
||||
b->dir = 1;
|
||||
if (b->x + 20 > herox) {
|
||||
b->dir = -1;
|
||||
}
|
||||
b->hsp = 3 * b->dir;
|
||||
}
|
||||
}
|
||||
//Fly diaganal
|
||||
else if (b->state == 3)
|
||||
{
|
||||
b->vsp -= 0.1;
|
||||
|
||||
if (b->vsp < -3) {
|
||||
b->vsp = -3;
|
||||
}
|
||||
|
||||
if (b->y <= b->ystart) {
|
||||
b->state = 4;
|
||||
|
||||
b->vsp = 0;
|
||||
b->y = b->ystart;
|
||||
|
||||
if (b->x < b->xstart) {
|
||||
b->dir = 1;
|
||||
}else{
|
||||
b->dir = -1;
|
||||
}
|
||||
b->hsp = b->dir;
|
||||
}
|
||||
}
|
||||
//Fly back to start
|
||||
else if (b->state == 4)
|
||||
{
|
||||
if ((b->dir == 1 && b->x >= b->xstart) || (b->dir == -1 && b->x <= b->xstart)) {
|
||||
b->state = 0;
|
||||
b->hsp = 0;
|
||||
|
||||
b->hoverdir = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
b->x += b->hsp;
|
||||
b->y += b->vsp;
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 24;
|
||||
mask.h = 32;
|
||||
mask.y = b->y + 6;
|
||||
mask.x = b->x + 14;
|
||||
if (b->dir == -1) {
|
||||
mask.x = b->x + 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Hit Player
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(15, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon Collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
createEffect(2, b->x - 12, b->y - 6);
|
||||
spawnCollectable(b->x + 20, b->y);
|
||||
enemyDestroy(b->id);
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void beeDraw(Bee* b)
|
||||
{
|
||||
int cropx = 280;
|
||||
|
||||
if (b->dir == -1) {
|
||||
cropx += 120;
|
||||
}
|
||||
|
||||
cropx += (int)b->imageIndex * 40;
|
||||
|
||||
PHL_DrawSurfacePart(b->x, b->y, cropx, 480, 40, 40, images[imgEnemies]);
|
||||
}
|
16
contrib/games/hydracastlelabyrinth/src/enemies/bee.h
Normal file
16
contrib/games/hydracastlelabyrinth/src/enemies/bee.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef BEE_H
|
||||
#define BEE_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
int xstart, ystart;
|
||||
double hsp, vsp;
|
||||
double imageIndex;
|
||||
int dir, state, timer;
|
||||
double hoverdir;
|
||||
} Bee;
|
||||
|
||||
void createBee(int x, int y, int dir);
|
||||
|
||||
#endif
|
221
contrib/games/hydracastlelabyrinth/src/enemies/boar.c
Normal file
221
contrib/games/hydracastlelabyrinth/src/enemies/boar.c
Normal file
@ -0,0 +1,221 @@
|
||||
#include "boar.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void boarStep(Boar* b);
|
||||
void boarDraw(Boar* b);
|
||||
|
||||
void createBoar(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = /*(Enemy*)*/malloc(sizeof *e);
|
||||
Boar* b = /*(Boar*)*/malloc(sizeof *b);
|
||||
|
||||
b->id = i;
|
||||
|
||||
b->hp = 3;
|
||||
|
||||
b->x = x;
|
||||
b->y = y;
|
||||
|
||||
b->hsp = 0;
|
||||
|
||||
b->imageIndex = 0;
|
||||
b->dir = 1;
|
||||
|
||||
b->blink = 0;
|
||||
|
||||
b->state = 0;
|
||||
b->timer = 0;
|
||||
|
||||
e->data = b;
|
||||
e->enemyStep = boarStep;
|
||||
e->enemyDraw = boarDraw;
|
||||
e->type = 26;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void boarStep(Boar* b)
|
||||
{
|
||||
//Setup mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.w = 32;
|
||||
mask.h = 28;
|
||||
mask.x = b->x + ((40 - mask.w) / 2);
|
||||
mask.y = b->y + 40 - mask.h;
|
||||
}
|
||||
|
||||
//Blink animation
|
||||
{
|
||||
if (b->blink > 0) {
|
||||
b->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Patterns
|
||||
{
|
||||
//Dance
|
||||
if (b->state == 0)
|
||||
{
|
||||
//Animate
|
||||
b->imageIndex += 0.15;
|
||||
if (b->imageIndex >= 8) {
|
||||
b->imageIndex -= 8;
|
||||
}
|
||||
|
||||
//if player gets near
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.x = b->x - 80;
|
||||
area.y = b->y - 40;
|
||||
area.w = 200;
|
||||
area.h = 80;
|
||||
|
||||
if (checkCollision(area, getHeroMask()) == 1) {
|
||||
b->state = 1;
|
||||
b->timer = -1;
|
||||
b->imageIndex = 0;
|
||||
b->dir = 1;
|
||||
if (herox < b->x + 20) {
|
||||
b->dir = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Rev up
|
||||
else if (b->state == 1)
|
||||
{
|
||||
b->timer += 1;
|
||||
|
||||
//Play sound
|
||||
if (b->timer % 10 == 0) {
|
||||
PHL_PlaySound(sounds[sndShot01], CHN_ENEMIES);
|
||||
}
|
||||
|
||||
//Create effect
|
||||
if (b->timer % 16 == 0) {
|
||||
if (b->dir == 1) {
|
||||
createEffectExtra(3, b->x + 20 - 30, b->y + 8, -1, 0, 0);
|
||||
}
|
||||
if (b->dir == -1) {
|
||||
createEffectExtra(3, b->x + 20 - 10, b->y + 8, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (b->timer >= 60) {
|
||||
b->state = 2;
|
||||
b->hsp = 3;
|
||||
}
|
||||
}
|
||||
//Running
|
||||
else if (b->state == 2)
|
||||
{
|
||||
b->x += b->hsp * b->dir;
|
||||
mask.x = b->x + ((40 - mask.w) / 2);
|
||||
|
||||
//Collide with wall
|
||||
if (checkTileCollision(1, mask) == 1) {
|
||||
b->x -= b->hsp * b->dir;
|
||||
b->dir *= -1;
|
||||
}
|
||||
|
||||
//On edge
|
||||
{
|
||||
mask.x = b->x + ((40 - mask.w) / 2);
|
||||
|
||||
mask.x += mask.w * b->dir;
|
||||
mask.y += 1;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
if (collide.x == -1) {
|
||||
b->dir *= -1;
|
||||
}
|
||||
|
||||
mask.y -= 1;
|
||||
mask.x = b->x + ((40 - mask.w) / 2);
|
||||
}
|
||||
|
||||
b->hsp -= 0.05;
|
||||
if (b->hsp <= 0) {
|
||||
b->state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Running animation
|
||||
if (b->state == 1 || b->state == 2) {
|
||||
//Animate
|
||||
b->imageIndex += 0.2;
|
||||
if (b->imageIndex >= 2) {
|
||||
b->imageIndex -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Collide with hero
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(30, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
b->hp -= 1;
|
||||
b->blink = 15;
|
||||
|
||||
//Death
|
||||
if (b->hp <= 0) {
|
||||
createEffect(2, b->x - 12, b->y - 12);
|
||||
spawnCollectable(b->x + 20, b->y);
|
||||
enemyDestroy(b->id);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void boarDraw(Boar* b)
|
||||
{
|
||||
if (b->blink % 2 == 0)
|
||||
{
|
||||
int cropx = 0, cropy = 360;
|
||||
int drawx = b->x, drawy = b->y;
|
||||
|
||||
//Dance
|
||||
if (b->state == 0) {
|
||||
int animation[8] = {0, 1, 2, 1, 0, 3, 4, 3};
|
||||
cropx = 160 + (animation[(int)b->imageIndex] * 40);
|
||||
}
|
||||
//Charge
|
||||
else{
|
||||
cropx = (int)b->imageIndex * 40;
|
||||
|
||||
if (b->dir == -1) {
|
||||
cropx += 80;
|
||||
}
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(drawx, drawy, cropx, cropy, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
18
contrib/games/hydracastlelabyrinth/src/enemies/boar.h
Normal file
18
contrib/games/hydracastlelabyrinth/src/enemies/boar.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef BOAR_H
|
||||
#define BOAR_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
double x, y;
|
||||
double hsp;
|
||||
double imageIndex;
|
||||
int blink;
|
||||
int dir;
|
||||
int state;
|
||||
int timer;
|
||||
} Boar;
|
||||
|
||||
void createBoar(int x, int y);
|
||||
|
||||
#endif
|
285
contrib/games/hydracastlelabyrinth/src/enemies/boomknight.c
Normal file
285
contrib/games/hydracastlelabyrinth/src/enemies/boomknight.c
Normal file
@ -0,0 +1,285 @@
|
||||
#include "boomknight.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void boomknightStep(Boomknight* b);
|
||||
void boomknightDraw(Boomknight* b);
|
||||
|
||||
void boomStep(Boom* b);
|
||||
void boomDraw(Boom* b);
|
||||
|
||||
void createBoomknight(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Boomknight* b = malloc(sizeof *b);
|
||||
b->id = i;
|
||||
|
||||
b->hp = 2;
|
||||
b->blink = 0;
|
||||
|
||||
b->x = x;
|
||||
b->y = y;
|
||||
|
||||
b->dir = 1;
|
||||
if (herox < b->x + 20) {
|
||||
b->dir = -1;
|
||||
}
|
||||
|
||||
b->imageIndex = 0;
|
||||
|
||||
b->state = 0;
|
||||
b->timer = 0;
|
||||
|
||||
e->data = b;
|
||||
e->enemyStep = boomknightStep;
|
||||
e->enemyDraw = boomknightDraw;
|
||||
e->type = 31;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void boomknightStep(Boomknight* b)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
b->imageIndex += 0.1;
|
||||
if (b->imageIndex >= 2) {
|
||||
b->imageIndex -= 2;
|
||||
}
|
||||
|
||||
if (b->blink > 0) {
|
||||
b->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 30;
|
||||
mask.h = 32;
|
||||
mask.x = b->x + ((40 - mask.w) / 2);
|
||||
mask.y = b->y + (40 - mask.h);
|
||||
}
|
||||
|
||||
//Walk
|
||||
if (b->state == 0) {
|
||||
//Movement
|
||||
{
|
||||
double hsp = 0.5;
|
||||
b->x += hsp * b->dir;
|
||||
mask.x = b->x + ((40 - mask.w) / 2);
|
||||
}
|
||||
|
||||
//Hit wall
|
||||
{
|
||||
if (checkTileCollision(1, mask) == 1) {
|
||||
b->dir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
//On edge
|
||||
{
|
||||
mask.x += mask.w * b->dir;
|
||||
mask.y += 20;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
if (collide.x == -1) {
|
||||
b->dir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
//Player is close
|
||||
{
|
||||
if (b->timer <= 0) {
|
||||
Mask area;
|
||||
{
|
||||
area.circle = area.unused = 0;
|
||||
area.w = 120;
|
||||
area.h = 40;
|
||||
area.x = b->x + 20;
|
||||
if (b->dir == -1) {
|
||||
area.x -= area.w;
|
||||
}
|
||||
area.y = b->y;
|
||||
}
|
||||
if (checkCollision(area, getHeroMask()) == 1) {
|
||||
b->state = 1;
|
||||
b->timer = 0;
|
||||
}
|
||||
|
||||
}else{
|
||||
b->timer -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Throw
|
||||
else if (b->state == 1) {
|
||||
//Animate
|
||||
{
|
||||
b->imageIndex = 0;
|
||||
if (b->timer >= 15) {
|
||||
b->imageIndex = 2;
|
||||
}
|
||||
}
|
||||
|
||||
b->timer += 1;
|
||||
if (b->timer == 15) {
|
||||
createBoom(b->x, b->y, b->dir);
|
||||
PHL_PlaySound(sounds[sndPi05], CHN_ENEMIES);
|
||||
}
|
||||
|
||||
if (b->timer >= 110) {
|
||||
b->state = 0;
|
||||
b->imageIndex = 0;
|
||||
b->timer = 120;
|
||||
}
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
mask.x = b->x + ((40 - mask.w) / 2);
|
||||
mask.y = b->y + (40 - mask.h);
|
||||
|
||||
//Hero Collision
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask()) == 1) {
|
||||
heroHit(15, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon Collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
b->hp -= 1;
|
||||
b->blink = 15;
|
||||
|
||||
//Death
|
||||
if (b->hp <= 0) {
|
||||
createEffect(2, b->x - 12, b->y - 6);
|
||||
spawnCollectable(b->x + 20, b->y);
|
||||
enemyDestroy(b->id);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void boomknightDraw(Boomknight* b)
|
||||
{
|
||||
if (b->blink % 2 == 0) {
|
||||
int cropX = 400 + ((int)b->imageIndex * 40);
|
||||
|
||||
if (b->dir == -1) {
|
||||
cropX += 120;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(b->x, b->y, cropX, 400, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Enemy boomerang
|
||||
void createBoom(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Boom* b = malloc(sizeof *b);
|
||||
b->id = i;
|
||||
|
||||
b->dir = dir;
|
||||
b->x = x;
|
||||
b->y = y;
|
||||
|
||||
b->hsp = 6 * b->dir;
|
||||
b->imageIndex = 0;
|
||||
|
||||
b->timer = 90;
|
||||
|
||||
e->data = b;
|
||||
e->enemyStep = boomStep;
|
||||
e->enemyDraw = boomDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void boomStep(Boom* b)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
b->imageIndex += 0.33;
|
||||
if (b->imageIndex >= 8) {
|
||||
b->imageIndex -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
b->x += b->hsp;
|
||||
|
||||
double fric = 0.125;
|
||||
b->hsp -= fric * b->dir;
|
||||
}
|
||||
|
||||
//Hero collision
|
||||
{
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 24;
|
||||
mask.h = 24;
|
||||
mask.x = b->x + ((40 - mask.w) / 2);
|
||||
mask.y = b->y + ((40 - mask.h) / 2);
|
||||
}
|
||||
|
||||
if (checkCollision(mask, getHeroMask()) == 1) {
|
||||
heroHit(10, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
b->timer -= 1;
|
||||
if (b->timer <= 0) {
|
||||
createEffectExtra(5, b->x + 20, b->y + 20, 0, 0, 0);
|
||||
enemyDestroy(b->id);
|
||||
}
|
||||
}
|
||||
|
||||
void boomDraw(Boom* b)
|
||||
{
|
||||
int cropX = (int)b->imageIndex * 40;
|
||||
|
||||
if (b->dir == -1) {
|
||||
cropX += 320;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(b->x, b->y, cropX, 360, 40, 40, images[imgMisc20]);
|
||||
}
|
27
contrib/games/hydracastlelabyrinth/src/enemies/boomknight.h
Normal file
27
contrib/games/hydracastlelabyrinth/src/enemies/boomknight.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef BOOMKNIGHT_H
|
||||
#define BOOMKNIGHT_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
int blink;
|
||||
double x, y;
|
||||
int dir;
|
||||
double imageIndex;
|
||||
int state, timer;
|
||||
} Boomknight;
|
||||
|
||||
void createBoomknight(int x, int y);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int dir;
|
||||
double x, y;
|
||||
double hsp;
|
||||
double imageIndex;
|
||||
int timer;
|
||||
} Boom;
|
||||
|
||||
void createBoom(int x, int y, int dir);
|
||||
|
||||
#endif
|
509
contrib/games/hydracastlelabyrinth/src/enemies/crab.c
Normal file
509
contrib/games/hydracastlelabyrinth/src/enemies/crab.c
Normal file
@ -0,0 +1,509 @@
|
||||
#include "crab.h"
|
||||
#include "../PHL.h"
|
||||
#include "../enemy.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int boss3flag = 13;
|
||||
|
||||
void crabStep(Crab* c);
|
||||
void crabDraw(Crab* c);
|
||||
void updateCrabMask(Crab* c);
|
||||
void crabDestroy(Crab* c);
|
||||
|
||||
void electricityStep(Electricity* e);
|
||||
void electricityDraw(Electricity* e);
|
||||
|
||||
void createCrab(int x, int y)
|
||||
{
|
||||
if (flags[boss3flag] == 0) { //have not beaten boss 3
|
||||
PHL_FreeSurface(images[imgBoss]);
|
||||
images[imgBoss] = PHL_LoadQDA("boss06.bmp");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
//Boss start
|
||||
setBossRoom();
|
||||
|
||||
Enemy* e = /*(Enemy*)*/malloc(sizeof(Enemy));
|
||||
Crab* c = /*(Crab*)*/malloc(sizeof(Crab));
|
||||
c->id = i;
|
||||
|
||||
//c->hp = 1;
|
||||
c->hp = 35;
|
||||
c->invincible = 0;
|
||||
|
||||
c->x = x;
|
||||
c->y = y;
|
||||
|
||||
c->vsp = 0;
|
||||
c->hsp = 0;
|
||||
|
||||
c->imageIndex = 0;
|
||||
|
||||
c->state = 0;
|
||||
c->timer = 0;
|
||||
c->counter = 0;
|
||||
|
||||
c->mask.unused = 0;
|
||||
c->mask.circle = 1;
|
||||
c->mask.w = 33;
|
||||
c->mask.h = 33;
|
||||
updateCrabMask(c);
|
||||
|
||||
//Setup phase
|
||||
c->timer = 60;
|
||||
|
||||
e->data = c;
|
||||
e->enemyStep = crabStep;
|
||||
e->enemyDraw = crabDraw;
|
||||
e->type = 42;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void crabStep(Crab* c)
|
||||
{
|
||||
char dead = 0;
|
||||
double grav = 0.15;
|
||||
|
||||
if (c->invincible > 0) {
|
||||
c->invincible -= 1;
|
||||
}
|
||||
|
||||
//Wait
|
||||
if (c->state == 0)
|
||||
{
|
||||
c->imageIndex = 0;
|
||||
|
||||
if (c->timer <= 0) {
|
||||
c->timer = 0;
|
||||
if (c->counter == 2 || c->counter == 5) { //Goto roll
|
||||
c->state = 3;
|
||||
if (c->counter == 5) {
|
||||
c->counter = 0;
|
||||
}else{
|
||||
c->counter = 3;
|
||||
}
|
||||
}else if (c->counter == 3) {
|
||||
c->state = 2;
|
||||
}else{
|
||||
c->state = 1; //Goto shoot
|
||||
}
|
||||
}else{
|
||||
c->timer -= 1;
|
||||
}
|
||||
}
|
||||
//Shoot Electric orbs
|
||||
else if (c->state == 1)
|
||||
{
|
||||
//Create orbs
|
||||
if (c->timer == 0) {
|
||||
PHL_PlaySound(sounds[sndPi05], CHN_ENEMIES);
|
||||
|
||||
double angle = (atan2(heroy + 20 - (c->y + 60), c->x - (herox - 20)) * 180 / 3.14159) + 270;
|
||||
createElectricity(c->x, c->y + 60, angle - 45, c->id);
|
||||
createElectricity(c->x, c->y + 60, angle - 22.5, c->id);
|
||||
createElectricity(c->x, c->y + 60, angle, c->id);
|
||||
createElectricity(c->x, c->y + 60, angle + 22.5, c->id);
|
||||
createElectricity(c->x, c->y + 60, angle + 45, c->id);
|
||||
}
|
||||
|
||||
if (c->timer >= 20) {
|
||||
c->state = 2;
|
||||
c->timer = 0;
|
||||
}else{
|
||||
c->timer += 1;
|
||||
}
|
||||
}
|
||||
//Leap
|
||||
else if (c->state == 2)
|
||||
{
|
||||
c->imageIndex = 1;
|
||||
|
||||
//Hopping down or hopping up
|
||||
int hopup = 1;
|
||||
if (c->counter > 2) {
|
||||
hopup = 0;
|
||||
}
|
||||
|
||||
//Jump
|
||||
if (c->timer == 0) {
|
||||
PHL_PlaySound(sounds[sndJump02], CHN_ENEMIES);
|
||||
|
||||
c->vsp = -6.5;
|
||||
if (hopup == 0) {
|
||||
c->vsp = -1.5;
|
||||
}
|
||||
c->timer = 1;
|
||||
}
|
||||
|
||||
//Vertical velocity
|
||||
c->y += c->vsp;
|
||||
c->vsp += grav;
|
||||
|
||||
if (c->vsp >= 6) {
|
||||
c->vsp = 6;
|
||||
}
|
||||
|
||||
//Check if onground
|
||||
if ((hopup == 1 && c->vsp > 0) || (hopup == 0 && c->vsp >= 6)) {
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.w = 40;
|
||||
area.h = 10;
|
||||
area.x = c->x - (area.w / 2);
|
||||
area.y = c->y + (80 - area.h);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, area);
|
||||
if (collide.x != -1) {
|
||||
c->y = collide.y - 80;
|
||||
c->state = 0;
|
||||
c->counter += 1;
|
||||
c->timer = 25;
|
||||
if (c->counter == 2 || c->counter == 5) {
|
||||
c->timer = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Roll hop
|
||||
else if (c->state == 3)
|
||||
{
|
||||
//Animate
|
||||
if (c->hsp > 0) {
|
||||
c->imageIndex += 0.25;
|
||||
}
|
||||
if (c->hsp < 0) {
|
||||
c->imageIndex -= 0.25;
|
||||
}
|
||||
if (c->imageIndex < 2) { c->imageIndex += 4; }
|
||||
if (c->imageIndex >= 6) { c->imageIndex -= 4; }
|
||||
|
||||
|
||||
if (c->timer == 0) {
|
||||
PHL_PlaySound(sounds[sndHit04], CHN_ENEMIES);
|
||||
|
||||
c->timer = 1;
|
||||
c->vsp = -1.5;
|
||||
c->imageIndex = 2;
|
||||
if (c->x > 320) {
|
||||
c->hsp = -8;
|
||||
}else{
|
||||
c->hsp = 8;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
c->y += c->vsp;
|
||||
c->vsp += grav;
|
||||
|
||||
//Check if onground
|
||||
if (c->vsp > 0) {
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.w = 40;
|
||||
area.h = 10;
|
||||
area.x = c->x - (area.w / 2);
|
||||
area.y = c->y + (80 - area.h);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, area);
|
||||
if (collide.x != -1) {
|
||||
c->y = collide.y - 80;
|
||||
c->state = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Roll
|
||||
if (c->state == 4)
|
||||
{
|
||||
//Animate
|
||||
if (c->hsp > 0) {
|
||||
c->imageIndex += 0.25;
|
||||
}
|
||||
if (c->hsp < 0) {
|
||||
c->imageIndex -= 0.25;
|
||||
}
|
||||
if (c->imageIndex < 2) { c->imageIndex += 4; }
|
||||
if (c->imageIndex >= 6) { c->imageIndex -= 4; }
|
||||
|
||||
//Movement
|
||||
c->x += c->hsp;
|
||||
|
||||
//Collide with wall
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.w = area.h = c->mask.w * 2;
|
||||
area.x = c->x - c->mask.w;
|
||||
area.y = c->y + (40 - c->mask.h);
|
||||
|
||||
if (checkTileCollision(1, area) == 1) {
|
||||
c->state = 5;
|
||||
c->timer = 0;
|
||||
}
|
||||
}
|
||||
//Bounce off wall
|
||||
if (c->state == 5)
|
||||
{
|
||||
if (c->timer == 0) {
|
||||
PHL_PlaySound(sounds[sndHit04], CHN_ENEMIES);
|
||||
|
||||
c->timer = 1;
|
||||
c->vsp = -2;
|
||||
c->hsp = 2;
|
||||
if (c->x > 320) {
|
||||
c->hsp *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
c->imageIndex = 1;
|
||||
|
||||
c->x += c->hsp;
|
||||
|
||||
c->y += c->vsp;
|
||||
c->vsp += grav;
|
||||
|
||||
//Check if onground
|
||||
if (c->vsp > 0) {
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.w = 40;
|
||||
area.h = 10;
|
||||
area.x = c->x - (area.w / 2);
|
||||
area.y = c->y + (80 - area.h);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, area);
|
||||
if (collide.x != -1) {
|
||||
c->y = collide.y - 80;
|
||||
c->state = 0;
|
||||
c->timer = 65;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Death
|
||||
else if (c->state == 6)
|
||||
{
|
||||
c->imageIndex = 1;
|
||||
|
||||
c->y += 0.2;
|
||||
|
||||
c->timer -= 1;
|
||||
|
||||
if (c->timer % 12 == 0) {
|
||||
createEffect(2, c->x - 64 + (rand() % 100), c->y + (rand() % 80));
|
||||
}
|
||||
|
||||
if (c->timer <= 0) {
|
||||
crabDestroy(c);
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dead == 0) {
|
||||
if (c->state != 6) {
|
||||
//Update Mask
|
||||
c->mask.x = c->x;
|
||||
c->mask.y = c->y + 40;
|
||||
|
||||
//Weapon collision
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(c->mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
c->invincible = 15;
|
||||
c->hp -= 1;
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Hit Player
|
||||
if (checkCollision(c->mask, getHeroMask())) {
|
||||
heroHit(30, c->x);
|
||||
}
|
||||
|
||||
//Die
|
||||
if (c->hp <= 0) {
|
||||
c->state = 6;
|
||||
c->timer = 180;
|
||||
c->invincible = 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void crabDraw(Crab* c)
|
||||
{
|
||||
if (c->invincible % 2 == 0) {
|
||||
PHL_DrawSurfacePart(c->x - 40, c->y, (int)c->imageIndex * 80, 0, 80, 80, images[imgBoss]);
|
||||
}
|
||||
}
|
||||
|
||||
void updateCrabMask(Crab* c)
|
||||
{
|
||||
c->mask.x = c->x;
|
||||
c->mask.y = c->y + 40;
|
||||
}
|
||||
|
||||
void crabDestroy(Crab* c)
|
||||
{
|
||||
enemyDestroy(c->id);
|
||||
bossDefeatedFlag = 1;
|
||||
roomSecret = 1;
|
||||
|
||||
flags[boss3flag] = 1;
|
||||
PHL_StopMusic();
|
||||
}
|
||||
|
||||
|
||||
void createElectricity(int x, int y, double angle, int minid)
|
||||
{
|
||||
int i;
|
||||
for (i = minid; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = /*(Enemy*)*/malloc(sizeof *e);
|
||||
Electricity* el = /*(Electricity*)*/malloc(sizeof *el);
|
||||
el->id = i;
|
||||
|
||||
el->x = x;
|
||||
el->y = y;
|
||||
|
||||
//Fix angle
|
||||
if (angle < 0) {
|
||||
angle += 360;
|
||||
}
|
||||
if (angle >= 360) {
|
||||
angle -= 360;
|
||||
}
|
||||
|
||||
el->angle = angle;
|
||||
el->imageIndex = 0;
|
||||
|
||||
el->mask.unused = 0;
|
||||
el->mask.circle = 1;
|
||||
el->mask.w = 16;
|
||||
el->mask.h = 16;
|
||||
el->mask.x = x;
|
||||
el->mask.y = y;
|
||||
|
||||
e->data = el;
|
||||
e->enemyStep = electricityStep;
|
||||
e->enemyDraw = electricityDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
/*
|
||||
int thisid = -1;
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
if (i <= minid) {
|
||||
thisid = i;
|
||||
i = MAX_ENEMIES;
|
||||
}else{
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thisid == -1) {
|
||||
for (i = minid + 1; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
enemies[i] = enemies[minid];
|
||||
Crab* c = enemies[i]->data;
|
||||
c->id = i;
|
||||
thisid = minid;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thisid != -1) {
|
||||
Enemy* e = (Enemy*)malloc(sizeof(Enemy));
|
||||
Electricity* el = (Electricity*)malloc(sizeof(Electricity));
|
||||
el->id = thisid;
|
||||
|
||||
el->x = x;
|
||||
el->y = y;
|
||||
|
||||
//Fix angle
|
||||
if (angle < 0) {
|
||||
angle += 360;
|
||||
}
|
||||
if (angle >= 360) {
|
||||
angle -= 360;
|
||||
}
|
||||
|
||||
el->angle = angle;
|
||||
el->imageIndex = 0;
|
||||
|
||||
el->mask.unused = 0;
|
||||
el->mask.circle = 1;
|
||||
el->mask.w = 16;
|
||||
el->mask.h = 16;
|
||||
el->mask.x = x;
|
||||
el->mask.y = y;
|
||||
|
||||
e->data = el;
|
||||
e->enemyStep = electricityStep;
|
||||
e->enemyDraw = electricityDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[thisid] = e;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void electricityStep(Electricity* e)
|
||||
{
|
||||
double spd = 3;
|
||||
e->x += spd * sin(e->angle * 3.14159 / 180);
|
||||
e->y += spd * cos(e->angle * 3.14159 / 180);
|
||||
|
||||
//Update Mask
|
||||
e->mask.x = e->x;
|
||||
e->mask.y = e->y;
|
||||
|
||||
//Collide with Shield
|
||||
if (checkCollision(shieldMask, e->mask) == 1) {
|
||||
createEffect(1, e->x - 20, e->y - 20);
|
||||
PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
|
||||
enemyDestroy(e->id);
|
||||
}else{
|
||||
//Collide with Hero
|
||||
if (checkCollision(getHeroMask(), e->mask) == 1) {
|
||||
if (heroHit(25, e->x) == 1) {
|
||||
heroStun();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Animate
|
||||
e->imageIndex += 0.25;
|
||||
if (e->imageIndex >= 3) {
|
||||
e->imageIndex -= 3;
|
||||
}
|
||||
|
||||
//Outside of screen
|
||||
if (e->x < -20 || e->x > 660 || e->y < -20 || e->y > 500) {
|
||||
enemyDestroy(e->id);
|
||||
}
|
||||
}
|
||||
|
||||
void electricityDraw(Electricity* e)
|
||||
{
|
||||
PHL_DrawSurfacePart(e->x - 20, e->y - 20, 40 + ((int)e->imageIndex * 40), 0, 40, 40, images[imgMisc20]);
|
||||
}
|
30
contrib/games/hydracastlelabyrinth/src/enemies/crab.h
Normal file
30
contrib/games/hydracastlelabyrinth/src/enemies/crab.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef CRAB_H
|
||||
#define CRAB_H
|
||||
|
||||
#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp, invincible;
|
||||
double x, y;
|
||||
double hsp, vsp;
|
||||
double imageIndex;
|
||||
int state, timer, counter;
|
||||
|
||||
Mask mask;
|
||||
} Crab;
|
||||
|
||||
void createCrab(int x, int y);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double angle;
|
||||
double imageIndex;
|
||||
|
||||
Mask mask;
|
||||
} Electricity;
|
||||
|
||||
void createElectricity(int x, int y, double angle, int minid);
|
||||
|
||||
#endif
|
458
contrib/games/hydracastlelabyrinth/src/enemies/devil.c
Normal file
458
contrib/games/hydracastlelabyrinth/src/enemies/devil.c
Normal file
@ -0,0 +1,458 @@
|
||||
#include "devil.h"
|
||||
#include "../game.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
int boss6flag = 31;
|
||||
|
||||
void devilStep(Devil* d);
|
||||
void devilDraw(Devil* d);
|
||||
|
||||
void orbStep(Orb* o);
|
||||
void orbDraw(Orb* o);
|
||||
|
||||
void createDevil(int x, int y)
|
||||
{
|
||||
if (flags[boss6flag] == 0) { //have not beaten boss 6
|
||||
PHL_FreeSurface(images[imgBoss]);
|
||||
images[imgBoss] = PHL_LoadQDA("boss04.bmp");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
setBossRoom();
|
||||
|
||||
Enemy* e = /*(Enemy*)*/malloc(sizeof *e);
|
||||
Devil* d = /*(Devil*)*/malloc(sizeof *d);
|
||||
d->id = i;
|
||||
|
||||
d->x = x;
|
||||
d->y = y;
|
||||
|
||||
d->ystart = d->y;
|
||||
d->newystart = d->ystart;
|
||||
d->hsp = -2.5;
|
||||
|
||||
d->hp = 100;
|
||||
//d->hp = 1;
|
||||
|
||||
d->state = 0;
|
||||
d->timer = 0;
|
||||
|
||||
d->blink = 0;
|
||||
d->boblen = 32;
|
||||
d->bobspd = 3;
|
||||
|
||||
d->tailangle = 90;
|
||||
|
||||
d->rotcounter = 0;
|
||||
d->bobcounter = 0;
|
||||
|
||||
d->bobspd = 3;
|
||||
d->rotspd = 1;
|
||||
|
||||
d->imageIndex = 0;
|
||||
|
||||
e->data = d;
|
||||
e->enemyStep = devilStep;
|
||||
e->enemyDraw = devilDraw;
|
||||
e->type = 45;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void devilStep(Devil* d)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Animate
|
||||
{
|
||||
d->imageIndex += 0.1;
|
||||
if (d->imageIndex >= 2) {
|
||||
d->imageIndex -= 2;
|
||||
}
|
||||
|
||||
if (d->blink > 0) {
|
||||
d->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Bob
|
||||
{
|
||||
if (d->state != 4) {
|
||||
d->bobcounter += d->bobspd;
|
||||
if (d->bobcounter >= 360) {
|
||||
d->bobcounter -= 360;
|
||||
}
|
||||
|
||||
d->y = d->ystart + (d->boblen * cos(d->bobcounter * 3.14159 / 180));
|
||||
}
|
||||
}
|
||||
|
||||
//Swing tail
|
||||
{
|
||||
d->rotcounter += d->rotspd;
|
||||
if (d->rotcounter >= 360) {
|
||||
d->rotcounter -= 360;
|
||||
}
|
||||
|
||||
d->tailangle = 90 + (55 * cos(d->rotcounter * 3.14159 / 180));
|
||||
}
|
||||
|
||||
//Patterns
|
||||
{
|
||||
//movement
|
||||
if (d->state == 0 || d->state == 2)
|
||||
{
|
||||
d->rotspd = 1;
|
||||
d->boblen = 32;
|
||||
d->bobspd = 3;
|
||||
|
||||
//Re-align ystart
|
||||
if (d->ystart > d->newystart) {
|
||||
d->ystart -= 1;
|
||||
}
|
||||
if (d->ystart < d->newystart) {
|
||||
d->ystart += 1;
|
||||
}
|
||||
|
||||
d->x += d->hsp;
|
||||
|
||||
//Slow Down
|
||||
double rate = 0.016;
|
||||
if (d->hsp < 0) {
|
||||
d->hsp += rate;
|
||||
if (d->hsp >= 0) {
|
||||
d->hsp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (d->hsp > 0) {
|
||||
d->hsp -= rate;
|
||||
if (d->hsp <= 0) {
|
||||
d->hsp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (d->hsp == 0) {
|
||||
d->timer = 0;
|
||||
if (d->state == 0) {
|
||||
d->state = 1;
|
||||
}
|
||||
|
||||
if (d->state == 2) {
|
||||
if ((d->rotcounter >= 90 && d->rotcounter <= 90 + d->rotspd) || (d->rotcounter >= 270 && d->rotcounter <= 270 + d->rotspd)) {
|
||||
d->state = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//mid room pause
|
||||
else if (d->state == 1)
|
||||
{
|
||||
d->timer += 1;
|
||||
if (d->timer >= 60) {
|
||||
if (d->state == 1) {
|
||||
d->hsp = 2.5;
|
||||
if (herox < d->x) {
|
||||
d->hsp *= -1;
|
||||
}
|
||||
}
|
||||
d->state = 2;
|
||||
}
|
||||
}
|
||||
//Shoot
|
||||
else if (d->state == 3)
|
||||
{
|
||||
d->rotspd = 3;
|
||||
d->boblen = 10;
|
||||
d->bobspd = 10;
|
||||
|
||||
d->timer += 1;
|
||||
|
||||
//Shoot orbs
|
||||
if (d->timer == 120 || d->timer == 240 || d->timer == 360) {
|
||||
int aim = (atan2((heroy + 20) - d->y, d->x - herox) * 180 / 3.14159) + 270;
|
||||
|
||||
int spawnY = d->y + 20;
|
||||
createOrb(d->x, spawnY, aim + 22);
|
||||
createOrb(d->x, spawnY, aim + 11);
|
||||
createOrb(d->x, spawnY, aim);
|
||||
createOrb(d->x, spawnY, aim - 11);
|
||||
createOrb(d->x, spawnY, aim - 22);
|
||||
|
||||
PHL_PlaySound(sounds[sndShot03], CHN_ENEMIES);
|
||||
}
|
||||
|
||||
if (d->timer == 360) {
|
||||
d->state = 0;
|
||||
d->hsp = 2.5;
|
||||
|
||||
if (d->x > 320) {
|
||||
d->hsp *= -1;
|
||||
}
|
||||
|
||||
int chaseY = heroy - d->ystart;
|
||||
if (chaseY > 52) { chaseY = 52; }
|
||||
if (chaseY < -52) { chaseY = -52; }
|
||||
|
||||
d->newystart = d->ystart + chaseY;
|
||||
}
|
||||
}
|
||||
|
||||
//Death
|
||||
if (d->state == 4) {
|
||||
d->rotspd = 3;
|
||||
d->y += 0.2;
|
||||
d->timer -= 1;
|
||||
|
||||
if (d->timer % 12 == 0) {
|
||||
createEffect(2, d->x - 64 + (rand() % 100), d->y - 64 + (rand() % 80));
|
||||
}
|
||||
|
||||
if (d->timer <= 0) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Collisions
|
||||
if (d->state != 4) {
|
||||
//Setup masks
|
||||
Mask masks[6];
|
||||
|
||||
//Head mask
|
||||
masks[0].unused = masks[0].circle = 0;
|
||||
masks[0].w = 100;
|
||||
masks[0].h = 104;
|
||||
masks[0].x = d->x - (masks[0].w / 2);
|
||||
masks[0].y = d->y - (masks[0].h / 2);
|
||||
|
||||
//Link masks
|
||||
for (int i = 1; i < 5; i++) {
|
||||
int taildis[4] = {54, 80, 108, 134};
|
||||
int taillag[4] = {10, 15, 10, 5};
|
||||
|
||||
double newtailangle = 90 + (55 * cos((d->rotcounter - taillag[i-1]) * 3.14159 / 180));
|
||||
|
||||
masks[i].unused = 0;
|
||||
masks[i].circle = 1;
|
||||
masks[i].w = 16;
|
||||
masks[i].h = 16;
|
||||
masks[i].x = d->x + (taildis[i-1] * cos(newtailangle * 3.14159 / 180));
|
||||
masks[i].y = d->y + (taildis[i-1] * sin(newtailangle * 3.14159 / 180));
|
||||
}
|
||||
|
||||
//Barb mask
|
||||
masks[5].unused = masks[5].circle = 0;
|
||||
masks[5].w = 40;
|
||||
masks[5].h = 40;
|
||||
masks[5].x = (d->x + (160 * cos(d->tailangle * 3.14159 / 180))) - (masks[5].w / 2);
|
||||
masks[5].y = (d->y + (160 * sin(d->tailangle * 3.14159 / 180))) - (masks[5].h / 2);
|
||||
|
||||
//Collisions
|
||||
int hitHead = 0;
|
||||
for (int a = 0; a < 6; a++)
|
||||
{
|
||||
if (a == 0 || a == 5) {
|
||||
//Hit Player
|
||||
if (checkCollision(masks[a], getHeroMask())) {
|
||||
|
||||
int damage = 25;
|
||||
if (a == 0) {
|
||||
damage = 50;
|
||||
}
|
||||
|
||||
if (heroHit(damage, masks[a].x + (masks[a].w / 2)) == 1) {
|
||||
if (a == 5) { //Barb
|
||||
heroStun();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
if (hitHead == 0) {
|
||||
for (int i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(masks[a], weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
//Head
|
||||
if (a == 0) {
|
||||
d->hp -= 1;
|
||||
d->blink = 15;
|
||||
hitHead = 1;
|
||||
|
||||
if (d->hp <= 0) {
|
||||
d->state = 4;
|
||||
d->timer = 180;
|
||||
d->blink = 200;
|
||||
}
|
||||
}else{
|
||||
PHL_PlaySound(sounds[sndHit03], CHN_WEAPONS);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy
|
||||
if (dead == 1) {
|
||||
enemyDestroy(d->id);
|
||||
bossDefeatedFlag = 1;
|
||||
roomSecret = 1;
|
||||
|
||||
flags[boss6flag] = 1;
|
||||
PHL_StopMusic();
|
||||
}
|
||||
}
|
||||
|
||||
void devilDraw(Devil* d)
|
||||
{
|
||||
if (d->blink % 2 == 0)
|
||||
{
|
||||
int dx, dy;
|
||||
|
||||
//Draw tail
|
||||
int taildis[4] = {54, 80, 108, 134};
|
||||
int taillag[4] = {10, 15, 10, 5};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
double newtailangle = 90 + (55 * cos((d->rotcounter - taillag[i]) * 3.14159 / 180));
|
||||
|
||||
dx = d->x + (taildis[i] * cos(newtailangle * 3.14159 / 180)) - 32;
|
||||
dy = d->y + (taildis[i] * sin(newtailangle * 3.14159 / 180)) - 32;
|
||||
PHL_DrawSurfacePart(dx, dy, 0, 128, 64, 64, images[imgBoss]);
|
||||
}
|
||||
|
||||
//Draw Head
|
||||
dx = d->x - 64;
|
||||
dy = d->y - 64;
|
||||
PHL_DrawSurfacePart(dx, dy, (int)d->imageIndex * 128, 0, 128, 128, images[imgBoss]);
|
||||
|
||||
//Draw Tail Tip
|
||||
dx = d->x + (160 * cos(d->tailangle * 3.14159 / 180)) - 32;
|
||||
dy = d->y + (160 * sin(d->tailangle * 3.14159 / 180)) - 32;
|
||||
PHL_DrawSurfacePart(dx, dy, 64, 128, 64, 64, images[imgBoss]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Stone Orbs
|
||||
void createOrb(int x, int y, double dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = /*(Enemy*)*/malloc(sizeof *e);
|
||||
Orb* o = /*(Orb*)*/malloc(sizeof *o);
|
||||
o->id = i;
|
||||
|
||||
o->x = x;
|
||||
o->y = y;
|
||||
|
||||
o->dir = dir;
|
||||
|
||||
o->imageIndex = 0;
|
||||
|
||||
e->data = o;
|
||||
e->enemyStep = orbStep;
|
||||
e->enemyDraw = orbDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void orbStep(Orb* o)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Animate
|
||||
{
|
||||
o->imageIndex += 0.33;
|
||||
if (o->imageIndex >= 4) {
|
||||
o->imageIndex -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
int spd = 4;
|
||||
o->x += spd * sin(o->dir * 3.14159 / 180);
|
||||
o->y += spd * cos(o->dir * 3.14159 / 180);
|
||||
}
|
||||
|
||||
//Collision
|
||||
{
|
||||
Mask mask;
|
||||
mask.unused = 0;
|
||||
mask.circle = 1;
|
||||
mask.w = 6;
|
||||
mask.x = o->x;
|
||||
mask.y = o->y;
|
||||
|
||||
//Collide with shield
|
||||
/*if (checkCollision(mask, shieldMask)) {
|
||||
createEffect(1, o->x - 20, o->y - 20);
|
||||
PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
|
||||
dead = 1;
|
||||
}else{*/
|
||||
//Hit player
|
||||
if (checkCollision(getHeroMask(), mask)) {
|
||||
heroStone();
|
||||
heroHit(25, mask.x);
|
||||
}
|
||||
//}
|
||||
|
||||
//Collide with weapon
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
createEffect(2, o->x - 32, o->y - 32);
|
||||
dead = 1;
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy if outside of room
|
||||
{
|
||||
if (o->x < -20 || o->x > 660 || o->y < -20 || o->y > 500) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Finally erase object
|
||||
{
|
||||
if (dead == 1) {
|
||||
enemyDestroy(o->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void orbDraw(Orb* o)
|
||||
{
|
||||
int animation[4] = {0, 1, 0, 2};
|
||||
PHL_DrawSurfacePart(o->x - 20, o->y - 20, 440 + (animation[(int)o->imageIndex] * 40), 480, 40, 40, images[imgMisc20]);
|
||||
}
|
28
contrib/games/hydracastlelabyrinth/src/enemies/devil.h
Normal file
28
contrib/games/hydracastlelabyrinth/src/enemies/devil.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef DEVIL_H
|
||||
#define DEVIL_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double ystart, newystart;
|
||||
double hsp;
|
||||
int hp;
|
||||
int state, timer;
|
||||
int blink;
|
||||
int boblen, bobspd;
|
||||
double tailangle, bobcounter, rotcounter, rotspd;
|
||||
double imageIndex;
|
||||
} Devil;
|
||||
|
||||
void createDevil(int x, int y);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double dir;
|
||||
double imageIndex;
|
||||
} Orb;
|
||||
|
||||
void createOrb(int x, int y, double dir);
|
||||
|
||||
#endif
|
587
contrib/games/hydracastlelabyrinth/src/enemies/dodo.c
Normal file
587
contrib/games/hydracastlelabyrinth/src/enemies/dodo.c
Normal file
@ -0,0 +1,587 @@
|
||||
#include "dodo.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include "../PHL.h"
|
||||
#include "../enemy.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void dodoStep(Dodo* d);
|
||||
void dodoDraw(Dodo* d);
|
||||
|
||||
Mask updateDodoMask(Dodo* d, Mask mask);
|
||||
int dodoWallCollision(Dodo* d, Mask mask);
|
||||
|
||||
int boss1flag = 1;
|
||||
|
||||
void createDodo(int x, int y, int flag)
|
||||
{
|
||||
char miniboss = 0;
|
||||
|
||||
if (flag != 0) {
|
||||
miniboss = 1;
|
||||
}else{
|
||||
flag = boss1flag;
|
||||
}
|
||||
|
||||
if (flags[flag] == 0) {
|
||||
PHL_FreeSurface(images[imgBoss]);
|
||||
images[imgBoss] = PHL_LoadQDA("boss01.bmp");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
|
||||
if (miniboss == 0) {
|
||||
setBossRoom();
|
||||
}
|
||||
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Dodo* d = malloc(sizeof *d);
|
||||
d->id = i;
|
||||
|
||||
d->x = x;
|
||||
d->y = y;
|
||||
|
||||
d->vsp = -6;
|
||||
d->hsp = 0;
|
||||
d->grav = 0.2;
|
||||
|
||||
d->onground = 0;
|
||||
d->dir = -1;
|
||||
if (herox > d->x) {
|
||||
d->dir = 1;
|
||||
}
|
||||
|
||||
d->imageIndex = 0;
|
||||
|
||||
d->timer = 0;
|
||||
d->state = 2;
|
||||
|
||||
d->hp = 45;
|
||||
d->blink = 0;
|
||||
|
||||
d->tojump = 1;
|
||||
d->jumptoggle = 0;
|
||||
|
||||
d->flag = flag;
|
||||
|
||||
e->data = d;
|
||||
e->enemyStep = dodoStep;
|
||||
e->enemyDraw = dodoDraw;
|
||||
e->type = 40;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dodoStep(Dodo* d)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Constants
|
||||
double fric = 0.06;
|
||||
|
||||
//Animation vars
|
||||
double imgspd = 0;
|
||||
int frames = 0;
|
||||
|
||||
//timers
|
||||
{
|
||||
if (d->timer > 0) {
|
||||
d->timer -= 1;
|
||||
}
|
||||
|
||||
if (d->blink > 0) {
|
||||
d->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 56;
|
||||
mask.h = 56;
|
||||
mask = updateDodoMask(d, mask);
|
||||
}
|
||||
|
||||
//Idle
|
||||
if (d->state == 0)
|
||||
{
|
||||
d->hsp = 0;
|
||||
d->vsp = 0;
|
||||
|
||||
//Animate
|
||||
imgspd = 0.1;
|
||||
frames = 4;
|
||||
|
||||
//End state
|
||||
if (d->timer <= 0) {
|
||||
//Go to chase
|
||||
if (d->tojump == 0) {
|
||||
d->state = 1;
|
||||
d->timer = 260;
|
||||
d->tojump = 1;
|
||||
}
|
||||
//Go to windup
|
||||
else {
|
||||
d->state = 3;
|
||||
d->timer = 30;
|
||||
}
|
||||
}
|
||||
|
||||
//Fall
|
||||
{
|
||||
if (d->onground == 0) {
|
||||
d->state = 6;
|
||||
d->imageIndex = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Chase
|
||||
else if (d->state == 1)
|
||||
{
|
||||
//Animate
|
||||
imgspd = 0.2;
|
||||
frames = 4;
|
||||
|
||||
//Chase
|
||||
if ( (d->dir == -1 && herox < d->x) || (d->dir == 1 && herox > d->x) ) {
|
||||
d->hsp += (fric / 2) * d->dir;
|
||||
|
||||
//limit speed
|
||||
if (d->hsp > 3) {
|
||||
d->hsp = 3;
|
||||
}
|
||||
if (d->hsp < -3) {
|
||||
d->hsp = -3;
|
||||
}
|
||||
}
|
||||
|
||||
//Turn around
|
||||
else{
|
||||
d->hsp -= fric * d->dir;
|
||||
|
||||
//Done slowing down
|
||||
if ( (d->dir == 1 && d->hsp <= 0) || (d->dir == -1 && d->hsp >= 0) ) {
|
||||
d->hsp = 0;
|
||||
d->state = 4;
|
||||
d->imageIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Stop running
|
||||
{
|
||||
if (d->timer <= 0) {
|
||||
if (d->hsp >= 1 || d->hsp <= -1) {
|
||||
d->state = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Fall
|
||||
{
|
||||
if (d->onground == 0) {
|
||||
d->state = 6;
|
||||
d->imageIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Turn around
|
||||
else if (d->state == 4)
|
||||
{
|
||||
//Animate
|
||||
imgspd = 0;
|
||||
d->imageIndex += 0.2;
|
||||
|
||||
//Done turning around
|
||||
if (d->imageIndex >= 3) {
|
||||
d->dir *= -1;
|
||||
d->state = 1;
|
||||
d->imageIndex = 0;
|
||||
}
|
||||
|
||||
//Fall
|
||||
{
|
||||
if (d->onground == 0) {
|
||||
d->state = 6;
|
||||
d->imageIndex = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Jump
|
||||
if (d->state == 2)
|
||||
{
|
||||
//Set image
|
||||
imgspd = 0;
|
||||
{
|
||||
//Fall
|
||||
d->imageIndex = 0;
|
||||
|
||||
//Jump
|
||||
if (d->vsp < 0) {
|
||||
d->imageIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Face hsp
|
||||
{
|
||||
if (d->hsp > 0) {
|
||||
d->dir = 1;
|
||||
}
|
||||
if (d->hsp < 0) {
|
||||
d->dir = -1;
|
||||
}
|
||||
}
|
||||
|
||||
//Land
|
||||
{
|
||||
if (d->onground == 1) {
|
||||
d->state = 5;
|
||||
d->tojump = 0;
|
||||
|
||||
PHL_PlaySound(sounds[sndHit04], CHN_ENEMIES);
|
||||
quakeTimer = 30;
|
||||
createEffectExtra(3, d->x - 30, d->y + 50, -1, 0, 0);
|
||||
createEffectExtra(3, d->x - 10, d->y + 50, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Windup
|
||||
if (d->state == 3)
|
||||
{
|
||||
//Set image
|
||||
imgspd = 0;
|
||||
d->imageIndex = 0;
|
||||
|
||||
//Jump
|
||||
if (d->timer <= 0) {
|
||||
d->state = 2;
|
||||
PHL_PlaySound(sounds[sndJump01], CHN_ENEMIES);
|
||||
if (d->jumptoggle == 0) {
|
||||
d->jumptoggle = 1;
|
||||
d->vsp = -3;
|
||||
d->hsp = 2 * d->dir;
|
||||
}else{
|
||||
d->jumptoggle = 0;
|
||||
d->hsp = 1.5 * d->dir;
|
||||
d->vsp = -6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Slide to a stop
|
||||
else if (d->state == 5)
|
||||
{
|
||||
//Friction
|
||||
{
|
||||
if (d->hsp > 0) {
|
||||
d->hsp -= fric;
|
||||
if (d->hsp <= 0) {
|
||||
d->hsp = 0;
|
||||
}
|
||||
}
|
||||
else if (d->hsp < 0) {
|
||||
d->hsp += fric;
|
||||
if (d->hsp >= 0) {
|
||||
d->hsp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Go to idle
|
||||
{
|
||||
if (d->hsp == 0) {
|
||||
d->state = 0;
|
||||
d->timer = 140;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Fall
|
||||
if (d->state == 6)
|
||||
{
|
||||
//Set image
|
||||
imgspd = 0;
|
||||
d->imageIndex = 0;
|
||||
|
||||
//Face hsp
|
||||
{
|
||||
if (d->hsp > 0) {
|
||||
d->dir = 1;
|
||||
}
|
||||
if (d->hsp < 0) {
|
||||
d->dir = -1;
|
||||
}
|
||||
}
|
||||
|
||||
//Land
|
||||
{
|
||||
if (d->onground == 1) {
|
||||
d->state = 5;
|
||||
d->tojump = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Death
|
||||
if (d->state == 7)
|
||||
{
|
||||
imgspd = 0.2;
|
||||
frames = 4;
|
||||
|
||||
//Movement
|
||||
d->y += 0.2;
|
||||
|
||||
if (d->blink % 12 == 0) {
|
||||
createEffect(2, d->x - 72 + (rand() % 80), d->y - 12 + (rand() % 76));
|
||||
}
|
||||
|
||||
if (d->blink <= 0) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
else{
|
||||
//Horizontal movement
|
||||
{
|
||||
if (d->hsp != 0) {
|
||||
d->x += d->hsp;
|
||||
|
||||
//Wall collision
|
||||
if (d->state != 6) {
|
||||
if (dodoWallCollision(d, mask) == 1) {
|
||||
d->hsp *= -1;
|
||||
if (d->state == 1) {
|
||||
d->state = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Vertical movement
|
||||
{
|
||||
if (d->vsp != 0) {
|
||||
d->y += d->vsp;
|
||||
|
||||
mask = updateDodoMask(d, mask);
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
if (d->vsp < 0) {
|
||||
d->y = collide.y + 40 - (96 - 14 - mask.h);
|
||||
}
|
||||
else if (d->vsp > 0) {
|
||||
d->y = collide.y - 96 + 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check if onground
|
||||
mask = updateDodoMask(d, mask);
|
||||
mask.y += 1;
|
||||
if (!checkTileCollision(1, mask)) {
|
||||
d->onground = 0;
|
||||
}else{
|
||||
d->onground = 1;
|
||||
}
|
||||
mask.y -= 1;
|
||||
|
||||
//Gravity
|
||||
{
|
||||
if (d->onground == 0) {
|
||||
d->vsp += d->grav;
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
//Hit
|
||||
d->blink = 15;
|
||||
d->hp -= 1;
|
||||
|
||||
//Death
|
||||
if (d->hp <= 0) {
|
||||
d->state = 7;
|
||||
d->blink = 180;
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Hit Player
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(30, d->x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Animate
|
||||
{
|
||||
if (imgspd != 0) {
|
||||
d->imageIndex += imgspd;
|
||||
|
||||
if (d->imageIndex >= frames) {
|
||||
d->imageIndex -= frames;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy object
|
||||
{
|
||||
if (dead == 1) {
|
||||
//Is the level 1 boss
|
||||
if (d->flag == boss1flag) {
|
||||
bossDefeatedFlag = 1;
|
||||
PHL_StopMusic();
|
||||
}
|
||||
|
||||
roomSecret = 1;
|
||||
flags[d->flag] = 1;
|
||||
enemyDestroy(d->id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void dodoDraw(Dodo* d)
|
||||
{
|
||||
//PHL_DrawMask(d->mask);
|
||||
if (d->blink % 2 == 0) {
|
||||
int cropX = 0,
|
||||
cropY = 0;
|
||||
|
||||
int dirW = 0;
|
||||
|
||||
//Idle
|
||||
if (d->state == 0) {
|
||||
dirW = 0;
|
||||
int frame = 0;
|
||||
|
||||
if (d->dir == 1) {
|
||||
int animation[4] = {0, 6, 7, 6};
|
||||
frame = animation[(int)d->imageIndex];
|
||||
}else{
|
||||
int animation[4] = {3, 8, 9, 8};
|
||||
frame = animation[(int)d->imageIndex];
|
||||
}
|
||||
|
||||
cropX = frame * 96;
|
||||
|
||||
while (cropX >= 576) {
|
||||
cropX -= 576;
|
||||
cropY += 96;
|
||||
}
|
||||
}
|
||||
|
||||
//Chase
|
||||
else if (d->state == 1 || d->state == 7) {
|
||||
dirW = 288;
|
||||
int animation[4] = {0, 1, 0, 2};
|
||||
|
||||
cropX = animation[(int)d->imageIndex] * 96;
|
||||
}
|
||||
|
||||
//Jump
|
||||
else if (d->state == 2) {
|
||||
dirW = 192;
|
||||
|
||||
cropY = 192;
|
||||
cropX = (int)d->imageIndex * 96;
|
||||
}
|
||||
|
||||
//Turn around
|
||||
else if (d->state == 4) {
|
||||
dirW = 0;
|
||||
cropY = 288;
|
||||
|
||||
if (d->dir == 1) {
|
||||
int animation[3] = {0, 1, 2};
|
||||
cropX = animation[(int)d->imageIndex] * 96;
|
||||
}else{
|
||||
int animation[3] = {2, 1, 0};
|
||||
cropX = animation[(int)d->imageIndex] * 96;
|
||||
}
|
||||
}
|
||||
|
||||
//Duck
|
||||
else if (d->state == 3 || d->state == 5 || d->state == 6) {
|
||||
dirW = 192;
|
||||
|
||||
cropX = 0;
|
||||
cropY = 192;
|
||||
}
|
||||
|
||||
//Direction offset
|
||||
{
|
||||
if (dirW != 0 && d->dir == -1) {
|
||||
cropX += dirW;
|
||||
}
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(d->x - 48, d->y, cropX, cropY, 96, 96, images[imgBoss]);
|
||||
}
|
||||
}
|
||||
|
||||
Mask updateDodoMask(Dodo* d, Mask mask)
|
||||
{
|
||||
mask.x = d->x - (mask.w / 2);
|
||||
mask.y = d->y + (96 - 14 - mask.h);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
int dodoWallCollision(Dodo* d, Mask mask)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
mask = updateDodoMask(d, mask);
|
||||
|
||||
//Stay inside of room
|
||||
if (d->x < 24) {
|
||||
result = 1;
|
||||
d->x = 24;
|
||||
}
|
||||
else if (d->x > 616) {
|
||||
result = 1;
|
||||
d->x = 616;
|
||||
}
|
||||
else{
|
||||
//Tile collision
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
result = 1;
|
||||
if (d->hsp > 0) {
|
||||
d->x = collide.x - (mask.w / 2);
|
||||
}else{
|
||||
d->x = collide.x + 40 + (mask.w / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
22
contrib/games/hydracastlelabyrinth/src/enemies/dodo.h
Normal file
22
contrib/games/hydracastlelabyrinth/src/enemies/dodo.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef DODO_H
|
||||
#define DODO_H
|
||||
|
||||
#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double vsp, hsp, grav;
|
||||
int dir, onground;
|
||||
double imageIndex;
|
||||
int state, timer, hp;
|
||||
int blink;
|
||||
int tojump, jumptoggle;
|
||||
int flag;
|
||||
|
||||
//Mask mask;
|
||||
} Dodo;
|
||||
|
||||
void createDodo(int x, int y, int flag);
|
||||
|
||||
#endif
|
294
contrib/games/hydracastlelabyrinth/src/enemies/dog.c
Normal file
294
contrib/games/hydracastlelabyrinth/src/enemies/dog.c
Normal file
@ -0,0 +1,294 @@
|
||||
#include "dog.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void dogStep(Dog* d);
|
||||
void dogDraw(Dog* d);
|
||||
|
||||
int hitWall(Dog* d, Mask mask);
|
||||
|
||||
void createDog(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Dog* d = malloc(sizeof *d);
|
||||
d->id = i;
|
||||
d->hp = 3;
|
||||
d->blink = 0;
|
||||
|
||||
d->x = x;
|
||||
d->y = y;
|
||||
|
||||
d->hsp = 0;
|
||||
d->vsp = 0;
|
||||
|
||||
d->imageIndex = 0;
|
||||
|
||||
d->dir = 1;
|
||||
if (herox < d->x) {
|
||||
d->dir = -1;
|
||||
}
|
||||
|
||||
d->state = 0;
|
||||
d->timer = 0;
|
||||
d->counter = 0;
|
||||
|
||||
e->data = d;
|
||||
e->enemyStep = dogStep;
|
||||
e->enemyDraw = dogDraw;
|
||||
e->type = 30;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dogStep(Dog* d)
|
||||
{
|
||||
double grav = 0.175;
|
||||
|
||||
char onground = 0;
|
||||
char wallhit = 0;
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 32;
|
||||
mask.h = 32;
|
||||
mask.x = d->x + ((40 - mask.w) / 2);
|
||||
mask.y = d->y + (40 - mask.h);
|
||||
}
|
||||
|
||||
//Blink animation
|
||||
{
|
||||
if (d->blink > 0) {
|
||||
d->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Horizontal movement
|
||||
{
|
||||
d->x += d->hsp;
|
||||
mask.x = d->x + ((40 - mask.w) / 2);
|
||||
|
||||
//Wall collision
|
||||
if (hitWall(d, mask) == 1) {
|
||||
wallhit = 1;
|
||||
mask.x = d->x + ((40 - mask.w) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
//Vertical Movement
|
||||
{
|
||||
d->vsp += grav;
|
||||
d->y += d->vsp;
|
||||
mask.y = d->y + (40 - mask.h);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
if (collide.x != -1) {
|
||||
//Floor
|
||||
if (d->vsp >= 0) {
|
||||
onground = 1;
|
||||
d->vsp = 0;
|
||||
d->y = collide.y - 40;
|
||||
}
|
||||
//Ceiling
|
||||
if (d->vsp < 0) {
|
||||
d->y = collide.y + 40 - (40 - mask.h);
|
||||
}
|
||||
mask.y = d->y + (40 - mask.h);
|
||||
}
|
||||
}
|
||||
|
||||
//Wait
|
||||
if (d->state == 0)
|
||||
{
|
||||
double fric = 0.1;
|
||||
|
||||
//Animate
|
||||
{
|
||||
d->imageIndex += 0.1;
|
||||
if (d->imageIndex >= 2) {
|
||||
d->imageIndex -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Collide with wall
|
||||
{
|
||||
if (wallhit == 1 && onground == 1) {
|
||||
d->hsp *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
//Slide to hault
|
||||
if (d->hsp > 0) {
|
||||
d->dir = 1;
|
||||
|
||||
d->hsp -= fric;
|
||||
if (d->hsp <= 0) {
|
||||
d->hsp = 0;
|
||||
}
|
||||
}
|
||||
if (d->hsp < 0) {
|
||||
d->dir = -1;
|
||||
|
||||
d->hsp += fric;
|
||||
if (d->hsp >= 0) {
|
||||
d->hsp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Player is close
|
||||
{
|
||||
if (d->hsp == 0) {
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.w = 220;
|
||||
area.h = 60;
|
||||
area.x = d->x - 90;
|
||||
area.y = d->y - 20;
|
||||
|
||||
if (checkCollision(area, getHeroMask()) == 1) {
|
||||
d->state = 1;
|
||||
d->counter = 0;
|
||||
d->vsp = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Hopping
|
||||
else if (d->state == 1)
|
||||
{
|
||||
int spd = 2;
|
||||
|
||||
d->hsp = spd * d->dir;
|
||||
|
||||
//Land on floor
|
||||
{
|
||||
if (onground == 1) {
|
||||
|
||||
//Landed
|
||||
d->counter += 1;
|
||||
d->vsp = -1.5;
|
||||
if (d->counter == 3) {
|
||||
d->vsp = -4;
|
||||
}
|
||||
if (d->counter == 4) {
|
||||
d->state = 0;
|
||||
d->counter = 0;
|
||||
d->vsp = 0;
|
||||
d->hsp = spd * d->dir;
|
||||
}else{
|
||||
PHL_PlaySound(sounds[sndPi05], CHN_ENEMIES);
|
||||
d->dir = 1;
|
||||
if (herox < d->x + 20) {
|
||||
d->dir = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Animate
|
||||
{
|
||||
d->imageIndex = 1;
|
||||
if (d->vsp < 0) {
|
||||
d->imageIndex = 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Update mask to be safe
|
||||
mask.x = d->x + ((40 - mask.w) / 2);
|
||||
mask.y = d->y + (40 - mask.h);
|
||||
|
||||
//Hit Player
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
if (heroHit(10, mask.x + (mask.w / 2)) == 1) {
|
||||
heroStun();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
//Hit
|
||||
d->blink = 15;
|
||||
d->hp -= 1;
|
||||
|
||||
//Death
|
||||
if (d->hp <= 0) {
|
||||
createEffect(2, d->x - 12, d->y - 6);
|
||||
spawnCollectable(d->x + 20, d->y);
|
||||
enemyDestroy(d->id);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void dogDraw(Dog* d)
|
||||
{
|
||||
if (d->blink % 2 == 0) {
|
||||
int cropX = 240 + ((int)d->imageIndex * 40);
|
||||
|
||||
if (d->dir == -1) {
|
||||
cropX += 120;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(d->x, d->y, cropX, 40, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
||||
|
||||
int hitWall(Dog* d, Mask mask)
|
||||
{
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
if (collide.x != -1) {
|
||||
int dir = 1;
|
||||
if (d->hsp < 0) {
|
||||
dir = -1;
|
||||
}
|
||||
d->x = collide.x + 20 - ((20 + (mask.w / 2)) * dir) - 20;
|
||||
|
||||
return 1;
|
||||
}else{
|
||||
if (d->x < -20) {
|
||||
d->x = -20;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (d->x > 620) {
|
||||
d->x = 620;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
17
contrib/games/hydracastlelabyrinth/src/enemies/dog.h
Normal file
17
contrib/games/hydracastlelabyrinth/src/enemies/dog.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef DOG_H
|
||||
#define DOG_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
int blink;
|
||||
double x, y;
|
||||
double vsp, hsp;
|
||||
double imageIndex;
|
||||
int dir;
|
||||
int state, timer, counter;
|
||||
} Dog;
|
||||
|
||||
void createDog(int x, int y);
|
||||
|
||||
#endif
|
272
contrib/games/hydracastlelabyrinth/src/enemies/firewheel.c
Normal file
272
contrib/games/hydracastlelabyrinth/src/enemies/firewheel.c
Normal file
@ -0,0 +1,272 @@
|
||||
#include "firewheel.h"
|
||||
#include "../game.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void firewheelRotate(Firewheel* f, int clockwise);
|
||||
|
||||
void firewheelStep(Firewheel* f);
|
||||
void firewheelDraw(Firewheel* f);
|
||||
|
||||
void createFirewheel(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Firewheel* f = malloc(sizeof *f);
|
||||
|
||||
f->id = i;
|
||||
|
||||
f->x = x;
|
||||
f->y = y;
|
||||
|
||||
f->imageIndex = 0;
|
||||
|
||||
f->hp = 2;
|
||||
f->blink = 0;
|
||||
|
||||
f->hsp = 1;
|
||||
f->vsp = 0;
|
||||
|
||||
f->wallx = 0;
|
||||
f->wally = 1;
|
||||
|
||||
f->timer = 0;
|
||||
if (x % 40 != 0) {
|
||||
f->timer = 20;
|
||||
}
|
||||
|
||||
//Start on ceiling
|
||||
{
|
||||
Mask mask;
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 40;
|
||||
mask.h = 40;
|
||||
mask.x = f->x;
|
||||
mask.y = f->y + 10;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
if (collide.x == -1) {
|
||||
f->wally = -1;
|
||||
f->hsp *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
f->dir = 1;
|
||||
if (dir == 1) {
|
||||
f->hsp *= -1;
|
||||
f->dir = -1;
|
||||
}
|
||||
|
||||
e->data = f;
|
||||
e->enemyStep = firewheelStep;
|
||||
e->enemyDraw = firewheelDraw;
|
||||
e->type = 27;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void firewheelStep(Firewheel* f)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
f->imageIndex += 0.33;
|
||||
if (f->imageIndex >= 4) {
|
||||
f->imageIndex -= 4;
|
||||
}
|
||||
|
||||
if (f->blink > 0) {
|
||||
f->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
int spd = 2;
|
||||
f->x += spd * f->hsp;
|
||||
f->y += spd * f->vsp;
|
||||
|
||||
//Setup mask
|
||||
Mask mask;
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 40;
|
||||
mask.h = 40;
|
||||
mask.x = f->x;
|
||||
mask.y = f->y;
|
||||
|
||||
//Check if ready to change angle
|
||||
if ( (f->hsp != 0 && (int)f->x % 20 == 0) || (f->vsp != 0 && (int)f->y % 20 == 0) )
|
||||
{
|
||||
int doCheck = 1;
|
||||
while (doCheck == 1) {
|
||||
doCheck = 0;
|
||||
|
||||
//Check on edge
|
||||
mask.x += (f->wallx * 10);
|
||||
mask.y += (f->wally * 10);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
//Outside of room
|
||||
if (f->y <= -40) {
|
||||
collide.x = 1;
|
||||
}
|
||||
|
||||
//On edge
|
||||
if (collide.x == -1) {
|
||||
int tempHsp = f->hsp;
|
||||
int tempVsp = f->vsp;
|
||||
f->hsp = f->wallx;
|
||||
f->vsp = f->wally;
|
||||
|
||||
f->wallx = -tempHsp;
|
||||
f->wally = -tempVsp;
|
||||
doCheck = 1;
|
||||
}
|
||||
//Hit wall
|
||||
else {
|
||||
mask.x = f->x;
|
||||
mask.y = f->y;
|
||||
mask.x += f->hsp * 10;
|
||||
mask.y += f->vsp * 10;
|
||||
|
||||
collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
//Outside of room
|
||||
if (collide.x == -1) {
|
||||
if (f->y <= -40 && f->vsp != 1) {
|
||||
collide.x = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Did collide with wall
|
||||
if (collide.x != -1) {
|
||||
int tempWallx = f->wallx;
|
||||
int tempWally = f->wally;
|
||||
f->wallx = f->hsp;
|
||||
f->wally = f->vsp;
|
||||
|
||||
f->hsp = -tempWallx;
|
||||
f->vsp = -tempWally;
|
||||
|
||||
doCheck = 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
mask.x += f->hsp * 10;
|
||||
mask.y += f->vsp * 10;
|
||||
|
||||
//Collide with wall
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
//Outside of room
|
||||
if (collide.x == -1) {
|
||||
if (mask.y <= 0 && f->vsp < 0) {
|
||||
collide.x = f->x;
|
||||
collide.y = -40;
|
||||
collide.w = 40;
|
||||
collide.h = 40;
|
||||
}
|
||||
}
|
||||
|
||||
//Did collide with wall
|
||||
if (collide.x != -1) {
|
||||
int tempWallx = f->wallx;
|
||||
int tempWally = f->wally;
|
||||
f->wallx = f->hsp;
|
||||
f->wally = f->vsp;
|
||||
|
||||
f->hsp = -tempWallx;
|
||||
f->vsp = -tempWally;
|
||||
}
|
||||
//Edge rotate
|
||||
else{
|
||||
mask.x = f->x;
|
||||
mask.y = f->y;
|
||||
mask.x += (f->wallx * 10);
|
||||
mask.y += (f->wally * 10);
|
||||
|
||||
collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
if (collide.x == -1) {
|
||||
int tempHsp = f->hsp;
|
||||
int tempVsp = f->vsp;
|
||||
f->hsp = f->wallx;
|
||||
f->vsp = f->wally;
|
||||
|
||||
f->wallx = -tempHsp;
|
||||
f->wally = -tempVsp;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
mask.w = 30;
|
||||
mask.h = 30;
|
||||
mask.x = f->x + 5;
|
||||
mask.y = f->y + 5;
|
||||
|
||||
//Collide with hero
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(20, mask.x + (mask.w / 2));
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
for (int i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
f->hp -= 1;
|
||||
f->blink = 15;
|
||||
|
||||
//Death
|
||||
if (f->hp <= 0) {
|
||||
createEffect(2, f->x - 12, f->y - 12);
|
||||
spawnCollectable(f->x + 20, f->y);
|
||||
enemyDestroy(f->id);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void firewheelDraw(Firewheel* f)
|
||||
{
|
||||
if (f->blink % 2 == 0) {
|
||||
int cy = 80;
|
||||
if (f->dir == -1) {
|
||||
cy += 40;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(f->x, f->y, 480 + ((int)f->imageIndex * 40), cy, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
18
contrib/games/hydracastlelabyrinth/src/enemies/firewheel.h
Normal file
18
contrib/games/hydracastlelabyrinth/src/enemies/firewheel.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef FIREWHEEL_H
|
||||
#define FIREWHEEL_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double imageIndex;
|
||||
int hp;
|
||||
int blink;
|
||||
int dir;
|
||||
int hsp, vsp;
|
||||
int wallx, wally;
|
||||
int timer;
|
||||
} Firewheel;
|
||||
|
||||
void createFirewheel(int x, int y, int dir);
|
||||
|
||||
#endif
|
139
contrib/games/hydracastlelabyrinth/src/enemies/fish.c
Normal file
139
contrib/games/hydracastlelabyrinth/src/enemies/fish.c
Normal file
@ -0,0 +1,139 @@
|
||||
#include "fish.h"
|
||||
#include "../game.h"
|
||||
#include "../enemy.h"
|
||||
#include "../PHL.h"
|
||||
#include "../collision.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void createFish(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Fish* f = malloc(sizeof *f);
|
||||
f->id = i;
|
||||
|
||||
f->x = f->xstart = x;
|
||||
f->y = y;
|
||||
|
||||
f->imageIndex = 0;
|
||||
|
||||
f->spd = 1;
|
||||
|
||||
f->turning = 0;
|
||||
f->dir = 1;
|
||||
if (dir == 1) {
|
||||
f->dir = -1;
|
||||
f->spd = -1;
|
||||
}
|
||||
|
||||
f->mask.circle = f->mask.unused = 0;
|
||||
f->mask.x = x + 3;
|
||||
f->mask.y = y + 6;
|
||||
f->mask.w = 34;
|
||||
f->mask.h = 32;
|
||||
|
||||
e->data = f;
|
||||
e->enemyStep = fishStep;
|
||||
e->enemyDraw = fishDraw;
|
||||
e->type = 13;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fishStep(Fish* f)
|
||||
{
|
||||
double fric = 0.02;
|
||||
|
||||
f->x += f->spd;
|
||||
f->mask.x = f->x + 3;
|
||||
|
||||
if (f->turning == 0) {
|
||||
f->imageIndex += 0.1;
|
||||
if (f->imageIndex >= 2) {
|
||||
f->imageIndex -= 2;
|
||||
}
|
||||
}else{
|
||||
f->imageIndex += 0.25;
|
||||
if (f->imageIndex >= 3) {
|
||||
f->turning = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (f->dir == 1) {
|
||||
if (f->x > f->xstart + 25) {
|
||||
f->spd -= fric;
|
||||
|
||||
if (f->spd < 0) {
|
||||
f->dir = -1;
|
||||
f->turning = 1;
|
||||
f->imageIndex = 0;
|
||||
}
|
||||
}else{
|
||||
f->spd += fric;
|
||||
if (f->spd > 1) {
|
||||
f->spd = 1;
|
||||
}
|
||||
}
|
||||
}else if (f->dir == -1) {
|
||||
if (f->x < f->xstart - 25) {
|
||||
f->spd += fric;
|
||||
|
||||
if (f->spd > 0) {
|
||||
f->dir = 1;
|
||||
f->turning = 1;
|
||||
f->imageIndex = 0;
|
||||
}
|
||||
}else{
|
||||
f->spd -= fric;
|
||||
if (f->spd < -1) {
|
||||
f->spd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checkCollision(f->mask, getHeroMask())) {
|
||||
heroHit(15, f->x + 20);
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(f->mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
createEffect(2, f->x - 12, f->y - 12);
|
||||
spawnCollectable(f->x + 20, f->y);
|
||||
enemyDestroy(f->id);
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fishDraw(Fish* f)
|
||||
{
|
||||
int thisImage = 0;
|
||||
if (f->turning == 1) {
|
||||
if (f->dir == -1) {
|
||||
int animation[3] = {4, 6, 5};
|
||||
thisImage = animation[(int)f->imageIndex];
|
||||
}else{
|
||||
int animation[3] = {5, 6, 4};
|
||||
thisImage = animation[(int)f->imageIndex];
|
||||
}
|
||||
}else{
|
||||
thisImage = f->imageIndex;
|
||||
if (f->spd < 0) {
|
||||
thisImage += 2;
|
||||
}
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(f->x, f->y, 360 + (thisImage * 40), 360, 40, 40, images[imgEnemies]);
|
||||
}
|
24
contrib/games/hydracastlelabyrinth/src/enemies/fish.h
Normal file
24
contrib/games/hydracastlelabyrinth/src/enemies/fish.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef FISH_H
|
||||
#define FISH_H
|
||||
|
||||
#include "../enemy.h"
|
||||
#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
|
||||
double x, y;
|
||||
int xstart;
|
||||
double imageIndex;
|
||||
double spd;
|
||||
int dir, turning;
|
||||
|
||||
Mask mask;
|
||||
} Fish;
|
||||
|
||||
void createFish(int x, int y, int dir);
|
||||
|
||||
void fishStep(Fish* f);
|
||||
void fishDraw(Fish* f);
|
||||
|
||||
#endif
|
578
contrib/games/hydracastlelabyrinth/src/enemies/garm.c
Normal file
578
contrib/games/hydracastlelabyrinth/src/enemies/garm.c
Normal file
@ -0,0 +1,578 @@
|
||||
#include "garm.h"
|
||||
#include "../game.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
int boss7flag = 47;
|
||||
|
||||
void garmStep(Garm* g);
|
||||
void garmDraw(Garm* g);
|
||||
|
||||
void garmrockStep(Garmrock* g);
|
||||
void garmrockDraw(Garmrock* g);
|
||||
|
||||
void createGarm(int x, int y)
|
||||
{
|
||||
if (flags[boss7flag] == 0) { //have not beaten boss 7
|
||||
PHL_FreeSurface(images[imgBoss]);
|
||||
images[imgBoss] = PHL_LoadQDA("boss07.bmp");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
setBossRoom();
|
||||
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Garm* g = malloc(sizeof *g);
|
||||
|
||||
g->id = i;
|
||||
|
||||
g->hp = 105;
|
||||
//g->hp = 1;
|
||||
|
||||
g->x = x;
|
||||
g->y = y;
|
||||
|
||||
g->hsp = 0;
|
||||
g->vsp = 0;
|
||||
|
||||
g->dir = -1;
|
||||
|
||||
g->imageIndex = 0;
|
||||
|
||||
g->state = 0;
|
||||
g->timer = 0;
|
||||
|
||||
g->blink = 0;
|
||||
|
||||
g->substate = 0;
|
||||
g->wallcounter = 0;
|
||||
g->targx = 0;
|
||||
|
||||
e->data = g;
|
||||
e->enemyStep = garmStep;
|
||||
e->enemyDraw = garmDraw;
|
||||
e->type = 46;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void garmStep(Garm* g)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Blink animation
|
||||
{
|
||||
if (g->blink > 0) {
|
||||
g->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 88;
|
||||
mask.h = 104;
|
||||
mask.x = g->x - (mask.w / 2);
|
||||
mask.y = g->y + (120 - mask.h);
|
||||
}
|
||||
|
||||
//Stand still
|
||||
if (g->state == 0)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
g->imageIndex += 0.0625;
|
||||
if (g->imageIndex >= 2) {
|
||||
g->imageIndex -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
//End state
|
||||
{
|
||||
g->timer += 1;
|
||||
if (g->timer >= 60) {
|
||||
g->state = 1;
|
||||
//g->vsp = -4.5;
|
||||
g->counter = 0;
|
||||
g->timer = 0;
|
||||
//PHL_PlaySound(sounds[sndPi09], CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Bounce
|
||||
else if (g->state == 1)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
g->imageIndex += 0.33;
|
||||
if (g->imageIndex >= 3) {
|
||||
g->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (g->timer > 0) {
|
||||
g->vsp = 0;
|
||||
g->imageIndex = 0;
|
||||
g->timer -= 1;
|
||||
if (g->timer <= 0) {
|
||||
//End state
|
||||
if (g->counter >= 3) {
|
||||
g->state = 2;
|
||||
g->counter = 0;
|
||||
g->imageIndex = 0;
|
||||
g->vsp = -6;
|
||||
g->hsp = 8;
|
||||
if (g->x > herox) {
|
||||
g->hsp *= -1;
|
||||
}
|
||||
|
||||
if (g->substate == 0) {
|
||||
g->wallcounter = 1;
|
||||
g->substate = 1;
|
||||
}else{
|
||||
g->wallcounter = 2;
|
||||
g->substate = 0;
|
||||
}
|
||||
}else{
|
||||
g->vsp = -5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (g->timer == 0) {
|
||||
double grav = 0.25;
|
||||
|
||||
//Movement
|
||||
if (g->timer == 0) {
|
||||
g->y += g->vsp;
|
||||
g->vsp += grav;
|
||||
mask.y = g->y + (120 - mask.h);
|
||||
}
|
||||
|
||||
//Land on ground
|
||||
if (g->vsp >= 0 && g->timer == 0) {
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
g->y = collide.y - 120;
|
||||
mask.y = g->y + (120 - mask.h);
|
||||
g->vsp = 0;
|
||||
g->timer = 3;
|
||||
g->counter += 1;
|
||||
PHL_PlaySound(sounds[sndPi09], CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Leap towards wall
|
||||
else if (g->state == 2)
|
||||
{
|
||||
double grav = 0.25;
|
||||
|
||||
//Set image
|
||||
{
|
||||
if (g->hsp > 0) {
|
||||
g->imageIndex = 0;
|
||||
}
|
||||
|
||||
if (g->hsp < 0) {
|
||||
g->imageIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
g->y += g->vsp;
|
||||
g->vsp += grav;
|
||||
mask.y = g->y + (120 - mask.h);
|
||||
|
||||
g->x += g->hsp;
|
||||
mask.x = g->x - (mask.w / 2);
|
||||
}
|
||||
|
||||
if (g->wallcounter > 0)
|
||||
{
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
g->wallcounter -= 1;
|
||||
if (g->hsp < 0) {
|
||||
g->x = collide.x + 40 + (mask.w / 2);
|
||||
}
|
||||
if (g->hsp > 0) {
|
||||
g->x = collide.x - (mask.w / 2);
|
||||
}
|
||||
g->state = 3;
|
||||
g->timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Ground pound
|
||||
else {
|
||||
char action = 0;
|
||||
|
||||
if ( (g->hsp > 0 && g->x > g->targx) || (g->hsp < 0 && g->x < g->targx) ) {
|
||||
action = 1;
|
||||
}
|
||||
//Wall collision backup
|
||||
else{
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
if (g->hsp < 0) {
|
||||
g->x = collide.x + 40 + (mask.w / 2);
|
||||
}
|
||||
if (g->hsp > 0) {
|
||||
g->x = collide.x - (mask.w / 2);
|
||||
}
|
||||
action = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (action == 1) {
|
||||
g->state = 4;
|
||||
g->vsp = -4;
|
||||
PHL_PlaySound(sounds[sndWolf01], CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Grab wall
|
||||
else if (g->state == 3)
|
||||
{
|
||||
g->timer += 1;
|
||||
if (g->timer > 5) {
|
||||
g->state = 2;
|
||||
g->vsp = -6;
|
||||
g->hsp *= -1;
|
||||
PHL_PlaySound(sounds[sndPi09], CHN_ENEMIES);
|
||||
|
||||
g->targx = herox;
|
||||
|
||||
if (g->wallcounter <= 0) {
|
||||
//Get distance from player
|
||||
int dis = g->x - g->targx;
|
||||
{
|
||||
if (dis < 0) {
|
||||
dis *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dis < 200 || g->substate == 1) {
|
||||
g->hsp /= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Ground pound
|
||||
else if (g->state == 4)
|
||||
{
|
||||
double grav = 0.2;
|
||||
|
||||
//Animate
|
||||
{
|
||||
g->imageIndex += 0.33;
|
||||
if (g->imageIndex >= 3) {
|
||||
g->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
g->y += g->vsp;
|
||||
g->vsp += grav;
|
||||
mask.y = g->y + (120 - mask.h);
|
||||
|
||||
//Collide with floor
|
||||
{
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
|
||||
if (collide.x != -1) {
|
||||
g->y = collide.y - 120;
|
||||
PHL_PlaySound(sounds[sndHit04], CHN_ENEMIES);
|
||||
quakeTimer = 30;
|
||||
g->state = 0;
|
||||
g->timer = -20;
|
||||
//Create rocks
|
||||
createGarmrock(g->x + 64, g->y + 100, 2, -4);
|
||||
createGarmrock(g->x + 34, g->y + 100, 1, -5);
|
||||
createGarmrock(g->x - 34, g->y + 100, -1, -5);
|
||||
createGarmrock(g->x - 64, g->y + 100, -2, -4);
|
||||
|
||||
createEffectExtra(3, g->x - 50, g->y + 90, -1, 0, 0);
|
||||
createEffectExtra(3, g->x + 10, g->y + 90, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Dead
|
||||
if (g->state == 5) {
|
||||
//Animate
|
||||
{
|
||||
g->imageIndex += 0.33;
|
||||
if (g->imageIndex >= 3) {
|
||||
g->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
g->y += 0.2;
|
||||
|
||||
if (g->blink % 12 == 0) {
|
||||
createEffect(2, g->x - 64 + (rand() % 100), g->y + 60 - 64 + (rand() % 80));
|
||||
}
|
||||
|
||||
if (g->blink <= 0) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
else{
|
||||
if (dead == 0) {
|
||||
//Update Mask
|
||||
{
|
||||
mask.x = g->x - (mask.w / 2);
|
||||
mask.y = g->y + (120 - mask.h);
|
||||
}
|
||||
|
||||
//Hero collision
|
||||
{
|
||||
if (checkCollision(getHeroMask(), mask) == 1) {
|
||||
heroHit(40, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
g->hp -= 1;
|
||||
g->blink = 15;
|
||||
//Dead
|
||||
if (g->hp <= 0) {
|
||||
g->state = 5;
|
||||
g->blink = 200;
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (dead == 1) {
|
||||
//Destroy
|
||||
{
|
||||
enemyDestroy(g->id);
|
||||
bossDefeatedFlag = 1;
|
||||
roomSecret = 1;
|
||||
|
||||
flags[boss7flag] = 1;
|
||||
PHL_StopMusic();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void garmDraw(Garm* g)
|
||||
{
|
||||
if (g->blink % 2 == 0) {
|
||||
int cropX = 0,
|
||||
cropY = 0;
|
||||
|
||||
//Jump Spinning
|
||||
if ((g->state == 1 && g->timer == 0) || g->state == 4 || g->state == 5) {
|
||||
cropY = 128;
|
||||
cropX = 256;
|
||||
}
|
||||
|
||||
//Jump
|
||||
if (g->state == 2) {
|
||||
cropY = 128;
|
||||
}
|
||||
|
||||
//Wall grab
|
||||
if (g->state == 3) {
|
||||
cropX = 384;
|
||||
}
|
||||
|
||||
cropX += (int)g->imageIndex * 128;
|
||||
|
||||
PHL_DrawSurfacePart(g->x - 64, g->y - 8, cropX, cropY, 128, 128, images[imgBoss]);
|
||||
}
|
||||
}
|
||||
|
||||
//Rocks
|
||||
void createGarmrock(int x, int y, double hsp, double vsp)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Garmrock* g = malloc(sizeof *g);
|
||||
|
||||
g->id = i;
|
||||
g->hp = 3;
|
||||
|
||||
g->x = x;
|
||||
g->y = y;
|
||||
|
||||
g->hsp = hsp;
|
||||
g->vsp = vsp;
|
||||
|
||||
g->imageIndex = 0;
|
||||
|
||||
g->counter = 0;
|
||||
g->inwall = 0;
|
||||
g->blink = 0;
|
||||
|
||||
e->data = g;
|
||||
e->enemyStep = garmrockStep;
|
||||
e->enemyDraw = garmrockDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void garmrockStep(Garmrock* g)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 44;
|
||||
mask.h = 44;
|
||||
mask.x = g->x - (mask.w / 2);
|
||||
mask.y = g->y - (mask.h / 2);
|
||||
}
|
||||
|
||||
//Animate
|
||||
{
|
||||
g->imageIndex += 0.2;
|
||||
if (g->imageIndex >= 4) {
|
||||
g->imageIndex -= 4;
|
||||
}
|
||||
|
||||
if (g->blink > 0) {
|
||||
g->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Horizontal movement
|
||||
{
|
||||
g->x += g->hsp;
|
||||
mask.x = g->x - (mask.w / 2);
|
||||
|
||||
g->inwall = 0;
|
||||
if (checkTileCollision(1, mask) == 1) {
|
||||
g->inwall = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Vertical movement
|
||||
{
|
||||
double grav = 0.1;
|
||||
|
||||
g->y += g->vsp;
|
||||
g->vsp += grav;
|
||||
mask.y = g->y - (mask.h / 2);
|
||||
|
||||
if (g->inwall == 0 && g->counter == 0) {
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
g->counter = 1;
|
||||
g->y = collide.y - (mask.h / 2);
|
||||
g->vsp = -2;
|
||||
PHL_PlaySound(sounds[sndHit06], CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Update mask
|
||||
{
|
||||
mask.x = g->x - (mask.w / 2);
|
||||
mask.y = g->y - (mask.h / 2);
|
||||
}
|
||||
|
||||
//Hero collision
|
||||
{
|
||||
if (checkCollision(getHeroMask(), mask) == 1) {
|
||||
heroHit(30, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
g->hp -= 1;
|
||||
g->blink = 15;
|
||||
|
||||
if (g->hp <= 0) {
|
||||
dead = 1;
|
||||
createRockSmash(g->x, g->y + 20);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy when out of room
|
||||
{
|
||||
if (mask.y > 480) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy object
|
||||
{
|
||||
if (dead == 1) {
|
||||
enemyDestroy(g->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void garmrockDraw(Garmrock* g)
|
||||
{
|
||||
if (g->blink % 2 == 0) {
|
||||
int cropX = 256,
|
||||
cropY = 192;
|
||||
|
||||
if (g->hsp < 0) {
|
||||
cropX = 512;
|
||||
}
|
||||
|
||||
cropX += (int)g->imageIndex * 64;
|
||||
|
||||
while (cropX >= 640) {
|
||||
cropX -= 640;
|
||||
cropY += 64;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(g->x - 32, g->y - 32, cropX, cropY, 64, 64, images[imgMisc32]);
|
||||
}
|
||||
}
|
31
contrib/games/hydracastlelabyrinth/src/enemies/garm.h
Normal file
31
contrib/games/hydracastlelabyrinth/src/enemies/garm.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef GARM_H
|
||||
#define GARM_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
double x, y;
|
||||
double hsp, vsp;
|
||||
int dir;
|
||||
double imageIndex;
|
||||
int state, timer, blink, counter;
|
||||
int wallcounter, substate;
|
||||
int targx;
|
||||
} Garm;
|
||||
|
||||
void createGarm(int x, int y);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
double x, y;
|
||||
double vsp, hsp;
|
||||
double imageIndex;
|
||||
int counter;
|
||||
int blink;
|
||||
int inwall;
|
||||
} Garmrock;
|
||||
|
||||
void createGarmrock(int x, int y, double hsp, double vsp);
|
||||
|
||||
#endif
|
116
contrib/games/hydracastlelabyrinth/src/enemies/gas.c
Normal file
116
contrib/games/hydracastlelabyrinth/src/enemies/gas.c
Normal file
@ -0,0 +1,116 @@
|
||||
#include "gas.h"
|
||||
#include "../PHL.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void gasStep(Gas* g);
|
||||
void gasDraw(Gas* g);
|
||||
|
||||
void createGas(int x, int y, int temp)
|
||||
{
|
||||
if (temp == 0 || hasKey[7] == 0) {
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Gas* g = malloc(sizeof *g);
|
||||
g->id = i;
|
||||
|
||||
g->x = x;
|
||||
g->y = y;
|
||||
|
||||
g->state = 0;
|
||||
g->timer = 0;
|
||||
g->imageIndex = 0;
|
||||
|
||||
/*
|
||||
g->mask.unused = g->mask.circle = 0;
|
||||
g->mask.w = g->mask.h = 24;
|
||||
g->mask.x = x + 20 - (g->mask.w / 2);
|
||||
g->mask.y = y + 40 - g->mask.h;
|
||||
*/
|
||||
|
||||
e->data = g;
|
||||
e->enemyStep = gasStep;
|
||||
e->enemyDraw = gasDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gasStep(Gas* g)
|
||||
{
|
||||
if (g->state != 0) {
|
||||
g->imageIndex += 0.2;
|
||||
}
|
||||
|
||||
if (g->state == 0) { //Wait
|
||||
Mask tempMask;
|
||||
tempMask.circle = tempMask.unused = 0;
|
||||
tempMask.x = g->x - 100;
|
||||
tempMask.y = g->y - 20;
|
||||
tempMask.w = 240;
|
||||
tempMask.h = 60;
|
||||
|
||||
if (checkCollisionXY(tempMask, herox, heroy + 20)) {
|
||||
g->state = 1;
|
||||
g->imageIndex = 3;
|
||||
g->timer = 32;
|
||||
PHL_PlaySound(sounds[sndGas01], CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
else if (g->state == 1 || g->state == 3) { //Small puff
|
||||
if (g->imageIndex >= 5) {
|
||||
g->imageIndex -= 2;
|
||||
}
|
||||
|
||||
g->timer -= 1;
|
||||
if (g->timer <= 0) {
|
||||
if (g->state == 3) {
|
||||
g->state = 0;
|
||||
}else{
|
||||
g->state = 2;
|
||||
g->imageIndex = 0;
|
||||
g->timer = 175;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (g->state == 2) { //Big puff
|
||||
if (g->imageIndex >= 3) {
|
||||
g->imageIndex -= 3;
|
||||
}
|
||||
|
||||
g->timer -= 1;
|
||||
if (g->timer <= 0) {
|
||||
g->state = 3;
|
||||
g->timer = 120;
|
||||
g->imageIndex = 3;
|
||||
}
|
||||
|
||||
if (hasItem[7] != 1) { //Does not have gas mask
|
||||
Mask mask;
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.w = mask.h = 24;
|
||||
mask.x = g->x + 20 - (mask.w / 2);
|
||||
mask.y = g->y + 40 - mask.h;
|
||||
|
||||
if (checkCollision(getHeroMask(), mask)) {
|
||||
if (heroHit(15, g->x + 20)) {
|
||||
heroPoison();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gasDraw(Gas* g)
|
||||
{
|
||||
if (g->state != 0) {
|
||||
PHL_DrawSurfacePart(g->x, g->y, (int)g->imageIndex * 40, 400, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
18
contrib/games/hydracastlelabyrinth/src/enemies/gas.h
Normal file
18
contrib/games/hydracastlelabyrinth/src/enemies/gas.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef GAS_H
|
||||
#define GAS_H
|
||||
|
||||
//#include "../enemy.h"
|
||||
//#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
int state, timer;
|
||||
double imageIndex;
|
||||
|
||||
//Mask mask;
|
||||
} Gas;
|
||||
|
||||
void createGas(int x, int y, int temp);
|
||||
|
||||
#endif
|
218
contrib/games/hydracastlelabyrinth/src/enemies/ghoul.c
Normal file
218
contrib/games/hydracastlelabyrinth/src/enemies/ghoul.c
Normal file
@ -0,0 +1,218 @@
|
||||
#include "ghoul.h"
|
||||
#include "../game.h"
|
||||
#include "../enemy.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void ghoulStep(Ghoul* g);
|
||||
void ghoulDraw(Ghoul* g);
|
||||
|
||||
void createGhoul(int x, int y, int type)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Ghoul* g = malloc(sizeof *g);
|
||||
g->id = i;
|
||||
g->hp = 2;
|
||||
|
||||
g->x = x;
|
||||
g->y = y;
|
||||
|
||||
g->vsp = 0;
|
||||
g->grav = 0.1;
|
||||
|
||||
g->dir = 0;
|
||||
g->type = type;
|
||||
g->onground = 0;
|
||||
|
||||
g->timer = 0;
|
||||
g->state = 0;
|
||||
g->invincible = 0;
|
||||
|
||||
g->imageIndex = 0;
|
||||
|
||||
g->mask.circle = 0;
|
||||
g->mask.unused = 1;
|
||||
g->mask.w = 24;
|
||||
g->mask.h = 32;
|
||||
g->mask.x = g->x + ((40 - g->mask.w) / 2);
|
||||
g->mask.y = g->y + (40 - g->mask.h);
|
||||
|
||||
e->data = g;
|
||||
e->enemyStep = ghoulStep;
|
||||
e->enemyDraw = ghoulDraw;
|
||||
e->type = 18;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ghoulStep(Ghoul* g)
|
||||
{
|
||||
if (g->invincible > 0) {
|
||||
g->invincible -= 1;
|
||||
}
|
||||
|
||||
if (g->state == 0) { //Wait
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.w = 280;
|
||||
area.h = 80;
|
||||
area.x = g->x - 120;
|
||||
area.y = g->y - 20;
|
||||
|
||||
if (checkCollisionXY(area, herox, heroy + 20) == 1) {
|
||||
g->state = 1;
|
||||
g->mask.unused = 0;
|
||||
g->imageIndex = 0;
|
||||
|
||||
g->dir = 1;
|
||||
if (herox < g->x + 20) {
|
||||
g->dir = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (g->state == 1) { //Pop-up
|
||||
g->imageIndex += 0.16;
|
||||
|
||||
if (g->imageIndex >= 4) {
|
||||
g->state = 2;
|
||||
g->vsp = -1;
|
||||
g->imageIndex = 0;
|
||||
PHL_PlaySound(sounds[sndPi05],CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
else if (g->state == 2) { //Walking
|
||||
g->mask.unused = 0;
|
||||
if (g->onground == 0) {
|
||||
//Vertical movement
|
||||
g->y += g->vsp;
|
||||
g->vsp += g->grav;
|
||||
|
||||
g->mask.y = g->y + (40 - g->mask.h);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, g->mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, g->mask);
|
||||
}
|
||||
if (collide.x != -1) {
|
||||
g->onground = 1;
|
||||
g->vsp = 0;
|
||||
g->y = collide.y - 40;
|
||||
g->mask.y = g->y + (40 - g->mask.h);
|
||||
}
|
||||
}
|
||||
|
||||
g->imageIndex += 0.1;
|
||||
if (g->imageIndex >= 2) {
|
||||
g->imageIndex -= 2;
|
||||
}
|
||||
|
||||
double hsp = 1;
|
||||
|
||||
if ((int)g->imageIndex == 0) {
|
||||
hsp = 0.5;
|
||||
}
|
||||
|
||||
//Purple
|
||||
if (g->type == 1) {
|
||||
hsp *= 2;
|
||||
}
|
||||
|
||||
g->x += hsp * g->dir;
|
||||
g->mask.x = g->x + ((40 - g->mask.w) / 2);
|
||||
|
||||
if (g->onground == 1) {
|
||||
if ((g->x < -20 || g->x > 660) || checkTileCollision(1, g->mask) == 1) {
|
||||
g->dir *= -1;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, g->mask);
|
||||
if (collide.x != -1) {
|
||||
g->x = collide.x + (40 * g->dir);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//check on ledge
|
||||
g->mask.w = 5;
|
||||
if (g->dir == 1) {
|
||||
g->mask.x = g->x + 30;
|
||||
}
|
||||
if (g->dir == -1) {
|
||||
g->mask.x = g->x + 5;
|
||||
}
|
||||
g->mask.y += 20;
|
||||
|
||||
if (checkTileCollision(1, g->mask) == 0 && checkTileCollision(3, g->mask) == 0) {
|
||||
g->dir *= -1;
|
||||
}
|
||||
g->mask.w = 24;
|
||||
g->mask.x = g->x + ((40 - g->mask.w) / 2);
|
||||
g->mask.y = g->y + (40 - g->mask.h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g->mask.x = g->x + ((40 - g->mask.w) / 2);
|
||||
g->mask.y = g->y + (40 - g->mask.h);
|
||||
|
||||
//Hit Player
|
||||
{
|
||||
if (checkCollision(g->mask, getHeroMask())) {
|
||||
if (heroHit(10, g->x + 20) == 1 && g->type == 1) {
|
||||
heroPoison();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon Collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(g->mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
g->hp -= 1;
|
||||
g->invincible = 15;
|
||||
//Death
|
||||
if (g->hp <= 0) {
|
||||
createEffect(2, g->x - 12, g->y - 6);
|
||||
spawnCollectable(g->x + 20, g->y);
|
||||
enemyDestroy(g->id);
|
||||
}
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ghoulDraw(Ghoul* g)
|
||||
{
|
||||
if (g->state != 0 && g->invincible % 2 == 0) {
|
||||
int cx = (int)g->imageIndex * 40,
|
||||
cy = 160;
|
||||
|
||||
if (g->state == 1) {
|
||||
cx += 160;
|
||||
}else{
|
||||
if (g->dir == -1) {
|
||||
cx += 80;
|
||||
}
|
||||
}
|
||||
|
||||
//Purple palette
|
||||
cy += 160 * g->type;
|
||||
|
||||
PHL_DrawSurfacePart(g->x, g->y, cx, cy, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
22
contrib/games/hydracastlelabyrinth/src/enemies/ghoul.h
Normal file
22
contrib/games/hydracastlelabyrinth/src/enemies/ghoul.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef GHOUL_H
|
||||
#define GHOUL_H
|
||||
|
||||
#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
double x, y;
|
||||
double vsp, grav;
|
||||
int type;
|
||||
int onground;
|
||||
int dir;
|
||||
int state, timer, invincible;
|
||||
double imageIndex;
|
||||
|
||||
Mask mask;
|
||||
} Ghoul;
|
||||
|
||||
void createGhoul(int x, int y, int type);
|
||||
|
||||
#endif
|
199
contrib/games/hydracastlelabyrinth/src/enemies/golem.c
Normal file
199
contrib/games/hydracastlelabyrinth/src/enemies/golem.c
Normal file
@ -0,0 +1,199 @@
|
||||
#include "golem.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include "../game.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void golemStep(Golem* g);
|
||||
void golemDraw(Golem* g);
|
||||
|
||||
void createGolem(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Golem* g = malloc(sizeof *g);
|
||||
g->id = i;
|
||||
|
||||
g->x = x;
|
||||
g->y = y;
|
||||
|
||||
g->hp = 4;
|
||||
|
||||
g->dir = 1;
|
||||
if (dir == 1) {
|
||||
g->dir = -1;
|
||||
}
|
||||
|
||||
g->imageIndex = 0;
|
||||
g->state = 0;
|
||||
g->blink = 0;
|
||||
|
||||
e->data = g;
|
||||
e->enemyStep = golemStep;
|
||||
e->enemyDraw = golemDraw;
|
||||
e->type = 28;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void golemStep(Golem* g)
|
||||
{
|
||||
double imageSpeed = 0.2;
|
||||
|
||||
//Timers
|
||||
{
|
||||
if (g->blink > 0) {
|
||||
g->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.w = 36;
|
||||
mask.h = 36;
|
||||
mask.x = g->x + ((40 - mask.w) / 2);
|
||||
mask.y = g->y + (40 - mask.h);
|
||||
}
|
||||
|
||||
//Rolling
|
||||
if (g->state == 0)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
g->imageIndex += imageSpeed * g->dir;
|
||||
|
||||
if (g->imageIndex >= 8) {
|
||||
g->imageIndex -= 8;
|
||||
}
|
||||
|
||||
if (g->imageIndex < 0) {
|
||||
g->imageIndex += 8;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
double hsp = 1;
|
||||
{
|
||||
g->x += hsp * g->dir;
|
||||
mask.x = g->x + ((40 - mask.w) / 2);
|
||||
}
|
||||
|
||||
char nextState = 0;
|
||||
|
||||
//Check on ledge
|
||||
{
|
||||
mask.x += 30 * g->dir;
|
||||
mask.y += 10;
|
||||
|
||||
if (checkTileCollision(1, mask) == 0 && checkTileCollision(3, mask) == 0) {
|
||||
nextState = 1;
|
||||
}
|
||||
|
||||
mask.x = g->x + ((40 - mask.w) / 2);
|
||||
mask.y = g->y + (40 - mask.h);
|
||||
}
|
||||
|
||||
//Collide with wall
|
||||
{
|
||||
mask.x += hsp * g->dir;
|
||||
|
||||
if (checkTileCollision(1, mask) == 1) {
|
||||
nextState = 1;
|
||||
}
|
||||
|
||||
mask.x = g->x + ((40 - mask.w) / 2);
|
||||
}
|
||||
|
||||
if (nextState == 1) {
|
||||
PHL_PlaySound(sounds[sndPi10], CHN_ENEMIES);
|
||||
g->state = 1;
|
||||
g->imageIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Forming
|
||||
else if (g->state == 1)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
g->imageIndex += imageSpeed;
|
||||
|
||||
if (g->imageIndex >= 12) {
|
||||
g->imageIndex = 0;
|
||||
g->state = 0;
|
||||
g->dir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Hero Collision
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(15, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
//Tink
|
||||
if (g->state == 0) {
|
||||
PHL_PlaySound(sounds[sndHit03], CHN_WEAPONS);
|
||||
}else{
|
||||
g->hp -= 1;
|
||||
g->blink = 15;
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Death
|
||||
{
|
||||
if (g->hp <= 0) {
|
||||
createRockSmash(mask.x + (mask.w / 2), mask.y + (mask.h / 2));
|
||||
spawnCollectable(g->x + 20, g->y);
|
||||
enemyDestroy(g->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void golemDraw(Golem* g)
|
||||
{
|
||||
if (g->blink % 2 == 0) {
|
||||
int cropX = 320,
|
||||
cropY = 160;
|
||||
|
||||
int drawY = g->y;
|
||||
|
||||
if (g->state == 0) {
|
||||
cropX += (int)g->imageIndex * 40;
|
||||
drawY += 2;
|
||||
}else{
|
||||
cropY = 280;
|
||||
cropX = 240;
|
||||
|
||||
int animation[12] = {0, 1, 2, 3, 3, 3, 3, 3, 3, 2, 1, 0};
|
||||
cropX += animation[(int)g->imageIndex] * 40;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(g->x, drawY, cropX, cropY, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
16
contrib/games/hydracastlelabyrinth/src/enemies/golem.h
Normal file
16
contrib/games/hydracastlelabyrinth/src/enemies/golem.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef GOLEM_H
|
||||
#define GOLEM_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double imageIndex;
|
||||
int hp;
|
||||
int dir;
|
||||
int state;
|
||||
int blink;
|
||||
} Golem;
|
||||
|
||||
void createGolem(int x, int y, int dir);
|
||||
|
||||
#endif
|
332
contrib/games/hydracastlelabyrinth/src/enemies/gyra.c
Normal file
332
contrib/games/hydracastlelabyrinth/src/enemies/gyra.c
Normal file
@ -0,0 +1,332 @@
|
||||
#include "gyra.h"
|
||||
#include "../game.h"
|
||||
#include "../enemy.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void gyraStep(Gyra* g);
|
||||
void gyraDraw(Gyra* g);
|
||||
void gyraDestroy(Gyra* g);
|
||||
|
||||
int boss4flag = 21;
|
||||
|
||||
void createGyra(int x, int y)
|
||||
{
|
||||
if (flags[boss4flag] == 0) { //have not yet beaten boss 4
|
||||
PHL_FreeSurface(images[imgBoss]);
|
||||
images[imgBoss] = PHL_LoadQDA("boss02.bmp");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
//Boss start
|
||||
setBossRoom();
|
||||
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Gyra* g = malloc(sizeof *g);
|
||||
|
||||
g->id = i;
|
||||
g->hp = 50;
|
||||
//g->hp = 1;
|
||||
|
||||
g->x = x;
|
||||
g->y = y;
|
||||
|
||||
g->targx = g->x;
|
||||
g->targy = g->y;
|
||||
|
||||
g->state = 0;
|
||||
g->timer = 260;
|
||||
g->counter = 0;
|
||||
|
||||
g->invincible = 0;
|
||||
g->dir = 0;
|
||||
g->imageIndex = 0;
|
||||
|
||||
//Setup
|
||||
g->targx = g->x - 32;
|
||||
g->targy = g->y + 64;
|
||||
g->dir = 160;
|
||||
|
||||
g->x = g->targx + (80 * sin(g->dir * 3.14159 / 180));
|
||||
g->y = g->targy + (80 * cos(g->dir * 3.14159 / 180));
|
||||
|
||||
int a;
|
||||
for (a = 0; a < 144; a++) {
|
||||
g->xrecord[a] = g->x;
|
||||
g->yrecord[a] = g->y;
|
||||
}
|
||||
|
||||
e->data = g;
|
||||
e->enemyStep = gyraStep;
|
||||
e->enemyDraw = gyraDraw;
|
||||
e->type = 43;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gyraStep(Gyra* g)
|
||||
{
|
||||
//Animate
|
||||
g->imageIndex += 0.1;
|
||||
if (g->imageIndex >= 2) {
|
||||
g->imageIndex -= 2;
|
||||
}
|
||||
|
||||
int pattern[6] = {0, 1, 2, 1, 0, 2};
|
||||
|
||||
//Move in a circle
|
||||
if (g->state == 0)
|
||||
{
|
||||
int len = 80;
|
||||
|
||||
//Setup
|
||||
if (g->timer == 0) {
|
||||
g->targx = g->x + (len * sin((g->dir + 90) * 3.14159 / 180));
|
||||
g->targy = g->y + (len * cos((g->dir + 90) * 3.14159 / 180));
|
||||
g->dir -= 90;
|
||||
g->timer = 250;
|
||||
}
|
||||
|
||||
g->dir += 1.5;
|
||||
if (g->dir >= 360) {
|
||||
g->dir -= 360;
|
||||
}
|
||||
|
||||
g->x = g->targx + (len * sin(g->dir * 3.14159 / 180));
|
||||
g->y = g->targy + (len * cos(g->dir * 3.14159 / 180));
|
||||
|
||||
g->timer -= 1;
|
||||
if (g->timer <= 0) {
|
||||
g->counter += 1;
|
||||
g->state = pattern[g->counter];
|
||||
/*
|
||||
if (g->state != 1 && (g->x < 40 || g->x > 600 || g->y < 40 || g->y > 440)) {
|
||||
g->state = 1;
|
||||
}*/
|
||||
|
||||
g->timer = 0;
|
||||
}
|
||||
}
|
||||
//Attack
|
||||
else if (g->state == 1)
|
||||
{
|
||||
//Setup
|
||||
if (g->timer == 0) {
|
||||
g->targx = herox;
|
||||
g->targy = heroy + 20;
|
||||
g->dir += 90;
|
||||
g->timer = 320;
|
||||
}
|
||||
|
||||
double spd = 2;
|
||||
double diralt = 1.2;
|
||||
|
||||
double targdir = (atan2(g->targy - g->y, g->x - g->targx) * 180 / 3.14159) + 270;
|
||||
|
||||
targdir = g->dir - targdir;
|
||||
while (targdir >= 360) { targdir -= 360; }
|
||||
while (targdir < 0) { targdir += 360; }
|
||||
|
||||
if (targdir > 180) {
|
||||
g->dir += diralt;
|
||||
}
|
||||
if (targdir < 180) {
|
||||
g->dir -= diralt;
|
||||
}
|
||||
|
||||
//Movement
|
||||
g->x += spd * sin(g->dir * 3.14159 / 180);
|
||||
g->y += spd * cos(g->dir * 3.14159 / 180);
|
||||
|
||||
//Get (close) to targ coords
|
||||
g->timer -= 1;
|
||||
if (g->timer <= 0 || sqrt( pow(g->x - g->targx, 2) + pow(g->y - g->targy, 2) ) <= spd * 2) {
|
||||
g->counter += 1;
|
||||
if (g->counter >= 5) {
|
||||
g->counter = 0;
|
||||
}
|
||||
g->state = pattern[g->counter];
|
||||
g->timer = 0;
|
||||
}
|
||||
}
|
||||
//Oval movement
|
||||
else if (g->state == 2)
|
||||
{
|
||||
int wlen = 120,
|
||||
hlen = 80;
|
||||
|
||||
//Setup
|
||||
if (g->timer == 0) {
|
||||
g->targx = g->x + (wlen * sin((g->dir - 90) * 3.14159 / 180));
|
||||
g->targy = g->y + (hlen * cos((g->dir - 90) * 3.14159 / 180));
|
||||
g->dir += 90;
|
||||
g->timer = 200;
|
||||
}
|
||||
|
||||
g->dir -= 1.5;
|
||||
if (g->dir < 0) {
|
||||
g->dir += 360;
|
||||
}
|
||||
|
||||
g->x = g->targx + (wlen * sin(g->dir * 3.14159 / 180));
|
||||
g->y = g->targy + (hlen * cos(g->dir * 3.14159 / 180));
|
||||
|
||||
g->timer -= 1;
|
||||
if (g->timer <= 0) {
|
||||
g->counter += 1;
|
||||
if (g->counter >= 5) {
|
||||
g->counter = 0;
|
||||
}
|
||||
g->state = pattern[g->counter];
|
||||
/*
|
||||
if (g->state != 1 && (g->x < 40 || g->x > 600 || g->y < 40 || g->y > 440)) {
|
||||
g->state = 1;
|
||||
g->timer = 0;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
//Death
|
||||
if (g->state == 3)
|
||||
{
|
||||
g->timer -= 1;
|
||||
if (g->timer <= 0) {
|
||||
g->timer = 12;
|
||||
|
||||
int cx = g->xrecord[128 - (g->counter * 16)],
|
||||
cy = g->yrecord[128 - (g->counter * 16)];
|
||||
|
||||
createEffect(2, cx - 32, cy - 32);
|
||||
|
||||
g->counter += 1;
|
||||
if (g->counter == 9) {
|
||||
gyraDestroy(g);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//Update tail record
|
||||
int i;
|
||||
for (i = 142; i >= 0; i--) {
|
||||
g->xrecord[i + 1] = g->xrecord[i];
|
||||
g->yrecord[i + 1] = g->yrecord[i];
|
||||
}
|
||||
g->xrecord[0] = g->x;
|
||||
g->yrecord[0] = g->y;
|
||||
|
||||
//for (i = 8; i >= 0; i--) {
|
||||
for (i = 0; i <= 8; i++) {
|
||||
int cx = g->x, cy = g->y;
|
||||
|
||||
if (i != 0) {
|
||||
cx = g->xrecord[i * 16];
|
||||
cy = g->yrecord[i * 16];
|
||||
}
|
||||
|
||||
Mask mask;
|
||||
mask.unused = 0;
|
||||
mask.circle = 1;
|
||||
mask.x = cx;
|
||||
mask.y = cy;
|
||||
mask.w = mask.h = 28;
|
||||
|
||||
int a;
|
||||
for (a = 0; a < MAX_WEAPONS; a++) {
|
||||
if (weapons[a] != NULL) {
|
||||
if (weapons[a]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[a]->weaponMask)) {
|
||||
g->invincible = -15;
|
||||
weaponHit(weapons[a]);
|
||||
|
||||
if (i == 8) {
|
||||
g->hp -= 1;
|
||||
g->invincible = 15;
|
||||
}else{
|
||||
PHL_PlaySound(sounds[sndHit03], CHN_WEAPONS);
|
||||
}
|
||||
|
||||
a = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Hit player
|
||||
if (checkCollision(getHeroMask(), mask)) {
|
||||
if (heroHit(30, mask.x) && i == 0) {
|
||||
heroPoison();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Death
|
||||
if (g->hp <= 0) {
|
||||
g->state = 3;
|
||||
g->timer = 0;
|
||||
g->counter = 0;
|
||||
g->invincible = 200;
|
||||
}
|
||||
}
|
||||
|
||||
if (g->invincible > 0) {
|
||||
g->invincible -= 1;
|
||||
}
|
||||
if (g->invincible < 0) {
|
||||
g->invincible += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void gyraDraw(Gyra* g)
|
||||
{
|
||||
if (g->invincible <= 0 || g->invincible % 2 == 0) {
|
||||
//Draw Tail Tip
|
||||
if (g->state != 3 || g->counter <= 0) {
|
||||
PHL_DrawSurfacePart(g->xrecord[126] - 40, g->yrecord[126] - 40, 320 + ((int)g->imageIndex * 80), 0, 80, 80, images[imgBoss]);
|
||||
}
|
||||
|
||||
//Draw Tail
|
||||
int i;
|
||||
for (i = 7; i > 0; i--) {
|
||||
if (g->state != 3 || g->counter <= (7 - i) + 1) {
|
||||
PHL_DrawSurfacePart(g->xrecord[i * 16] - 40, g->yrecord[i * 16] - 40, 160 + ((int)g->imageIndex * 80), 0, 80, 80, images[imgBoss]);
|
||||
}
|
||||
}
|
||||
|
||||
//Draw Head
|
||||
PHL_DrawSurfacePart(g->x - 40, g->y - 40, (int)g->imageIndex * 80, 0, 80, 80, images[imgBoss]);
|
||||
}
|
||||
|
||||
//PHL_DrawRect(g->targx, g->targy, 10, 10, PHL_NewRGB(255, 255, 255));
|
||||
//heroAmmo = g->state;
|
||||
|
||||
/*
|
||||
int i;
|
||||
for (i = 8; i >= 0; i--) {
|
||||
int cx = g->x, cy = g->y;
|
||||
|
||||
if (i != 0) {
|
||||
cx = g->xrecord[i * 16];
|
||||
cy = g->yrecord[i * 16];
|
||||
}
|
||||
|
||||
PHL_DrawRect(cx, cy, 10, 10, PHL_NewRGB(255, 255, 255));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void gyraDestroy(Gyra* g)
|
||||
{
|
||||
enemyDestroy(g->id);
|
||||
bossDefeatedFlag = 1;
|
||||
roomSecret = 1;
|
||||
|
||||
flags[boss4flag] = 1;
|
||||
PHL_StopMusic();
|
||||
}
|
19
contrib/games/hydracastlelabyrinth/src/enemies/gyra.h
Normal file
19
contrib/games/hydracastlelabyrinth/src/enemies/gyra.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef GYRA_H
|
||||
#define GYRA_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
double x, y;
|
||||
double xrecord[144];
|
||||
double yrecord[144];
|
||||
int state, timer, counter;
|
||||
int targx, targy;
|
||||
int invincible;
|
||||
double dir;
|
||||
double imageIndex;
|
||||
} Gyra;
|
||||
|
||||
void createGyra(int x, int y);
|
||||
|
||||
#endif
|
838
contrib/games/hydracastlelabyrinth/src/enemies/heads.c
Normal file
838
contrib/games/hydracastlelabyrinth/src/enemies/heads.c
Normal file
@ -0,0 +1,838 @@
|
||||
#include "heads.h"
|
||||
#include "../enemy.h"
|
||||
#include "../game.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void headStep(Head* h);
|
||||
void headDraw(Head* h);
|
||||
|
||||
void bulletStep(Bullet* b);
|
||||
void bulletDraw(Bullet* b);
|
||||
|
||||
void fireballStep(Fireball* f);
|
||||
void fireballDraw(Fireball* f);
|
||||
|
||||
void laserStep(Laser* l);
|
||||
void laserDraw(Laser* l);
|
||||
|
||||
void flameStep(Flame* f);
|
||||
void flameDraw(Flame* f);
|
||||
|
||||
void rockStep(Rock* r);
|
||||
void rockDraw(Rock* r);
|
||||
|
||||
void airStep(Air* a);
|
||||
void airDraw(Air* a);
|
||||
|
||||
void createHead(int type, int x, int y, int dir, int offset, int cooloff)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Head* h = malloc(sizeof *h);
|
||||
|
||||
h->id = i;
|
||||
h->type = type;
|
||||
|
||||
h->x = x;
|
||||
h->y = y;
|
||||
|
||||
h->state = 0;
|
||||
|
||||
h->hp = 5;
|
||||
h->invincible = 0;
|
||||
h->counter = 0;
|
||||
|
||||
h->dir = 1;
|
||||
if (dir == 1) {
|
||||
h->dir = -1;
|
||||
}
|
||||
|
||||
h->timer = 30 * offset;
|
||||
h->cooloff = 60;
|
||||
if (cooloff != 0) {
|
||||
h->cooloff = 30 * cooloff;
|
||||
}
|
||||
|
||||
e->type = -1;
|
||||
if (h->type == 0) {
|
||||
e->type = 4;
|
||||
h->cooloff = 120;
|
||||
}
|
||||
else if (h->type == 1) {
|
||||
e->type = 6;
|
||||
}
|
||||
else if (h->type == 2) {
|
||||
e->type = 5;
|
||||
}
|
||||
else if (h->type == 3) {
|
||||
e->type = 7;
|
||||
h->cooloff = 120;
|
||||
}
|
||||
else if (h->type == 4) {
|
||||
e->type = 10;
|
||||
h->dir = 0;
|
||||
}
|
||||
else if (h->type == 5) {
|
||||
e->type = 25;
|
||||
h->dir = 0;
|
||||
}
|
||||
e->data = h;
|
||||
e->enemyStep = headStep;
|
||||
e->enemyDraw = headDraw;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void headStep(Head* h)
|
||||
{
|
||||
int RHYNO = 0,
|
||||
MEDUSA = 1,
|
||||
DRAGON = 2,
|
||||
DEMON = 3,
|
||||
FIRE = 4,
|
||||
JAR = 5;
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.x = h->x;
|
||||
mask.y = h->y + 1;
|
||||
mask.w = 40;
|
||||
mask.h = 39;
|
||||
}
|
||||
|
||||
//Timers
|
||||
{
|
||||
if (h->invincible > 0) {
|
||||
h->invincible -= 1;
|
||||
}
|
||||
|
||||
if (h->timer > 0) {
|
||||
h->timer -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Wait
|
||||
if (h->state == 0)
|
||||
{
|
||||
char endstate = 0;
|
||||
|
||||
if (h->timer <= 0) {
|
||||
//Proximity
|
||||
if (h->type == RHYNO || h->type == DEMON) {
|
||||
Mask area;
|
||||
area.circle = area.unused = 0;
|
||||
area.h = 80;
|
||||
area.w = 400;
|
||||
area.y = h->y - 20;
|
||||
area.x = h->x;
|
||||
if (h->dir == -1) {
|
||||
area.x -= area.w - 40;
|
||||
}
|
||||
|
||||
if (checkCollision(area, getHeroMask()) == 1) {
|
||||
endstate = 1;
|
||||
}
|
||||
}else{
|
||||
endstate = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Move onto next state
|
||||
if (endstate == 1) {
|
||||
h->state = 1;
|
||||
h->timer = 30;
|
||||
}
|
||||
}
|
||||
|
||||
//Blink
|
||||
else if (h->state == 1)
|
||||
{
|
||||
//Shoot projectile
|
||||
if (h->timer <= 0) {
|
||||
//Play Sound
|
||||
{
|
||||
int soundtoplay[6] = {sndShot03, sndShot04, sndFire01, sndHit06, sndShot03, sndShot06};
|
||||
PHL_PlaySound(sounds[soundtoplay[h->type]], CHN_ENEMIES);
|
||||
}
|
||||
|
||||
//Set vars
|
||||
{
|
||||
h->state = 0;
|
||||
h->timer = h->cooloff;
|
||||
}
|
||||
|
||||
//Create projectile
|
||||
{
|
||||
//Rhyno head
|
||||
if (h->type == RHYNO) {
|
||||
createBullet(mask.x + (mask.w / 2), h->y + 24, h->dir, h->id);
|
||||
}
|
||||
//Medusa head
|
||||
if (h->type == MEDUSA) {
|
||||
createLaser(h->x, h->y, h->dir);
|
||||
}
|
||||
//Dragon head
|
||||
if (h->type == DRAGON) {
|
||||
createFlame(h->x + 20 + (20 * h->dir), h->y - 10, h->dir);
|
||||
}
|
||||
//Demon head
|
||||
if (h->type == DEMON) {
|
||||
createRock(h->x + (20 * h->dir), h->y, h->dir);
|
||||
}
|
||||
//Fireball Statue
|
||||
if (h->type == FIRE) {
|
||||
createFireball(h->x + 20, h->y + 20, (atan2(heroy - h->y, h->x - (herox - 20)) * 180 / 3.14159) + 270, h->id);
|
||||
}
|
||||
//Air Jar
|
||||
if (h->type == JAR) {
|
||||
h->state = 3;
|
||||
h->timer = 12;
|
||||
h->counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Air Jar
|
||||
else if (h->state == 3)
|
||||
{
|
||||
if (h->timer <= 0) {
|
||||
h->counter += 1;
|
||||
h->timer = 12;
|
||||
createAir(h->x, h->y - 20);
|
||||
}
|
||||
|
||||
if (h->counter >= 6) {
|
||||
h->counter = 0;
|
||||
h->state = 0;
|
||||
h->timer = h->cooloff;
|
||||
}
|
||||
}
|
||||
|
||||
//Hit player
|
||||
if (h->type != JAR) {
|
||||
if (checkCollision(getHeroMask(), mask)) {
|
||||
heroHit(10, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
h->hp -= 1;
|
||||
h->invincible = 15;
|
||||
weaponHit(weapons[i]);
|
||||
//Death
|
||||
if (h->hp <= 0) {
|
||||
createRockSmash(h->x + 20, h->y + 20);
|
||||
spawnCollectable(h->x + 20, h->y);
|
||||
enemyDestroy(h->id);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void headDraw(Head* h)
|
||||
{
|
||||
if (h->invincible % 2 == 0)
|
||||
{
|
||||
int sheetX[6] = {0, 320, 160, 240, 560, 400};
|
||||
int sheetY[6] = {80, 80, 80, 120, 0, 120};
|
||||
|
||||
int cropX = sheetX[h->type];
|
||||
|
||||
int addx[6] = {6, 2, 0, 0, 0, 0};
|
||||
int frames = 2;
|
||||
|
||||
//Change dir
|
||||
if (h->dir == 0) {
|
||||
frames = 1;
|
||||
}else{
|
||||
frames = 2;
|
||||
if (h->dir == -1) {
|
||||
cropX += 40;
|
||||
}
|
||||
}
|
||||
|
||||
//White flash
|
||||
if (h->state == 1 && h->timer % 6 < 3) {
|
||||
cropX += 40 * frames;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(h->x - (addx[h->type] * h->dir), h->y, cropX, sheetY[h->type], 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
||||
|
||||
//Bullets
|
||||
void createBullet(int x, int y, int dir, int minid)
|
||||
{
|
||||
int i;
|
||||
for (i = minid; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Bullet* b = malloc(sizeof *b);
|
||||
b->id = i;
|
||||
|
||||
b->x = x;
|
||||
b->y = y;
|
||||
|
||||
b->hsp = dir * 4;
|
||||
|
||||
b->imageIndex = 0;
|
||||
|
||||
e->data = b;
|
||||
e->enemyStep = bulletStep;
|
||||
e->enemyDraw = bulletDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bulletStep(Bullet* b)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Movement
|
||||
{
|
||||
b->x += b->hsp;
|
||||
}
|
||||
|
||||
//Create Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = 0;
|
||||
mask.circle = 1;
|
||||
mask.w = mask.h = 10;
|
||||
mask.x = b->x;
|
||||
mask.y = b->y;
|
||||
}
|
||||
|
||||
//Animation
|
||||
{
|
||||
if (b->hsp > 0) {
|
||||
b->imageIndex += 0.33;
|
||||
}else{
|
||||
b->imageIndex -= 0.33;
|
||||
}
|
||||
|
||||
if (b->imageIndex < 0) {
|
||||
b->imageIndex += 4;
|
||||
}
|
||||
if (b->imageIndex >= 4) {
|
||||
b->imageIndex -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
//Collide with wall
|
||||
{
|
||||
if (checkTileCollision(1, mask) == 1) {
|
||||
createEffect(1, b->x - 20, b->y - 20);
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Collide with hero
|
||||
{
|
||||
//Shield collision
|
||||
if (checkCollision(mask, shieldMask) == 1) {
|
||||
dead = 1;
|
||||
createEffect(1, b->x - 20, b->y - 20);
|
||||
PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
|
||||
}
|
||||
//Collide with hero
|
||||
else{
|
||||
if (checkCollision(getHeroMask(), mask)) {
|
||||
heroHit(10, mask.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy if outside of view
|
||||
{
|
||||
if (b->x > 660 || b->x < -20 || b->y < -20 || b->y > 520) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy
|
||||
{
|
||||
if (dead == 1) {
|
||||
enemyDestroy(b->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bulletDraw(Bullet* b)
|
||||
{
|
||||
PHL_DrawSurfacePart(b->x - 20, b->y - 20, 160 + (40 * (int)b->imageIndex), 480, 40, 40, images[imgMisc20]);
|
||||
}
|
||||
|
||||
//Fireball
|
||||
void createFireball(int x, int y, int angle, int minid)
|
||||
{
|
||||
//General idea: try to place fireball over spawner
|
||||
int i;
|
||||
for (i = minid; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Fireball* f = malloc(sizeof *f);
|
||||
f->id = i;
|
||||
|
||||
f->x = x;
|
||||
f->y = y;
|
||||
|
||||
f->spd = 3;
|
||||
|
||||
f->imageIndex = 0;
|
||||
f->angle = angle;
|
||||
|
||||
f->mask.circle = 1;
|
||||
f->mask.unused = 0;
|
||||
f->mask.x = x;
|
||||
f->mask.y = y;
|
||||
f->mask.w = f->mask.h = 14;
|
||||
|
||||
e->data = f;
|
||||
e->enemyStep = fireballStep;
|
||||
e->enemyDraw = fireballDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fireballStep(Fireball* f)
|
||||
{
|
||||
f->x += (f->spd) * sin(f->angle * 3.14159 / 180);
|
||||
f->y += (f->spd) * cos(f->angle * 3.14159 / 180);
|
||||
|
||||
f->mask.x = f->x;
|
||||
f->mask.y = f->y;
|
||||
|
||||
f->imageIndex += 0.5;
|
||||
if (f->imageIndex >= 8) {
|
||||
f->imageIndex -= 8;
|
||||
}
|
||||
|
||||
//Collide with shield
|
||||
if (checkCollision(f->mask, shieldMask)) {
|
||||
createEffect(1, f->x - 20, f->y - 20);
|
||||
PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
|
||||
enemyDestroy(f->id);
|
||||
}else{
|
||||
//Hit player
|
||||
if (checkCollision(getHeroMask(), f->mask)) {
|
||||
heroHit(10, f->mask.x);
|
||||
}
|
||||
//Destroy if outside of view
|
||||
if (f->x > 660 || f->x < -20 || f->y < -20 || f->y > 520) {
|
||||
enemyDestroy(f->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fireballDraw(Fireball* f)
|
||||
{
|
||||
PHL_DrawSurfacePart(f->x - 20, f->y - 20, 320 + (40 * (int)f->imageIndex), 440, 40, 40, images[imgMisc20]);
|
||||
}
|
||||
|
||||
//Laser
|
||||
void createLaser(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Laser* l = malloc(sizeof *l);
|
||||
l->id = i;
|
||||
|
||||
l->x = x;
|
||||
l->y = y;
|
||||
|
||||
l->dir = dir;
|
||||
l->imageIndex = 0;
|
||||
|
||||
l->mask.circle = l->mask.unused = 0;
|
||||
l->mask.x = x;
|
||||
l->mask.y = y + 17;
|
||||
l->mask.w = 40;
|
||||
l->mask.h = 6;
|
||||
|
||||
e->data = l;
|
||||
e->enemyStep = laserStep;
|
||||
e->enemyDraw = laserDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void laserStep(Laser* l)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
l->x += l->dir * 10;
|
||||
l->mask.x = l->x;
|
||||
|
||||
l->imageIndex += 0.34;
|
||||
if (l->imageIndex >= 2) {
|
||||
l->imageIndex -= 2;
|
||||
}
|
||||
|
||||
if (checkCollision(shieldMask, l->mask)) { //Hit shield
|
||||
PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
|
||||
createEffect(1, l->x + (20 * l->dir), l->y);
|
||||
enemyDestroy(l->id);
|
||||
dead = 1;
|
||||
}else if (checkCollision(getHeroMask(), l->mask)) {
|
||||
heroStone();
|
||||
heroHit(15, l->x + 20);
|
||||
}
|
||||
|
||||
if (dead == 0) {
|
||||
if (checkTileCollision(1, l->mask)) {
|
||||
createEffect(1, l->x + (20 * l->dir), l->y);
|
||||
enemyDestroy(l->id);
|
||||
dead = 1;
|
||||
}
|
||||
|
||||
if (dead == 0) {
|
||||
if (l->mask.x > 640 || l->mask.x + l->mask.w <= 0) {
|
||||
enemyDestroy(l->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void laserDraw(Laser* l)
|
||||
{
|
||||
int dx = 0,
|
||||
dy = 480;
|
||||
if (l->dir == -1) {
|
||||
dx += 80;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(l->x, l->y, dx + (((int)l->imageIndex) * 40), dy, 40, 40, images[imgMisc20]);
|
||||
}
|
||||
|
||||
//Dragon Flame
|
||||
void createFlame(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Flame* f = malloc(sizeof *f);
|
||||
f->id = i;
|
||||
|
||||
f->x = x;
|
||||
f->y = y;
|
||||
|
||||
f->dir = dir;
|
||||
f->timer = 60;
|
||||
|
||||
f->imageIndex = 0;
|
||||
|
||||
e->data = f;
|
||||
e->enemyStep = flameStep;
|
||||
e->enemyDraw = flameDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flameStep(Flame* f)
|
||||
{
|
||||
f->imageIndex += 0.25;
|
||||
|
||||
if (f->timer > 0) {
|
||||
if (f->imageIndex >= 3) {
|
||||
f->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
f->timer -= 1;
|
||||
|
||||
if (f->timer == 0) {
|
||||
f->imageIndex = 3;
|
||||
}
|
||||
|
||||
//Hero Collision
|
||||
{
|
||||
Mask mask;
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.x = f->x;
|
||||
mask.y = f->y + 16;
|
||||
mask.w = 120;
|
||||
mask.h = 18;
|
||||
if (f->dir == -1) {
|
||||
mask.x -= 120;
|
||||
}
|
||||
|
||||
if (checkCollision(mask, getHeroMask()) == 1) {
|
||||
int centerX = mask.x + 60 - (60 * f->dir);
|
||||
|
||||
//Hero is on ladder
|
||||
if (getHeroState() == 3) {
|
||||
centerX = herox;
|
||||
}
|
||||
|
||||
heroHit(30, centerX);
|
||||
}
|
||||
}
|
||||
|
||||
if (f->timer < 0 && f->imageIndex >= 6) {
|
||||
enemyDestroy(f->id);
|
||||
}
|
||||
}
|
||||
|
||||
void flameDraw(Flame* f)
|
||||
{
|
||||
int drawX = f->x,
|
||||
drawY = f->y;
|
||||
|
||||
int cropX = 0,
|
||||
cropY = 0;
|
||||
|
||||
if (f->dir == -1) {
|
||||
cropX += 720;
|
||||
drawX -= 120;
|
||||
}
|
||||
|
||||
cropX += 120 * (int)f->imageIndex;
|
||||
|
||||
while (cropX >= 600) {
|
||||
cropX -= 600;
|
||||
cropY += 40;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(drawX, drawY, cropX, cropY, 120, 40, images[imgMisc6020]);
|
||||
}
|
||||
|
||||
//Demon Rock
|
||||
void createRock(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Rock* r = malloc(sizeof *r);
|
||||
r->id = i;
|
||||
|
||||
r->x = x;
|
||||
r->y = y;
|
||||
|
||||
r->vsp = -3;
|
||||
r->dir = dir;
|
||||
|
||||
r->imageIndex = 0;
|
||||
|
||||
e->data = r;
|
||||
e->enemyStep = rockStep;
|
||||
e->enemyDraw = rockDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rockStep(Rock* r)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Animate
|
||||
{
|
||||
r->imageIndex += 0.25 * r->dir;
|
||||
if (r->imageIndex >= 8) {
|
||||
r->imageIndex -= 8;
|
||||
}
|
||||
if (r->imageIndex < 0) {
|
||||
r->imageIndex += 8;
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.x = r->x + 2;
|
||||
mask.y = r->y + 2;
|
||||
mask.w = 36;
|
||||
mask.h = 36;
|
||||
}
|
||||
|
||||
int hsp = 3;
|
||||
double grav = 0.12;
|
||||
|
||||
//Movement
|
||||
{
|
||||
r->y += r->vsp;
|
||||
r->vsp += grav;
|
||||
|
||||
//Collide with floor
|
||||
{
|
||||
mask.y = r->y + 2;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
if (collide.x != -1) {
|
||||
PHL_PlaySound(sounds[sndHit06], CHN_ENEMIES);
|
||||
r->y = collide.y - mask.h - 2;
|
||||
r->vsp = -3;
|
||||
mask.y = r->y + 2;
|
||||
}
|
||||
}
|
||||
|
||||
r->x += hsp * r->dir;
|
||||
|
||||
//Collide with wall
|
||||
{
|
||||
mask.x = r->x + 2;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
|
||||
if (collide.x != -1) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Collision
|
||||
{
|
||||
//Hero collision
|
||||
if (checkCollision(mask, getHeroMask()) == 1) {
|
||||
heroHit(20, mask.x + (mask.w / 2));
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
PHL_PlaySound(sounds[sndHit03], CHN_WEAPONS);
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy
|
||||
if (dead == 1) {
|
||||
createRockSmash(r->x + 20, r->y);
|
||||
enemyDestroy(r->id);
|
||||
}
|
||||
}
|
||||
|
||||
void rockDraw(Rock* r)
|
||||
{
|
||||
PHL_DrawSurfacePart(r->x, r->y, 320 + ((int)r->imageIndex * 40), 160, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
|
||||
//Air Stream
|
||||
void createAir(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Air* a = malloc(sizeof *a);
|
||||
a->id = i;
|
||||
|
||||
a->x = x;
|
||||
a->y = y;
|
||||
|
||||
a->imageIndex = 0;
|
||||
|
||||
e->data = a;
|
||||
e->enemyStep = airStep;
|
||||
e->enemyDraw = airDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Air Puff
|
||||
void airStep(Air* a)
|
||||
{
|
||||
Mask mask;
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 36;
|
||||
mask.h = 30;
|
||||
mask.x = a->x + ((40 - mask.w) / 2);
|
||||
|
||||
//Animate
|
||||
a->imageIndex += 0.5;
|
||||
if (a->imageIndex >= 2) {
|
||||
a->imageIndex -= 2;
|
||||
}
|
||||
|
||||
//Movement
|
||||
a->y -= 6;
|
||||
mask.y = a->y + (40 - mask.h);
|
||||
|
||||
//Collide with player
|
||||
if (getHeroState() != 2) {
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
if (hasItem[27] == 0) {
|
||||
heroHit(10, mask.x + (mask.w / 2));
|
||||
}else{
|
||||
//Floating stuff
|
||||
if (getHeroVsp() > -5) {
|
||||
setHeroVsp(-5);
|
||||
setHeroOnground(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//destroy if outside of room
|
||||
if (mask.y + mask.h < 0) {
|
||||
enemyDestroy(a->id);
|
||||
}
|
||||
}
|
||||
|
||||
void airDraw(Air* a)
|
||||
{
|
||||
PHL_DrawSurfacePart(a->x, a->y, (int)a->imageIndex * 40, 560, 40, 40, images[imgMisc20]);
|
||||
}
|
89
contrib/games/hydracastlelabyrinth/src/enemies/heads.h
Normal file
89
contrib/games/hydracastlelabyrinth/src/enemies/heads.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef HEADS_H
|
||||
#define HEADS_H
|
||||
|
||||
#include "../collision.h"
|
||||
|
||||
//Goblin/medusa/dragon head statues
|
||||
typedef struct {
|
||||
int id, type; //0 = Rhyno head | 1 = Goblin | 2 = Dragon | 3 = Demon | 4 = Fireball | 5 = Air Jar
|
||||
int state, timer;
|
||||
double x, y;
|
||||
int dir;
|
||||
int hp, invincible;
|
||||
int cooloff;
|
||||
int counter;
|
||||
|
||||
//Mask mask;
|
||||
} Head;
|
||||
|
||||
void createHead(int type, int x, int y, int dir, int offset, int cooloff);
|
||||
|
||||
//Bullet from Rhyno statues
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
int hsp;
|
||||
double imageIndex;
|
||||
|
||||
//Mask mask;
|
||||
} Bullet;
|
||||
|
||||
void createBullet(int x, int y, int dir, int minid); //Minid is the spawner's id
|
||||
|
||||
//Fireball
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
int angle;
|
||||
int spd;
|
||||
double imageIndex;
|
||||
|
||||
Mask mask;
|
||||
} Fireball;
|
||||
|
||||
void createFireball(int x, int y, int angle, int minid);
|
||||
|
||||
//Medusa lazer
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
int dir;
|
||||
double imageIndex;
|
||||
|
||||
Mask mask;
|
||||
} Laser;
|
||||
|
||||
void createLaser(int x, int y, int dir);
|
||||
|
||||
//Dragon flame
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
int dir;
|
||||
int timer;
|
||||
double imageIndex;
|
||||
} Flame;
|
||||
|
||||
void createFlame(int x, int y, int dir);
|
||||
|
||||
//Demon Boulder
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double vsp;
|
||||
int dir;
|
||||
double imageIndex;
|
||||
} Rock;
|
||||
|
||||
void createRock(int x, int y, int dir);
|
||||
|
||||
//Air
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double imageIndex;
|
||||
} Air;
|
||||
|
||||
void createAir(int x, int y);
|
||||
|
||||
#endif
|
1127
contrib/games/hydracastlelabyrinth/src/enemies/hydra.c
Normal file
1127
contrib/games/hydracastlelabyrinth/src/enemies/hydra.c
Normal file
File diff suppressed because it is too large
Load Diff
65
contrib/games/hydracastlelabyrinth/src/enemies/hydra.h
Normal file
65
contrib/games/hydracastlelabyrinth/src/enemies/hydra.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef HYDRA_H
|
||||
#define HYDRA_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp, blink;
|
||||
double x, y;
|
||||
double hsp, vsp;
|
||||
double imageIndex;
|
||||
int state, timer;
|
||||
int patternCounter;
|
||||
char onground;
|
||||
char noheads;
|
||||
int headid[4];
|
||||
} Hydra;
|
||||
|
||||
void createHydra(int x);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp, blink;
|
||||
int dir;
|
||||
int position; //0 = lower 1 = higher
|
||||
double imageIndex;
|
||||
double neckRot;
|
||||
int state, timer, counter;
|
||||
int bodyid;
|
||||
double bodyposX[7];
|
||||
double bodyposY[7];
|
||||
} Hydrahead;
|
||||
|
||||
int createHydrahead(int dir, int position, int bodyid);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double hsp, vsp;
|
||||
char inwall;
|
||||
char bounce;
|
||||
double imageIndex;
|
||||
} Hydragoop;
|
||||
|
||||
void createHydragoop(int x, int y, int hsp, int vsp);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double vsp;
|
||||
char bounce;
|
||||
double imageIndex;
|
||||
} Hydrarock;
|
||||
|
||||
void createHydrarock();
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int timer;
|
||||
double x, y;
|
||||
double angle;
|
||||
double imageIndex;
|
||||
} Hydrashock;
|
||||
|
||||
void createHydrashock(int x, int y);
|
||||
|
||||
#endif
|
195
contrib/games/hydracastlelabyrinth/src/enemies/jellyfish.c
Normal file
195
contrib/games/hydracastlelabyrinth/src/enemies/jellyfish.c
Normal file
@ -0,0 +1,195 @@
|
||||
#include "jellyfish.h"
|
||||
#include "../enemy.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void jellyfishStep(Jellyfish* j);
|
||||
void jellyfishDraw(Jellyfish* j);
|
||||
|
||||
void createJellyfish(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Jellyfish* j = malloc(sizeof *j);
|
||||
j->id = i;
|
||||
|
||||
j->x = x;
|
||||
j->y = j->ystart = y;
|
||||
j->ystart += 20;
|
||||
|
||||
j->spd = 0;
|
||||
j->angle = 0;
|
||||
|
||||
j->state = 0;
|
||||
j->imageIndex = 0;
|
||||
|
||||
e->data = j;
|
||||
e->enemyStep = jellyfishStep;
|
||||
e->enemyDraw = jellyfishDraw;
|
||||
e->type = 20;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void jellyfishStep(Jellyfish* j)
|
||||
{
|
||||
Mask mask;
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.w = mask.h = 30;
|
||||
mask.x = j->x + 20 - (mask.w / 2);
|
||||
mask.y = j->y + 20 - (mask.h / 2);
|
||||
|
||||
//Idle float
|
||||
if (j->state == 0)
|
||||
{
|
||||
//Animate
|
||||
j->imageIndex += 0.06;
|
||||
if (j->imageIndex >= 4) {
|
||||
j->imageIndex -= 4;
|
||||
}
|
||||
|
||||
//Movement
|
||||
j->angle += 2.5;
|
||||
if (j->angle >= 360) { j->angle -= 360; }
|
||||
j->y = j->ystart + (20 * sin(j->angle * 3.14159 / 180));
|
||||
|
||||
//Update mask
|
||||
mask.y = j->y + 20 - (mask.h / 2);
|
||||
|
||||
//if player is close enough
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.w = area.h = 160;
|
||||
area.x = j->x - 60;
|
||||
area.y = j->y - 60;
|
||||
|
||||
if (checkCollision(area, getHeroMask()) == 1) {
|
||||
j->state = 1;
|
||||
j->spd = 0;
|
||||
}
|
||||
}
|
||||
//Attack
|
||||
if (j->state == 1)
|
||||
{
|
||||
//Setup
|
||||
if (j->spd == 0) {
|
||||
PHL_PlaySound(sounds[sndPi02], CHN_ENEMIES);
|
||||
j->spd = 3;
|
||||
|
||||
//Move Right
|
||||
if (herox > j->x + 20) {
|
||||
//Move Up
|
||||
if (heroy < j->y) {
|
||||
j->angle = 135;
|
||||
}
|
||||
//Move Down
|
||||
else {
|
||||
j->angle = 45;
|
||||
}
|
||||
}
|
||||
//Move Left
|
||||
else{
|
||||
//Move Up
|
||||
if (heroy < j->y) {
|
||||
j->angle = 225;
|
||||
}
|
||||
//Move Down
|
||||
else {
|
||||
j->angle = 315;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
j->x += (j->spd) * sin(j->angle * 3.14159 / 180);
|
||||
j->y += (j->spd) * cos(j->angle * 3.14159 / 180);
|
||||
|
||||
//Slow down
|
||||
j->spd -= 0.075;
|
||||
if (j->spd <= 0) {
|
||||
j->spd = 0;
|
||||
j->state = 2;
|
||||
}
|
||||
}
|
||||
//Stablize
|
||||
if (j->state == 2)
|
||||
{
|
||||
//Setup
|
||||
if (j->spd == 0) {
|
||||
j->spd = 1;
|
||||
j->ystart = j->y - 20;
|
||||
j->angle = 80;
|
||||
}
|
||||
|
||||
//Movement
|
||||
j->angle += 2.5;
|
||||
if (j->angle >= 360) { j->angle -= 360; }
|
||||
j->y = j->ystart + (20 * sin(j->angle * 3.14159 / 180));
|
||||
|
||||
|
||||
if (j->angle >= 180) {
|
||||
j->state = 0;
|
||||
j->ystart = j->y - 20;
|
||||
j->angle = 100;
|
||||
}
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
mask.x = j->x + 20 - (mask.w / 2);
|
||||
mask.y = j->y + 20 - (mask.h / 2);
|
||||
|
||||
//Collide with hero
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(15, j->x + 20);
|
||||
}
|
||||
|
||||
//Sword collision
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
spawnCollectable(j->x + 20, j->y);
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
createEffect(2, j->x - 12, j->y - 12);
|
||||
enemyDestroy(j->id);
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void jellyfishDraw(Jellyfish* j)
|
||||
{
|
||||
int frame = 0;
|
||||
|
||||
//if (j->state == 0) {
|
||||
int animation[4] = { 0, 1, 0, 2};
|
||||
frame = animation[(int)j->imageIndex];
|
||||
//}
|
||||
|
||||
if (j->state == 1) {
|
||||
if (j->angle == 135) {
|
||||
frame = 3;
|
||||
}
|
||||
else if (j->angle == 225) {
|
||||
frame = 4;
|
||||
}
|
||||
else if (j->angle == 315) {
|
||||
frame = 5;
|
||||
}
|
||||
else {
|
||||
frame = 6;
|
||||
}
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(j->x, j->y, frame * 40, 520, 40, 40, images[imgEnemies]);
|
||||
}
|
16
contrib/games/hydracastlelabyrinth/src/enemies/jellyfish.h
Normal file
16
contrib/games/hydracastlelabyrinth/src/enemies/jellyfish.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef JELLYFISH_H
|
||||
#define JELLYFISH_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
int ystart;
|
||||
double spd;
|
||||
double angle;
|
||||
int state;
|
||||
double imageIndex;
|
||||
} Jellyfish;
|
||||
|
||||
void createJellyfish(int x, int y);
|
||||
|
||||
#endif
|
232
contrib/games/hydracastlelabyrinth/src/enemies/knight.c
Normal file
232
contrib/games/hydracastlelabyrinth/src/enemies/knight.c
Normal file
@ -0,0 +1,232 @@
|
||||
#include "knight.h"
|
||||
#include "../enemy.h"
|
||||
#include "../hero.h"
|
||||
#include "../PHL.h"
|
||||
#include "../game.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void knightDestroy(Knight* k);
|
||||
|
||||
void createKnight(int x, int y, int type)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Knight* k = malloc(sizeof *k);
|
||||
|
||||
k->id = i;
|
||||
k->type = type;
|
||||
|
||||
k->x = x;
|
||||
k->y = y;
|
||||
|
||||
//They face the player when they are spawned
|
||||
k->dir = -1;
|
||||
if (herox > x + 20) {
|
||||
k->dir = 1;
|
||||
}
|
||||
|
||||
k->vsp = 0;
|
||||
k->grav = 0.2;
|
||||
|
||||
k->state = 0;
|
||||
k->timer = 60 + (((rand() % 5) + 1) * 60);
|
||||
k->imageIndex = 0;
|
||||
|
||||
k->hp = 2;
|
||||
//Shield Knight
|
||||
if (k->type == 1) {
|
||||
k->hp = 3;
|
||||
}
|
||||
|
||||
k->invincible = 0;
|
||||
k->shieldhit = 0;
|
||||
|
||||
k->mask.circle = 0;
|
||||
k->mask.unused = 0;
|
||||
k->mask.x = x + 4;
|
||||
k->mask.y = y + 8;
|
||||
k->mask.w = 32;
|
||||
k->mask.h = 32;
|
||||
|
||||
e->data = k;
|
||||
e->enemyStep = knightStep;
|
||||
e->enemyDraw = knightDraw;
|
||||
e->type = 3;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void knightStep(Knight* k)
|
||||
{
|
||||
if (k->shieldhit > 0) {
|
||||
k->shieldhit -= 1;
|
||||
}
|
||||
|
||||
if (k->invincible > 0) {
|
||||
k->invincible -= 1;
|
||||
}
|
||||
|
||||
if (k->state == 0) { //Walk
|
||||
k->imageIndex += 0.1;
|
||||
if (k->imageIndex >= 2) {
|
||||
k->imageIndex -= 2;
|
||||
}
|
||||
|
||||
double spd = 1;
|
||||
if (k->type == 1) {
|
||||
spd = 0.5;
|
||||
}
|
||||
spd *= k->dir;
|
||||
|
||||
k->x += spd;
|
||||
|
||||
k->mask.x = k->x + 4;
|
||||
k->mask.y = k->y + 8;
|
||||
|
||||
Mask emask;
|
||||
emask.circle = emask.unused = 0;
|
||||
emask.w = 16;
|
||||
emask.h = 32;
|
||||
emask.x = k->x + 12;
|
||||
emask.y = k->y + 8;
|
||||
|
||||
//Turn when colliding with a wall
|
||||
if (checkTileCollision(1, emask)) {
|
||||
k->dir *= -1;
|
||||
}else{
|
||||
//Turn when on an edge
|
||||
k->mask.x += k->mask.w * k->dir;
|
||||
k->mask.y += 1;
|
||||
PHL_Rect collide = getTileCollision(1, k->mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, k->mask);
|
||||
}
|
||||
if (collide.x == -1) {
|
||||
k->dir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (k->x + 20 >= 640 || k->x + 20 <= 0) {
|
||||
k->dir *= -1;
|
||||
}
|
||||
|
||||
k->mask.x = k->x + 4;
|
||||
k->mask.y = k->y + 8;
|
||||
|
||||
k->timer -= 1;
|
||||
if (k->timer <= 0) {
|
||||
k->state = 1;
|
||||
k->timer = 120;
|
||||
k->imageIndex = 0;
|
||||
}
|
||||
}
|
||||
else if (k->state == 1) { //Wait
|
||||
k->timer -= 1;
|
||||
if (k->timer <= 0) {
|
||||
k->state = 0;
|
||||
k->dir = 1;
|
||||
if (herox < k->x + 20) {
|
||||
k->dir = -1;
|
||||
}
|
||||
k->timer = 60 + (((rand() % 5) + 1) * 60);
|
||||
}
|
||||
}
|
||||
|
||||
//Green Sword Knight
|
||||
if (k->type == 0) {
|
||||
//Hit player
|
||||
Mask swordMask;
|
||||
swordMask.unused = 0;
|
||||
swordMask.circle = 0;
|
||||
swordMask.x = k->x + (24 * k->dir);
|
||||
swordMask.y = k->y + 20;
|
||||
swordMask.w = 40;
|
||||
swordMask.h = 10;
|
||||
|
||||
if (checkCollision(getHeroMask(), swordMask)) {
|
||||
heroHit(30, k->x + 20);
|
||||
}
|
||||
}
|
||||
|
||||
if (checkCollision(getHeroMask(), k->mask)) {
|
||||
heroHit(15, k->x + 20);
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(k->mask, weapons[i]->weaponMask)) {
|
||||
char gotHit = 1;
|
||||
|
||||
int weapondir = weapons[i]->dir;
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
//Shield Collision
|
||||
if (k->type == 1) {
|
||||
if (weapondir == k->dir * -1) {
|
||||
gotHit = 0;
|
||||
k->shieldhit = 15;
|
||||
PHL_PlaySound(sounds[sndHit03], CHN_WEAPONS);
|
||||
}
|
||||
}
|
||||
|
||||
if (gotHit == 1) {
|
||||
k->hp -= 1;
|
||||
k->invincible = 15;
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
|
||||
if (k->hp <= 0) {
|
||||
knightDestroy(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void knightDraw(Knight* k)
|
||||
{
|
||||
if (k->invincible % 2 == 0) {
|
||||
int cx = 0, cy = 200;
|
||||
|
||||
//Green Knight's Sword
|
||||
if (k->type == 0) {
|
||||
int swordimg = 0;
|
||||
if (k->dir == -1) {
|
||||
swordimg = 1;
|
||||
}
|
||||
int posx = 24, posy = 8;
|
||||
if ((int)k->imageIndex == 1) {
|
||||
posx -= 2;
|
||||
posy -= 2;
|
||||
}
|
||||
PHL_DrawSurfacePart(k->x + (posx * k->dir), k->y + posy, 160 + (swordimg * 40), 200, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
|
||||
//Shield Knight
|
||||
if (k->type == 1) {
|
||||
cx = 240;
|
||||
}
|
||||
|
||||
if (k->dir == -1) {
|
||||
cx += 80;
|
||||
}
|
||||
PHL_DrawSurfacePart(k->x, k->y, cx + ((int)k->imageIndex * 40), cy, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
||||
|
||||
void knightDestroy(Knight* k)
|
||||
{
|
||||
createEffect(2, k->x - 12, k->y - 6);
|
||||
spawnCollectable(k->x + 20, k->y);
|
||||
enemyDestroy(k->id);
|
||||
}
|
23
contrib/games/hydracastlelabyrinth/src/enemies/knight.h
Normal file
23
contrib/games/hydracastlelabyrinth/src/enemies/knight.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef KNIGHT_H
|
||||
#define KNIGHT_H
|
||||
|
||||
#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id, type;
|
||||
double x, y,
|
||||
vsp, grav;
|
||||
int dir, state, timer;
|
||||
double imageIndex;
|
||||
int hp, invincible;
|
||||
int shieldhit;
|
||||
|
||||
Mask mask;
|
||||
} Knight;
|
||||
|
||||
void createKnight(int x, int y, int type);
|
||||
|
||||
void knightStep(Knight* k);
|
||||
void knightDraw(Knight* k);
|
||||
|
||||
#endif
|
367
contrib/games/hydracastlelabyrinth/src/enemies/lolidra.c
Normal file
367
contrib/games/hydracastlelabyrinth/src/enemies/lolidra.c
Normal file
@ -0,0 +1,367 @@
|
||||
#include "lolidra.h"
|
||||
#include "../enemy.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
int boss5flag = 38;
|
||||
|
||||
void lolidraDestroy(Lolidra* l);
|
||||
int getNumOfMinions();
|
||||
|
||||
void createLolidra(int x, int y)
|
||||
{
|
||||
if (flags[boss5flag] == 0) { //have not beaten boss 5
|
||||
PHL_FreeSurface(images[imgBoss]);
|
||||
images[imgBoss] = PHL_LoadQDA("boss05.bmp");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
//Boss start
|
||||
setBossRoom();
|
||||
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Lolidra* l = malloc(sizeof *l);
|
||||
l->id = i;
|
||||
|
||||
l->x = x;
|
||||
l->y = y;
|
||||
|
||||
l->positionY = l->y;
|
||||
|
||||
l->imageIndex = 0;
|
||||
l->hoverRot = 0;
|
||||
|
||||
l->hp = 100;
|
||||
//l->hp = 1;
|
||||
l->state = 0;
|
||||
l->invincible = 0;
|
||||
l->visible = 1;
|
||||
|
||||
l->timer = 0;
|
||||
l->counter = 0;
|
||||
|
||||
l->mask.unused = 0;
|
||||
l->mask.circle = 1;
|
||||
l->mask.w = 46;
|
||||
l->mask.h = 0;
|
||||
l->mask.x = l->x;
|
||||
l->mask.y = l->y;
|
||||
|
||||
e->data = l;
|
||||
e->enemyStep = lolidraStep;
|
||||
e->enemyDraw = lolidraDraw;
|
||||
e->type = 44;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lolidraStep(Lolidra* l)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
l->imageIndex += 0.1;
|
||||
if (l->imageIndex >= 3) {
|
||||
l->imageIndex -= 3;
|
||||
}
|
||||
|
||||
if (l->invincible > 0) {
|
||||
l->invincible -= 1;
|
||||
}
|
||||
|
||||
//Spawn minions
|
||||
if (l->state == 0)
|
||||
{
|
||||
if (l->counter < 5) {
|
||||
l->counter += 1;
|
||||
}else{
|
||||
if (getNumOfMinions() < 10) {
|
||||
l->counter = 0;
|
||||
PHL_PlaySound(sounds[sndPi02], CHN_ENEMIES);
|
||||
createMinion(l->x, l->y - 10);
|
||||
}
|
||||
}
|
||||
|
||||
l->timer += 1;
|
||||
if (l->timer >= 600){
|
||||
l->counter = 0;
|
||||
l->timer = 0;
|
||||
l->state = 1;
|
||||
l->invincible = 20;
|
||||
}
|
||||
}
|
||||
//Disappear
|
||||
else if (l->state == 1 || l->state == 3)
|
||||
{
|
||||
if (l->invincible <= 0) {
|
||||
l->visible = 0;
|
||||
}
|
||||
|
||||
if (l->timer == 0) {
|
||||
PHL_PlaySound(sounds[sndPi10], CHN_ENEMIES);
|
||||
}
|
||||
|
||||
l->timer += 1;
|
||||
if (l->timer >= 330) {
|
||||
PHL_PlaySound(sounds[sndPi03], CHN_ENEMIES);
|
||||
l->timer = 0;
|
||||
l->visible = 1;
|
||||
l->invincible = 20;
|
||||
l->x = herox;
|
||||
l->positionY = heroy - 40;
|
||||
|
||||
if (l->state == 1) {
|
||||
l->state = 2;
|
||||
}
|
||||
if (l->state == 3) {
|
||||
l->state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Pop-up
|
||||
else if (l->state == 2)
|
||||
{
|
||||
l->timer += 1;
|
||||
if (l->timer >= 180) {
|
||||
l->timer = 0;
|
||||
l->state = 3;
|
||||
l->invincible = 20;
|
||||
}
|
||||
}
|
||||
//Death
|
||||
else if (l->state == 4)
|
||||
{
|
||||
l->y += 0.2;
|
||||
|
||||
l->timer -= 1;
|
||||
l->invincible -= 1;
|
||||
|
||||
if (l->timer % 12 == 0) {
|
||||
createEffect(2, l->x - 64 + (rand() % 128), l->y - 64 + (rand() % 128));
|
||||
}
|
||||
|
||||
if (l->timer <= 0) {
|
||||
lolidraDestroy(l);
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dead == 0)
|
||||
{
|
||||
if (l->state != 4) {
|
||||
//Hover
|
||||
l->hoverRot += 5;
|
||||
if (l->hoverRot >= 360) {
|
||||
l->hoverRot -= 360;
|
||||
}
|
||||
l->y = l->positionY + (5 * sin(l->hoverRot * 3.14159 / 180));
|
||||
|
||||
//Update Mask
|
||||
l->mask.x = l->x;
|
||||
l->mask.y = l->y;
|
||||
|
||||
//Collisions
|
||||
if (l->visible == 1) {
|
||||
//Collide with Hero
|
||||
if (checkCollision(getHeroMask(), l->mask) == 1) {
|
||||
heroHit(30, l->x);
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(l->mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
l->invincible = 15;
|
||||
l->hp -= 1;
|
||||
|
||||
//Die
|
||||
if (l->hp <= 0) {
|
||||
l->state = 4;
|
||||
l->timer = 180;
|
||||
l->invincible = 200;
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void lolidraDraw(Lolidra* l)
|
||||
{
|
||||
if (l->visible == 1 && l->invincible % 2 == 0) {
|
||||
PHL_DrawSurfacePart(l->x - 64, l->y - 74, ((int)l->imageIndex) * 128, 0, 128, 128, images[imgBoss]);
|
||||
}
|
||||
}
|
||||
|
||||
void lolidraDestroy(Lolidra* l)
|
||||
{
|
||||
enemyDestroy(l->id);
|
||||
bossDefeatedFlag = 1;
|
||||
roomSecret = 1;
|
||||
|
||||
flags[boss5flag] = 1;
|
||||
PHL_StopMusic();
|
||||
}
|
||||
|
||||
//Minions
|
||||
void createMinion(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Minion* m = malloc(sizeof *m);
|
||||
m->id = i;
|
||||
|
||||
m->state = 0;
|
||||
m->timer = 0;
|
||||
|
||||
m->x = x;
|
||||
m->y = y;
|
||||
|
||||
m->positionY = m->y;
|
||||
|
||||
m->dir = rand() % 360;
|
||||
m->spd = 8;
|
||||
|
||||
m->imageIndex = 0;
|
||||
|
||||
m->mask.circle = 1;
|
||||
m->mask.unused = 0;
|
||||
m->mask.w = 10;
|
||||
m->mask.x = 0;
|
||||
m->mask.y = 0;
|
||||
|
||||
e->data = m;
|
||||
e->enemyStep = minionStep;
|
||||
e->enemyDraw = minionDraw;
|
||||
e->type = 23;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void minionStep(Minion* m)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
m->imageIndex += 0.2;
|
||||
if (m->imageIndex >= 2) {
|
||||
m->imageIndex -= 2;
|
||||
}
|
||||
|
||||
//Slow down
|
||||
if (m->state == 0)
|
||||
{
|
||||
if (m->spd > 0) {
|
||||
m->spd -= 0.3;
|
||||
}
|
||||
|
||||
if (m->spd <= 0) {
|
||||
m->positionY = m->y;
|
||||
m->spd = 0;
|
||||
m->dir = 0;
|
||||
m->state = 1;
|
||||
}
|
||||
}
|
||||
//Hover
|
||||
else if (m->state == 1)
|
||||
{
|
||||
//Hover
|
||||
m->dir += 5;
|
||||
if (m->dir >= 360) {
|
||||
m->dir -= 360;
|
||||
}
|
||||
m->y = m->positionY + (10 * sin(m->dir * 3.14159 / 180));
|
||||
|
||||
m->timer += 1;
|
||||
if (m->timer >= 120) {
|
||||
m->timer = 0;
|
||||
m->state = 2;
|
||||
m->spd = (rand() % 2) + 1;
|
||||
m->dir = (atan2(heroy + 20 - m->y, m->x - herox) * 180 / 3.14159) + 270;
|
||||
}
|
||||
}
|
||||
//Suicide
|
||||
else if (m->state == 2)
|
||||
{
|
||||
m->timer += 1;
|
||||
if (m->timer >= 120) {
|
||||
createEffect(5, m->x, m->y);
|
||||
enemyDestroy(m->id);
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dead == 0)
|
||||
{
|
||||
//Movement
|
||||
if (m->spd != 0) {
|
||||
m->x += m->spd * sin(m->dir * 3.14159 / 180);
|
||||
m->y += m->spd * cos(m->dir * 3.14159 / 180);
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
m->mask.x = m->x;
|
||||
m->mask.y = m->y;
|
||||
|
||||
//Collide with Hero
|
||||
if (checkCollision(getHeroMask(), m->mask) == 1) {
|
||||
if (heroHit(10, m->x) == 1) {
|
||||
heroPoison();
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(m->mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
createEffect(2, m->x - 32, m->y - 32);
|
||||
enemyDestroy(m->id);
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void minionDraw(Minion* m)
|
||||
{
|
||||
PHL_DrawSurfacePart(m->x - 32, m->y - 32, ((int)m->imageIndex) * 64, 128, 64, 64, images[imgBoss]);
|
||||
}
|
||||
|
||||
int getNumOfMinions()
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] != NULL) {
|
||||
if (enemies[i]->type == 23) {
|
||||
result += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
40
contrib/games/hydracastlelabyrinth/src/enemies/lolidra.h
Normal file
40
contrib/games/hydracastlelabyrinth/src/enemies/lolidra.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef LOLIDRA_H
|
||||
#define LOLIDRA_H
|
||||
|
||||
#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double positionY;
|
||||
double imageIndex, hoverRot;
|
||||
int hp, state, invincible,
|
||||
visible, timer, counter;
|
||||
|
||||
Mask mask;
|
||||
} Lolidra;
|
||||
|
||||
void createLolidra(int x, int y);
|
||||
|
||||
void lolidraStep(Lolidra* l);
|
||||
void lolidraDraw(Lolidra* l);
|
||||
|
||||
//Minion
|
||||
typedef struct {
|
||||
int id;
|
||||
int state;
|
||||
int timer;
|
||||
double x, y;
|
||||
double positionY;
|
||||
double imageIndex;
|
||||
double dir, spd;
|
||||
|
||||
Mask mask;
|
||||
} Minion;
|
||||
|
||||
void createMinion(int x, int y);
|
||||
|
||||
void minionStep(Minion* m);
|
||||
void minionDraw(Minion* m);
|
||||
|
||||
#endif
|
78
contrib/games/hydracastlelabyrinth/src/enemies/pendulum.c
Normal file
78
contrib/games/hydracastlelabyrinth/src/enemies/pendulum.c
Normal file
@ -0,0 +1,78 @@
|
||||
#include "pendulum.h"
|
||||
#include "../enemy.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void createPendulum(int x, int y, int side)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Pendulum* p = malloc(sizeof *p);
|
||||
p->id = i;
|
||||
|
||||
p->x = x;
|
||||
p->y = y;
|
||||
|
||||
p->angle = 0;
|
||||
p->rotCounter = 180;
|
||||
if (side == 1) {
|
||||
p->rotCounter += 180;
|
||||
}
|
||||
|
||||
p->mask.circle = 1;
|
||||
p->mask.unused = 0;
|
||||
p->mask.w = 24;
|
||||
p->mask.x = 0;
|
||||
p->mask.y = 0;
|
||||
|
||||
e->data = p;
|
||||
e->enemyStep = pendulumStep;
|
||||
e->enemyDraw = pendulumDraw;
|
||||
e->type = 22;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pendulumStep(Pendulum* p)
|
||||
{
|
||||
p->rotCounter += 2;
|
||||
if (p->rotCounter >= 360) {
|
||||
p->rotCounter -= 360;
|
||||
}
|
||||
|
||||
p->angle += (3.15 * cos(p->rotCounter * 3.14159 / 180));
|
||||
|
||||
//Update Mask
|
||||
p->mask.x = p->x + (96 * cos((p->angle + 90) * 3.14159 / 180));
|
||||
p->mask.y = p->y + (96 * sin((p->angle + 90) * 3.14159 / 180));
|
||||
|
||||
//Hit Player
|
||||
if (checkCollision(p->mask, getHeroMask())) {
|
||||
heroHit(15, p->mask.x);
|
||||
}
|
||||
}
|
||||
|
||||
void pendulumDraw(Pendulum* p)
|
||||
{
|
||||
int drawX = p->x,
|
||||
drawY = p->y;
|
||||
|
||||
int len[] = {0, 16, 32, 48, 66, 96};
|
||||
int cropX[] = {64, 64, 64, 64, 0, 576};
|
||||
int cropY[] = {128, 128, 128, 128, 128, 64};
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 6; i++) {
|
||||
drawX = p->x + (len[i] * cos((p->angle + 90) * 3.14159 / 180));
|
||||
drawY = p->y + (len[i] * sin((p->angle + 90) * 3.14159 / 180));
|
||||
|
||||
PHL_DrawSurfacePart(drawX- 32, drawY - 32, cropX[i], cropY[i], 64, 64, images[imgMisc32]);
|
||||
}
|
||||
}
|
19
contrib/games/hydracastlelabyrinth/src/enemies/pendulum.h
Normal file
19
contrib/games/hydracastlelabyrinth/src/enemies/pendulum.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef PENDULUM_H
|
||||
#define PENDULUM_H
|
||||
|
||||
#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double rotCounter, angle;
|
||||
|
||||
Mask mask;
|
||||
} Pendulum;
|
||||
|
||||
void createPendulum(int x, int y, int side);
|
||||
|
||||
void pendulumStep(Pendulum* p);
|
||||
void pendulumDraw(Pendulum* p);
|
||||
|
||||
#endif
|
176
contrib/games/hydracastlelabyrinth/src/enemies/podoboo.c
Normal file
176
contrib/games/hydracastlelabyrinth/src/enemies/podoboo.c
Normal file
@ -0,0 +1,176 @@
|
||||
#include "podoboo.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include "../game.h"
|
||||
#include "../effect.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void podobooStep(Podoboo* p);
|
||||
void podobooDraw(Podoboo* p);
|
||||
|
||||
void createPodoboo(int x, int y, int offset, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Podoboo* p = malloc(sizeof *p);
|
||||
|
||||
p->id = i;
|
||||
|
||||
p->x = x;
|
||||
p->y = p->ystart = y;
|
||||
|
||||
p->hp = 2;
|
||||
p->blink = 0;
|
||||
|
||||
p->yoffset = p->rot = 0;
|
||||
|
||||
p->vsp = 0;
|
||||
p->grav = 0.13;
|
||||
|
||||
p->jumpheight = -5;
|
||||
/*
|
||||
if (height == 1) {
|
||||
p->jumpheight = -5.4;
|
||||
}
|
||||
*/
|
||||
if (height == 1) {
|
||||
p->jumpheight = -7;
|
||||
}
|
||||
|
||||
p->imageIndex = 0;
|
||||
|
||||
p->timer = 30 * offset;
|
||||
p->state = 0;
|
||||
|
||||
e->data = p;
|
||||
e->enemyStep = podobooStep;
|
||||
e->enemyDraw = podobooDraw;
|
||||
e->type = 15;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void podobooStep(Podoboo* p)
|
||||
{
|
||||
//Blinking
|
||||
{
|
||||
if (p->blink > 0) {
|
||||
p->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
p->timer -= 1;
|
||||
|
||||
//Patterns
|
||||
{
|
||||
//Float in lava
|
||||
if (p->state == 0)
|
||||
{
|
||||
//Animate
|
||||
p->imageIndex += 0.1;
|
||||
if (p->imageIndex >= 2) {
|
||||
p->imageIndex -= 2;
|
||||
}
|
||||
|
||||
//Bob movement
|
||||
p->rot += 5;
|
||||
if (p->rot >= 360) {
|
||||
p->rot -= 360;
|
||||
}
|
||||
p->y = p->ystart + (5 * sin(p->rot * 3.14159 / 180));
|
||||
|
||||
//Jump
|
||||
if (p->timer <= 0) {
|
||||
p->state = 1;
|
||||
createLavaSplash(p->x + 20, p->y);
|
||||
|
||||
p->y = p->ystart;
|
||||
p->vsp = p->jumpheight;
|
||||
}
|
||||
}
|
||||
//In air
|
||||
else if (p->state == 1)
|
||||
{
|
||||
//Animate
|
||||
p->imageIndex += 0.25;
|
||||
if (p->imageIndex >= 3) {
|
||||
p->imageIndex -= 3;
|
||||
}
|
||||
|
||||
//Movement
|
||||
p->y += p->vsp;
|
||||
p->vsp += p->grav;
|
||||
|
||||
//Land in lava again
|
||||
if (p->vsp > 0 && p->y >= p->ystart) {
|
||||
createLavaSplash(p->x + 20, p->y);
|
||||
p->y = p->ystart;
|
||||
p->state = 0;
|
||||
p->vsp = 0;
|
||||
p->timer = 60;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Create Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.w = mask.h = 30;
|
||||
mask.x = p->x + 5;
|
||||
mask.y = p->y + 5;
|
||||
}
|
||||
|
||||
//Collide with hero
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(15, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
p->hp -= 1;
|
||||
p->blink = 15;
|
||||
|
||||
//Death
|
||||
if (p->hp <= 0) {
|
||||
createEffect(2, p->x - 12, p->y - 12);
|
||||
spawnCollectable(p->x + 20, p->y);
|
||||
enemyDestroy(p->id);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void podobooDraw(Podoboo* p)
|
||||
{
|
||||
if (p->blink % 2 == 0) {
|
||||
int thisImage = p->imageIndex;
|
||||
|
||||
if (p->state == 1) {
|
||||
thisImage += 2;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(p->x, p->y, 280 + (40 * thisImage), 520, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
20
contrib/games/hydracastlelabyrinth/src/enemies/podoboo.h
Normal file
20
contrib/games/hydracastlelabyrinth/src/enemies/podoboo.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef PODOBOO_H
|
||||
#define PODOBOO_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
int ystart;
|
||||
int hp;
|
||||
int blink;
|
||||
int rot;
|
||||
double yoffset;
|
||||
double vsp, grav;
|
||||
double jumpheight;
|
||||
double imageIndex;
|
||||
int timer, state;
|
||||
} Podoboo;
|
||||
|
||||
void createPodoboo(int x, int y, int offset, int height);
|
||||
|
||||
#endif
|
318
contrib/games/hydracastlelabyrinth/src/enemies/poisonknight.c
Normal file
318
contrib/games/hydracastlelabyrinth/src/enemies/poisonknight.c
Normal file
@ -0,0 +1,318 @@
|
||||
#include "poisonknight.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void poisonknightStep(Poisonknight* p);
|
||||
void poisonknightDraw(Poisonknight* p);
|
||||
|
||||
void goopStep(Goop* g);
|
||||
void goopDraw(Goop* g);
|
||||
|
||||
void createPoisonknight(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Poisonknight* p = malloc(sizeof *p);
|
||||
p->id = i;
|
||||
p->hp = 2;
|
||||
|
||||
p->x = x;
|
||||
p->y = y;
|
||||
|
||||
p->imageIndex = 0;
|
||||
|
||||
p->dir = 1;
|
||||
if (herox < p->x) {
|
||||
p->dir = -1;
|
||||
}
|
||||
|
||||
p->blink = 0;
|
||||
p->timer = 0;
|
||||
p->state = 0;
|
||||
|
||||
e->data = p;
|
||||
e->enemyStep = poisonknightStep;
|
||||
e->enemyDraw = poisonknightDraw;
|
||||
e->type = 29;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void poisonknightStep(Poisonknight* p)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Animate
|
||||
{
|
||||
p->imageIndex += 0.1;
|
||||
if (p->imageIndex >= 2) {
|
||||
p->imageIndex -= 2;
|
||||
}
|
||||
|
||||
if (p->blink > 0) {
|
||||
p->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 38;
|
||||
mask.h = 36;
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
mask.y = p->y + (40 - mask.h);
|
||||
}
|
||||
|
||||
//Walk
|
||||
if (p->state == 0) {
|
||||
double hsp = 1;
|
||||
|
||||
p->x += hsp * p->dir;
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
|
||||
//Hit wall
|
||||
if (checkTileCollision(1, mask) == 1) {
|
||||
p->dir *= -1;
|
||||
}
|
||||
|
||||
//On wall edge
|
||||
else {
|
||||
mask.x += mask.w * p->dir;
|
||||
mask.y += 10;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
if (collide.x == -1) {
|
||||
p->dir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
//Hero is close enough
|
||||
{
|
||||
if (p->timer <= 0) {
|
||||
Mask area;
|
||||
area.circle = area.unused = 0;
|
||||
area.x = p->x - 110;
|
||||
area.y = p->y;
|
||||
area.w = 260;
|
||||
area.h = 40;
|
||||
|
||||
if (checkCollision(area, getHeroMask()) == 1) {
|
||||
p->dir = 1;
|
||||
if (herox < p->x + 20) {
|
||||
p->dir = -1;
|
||||
}
|
||||
p->imageIndex = 1;
|
||||
p->timer = 0;
|
||||
p->state = 1;
|
||||
}
|
||||
|
||||
}else{
|
||||
p->timer -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*beat*
|
||||
else if (p->state == 1)
|
||||
{
|
||||
//Animate
|
||||
p->imageIndex = 1;
|
||||
|
||||
p->timer += 1;
|
||||
if (p->timer >= 15) {
|
||||
p->state = 2;
|
||||
p->timer = 0;
|
||||
p->imageIndex = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Shoot goop
|
||||
else if (p->state == 2)
|
||||
{
|
||||
//Shoot goop
|
||||
if (p->timer == 0) {
|
||||
PHL_PlaySound(sounds[sndPi05], CHN_ENEMIES);
|
||||
createGoop(p->x + (20 * p->dir), p->y - 2, p->dir);
|
||||
}
|
||||
|
||||
//Animate
|
||||
p->imageIndex = 2;
|
||||
|
||||
p->timer += 1;
|
||||
if (p->timer >= 25) {
|
||||
p->state = 0;
|
||||
p->timer = 240;
|
||||
}
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
mask.y = p->y + (40 - mask.h);
|
||||
|
||||
|
||||
//Collide with hero
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask()) == 1) {
|
||||
heroHit(15, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
p->hp -= 1;
|
||||
p->blink = 15;
|
||||
|
||||
if (p->hp <= 0) {
|
||||
dead = 1;
|
||||
createEffect(2, p->x - 12, p->y - 6);
|
||||
spawnCollectable(p->x + 20, p->y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy object
|
||||
{
|
||||
if (dead == 1) {
|
||||
enemyDestroy(p->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void poisonknightDraw(Poisonknight* p)
|
||||
{
|
||||
if (p->blink % 2 == 0) {
|
||||
int cropX = (int)p->imageIndex * 40;
|
||||
|
||||
if (p->dir == -1) {
|
||||
cropX += 120;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(p->x, p->y, cropX, 280, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
||||
|
||||
//Poison Goop
|
||||
void createGoop(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Goop* g = malloc(sizeof *g);
|
||||
g->id = i;
|
||||
|
||||
g->x = x;
|
||||
g->y = y;
|
||||
|
||||
g->dir = dir;
|
||||
|
||||
g->imageIndex = 0;
|
||||
|
||||
e->data = g;
|
||||
e->enemyStep = goopStep;
|
||||
e->enemyDraw = goopDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void goopStep(Goop* g)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Animate
|
||||
{
|
||||
g->imageIndex += 0.33;
|
||||
if (g->imageIndex >= 3) {
|
||||
g->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
int hsp = 4;
|
||||
g->x += hsp * g->dir;
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 22;
|
||||
mask.h = 22;
|
||||
mask.x = g->x + ((40 - mask.w) / 2);
|
||||
mask.y = g->y + ((40 - mask.h) / 2);
|
||||
}
|
||||
|
||||
//Collide with hero
|
||||
{
|
||||
//Collide with shield
|
||||
if (checkCollision(mask, shieldMask) == 1) {
|
||||
dead = 1;
|
||||
PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
|
||||
createEffect(1, g->x, g->y);
|
||||
}
|
||||
//Collide with hero
|
||||
else if (checkCollision(mask, getHeroMask()) == 1) {
|
||||
if (heroHit(10, mask.x + (mask.w / 2)) == 1) {
|
||||
heroPoison();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Collide with wall
|
||||
{
|
||||
if (checkTileCollision(1, mask) == 1) {
|
||||
dead = 1;
|
||||
createEffect(1, g->x, g->y);
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy if out of room
|
||||
{
|
||||
if (g->x + 40 < 0 || g->x > 640) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy object
|
||||
{
|
||||
if (dead == 1) {
|
||||
enemyDestroy(g->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void goopDraw(Goop* g)
|
||||
{
|
||||
int cropX = 400 + ((int)g->imageIndex * 40);
|
||||
|
||||
if (g->dir == -1) {
|
||||
cropX += 120;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(g->x, g->y, cropX, 520, 40, 40, images[imgMisc20]);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#ifndef POISONKNIGHT_H
|
||||
#define POISONKNIGHT_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
double x, y;
|
||||
double imageIndex;
|
||||
int dir;
|
||||
int blink;
|
||||
int timer;
|
||||
int state;
|
||||
} Poisonknight;
|
||||
|
||||
void createPoisonknight(int x, int y);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
int dir;
|
||||
double imageIndex;
|
||||
} Goop;
|
||||
|
||||
void createGoop(int x, int y, int dir);
|
||||
|
||||
#endif
|
375
contrib/games/hydracastlelabyrinth/src/enemies/pumpkin.c
Normal file
375
contrib/games/hydracastlelabyrinth/src/enemies/pumpkin.c
Normal file
@ -0,0 +1,375 @@
|
||||
#include "pumpkin.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void pumpkinenemyStep(Pumpkinenemy* p);
|
||||
void pumpkinenemyDraw(Pumpkinenemy* p);
|
||||
|
||||
void pumpkinheadStep(Pumpkinhead* p);
|
||||
void pumpkinheadDraw(Pumpkinhead* p);
|
||||
|
||||
void createPumpkinenemy(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Pumpkinenemy* p = malloc(sizeof *p);
|
||||
|
||||
p->id = i;
|
||||
|
||||
p->hp = 3;
|
||||
p->blink = 0;
|
||||
|
||||
p->x = x;
|
||||
p->y = y;
|
||||
|
||||
p->dir = 1;
|
||||
if (herox < p->x + 20) {
|
||||
p->dir = -1;
|
||||
}
|
||||
|
||||
p->imageIndex = 0;
|
||||
|
||||
p->state = 0;
|
||||
p->timer = 0;
|
||||
|
||||
e->data = p;
|
||||
e->enemyStep = pumpkinenemyStep;
|
||||
e->enemyDraw = pumpkinenemyDraw;
|
||||
e->type = 32;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pumpkinenemyStep(Pumpkinenemy* p)
|
||||
{
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.w = 20;
|
||||
mask.h = 38;
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
mask.y = p->y + (40 - mask.h);
|
||||
}
|
||||
|
||||
//Animate
|
||||
{
|
||||
p->imageIndex += 0.1;
|
||||
if (p->imageIndex >= 2) {
|
||||
p->imageIndex -= 2;
|
||||
}
|
||||
|
||||
if (p->blink > 0) {
|
||||
p->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Walking
|
||||
if (p->state == 0)
|
||||
{
|
||||
double hsp = 0.5;
|
||||
p->x += hsp * p->dir;
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
|
||||
//Hit wall
|
||||
{
|
||||
if (checkTileCollision(1, mask) == 1 || mask.x > 640 || mask.x + mask.w < 0) {
|
||||
p->dir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
//On edge
|
||||
{
|
||||
mask.x += mask.w * p->dir;
|
||||
mask.y += 20;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
if (collide.x == -1) {
|
||||
p->dir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
//Player is close
|
||||
{
|
||||
if (p->timer <= 0) {
|
||||
Mask area;
|
||||
{
|
||||
area.circle = area.unused = 0;
|
||||
area.w = 240;
|
||||
area.h = 80;
|
||||
area.x = p->x - 100;
|
||||
area.y = p->y - 40;
|
||||
}
|
||||
if (checkCollision(area, getHeroMask()) == 1) {
|
||||
p->state = 1;
|
||||
p->timer = 0;
|
||||
p->dir = 1;
|
||||
if (herox < p->x + 20) {
|
||||
p->dir = -1;
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
p->timer -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Deheaded
|
||||
else if (p->state == 1) {
|
||||
//Animate
|
||||
{
|
||||
p->imageIndex = 0;
|
||||
if (p->timer >= 15) {
|
||||
p->imageIndex = 2;
|
||||
}
|
||||
}
|
||||
|
||||
p->timer += 1;
|
||||
if (p->timer == 15) {
|
||||
createPumpkinhead(p->x, p->y - 6, p->dir);
|
||||
PHL_PlaySound(sounds[sndPi05], CHN_ENEMIES);
|
||||
}
|
||||
|
||||
if (p->timer >= 40) {
|
||||
p->state = 0;
|
||||
p->imageIndex = 0;
|
||||
p->timer = 300;
|
||||
}
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
mask.y = p->y + (40 - mask.h);
|
||||
|
||||
//Hero Collision
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask()) == 1) {
|
||||
heroHit(15, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon Collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
p->hp -= 1;
|
||||
p->blink = 15;
|
||||
|
||||
//Death
|
||||
if (p->hp <= 0) {
|
||||
createEffect(2, p->x - 12, p->y - 6);
|
||||
spawnCollectable(p->x + 20, p->y);
|
||||
enemyDestroy(p->id);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void pumpkinenemyDraw(Pumpkinenemy* p)
|
||||
{
|
||||
if (p->blink % 2 == 0) {
|
||||
int cropX = (int)p->imageIndex * 40;
|
||||
|
||||
if (p->dir == -1) {
|
||||
cropX += 120;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(p->x, p->y, cropX, 560, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Pumpkin bomb head
|
||||
void createPumpkinhead(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Pumpkinhead* p = malloc(sizeof *p);
|
||||
p->id = i;
|
||||
|
||||
p->dir = dir;
|
||||
|
||||
p->x = x;
|
||||
p->y = y;
|
||||
|
||||
p->vsp = -2;
|
||||
|
||||
p->imageIndex = 0;
|
||||
|
||||
p->state = 0;
|
||||
p->timer = 0;
|
||||
|
||||
e->data = p;
|
||||
e->enemyStep = pumpkinheadStep;
|
||||
e->enemyDraw = pumpkinheadDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pumpkinheadStep(Pumpkinhead* p)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = mask.unused = 0;
|
||||
mask.w = 20;
|
||||
mask.h = 22;
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
mask.y = p->y + ((40 - mask.h) / 2);
|
||||
}
|
||||
|
||||
//Pumpkin head
|
||||
if (p->state == 0)
|
||||
{
|
||||
char explode = 0;
|
||||
|
||||
//Animate
|
||||
{
|
||||
p->imageIndex += 0.1;
|
||||
if (p->imageIndex >= 2) {
|
||||
p->imageIndex -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
int hsp = 3;
|
||||
p->x += hsp * p->dir;
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
p->x = collide.x + 20 - ((20 + (mask.w / 2)) * p->dir) - 20;
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
p->dir *= -1;
|
||||
}
|
||||
|
||||
double grav = 0.15;
|
||||
p->y += p->vsp;
|
||||
p->vsp += grav;
|
||||
mask.y = p->y + ((40 - mask.h) / 2);
|
||||
|
||||
collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
|
||||
if (collide.x != -1) {
|
||||
p->y = collide.y - 40;
|
||||
explode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
mask.x = p->x + ((40 - mask.w) / 2);
|
||||
mask.y = p->y + ((40 - mask.h) / 2);
|
||||
|
||||
//Explode
|
||||
{
|
||||
if (explode == 1) {
|
||||
PHL_PlaySound(sounds[sndBom03], CHN_ENEMIES);
|
||||
p->state = 1;
|
||||
p->imageIndex = 0;
|
||||
p->timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Outside of room
|
||||
{
|
||||
if (mask.y > 480 || mask.x > 640 || mask.x + mask.w < 0) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Explosion
|
||||
else if (p->state == 1)
|
||||
{
|
||||
//Update Mask
|
||||
{
|
||||
mask.w = 68;
|
||||
mask.h = 66;
|
||||
mask.x = p->x - 44 + 64 - (mask.w / 2);
|
||||
mask.y = p->y - 44 + (84 - mask.h);
|
||||
}
|
||||
|
||||
//Animate
|
||||
{
|
||||
p->imageIndex += 0.33;
|
||||
if (p->imageIndex >= 12) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Hero Collision
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask()) == 1) {
|
||||
heroHit(40, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy object
|
||||
{
|
||||
if (dead == 1) {
|
||||
enemyDestroy(p->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pumpkinheadDraw(Pumpkinhead* p)
|
||||
{
|
||||
if (p->state == 0) {
|
||||
int cropX = (int)p->imageIndex * 40;
|
||||
|
||||
if (p->dir == -1) {
|
||||
cropX += 80;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(p->x, p->y, cropX, 240, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
|
||||
if (p->state == 1) {
|
||||
int cropX = (int)p->imageIndex * 128;
|
||||
int cropY = 0;
|
||||
|
||||
while (cropX >= 640) {
|
||||
cropX -= 640;
|
||||
cropY += 96;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(p->x - 44, p->y - 44, cropX, cropY, 128, 96, images[imgExplosion]);
|
||||
}
|
||||
}
|
27
contrib/games/hydracastlelabyrinth/src/enemies/pumpkin.h
Normal file
27
contrib/games/hydracastlelabyrinth/src/enemies/pumpkin.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef PUMPKIN_H
|
||||
#define PUMPKIN_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
int blink;
|
||||
double x, y;
|
||||
int dir;
|
||||
double imageIndex;
|
||||
int state, timer;
|
||||
} Pumpkinenemy;
|
||||
|
||||
void createPumpkinenemy(int x, int y);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int dir;
|
||||
double x, y;
|
||||
double vsp;
|
||||
double imageIndex;
|
||||
int state, timer;
|
||||
} Pumpkinhead;
|
||||
|
||||
void createPumpkinhead(int x, int y, int dir);
|
||||
|
||||
#endif
|
204
contrib/games/hydracastlelabyrinth/src/enemies/seal.c
Normal file
204
contrib/games/hydracastlelabyrinth/src/enemies/seal.c
Normal file
@ -0,0 +1,204 @@
|
||||
#include "seal.h"
|
||||
#include "../game.h"
|
||||
#include "../enemy.h"
|
||||
#include "../collision.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void sealStep(Seal* s);
|
||||
void sealDraw(Seal* s);
|
||||
|
||||
void createSeal(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Seal* s = malloc(sizeof *s);
|
||||
s->id = i;
|
||||
s->hp = 2;
|
||||
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
|
||||
s->imageIndex = 0;
|
||||
|
||||
s->dir = 1;
|
||||
if (x + 20 > herox) {
|
||||
s->dir = -1;
|
||||
}
|
||||
|
||||
s->state = 0;
|
||||
s->timer = 0;
|
||||
|
||||
s->invincible = 0;
|
||||
|
||||
e->data = s;
|
||||
e->enemyStep = sealStep;
|
||||
e->enemyDraw = sealDraw;
|
||||
e->type = 19;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sealStep(Seal* s)
|
||||
{
|
||||
if (s->invincible > 0) {
|
||||
s->invincible -= 1;
|
||||
}
|
||||
|
||||
Mask mask;
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.w = mask.h = 28;
|
||||
mask.x = s->x + ((40 - mask.w) / 2);
|
||||
mask.y = s->y + (40 - mask.h);
|
||||
|
||||
//Walk
|
||||
if (s->state == 0)
|
||||
{
|
||||
//Animate
|
||||
s->imageIndex += 0.1;
|
||||
if (s->imageIndex >= 2) {
|
||||
s->imageIndex -= 2;
|
||||
}
|
||||
|
||||
//Check if hit a wall
|
||||
if (checkTileCollision(1, mask) == 1) {
|
||||
s->dir *= -1;
|
||||
}else{
|
||||
//Check if on edge
|
||||
mask.x += mask.w * s->dir;
|
||||
mask.y += mask.h;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
if (collide.x == -1) {
|
||||
s->dir *= -1;
|
||||
}
|
||||
|
||||
mask.x = s->x + ((40 - mask.w) / 2);
|
||||
mask.y = s->y + (40 - mask.h);
|
||||
}
|
||||
|
||||
//Movement
|
||||
s->x += 0.5 * s->dir;
|
||||
|
||||
if (s->timer <= 0) {
|
||||
//Check if player is close enough
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.x = s->x - 40;
|
||||
area.y = s->y;
|
||||
area.w = 120;
|
||||
area.h = 120;
|
||||
|
||||
if (checkCollision(area, getHeroMask()) == 1) {
|
||||
s->state = 1;
|
||||
s->timer = -1;
|
||||
}
|
||||
}else{
|
||||
s->timer -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Rear back
|
||||
else if (s->state == 1)
|
||||
{
|
||||
//Setup
|
||||
if (s->timer == -1) {
|
||||
s->imageIndex = 4;
|
||||
s->timer = 20;
|
||||
}
|
||||
|
||||
s->timer -= 1;
|
||||
|
||||
if (s->timer <= 0) {
|
||||
s->state = 2;
|
||||
s->timer = -1;
|
||||
s->imageIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Tounge attack
|
||||
else if (s->state == 2)
|
||||
{
|
||||
//Setup
|
||||
if (s->timer == -1) {
|
||||
s->timer = 0;
|
||||
PHL_PlaySound(sounds[sndGet01], CHN_ENEMIES);
|
||||
}
|
||||
|
||||
//Animate
|
||||
int animation[41] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 3, 3,
|
||||
2, 2, 1, 1, 0, 0, 5, 5, 5, 5, 5 };
|
||||
|
||||
s->imageIndex = animation[(int)s->timer];
|
||||
|
||||
//Update mask height to fit tounge
|
||||
int len[6] = { 18, 38, 58, 64, 66, 0};
|
||||
mask.h += len[(int)s->imageIndex];
|
||||
|
||||
s->timer += 1;
|
||||
|
||||
if (s->timer >= 41) {
|
||||
s->state = 0;
|
||||
s->timer = 120;
|
||||
s->imageIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Hit Player
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(10, s->x + 20);
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
s->hp -= 1;
|
||||
s->invincible = 15;
|
||||
weaponHit(weapons[i]);
|
||||
if (s->hp <= 0) {
|
||||
enemyDestroy(s->id);
|
||||
createEffect(2, s->x - 12, s->y - 6);
|
||||
spawnCollectable(s->x + 20, s->y);
|
||||
}
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sealDraw(Seal* s)
|
||||
{
|
||||
if (s->invincible % 2 == 0) {
|
||||
int cx = 400 + ((int)s->imageIndex * 40);
|
||||
|
||||
if (s->state == 0) {
|
||||
if (s->dir == -1) {
|
||||
cx += 80;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->state == 2) {
|
||||
cx = 600;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(s->x, s->y, cx, 200, 40, 40, images[imgEnemies]);
|
||||
|
||||
//Draw tounge
|
||||
if (s->state == 2) {
|
||||
PHL_DrawSurfacePart(s->x, s->y + 28, 200 + ((int)s->imageIndex * 40), 0, 40, 80, images[imgMisc2040]);
|
||||
}
|
||||
}
|
||||
}
|
14
contrib/games/hydracastlelabyrinth/src/enemies/seal.h
Normal file
14
contrib/games/hydracastlelabyrinth/src/enemies/seal.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef SEAL_H
|
||||
#define SEAL_H
|
||||
|
||||
typedef struct {
|
||||
int id, hp;
|
||||
double x, y;
|
||||
double imageIndex;
|
||||
int dir, state, timer;
|
||||
int invincible;
|
||||
} Seal;
|
||||
|
||||
void createSeal(int x, int y);
|
||||
|
||||
#endif
|
298
contrib/games/hydracastlelabyrinth/src/enemies/skeleton.c
Normal file
298
contrib/games/hydracastlelabyrinth/src/enemies/skeleton.c
Normal file
@ -0,0 +1,298 @@
|
||||
#include "skeleton.h"
|
||||
#include "../enemy.h"
|
||||
#include "../game.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void skeletonStep(Skeleton* s);
|
||||
void skeletonDraw(Skeleton* s);
|
||||
|
||||
void boneStep(Bone* b);
|
||||
void boneDraw(Bone* b);
|
||||
|
||||
void createSkeleton(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Skeleton* s = malloc(sizeof *s);
|
||||
s->id = i;
|
||||
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
|
||||
s->imageIndex = 0;
|
||||
|
||||
s->dir = 1;
|
||||
if (dir == 1) {
|
||||
s->dir = -1;
|
||||
}
|
||||
|
||||
s->hsp = 0.5 * s->dir;
|
||||
|
||||
s->hp = 2;
|
||||
|
||||
s->state = 0;
|
||||
s->timer = 0;
|
||||
s->invincible = 0;
|
||||
|
||||
s->mask.unused = s->mask.circle = 0;
|
||||
s->mask.w = 24;
|
||||
s->mask.h = 36;
|
||||
s->mask.x = s->x + 8;
|
||||
s->mask.y = s->y + 4;
|
||||
|
||||
e->data = s;
|
||||
e->enemyStep = skeletonStep;
|
||||
e->enemyDraw = skeletonDraw;
|
||||
e->type = 17;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void skeletonStep(Skeleton* s)
|
||||
{
|
||||
if (s->invincible > 0) {
|
||||
s->invincible -= 1;
|
||||
}
|
||||
|
||||
//Collide with wall
|
||||
if (checkTileCollision(1, s->mask) == 1) {
|
||||
s->hsp *= -1;
|
||||
}else{
|
||||
//Check if on ledge
|
||||
int tempdir = 1;
|
||||
if (s->hsp < 0) {
|
||||
tempdir = -1;
|
||||
}
|
||||
s->mask.x += tempdir * s->mask.w;
|
||||
s->mask.y += 10;
|
||||
if (checkTileCollision(1, s->mask) == 0 && checkTileCollision(3, s->mask) == 0) {
|
||||
s->hsp *= -1;
|
||||
}
|
||||
s->mask.y -= 10;
|
||||
s->mask.x = s->x + 8;
|
||||
}
|
||||
|
||||
s->x += s->hsp;
|
||||
|
||||
if (s->timer >= 0) {
|
||||
s->timer -= 1;
|
||||
}
|
||||
|
||||
//Walk around
|
||||
if (s->state == 0)
|
||||
{
|
||||
s->imageIndex += 0.1;
|
||||
|
||||
if (s->hsp < 0) {
|
||||
s->dir = -1;
|
||||
s->hsp = -0.5;
|
||||
}else if (s->hsp > 0) {
|
||||
s->dir = 1;
|
||||
s->hsp = 0.5;
|
||||
}else{
|
||||
s->hsp = 0.5 * s->dir;
|
||||
}
|
||||
|
||||
if (s->timer <= 0) {
|
||||
//If hero is too close
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.x = s->x - 80;
|
||||
area.y = s->y - 20;
|
||||
area.w = 200;
|
||||
area.h = 80;
|
||||
|
||||
if (checkCollision(area, getHeroMask()) == 1) {
|
||||
s->state = 1;
|
||||
s->timer = 30;
|
||||
s->hsp = 0;
|
||||
|
||||
s->dir = 1;
|
||||
if (herox < s->mask.x + (s->mask.w / 2)) {
|
||||
s->dir = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Alert
|
||||
else if (s->state == 1)
|
||||
{
|
||||
s->hsp = 0;
|
||||
s->imageIndex += 0.1;
|
||||
|
||||
if (s->timer <= 0) {
|
||||
s->state = 2;
|
||||
s->hsp = 2.5 * -s->dir;
|
||||
PHL_PlaySound(sounds[sndPi05], CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
//Slide backwards
|
||||
else if (s->state == 2)
|
||||
{
|
||||
s->imageIndex = 0;
|
||||
double fric = 0.075;
|
||||
if (s->hsp > 0) {
|
||||
s->hsp -= fric;
|
||||
if (s->hsp <= 0) { s->hsp = 0; }
|
||||
}
|
||||
else if (s->hsp < 0) {
|
||||
s->hsp += fric;
|
||||
if (s->hsp >= 0) { s->hsp = 0; }
|
||||
}
|
||||
|
||||
if (s->hsp == 0) {
|
||||
s->state = 3;
|
||||
s->timer = 30;
|
||||
createBone(s->x, s->y, s->dir);
|
||||
PHL_PlaySound(sounds[sndShot05], CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
//Throw bone
|
||||
else if (s->state == 3)
|
||||
{
|
||||
s->imageIndex += 0.1;
|
||||
if (s->timer <= 0) {
|
||||
s->timer = 0;
|
||||
s->state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->imageIndex >= 2) {
|
||||
s->imageIndex -= 2;
|
||||
}
|
||||
|
||||
//Update mask
|
||||
s->mask.x = s->x + 8;
|
||||
|
||||
//Hit Player
|
||||
if (checkCollision(s->mask, getHeroMask())) {
|
||||
heroHit(10, s->x + 20);
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(s->mask, weapons[i]->weaponMask)) {
|
||||
s->hp -= 1;
|
||||
s->invincible = 15;
|
||||
weaponHit(weapons[i]);
|
||||
if (s->hp <= 0) {
|
||||
createRockSmash(s->x + 20, s->y + 20);
|
||||
spawnCollectable(s->x + 20, s->mask.y + s->mask.h - 40);
|
||||
enemyDestroy(s->id);
|
||||
}
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void skeletonDraw(Skeleton* s)
|
||||
{
|
||||
if (s->invincible % 2 == 0) {
|
||||
int dx = 160 + ((int)s->imageIndex * 40);
|
||||
|
||||
if (s->dir == -1) {
|
||||
dx += 80;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(s->x, s->y, dx, 240, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void createBone(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Bone* b = malloc(sizeof *b);
|
||||
b->id = i;
|
||||
|
||||
b->x = x;
|
||||
b->y = y;
|
||||
|
||||
b->hsp = dir * 0.75;
|
||||
b->vsp = -4;
|
||||
b->grav = 0.1;
|
||||
|
||||
b->imageIndex = 0;
|
||||
|
||||
b->mask.unused = 0;
|
||||
b->mask.circle = 1;
|
||||
b->mask.w = 12;
|
||||
b->mask.h = 12;
|
||||
b->mask.x = b->x + 20;
|
||||
b->mask.y = b->y + 20;
|
||||
|
||||
e->data = b;
|
||||
e->enemyStep = boneStep;
|
||||
e->enemyDraw = boneDraw;
|
||||
e->type = -1;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void boneStep(Bone* b)
|
||||
{
|
||||
if (b->hsp < 0) {
|
||||
b->imageIndex += 0.25;
|
||||
if (b->imageIndex >= 4) {
|
||||
b->imageIndex -= 4;
|
||||
}
|
||||
}
|
||||
else{
|
||||
b->imageIndex -= 0.25;
|
||||
if (b->imageIndex < 0) {
|
||||
b->imageIndex += 4;
|
||||
}
|
||||
}
|
||||
|
||||
b->x += b->hsp;
|
||||
|
||||
b->y += b->vsp;
|
||||
b->vsp += b->grav;
|
||||
|
||||
//Update Mask
|
||||
b->mask.x = b->x + 20;
|
||||
b->mask.y = b->y + 20;
|
||||
|
||||
if (b->y > 480) {
|
||||
enemyDestroy(b->id);
|
||||
}
|
||||
|
||||
//Hit Player
|
||||
if (checkCollision(b->mask, shieldMask)) {
|
||||
enemyDestroy(b->id);
|
||||
PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
|
||||
createEffect(1, b->x, b->y);
|
||||
}else{
|
||||
if (checkCollision(b->mask, getHeroMask())) {
|
||||
heroHit(10, b->x + 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void boneDraw(Bone* b)
|
||||
{
|
||||
int img = 320 + ((int)b->imageIndex * 40);
|
||||
if (b->hsp > 0) {
|
||||
img += 160;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(b->x, b->y, img, 240, 40, 40, images[imgEnemies]);
|
||||
}
|
31
contrib/games/hydracastlelabyrinth/src/enemies/skeleton.h
Normal file
31
contrib/games/hydracastlelabyrinth/src/enemies/skeleton.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef SKELETON_H
|
||||
#define SKELETON_H
|
||||
|
||||
#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double hsp;
|
||||
double imageIndex;
|
||||
int dir;
|
||||
int hp;
|
||||
int state, timer, invincible;
|
||||
|
||||
Mask mask;
|
||||
} Skeleton;
|
||||
|
||||
void createSkeleton(int x, int y, int dir);
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double hsp, vsp, grav;
|
||||
double imageIndex;
|
||||
|
||||
Mask mask;
|
||||
} Bone;
|
||||
|
||||
void createBone(int x, int y, int dir);
|
||||
|
||||
#endif
|
174
contrib/games/hydracastlelabyrinth/src/enemies/skull.c
Normal file
174
contrib/games/hydracastlelabyrinth/src/enemies/skull.c
Normal file
@ -0,0 +1,174 @@
|
||||
#include "skull.h"
|
||||
#include "../enemy.h"
|
||||
#include "../PHL.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void skullStep(Skull* s);
|
||||
void skullDraw(Skull* s);
|
||||
|
||||
void createSkull(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Skull* s = malloc(sizeof *s);
|
||||
s->id = i;
|
||||
|
||||
//X/Y in center of sprite
|
||||
s->x = x + 20;
|
||||
s->y = y + 20;
|
||||
s->yoffset = 0;
|
||||
|
||||
s->rot = 0;
|
||||
s->state = 0;
|
||||
s->timer = 0;
|
||||
s->imageIndex = 0;
|
||||
s->dir = 0;
|
||||
|
||||
e->data = s;
|
||||
e->enemyStep = skullStep;
|
||||
e->enemyDraw = skullDraw;
|
||||
e->type = 12;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void skullStep(Skull* s)
|
||||
{
|
||||
double imageSpeed = 0;
|
||||
|
||||
//Wait
|
||||
if (s->state == 0)
|
||||
{
|
||||
imageSpeed = 0.2;
|
||||
|
||||
if (s->timer > 0) {
|
||||
s->timer -= 1;
|
||||
}else{
|
||||
Mask tempmask;
|
||||
|
||||
tempmask.unused = tempmask.circle = 0;
|
||||
tempmask.x = s->x - 100;
|
||||
tempmask.y = s->y - 100;
|
||||
tempmask.w = tempmask.h = 200;
|
||||
|
||||
if (checkCollisionXY(tempmask, herox, heroy + 20)) {
|
||||
|
||||
//Calculate distance
|
||||
//int dis = sqrt(pow(s->x - herox, 2) + pow(s->y - (heroy + 20), 2));
|
||||
//if (dis <= 100) {
|
||||
s->state = 1;
|
||||
//s->dir = (rand() % 8) * 45;
|
||||
s->dir = (rand() % 360) + 1;
|
||||
PHL_PlaySound(sounds[sndPi08], CHN_ENEMIES);
|
||||
s->timer = 130;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Chase
|
||||
else if (s->state == 1)
|
||||
{
|
||||
imageSpeed = 0.3;
|
||||
|
||||
int spd = 2;
|
||||
s->x += (spd * cos(s->dir * 3.14159 / 180));
|
||||
s->y += (spd * sin(s->dir * 3.14159 / 180));
|
||||
|
||||
double herodir = ((atan2((heroy + 20) - s->y, herox - s->x) * 180) / 3.14159);
|
||||
if (herodir >= 360) {
|
||||
herodir -= 360;
|
||||
}
|
||||
if (herodir < 0) {
|
||||
herodir += 360;
|
||||
}
|
||||
|
||||
double tempdir = s->dir - herodir;
|
||||
if (tempdir < 0) {
|
||||
tempdir += 360;
|
||||
}
|
||||
|
||||
if (tempdir < 180) {
|
||||
s->dir -= 2;
|
||||
}else{
|
||||
s->dir += 2;
|
||||
}
|
||||
if (s->dir >= 360) {
|
||||
s->dir -= 360;
|
||||
}
|
||||
if (s->dir < 0) {
|
||||
s->dir += 360;
|
||||
}
|
||||
|
||||
s->timer -= 1;
|
||||
if (s->timer <= 0) {
|
||||
s->state = 0;
|
||||
s->timer = 10;
|
||||
}
|
||||
}
|
||||
|
||||
//Animate
|
||||
{
|
||||
s->imageIndex += imageSpeed;
|
||||
if (s->imageIndex >= 4) {
|
||||
s->imageIndex -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
//Hover offset
|
||||
{
|
||||
s->rot += 5;
|
||||
if (s->rot >= 360) {
|
||||
s->rot -= 360;
|
||||
}
|
||||
s->yoffset = (5 * sin(s->rot * 3.14159 / 180));
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = 0;
|
||||
mask.circle = 1;
|
||||
mask.x = s->x;
|
||||
mask.y = s->y;
|
||||
mask.w = mask.h = 10;
|
||||
}
|
||||
|
||||
//Hero collision
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(15, mask.x);
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
createEffect(2, s->x - 32, s->y - 32);
|
||||
spawnCollectable(s->x, s->y - 20);
|
||||
enemyDestroy(s->id);
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void skullDraw(Skull* s)
|
||||
{
|
||||
PHL_DrawSurfacePart(s->x - 20, s->y + s->yoffset - 20, 480 + ((int)s->imageIndex * 40), 40, 40, 40, images[imgEnemies]);
|
||||
}
|
15
contrib/games/hydracastlelabyrinth/src/enemies/skull.h
Normal file
15
contrib/games/hydracastlelabyrinth/src/enemies/skull.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef SKULL_H
|
||||
#define SKULL_H
|
||||
|
||||
typedef struct {
|
||||
int id, state, timer;
|
||||
double x, y;
|
||||
double yoffset;
|
||||
int rot;
|
||||
double dir;
|
||||
double imageIndex;
|
||||
} Skull;
|
||||
|
||||
void createSkull(int x, int y);
|
||||
|
||||
#endif
|
228
contrib/games/hydracastlelabyrinth/src/enemies/slime.c
Normal file
228
contrib/games/hydracastlelabyrinth/src/enemies/slime.c
Normal file
@ -0,0 +1,228 @@
|
||||
#include "slime.h"
|
||||
#include <stdlib.h>
|
||||
#include "../PHL.h"
|
||||
#include "../game.h"
|
||||
#include "../collision.h"
|
||||
#include "../hero.h"
|
||||
#include "../enemy.h"
|
||||
#include "../weapon.h"
|
||||
|
||||
void slimeStep(Slime* s);
|
||||
void slimeDraw(Slime* s);
|
||||
|
||||
void createSlime(int x, int y, int type, int offset)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* result = malloc(sizeof *result);
|
||||
Slime* s = malloc(sizeof *s);
|
||||
|
||||
s->id = i;
|
||||
|
||||
s->x = x + 20;
|
||||
s->y = y;
|
||||
s->type = type;
|
||||
s->offset = offset;
|
||||
|
||||
s->hp = 1;
|
||||
s->state = 0;
|
||||
s->counter = 0;
|
||||
s->timer = 0;
|
||||
s->grav = 0.125;
|
||||
s->vsp = 0;
|
||||
s->hsp = 0;
|
||||
s->imageIndex = 0;
|
||||
|
||||
result->data = s;
|
||||
result->enemyStep = slimeStep;
|
||||
result->enemyDraw = slimeDraw;
|
||||
result->type = 0;
|
||||
|
||||
enemies[i] = result;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void slimeStep(Slime* s)
|
||||
{
|
||||
char dead = 0;
|
||||
|
||||
//Stay within room
|
||||
{
|
||||
if (s->x > 640) {
|
||||
s->x = 640;
|
||||
}
|
||||
|
||||
if (s->x < 0) {
|
||||
s->x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Rectangle Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = 0;
|
||||
mask.circle = 0;
|
||||
mask.w = 24;
|
||||
mask.h = 24;
|
||||
mask.x = s->x - (mask.w / 2);
|
||||
mask.y = s->y + 28 - (mask.h / 2);
|
||||
}
|
||||
|
||||
//Idle
|
||||
if (s->state == 0)
|
||||
{
|
||||
s->imageIndex += 0.25;
|
||||
|
||||
if (s->imageIndex >= 6) {
|
||||
s->imageIndex = 0;
|
||||
|
||||
if (s->offset <= 0) {
|
||||
s->state = 1;
|
||||
|
||||
//Red/Yellow Slime
|
||||
if (s->type == 1 || s->type == 2)
|
||||
{
|
||||
s->hsp = 1;
|
||||
if (s->type == 2) {
|
||||
s->hsp = 1.5;
|
||||
}
|
||||
if ((int)(rand() % 2) == 0) {
|
||||
s->hsp *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->counter < 2) {
|
||||
s->vsp = -2;
|
||||
s->counter += 1;
|
||||
}else{
|
||||
s->vsp = -4;
|
||||
s->counter = 0;
|
||||
}
|
||||
}else{
|
||||
s->offset -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Jump
|
||||
else if (s->state == 1)
|
||||
{
|
||||
//Red/Yellow Slime
|
||||
if (s->type == 1 || s->type == 2)
|
||||
{
|
||||
s->x += s->hsp;
|
||||
mask.x = s->x - (mask.w / 2);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
if (s->hsp > 0) {
|
||||
s->x = collide.x - (mask.w / 2);
|
||||
}else if (s->hsp < 0) {
|
||||
s->x = collide.x + 40 + (mask.w / 2);
|
||||
}
|
||||
}
|
||||
|
||||
mask.x = s->x - (mask.w / 2);
|
||||
}
|
||||
|
||||
s->y += s->vsp;
|
||||
s->vsp += s->grav;
|
||||
|
||||
mask.y = s->y + 28 - (mask.h / 2);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
if (collide.x != -1) {
|
||||
if (s->vsp >= 0) {
|
||||
s->state = 0;
|
||||
s->hsp = 0;
|
||||
s->y = collide.y - 40;
|
||||
}else{
|
||||
s->y = collide.y + 40 - (40 - mask.h) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Collision Mask
|
||||
{
|
||||
mask.unused = 0;
|
||||
mask.circle = 1;
|
||||
mask.w = 12;
|
||||
mask.x = s->x;
|
||||
mask.y = s->y + 28;
|
||||
}
|
||||
|
||||
//Fell in a pit
|
||||
{
|
||||
if (s->y > 480) {
|
||||
dead = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Collide with hero
|
||||
{
|
||||
if (checkCollision(mask, heroMask)) {
|
||||
int dmg[3] = {10, 20, 20};
|
||||
|
||||
if (heroHit(dmg[s->type], s->x) == 1 && s->type == 2) {
|
||||
heroStun();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Sword collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
spawnCollectable(s->x, s->y + 6);
|
||||
createEffect(2, s->x - 32, s->y - 12);
|
||||
dead = 1;
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Destroy object
|
||||
{
|
||||
if (dead == 1) {
|
||||
enemyDestroy(s->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void slimeDraw(Slime* s)
|
||||
{
|
||||
int cropX = 0,
|
||||
cropY = 0;
|
||||
|
||||
//Idle
|
||||
if (s->state == 0) {
|
||||
int image[6] = { 0, 1, 2, 3, 4, 6 };
|
||||
cropX = image[(int)s->imageIndex] * 40;
|
||||
}
|
||||
|
||||
//Jump
|
||||
else if (s->state == 1) {
|
||||
cropX = 200;
|
||||
if (s->vsp >= 0) {
|
||||
cropX += 40;
|
||||
}
|
||||
}
|
||||
|
||||
//Color offsets
|
||||
int addX[3] = {0, 280, 0};
|
||||
int addY[3] = {0, 0, 480};
|
||||
|
||||
PHL_DrawSurfacePart(s->x - 20, s->y + 12, cropX + addX[s->type], cropY + addY[s->type], 40, 40, images[imgEnemies]);
|
||||
}
|
17
contrib/games/hydracastlelabyrinth/src/enemies/slime.h
Normal file
17
contrib/games/hydracastlelabyrinth/src/enemies/slime.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef SLIME_H
|
||||
#define SLIME_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
int type; //0 = blue | 1 = red | 2 = yellow
|
||||
int offset;
|
||||
double vsp, hsp, grav;
|
||||
double imageIndex;
|
||||
int counter, timer, state;
|
||||
int hp;
|
||||
} Slime;
|
||||
|
||||
void createSlime(int x, int y, int type, int offset);
|
||||
|
||||
#endif
|
164
contrib/games/hydracastlelabyrinth/src/enemies/slug.c
Normal file
164
contrib/games/hydracastlelabyrinth/src/enemies/slug.c
Normal file
@ -0,0 +1,164 @@
|
||||
#include "slug.h"
|
||||
#include "../enemy.h"
|
||||
#include "../game.h"
|
||||
#include "../PHL.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void slugStep(Slug* s);
|
||||
void slugDraw(Slug* s);
|
||||
|
||||
void createSlug(int x, int y, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Slug* s = malloc(sizeof *s);
|
||||
s->id = i;
|
||||
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
|
||||
s->imageIndex = 0;
|
||||
s->vsp = 0;
|
||||
|
||||
s->dir = 1;
|
||||
if (dir == 1) {
|
||||
s->dir = -1;
|
||||
}
|
||||
|
||||
e->data = s;
|
||||
e->enemyStep = slugStep;
|
||||
e->enemyDraw = slugDraw;
|
||||
e->type = 2;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void slugStep(Slug* s)
|
||||
{
|
||||
//Create Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.circle = 0;
|
||||
mask.unused = 0;
|
||||
mask.w = 32;
|
||||
mask.h = 24;
|
||||
mask.x = s->x + ((40 - mask.w) / 2);
|
||||
mask.y = s->y + (40 - mask.h);
|
||||
}
|
||||
|
||||
//Animate
|
||||
{
|
||||
s->imageIndex += 0.1;
|
||||
if (s->imageIndex >= 4) {
|
||||
s->imageIndex -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
//Check if on ground
|
||||
int onground = 1;
|
||||
{
|
||||
mask.y += 1;
|
||||
if (checkTileCollision(1, mask) == 0 && checkTileCollision(3, mask) == 0) {
|
||||
onground = 0;
|
||||
}
|
||||
mask.y -= 1;
|
||||
}
|
||||
|
||||
if (onground == 0) {
|
||||
double grav = 0.2;
|
||||
|
||||
//Fall
|
||||
{
|
||||
s->y += s->vsp;
|
||||
s->vsp += grav;
|
||||
}
|
||||
|
||||
//Land on ground
|
||||
{
|
||||
mask.y = mask.y + (40 - mask.h);
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
if (collide.x != -1) {
|
||||
s->y = collide.y - 40;
|
||||
s->vsp = 0;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//Check if on ledge
|
||||
{
|
||||
mask.x += mask.w * s->dir;
|
||||
mask.y += 1;
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
if (collide.x == -1) {
|
||||
s->dir *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Horizontal movement
|
||||
double hsp = 0.5;
|
||||
{
|
||||
s->x += s->dir * hsp;
|
||||
}
|
||||
|
||||
//Check if hit a wall
|
||||
{
|
||||
mask.x = s->x + ((40 - mask.w) / 2);
|
||||
mask.y = s->y + (40 - mask.h);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
s->dir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
//Hit Player
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask()) == 1) {
|
||||
heroHit(15, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask) == 1) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
createEffect(2, s->x - 12, s->y - 6);
|
||||
spawnCollectable(s->x + 20, s->y);
|
||||
enemyDestroy(s->id);
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void slugDraw(Slug* s)
|
||||
{
|
||||
int anim[4] = { 1, 0, 2, 0 };
|
||||
|
||||
int cropx = anim[(int)s->imageIndex] * 40;
|
||||
if (s->dir == -1) {
|
||||
cropx += 120;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(s->x, s->y + 10, cropx, 40, 40, 40, images[imgEnemies]);
|
||||
}
|
13
contrib/games/hydracastlelabyrinth/src/enemies/slug.h
Normal file
13
contrib/games/hydracastlelabyrinth/src/enemies/slug.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef SLUG_H
|
||||
#define SLUG_H
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int dir;
|
||||
double x, y, vsp;
|
||||
double imageIndex;
|
||||
} Slug;
|
||||
|
||||
void createSlug(int x, int y, int dir);
|
||||
|
||||
#endif
|
265
contrib/games/hydracastlelabyrinth/src/enemies/thwomp.c
Normal file
265
contrib/games/hydracastlelabyrinth/src/enemies/thwomp.c
Normal file
@ -0,0 +1,265 @@
|
||||
#include "thwomp.h"
|
||||
#include "../enemy.h"
|
||||
#include "../hero.h"
|
||||
#include "../game.h"
|
||||
#include "../PHL.h"
|
||||
#include "../effect.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void thwompStep(Thwomp* t);
|
||||
void thwompDraw(Thwomp* t);
|
||||
|
||||
void createThwomp(int x, int y, int type, int offset, int delay, int dir)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Thwomp* t = malloc(sizeof *t);
|
||||
|
||||
t->id = i;
|
||||
|
||||
t->x = x;
|
||||
t->y = y;
|
||||
|
||||
t->vsp = 0;
|
||||
t->grav = 0.3;
|
||||
|
||||
t->imageIndex = 0;
|
||||
|
||||
t->type = type;
|
||||
t->state = 0;
|
||||
t->timer = offset * 30;
|
||||
t->delay = delay * 30;
|
||||
//default delay is 60
|
||||
if (delay == 0) {
|
||||
t->delay = 60;
|
||||
}
|
||||
|
||||
t->dir = dir;
|
||||
|
||||
t->hp = 3;
|
||||
t->blink = 0;
|
||||
|
||||
e->data = t;
|
||||
e->enemyStep = thwompStep;
|
||||
e->enemyDraw = thwompDraw;
|
||||
e->type = 16;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void thwompStep(Thwomp* t)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
t->imageIndex += 0.1;
|
||||
if (t->imageIndex >= 3) {
|
||||
t->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
//Counters
|
||||
{
|
||||
if (t->blink > 0) {
|
||||
t->blink -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.w = mask.h = 36;
|
||||
mask.x = t->x + ((40 - mask.w) / 2);
|
||||
mask.y = t->y + ((40 - mask.h) / 2);
|
||||
}
|
||||
|
||||
//Wait
|
||||
if (t->state == 0) {
|
||||
t->vsp = 0;
|
||||
|
||||
//Waiter
|
||||
if (t->type == 0) {
|
||||
Mask area;
|
||||
area.unused = area.circle = 0;
|
||||
area.x = t->x - 40;
|
||||
area.y = t->y;
|
||||
area.w = 120;
|
||||
area.h = 160;
|
||||
|
||||
if (checkCollisionXY(area, herox, heroy)) {
|
||||
t->state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Automatic
|
||||
else{
|
||||
t->timer -= 1;
|
||||
if (t->timer <= 0) {
|
||||
t->state = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Fall
|
||||
else if (t->state == 1) {
|
||||
//Down
|
||||
if (t->dir == 0) {
|
||||
t->y += t->vsp;
|
||||
}
|
||||
//Left
|
||||
if (t->dir == 1) {
|
||||
t->x -= t->vsp;
|
||||
}
|
||||
//Right
|
||||
if (t->dir == 2) {
|
||||
t->x += t->vsp;
|
||||
}
|
||||
|
||||
t->vsp += t->grav;
|
||||
|
||||
if (t->vsp >= 7) {
|
||||
t->vsp = 7;
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
mask.x = t->x + ((40 - mask.w) / 2);
|
||||
mask.y = t->y + ((40 - mask.h) / 2);
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
int effX = t->x,
|
||||
effY = t->y;
|
||||
//Down
|
||||
if (t->dir == 0) {
|
||||
t->y = collide.y - 40;
|
||||
effY = t->y + 20;
|
||||
}
|
||||
//Left
|
||||
if (t->dir == 1) {
|
||||
t->x = collide.x + 40;
|
||||
effX = t->x - 20;
|
||||
}
|
||||
//Right
|
||||
if (t->dir == 2) {
|
||||
t->x = collide.x - 40;
|
||||
effX = t->x + 20;
|
||||
}
|
||||
|
||||
t->state = 2;
|
||||
t->timer = 60;
|
||||
createEffect(1, effX, effY);
|
||||
PHL_PlaySound(sounds[sndHit07], CHN_ENEMIES);
|
||||
}
|
||||
}
|
||||
else if (t->state == 2) {
|
||||
if (t->type == 1) { //Automatic
|
||||
t->timer -= 1;
|
||||
if (t->timer <= 0) {
|
||||
t->state = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t->state == 3) { //rise up
|
||||
//Down
|
||||
if (t->dir == 0) {
|
||||
t->y -= 2;
|
||||
}
|
||||
//Left
|
||||
if (t->dir == 1) {
|
||||
t->x += 2;
|
||||
}
|
||||
//Right
|
||||
if (t->dir == 2) {
|
||||
t->x -= 2;
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
mask.x = t->x + ((40 - mask.w) / 2);
|
||||
mask.y = t->y + ((40 - mask.h) / 2);
|
||||
|
||||
if (t->dir == 0) {
|
||||
mask.y -= 4;
|
||||
}
|
||||
if (t->dir == 1) {
|
||||
mask.x += 4;
|
||||
}
|
||||
if (t->dir == 2) {
|
||||
mask.x -= 4;
|
||||
}
|
||||
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x != -1) {
|
||||
//Down
|
||||
if (t->dir == 0) {
|
||||
t->y = collide.y + 40 + 2;
|
||||
}
|
||||
//Left
|
||||
if (t->dir == 1) {
|
||||
t->x = collide.x - 40 + 2;
|
||||
}
|
||||
//Right
|
||||
if (t->dir == 2) {
|
||||
t->x = collide.x + 40 + 2;
|
||||
}
|
||||
|
||||
t->state = 0;
|
||||
t->timer = t->delay;
|
||||
}
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
{
|
||||
mask.x = t->x + ((40 - mask.w) / 2);
|
||||
mask.y = t->y + ((40 - mask.h) / 2);
|
||||
}
|
||||
|
||||
//Hit Player
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(15, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
if (hasItem[16] == 1) { //Has blue paper
|
||||
t->hp -= 1;
|
||||
t->blink = 15;
|
||||
|
||||
if (t->hp <= 0) {
|
||||
createRockSmash(t->x + 20, t->y + 20);
|
||||
spawnCollectable(t->x + 20, t->y);
|
||||
enemyDestroy(t->id);
|
||||
}
|
||||
}else{
|
||||
//Tink
|
||||
PHL_PlaySound(sounds[sndHit03], CHN_WEAPONS);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void thwompDraw(Thwomp* t)
|
||||
{
|
||||
if (t->blink % 2 == 0) {
|
||||
PHL_DrawSurfacePart(t->x, t->y, 240 + ((int)t->imageIndex * 40), 400, 40, 40, images[imgMisc20]);
|
||||
}
|
||||
}
|
18
contrib/games/hydracastlelabyrinth/src/enemies/thwomp.h
Normal file
18
contrib/games/hydracastlelabyrinth/src/enemies/thwomp.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef THWOMP_H
|
||||
#define THWOMP_H
|
||||
|
||||
//#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double vsp, grav;
|
||||
double imageIndex;
|
||||
int type, state, timer, dir;
|
||||
int hp, blink;
|
||||
int delay;
|
||||
} Thwomp;
|
||||
|
||||
void createThwomp(int x, int y, int type, int offset, int delay, int dir);
|
||||
|
||||
#endif
|
356
contrib/games/hydracastlelabyrinth/src/enemies/waterjumper.c
Normal file
356
contrib/games/hydracastlelabyrinth/src/enemies/waterjumper.c
Normal file
@ -0,0 +1,356 @@
|
||||
#include "waterjumper.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "../game.h"
|
||||
#include "../enemy.h"
|
||||
#include "../hero.h"
|
||||
#include "../collision.h"
|
||||
|
||||
void waterJumperStep(WaterJumper* w);
|
||||
void waterJumperDraw(WaterJumper* w);
|
||||
|
||||
void createWaterJumper(int x, int y, int type, int offset, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
WaterJumper* w = malloc(sizeof *w);
|
||||
w->id = i;
|
||||
w->type = type;
|
||||
|
||||
w->x = x;
|
||||
w->y = w->ystart = y;
|
||||
|
||||
w->hp = 1;
|
||||
|
||||
w->hsp = w->vsp = 0;
|
||||
w->grav = 0.115;
|
||||
w->yoffset = 0;
|
||||
|
||||
w->imageIndex = 0;
|
||||
w->blink = 0;
|
||||
|
||||
w->timer = 60;
|
||||
w->timer += 60 * offset;
|
||||
|
||||
w->rot = 0;
|
||||
w->state = 0;
|
||||
|
||||
if (type == 1) {
|
||||
w->hp = 2;
|
||||
w->timer = 60 * offset;
|
||||
}
|
||||
|
||||
//Specific offset timer
|
||||
if (offset > 10) {
|
||||
w->timer = offset;
|
||||
}
|
||||
|
||||
w->height = height;
|
||||
/*
|
||||
w->mask.unused = w->mask.circle = 0;
|
||||
w->mask.x = x + 8;
|
||||
w->mask.y = y + 8;
|
||||
w->mask.w = 24;
|
||||
w->mask.h = 24;
|
||||
*/
|
||||
e->data = w;
|
||||
e->enemyStep = waterJumperStep;
|
||||
e->enemyDraw = waterJumperDraw;
|
||||
e->type = 14;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void waterJumperStep(WaterJumper* w)
|
||||
{
|
||||
//Counters
|
||||
{
|
||||
if (w->blink > 0) {
|
||||
w->blink -= 1;
|
||||
}
|
||||
|
||||
if (w->timer > 0) {
|
||||
w->timer -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Setup Mask
|
||||
Mask mask;
|
||||
{
|
||||
mask.unused = mask.circle = 0;
|
||||
mask.w = 24;
|
||||
mask.h = 24;
|
||||
mask.x = w->x + ((40 - mask.w) / 2);
|
||||
mask.y = w->y + ((40 - mask.h) / 2);
|
||||
}
|
||||
|
||||
//Float
|
||||
if (w->state == 0)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
w->imageIndex += 0.1;
|
||||
if (w->imageIndex >= 2) {
|
||||
w->imageIndex -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
w->rot += 5;
|
||||
if (w->rot >= 360) {
|
||||
w->rot -= 360;
|
||||
}
|
||||
|
||||
w->y = w->ystart + (5 * sin(w->rot * 3.14159 / 180));
|
||||
}
|
||||
|
||||
//Hop out of water
|
||||
{
|
||||
if (w->timer <= 0) {
|
||||
w->state = 1;
|
||||
w->timer = -1;
|
||||
|
||||
createSplash(w->x + 20, w->y);
|
||||
w->y = w->ystart;
|
||||
}
|
||||
}
|
||||
}
|
||||
//In air
|
||||
else if (w->state == 1)
|
||||
{
|
||||
//Animate
|
||||
{
|
||||
w->imageIndex += 0.25;
|
||||
if (w->imageIndex >= 3) {
|
||||
w->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
//Green type
|
||||
if (w->type == 0)
|
||||
{
|
||||
//State Start
|
||||
{
|
||||
if (w->timer == -1) {
|
||||
w->timer = 0;
|
||||
|
||||
w->vsp = -5.5;
|
||||
w->hsp = -2;
|
||||
if (w->x + 20 < herox) {
|
||||
w->hsp *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Horizontal Movement
|
||||
w->x += w->hsp;
|
||||
|
||||
//Land in water
|
||||
{
|
||||
if (w->vsp > 0 && w->y >= w->ystart) {
|
||||
createSplash(w->x + 20, w->y);
|
||||
w->y = w->ystart;
|
||||
w->state = 0;
|
||||
w->hsp = w->vsp = 0;
|
||||
w->timer = 120;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Blue type
|
||||
else
|
||||
{
|
||||
//State Start
|
||||
{
|
||||
if (w->timer == -1) {
|
||||
w->timer = 0;
|
||||
|
||||
if (w->height == 2) {
|
||||
w->vsp = -5.5;
|
||||
}
|
||||
else if (w->height == 3) {
|
||||
w->vsp = -6;
|
||||
}
|
||||
else if (w->height == 4) {
|
||||
w->vsp = -7;
|
||||
}
|
||||
else if (w->height == 5) {
|
||||
w->vsp = -7.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Land on expected ground
|
||||
{
|
||||
if (w->vsp > 0) {
|
||||
if (w->y >= w->ystart - 22 - (w->height * 40)) {
|
||||
w->y = w->ystart - 22 - (w->height * 40);
|
||||
w->imageIndex = 5;
|
||||
w->state = 2;
|
||||
w->timer = 240;
|
||||
w->hsp = 2;
|
||||
if (herox < w->x + 20) {
|
||||
w->hsp *= -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Vertical Movement
|
||||
w->y += w->vsp;
|
||||
w->vsp += w->grav;
|
||||
|
||||
}
|
||||
|
||||
//Walk
|
||||
else if (w->state == 2) {
|
||||
//Animate
|
||||
{
|
||||
w->imageIndex += 0.16;
|
||||
if (w->imageIndex >= 7) {
|
||||
w->imageIndex -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
w->x += w->hsp;
|
||||
mask.x = w->x + ((40 - mask.w) / 2);
|
||||
}
|
||||
|
||||
//Hit wall
|
||||
if (checkTileCollision(1, mask) == 1) {
|
||||
w->hsp *= -1;
|
||||
}
|
||||
|
||||
//Turn on edge
|
||||
else{
|
||||
mask.x += (mask.w / 2) * w->hsp;
|
||||
mask.y += mask.h;
|
||||
PHL_Rect collide = getTileCollision(1, mask);
|
||||
if (collide.x == -1) {
|
||||
collide = getTileCollision(3, mask);
|
||||
}
|
||||
if (collide.x == -1) {
|
||||
w->hsp *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
//End walk
|
||||
{
|
||||
if (w->timer <= 0) {
|
||||
w->state = 3;
|
||||
w->timer = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Jump Down
|
||||
else if (w->state == 3)
|
||||
{
|
||||
//Setup
|
||||
{
|
||||
if (w->timer == -1) {
|
||||
w->timer = 0;
|
||||
PHL_PlaySound(sounds[sndPi02], CHN_ENEMIES);
|
||||
w->vsp = -4;
|
||||
w->imageIndex = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Animate
|
||||
{
|
||||
w->imageIndex += 0.25;
|
||||
if (w->imageIndex >= 5) {
|
||||
w->imageIndex -= 3;
|
||||
}
|
||||
}
|
||||
|
||||
//Movement
|
||||
{
|
||||
w->y += w->vsp;
|
||||
w->vsp += w->grav;
|
||||
|
||||
if (w->vsp > 6) {
|
||||
w->vsp = 6;
|
||||
}
|
||||
}
|
||||
|
||||
//Land in Water
|
||||
{
|
||||
if (w->y >= w->ystart) {
|
||||
w->state = 0;
|
||||
createSplash(w->x + 20, w->y);
|
||||
w->timer = 60;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
{
|
||||
mask.x = w->x + ((40 - mask.w) / 2);
|
||||
mask.y = w->y + ((40 - mask.h) / 2);
|
||||
}
|
||||
|
||||
//Collide with hero
|
||||
{
|
||||
if (checkCollision(mask, getHeroMask())) {
|
||||
heroHit(15, mask.x + (mask.w / 2));
|
||||
}
|
||||
}
|
||||
|
||||
//Weapon collision
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (weapons[i]->cooldown == 0) {
|
||||
if (checkCollision(mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
|
||||
w->blink = 15;
|
||||
w->hp -= 1;
|
||||
if (w->hp <= 0) {
|
||||
createEffect(2, w->x - 12, w->y - 12);
|
||||
spawnCollectable(w->x + 20, w->y);
|
||||
enemyDestroy(w->id);
|
||||
}
|
||||
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void waterJumperDraw(WaterJumper* w)
|
||||
{
|
||||
if (w->blink % 2 == 0) {
|
||||
int cx = (int)w->imageIndex * 40;
|
||||
|
||||
if (w->state == 1) {
|
||||
cx += 80;
|
||||
}
|
||||
|
||||
if (w->type == 1) {
|
||||
cx += 200;
|
||||
|
||||
if (w->state == 2 && w->hsp < 0) {
|
||||
cx += 80;
|
||||
}
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(w->x, w->y, cx, 440, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
23
contrib/games/hydracastlelabyrinth/src/enemies/waterjumper.h
Normal file
23
contrib/games/hydracastlelabyrinth/src/enemies/waterjumper.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef WATERJUMPER_H
|
||||
#define WATERJUMPER_H
|
||||
|
||||
#include "../enemy.h"
|
||||
|
||||
typedef struct {
|
||||
int id, type;
|
||||
|
||||
double x, y;
|
||||
int hp;
|
||||
int blink;
|
||||
int ystart, rot;
|
||||
double yoffset;
|
||||
double hsp, vsp, grav;
|
||||
|
||||
double imageIndex;
|
||||
int state, timer;
|
||||
int height;
|
||||
} WaterJumper;
|
||||
|
||||
void createWaterJumper(int x, int y, int type, int offset, int height);
|
||||
|
||||
#endif
|
133
contrib/games/hydracastlelabyrinth/src/enemies/wizard.c
Normal file
133
contrib/games/hydracastlelabyrinth/src/enemies/wizard.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include "wizard.h"
|
||||
#include "../enemy.h"
|
||||
#include "../game.h"
|
||||
#include "../hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void createWizard(int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ENEMIES; i++) {
|
||||
if (enemies[i] == NULL) {
|
||||
Enemy* e = malloc(sizeof *e);
|
||||
Wizard* w = malloc(sizeof *w);
|
||||
w->id = i;
|
||||
|
||||
w->x = x;
|
||||
w->y = y;
|
||||
|
||||
w->imageIndex = 0;
|
||||
|
||||
w->state = 0;
|
||||
w->timer = 50;
|
||||
w->visible = 1;
|
||||
|
||||
w->mask.circle = w->mask.unused = 0;
|
||||
w->mask.w = 24;
|
||||
w->mask.h = 38;
|
||||
w->mask.x = w->x + 8;
|
||||
w->mask.y = w->y + 2;
|
||||
|
||||
e->data = w;
|
||||
e->enemyStep = wizardStep;
|
||||
e->enemyDraw = wizardDraw;
|
||||
e->type = 21;
|
||||
|
||||
enemies[i] = e;
|
||||
i = MAX_ENEMIES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wizardStep(Wizard* w)
|
||||
{
|
||||
w->imageIndex += 0.3;
|
||||
if (w->imageIndex >= 3) {
|
||||
w->imageIndex -= 3;
|
||||
}
|
||||
|
||||
//Stand still
|
||||
if (w->state == 0) {
|
||||
w->timer -= 1;
|
||||
|
||||
if (w->timer <= 0) {
|
||||
PHL_PlaySound(sounds[sndPi10], CHN_ENEMIES);
|
||||
w->state = 1;
|
||||
w->timer = 15;
|
||||
}
|
||||
}
|
||||
//Flash
|
||||
else if (w->state == 1 || w->state == 3) {
|
||||
if (w->visible == 0) {
|
||||
w->visible = 1;
|
||||
}else{
|
||||
w->visible = 0;
|
||||
}
|
||||
|
||||
w->timer -= 1;
|
||||
if (w->timer <= 0) {
|
||||
if (w->state == 1) {
|
||||
w->state = 2;
|
||||
w->timer = 60;
|
||||
}
|
||||
else if (w->state == 3) {
|
||||
w->visible = 1;
|
||||
w->state = 0;
|
||||
w->timer = 50;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Invisible
|
||||
else if (w->state == 2) {
|
||||
w->visible = 0;
|
||||
|
||||
w->timer -= 1;
|
||||
if (w->timer <= 0) {
|
||||
PHL_PlaySound(sounds[sndPi03], CHN_ENEMIES);
|
||||
w->state = 3;
|
||||
w->timer = 15;
|
||||
|
||||
//Horizontal Jump
|
||||
int gridX = w->x / 40,
|
||||
gridY = w->y / 40,
|
||||
lastGridX = gridX;
|
||||
|
||||
do {
|
||||
gridX = (rand() % 16) + 1;
|
||||
} while (collisionTiles[gridX][gridY] != 0 ||
|
||||
collisionTiles[gridX][gridY+1] != 1 ||
|
||||
gridX == lastGridX);
|
||||
|
||||
w->x = gridX * 40;
|
||||
w->mask.x = w->x + 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (w->state == 0 || w->state == 3) {
|
||||
//Hit Player
|
||||
if (checkCollision(w->mask, getHeroMask())) {
|
||||
heroHit(15, w->x + 20);
|
||||
}
|
||||
|
||||
//Weapon Collision
|
||||
int i;
|
||||
for (i = 0; i < MAX_WEAPONS; i++) {
|
||||
if (weapons[i] != NULL) {
|
||||
if (checkCollision(w->mask, weapons[i]->weaponMask)) {
|
||||
weaponHit(weapons[i]);
|
||||
createEffect(2, w->x - 12, w->y - 6);
|
||||
spawnCollectable(w->x + 20, w->y);
|
||||
enemyDestroy(w->id);
|
||||
i = MAX_WEAPONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wizardDraw(Wizard* w)
|
||||
{
|
||||
if (w->visible == 1) {
|
||||
PHL_DrawSurfacePart(w->x, w->y, 520 + (((int)w->imageIndex) * 40), 480, 40, 40, images[imgEnemies]);
|
||||
}
|
||||
}
|
20
contrib/games/hydracastlelabyrinth/src/enemies/wizard.h
Normal file
20
contrib/games/hydracastlelabyrinth/src/enemies/wizard.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef WIZARD_H
|
||||
#define WIZARD_H
|
||||
|
||||
#include "../collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
double x, y;
|
||||
double imageIndex;
|
||||
int state, timer, visible;
|
||||
|
||||
Mask mask;
|
||||
} Wizard;
|
||||
|
||||
void createWizard(int x, int y);
|
||||
|
||||
void wizardStep(Wizard* w);
|
||||
void wizardDraw(Wizard* w);
|
||||
|
||||
#endif
|
16
contrib/games/hydracastlelabyrinth/src/enemy.c
Normal file
16
contrib/games/hydracastlelabyrinth/src/enemy.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "enemy.h"
|
||||
#include "game.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void enemyDestroy(int id)
|
||||
{
|
||||
if (enemies[id] != NULL) {
|
||||
if (enemies[id]->data != NULL) {
|
||||
free(enemies[id]->data);
|
||||
}
|
||||
enemies[id]->data = NULL;
|
||||
|
||||
free(enemies[id]);
|
||||
}
|
||||
enemies[id] = NULL;
|
||||
}
|
13
contrib/games/hydracastlelabyrinth/src/enemy.h
Normal file
13
contrib/games/hydracastlelabyrinth/src/enemy.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef ENEMY_H
|
||||
#define ENEMY_H
|
||||
|
||||
typedef struct {
|
||||
void* data; //Specific enemy struct
|
||||
void (*enemyStep)();
|
||||
void (*enemyDraw)();
|
||||
int type;
|
||||
} Enemy;
|
||||
|
||||
void enemyDestroy(int id);
|
||||
|
||||
#endif
|
1976
contrib/games/hydracastlelabyrinth/src/game.c
Normal file
1976
contrib/games/hydracastlelabyrinth/src/game.c
Normal file
File diff suppressed because it is too large
Load Diff
237
contrib/games/hydracastlelabyrinth/src/game.h
Normal file
237
contrib/games/hydracastlelabyrinth/src/game.h
Normal file
@ -0,0 +1,237 @@
|
||||
#ifndef GAME_H
|
||||
#define GAME_H
|
||||
|
||||
#include "PHL.h"
|
||||
#include "enemy.h"
|
||||
#include "enemies/slime.h"
|
||||
#include "enemies/bat.h"
|
||||
#include "enemies/slug.h"
|
||||
#include "enemies/knight.h"
|
||||
#include "enemies/heads.h"
|
||||
#include "enemies/gas.h"
|
||||
#include "enemies/skull.h"
|
||||
#include "enemies/fish.h"
|
||||
#include "enemies/waterjumper.h"
|
||||
#include "enemies/podoboo.h"
|
||||
#include "enemies/thwomp.h"
|
||||
#include "enemies/dodo.h"
|
||||
#include "enemies/batboss.h"
|
||||
#include "enemies/crab.h"
|
||||
#include "enemies/skeleton.h"
|
||||
#include "enemies/ghoul.h"
|
||||
#include "enemies/seal.h"
|
||||
#include "enemies/jellyfish.h"
|
||||
#include "enemies/wizard.h"
|
||||
#include "enemies/pendulum.h"
|
||||
#include "enemies/gyra.h"
|
||||
#include "enemies/lolidra.h"
|
||||
#include "enemies/bee.h"
|
||||
#include "enemies/devil.h"
|
||||
#include "enemies/firewheel.h"
|
||||
#include "enemies/boar.h"
|
||||
#include "enemies/golem.h"
|
||||
#include "enemies/garm.h"
|
||||
#include "enemies/poisonknight.h"
|
||||
#include "enemies/dog.h"
|
||||
#include "enemies/boomknight.h"
|
||||
#include "enemies/pumpkin.h"
|
||||
#include "enemies/hydra.h"
|
||||
#include "object.h"
|
||||
#include "effect.h"
|
||||
#include "weapon.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define TITLE 0
|
||||
#define GAME 1
|
||||
#define INVENTORY 2
|
||||
#define OPTIONS 3
|
||||
#define SAVING 4
|
||||
#define LEVELSTART 5
|
||||
#define GETITEM 6
|
||||
|
||||
//Sound channels
|
||||
#define CHN_MUSIC 0
|
||||
#define CHN_SOUND 1 //Various sounds, like menus and fanfares
|
||||
#define CHN_HERO 2
|
||||
#define CHN_WEAPONS 3
|
||||
#define CHN_ENEMIES 4
|
||||
#define CHN_EFFECTS 5
|
||||
|
||||
extern Door* lastDoor;
|
||||
|
||||
extern int secretTimer;
|
||||
extern int levelStartTimer;
|
||||
extern int saveTimer;
|
||||
|
||||
extern int quakeTimer;
|
||||
|
||||
extern int bellFlag;
|
||||
extern int bossFlag;
|
||||
extern int bossDefeatedFlag;
|
||||
|
||||
extern char roomDarkness;
|
||||
|
||||
//Used for item get message
|
||||
extern int itemGotX;
|
||||
extern int itemGotY;
|
||||
|
||||
extern int roomSecret;
|
||||
|
||||
extern int collisionTiles[16][12];
|
||||
|
||||
//Playtime in frames. At 60 frames per second can hold ~828 1/2 days worth of playtime if my math isn't shit
|
||||
extern unsigned long playTime;
|
||||
|
||||
//Inventory
|
||||
extern unsigned char hasWeapon[5];
|
||||
extern unsigned char hasItem[28];
|
||||
extern unsigned char hasKey[8];
|
||||
|
||||
//Save data flags
|
||||
extern unsigned char flags[60];
|
||||
|
||||
extern PHL_Background background,
|
||||
foreground;
|
||||
|
||||
//Game assets
|
||||
extern PHL_Surface images[15];
|
||||
extern PHL_Music bgmMusic;
|
||||
extern PHL_Music bgmSecret;
|
||||
extern PHL_Music bgmGameover;
|
||||
extern PHL_Sound sounds[43];
|
||||
|
||||
#define MAX_WEAPONS 5
|
||||
extern Weapon* weapons[MAX_WEAPONS];
|
||||
|
||||
#define MAX_OBJECTS 40
|
||||
extern Object* objects[MAX_OBJECTS];
|
||||
|
||||
#define MAX_ENEMIES 20
|
||||
extern Enemy* enemies[MAX_ENEMIES];
|
||||
|
||||
#define MAX_EFFECTS 30
|
||||
extern Effect* effects[MAX_EFFECTS];
|
||||
|
||||
#define MAX_PLATFORMS 10
|
||||
extern Platform* platforms[MAX_PLATFORMS];
|
||||
|
||||
//Graphic names
|
||||
#define imgTiles 0
|
||||
#define imgEnemies 1
|
||||
#define imgHud 2
|
||||
#define imgMisc20 3
|
||||
#define imgMisc32 4
|
||||
#define imgHero 5
|
||||
#define imgItems 6
|
||||
#define imgExplosion 7
|
||||
#define imgBoss 8
|
||||
#define imgMisc2040 9
|
||||
#define imgFontKana 10
|
||||
#define imgBoldFont 11
|
||||
#define imgDark 12
|
||||
#define imgMisc6020 13
|
||||
#define imgTitle01 14
|
||||
|
||||
//Sound names
|
||||
#define sndBee01 0
|
||||
#define sndBell01 1
|
||||
#define sndBom01 2
|
||||
#define sndBom02 3
|
||||
#define sndBom03 4
|
||||
#define sndDoor00 5
|
||||
#define sndFire01 6
|
||||
#define sndGas01 7
|
||||
#define sndGet01 8
|
||||
#define sndGet02 9
|
||||
#define sndHit01 10
|
||||
#define sndHit02 11
|
||||
#define sndHit03 12
|
||||
#define sndHit04 13
|
||||
#define sndHit05 14
|
||||
#define sndHit06 15
|
||||
#define sndHit07 16
|
||||
#define sndJump01 17
|
||||
#define sndJump02 18
|
||||
#define sndNg 19
|
||||
#define sndOk 20
|
||||
#define sndPi01 21
|
||||
#define sndPi02 22
|
||||
#define sndPi03 23
|
||||
#define sndPi04 24
|
||||
#define sndPi05 25
|
||||
#define sndPi06 26
|
||||
#define sndPi07 27
|
||||
#define sndPi08 28
|
||||
#define sndPi09 29
|
||||
#define sndPi10 30
|
||||
#define sndPower01 31
|
||||
#define sndPower02 32
|
||||
#define sndShot01 33
|
||||
#define sndShot02 34
|
||||
#define sndShot03 35
|
||||
#define sndShot04 36
|
||||
#define sndShot05 37
|
||||
#define sndShot06 38
|
||||
#define sndShot07 39
|
||||
#define sndStep01 40
|
||||
#define sndWater01 41
|
||||
#define sndWolf01 42
|
||||
|
||||
#ifdef _SDL
|
||||
extern char savename[4096];
|
||||
extern char savemap[4096];
|
||||
#else
|
||||
#define savename "data/save.tmp"
|
||||
#define savemap "map/018.map"
|
||||
#endif
|
||||
|
||||
#ifdef _KOLIBRI
|
||||
#define KOS_HCL_SAVES_PATH "/tmp0/1/.hydracastlelabyrinth"
|
||||
#define KOS_TMP_DIR "/tmp0/1"
|
||||
#endif
|
||||
|
||||
void loadImages();
|
||||
void freeImages();
|
||||
void loadResources();
|
||||
void freeResources();
|
||||
|
||||
void game();
|
||||
|
||||
void gameSetup();
|
||||
void gameCleanup();
|
||||
|
||||
void enterDoor();
|
||||
#ifdef EMSCRIPTEN
|
||||
void getItemSetup(int itemNum);
|
||||
int getItemEMStep();
|
||||
#else
|
||||
void getItem(int itemNum);
|
||||
#endif
|
||||
void saveScreen();
|
||||
|
||||
void gameEnding();
|
||||
|
||||
//void enterDoor(Door* d);
|
||||
void loadScreen();
|
||||
|
||||
void changeScreen(int dx, int dy);
|
||||
|
||||
int writeSave(char* fname);
|
||||
void loadSave(char* fname);
|
||||
|
||||
int fileExists(char* fpath);
|
||||
|
||||
void playSecret();
|
||||
void secretCountdown();
|
||||
|
||||
int getDrawHP();
|
||||
void setDrawHP(int val);
|
||||
|
||||
int getLevel();
|
||||
|
||||
void setBossRoom();
|
||||
|
||||
void setAutoSave(char val);
|
||||
char getAutoSave();
|
||||
|
||||
#endif
|
1415
contrib/games/hydracastlelabyrinth/src/hero.c
Normal file
1415
contrib/games/hydracastlelabyrinth/src/hero.c
Normal file
File diff suppressed because it is too large
Load Diff
55
contrib/games/hydracastlelabyrinth/src/hero.h
Normal file
55
contrib/games/hydracastlelabyrinth/src/hero.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef HERO_H
|
||||
#define HERO_H
|
||||
|
||||
#include "PHL.h"
|
||||
#include "collision.h"
|
||||
|
||||
extern double herox, heroy;
|
||||
extern double herohp, maxhp;
|
||||
extern int heroAmmo, maxAmmo;
|
||||
extern int heroWeapon;
|
||||
|
||||
extern Mask heroMask;
|
||||
extern Mask shieldMask;
|
||||
|
||||
void heroSetup();
|
||||
void heroCleanup();
|
||||
int heroStep();
|
||||
void heroDraw();
|
||||
|
||||
int heroHit(int damage, int centerx);
|
||||
|
||||
void heroPoison();
|
||||
void heroStone();
|
||||
|
||||
Mask getHeroMask();
|
||||
|
||||
int getHeroState();
|
||||
void setHeroState(int s);
|
||||
|
||||
int getHeroInvincible();
|
||||
|
||||
int getHeroDirection();
|
||||
void setHeroDirection(int d);
|
||||
|
||||
double getHeroImageIndex();
|
||||
void setHeroImageIndex(double index);
|
||||
|
||||
double getHeroVsp();
|
||||
double getHeroHsp();
|
||||
|
||||
void setHeroHsp(double newHsp);
|
||||
void setHeroVsp(double newVsp);
|
||||
|
||||
int getHeroOnground();
|
||||
void setHeroOnground(int val);
|
||||
|
||||
void setHeroTimer(int t);
|
||||
|
||||
int getHeroPoisoned();
|
||||
|
||||
void heroStun();
|
||||
|
||||
void setHeroCanjump(int set);
|
||||
|
||||
#endif
|
395
contrib/games/hydracastlelabyrinth/src/ini.c
Normal file
395
contrib/games/hydracastlelabyrinth/src/ini.c
Normal file
@ -0,0 +1,395 @@
|
||||
#include "ini.h"
|
||||
#include "game.h"
|
||||
#include "options.h"
|
||||
#include "PHL.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "text.h"
|
||||
#ifdef EMSCRIPTEN
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
//char* getFileLocation();
|
||||
char* trimString(char* orig);
|
||||
|
||||
void screenLoad(char* first, char* second);
|
||||
void sizeLoad(char* first, char* second);
|
||||
void blurLoad(char* first, char* second);
|
||||
void xbrzLoad(char* first, char* second);
|
||||
void languageLoad(char* first, char* second);
|
||||
void autosaveLoad(char* first, char* second);
|
||||
void musictypeLoad(char* first, char* second);
|
||||
void musicvolumeLoad(char* first, char* second);
|
||||
|
||||
void iniInit()
|
||||
{
|
||||
//Build filepath
|
||||
char fullPath[128];
|
||||
{
|
||||
#ifdef _SDL
|
||||
#if defined(__amigaos4__) || defined(__MORPHOS__)
|
||||
strcpy(fullPath, "PROGDIR:.hydracastlelabyrinth/");
|
||||
#elif defined(EMSCRIPTEN)
|
||||
strcpy(fullPath, "hcl_data/");
|
||||
#elif defined(_KOLIBRI)
|
||||
strcpy(fullPath, KOS_HCL_SAVES_PATH"/");
|
||||
#else
|
||||
strcpy(fullPath, getenv("HOME"));
|
||||
strcat(fullPath, "/.hydracastlelabyrinth/");
|
||||
#endif
|
||||
#elif defined(_3DS)
|
||||
strcpy(fullPath, "sdmc:/3ds/appdata/HydraCastleLabyrinth/");
|
||||
#else
|
||||
strcpy(fullPath, "");
|
||||
#endif
|
||||
strcat(fullPath, "system.ini");
|
||||
}
|
||||
|
||||
FILE* f;
|
||||
|
||||
if ( (f = fopen(fullPath, "rt")) )
|
||||
{
|
||||
//File exists - read it
|
||||
fclose(f);
|
||||
loadSettings();
|
||||
}else{
|
||||
//File does not exists - create it (with default hardcoded settings)
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void saveSettings()
|
||||
{
|
||||
//Build filepath
|
||||
char fullPath[128];
|
||||
{
|
||||
#ifdef _SDL
|
||||
#if defined(__amigaos4__) || defined(__MORPHOS__)
|
||||
strcpy(fullPath, "PROGDIR:.hydracastlelabyrinth/");
|
||||
#elif defined(EMSCRIPTEN)
|
||||
strcpy(fullPath, "hcl_data/");
|
||||
#elif defined(_KOLIBRI)
|
||||
strcpy(fullPath, KOS_HCL_SAVES_PATH"/");
|
||||
#else
|
||||
strcpy(fullPath, getenv("HOME"));
|
||||
strcat(fullPath, "/.hydracastlelabyrinth/");
|
||||
#endif
|
||||
#elif defined(_3DS)
|
||||
strcpy(fullPath, "sdmc:/3ds/appdata/HydraCastleLabyrinth/");
|
||||
#else
|
||||
strcpy(fullPath, "");
|
||||
#endif
|
||||
strcat(fullPath, "system.ini");
|
||||
}
|
||||
|
||||
FILE* f;
|
||||
|
||||
if ( (f = fopen(fullPath, "wt")) )
|
||||
{
|
||||
fprintf(f, "[disp]");
|
||||
#ifdef _3DS
|
||||
//Screen
|
||||
fprintf(f, "\r\nscreen=");
|
||||
if (activeScreen->screen == GFX_BOTTOM) {
|
||||
fprintf(f, "bottom");
|
||||
}else{
|
||||
fprintf(f, "top");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _PSP
|
||||
//Screen Size
|
||||
fprintf(f, "\r\nsize=");
|
||||
if (getScreenSize() == 1) {
|
||||
fprintf(f, "1");
|
||||
}
|
||||
else if (getScreenSize() == 2) {
|
||||
fprintf(f, "2");
|
||||
}
|
||||
else {
|
||||
fprintf(f, "0");
|
||||
}
|
||||
|
||||
//Screen Blur
|
||||
fprintf(f, "\r\nblur=");
|
||||
if (getBlur() == 1) {
|
||||
fprintf(f, "on");
|
||||
}else{
|
||||
fprintf(f, "off");
|
||||
}
|
||||
#endif
|
||||
#ifdef _SDL
|
||||
//xBRZ Scaling
|
||||
fprintf(f, "\r\nxbrz=");
|
||||
if (getXBRZ() == 1) {
|
||||
fprintf(f, "on");
|
||||
}else{
|
||||
fprintf(f, "off");
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf(f, "\r\n[system]");
|
||||
|
||||
//Language
|
||||
fprintf(f, "\r\nlanguage=");
|
||||
if (getLanguage() == 0) {
|
||||
fprintf(f, "jp");
|
||||
}
|
||||
if (getLanguage() == 1) {
|
||||
fprintf(f, "en");
|
||||
}
|
||||
|
||||
//Autosave
|
||||
fprintf(f, "\r\nautosave=");
|
||||
if (getAutoSave() == 1) {
|
||||
fprintf(f, "on");
|
||||
}else{
|
||||
fprintf(f, "off");
|
||||
}
|
||||
|
||||
#ifdef _SDL
|
||||
fprintf(f, "\r\n[audio]");
|
||||
fprintf(f, "\r\nmusic_type=%s", getMusicType()?"ogg":"midi");
|
||||
fprintf(f, "\r\nmusic=%d", music_volume);
|
||||
// Audio
|
||||
#endif
|
||||
fclose(f);
|
||||
}
|
||||
#ifdef EMSCRIPTEN
|
||||
EM_ASM(
|
||||
FS.syncfs(false,function () {
|
||||
Module.print("File sych'd")
|
||||
});
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
void loadSettings()
|
||||
{
|
||||
//Build filepath
|
||||
char fullPath[128];
|
||||
{
|
||||
#ifdef _SDL
|
||||
#if defined(__amigaos4__) || defined(__MORPHOS__)
|
||||
strcpy(fullPath, "PROGDIR:.hydracastlelabyrinth/");
|
||||
#elif defined(EMSCRIPTEN)
|
||||
strcpy(fullPath, "hcl_data/");
|
||||
#elif defined(_KOLIBRI)
|
||||
strcat(fullPath, KOS_HCL_SAVES_PATH"/");
|
||||
#else
|
||||
strcpy(fullPath, getenv("HOME"));
|
||||
strcat(fullPath, "/.hydracastlelabyrinth/");
|
||||
#endif
|
||||
#elif defined(_3DS)
|
||||
strcpy(fullPath, "sdmc:/3ds/appdata/HydraCastleLabyrinth/");
|
||||
#else
|
||||
strcpy(fullPath, "");
|
||||
#endif
|
||||
strcat(fullPath, "system.ini");
|
||||
}
|
||||
|
||||
FILE* f;
|
||||
|
||||
if ( (f = fopen(fullPath, "rt")) )
|
||||
{
|
||||
char line[80];
|
||||
|
||||
while ( (fgets(line, 80, f) != NULL) )
|
||||
{
|
||||
char* lineptr = line;
|
||||
lineptr = trimString(lineptr);
|
||||
|
||||
if (lineptr != NULL) {
|
||||
//Ignore category lines
|
||||
if (lineptr[0] != '[')
|
||||
{
|
||||
//Check if it has a = delimiter first
|
||||
int i;
|
||||
for (i = 0; i < 80; i++) {
|
||||
if (line[i] == '=')
|
||||
{
|
||||
//Begin line splitting
|
||||
char* half;
|
||||
if ( (half = strsep(&lineptr, "=")) != NULL)
|
||||
{
|
||||
//first half
|
||||
char* fhalf = half;
|
||||
|
||||
if ( (half = strsep(&lineptr, "=")) != NULL) {
|
||||
//Second half
|
||||
char* shalf = half;
|
||||
|
||||
//Load options
|
||||
screenLoad(fhalf, shalf);
|
||||
sizeLoad(fhalf, shalf);
|
||||
blurLoad(fhalf, shalf);
|
||||
xbrzLoad(fhalf, shalf);
|
||||
languageLoad(fhalf, shalf);
|
||||
autosaveLoad(fhalf, shalf);
|
||||
musictypeLoad(fhalf, shalf);
|
||||
musicvolumeLoad(fhalf, shalf);
|
||||
}
|
||||
}
|
||||
|
||||
//End
|
||||
i = 81;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Build file path
|
||||
/*
|
||||
char* getFileLocation()
|
||||
{
|
||||
char fullPath[128];
|
||||
strcpy(fullPath, "");
|
||||
#ifdef _CIA
|
||||
strcat(fullPath, "sdmc:/3ds/HydraCastleLabyrinth/");
|
||||
#endif
|
||||
strcat(fullPath, "system.ini");
|
||||
|
||||
return fullPath;
|
||||
}
|
||||
*/
|
||||
|
||||
char* trimString(char* orig)
|
||||
{
|
||||
char* output = orig;
|
||||
|
||||
int i, r = 0;
|
||||
for (i = 0; i < strlen(orig); i++) {
|
||||
if (orig[i] != ' ' && orig[i] != '\n' && orig[i] != '\r') {
|
||||
output[r] = orig[i];
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
orig[r] = 0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void screenLoad(char* first, char* second)
|
||||
{
|
||||
#ifdef _3DS
|
||||
if (strcmp(first, "screen") == 0) {
|
||||
if (strcmp(second, "top") == 0) {
|
||||
swapScreen(GFX_TOP, GFX_LEFT);
|
||||
}
|
||||
if (strcmp(second, "bottom") == 0) {
|
||||
swapScreen(GFX_BOTTOM, GFX_LEFT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void sizeLoad(char* first, char* second)
|
||||
{
|
||||
#ifdef _PSP
|
||||
if (strcmp(first, "size") == 0) {
|
||||
if (second[0] == '0') {
|
||||
//fprintf(debug, "\nsize is 0");
|
||||
setScreenSize(0);
|
||||
}
|
||||
if (second[0] == '1') {
|
||||
//fprintf(debug, "\nsize is 1");
|
||||
setScreenSize(1);
|
||||
}
|
||||
if (second[0] == '2') {
|
||||
//fprintf(debug, "\nsize is 2");
|
||||
setScreenSize(2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void blurLoad(char* first, char* second)
|
||||
{
|
||||
#ifdef _PSP
|
||||
if (strcmp(first, "blur") == 0) {
|
||||
if (strcmp(second, "on") == 0) {
|
||||
//fprintf(debug, "\nblur is on");
|
||||
//oslSetBilinearFilter(1);
|
||||
setBlur(1);
|
||||
}
|
||||
if (strcmp(second, "off") == 0) {
|
||||
//fprintf(debug, "\nblur is off");
|
||||
//oslSetBilinearFilter(0);
|
||||
setBlur(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void xbrzLoad(char* first, char* second)
|
||||
{
|
||||
#ifdef _SDL
|
||||
if (strcmp(first, "xbrz") == 0) {
|
||||
if (strcmp(second, "on") == 0) {
|
||||
setXBRZ(1);
|
||||
}
|
||||
if (strcmp(second, "off") == 0) {
|
||||
setXBRZ(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void languageLoad(char* first, char* second)
|
||||
{
|
||||
if (strcmp(first, "language") == 0) {
|
||||
if (strcmp(second, "en") == 0) {
|
||||
setLanguage(ENGLISH);
|
||||
}
|
||||
if (strcmp(second, "jp") == 0) {
|
||||
setLanguage(JAPANESE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void autosaveLoad(char* first, char* second)
|
||||
{
|
||||
if (strcmp(first, "autosave") == 0) {
|
||||
if (strcmp(second, "on") == 0) {
|
||||
//fprintf(debug, "\nautosave is on");
|
||||
setAutoSave(1);
|
||||
}
|
||||
if (strcmp(second, "off") == 0) {
|
||||
//fprintf(debug, "\nautosave is off");
|
||||
setAutoSave(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void musicvolumeLoad(char* first, char* second)
|
||||
{
|
||||
#ifdef _SDL
|
||||
if (strcmp(first, "music") == 0) {
|
||||
if (second[0] >= '0' && second[0] <= '4') {
|
||||
music_volume = second[0]-'0';
|
||||
PHL_MusicVolume(0.25f * music_volume);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void musictypeLoad(char* first, char* second)
|
||||
{
|
||||
#ifdef _SDL
|
||||
if (strcmp(first, "music_type") == 0) {
|
||||
if (strcmp(second, "ogg") == 0) {
|
||||
setMusicType(1);
|
||||
}
|
||||
if (strcmp(second, "midi") == 0) {
|
||||
setMusicType(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
10
contrib/games/hydracastlelabyrinth/src/ini.h
Normal file
10
contrib/games/hydracastlelabyrinth/src/ini.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef INI_H
|
||||
#define INI_H
|
||||
|
||||
//Functions to handle the "system.ini" file
|
||||
void iniInit();
|
||||
|
||||
void saveSettings();
|
||||
void loadSettings();
|
||||
|
||||
#endif
|
180
contrib/games/hydracastlelabyrinth/src/inventory.c
Normal file
180
contrib/games/hydracastlelabyrinth/src/inventory.c
Normal file
@ -0,0 +1,180 @@
|
||||
#include "inventory.h"
|
||||
#include "PHL.h"
|
||||
#include "game.h"
|
||||
#include "text.h"
|
||||
|
||||
int cursorX = 0;
|
||||
int cursorY = 0;
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
static char tempDark;
|
||||
void inventorySetup()
|
||||
{
|
||||
tempDark = roomDarkness;
|
||||
roomDarkness = 0;
|
||||
|
||||
PHL_PlaySound(sounds[sndPi04], CHN_SOUND);
|
||||
}
|
||||
int inventoryEMStep()
|
||||
{
|
||||
int result = -1;
|
||||
PHL_MainLoop();
|
||||
|
||||
PHL_StartDrawing();
|
||||
PHL_ScanInput();
|
||||
|
||||
if (inventoryStep() == 1) {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
inventoryDraw();
|
||||
|
||||
PHL_EndDrawing();
|
||||
|
||||
if(!result)
|
||||
roomDarkness = tempDark;
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
|
||||
void inventory()
|
||||
{
|
||||
char tempDark = roomDarkness;
|
||||
roomDarkness = 0;
|
||||
|
||||
char loop = 1;
|
||||
PHL_PlaySound(sounds[sndPi04], CHN_SOUND);
|
||||
while (PHL_MainLoop() && loop == 1)
|
||||
{
|
||||
PHL_StartDrawing();
|
||||
PHL_ScanInput();
|
||||
|
||||
if (inventoryStep() == 1) {
|
||||
loop = 0;
|
||||
}
|
||||
|
||||
inventoryDraw();
|
||||
|
||||
PHL_EndDrawing();
|
||||
}
|
||||
|
||||
roomDarkness = tempDark;
|
||||
}
|
||||
#endif
|
||||
int inventoryStep()
|
||||
{
|
||||
secretCountdown();
|
||||
|
||||
//Input
|
||||
char playsnd = 0;
|
||||
|
||||
if (btnRight.pressed - btnLeft.pressed != 0) {
|
||||
cursorX += btnRight.pressed - btnLeft.pressed;
|
||||
playsnd = 1;
|
||||
}
|
||||
if (btnDown.pressed - btnUp.pressed != 0) {
|
||||
cursorY += btnDown.pressed - btnUp.pressed;
|
||||
playsnd = 1;
|
||||
}
|
||||
|
||||
if (playsnd == 1) {
|
||||
PHL_PlaySound(sounds[sndPi01], CHN_SOUND);
|
||||
}
|
||||
|
||||
//Limit cursor
|
||||
if (cursorX < 0) { cursorX = 6; }
|
||||
if (cursorX > 6) { cursorX = 0; }
|
||||
if (cursorY < 0) { cursorY = 3; }
|
||||
if (cursorY > 3) { cursorY = 0; }
|
||||
|
||||
if (btnStart.pressed == 1 || btnDecline.pressed == 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void inventoryDraw()
|
||||
{
|
||||
//Black background
|
||||
PHL_DrawRect(0, 0, 640, 480, PHL_NewRGB(0, 0, 0));
|
||||
|
||||
//Labels
|
||||
PHL_DrawTextBold("SUB WEAPON", 16, 16, YELLOW);
|
||||
PHL_DrawTextBold("ITEM", 16, 96, YELLOW);
|
||||
PHL_DrawTextBold("KEY", 16, 320, YELLOW);
|
||||
|
||||
//Blue rectangles
|
||||
int i, a, cx, cy;
|
||||
//Weapons
|
||||
for (i = 0; i < 5; i++) {
|
||||
PHL_DrawRect(18 + (48 * i), 34, 44, 44, PHL_NewRGB(255, 255, 255));
|
||||
PHL_DrawRect(20 + (48 * i), 36, 40, 40, PHL_NewRGB(119, 166, 219));
|
||||
if (hasWeapon[i] == 1) {
|
||||
cx = (i + 1) * 40;
|
||||
}else{
|
||||
cx = 0;
|
||||
}
|
||||
PHL_DrawSurfacePart(20 + (48 * i), 36, cx, 0, 40, 40, images[imgItems]);
|
||||
}
|
||||
//Items
|
||||
int count = 0;
|
||||
int imageOrder[28] = { 13, 17, 16, 15, 8, 10, 9,
|
||||
18, 4, 6, 5, 7, 3, 11,
|
||||
14, 12, 1, 2, 22, 26, 27,
|
||||
21, 25, 28, 23, 20, 19, 24 };
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (a = 0; a < 7; a++) {
|
||||
PHL_DrawRect(18 + (48 * a), 114 + (48 * i), 44, 44, PHL_NewRGB(255, 255, 255));
|
||||
PHL_DrawRect(20 + (48 * a), 116 + (48 * i), 40, 40, PHL_NewRGB(119, 166, 219));
|
||||
|
||||
if (hasItem[count] == 0) {
|
||||
cx = 0;
|
||||
cy = 0;
|
||||
}else{
|
||||
cy = 0;
|
||||
cx = (imageOrder[count] + 6) * 40;
|
||||
while (cx >= 640) {
|
||||
cy += 40;
|
||||
cx -= 640;
|
||||
}
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(20 + (48 * a), 116 + (48 * i), cx, cy, 40, 40, images[imgItems]);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
//Keys
|
||||
for (i = 0; i < 8; i++) {
|
||||
PHL_DrawRect(18 + (48 * i), 338, 44, 44, PHL_NewRGB(255, 255, 255));
|
||||
PHL_DrawRect(20 + (48 * i), 340, 40, 40, PHL_NewRGB(119, 166, 219));
|
||||
if (hasKey[i] == 1) {
|
||||
cx = 120 + (i * 40);
|
||||
cy = 80;
|
||||
}else{
|
||||
cx = 0;
|
||||
cy = 0;
|
||||
}
|
||||
PHL_DrawSurfacePart(20 + (48 * i), 340, cx, cy, 40, 40, images[imgItems]);
|
||||
}
|
||||
|
||||
//Text box
|
||||
PHL_DrawRect(16, 400, 606, 46, PHL_NewRGB(255, 255, 255));
|
||||
PHL_DrawRect(18, 402, 602, 42, PHL_NewRGB(0, 0, 255));
|
||||
|
||||
//Text
|
||||
if (hasItem[cursorX + (cursorY * 7)] == 1) {
|
||||
int drawX = 32, drawY = 402;
|
||||
|
||||
//Draw item name
|
||||
drawX = drawText(itemName[cursorX + (cursorY * 7) + 5], drawX, drawY);
|
||||
//Draw item description
|
||||
drawX = drawCharacter(6, 0, drawX, drawY);
|
||||
drawText(itemDescription[cursorX + (cursorY * 7)], drawX, drawY);
|
||||
}
|
||||
|
||||
//Cursor
|
||||
PHL_DrawSurfacePart(16 + (cursorX * 48), 112 + (cursorY * 48), 0, 96, 48, 48, images[imgHud]);
|
||||
}
|
13
contrib/games/hydracastlelabyrinth/src/inventory.h
Normal file
13
contrib/games/hydracastlelabyrinth/src/inventory.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef INVENTORY_H
|
||||
#define INVENTORY_H
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
void inventorySetup();
|
||||
int inventoryEMStep();
|
||||
#else
|
||||
void inventory();
|
||||
#endif
|
||||
int inventoryStep();
|
||||
void inventoryDraw();
|
||||
|
||||
#endif
|
182
contrib/games/hydracastlelabyrinth/src/main.c
Normal file
182
contrib/games/hydracastlelabyrinth/src/main.c
Normal file
@ -0,0 +1,182 @@
|
||||
#include "PHL.h"
|
||||
#include "game.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef ODROID
|
||||
#define _XTYPEDEF_MASK
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
#ifdef EMSCRIPTEN
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
#ifdef __amigaos4__
|
||||
static const char* __attribute__((used)) stackcookie = "$STACK: 1000000";
|
||||
#endif
|
||||
#ifdef __MORPHOS__
|
||||
unsigned long __stack = 1000000;
|
||||
#endif
|
||||
|
||||
#ifdef _KOLIBRI
|
||||
extern char* dirname(char*);
|
||||
extern void setcwd(char*);
|
||||
#endif
|
||||
|
||||
void createSaveLocations()
|
||||
{
|
||||
//Force create save data folders
|
||||
#ifdef _3DS
|
||||
//3DS builds
|
||||
mkdir("sdmc:/3ds", 0777);
|
||||
mkdir("sdmc:/3ds/appdata", 0777);
|
||||
mkdir("sdmc:/3ds/appdata/HydraCastleLabyrinth", 0777);
|
||||
mkdir("sdmc:/3ds/appdata/HydraCastleLabyrinth/data", 0777);
|
||||
mkdir("sdmc:/3ds/appdata/HydraCastleLabyrinth/map", 0777);
|
||||
#elif defined(_SDL)
|
||||
char buff[4096];
|
||||
#if defined(__amigaos4__) || defined(__MORPHOS__)
|
||||
strcpy(buff,"PROGDIR:.hydracastlelabyrinth");
|
||||
#elif defined(EMSCRIPTEN)
|
||||
strcpy(buff, "hcl_data");
|
||||
#elif defined (_KOLIBRI)
|
||||
mkdir(KOS_HCL_SAVES_PATH, 777);
|
||||
#else
|
||||
strcpy(buff, getenv("HOME"));
|
||||
strcat(buff, "/.hydracastlelabyrinth");
|
||||
#endif
|
||||
// if exist first?
|
||||
#ifndef _KOLIBRI
|
||||
struct stat sb;
|
||||
if(!(stat(buff, &sb)==0 && S_ISDIR(sb.st_mode)))
|
||||
mkdir(buff, 0777);
|
||||
#endif
|
||||
#else
|
||||
//psp, wii
|
||||
mkdir("/data", 0777);
|
||||
mkdir("/map", 0777);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
int fileSynched = 0;
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
//Setup
|
||||
#ifdef _KOLIBRI
|
||||
setcwd(dirname(argv[0]));
|
||||
#endif
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
// that HEAP32 on &fileSynched looks like a hack, but I needed a way to be sure the DB is read before reading the ini files
|
||||
EM_ASM_INT({
|
||||
FS.mkdir('hcl_data');
|
||||
FS.mount(IDBFS,{},'hcl_data');
|
||||
Module.print("Will import permanent storage");
|
||||
FS.syncfs(true, function() {
|
||||
Module.print("Permanent storage imported");
|
||||
HEAP32[$0>>2] = 1;
|
||||
});
|
||||
}, &fileSynched);
|
||||
#endif
|
||||
#ifdef _3DS
|
||||
sdmcInit();
|
||||
osSetSpeedupEnable(false);
|
||||
#endif
|
||||
#ifdef _SDL
|
||||
if ( SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
SDL_Delay(5000);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#if defined(PANDORA) || defined(PYRA) || defined(CHIP) || defined(ODROID)
|
||||
wantFullscreen = 1;
|
||||
#else
|
||||
wantFullscreen = 0;
|
||||
#endif
|
||||
#ifdef CHIP
|
||||
screenScale = 1;
|
||||
#elif defined(BITTBOY)
|
||||
screenScale = 1;
|
||||
#elif defined(PYRA)
|
||||
//screenScale = 3;
|
||||
desktopFS = 1;
|
||||
#elif defined(ODROID)
|
||||
desktopFS = 1;
|
||||
#else
|
||||
screenScale = 2;
|
||||
#endif
|
||||
useJoystick = 1;
|
||||
// get command line arguments
|
||||
for (int i=1; i<argc; i++)
|
||||
{
|
||||
if(!strcmp(argv[i], "-f"))
|
||||
wantFullscreen = 1;
|
||||
if(!strcmp(argv[i], "--fullscreen"))
|
||||
wantFullscreen = 1;
|
||||
if(!strcmp(argv[i], "-d"))
|
||||
desktopFS = 1;
|
||||
if(!strcmp(argv[i], "--desktop"))
|
||||
desktopFS = 1;
|
||||
if(!strcmp(argv[i], "-x1"))
|
||||
screenScale = 1;
|
||||
if(!strcmp(argv[i], "-x2"))
|
||||
screenScale = 2;
|
||||
if(!strcmp(argv[i], "-x3"))
|
||||
screenScale = 3;
|
||||
if(!strcmp(argv[i], "-x4"))
|
||||
screenScale = 4;
|
||||
if(!strcmp(argv[i], "-x5"))
|
||||
screenScale = 5;
|
||||
if(!strcmp(argv[i], "--xbrz"))
|
||||
setXBRZ(1);
|
||||
if(!strcmp(argv[i], "--no-xbrz"))
|
||||
setXBRZ(0);
|
||||
if(!strcmp(argv[i], "-j"))
|
||||
useJoystick = 0;
|
||||
if(!strcmp(argv[i], "--nojoy"))
|
||||
useJoystick = 0;
|
||||
if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
|
||||
printf("Quick help\n-f|--fullscreen\tUse fullscreen\n-d|--desktop\tdesktop fullscreen\n-x1|-x2|-x3|-x4\tUse screenScale of *1..*4 (default *2 = 640x480)\n-j|-nojoy\tdo not use Joystick\n--xbrz\tUse xBRZ scaling\n--no-xbrz\tNo xBRZ scaling\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
if(desktopFS)
|
||||
{
|
||||
#ifdef _SDL2
|
||||
SDL_DisplayMode infos;
|
||||
SDL_GetCurrentDisplayMode(0, &infos);
|
||||
screenW = infos.w;
|
||||
screenH = infos.h;
|
||||
#else
|
||||
const SDL_VideoInfo* infos = SDL_GetVideoInfo();
|
||||
screenH = infos->current_h;
|
||||
screenW = infos->current_w;
|
||||
#endif
|
||||
} else {
|
||||
screenW = 320 * screenScale;
|
||||
screenH = 240 * screenScale;
|
||||
}
|
||||
printf("Hydra Castle Labyrinth, %s %dx%d scale=x%d%s, using Joystick=%d\n", (wantFullscreen || desktopFS)?"Fullscreen":"Windowed", screenW, screenH, screenScale, getXBRZ()?" xBRZ":"", useJoystick);
|
||||
#endif
|
||||
|
||||
srand(time(NULL));
|
||||
createSaveLocations();
|
||||
|
||||
game();
|
||||
|
||||
//System specific cleanup
|
||||
#ifdef _PSP
|
||||
sceKernelExitGame();
|
||||
#endif
|
||||
|
||||
#ifdef _3DS
|
||||
sdmcExit();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
92
contrib/games/hydracastlelabyrinth/src/misc.c
Normal file
92
contrib/games/hydracastlelabyrinth/src/misc.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
void *memrchr(const void *m, int c, size_t n)
|
||||
{
|
||||
const unsigned char *s = (const unsigned char*)m;
|
||||
c = (unsigned char)c;
|
||||
while (n--) if (s[n]==c) return (void *)(s+n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setcwd(char* path){
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
::"a"(30), "b"(1), "c"(path)
|
||||
:"memory"
|
||||
);
|
||||
}
|
||||
|
||||
char *dirname(char *path)
|
||||
{
|
||||
static const char dot[] = ".";
|
||||
char *last_slash;
|
||||
last_slash = path != NULL ? strrchr (path, '/') : NULL;
|
||||
if (last_slash != NULL && last_slash != path && last_slash[1] == '\0')
|
||||
{
|
||||
char *runp;
|
||||
for (runp = last_slash; runp != path; --runp)
|
||||
if (runp[-1] != '/')
|
||||
break;
|
||||
if (runp != path)
|
||||
last_slash = (char*)memrchr((void*)path, '/', runp - path);
|
||||
}
|
||||
if (last_slash != NULL)
|
||||
{
|
||||
char *runp;
|
||||
for (runp = last_slash; runp != path; --runp)
|
||||
if (runp[-1] != '/')
|
||||
break;
|
||||
if (runp == path)
|
||||
{
|
||||
if (last_slash == path + 1)
|
||||
++last_slash;
|
||||
else
|
||||
last_slash = path + 1;
|
||||
}
|
||||
else
|
||||
last_slash = runp;
|
||||
last_slash[0] = '\0';
|
||||
}
|
||||
else
|
||||
path = (char *) dot;
|
||||
return path;
|
||||
}
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct{
|
||||
unsigned p00;
|
||||
union{
|
||||
uint64_t p04;
|
||||
struct {
|
||||
unsigned p04dw;
|
||||
unsigned p08dw;
|
||||
};
|
||||
};
|
||||
unsigned p12;
|
||||
union {
|
||||
unsigned p16;
|
||||
const char *new_name;
|
||||
void *bdfe;
|
||||
void *buf16;
|
||||
const void *cbuf16;
|
||||
};
|
||||
char p20;
|
||||
const char *p21;
|
||||
}ksys70_t;
|
||||
|
||||
|
||||
int kos_mkdir(const char *path, unsigned v)
|
||||
{
|
||||
int status;
|
||||
ksys70_t dir_opt;
|
||||
dir_opt.p00 = 9;
|
||||
dir_opt.p21 = path;
|
||||
__asm__ __volatile__(
|
||||
"int $0x40"
|
||||
:"=a"(status)
|
||||
:"a"(70), "b"(&dir_opt)
|
||||
:"memory"
|
||||
);
|
||||
return status;
|
||||
}
|
1532
contrib/games/hydracastlelabyrinth/src/object.c
Normal file
1532
contrib/games/hydracastlelabyrinth/src/object.c
Normal file
File diff suppressed because it is too large
Load Diff
181
contrib/games/hydracastlelabyrinth/src/object.h
Normal file
181
contrib/games/hydracastlelabyrinth/src/object.h
Normal file
@ -0,0 +1,181 @@
|
||||
#ifndef OBJECT_H
|
||||
#define OBJECT_H
|
||||
|
||||
#include "collision.h"
|
||||
|
||||
typedef struct {
|
||||
void* data; //Specific object struct
|
||||
void (*objectStep)();
|
||||
void (*objectDraw)();
|
||||
int type;
|
||||
} Object;
|
||||
|
||||
void objectDestroy(int id);
|
||||
|
||||
//Health/Ammo collectables
|
||||
typedef struct {
|
||||
int id, type; //0 for ammo, 1 for heart
|
||||
double x, y,
|
||||
vsp, grav;
|
||||
|
||||
int blink, canLand, bounce;
|
||||
} Ammo;
|
||||
|
||||
void spawnCollectable(int x, int y);
|
||||
void createAmmo(int x, int y, int type);
|
||||
|
||||
//Destroyable blocks
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
int hp/*, invulnerable*/;
|
||||
int secret;
|
||||
Mask mask;
|
||||
} Destroyable;
|
||||
|
||||
void createDestroyable(int x, int y, int secret);
|
||||
|
||||
//Secret Trigger
|
||||
typedef struct {
|
||||
int id, flag;
|
||||
int type, enemyType;
|
||||
} SecretTrigger;
|
||||
|
||||
void createSecretTrigger(int type, int enemyType, int flag);
|
||||
|
||||
//Chest
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
int item, secret;
|
||||
int visible;
|
||||
int timer;
|
||||
|
||||
Mask mask;
|
||||
} Chest;
|
||||
|
||||
void createChest(int x, int y, int item, int secret);
|
||||
|
||||
//Save point
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
double imageIndex;
|
||||
|
||||
Mask mask;
|
||||
} SavePoint;
|
||||
|
||||
void createSavePoint(int x, int y, int hidden);
|
||||
|
||||
//Door
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
int open, secret, visible;
|
||||
|
||||
int warplevel, warpcoords;
|
||||
int warpx, warpy;
|
||||
|
||||
Mask mask;
|
||||
} Door;
|
||||
|
||||
void createDoor(int x, int y, int level, int coords, int warpx, int warpy, int secret);
|
||||
|
||||
//Lock Block
|
||||
typedef struct {
|
||||
int id, flag;
|
||||
int x, y;
|
||||
int tile;
|
||||
int invincible;
|
||||
} LockBlock;
|
||||
|
||||
void createLockBlock(int x, int y, int flag);
|
||||
|
||||
//Light Switch
|
||||
typedef struct {
|
||||
int id, flag;
|
||||
int x, y;
|
||||
int activated;
|
||||
double imageIndex;
|
||||
} Switch;
|
||||
|
||||
void createSwitch(int x, int y, int flag);
|
||||
|
||||
//Blue/Red Gates
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
int col;
|
||||
int timer, open;
|
||||
//int invincible;
|
||||
double imageIndex;
|
||||
} Gate;
|
||||
|
||||
void createGate(int x, int y, int col);
|
||||
|
||||
//Statue
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
int type;
|
||||
int invincible;
|
||||
int hp;
|
||||
} Statue;
|
||||
|
||||
void createStatue(int x, int y, int type);
|
||||
|
||||
//Button
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
int flag;
|
||||
int pressed;
|
||||
} FloorPad;
|
||||
|
||||
void createFloorPad(int x, int y, int flag);
|
||||
|
||||
//Ladder
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
int flag;
|
||||
} Ladder;
|
||||
|
||||
void createLadder(int x, int y, int flag);
|
||||
|
||||
//Generator
|
||||
typedef struct {
|
||||
int id;
|
||||
int hp;
|
||||
int blink;
|
||||
int x, y;
|
||||
double imageIndex;
|
||||
int flag;
|
||||
} Generator;
|
||||
|
||||
void createGenerator(int x, int y, int flag);
|
||||
|
||||
//Electric gate
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, y;
|
||||
double imageIndex;
|
||||
int flag;
|
||||
} Shockgate;
|
||||
|
||||
void createShockgate(int x, int y, int flag);
|
||||
|
||||
//Ending crown
|
||||
typedef struct {
|
||||
int id;
|
||||
int x, ystart;
|
||||
double y;
|
||||
double bobRot;
|
||||
double imageIndex;
|
||||
int timer;
|
||||
char visible;
|
||||
} Crown;
|
||||
|
||||
void createCrown(int x, int y);
|
||||
|
||||
#endif
|
381
contrib/games/hydracastlelabyrinth/src/options.c
Normal file
381
contrib/games/hydracastlelabyrinth/src/options.c
Normal file
@ -0,0 +1,381 @@
|
||||
#include <stdio.h>
|
||||
#include "options.h"
|
||||
#include "PHL.h"
|
||||
#include "game.h"
|
||||
#include "ini.h"
|
||||
#include "text.h"
|
||||
|
||||
char page = 0;
|
||||
int optCursor = 0;
|
||||
int lastOption = -1;
|
||||
#ifdef _SDL
|
||||
int musicType = 1;
|
||||
|
||||
int getMusicType()
|
||||
{
|
||||
return musicType;
|
||||
}
|
||||
void setMusicType(int t)
|
||||
{
|
||||
#ifndef _KOLIBRI
|
||||
if(t!=musicType)
|
||||
{
|
||||
musicType = t;
|
||||
// restart music...
|
||||
}
|
||||
#else
|
||||
musicType = 1; /* MIDI NOT WORK! */
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
static char tempDark;
|
||||
static int emOnly;
|
||||
void optionsSetup(int only)
|
||||
{
|
||||
tempDark = roomDarkness;
|
||||
roomDarkness = 0;
|
||||
emOnly = only;
|
||||
page = only?1:0;
|
||||
}
|
||||
|
||||
int optionsEMStep()
|
||||
{
|
||||
int loop = 1;
|
||||
PHL_MainLoop();
|
||||
|
||||
PHL_StartDrawing();
|
||||
|
||||
optionsDraw();
|
||||
|
||||
PHL_ScanInput();
|
||||
int result = optionsStep();
|
||||
|
||||
PHL_EndDrawing();
|
||||
|
||||
if (page == 0 && result != -1 && result != 2) {
|
||||
loop = 0;
|
||||
}
|
||||
if (emOnly && page==0) {
|
||||
loop = 0;
|
||||
}
|
||||
|
||||
if(!loop) roomDarkness = tempDark;
|
||||
|
||||
return (!loop)?result:-1;
|
||||
}
|
||||
#else
|
||||
|
||||
int options(int only)
|
||||
{
|
||||
char tempDark = roomDarkness;
|
||||
roomDarkness = 0;
|
||||
|
||||
int result = -1;
|
||||
char loop = 1;
|
||||
|
||||
if(only) page=1;
|
||||
|
||||
while (PHL_MainLoop() && loop == 1)
|
||||
{
|
||||
PHL_StartDrawing();
|
||||
|
||||
optionsDraw();
|
||||
|
||||
PHL_ScanInput();
|
||||
result = optionsStep();
|
||||
|
||||
PHL_EndDrawing();
|
||||
|
||||
if (page == 0 && result != -1 && result != 2) {
|
||||
loop = 0;
|
||||
}
|
||||
if (only && page==0) {
|
||||
loop = 0;
|
||||
}
|
||||
}
|
||||
|
||||
roomDarkness = tempDark;
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
int optionsStep()
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
secretCountdown();
|
||||
|
||||
//input
|
||||
if (btnDown.pressed == 1) {
|
||||
optCursor += 1;
|
||||
PHL_PlaySound(sounds[sndPi01], CHN_SOUND);
|
||||
|
||||
}else if (btnUp.pressed == 1) {
|
||||
optCursor -= 1;
|
||||
PHL_PlaySound(sounds[sndPi01], CHN_SOUND);
|
||||
}
|
||||
|
||||
//First screen (continue/reset/exit)
|
||||
if (page == 0) {
|
||||
//Limit cursor
|
||||
if (optCursor >= 4) {
|
||||
optCursor = 0;
|
||||
}
|
||||
|
||||
if (optCursor < 0) {
|
||||
optCursor = 3;
|
||||
}
|
||||
|
||||
if (btnAccept.pressed == 1 || btnStart.pressed == 1) {
|
||||
result = optCursor;
|
||||
if (result == 1) {
|
||||
PHL_StopMusic();
|
||||
}
|
||||
if (result == 2) {
|
||||
page = 1;
|
||||
optCursor = 0;
|
||||
}
|
||||
|
||||
//No blip on game exit
|
||||
if (optCursor != 3) {
|
||||
PHL_PlaySound(sounds[sndOk], CHN_SOUND);
|
||||
}
|
||||
}
|
||||
|
||||
if (btnSelect.pressed == 1) {
|
||||
result = 0;
|
||||
PHL_PlaySound(sounds[sndOk], CHN_SOUND);
|
||||
}
|
||||
}
|
||||
//Actual options screen
|
||||
else if (page == 1) {
|
||||
//Limit cursor
|
||||
if (optCursor > lastOption) {
|
||||
optCursor = 0;
|
||||
}
|
||||
|
||||
if (optCursor < 0) {
|
||||
optCursor = lastOption;
|
||||
}
|
||||
|
||||
if (btnAccept.pressed == 1 || btnStart.pressed == 1) {
|
||||
//Universal settings
|
||||
//Language
|
||||
if (optCursor == 0) {
|
||||
if (getLanguage() == JAPANESE) {
|
||||
setLanguage(ENGLISH);
|
||||
}else{
|
||||
setLanguage(JAPANESE);
|
||||
}
|
||||
}
|
||||
|
||||
//Autosave
|
||||
if (optCursor == 1) {
|
||||
if (getAutoSave() == 0) {
|
||||
setAutoSave(1);
|
||||
}else{
|
||||
setAutoSave(0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _3DS
|
||||
if (optCursor == 2) {
|
||||
if (activeScreen->screen == GFX_TOP) {
|
||||
swapScreen(GFX_BOTTOM, GFX_LEFT);
|
||||
}else{
|
||||
swapScreen(GFX_TOP, GFX_LEFT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _PSP
|
||||
if (optCursor == 2) {
|
||||
if (getScreenSize() == 0) {
|
||||
setScreenSize(1);
|
||||
}else if (getScreenSize() == 1) {
|
||||
setScreenSize(2);
|
||||
}else{
|
||||
setScreenSize(0);
|
||||
}
|
||||
}
|
||||
|
||||
//Blur
|
||||
if (optCursor == 3) {
|
||||
if (getBlur() == 0) {
|
||||
setBlur(1);
|
||||
}else{
|
||||
setBlur(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _SDL
|
||||
// Music type
|
||||
if(optCursor == 2) {
|
||||
if(getMusicType() == 0)
|
||||
setMusicType(1);
|
||||
else
|
||||
setMusicType(0);
|
||||
}
|
||||
// Music volume
|
||||
if(optCursor == 3) {
|
||||
music_volume = (music_volume+1)%5;
|
||||
PHL_MusicVolume(0.25f * music_volume);
|
||||
}
|
||||
// xBRZ
|
||||
if (optCursor == 4) {
|
||||
if (getXBRZ() == 0) {
|
||||
setXBRZ(1);
|
||||
}else{
|
||||
setXBRZ(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//Back
|
||||
if (optCursor == lastOption) {
|
||||
page = 0;
|
||||
}
|
||||
}
|
||||
else if (btnDecline.pressed == 1) {
|
||||
page = 0;
|
||||
}
|
||||
|
||||
if (page == 0) {
|
||||
saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void optionsDraw()
|
||||
{
|
||||
PHL_DrawRect(0, 0, 640, 480, PHL_NewRGB(0, 0, 0));
|
||||
|
||||
if (page == 0)
|
||||
{
|
||||
PHL_DrawTextBold("CONTINUE", 254, 144, YELLOW);
|
||||
PHL_DrawTextBold("RESET", 278, 176, YELLOW);
|
||||
PHL_DrawTextBold("OPTIONS", 262, 208, YELLOW);
|
||||
PHL_DrawTextBold("EXIT", 286, 240, YELLOW);
|
||||
|
||||
PHL_DrawTextBold("<", 232, 144 + (32 * optCursor), RED);
|
||||
PHL_DrawTextBold(">", 390, 144 + (32 * optCursor), RED);
|
||||
}
|
||||
else if (page == 1)
|
||||
{
|
||||
int xleft = 216;
|
||||
int xright = xleft + 160;
|
||||
|
||||
int ydrawstart = 144;
|
||||
int ydraw = ydrawstart;
|
||||
int ystep = 32;
|
||||
int optioncount = 0;
|
||||
|
||||
//Language
|
||||
PHL_DrawTextBold("LANGUAGE", xleft, ydraw, YELLOW);
|
||||
if (getLanguage() == 1) {
|
||||
PHL_DrawTextBold("EN", xright, ydraw, YELLOW);
|
||||
}
|
||||
if (getLanguage() == 0) {
|
||||
PHL_DrawTextBold("JP", xright, ydraw, YELLOW);
|
||||
}
|
||||
|
||||
ydraw += ystep;
|
||||
optioncount++;
|
||||
|
||||
//AutoSave
|
||||
PHL_DrawTextBold("SAFE SAVE", xleft, ydraw, YELLOW);
|
||||
if (getAutoSave() == 1) {
|
||||
PHL_DrawTextBold("ON", xright, ydraw, YELLOW);
|
||||
}else{
|
||||
PHL_DrawTextBold("OFF", xright, ydraw, YELLOW);
|
||||
}
|
||||
|
||||
ydraw += ystep;
|
||||
optioncount++;
|
||||
|
||||
#ifdef _3DS
|
||||
//Screen
|
||||
PHL_DrawTextBold("SCREEN", xleft, ydraw, YELLOW);
|
||||
if (activeScreen->screen == GFX_TOP) {
|
||||
PHL_DrawTextBold("TOP", xright, ydraw, YELLOW);
|
||||
}else{
|
||||
PHL_DrawTextBold("BOTTOM", xright, ydraw, YELLOW);
|
||||
}
|
||||
|
||||
ydraw += ystep;
|
||||
optioncount++;
|
||||
#endif
|
||||
|
||||
#ifdef _PSP
|
||||
//Screen Size
|
||||
PHL_DrawTextBold("SCREEN", xleft, ydraw, YELLOW);
|
||||
if (getScreenSize() == 0) {
|
||||
PHL_DrawTextBold("1:1", xright, ydraw, YELLOW);
|
||||
}
|
||||
else if (getScreenSize() == 1) {
|
||||
PHL_DrawTextBold("FILL", xright, ydraw, YELLOW);
|
||||
}
|
||||
else if (getScreenSize() == 2) {
|
||||
PHL_DrawTextBold("FULL", xright, ydraw, YELLOW);
|
||||
}
|
||||
|
||||
ydraw += ystep;
|
||||
optioncount++;
|
||||
|
||||
//Blur
|
||||
PHL_DrawTextBold("BLUR", xleft, ydraw, YELLOW);
|
||||
if (getBlur() == 1) {
|
||||
PHL_DrawTextBold("ON", xright, ydraw, YELLOW);
|
||||
}
|
||||
else{
|
||||
PHL_DrawTextBold("OFF", xright, ydraw, YELLOW);
|
||||
}
|
||||
|
||||
ydraw += ystep;
|
||||
optioncount++;
|
||||
#endif
|
||||
|
||||
#ifdef _SDL
|
||||
// Music type
|
||||
PHL_DrawTextBold("MUSIC", xleft, ydraw, YELLOW);
|
||||
if (getMusicType() == 1) {
|
||||
PHL_DrawTextBold("OGG", xright, ydraw, YELLOW);
|
||||
}
|
||||
else{
|
||||
PHL_DrawTextBold("MIDI", xright, ydraw, YELLOW);
|
||||
}
|
||||
ydraw += ystep;
|
||||
optioncount++;
|
||||
// Music volume
|
||||
PHL_DrawTextBold("MUSIC", xleft, ydraw, YELLOW);
|
||||
char buff[50];
|
||||
sprintf(buff, "%d%%", music_volume*25);
|
||||
PHL_DrawTextBold(buff, xright, ydraw, YELLOW);
|
||||
ydraw += ystep;
|
||||
optioncount++;
|
||||
// xBRZ scaling
|
||||
PHL_DrawTextBold("XBRZ", xleft, ydraw, YELLOW);
|
||||
if (getXBRZ() == 1) {
|
||||
PHL_DrawTextBold("ON", xright, ydraw, YELLOW);
|
||||
}
|
||||
else{
|
||||
PHL_DrawTextBold("OFF", xright, ydraw, YELLOW);
|
||||
}
|
||||
ydraw += ystep;
|
||||
optioncount++;
|
||||
#endif
|
||||
|
||||
PHL_DrawTextBold("BACK", xleft, ydraw, YELLOW);
|
||||
|
||||
if (lastOption == -1) {
|
||||
lastOption = optioncount;
|
||||
}
|
||||
|
||||
PHL_DrawTextBold(">", xleft - 32, ydrawstart + (ystep * optCursor), RED);
|
||||
}
|
||||
}
|
18
contrib/games/hydracastlelabyrinth/src/options.h
Normal file
18
contrib/games/hydracastlelabyrinth/src/options.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef OPTIONS_H
|
||||
#define OPTIONS_H
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
void optionsSetup(int only);
|
||||
int optionsEMStep();
|
||||
#else
|
||||
int options(int only);
|
||||
#endif
|
||||
|
||||
int optionsStep();
|
||||
void optionsDraw();
|
||||
#ifdef _SDL
|
||||
int getMusicType();
|
||||
void setMusicType(int t);
|
||||
#endif
|
||||
|
||||
#endif
|
223
contrib/games/hydracastlelabyrinth/src/platform.c
Normal file
223
contrib/games/hydracastlelabyrinth/src/platform.c
Normal file
@ -0,0 +1,223 @@
|
||||
#include "platform.h"
|
||||
#include "game.h"
|
||||
#include "PHL.h"
|
||||
#include "hero.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void createPlatform(int type, int xstart, int ystart, int xend, int yend, int spd, int secret)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_PLATFORMS; i++) {
|
||||
if (platforms[i] == NULL) {
|
||||
Platform* p = malloc(sizeof *p);
|
||||
p->id = i;
|
||||
p->type = type;
|
||||
|
||||
p->x = p->xstart = xstart;
|
||||
p->y = p->ystart = ystart;
|
||||
|
||||
p->xend = xend;
|
||||
p->yend = yend;
|
||||
|
||||
p->timer = 0;
|
||||
|
||||
p->secret = secret;
|
||||
|
||||
if (roomSecret == 1) {
|
||||
p->secret = 0;
|
||||
}
|
||||
|
||||
p->visible = 1;
|
||||
if (p->secret == 1) {
|
||||
p->visible = 0;
|
||||
}
|
||||
|
||||
if (type == 1) {
|
||||
p->xend = p->x + 1;
|
||||
p->yend = p->y;
|
||||
}
|
||||
|
||||
p->state = 0;
|
||||
p->spd = spd;
|
||||
|
||||
p->mask.circle = 0;
|
||||
p->mask.unused = 0;
|
||||
if (p->secret == 1) {
|
||||
p->mask.unused = 1;
|
||||
}
|
||||
p->mask.x = xstart;
|
||||
p->mask.y = ystart;
|
||||
p->mask.w = p->mask.h = 40;
|
||||
|
||||
platforms[i] = p;
|
||||
i = MAX_PLATFORMS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void platformStep(Platform* p)
|
||||
{
|
||||
char isSolid = p->visible;
|
||||
|
||||
//Megaman blocks
|
||||
if (p->type == 2) {
|
||||
int myStep = p->xend,
|
||||
maxSteps = p->yend;
|
||||
|
||||
p->timer += 1;
|
||||
if (p->timer >= maxSteps * 60 + 60) {
|
||||
p->timer = 0;
|
||||
}
|
||||
|
||||
//Play sound
|
||||
if (p->timer == myStep * 60) {
|
||||
PHL_PlaySound(sounds[sndPi03], CHN_SOUND);
|
||||
}
|
||||
|
||||
if (p->timer > myStep * 60 && p->timer <= (myStep * 60) + 60) {
|
||||
isSolid = 1;
|
||||
p->visible = 1;
|
||||
|
||||
//Blink effect
|
||||
if (p->timer > myStep * 60 + 30) {
|
||||
p->visible = p->timer % 2;
|
||||
}
|
||||
}else{
|
||||
isSolid = 0;
|
||||
p->mask.unused = 1;
|
||||
p->visible = 0;
|
||||
|
||||
//Fall off platform
|
||||
if (getHeroMask().x > p->mask.x + p->mask.w || getHeroMask().x + getHeroMask().w < p->mask.x) {
|
||||
}else if (heroy == p->y - 40 && getHeroVsp() >= 0) {
|
||||
setHeroOnground(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isSolid == 1) {
|
||||
p->mask.unused = 0;
|
||||
|
||||
int targx = p->xend,
|
||||
targy = p->yend;
|
||||
|
||||
if (p->state == 1) {
|
||||
targx = p->xstart;
|
||||
targy = p->ystart;
|
||||
}
|
||||
|
||||
//Check if the player is standing on top
|
||||
int isontop = 0;
|
||||
int isabove = 0;
|
||||
if (getHeroMask().x > p->mask.x + p->mask.w || getHeroMask().x + getHeroMask().w < p->mask.x) {
|
||||
}else if (heroy == p->y - 40 && getHeroVsp() >= 0) {
|
||||
isontop = 1;
|
||||
}else if (heroy < p->y - 40) {
|
||||
isabove = 1;
|
||||
}
|
||||
|
||||
//Move platform
|
||||
if (p->y != targy) {
|
||||
if (p->y < targy) {
|
||||
p->y += p->spd;
|
||||
if (isontop == 1) {
|
||||
heroy += p->spd;
|
||||
}
|
||||
}else{
|
||||
p->y -= p->spd;
|
||||
if (isontop == 1) {
|
||||
heroy -= p->spd;
|
||||
}else{
|
||||
p->mask.y = p->y;
|
||||
if (checkCollision(p->mask, getHeroMask()) && isabove == 1) {
|
||||
heroy = p->y - 40;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p->x != targx) {
|
||||
if (p->x < targx) {
|
||||
p->x += p->spd;
|
||||
if (isontop == 1) {
|
||||
herox += p->spd;
|
||||
}
|
||||
}else{
|
||||
p->x -= p->spd;
|
||||
if (isontop == 1) {
|
||||
herox -= p->spd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p->x == targx && p->y == targy) {
|
||||
if (p->state == 0) {
|
||||
p->state = 1;
|
||||
}else{
|
||||
p->state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (p->type == 0) //Moving platform
|
||||
{
|
||||
|
||||
}
|
||||
else if (p->type == 1) { //Loose block
|
||||
if (p->spd != 0) {
|
||||
p->timer -= 1;
|
||||
if (p->timer <= 0) {
|
||||
createRockSmash(p->x + 20, p->y + 20);
|
||||
if (isontop == 1) {
|
||||
setHeroOnground(0);
|
||||
}
|
||||
platformDestroy(p->id);
|
||||
/*createEffectExtra(4, p->x, p->y, -1, 0, 0);
|
||||
createEffectExtra(4, p->x, p->y, -1, 0, 1);
|
||||
createEffectExtra(4, p->x, p->y, 1, 0, 0);
|
||||
createEffectExtra(4, p->x, p->y, 1, 0, 1);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (p->spd == 0 && isontop == 1) {
|
||||
p->spd = 2;
|
||||
p->timer = 30;
|
||||
}
|
||||
}
|
||||
|
||||
//Update Mask
|
||||
p->mask.x = p->x;
|
||||
p->mask.y = p->y;
|
||||
}else{
|
||||
//p->mask.unused = 1;
|
||||
if (p->secret == 1) {
|
||||
if (roomSecret == 1) {
|
||||
p->mask.unused = 0;
|
||||
p->visible = 1;
|
||||
p->secret = 0;
|
||||
playSecret();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void platformDraw(Platform* p)
|
||||
{
|
||||
if (p->visible == 1) {
|
||||
int cropX = p->type * 40;
|
||||
|
||||
if (p->type == 3) {
|
||||
cropX = 9 * 40;
|
||||
}
|
||||
|
||||
PHL_DrawSurfacePart(p->x, p->y, cropX, 400, 40, 40, images[imgMisc20]);
|
||||
}
|
||||
}
|
||||
|
||||
void platformDestroy(int id)
|
||||
{
|
||||
if (platforms[id] != NULL) {
|
||||
free(platforms[id]);
|
||||
}
|
||||
platforms[id] = NULL;
|
||||
}
|
26
contrib/games/hydracastlelabyrinth/src/platform.h
Normal file
26
contrib/games/hydracastlelabyrinth/src/platform.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#include "collision.h"
|
||||
|
||||
typedef struct {
|
||||
int id, type; //0 = moving platform
|
||||
double x, y;
|
||||
int xstart, ystart;
|
||||
int xend, yend;
|
||||
int state;
|
||||
double spd;
|
||||
int timer;
|
||||
int secret, visible;
|
||||
|
||||
Mask mask;
|
||||
} Platform;
|
||||
|
||||
void createPlatform(int type, int xstart, int ystart, int xend, int yend, int spd, int secret);
|
||||
|
||||
void platformStep(Platform* p);
|
||||
void platformDraw(Platform* p);
|
||||
|
||||
void platformDestroy(int id);
|
||||
|
||||
#endif
|
72
contrib/games/hydracastlelabyrinth/src/qda.c
Normal file
72
contrib/games/hydracastlelabyrinth/src/qda.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include "qda.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined(__amigaos4__) || defined(__MORPHOS__)
|
||||
#include "amigaos.h"
|
||||
#endif
|
||||
|
||||
QDAHeader headers[29];
|
||||
//Load headers for each image
|
||||
//Returns: 0 = file not found | 1 = success | 2 = Invalid file
|
||||
int initQDA()
|
||||
{
|
||||
int result = 0;
|
||||
FILE* f;
|
||||
|
||||
char fullPath[80];
|
||||
#ifdef _SDL
|
||||
strcpy(fullPath, "data/");
|
||||
#else
|
||||
strcpy(fullPath, "");
|
||||
#endif
|
||||
#ifdef _3DS
|
||||
strcat(fullPath, "romfs:/");
|
||||
#endif
|
||||
strcat(fullPath, "bmp.qda");
|
||||
|
||||
if ( (f = fopen(fullPath, "rb")) ) {
|
||||
result = 1;
|
||||
|
||||
//Read header data into memory
|
||||
int allHeadersSize = 0x1F5C;
|
||||
unsigned char* QDAFile = (unsigned char*)malloc(allHeadersSize);
|
||||
int tmp = fread(QDAFile, allHeadersSize, 1, f);
|
||||
(void)tmp;
|
||||
|
||||
//Check if QDA file is valid
|
||||
{
|
||||
if (QDAFile[4] == 0x51 && QDAFile[5] == 0x44 && QDAFile[6] == 0x41 && QDAFile[7] == 0x30) {
|
||||
//Load headers separately
|
||||
{
|
||||
int numofsheets = 29;
|
||||
int headerSize = 0x10C;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < numofsheets; i++) {
|
||||
//memcpy(&headers[i], &QDAFile[0x100 + (i * headerSize)], sizeof(QDAHeader));
|
||||
int offset = 256 + (i * headerSize);
|
||||
memcpy(&headers[i].offset, &QDAFile[offset], 4);
|
||||
memcpy(&headers[i].size, &QDAFile[offset + 4], 4);
|
||||
memcpy(&headers[i].bytes, &QDAFile[offset + 8], 4);
|
||||
memcpy(&headers[i].fileName, &QDAFile[offset + 12], 0x100);
|
||||
#if defined(__amigaos4__) || defined(__MORPHOS__)
|
||||
BE32(&headers[i].offset);
|
||||
BE32(&headers[i].size);
|
||||
BE32(&headers[i].bytes);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}else{
|
||||
result = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Cleanup
|
||||
free(QDAFile);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return result;
|
||||
}
|
14
contrib/games/hydracastlelabyrinth/src/qda.h
Normal file
14
contrib/games/hydracastlelabyrinth/src/qda.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef QDA_H
|
||||
#define QDA_H
|
||||
|
||||
typedef struct {
|
||||
unsigned long offset;
|
||||
unsigned long size;
|
||||
unsigned long bytes;
|
||||
unsigned char* fileName[256];
|
||||
} QDAHeader;
|
||||
|
||||
extern QDAHeader headers[29]; //names, offsets, and sizes of each sheet
|
||||
int initQDA();
|
||||
|
||||
#endif
|
83
contrib/games/hydracastlelabyrinth/src/sdl/audio.c
Normal file
83
contrib/games/hydracastlelabyrinth/src/sdl/audio.c
Normal file
@ -0,0 +1,83 @@
|
||||
#include "audio.h"
|
||||
#include "../options.h"
|
||||
#include <SDL.h>
|
||||
|
||||
int music_volume = 4;
|
||||
|
||||
void PHL_AudioInit()
|
||||
{
|
||||
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||
#ifndef __MORPHOS__
|
||||
Mix_Init(MIX_INIT_OGG); // midi is on by default
|
||||
#endif
|
||||
Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096);
|
||||
|
||||
PHL_MusicVolume(0.25f * music_volume);
|
||||
}
|
||||
|
||||
void PHL_AudioClose()
|
||||
{
|
||||
Mix_CloseAudio();
|
||||
#ifndef __MORPHOS__
|
||||
Mix_Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
//Same as PHL_LoadSound, but expects a file name without extension
|
||||
PHL_Music PHL_LoadMusic(char* fname, int loop)
|
||||
{
|
||||
PHL_Music ret;
|
||||
ret.loop = loop;
|
||||
char buff[4096];
|
||||
strcpy(buff, "data/");
|
||||
strcat(buff, fname);
|
||||
strcat(buff, getMusicType()?".ogg":".mid");
|
||||
ret.snd = Mix_LoadMUS(buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PHL_Sound PHL_LoadSound(char* fname)
|
||||
{
|
||||
char buff[4096];
|
||||
strcpy(buff, "data/");
|
||||
strcat(buff, fname);
|
||||
return Mix_LoadWAV(buff);
|
||||
}
|
||||
|
||||
void PHL_MusicVolume(float vol)
|
||||
{
|
||||
Mix_VolumeMusic(SDL_MIX_MAXVOLUME*vol);
|
||||
}
|
||||
|
||||
void PHL_PlayMusic(PHL_Music snd)
|
||||
{
|
||||
if(snd.snd)
|
||||
Mix_PlayMusic(snd.snd, snd.loop?-1:0);
|
||||
}
|
||||
|
||||
void PHL_PlaySound(PHL_Sound snd, int channel)
|
||||
{
|
||||
Mix_PlayChannel(channel, snd, 0);
|
||||
}
|
||||
|
||||
void PHL_StopMusic()
|
||||
{
|
||||
Mix_HaltMusic();
|
||||
}
|
||||
|
||||
void PHL_StopSound(PHL_Sound snd, int channel)
|
||||
{
|
||||
Mix_HaltChannel(channel);
|
||||
}
|
||||
|
||||
void PHL_FreeMusic(PHL_Music snd)
|
||||
{
|
||||
if(snd.snd)
|
||||
Mix_FreeMusic(snd.snd);
|
||||
snd.snd = NULL;
|
||||
}
|
||||
|
||||
void PHL_FreeSound(PHL_Sound snd)
|
||||
{
|
||||
Mix_FreeChunk(snd);
|
||||
}
|
35
contrib/games/hydracastlelabyrinth/src/sdl/audio.h
Normal file
35
contrib/games/hydracastlelabyrinth/src/sdl/audio.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef SDLAUDIO_H
|
||||
#define SDLAUDIO_H
|
||||
|
||||
#include <SDL_mixer.h>
|
||||
#include <string.h>
|
||||
|
||||
//#define PHL_Music Mix_Music*
|
||||
#define PHL_Sound Mix_Chunk*
|
||||
typedef struct
|
||||
{
|
||||
int loop;
|
||||
Mix_Music* snd;
|
||||
|
||||
} PHL_Music;
|
||||
|
||||
extern int music_volume;
|
||||
|
||||
void PHL_AudioInit();
|
||||
void PHL_AudioClose();
|
||||
|
||||
void PHL_MusicVolume(float vol);
|
||||
|
||||
PHL_Music PHL_LoadMusic(char* fname, int loop); //Same as PHL_LoadSound, but expects a file name without extension
|
||||
PHL_Sound PHL_LoadSound(char* fname);
|
||||
|
||||
void PHL_PlayMusic(PHL_Music snd);
|
||||
void PHL_PlaySound(PHL_Sound snd, int channel);
|
||||
|
||||
void PHL_StopMusic();
|
||||
void PHL_StopSound(PHL_Sound snd, int channel);
|
||||
|
||||
void PHL_FreeMusic(PHL_Music snd);
|
||||
void PHL_FreeSound(PHL_Sound snd);
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user