Compare commits
No commits in common. 'master' and 'release0.1' have entirely different histories.
master
...
release0.1
87 changed files with 990 additions and 8935 deletions
@ -1,6 +1,6 @@ |
|||||||
[submodule "datastructures"] |
[submodule "datastructures"] |
||||||
path = datastructures |
path = datastructures |
||||||
url = https://git.topost.net/alistair/datastructures.git |
url = git@git.topost.net:alistair/datastructures.git |
||||||
[submodule "c-colours"] |
[submodule "c-colours"] |
||||||
path = c-colours |
path = c-colours |
||||||
url = https://git.topost.net/alistair/c-colours.git |
url = git@git.topost.net:alistair/c-colours.git |
||||||
|
@ -1,15 +0,0 @@ |
|||||||
AYIGIaRWaGH |
|
||||||
Copyright (C) 2020 Alistair Michael |
|
||||||
|
|
||||||
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 3 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, see <https://www.gnu.org/licenses/>. |
|
@ -1,97 +0,0 @@ |
|||||||
Copyright (c) 2010 Dimitar Toshkov Zhekov, |
|
||||||
with Reserved Font Name "Terminus Font". |
|
||||||
|
|
||||||
Copyright (c) 2011 Tilman Blumenbach, |
|
||||||
with Reserved Font Name "Terminus (TTF)". |
|
||||||
|
|
||||||
This Font Software is licensed under the SIL Open Font License, Version 1.1. |
|
||||||
This license is copied below, and is also available with a FAQ at: |
|
||||||
http://scripts.sil.org/OFL |
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------- |
|
||||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 |
|
||||||
----------------------------------------------------------- |
|
||||||
|
|
||||||
PREAMBLE |
|
||||||
The goals of the Open Font License (OFL) are to stimulate worldwide |
|
||||||
development of collaborative font projects, to support the font creation |
|
||||||
efforts of academic and linguistic communities, and to provide a free and |
|
||||||
open framework in which fonts may be shared and improved in partnership |
|
||||||
with others. |
|
||||||
|
|
||||||
The OFL allows the licensed fonts to be used, studied, modified and |
|
||||||
redistributed freely as long as they are not sold by themselves. The |
|
||||||
fonts, including any derivative works, can be bundled, embedded, |
|
||||||
redistributed and/or sold with any software provided that any reserved |
|
||||||
names are not used by derivative works. The fonts and derivatives, |
|
||||||
however, cannot be released under any other type of license. The |
|
||||||
requirement for fonts to remain under this license does not apply |
|
||||||
to any document created using the fonts or their derivatives. |
|
||||||
|
|
||||||
DEFINITIONS |
|
||||||
"Font Software" refers to the set of files released by the Copyright |
|
||||||
Holder(s) under this license and clearly marked as such. This may |
|
||||||
include source files, build scripts and documentation. |
|
||||||
|
|
||||||
"Reserved Font Name" refers to any names specified as such after the |
|
||||||
copyright statement(s). |
|
||||||
|
|
||||||
"Original Version" refers to the collection of Font Software components as |
|
||||||
distributed by the Copyright Holder(s). |
|
||||||
|
|
||||||
"Modified Version" refers to any derivative made by adding to, deleting, |
|
||||||
or substituting -- in part or in whole -- any of the components of the |
|
||||||
Original Version, by changing formats or by porting the Font Software to a |
|
||||||
new environment. |
|
||||||
|
|
||||||
"Author" refers to any designer, engineer, programmer, technical |
|
||||||
writer or other person who contributed to the Font Software. |
|
||||||
|
|
||||||
PERMISSION & CONDITIONS |
|
||||||
Permission is hereby granted, free of charge, to any person obtaining |
|
||||||
a copy of the Font Software, to use, study, copy, merge, embed, modify, |
|
||||||
redistribute, and sell modified and unmodified copies of the Font |
|
||||||
Software, subject to the following conditions: |
|
||||||
|
|
||||||
1) Neither the Font Software nor any of its individual components, |
|
||||||
in Original or Modified Versions, may be sold by itself. |
|
||||||
|
|
||||||
2) Original or Modified Versions of the Font Software may be bundled, |
|
||||||
redistributed and/or sold with any software, provided that each copy |
|
||||||
contains the above copyright notice and this license. These can be |
|
||||||
included either as stand-alone text files, human-readable headers or |
|
||||||
in the appropriate machine-readable metadata fields within text or |
|
||||||
binary files as long as those fields can be easily viewed by the user. |
|
||||||
|
|
||||||
3) No Modified Version of the Font Software may use the Reserved Font |
|
||||||
Name(s) unless explicit written permission is granted by the corresponding |
|
||||||
Copyright Holder. This restriction only applies to the primary font name as |
|
||||||
presented to the users. |
|
||||||
|
|
||||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font |
|
||||||
Software shall not be used to promote, endorse or advertise any |
|
||||||
Modified Version, except to acknowledge the contribution(s) of the |
|
||||||
Copyright Holder(s) and the Author(s) or with their explicit written |
|
||||||
permission. |
|
||||||
|
|
||||||
5) The Font Software, modified or unmodified, in part or in whole, |
|
||||||
must be distributed entirely under this license, and must not be |
|
||||||
distributed under any other license. The requirement for fonts to |
|
||||||
remain under this license does not apply to any document created |
|
||||||
using the Font Software. |
|
||||||
|
|
||||||
TERMINATION |
|
||||||
This license becomes null and void if any of the above conditions are |
|
||||||
not met. |
|
||||||
|
|
||||||
DISCLAIMER |
|
||||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF |
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT |
|
||||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE |
|
||||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL |
|
||||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
||||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM |
|
||||||
OTHER DEALINGS IN THE FONT SOFTWARE. |
|
@ -1,173 +0,0 @@ |
|||||||
The source code to this library used with SDL_ttf can be found here: |
|
||||||
https://hg.libsdl.org/SDL_ttf/file/default/external |
|
||||||
--- |
|
||||||
|
|
||||||
The FreeType Project LICENSE |
|
||||||
---------------------------- |
|
||||||
|
|
||||||
2006-Jan-27 |
|
||||||
|
|
||||||
Copyright 1996-2002, 2006 by |
|
||||||
David Turner, Robert Wilhelm, and Werner Lemberg |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Introduction |
|
||||||
============ |
|
||||||
|
|
||||||
The FreeType Project is distributed in several archive packages; |
|
||||||
some of them may contain, in addition to the FreeType font engine, |
|
||||||
various tools and contributions which rely on, or relate to, the |
|
||||||
FreeType Project. |
|
||||||
|
|
||||||
This license applies to all files found in such packages, and |
|
||||||
which do not fall under their own explicit license. The license |
|
||||||
affects thus the FreeType font engine, the test programs, |
|
||||||
documentation and makefiles, at the very least. |
|
||||||
|
|
||||||
This license was inspired by the BSD, Artistic, and IJG |
|
||||||
(Independent JPEG Group) licenses, which all encourage inclusion |
|
||||||
and use of free software in commercial and freeware products |
|
||||||
alike. As a consequence, its main points are that: |
|
||||||
|
|
||||||
o We don't promise that this software works. However, we will be |
|
||||||
interested in any kind of bug reports. (`as is' distribution) |
|
||||||
|
|
||||||
o You can use this software for whatever you want, in parts or |
|
||||||
full form, without having to pay us. (`royalty-free' usage) |
|
||||||
|
|
||||||
o You may not pretend that you wrote this software. If you use |
|
||||||
it, or only parts of it, in a program, you must acknowledge |
|
||||||
somewhere in your documentation that you have used the |
|
||||||
FreeType code. (`credits') |
|
||||||
|
|
||||||
We specifically permit and encourage the inclusion of this |
|
||||||
software, with or without modifications, in commercial products. |
|
||||||
We disclaim all warranties covering The FreeType Project and |
|
||||||
assume no liability related to The FreeType Project. |
|
||||||
|
|
||||||
|
|
||||||
Finally, many people asked us for a preferred form for a |
|
||||||
credit/disclaimer to use in compliance with this license. We thus |
|
||||||
encourage you to use the following text: |
|
||||||
|
|
||||||
""" |
|
||||||
Portions of this software are copyright © <year> The FreeType |
|
||||||
Project (www.freetype.org). All rights reserved. |
|
||||||
""" |
|
||||||
|
|
||||||
Please replace <year> with the value from the FreeType version you |
|
||||||
actually use. |
|
||||||
|
|
||||||
|
|
||||||
Legal Terms |
|
||||||
=========== |
|
||||||
|
|
||||||
0. Definitions |
|
||||||
-------------- |
|
||||||
|
|
||||||
Throughout this license, the terms `package', `FreeType Project', |
|
||||||
and `FreeType archive' refer to the set of files originally |
|
||||||
distributed by the authors (David Turner, Robert Wilhelm, and |
|
||||||
Werner Lemberg) as the `FreeType Project', be they named as alpha, |
|
||||||
beta or final release. |
|
||||||
|
|
||||||
`You' refers to the licensee, or person using the project, where |
|
||||||
`using' is a generic term including compiling the project's source |
|
||||||
code as well as linking it to form a `program' or `executable'. |
|
||||||
This program is referred to as `a program using the FreeType |
|
||||||
engine'. |
|
||||||
|
|
||||||
This license applies to all files distributed in the original |
|
||||||
FreeType Project, including all source code, binaries and |
|
||||||
documentation, unless otherwise stated in the file in its |
|
||||||
original, unmodified form as distributed in the original archive. |
|
||||||
If you are unsure whether or not a particular file is covered by |
|
||||||
this license, you must contact us to verify this. |
|
||||||
|
|
||||||
The FreeType Project is copyright (C) 1996-2000 by David Turner, |
|
||||||
Robert Wilhelm, and Werner Lemberg. All rights reserved except as |
|
||||||
specified below. |
|
||||||
|
|
||||||
1. No Warranty |
|
||||||
-------------- |
|
||||||
|
|
||||||
THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY |
|
||||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, |
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
||||||
PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS |
|
||||||
BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO |
|
||||||
USE, OF THE FREETYPE PROJECT. |
|
||||||
|
|
||||||
2. Redistribution |
|
||||||
----------------- |
|
||||||
|
|
||||||
This license grants a worldwide, royalty-free, perpetual and |
|
||||||
irrevocable right and license to use, execute, perform, compile, |
|
||||||
display, copy, create derivative works of, distribute and |
|
||||||
sublicense the FreeType Project (in both source and object code |
|
||||||
forms) and derivative works thereof for any purpose; and to |
|
||||||
authorize others to exercise some or all of the rights granted |
|
||||||
herein, subject to the following conditions: |
|
||||||
|
|
||||||
o Redistribution of source code must retain this license file |
|
||||||
(`FTL.TXT') unaltered; any additions, deletions or changes to |
|
||||||
the original files must be clearly indicated in accompanying |
|
||||||
documentation. The copyright notices of the unaltered, |
|
||||||
original files must be preserved in all copies of source |
|
||||||
files. |
|
||||||
|
|
||||||
o Redistribution in binary form must provide a disclaimer that |
|
||||||
states that the software is based in part of the work of the |
|
||||||
FreeType Team, in the distribution documentation. We also |
|
||||||
encourage you to put an URL to the FreeType web page in your |
|
||||||
documentation, though this isn't mandatory. |
|
||||||
|
|
||||||
These conditions apply to any software derived from or based on |
|
||||||
the FreeType Project, not just the unmodified files. If you use |
|
||||||
our work, you must acknowledge us. However, no fee need be paid |
|
||||||
to us. |
|
||||||
|
|
||||||
3. Advertising |
|
||||||
-------------- |
|
||||||
|
|
||||||
Neither the FreeType authors and contributors nor you shall use |
|
||||||
the name of the other for commercial, advertising, or promotional |
|
||||||
purposes without specific prior written permission. |
|
||||||
|
|
||||||
We suggest, but do not require, that you use one or more of the |
|
||||||
following phrases to refer to this software in your documentation |
|
||||||
or advertising materials: `FreeType Project', `FreeType Engine', |
|
||||||
`FreeType library', or `FreeType Distribution'. |
|
||||||
|
|
||||||
As you have not signed this license, you are not required to |
|
||||||
accept it. However, as the FreeType Project is copyrighted |
|
||||||
material, only this license, or another one contracted with the |
|
||||||
authors, grants you the right to use, distribute, and modify it. |
|
||||||
Therefore, by using, distributing, or modifying the FreeType |
|
||||||
Project, you indicate that you understand and accept all the terms |
|
||||||
of this license. |
|
||||||
|
|
||||||
4. Contacts |
|
||||||
----------- |
|
||||||
|
|
||||||
There are two mailing lists related to FreeType: |
|
||||||
|
|
||||||
o freetype@nongnu.org |
|
||||||
|
|
||||||
Discusses general use and applications of FreeType, as well as |
|
||||||
future and wanted additions to the library and distribution. |
|
||||||
If you are looking for support, start in this list if you |
|
||||||
haven't found anything to help you in the documentation. |
|
||||||
|
|
||||||
o freetype-devel@nongnu.org |
|
||||||
|
|
||||||
Discusses bugs, as well as engine internals, design issues, |
|
||||||
specific licenses, porting, etc. |
|
||||||
|
|
||||||
Our home page can be found at |
|
||||||
|
|
||||||
https://www.freetype.org |
|
||||||
|
|
||||||
|
|
||||||
--- end of FTL.TXT --- |
|
@ -1,31 +0,0 @@ |
|||||||
The source code to this library used with SDL_ttf can be found here: |
|
||||||
https://hg.libsdl.org/SDL_image/file/default/external |
|
||||||
--- |
|
||||||
|
|
||||||
Copyright notice: |
|
||||||
|
|
||||||
(C) 1995-2010 Jean-loup Gailly and Mark Adler |
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied |
|
||||||
warranty. In no event will the authors be held liable for any damages |
|
||||||
arising from the use of this software. |
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose, |
|
||||||
including commercial applications, and to alter it and redistribute it |
|
||||||
freely, subject to the following restrictions: |
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not |
|
||||||
claim that you wrote the original software. If you use this software |
|
||||||
in a product, an acknowledgment in the product documentation would be |
|
||||||
appreciated but is not required. |
|
||||||
2. Altered source versions must be plainly marked as such, and must not be |
|
||||||
misrepresented as being the original software. |
|
||||||
3. This notice may not be removed or altered from any source distribution. |
|
||||||
|
|
||||||
Jean-loup Gailly Mark Adler |
|
||||||
jloup@gzip.org madler@alumni.caltech.edu |
|
||||||
|
|
||||||
If you use the zlib library in a product, we would appreciate *not* receiving |
|
||||||
lengthy legal documents to sign. The sources are provided for free but without |
|
||||||
warranty of any kind. The library has been entirely written by Jean-loup |
|
||||||
Gailly and Mark Adler; it does not include third-party code. |
|
@ -1,13 +0,0 @@ |
|||||||
|
|
||||||
Please distribute this file with the SDL runtime environment: |
|
||||||
|
|
||||||
The Simple DirectMedia Layer (SDL for short) is a cross-platform library |
|
||||||
designed to make it easy to write multi-media software, such as games |
|
||||||
and emulators. |
|
||||||
|
|
||||||
The Simple DirectMedia Layer library source code is available from: |
|
||||||
https://www.libsdl.org/ |
|
||||||
|
|
||||||
This library is distributed under the terms of the zlib license: |
|
||||||
http://www.zlib.net/zlib_license.html |
|
||||||
|
|
@ -1,20 +0,0 @@ |
|||||||
This library is distributed under the terms of the zlib license: |
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied |
|
||||||
warranty. In no event will the authors be held liable for any damages |
|
||||||
arising from the use of this software. |
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose, |
|
||||||
including commercial applications, and to alter it and redistribute it |
|
||||||
freely, subject to the following restrictions: |
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not |
|
||||||
claim that you wrote the original software. If you use this software |
|
||||||
in a product, an acknowledgment in the product documentation would be |
|
||||||
appreciated but is not required. |
|
||||||
2. Altered source versions must be plainly marked as such, and must not be |
|
||||||
misrepresented as being the original software. |
|
||||||
3. This notice may not be removed or altered from any source distribution. |
|
||||||
|
|
||||||
The source is available from the SDL website: |
|
||||||
http://www.libsdl.org/projects/SDL_mixer |
|
@ -1,22 +0,0 @@ |
|||||||
This library is distributed under the terms of the zlib license: |
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied |
|
||||||
warranty. In no event will the authors be held liable for any damages |
|
||||||
arising from the use of this software. |
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose, |
|
||||||
including commercial applications, and to alter it and redistribute it |
|
||||||
freely, subject to the following restrictions: |
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not |
|
||||||
claim that you wrote the original software. If you use this software |
|
||||||
in a product, an acknowledgment in the product documentation would be |
|
||||||
appreciated but is not required. |
|
||||||
2. Altered source versions must be plainly marked as such, and must not be |
|
||||||
misrepresented as being the original software. |
|
||||||
3. This notice may not be removed or altered from any source distribution. |
|
||||||
|
|
||||||
Portions of this software are copyright © 2013 The FreeType Project (www.freetype.org). All rights reserved. |
|
||||||
|
|
||||||
The source is available from the SDL website: |
|
||||||
http://www.libsdl.org/projects/SDL_ttf |
|
@ -1,674 +0,0 @@ |
|||||||
GNU GENERAL PUBLIC LICENSE |
|
||||||
Version 3, 29 June 2007 |
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> |
|
||||||
Everyone is permitted to copy and distribute verbatim copies |
|
||||||
of this license document, but changing it is not allowed. |
|
||||||
|
|
||||||
Preamble |
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for |
|
||||||
software and other kinds of works. |
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed |
|
||||||
to take away your freedom to share and change the works. By contrast, |
|
||||||
the GNU General Public License is intended to guarantee your freedom to |
|
||||||
share and change all versions of a program--to make sure it remains free |
|
||||||
software for all its users. We, the Free Software Foundation, use the |
|
||||||
GNU General Public License for most of our software; it applies also to |
|
||||||
any other work released this way by its authors. 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 |
|
||||||
them 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 prevent others from denying you |
|
||||||
these rights or asking you to surrender the rights. Therefore, you have |
|
||||||
certain responsibilities if you distribute copies of the software, or if |
|
||||||
you modify it: responsibilities to respect the freedom of others. |
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether |
|
||||||
gratis or for a fee, you must pass on to the recipients the same |
|
||||||
freedoms that you received. 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. |
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps: |
|
||||||
(1) assert copyright on the software, and (2) offer you this License |
|
||||||
giving you legal permission to copy, distribute and/or modify it. |
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains |
|
||||||
that there is no warranty for this free software. For both users' and |
|
||||||
authors' sake, the GPL requires that modified versions be marked as |
|
||||||
changed, so that their problems will not be attributed erroneously to |
|
||||||
authors of previous versions. |
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run |
|
||||||
modified versions of the software inside them, although the manufacturer |
|
||||||
can do so. This is fundamentally incompatible with the aim of |
|
||||||
protecting users' freedom to change the software. The systematic |
|
||||||
pattern of such abuse occurs in the area of products for individuals to |
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we |
|
||||||
have designed this version of the GPL to prohibit the practice for those |
|
||||||
products. If such problems arise substantially in other domains, we |
|
||||||
stand ready to extend this provision to those domains in future versions |
|
||||||
of the GPL, as needed to protect the freedom of users. |
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents. |
|
||||||
States should not allow patents to restrict development and use of |
|
||||||
software on general-purpose computers, but in those that do, we wish to |
|
||||||
avoid the special danger that patents applied to a free program could |
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that |
|
||||||
patents cannot be used to render the program non-free. |
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and |
|
||||||
modification follow. |
|
||||||
|
|
||||||
TERMS AND CONDITIONS |
|
||||||
|
|
||||||
0. Definitions. |
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License. |
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of |
|
||||||
works, such as semiconductor masks. |
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this |
|
||||||
License. Each licensee is addressed as "you". "Licensees" and |
|
||||||
"recipients" may be individuals or organizations. |
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work |
|
||||||
in a fashion requiring copyright permission, other than the making of an |
|
||||||
exact copy. The resulting work is called a "modified version" of the |
|
||||||
earlier work or a work "based on" the earlier work. |
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based |
|
||||||
on the Program. |
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without |
|
||||||
permission, would make you directly or secondarily liable for |
|
||||||
infringement under applicable copyright law, except executing it on a |
|
||||||
computer or modifying a private copy. Propagation includes copying, |
|
||||||
distribution (with or without modification), making available to the |
|
||||||
public, and in some countries other activities as well. |
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other |
|
||||||
parties to make or receive copies. Mere interaction with a user through |
|
||||||
a computer network, with no transfer of a copy, is not conveying. |
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices" |
|
||||||
to the extent that it includes a convenient and prominently visible |
|
||||||
feature that (1) displays an appropriate copyright notice, and (2) |
|
||||||
tells the user that there is no warranty for the work (except to the |
|
||||||
extent that warranties are provided), that licensees may convey the |
|
||||||
work under this License, and how to view a copy of this License. If |
|
||||||
the interface presents a list of user commands or options, such as a |
|
||||||
menu, a prominent item in the list meets this criterion. |
|
||||||
|
|
||||||
1. Source Code. |
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work |
|
||||||
for making modifications to it. "Object code" means any non-source |
|
||||||
form of a work. |
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official |
|
||||||
standard defined by a recognized standards body, or, in the case of |
|
||||||
interfaces specified for a particular programming language, one that |
|
||||||
is widely used among developers working in that language. |
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other |
|
||||||
than the work as a whole, that (a) is included in the normal form of |
|
||||||
packaging a Major Component, but which is not part of that Major |
|
||||||
Component, and (b) serves only to enable use of the work with that |
|
||||||
Major Component, or to implement a Standard Interface for which an |
|
||||||
implementation is available to the public in source code form. A |
|
||||||
"Major Component", in this context, means a major essential component |
|
||||||
(kernel, window system, and so on) of the specific operating system |
|
||||||
(if any) on which the executable work runs, or a compiler used to |
|
||||||
produce the work, or an object code interpreter used to run it. |
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all |
|
||||||
the source code needed to generate, install, and (for an executable |
|
||||||
work) run the object code and to modify the work, including scripts to |
|
||||||
control those activities. However, it does not include the work's |
|
||||||
System Libraries, or general-purpose tools or generally available free |
|
||||||
programs which are used unmodified in performing those activities but |
|
||||||
which are not part of the work. For example, Corresponding Source |
|
||||||
includes interface definition files associated with source files for |
|
||||||
the work, and the source code for shared libraries and dynamically |
|
||||||
linked subprograms that the work is specifically designed to require, |
|
||||||
such as by intimate data communication or control flow between those |
|
||||||
subprograms and other parts of the work. |
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users |
|
||||||
can regenerate automatically from other parts of the Corresponding |
|
||||||
Source. |
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that |
|
||||||
same work. |
|
||||||
|
|
||||||
2. Basic Permissions. |
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of |
|
||||||
copyright on the Program, and are irrevocable provided the stated |
|
||||||
conditions are met. This License explicitly affirms your unlimited |
|
||||||
permission to run the unmodified Program. The output from running a |
|
||||||
covered work is covered by this License only if the output, given its |
|
||||||
content, constitutes a covered work. This License acknowledges your |
|
||||||
rights of fair use or other equivalent, as provided by copyright law. |
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not |
|
||||||
convey, without conditions so long as your license otherwise remains |
|
||||||
in force. You may convey covered works to others for the sole purpose |
|
||||||
of having them make modifications exclusively for you, or provide you |
|
||||||
with facilities for running those works, provided that you comply with |
|
||||||
the terms of this License in conveying all material for which you do |
|
||||||
not control copyright. Those thus making or running the covered works |
|
||||||
for you must do so exclusively on your behalf, under your direction |
|
||||||
and control, on terms that prohibit them from making any copies of |
|
||||||
your copyrighted material outside their relationship with you. |
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under |
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10 |
|
||||||
makes it unnecessary. |
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. |
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological |
|
||||||
measure under any applicable law fulfilling obligations under article |
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or |
|
||||||
similar laws prohibiting or restricting circumvention of such |
|
||||||
measures. |
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid |
|
||||||
circumvention of technological measures to the extent such circumvention |
|
||||||
is effected by exercising rights under this License with respect to |
|
||||||
the covered work, and you disclaim any intention to limit operation or |
|
||||||
modification of the work as a means of enforcing, against the work's |
|
||||||
users, your or third parties' legal rights to forbid circumvention of |
|
||||||
technological measures. |
|
||||||
|
|
||||||
4. Conveying Verbatim Copies. |
|
||||||
|
|
||||||
You may convey 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; |
|
||||||
keep intact all notices stating that this License and any |
|
||||||
non-permissive terms added in accord with section 7 apply to the code; |
|
||||||
keep intact all notices of the absence of any warranty; and give all |
|
||||||
recipients a copy of this License along with the Program. |
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey, |
|
||||||
and you may offer support or warranty protection for a fee. |
|
||||||
|
|
||||||
5. Conveying Modified Source Versions. |
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to |
|
||||||
produce it from the Program, in the form of source code under the |
|
||||||
terms of section 4, provided that you also meet all of these conditions: |
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified |
|
||||||
it, and giving a relevant date. |
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is |
|
||||||
released under this License and any conditions added under section |
|
||||||
7. This requirement modifies the requirement in section 4 to |
|
||||||
"keep intact all notices". |
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this |
|
||||||
License to anyone who comes into possession of a copy. This |
|
||||||
License will therefore apply, along with any applicable section 7 |
|
||||||
additional terms, to the whole of the work, and all its parts, |
|
||||||
regardless of how they are packaged. This License gives no |
|
||||||
permission to license the work in any other way, but it does not |
|
||||||
invalidate such permission if you have separately received it. |
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display |
|
||||||
Appropriate Legal Notices; however, if the Program has interactive |
|
||||||
interfaces that do not display Appropriate Legal Notices, your |
|
||||||
work need not make them do so. |
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent |
|
||||||
works, which are not by their nature extensions of the covered work, |
|
||||||
and which are not combined with it such as to form a larger program, |
|
||||||
in or on a volume of a storage or distribution medium, is called an |
|
||||||
"aggregate" if the compilation and its resulting copyright are not |
|
||||||
used to limit the access or legal rights of the compilation's users |
|
||||||
beyond what the individual works permit. Inclusion of a covered work |
|
||||||
in an aggregate does not cause this License to apply to the other |
|
||||||
parts of the aggregate. |
|
||||||
|
|
||||||
6. Conveying Non-Source Forms. |
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms |
|
||||||
of sections 4 and 5, provided that you also convey the |
|
||||||
machine-readable Corresponding Source under the terms of this License, |
|
||||||
in one of these ways: |
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product |
|
||||||
(including a physical distribution medium), accompanied by the |
|
||||||
Corresponding Source fixed on a durable physical medium |
|
||||||
customarily used for software interchange. |
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product |
|
||||||
(including a physical distribution medium), accompanied by a |
|
||||||
written offer, valid for at least three years and valid for as |
|
||||||
long as you offer spare parts or customer support for that product |
|
||||||
model, to give anyone who possesses the object code either (1) a |
|
||||||
copy of the Corresponding Source for all the software in the |
|
||||||
product that is covered by this License, on a durable physical |
|
||||||
medium customarily used for software interchange, for a price no |
|
||||||
more than your reasonable cost of physically performing this |
|
||||||
conveying of source, or (2) access to copy the |
|
||||||
Corresponding Source from a network server at no charge. |
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the |
|
||||||
written offer to provide the Corresponding Source. This |
|
||||||
alternative is allowed only occasionally and noncommercially, and |
|
||||||
only if you received the object code with such an offer, in accord |
|
||||||
with subsection 6b. |
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated |
|
||||||
place (gratis or for a charge), and offer equivalent access to the |
|
||||||
Corresponding Source in the same way through the same place at no |
|
||||||
further charge. You need not require recipients to copy the |
|
||||||
Corresponding Source along with the object code. If the place to |
|
||||||
copy the object code is a network server, the Corresponding Source |
|
||||||
may be on a different server (operated by you or a third party) |
|
||||||
that supports equivalent copying facilities, provided you maintain |
|
||||||
clear directions next to the object code saying where to find the |
|
||||||
Corresponding Source. Regardless of what server hosts the |
|
||||||
Corresponding Source, you remain obligated to ensure that it is |
|
||||||
available for as long as needed to satisfy these requirements. |
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided |
|
||||||
you inform other peers where the object code and Corresponding |
|
||||||
Source of the work are being offered to the general public at no |
|
||||||
charge under subsection 6d. |
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded |
|
||||||
from the Corresponding Source as a System Library, need not be |
|
||||||
included in conveying the object code work. |
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any |
|
||||||
tangible personal property which is normally used for personal, family, |
|
||||||
or household purposes, or (2) anything designed or sold for incorporation |
|
||||||
into a dwelling. In determining whether a product is a consumer product, |
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular |
|
||||||
product received by a particular user, "normally used" refers to a |
|
||||||
typical or common use of that class of product, regardless of the status |
|
||||||
of the particular user or of the way in which the particular user |
|
||||||
actually uses, or expects or is expected to use, the product. A product |
|
||||||
is a consumer product regardless of whether the product has substantial |
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent |
|
||||||
the only significant mode of use of the product. |
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods, |
|
||||||
procedures, authorization keys, or other information required to install |
|
||||||
and execute modified versions of a covered work in that User Product from |
|
||||||
a modified version of its Corresponding Source. The information must |
|
||||||
suffice to ensure that the continued functioning of the modified object |
|
||||||
code is in no case prevented or interfered with solely because |
|
||||||
modification has been made. |
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or |
|
||||||
specifically for use in, a User Product, and the conveying occurs as |
|
||||||
part of a transaction in which the right of possession and use of the |
|
||||||
User Product is transferred to the recipient in perpetuity or for a |
|
||||||
fixed term (regardless of how the transaction is characterized), the |
|
||||||
Corresponding Source conveyed under this section must be accompanied |
|
||||||
by the Installation Information. But this requirement does not apply |
|
||||||
if neither you nor any third party retains the ability to install |
|
||||||
modified object code on the User Product (for example, the work has |
|
||||||
been installed in ROM). |
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a |
|
||||||
requirement to continue to provide support service, warranty, or updates |
|
||||||
for a work that has been modified or installed by the recipient, or for |
|
||||||
the User Product in which it has been modified or installed. Access to a |
|
||||||
network may be denied when the modification itself materially and |
|
||||||
adversely affects the operation of the network or violates the rules and |
|
||||||
protocols for communication across the network. |
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided, |
|
||||||
in accord with this section must be in a format that is publicly |
|
||||||
documented (and with an implementation available to the public in |
|
||||||
source code form), and must require no special password or key for |
|
||||||
unpacking, reading or copying. |
|
||||||
|
|
||||||
7. Additional Terms. |
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this |
|
||||||
License by making exceptions from one or more of its conditions. |
|
||||||
Additional permissions that are applicable to the entire Program shall |
|
||||||
be treated as though they were included in this License, to the extent |
|
||||||
that they are valid under applicable law. If additional permissions |
|
||||||
apply only to part of the Program, that part may be used separately |
|
||||||
under those permissions, but the entire Program remains governed by |
|
||||||
this License without regard to the additional permissions. |
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option |
|
||||||
remove any additional permissions from that copy, or from any part of |
|
||||||
it. (Additional permissions may be written to require their own |
|
||||||
removal in certain cases when you modify the work.) You may place |
|
||||||
additional permissions on material, added by you to a covered work, |
|
||||||
for which you have or can give appropriate copyright permission. |
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you |
|
||||||
add to a covered work, you may (if authorized by the copyright holders of |
|
||||||
that material) supplement the terms of this License with terms: |
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the |
|
||||||
terms of sections 15 and 16 of this License; or |
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or |
|
||||||
author attributions in that material or in the Appropriate Legal |
|
||||||
Notices displayed by works containing it; or |
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or |
|
||||||
requiring that modified versions of such material be marked in |
|
||||||
reasonable ways as different from the original version; or |
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or |
|
||||||
authors of the material; or |
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some |
|
||||||
trade names, trademarks, or service marks; or |
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that |
|
||||||
material by anyone who conveys the material (or modified versions of |
|
||||||
it) with contractual assumptions of liability to the recipient, for |
|
||||||
any liability that these contractual assumptions directly impose on |
|
||||||
those licensors and authors. |
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further |
|
||||||
restrictions" within the meaning of section 10. If the Program as you |
|
||||||
received it, or any part of it, contains a notice stating that it is |
|
||||||
governed by this License along with a term that is a further |
|
||||||
restriction, you may remove that term. If a license document contains |
|
||||||
a further restriction but permits relicensing or conveying under this |
|
||||||
License, you may add to a covered work material governed by the terms |
|
||||||
of that license document, provided that the further restriction does |
|
||||||
not survive such relicensing or conveying. |
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you |
|
||||||
must place, in the relevant source files, a statement of the |
|
||||||
additional terms that apply to those files, or a notice indicating |
|
||||||
where to find the applicable terms. |
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the |
|
||||||
form of a separately written license, or stated as exceptions; |
|
||||||
the above requirements apply either way. |
|
||||||
|
|
||||||
8. Termination. |
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly |
|
||||||
provided under this License. Any attempt otherwise to propagate or |
|
||||||
modify it is void, and will automatically terminate your rights under |
|
||||||
this License (including any patent licenses granted under the third |
|
||||||
paragraph of section 11). |
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your |
|
||||||
license from a particular copyright holder is reinstated (a) |
|
||||||
provisionally, unless and until the copyright holder explicitly and |
|
||||||
finally terminates your license, and (b) permanently, if the copyright |
|
||||||
holder fails to notify you of the violation by some reasonable means |
|
||||||
prior to 60 days after the cessation. |
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is |
|
||||||
reinstated permanently if the copyright holder notifies you of the |
|
||||||
violation by some reasonable means, this is the first time you have |
|
||||||
received notice of violation of this License (for any work) from that |
|
||||||
copyright holder, and you cure the violation prior to 30 days after |
|
||||||
your receipt of the notice. |
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the |
|
||||||
licenses of parties who have received copies or rights from you under |
|
||||||
this License. If your rights have been terminated and not permanently |
|
||||||
reinstated, you do not qualify to receive new licenses for the same |
|
||||||
material under section 10. |
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies. |
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or |
|
||||||
run a copy of the Program. Ancillary propagation of a covered work |
|
||||||
occurring solely as a consequence of using peer-to-peer transmission |
|
||||||
to receive a copy likewise does not require acceptance. However, |
|
||||||
nothing other than this License grants you permission to propagate or |
|
||||||
modify any covered work. These actions infringe copyright if you do |
|
||||||
not accept this License. Therefore, by modifying or propagating a |
|
||||||
covered work, you indicate your acceptance of this License to do so. |
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients. |
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically |
|
||||||
receives a license from the original licensors, to run, modify and |
|
||||||
propagate that work, subject to this License. You are not responsible |
|
||||||
for enforcing compliance by third parties with this License. |
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an |
|
||||||
organization, or substantially all assets of one, or subdividing an |
|
||||||
organization, or merging organizations. If propagation of a covered |
|
||||||
work results from an entity transaction, each party to that |
|
||||||
transaction who receives a copy of the work also receives whatever |
|
||||||
licenses to the work the party's predecessor in interest had or could |
|
||||||
give under the previous paragraph, plus a right to possession of the |
|
||||||
Corresponding Source of the work from the predecessor in interest, if |
|
||||||
the predecessor has it or can get it with reasonable efforts. |
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the |
|
||||||
rights granted or affirmed under this License. For example, you may |
|
||||||
not impose a license fee, royalty, or other charge for exercise of |
|
||||||
rights granted under this License, and you may not initiate litigation |
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that |
|
||||||
any patent claim is infringed by making, using, selling, offering for |
|
||||||
sale, or importing the Program or any portion of it. |
|
||||||
|
|
||||||
11. Patents. |
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this |
|
||||||
License of the Program or a work on which the Program is based. The |
|
||||||
work thus licensed is called the contributor's "contributor version". |
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims |
|
||||||
owned or controlled by the contributor, whether already acquired or |
|
||||||
hereafter acquired, that would be infringed by some manner, permitted |
|
||||||
by this License, of making, using, or selling its contributor version, |
|
||||||
but do not include claims that would be infringed only as a |
|
||||||
consequence of further modification of the contributor version. For |
|
||||||
purposes of this definition, "control" includes the right to grant |
|
||||||
patent sublicenses in a manner consistent with the requirements of |
|
||||||
this License. |
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free |
|
||||||
patent license under the contributor's essential patent claims, to |
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and |
|
||||||
propagate the contents of its contributor version. |
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express |
|
||||||
agreement or commitment, however denominated, not to enforce a patent |
|
||||||
(such as an express permission to practice a patent or covenant not to |
|
||||||
sue for patent infringement). To "grant" such a patent license to a |
|
||||||
party means to make such an agreement or commitment not to enforce a |
|
||||||
patent against the party. |
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license, |
|
||||||
and the Corresponding Source of the work is not available for anyone |
|
||||||
to copy, free of charge and under the terms of this License, through a |
|
||||||
publicly available network server or other readily accessible means, |
|
||||||
then you must either (1) cause the Corresponding Source to be so |
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the |
|
||||||
patent license for this particular work, or (3) arrange, in a manner |
|
||||||
consistent with the requirements of this License, to extend the patent |
|
||||||
license to downstream recipients. "Knowingly relying" means you have |
|
||||||
actual knowledge that, but for the patent license, your conveying the |
|
||||||
covered work in a country, or your recipient's use of the covered work |
|
||||||
in a country, would infringe one or more identifiable patents in that |
|
||||||
country that you have reason to believe are valid. |
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or |
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a |
|
||||||
covered work, and grant a patent license to some of the parties |
|
||||||
receiving the covered work authorizing them to use, propagate, modify |
|
||||||
or convey a specific copy of the covered work, then the patent license |
|
||||||
you grant is automatically extended to all recipients of the covered |
|
||||||
work and works based on it. |
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within |
|
||||||
the scope of its coverage, prohibits the exercise of, or is |
|
||||||
conditioned on the non-exercise of one or more of the rights that are |
|
||||||
specifically granted under this License. You may not convey a covered |
|
||||||
work if you are a party to an arrangement with a third party that is |
|
||||||
in the business of distributing software, under which you make payment |
|
||||||
to the third party based on the extent of your activity of conveying |
|
||||||
the work, and under which the third party grants, to any of the |
|
||||||
parties who would receive the covered work from you, a discriminatory |
|
||||||
patent license (a) in connection with copies of the covered work |
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily |
|
||||||
for and in connection with specific products or compilations that |
|
||||||
contain the covered work, unless you entered into that arrangement, |
|
||||||
or that patent license was granted, prior to 28 March 2007. |
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting |
|
||||||
any implied license or other defenses to infringement that may |
|
||||||
otherwise be available to you under applicable patent law. |
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom. |
|
||||||
|
|
||||||
If 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 convey a |
|
||||||
covered work so as to satisfy simultaneously your obligations under this |
|
||||||
License and any other pertinent obligations, then as a consequence you may |
|
||||||
not convey it at all. For example, if you agree to terms that obligate you |
|
||||||
to collect a royalty for further conveying from those to whom you convey |
|
||||||
the Program, the only way you could satisfy both those terms and this |
|
||||||
License would be to refrain entirely from conveying the Program. |
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License. |
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have |
|
||||||
permission to link or combine any covered work with a work licensed |
|
||||||
under version 3 of the GNU Affero General Public License into a single |
|
||||||
combined work, and to convey the resulting work. The terms of this |
|
||||||
License will continue to apply to the part which is the covered work, |
|
||||||
but the special requirements of the GNU Affero General Public License, |
|
||||||
section 13, concerning interaction through a network will apply to the |
|
||||||
combination as such. |
|
||||||
|
|
||||||
14. Revised Versions of this License. |
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of |
|
||||||
the GNU 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 that a certain numbered version of the GNU General |
|
||||||
Public License "or any later version" applies to it, you have the |
|
||||||
option of following the terms and conditions either of that numbered |
|
||||||
version or of any later version published by the Free Software |
|
||||||
Foundation. If the Program does not specify a version number of the |
|
||||||
GNU General Public License, you may choose any version ever published |
|
||||||
by the Free Software Foundation. |
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future |
|
||||||
versions of the GNU General Public License can be used, that proxy's |
|
||||||
public statement of acceptance of a version permanently authorizes you |
|
||||||
to choose that version for the Program. |
|
||||||
|
|
||||||
Later license versions may give you additional or different |
|
||||||
permissions. However, no additional obligations are imposed on any |
|
||||||
author or copyright holder as a result of your choosing to follow a |
|
||||||
later version. |
|
||||||
|
|
||||||
15. Disclaimer of Warranty. |
|
||||||
|
|
||||||
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. |
|
||||||
|
|
||||||
16. Limitation of Liability. |
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS |
|
||||||
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. |
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16. |
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided |
|
||||||
above cannot be given local legal effect according to their terms, |
|
||||||
reviewing courts shall apply local law that most closely approximates |
|
||||||
an absolute waiver of all civil liability in connection with the |
|
||||||
Program, unless a warranty or assumption of liability accompanies a |
|
||||||
copy of the Program in return for a fee. |
|
||||||
|
|
||||||
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 |
|
||||||
state the exclusion of warranty; and each file should have at least |
|
||||||
the "copyright" line and a pointer to where the full notice is found. |
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.> |
|
||||||
Copyright (C) <year> <name of author> |
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 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, see <https://www.gnu.org/licenses/>. |
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail. |
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short |
|
||||||
notice like this when it starts in an interactive mode: |
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author> |
|
||||||
This program 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, your program's commands |
|
||||||
might be different; for a GUI interface, you would use an "about box". |
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school, |
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary. |
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see |
|
||||||
<https://www.gnu.org/licenses/>. |
|
||||||
|
|
||||||
The GNU 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. But first, please read |
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>. |
|
@ -1,99 +1,85 @@ |
|||||||
|
|
||||||
EXE = main
|
EXE = main
|
||||||
|
|
||||||
|
.PHONY: windows |
||||||
|
.PHONY: linux |
||||||
|
|
||||||
sdl2ibdir = sdllib
|
sdl2ibdir = sdllib
|
||||||
|
|
||||||
ifndef target
|
target=linux
|
||||||
target=linux
|
|
||||||
endif |
|
||||||
|
|
||||||
ifeq ($(target),windows) |
ifeq ($(target),windows) |
||||||
CC=x86_64-w64-mingw32-gcc -DWIN32 -g
|
CC=x86_64-w64-mingw32-gcc
|
||||||
SDL_INCLUDE = -Dmain=SDL_main -Lsdllib -lSDL2main -lSDL2main -lSDL2_mixer -lSDL2_ttf -lSDL2 -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,-static -lpthread -lm
|
SDL_INCLUDE = -Dmain=SDL_main -Lsdllib -lSDL2main -lSDL2main -lSDL2 -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,-static -lpthread -lm
|
||||||
CCFLAGS=$(SDL_INCLUDE) -O2
|
CCFLAGS=$(SDL_INCLUDE) -O3
|
||||||
else |
|
||||||
ifeq ($(target),web) |
|
||||||
CC=emcc
|
|
||||||
SDL_INCLUDE= -s USE_SDL=2 -s USE_SDL_MIXER=2 -s USE_SDL_TTF=2 -s FULL_ES3=1 --preload-file "TerminusTTF.ttf"
|
|
||||||
CCFLAGS=$(SDL_INCLUDE) -O2
|
|
||||||
else |
else |
||||||
CC=gcc -D__linux__
|
CC=gcc
|
||||||
SDL_INCLUDE= -lSDL2 -lSDL2_ttf -lSDL2_mixer -lm
|
SDL_INCLUDE= -lSDL2 -lm
|
||||||
CCFLAGS=$(SDL_INCLUDE) -O3
|
CCFLAGS=$(SDL_INCLUDE) -O3
|
||||||
endif |
endif |
||||||
endif |
|
||||||
|
|
||||||
ifdef debug |
ifdef debug |
||||||
CC += -fsanitize=address -g -ggdb -fno-omit-frame-pointer -Wall
|
CC = $(CC) -g -Wall
|
||||||
endif |
endif |
||||||
|
|
||||||
.PHONY: default |
.PHONY: default |
||||||
.PHONY: all |
.PHONY: all |
||||||
.PHONY: run |
.PHONY: run |
||||||
.PHONY: dist |
.PHONY: dist |
||||||
.PHONY: web |
|
||||||
|
|
||||||
default: all |
default: all |
||||||
|
|
||||||
dist: all |
dist: all |
||||||
mkdir -p dist
|
mkdir -p dist
|
||||||
mkdir -p dist/windows
|
mkdir -p dist/windows
|
||||||
cp build/main.exe dist/windows
|
|
||||||
cp build/SDL2.dll dist/windows
|
|
||||||
cp README.md dist/windows
|
|
||||||
cd dist && zip -r windows.zip windows
|
|
||||||
|
|
||||||
distlin: all |
|
||||||
mkdir -p dist
|
|
||||||
mkdir -p dist/linux
|
mkdir -p dist/linux
|
||||||
cp build/main dist/linux
|
cp main dist/linux
|
||||||
cp README.md dist/linux
|
cp main.exe dist/windows
|
||||||
cd dist && zip -r linux.zip linux
|
cp SDL2.dll dist/windows
|
||||||
|
cd dist && zip -r windows.zip windows
|
||||||
|
cd dist && tar -czvf linux.tar.gz linux
|
||||||
|
|
||||||
run: all |
run: all |
||||||
./main
|
./main
|
||||||
|
|
||||||
all: $(EXE) |
all: $(EXE) |
||||||
|
|
||||||
web: $(EXE) |
$(EXE): main.o vect.o logger.o game.o garbo.o draw.o controlscheme.o environment.o c-colours/colours.o datastructures/datatypes.o |
||||||
$(CC) -o build/index.html build/main.o build/vect.o build/game.o build/draw.o build/environment.o build/controlscheme.o build/colours.o build/datatypes.o build/audio.o $(CCFLAGS)
|
$(CC) -o $(EXE) main.o vect.o game.o logger.o draw.o garbo.o environment.o controlscheme.o c-colours/colours.o datastructures/datatypes.o $(CCFLAGS)
|
||||||
|
|
||||||
|
|
||||||
$(EXE): prebuild build/main.o build/vect.o build/game.o build/draw.o build/controlscheme.o build/environment.o build/colours.o build/datatypes.o build/audio.o |
c-colours/colours.o: c-colours/colours.c c-colours/colours.h |
||||||
cd build && $(CC) -o $(EXE) main.o vect.o game.o draw.o environment.o controlscheme.o colours.o datatypes.o audio.o $(CCFLAGS)
|
$(CC) -c c-colours/colours.c -o c-colours/colours.o $(CCFLAGS)
|
||||||
|
|
||||||
build/colours.o: c-colours/colours.c c-colours/colours.h |
datastructures/datatypes.o: datastructures/datatypes.c datastructures/datatypes.h |
||||||
$(CC) -c c-colours/colours.c -o build/colours.o $(CCFLAGS)
|
$(CC) -c datastructures/datatypes.c -o datastructures/datatypes.o $(CCFLAGS)
|
||||||
|
|
||||||
build/datatypes.o: datastructures/datatypes.c datastructures/datatypes.h |
main.o: main.c logger.h game.h garbo.h draw.h |
||||||
$(CC) -c datastructures/datatypes.c -o build/datatypes.o $(CCFLAGS)
|
$(CC) -c main.c $(CCFLAGS)
|
||||||
|
|
||||||
build/main.o: src/main.c |
logger.o: logger.c logger.h |
||||||
$(CC) -c src/main.c -o build/main.o $(CCFLAGS)
|
$(CC) -c logger.c $(CCFLAGS)
|
||||||
|
|
||||||
build/game.o: src/game.c src/game.h |
game.o: game.c game.h draw.h |
||||||
$(CC) -c src/game.c -o build/game.o $(CCFLAGS)
|
$(CC) -c game.c $(CCFLAGS)
|
||||||
|
|
||||||
build/draw.o: src/draw.c src/draw.h |
garbo.o: garbo.c garbo.h |
||||||
$(CC) -c src/draw.c -o build/draw.o $(CCFLAGS)
|
$(CC) -c garbo.c $(CCFLAGS)
|
||||||
|
|
||||||
build/vect.o: src/vect.c src/vect.h |
draw.o: draw.c draw.h |
||||||
$(CC) -c src/vect.c -o build/vect.o $(CCFLAGS)
|
$(CC) -c draw.c $(CCFLAGS)
|
||||||
|
|
||||||
build/controlscheme.o: src/controlscheme.c src/controlscheme.h |
vect.o: vect.c vect.h |
||||||
$(CC) -c src/controlscheme.c -o build/controlscheme.o $(CCFLAGS)
|
$(CC) -c vect.c $(CCFLAGS)
|
||||||
|
|
||||||
build/environment.o: src/environment.c src/environment.h |
controlscheme.o: controlscheme.c controlscheme.h |
||||||
$(CC) -c src/environment.c -o build/environment.o $(CCFLAGS)
|
$(CC) -c controlscheme.c $(CCFLAGS)
|
||||||
|
|
||||||
build/audio.o: src/audio.c src/audio.h |
environment.o: environment.c environment.h |
||||||
$(CC) -c src/audio.c -o build/audio.o $(CCFLAGS)
|
$(CC) -c environment.c $(CCFLAGS)
|
||||||
|
|
||||||
clean: |
clean: |
||||||
rm build/*.o
|
rm c-colours/*.o
|
||||||
|
rm datastructures/*.o
|
||||||
prebuild: |
rm *.o
|
||||||
mkdir -p build
|
rm -rf dist
|
||||||
ln -srf datastructures src/
|
|
||||||
ln -srf c-colours src/
|
|
||||||
|
|
||||||
|
Binary file not shown.
@ -1,25 +0,0 @@ |
|||||||
cmake_minimum_required(VERSION 3.4.1) |
|
||||||
|
|
||||||
string(TOLOWER ${CMAKE_BUILD_TYPE} ANDROID_BUILD_DIR) |
|
||||||
set(DISTRIBUTION_DIR ${CMAKE_SOURCE_DIR}/android/distribution/android/SDL2/intermediates/ndkBuild) |
|
||||||
set(SOURCE_FILES src/audio.c src/colours.c src/datatypes.c src/environment.c src/main.c src/vect.c src/basic-lib.c src/controlscheme.c src/draw.c src/game.c src/physics.c) |
|
||||||
set(SDL_LOCATION ${CMAKE_SOURCE_DIR}/external/SDL2) |
|
||||||
|
|
||||||
add_library( SDL2 SHARED IMPORTED ) |
|
||||||
add_library( SDL2_mixer SHARED IMPORTED ) |
|
||||||
add_library( SDL2_ttf SHARED IMPORTED ) |
|
||||||
set_target_properties(SDL2 PROPERTIES IMPORTED_LOCATION |
|
||||||
${DISTRIBUTION_DIR}/${ANDROID_BUILD_DIR}/obj/local/${ANDROID_ABI}/libSDL2.so) |
|
||||||
set_target_properties(SDL2_mixer PROPERTIES IMPORTED_LOCATION |
|
||||||
${DISTRIBUTION_DIR}/${ANDROID_BUILD_DIR}/obj/local/${ANDROID_ABI}/libSDL2_mixer.so) |
|
||||||
set_target_properties(SDL2_ttf PROPERTIES IMPORTED_LOCATION |
|
||||||
${DISTRIBUTION_DIR}/${ANDROID_BUILD_DIR}/obj/local/${ANDROID_ABI}/libSDL2_ttf.so) |
|
||||||
|
|
||||||
include_directories(${SDL_LOCATION}/SDL2/SDL2/incl2) |
|
||||||
include_directories(${SDL_LOCATION}/SDL2/include) |
|
||||||
include_directories(${SDL_LOCATION}/SDL2_mixer) |
|
||||||
include_directories(${SDL_LOCATION}/SDL2_ttf) |
|
||||||
|
|
||||||
add_library( main SHARED ${SDL_LOCATION}/SDL2/src/main/android/SDL_android_main.c ${SOURCE_FILES} ) |
|
||||||
|
|
||||||
target_link_libraries( main SDL2 SDL2_mixer SDL2_ttf) |
|
@ -1,20 +0,0 @@ |
|||||||
|
|
||||||
hello-sdl2-android |
|
||||||
Copyright (C) 2017 Paul Vallet <luap.vallet@gmail.com> |
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied |
|
||||||
warranty. In no event will the authors be held liable for any damages |
|
||||||
arising from the use of this software. |
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose, |
|
||||||
including commercial applications, and to alter it and redistribute it |
|
||||||
freely, subject to the following restrictions: |
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not |
|
||||||
claim that you wrote the original software. If you use this software |
|
||||||
in a product, an acknowledgment in the product documentation would be |
|
||||||
appreciated but is not required. |
|
||||||
2. Altered source versions must be plainly marked as such, and must not be |
|
||||||
misrepresented as being the original software. |
|
||||||
3. This notice may not be removed or altered from any source distribution. |
|
||||||
|
|
@ -1,56 +0,0 @@ |
|||||||
# hello-sdl2-android |
|
||||||
|
|
||||||
## Synopsis |
|
||||||
|
|
||||||
This project is an update of the hello world project here https://github.com/stephen47/android-sdl2-gradle-template, as I couldn't find a good way to integrate a CMake built C++ project to an android application. |
|
||||||
It features a sample hello world using SDL and SDL_image. |
|
||||||
|
|
||||||
## Requirements |
|
||||||
- JDK and JRE 8 |
|
||||||
- Android SDK and NDK (with Android Build-tools 28.0.3 and Android Platform API 28, though these are configurable) |
|
||||||
- ANDROID_HOME and ANDROID_NDK_HOME environment variables set (I did this in /etc/environment) |
|
||||||
|
|
||||||
## Compiling the sample program (command line) |
|
||||||
|
|
||||||
You can download the dependencies (SDL2 and SDL2_image), compile your program and then install it on a connected device with the following commands: |
|
||||||
``` |
|
||||||
./get_dependencies |
|
||||||
cd android |
|
||||||
./gradlew assembleDebug |
|
||||||
./gradlew installDebug |
|
||||||
``` |
|
||||||
|
|
||||||
## Compiling the sample program (Android Studio 3.2.1) |
|
||||||
|
|
||||||
First download the dependencies (SDL2 and SDL2_image) as above or manually like below. Then open the ./android folder as an existing project in Android Studio. |
|
||||||
|
|
||||||
## Downloading dependencies manually |
|
||||||
|
|
||||||
Download the latest source release from SDL and SDL_image websites: |
|
||||||
|
|
||||||
https://www.libsdl.org/download-2.0.php |
|
||||||
https://www.libsdl.org/projects/SDL_image/ |
|
||||||
|
|
||||||
Unzip it, put the SDL2-x.x.x and SDL2_image-x.x.x folders in `external/SDL2` and rename them to SDL2 and SDL2_image so your project folder looks like this: |
|
||||||
``` |
|
||||||
+ android |
|
||||||
+ external |
|
||||||
| + SDL2 |
|
||||||
| | + Android.mk |
|
||||||
| | | SDL2 |
|
||||||
| | | SDL2_image |
|
||||||
``` |
|
||||||
|
|
||||||
There, it's done! |
|
||||||
|
|
||||||
## Thanks |
|
||||||
|
|
||||||
Most of the code here is inspired by these repositories: |
|
||||||
|
|
||||||
https://github.com/stephen47/android-sdl2-gradle-template (Android + gradle) |
|
||||||
|
|
||||||
https://github.com/suikki/simpleSDL/ (Android + CMake) |
|
||||||
|
|
||||||
The example libSDL2 program which draws the square on screen was found at https://stackoverflow.com/questions/21890627/drawing-a-rectangle-with-sdl2/21903973#21903973. |
|
||||||
|
|
||||||
The Google NDK example projects were very helpful: https://github.com/googlesamples/android-ndk |
|
@ -1,3 +0,0 @@ |
|||||||
distribution/ |
|
||||||
.gradle/ |
|
||||||
.idea/ |
|
@ -1 +0,0 @@ |
|||||||
.externalNativeBuild/ |
|
@ -1,50 +0,0 @@ |
|||||||
apply plugin: 'com.android.library' |
|
||||||
|
|
||||||
android { |
|
||||||
signingConfigs { |
|
||||||
debug { |
|
||||||
storeFile file('/home/alistair/Documents/androiddevkeystore.jks') |
|
||||||
storePassword 'T2964d7^5Nksof!Z' |
|
||||||
keyPassword 'T2964d7^5Nksof!Z' |
|
||||||
keyAlias 'key0' |
|
||||||
} |
|
||||||
} |
|
||||||
compileSdkVersion 28 |
|
||||||
buildToolsVersion "28.0.3" |
|
||||||
|
|
||||||
defaultConfig { |
|
||||||
minSdkVersion 21 |
|
||||||
targetSdkVersion 28 |
|
||||||
versionCode 1 |
|
||||||
versionName "1.0" |
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" |
|
||||||
ndk { |
|
||||||
abiFilters "armeabi-v7a" |
|
||||||
} |
|
||||||
} |
|
||||||
buildTypes { |
|
||||||
release { |
|
||||||
minifyEnabled false |
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' |
|
||||||
signingConfig signingConfigs.debug |
|
||||||
} |
|
||||||
debug { |
|
||||||
signingConfig signingConfigs.debug |
|
||||||
} |
|
||||||
} |
|
||||||
externalNativeBuild { |
|
||||||
ndkBuild { |
|
||||||
path '../../external/SDL2/Android.mk' |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar']) |
|
||||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { |
|
||||||
exclude group: 'com.android.support', module: 'support-annotations' |
|
||||||
}) |
|
||||||
compile 'com.android.support:appcompat-v7:28.0.0' |
|
||||||
testCompile 'junit:junit:4.12' |
|
||||||
} |
|
@ -1,25 +0,0 @@ |
|||||||
# Add project specific ProGuard rules here. |
|
||||||
# By default, the flags in this file are appended to flags specified |
|
||||||
# in /home/luap/Logiciels/android-sdk/tools/proguard/proguard-android.txt |
|
||||||
# You can edit the include path and order by changing the proguardFiles |
|
||||||
# directive in build.gradle. |
|
||||||
# |
|
||||||
# For more details, see |
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html |
|
||||||
|
|
||||||
# Add any project specific keep options here: |
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following |
|
||||||
# and specify the fully qualified class name to the JavaScript interface |
|
||||||
# class: |
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { |
|
||||||
# public *; |
|
||||||
#} |
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for |
|
||||||
# debugging stack traces. |
|
||||||
#-keepattributes SourceFile,LineNumberTable |
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to |
|
||||||
# hide the original source file name. |
|
||||||
#-renamesourcefileattribute SourceFile |
|
@ -1 +0,0 @@ |
|||||||
.externalNativeBuild/ |
|
@ -1,57 +0,0 @@ |
|||||||
apply plugin: 'com.android.application' |
|
||||||
|
|
||||||
android { |
|
||||||
signingConfigs { |
|
||||||
debug { |
|
||||||
storeFile file('/home/alistair/Documents/androiddevkeystore.jks') |
|
||||||
storePassword 'T2964d7^5Nksof!Z' |
|
||||||
keyPassword 'T2964d7^5Nksof!Z' |
|
||||||
keyAlias 'key0' |
|
||||||
} |
|
||||||
} |
|
||||||
compileSdkVersion 28 |
|
||||||
buildToolsVersion "28.0.3" |
|
||||||
defaultConfig { |
|
||||||
applicationId "alistair.net.topost.git.ayugiarwagh" |
|
||||||
minSdkVersion 21 |
|
||||||
targetSdkVersion 28 |
|
||||||
versionCode 1 |
|
||||||
versionName "1.0" |
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" |
|
||||||
externalNativeBuild { |
|
||||||
cmake { |
|
||||||
cppFlags "-std=c++11 -frtti -fexceptions" |
|
||||||
} |
|
||||||
} |
|
||||||
ndk { |
|
||||||
abiFilters "armeabi-v7a" |
|
||||||
} |
|
||||||
} |
|
||||||
buildTypes { |
|
||||||
release { |
|
||||||
minifyEnabled false |
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' |
|
||||||
signingConfig signingConfigs.debug |
|
||||||
} |
|
||||||
debug { |
|
||||||
signingConfig signingConfigs.debug |
|
||||||
} |
|
||||||
} |
|
||||||
externalNativeBuild { |
|
||||||
cmake { |
|
||||||
path "../../CMakeLists.txt" |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
dependencies { |
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar']) |
|
||||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { |
|
||||||
exclude group: 'com.android.support', module: 'support-annotations' |
|
||||||
}) |
|
||||||
compile 'com.android.support:appcompat-v7:28.0.0' |
|
||||||
// Uncomment this line to build SDL2 |
|
||||||
// Uncomment a line in ../gradle.settings as well |
|
||||||
compile project(':SDL2') |
|
||||||
testCompile 'junit:junit:4.12' |
|
||||||
} |
|
@ -1,25 +0,0 @@ |
|||||||
# Add project specific ProGuard rules here. |
|
||||||
# By default, the flags in this file are appended to flags specified |
|
||||||
# in /home/luap/Logiciels/android-sdk/tools/proguard/proguard-android.txt |
|
||||||
# You can edit the include path and order by changing the proguardFiles |
|
||||||
# directive in build.gradle. |
|
||||||
# |
|
||||||
# For more details, see |
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html |
|
||||||
|
|
||||||
# Add any project specific keep options here: |
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following |
|
||||||
# and specify the fully qualified class name to the JavaScript interface |
|
||||||
# class: |
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { |
|
||||||
# public *; |
|
||||||
#} |
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for |
|
||||||
# debugging stack traces. |
|
||||||
#-keepattributes SourceFile,LineNumberTable |
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to |
|
||||||
# hide the original source file name. |
|
||||||
#-renamesourcefileattribute SourceFile |
|
Binary file not shown.
@ -1 +0,0 @@ |
|||||||
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] |
|
@ -1,31 +0,0 @@ |
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules. |
|
||||||
|
|
||||||
buildscript { |
|
||||||
repositories { |
|
||||||
google() |
|
||||||
jcenter() |
|
||||||
} |
|
||||||
dependencies { |
|
||||||
classpath 'com.android.tools.build:gradle:3.2.1' |
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong |
|
||||||
// in the individual module build.gradle files |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Instead of having a build dir inside android app dir use the same project top level build dir to reduce clutter |
|
||||||
buildDir = file("distribution/${rootProject.name}/${project.name}") |
|
||||||
subprojects { |
|
||||||
buildDir = file("../distribution/${rootProject.name}/${project.name}") |
|
||||||
} |
|
||||||
|
|
||||||
allprojects { |
|
||||||
repositories { |
|
||||||
google() |
|
||||||
jcenter() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
task clean(type: Delete) { |
|
||||||
delete rootProject.buildDir |
|
||||||
} |
|
@ -1,17 +0,0 @@ |
|||||||
# Project-wide Gradle settings. |
|
||||||
|
|
||||||
# IDE (e.g. Android Studio) users: |
|
||||||
# Gradle settings configured through the IDE *will override* |
|
||||||
# any settings specified in this file. |
|
||||||
|
|
||||||
# For more details on how to configure your build environment visit |
|
||||||
# http://www.gradle.org/docs/current/userguide/build_environment.html |
|
||||||
|
|
||||||
# Specifies the JVM arguments used for the daemon process. |
|
||||||
# The setting is particularly useful for tweaking memory settings. |
|
||||||
org.gradle.jvmargs=-Xmx1536m |
|
||||||
|
|
||||||
# When configured, Gradle will run in incubating parallel mode. |
|
||||||
# This option should only be used with decoupled projects. More details, visit |
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects |
|
||||||
# org.gradle.parallel=true |
|
Binary file not shown.
@ -1,6 +0,0 @@ |
|||||||
#Wed Jul 05 15:54:11 CEST 2017 |
|
||||||
distributionBase=GRADLE_USER_HOME |
|
||||||
distributionPath=wrapper/dists |
|
||||||
zipStoreBase=GRADLE_USER_HOME |
|
||||||
zipStorePath=wrapper/dists |
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip |
|
@ -1,160 +0,0 @@ |
|||||||
#!/usr/bin/env bash |
|
||||||
|
|
||||||
############################################################################## |
|
||||||
## |
|
||||||
## Gradle start up script for UN*X |
|
||||||
## |
|
||||||
############################################################################## |
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
|
||||||
DEFAULT_JVM_OPTS="" |
|
||||||
|
|
||||||
APP_NAME="Gradle" |
|
||||||
APP_BASE_NAME=`basename "$0"` |
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value. |
|
||||||
MAX_FD="maximum" |
|
||||||
|
|
||||||
warn ( ) { |
|
||||||
echo "$*" |
|
||||||
} |
|
||||||
|
|
||||||
die ( ) { |
|
||||||
echo |
|
||||||
echo "$*" |
|
||||||
echo |
|
||||||
exit 1 |
|
||||||
} |
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false'). |
|
||||||
cygwin=false |
|
||||||
msys=false |
|
||||||
darwin=false |
|
||||||
case "`uname`" in |
|
||||||
CYGWIN* ) |
|
||||||
cygwin=true |
|
||||||
;; |
|
||||||
Darwin* ) |
|
||||||
darwin=true |
|
||||||
;; |
|
||||||
MINGW* ) |
|
||||||
msys=true |
|
||||||
;; |
|
||||||
esac |
|
||||||
|
|
||||||
# Attempt to set APP_HOME |
|
||||||
# Resolve links: $0 may be a link |
|
||||||
PRG="$0" |
|
||||||
# Need this for relative symlinks. |
|
||||||
while [ -h "$PRG" ] ; do |
|
||||||
ls=`ls -ld "$PRG"` |
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'` |
|
||||||
if expr "$link" : '/.*' > /dev/null; then |
|
||||||
PRG="$link" |
|
||||||
else |
|
||||||
PRG=`dirname "$PRG"`"/$link" |
|
||||||
fi |
|
||||||
done |
|
||||||
SAVED="`pwd`" |
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null |
|
||||||
APP_HOME="`pwd -P`" |
|
||||||
cd "$SAVED" >/dev/null |
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar |
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM. |
|
||||||
if [ -n "$JAVA_HOME" ] ; then |
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
|
||||||
# IBM's JDK on AIX uses strange locations for the executables |
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java" |
|
||||||
else |
|
||||||
JAVACMD="$JAVA_HOME/bin/java" |
|
||||||
fi |
|
||||||
if [ ! -x "$JAVACMD" ] ; then |
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME |
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the |
|
||||||
location of your Java installation." |
|
||||||
fi |
|
||||||
else |
|
||||||
JAVACMD="java" |
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the |
|
||||||
location of your Java installation." |
|
||||||
fi |
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can. |
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then |
|
||||||
MAX_FD_LIMIT=`ulimit -H -n` |
|
||||||
if [ $? -eq 0 ] ; then |
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then |
|
||||||
MAX_FD="$MAX_FD_LIMIT" |
|
||||||
fi |
|
||||||
ulimit -n $MAX_FD |
|
||||||
if [ $? -ne 0 ] ; then |
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD" |
|
||||||
fi |
|
||||||
else |
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" |
|
||||||
fi |
|
||||||
fi |
|
||||||
|
|
||||||
# For Darwin, add options to specify how the application appears in the dock |
|
||||||
if $darwin; then |
|
||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" |
|
||||||
fi |
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java |
|
||||||
if $cygwin ; then |
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"` |
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` |
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"` |
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath |
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` |
|
||||||
SEP="" |
|
||||||
for dir in $ROOTDIRSRAW ; do |
|
||||||
ROOTDIRS="$ROOTDIRS$SEP$dir" |
|
||||||
SEP="|" |
|
||||||
done |
|
||||||
OURCYGPATTERN="(^($ROOTDIRS))" |
|
||||||
# Add a user-defined pattern to the cygpath arguments |
|
||||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then |
|
||||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" |
|
||||||
fi |
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh |
|
||||||
i=0 |
|
||||||
for arg in "$@" ; do |
|
||||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` |
|
||||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option |
|
||||||
|
|
||||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition |
|
||||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` |
|
||||||
else |
|
||||||
eval `echo args$i`="\"$arg\"" |
|
||||||
fi |
|
||||||
i=$((i+1)) |
|
||||||
done |
|
||||||
case $i in |
|
||||||
(0) set -- ;; |
|
||||||
(1) set -- "$args0" ;; |
|
||||||
(2) set -- "$args0" "$args1" ;; |
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;; |
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; |
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; |
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; |
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; |
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; |
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; |
|
||||||
esac |
|
||||||
fi |
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules |
|
||||||
function splitJvmOpts() { |
|
||||||
JVM_OPTS=("$@") |
|
||||||
} |
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS |
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" |
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" |
|
@ -1,90 +0,0 @@ |
|||||||
@if "%DEBUG%" == "" @echo off |
|
||||||
@rem ########################################################################## |
|
||||||
@rem |
|
||||||
@rem Gradle startup script for Windows |
|
||||||
@rem |
|
||||||
@rem ########################################################################## |
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell |
|
||||||
if "%OS%"=="Windows_NT" setlocal |
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
|
||||||
set DEFAULT_JVM_OPTS= |
|
||||||
|
|
||||||
set DIRNAME=%~dp0 |
|
||||||
if "%DIRNAME%" == "" set DIRNAME=. |
|
||||||
set APP_BASE_NAME=%~n0 |
|
||||||
set APP_HOME=%DIRNAME% |
|
||||||
|
|
||||||
@rem Find java.exe |
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome |
|
||||||
|
|
||||||
set JAVA_EXE=java.exe |
|
||||||
%JAVA_EXE% -version >NUL 2>&1 |
|
||||||
if "%ERRORLEVEL%" == "0" goto init |
|
||||||
|
|
||||||
echo. |
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
|
||||||
echo. |
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the |
|
||||||
echo location of your Java installation. |
|
||||||
|
|
||||||
goto fail |
|
||||||
|
|
||||||
:findJavaFromJavaHome |
|
||||||
set JAVA_HOME=%JAVA_HOME:"=% |
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe |
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init |
|
||||||
|
|
||||||
echo. |
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% |
|
||||||
echo. |
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the |
|
||||||
echo location of your Java installation. |
|
||||||
|
|
||||||
goto fail |
|
||||||
|
|
||||||
:init |
|
||||||
@rem Get command-line arguments, handling Windowz variants |
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args |
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args |
|
||||||
|
|
||||||
:win9xME_args |
|
||||||
@rem Slurp the command line arguments. |
|
||||||
set CMD_LINE_ARGS= |
|
||||||
set _SKIP=2 |
|
||||||
|
|
||||||
:win9xME_args_slurp |
|
||||||
if "x%~1" == "x" goto execute |
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%* |
|
||||||
goto execute |
|
||||||
|
|
||||||
:4NT_args |
|
||||||
@rem Get arguments from the 4NT Shell from JP Software |
|
||||||
set CMD_LINE_ARGS=%$ |
|
||||||
|
|
||||||
:execute |
|
||||||
@rem Setup the command line |
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar |
|
||||||
|
|
||||||
@rem Execute Gradle |
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% |
|
||||||
|
|
||||||
:end |
|
||||||
@rem End local scope for the variables with windows NT shell |
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd |
|
||||||
|
|
||||||
:fail |
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of |
|
||||||
rem the _cmd.exe /c_ return code! |
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 |
|
||||||
exit /b 1 |
|
||||||
|
|
||||||
:mainEnd |
|
||||||
if "%OS%"=="Windows_NT" endlocal |
|
||||||
|
|
||||||
:omega |
|
@ -1,4 +0,0 @@ |
|||||||
include ':app' |
|
||||||
// Uncomment this line to build SDL2 |
|
||||||
// Uncomment the dependency line in app/build.gradle as well |
|
||||||
include ':SDL2' |
|
@ -1,17 +0,0 @@ |
|||||||
#!/bin/bash -x |
|
||||||
|
|
||||||
pushd external/SDL2 |
|
||||||
|
|
||||||
wget https://www.libsdl.org/release/SDL2-2.0.8.zip |
|
||||||
unzip -q SDL2-2.0.8.zip |
|
||||||
mv SDL2-2.0.8 SDL2 |
|
||||||
rm SDL2-2.0.8.zip |
|
||||||
|
|
||||||
wget https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.3.zip |
|
||||||
unzip -q SDL2_image-2.0.3.zip |
|
||||||
mv SDL2_image-2.0.3 SDL2_image |
|
||||||
rm SDL2_image-2.0.3.zip |
|
||||||
|
|
||||||
popd |
|
||||||
# No need to copy SDLActivity.java et al, repo contains those from 2.0.8 |
|
||||||
# cp external/SDL2/SDL2/android-project/app/src/main/java/org/libsdl/app/*.java android/app/src/main/java/org/libsdl/app/ |
|
Binary file not shown.
@ -1,235 +0,0 @@ |
|||||||
#include "audio.h" |
|
||||||
#include <SDL_keycode.h> |
|
||||||
#include <SDL_mixer.h> |
|
||||||
#include <SDL_mutex.h> |
|
||||||
|
|
||||||
void generate_audio(void); |
|
||||||
struct game_sounds game_sounds; |
|
||||||
|
|
||||||
Uint8 big_hum(unsigned int t);
|
|
||||||
Uint8 func0(unsigned int t);
|
|
||||||
|
|
||||||
int mute = false; |
|
||||||
|
|
||||||
void fill_audio(void *func, Uint8 *stream, int len) { |
|
||||||
Uint8 (*wavegen)(unsigned int) = func; |
|
||||||
|
|
||||||
unsigned int t = 1; |
|
||||||
for(int i = 0; i < len; i++,t++) { |
|
||||||
stream[i] = wavegen(t); |
|
||||||
if (len - i < 300) { |
|
||||||
stream[i] = (float)wavegen(t) * (len - i) / 300.0; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void callbackfn3(void *unused, Uint8 *stream, int len) { |
|
||||||
static int t = 1; |
|
||||||
for(int i = 0; i < len; i++,t++) { |
|
||||||
stream[i] = big_hum(t); |
|
||||||
stream[i] = 0;
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void start_audio(void) { |
|
||||||
|
|
||||||
//audio_format.callback = callbackfn3;
|
|
||||||
/* just for playing background music
|
|
||||||
if (SDL_OpenAudio(&audio_format, NULL)) { |
|
||||||
fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError()); |
|
||||||
exit(1); |
|
||||||
} |
|
||||||
*/ |
|
||||||
//SDL_PauseAudio(0);
|
|
||||||
if (Mix_OpenAudio(G_AUDIO_SFREQ,AUDIO_S8,1,G_AUDIO_BSIZE) < 0) { |
|
||||||
fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError()); |
|
||||||
exit(1); |
|
||||||
} |
|
||||||
|
|
||||||
if (Mix_AllocateChannels(20) < 0) { |
|
||||||
fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError()); |
|
||||||
} |
|
||||||
|
|
||||||
generate_audio(); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void
|
|
||||||
play_game_sound(Mix_Chunk *chunk, int len, int channel)
|
|
||||||
{ |
|
||||||
if (mute || Mix_Playing(channel)) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if(Mix_PlayChannel(channel, chunk, 1) < 0) |
|
||||||
fprintf(stderr, "Unable to play audio: %s\n", SDL_GetError()); |
|
||||||
} |
|
||||||
|
|
||||||
Uint8
|
|
||||||
pitchshift_hit(unsigned int t, void *arg)
|
|
||||||
{ |
|
||||||
double *hitt = arg; |
|
||||||
double hit = *hitt; |
|
||||||
hit = 6 - hit; |
|
||||||
int lower = 10 + 2 * (hit > 6 ? 6 : hit); |
|
||||||
int higher = 1 + (hit > 6 ? 6 : hit); |
|
||||||
// printf("mag %f higher %d lower %d\n", hit, higher, lower);
|
|
||||||
|
|
||||||
const double R=8000; // sample rate (samples per second)
|
|
||||||
const double C=125; // frequency of middle-C (hertz)
|
|
||||||
const double F=R/256; // bytebeat frequency of 1*t due to 8-bit truncation (hertz)
|
|
||||||
const double V=127; // a volume constant
|
|
||||||
double volume = (((t / 3000) > 2) ? 2 : t / 3000); |
|
||||||
|
|
||||||
return ((sin(t*2*M_PI/R*(125 + hit))+1)*10 + (sin(t*2*M_PI/R*(250 + hit))+1)*(50 + hit) + (sin(t*2*M_PI/R*(900 + hit))+1)*100 + (sin(t*2*M_PI/R*(150+ hit))+1)*5) ; |
|
||||||
|
|
||||||
return ((t < 3000) * ((t % higher) * (3000 - t % 3000) * 0.00351)); |
|
||||||
//+ ((t < 3500) * ((3500 - t % 3500)) * 0.0002 * (t % lower));
|
|
||||||
} |
|
||||||
|
|
||||||
void
|
|
||||||
synthplay_now(Uint8 (*bbgen)(unsigned int t, void *), void *arg, int len)
|
|
||||||
{ |
|
||||||
static Mix_Chunk *new_chunk = NULL; |
|
||||||
|
|
||||||
if (Mix_Playing(1)) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if (new_chunk) |
|
||||||
Mix_FreeChunk(new_chunk); |
|
||||||
|
|
||||||
int generate_len = len * (512); |
|
||||||
|
|
||||||
Uint8 raw_data[generate_len]; |
|
||||||
|
|
||||||
unsigned int t = 1; |
|
||||||
for(int i = 0; i < generate_len; i++,t++) { |
|
||||||
raw_data[i] = bbgen(t, arg); |
|
||||||
} |
|
||||||
|
|
||||||
new_chunk = Mix_QuickLoad_RAW(raw_data, generate_len); |
|
||||||
Mix_PlayChannelTimed(1, new_chunk, -1, len); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void callbackfn2(void *unused, Uint8 *stream, int len) { |
|
||||||
static int t = 1; |
|
||||||
int i; |
|
||||||
int yeet = rand(); |
|
||||||
for(i=0; i < len; i++,t++) { |
|
||||||
stream[i] = func0(t); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void callbackfn(void *unused, Uint8 *stream, int len) |
|
||||||
{ |
|
||||||
static int t = 0; |
|
||||||
int i; |
|
||||||
int yeet = rand(); |
|
||||||
for( i=0; i < len; i++,t++) { |
|
||||||
/*
|
|
||||||
stream[i] = (t*5&(t>>7))|(t*3&(t>>8)); |
|
||||||
*/ |
|
||||||
//stream[i] = (( t >> 10 ) & 42) * t;
|
|
||||||
stream[i] = (t & yeet) % 73; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* Waveform Generators */ |
|
||||||
|
|
||||||
Uint8 big_hum(unsigned int t) { |
|
||||||
return ( (sin(t*2*3.14159265/8000*200)+1) * 20) + ( (sin(t*2*3.14159265/8000*110)+1) * 20) + ( (sin(t*2*3.14159265/8000*230)+1) * 20) + ( (sin((t % 80)*2*3.14159265/8000 * 6)+1) * 12); |
|
||||||
} |
|
||||||
|
|
||||||
unsigned int sine_wave_sound(unsigned int t) { |
|
||||||
const double R=8000; // sample rate (samples per second)
|
|
||||||
const double C=261.625565; // frequency of middle-C (hertz)
|
|
||||||
const double F=R/256; // bytebeat frequency of 1*t due to 8-bit truncation (hertz)
|
|
||||||
const double V=127; // a volume constant
|
|
||||||
return (sin(t*2*M_PI/R*C)+1)*V; |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 winch_sound(unsigned t) { |
|
||||||
return (((t % 80) | (t % 36) | (6 * (t % 6))) + 20) * 1.6; |
|
||||||
return ((t % 80) | (t % 36) | (6 * (t % 6))); |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 beat_2(unsigned t) { |
|
||||||
return ((((t % 250) / 2)) | (t % 129)) % 110; |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 func0(unsigned t) { |
|
||||||
int note = 18; |
|
||||||
if (!(t % 1240)) { |
|
||||||
note = (1 + rand()) % 18 + 1; |
|
||||||
} |
|
||||||
|
|
||||||
fflush(stdout); |
|
||||||
return (t % note); |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 func1(unsigned int t) { |
|
||||||
int note = 10; |
|
||||||
if (!(t % 8000)) { |
|
||||||
note = (1 + rand()) % 10 + 5; |
|
||||||
} |
|
||||||
return ((t & 110) % 73 | (t % 1711)); |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 collision_test(unsigned int t) { |
|
||||||
// try not to loop
|
|
||||||
int x = ((t < 3000) * ((t % 5) * (3000 - t % 3000) * 0.00351))
|
|
||||||
+ ((t < 3500) * ((3500 - t % 3500)) * 0.0002 * (t % 14)); |
|
||||||
float y = x; |
|
||||||
float lerp = 1; |
|
||||||
if (t > 80)
|
|
||||||
lerp = (100 - t) / 30; |
|
||||||
if (lerp > 1) lerp = 1; |
|
||||||
if (lerp < 0) lerp = 0; |
|
||||||
return y; |
|
||||||
return ((t < 3000) * ((t % 5) * (3000 - t % 3000) * 0.00351))
|
|
||||||
+ ((4000 - t % 4000) * 0.0003 * (t % 128))
|
|
||||||
+ ((t < 3500) * ((3500 - t % 3500)) * 0.0002 * (t % 64)); // has a big low sound
|
|
||||||
return (t % 4) * (4000 - t % 4000) * 0.01; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
Uint8 boop_noise(unsigned int t) { |
|
||||||
return ((t >> 10) & 42) * t; |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 rope_attach(unsigned int t) { |
|
||||||
return (((2000 - (t % 2000)))/40 * (t % 20) | (t % 44) + 20) * 1.6; |
|
||||||
} |
|
||||||
|
|
||||||
void generate_audio(void) { |
|
||||||
const int sfx_len_ms = 1000; |
|
||||||
unsigned int sfx_len = (G_AUDIO_SFREQ/1000) * G_AUDIO_BSIZE * sfx_len_ms; |
|
||||||
sfx_len = G_AUDIO_BSIZE; |
|
||||||
|
|
||||||
Uint8 *raw_data = calloc(sfx_len, sizeof(Uint8));
|
|
||||||
fill_audio(winch_sound, raw_data, sfx_len); |
|
||||||
game_sounds.rope_pull = Mix_QuickLoad_RAW(raw_data, sfx_len); |
|
||||||
Mix_Volume(BC_ROPE_PULL, MIX_MAX_VOLUME * 0.1); |
|
||||||
|
|
||||||
Uint8 *raw_data2 = calloc(sfx_len, sizeof(Uint8));
|
|
||||||
fill_audio(collision_test, raw_data2, sfx_len); |
|
||||||
game_sounds.collision = Mix_QuickLoad_RAW(raw_data2, sfx_len); |
|
||||||
Mix_Volume(BC_COLLISION, MIX_MAX_VOLUME); |
|
||||||
|
|
||||||
Uint8 *raw_data3 = calloc(sfx_len, sizeof(Uint8));
|
|
||||||
fill_audio(big_hum, raw_data3, sfx_len); |
|
||||||
game_sounds.background = Mix_QuickLoad_RAW(raw_data3, sfx_len); |
|
||||||
Mix_Volume(BC_MUSIC, MIX_MAX_VOLUME * 0.1); |
|
||||||
|
|
||||||
Uint8 *raw_data4 = calloc(sfx_len, sizeof(Uint8));
|
|
||||||
fill_audio(rope_attach, raw_data4, sfx_len); |
|
||||||
game_sounds.rope_attach = Mix_QuickLoad_RAW(raw_data4, sfx_len); |
|
||||||
Mix_Volume(BC_ROPE_ATTACH, MIX_MAX_VOLUME * 0.1); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
@ -1,37 +0,0 @@ |
|||||||
|
|
||||||
#ifndef AUDIO_H |
|
||||||
#define AUDIO_H |
|
||||||
|
|
||||||
#include <SDL_audio.h> |
|
||||||
#include "types.h" |
|
||||||
#include <math.h> |
|
||||||
#include <stdlib.h> |
|
||||||
|
|
||||||
#define G_AUDIO_SFREQ 8000 |
|
||||||
#define G_AUDIO_BSIZE 512 |
|
||||||
|
|
||||||
struct game_sounds { |
|
||||||
unsigned int t; |
|
||||||
Mix_Chunk *collision; |
|
||||||
Mix_Chunk *rope_attach; |
|
||||||
Mix_Chunk *rope_pull; |
|
||||||
Mix_Chunk *background; |
|
||||||
/* Looping samples (need backbuffer to fill while playing ) */ |
|
||||||
Mix_Chunk *menu; |
|
||||||
}; |
|
||||||
|
|
||||||
extern struct game_sounds game_sounds; |
|
||||||
|
|
||||||
void play_game_sound(Mix_Chunk *chunk, int len, int channel); |
|
||||||
void start_audio(void);
|
|
||||||
|
|
||||||
Uint8 pitchshift_hit(unsigned int t, void *arg); |
|
||||||
void synthplay_now(Uint8 (*bbgen)(unsigned int t, void *), void *arg, int len);
|
|
||||||
|
|
||||||
enum audio_channel_names { |
|
||||||
BC_COLLISION = 1, |
|
||||||
BC_ROPE_PULL = 2, |
|
||||||
BC_ROPE_ATTACH = 3, |
|
||||||
BC_MUSIC = 4, |
|
||||||
}; |
|
||||||
#endif |
|
@ -1,97 +0,0 @@ |
|||||||
#include <stdio.h> |
|
||||||
#include <time.h> |
|
||||||
#include <string.h> |
|
||||||
|
|
||||||
// #define LOGGING 1
|
|
||||||
// #define log_var(string, content) if (LOGGING) {time_t current_time; time(¤t_time); printf("%s",asctime(localtime(¤t_time))); printf(string, content);}
|
|
||||||
// #define log_str(string) if (LOGGING) {time_t current_time; time(¤t_time); puts(asctime(localtime(¤t_time))); puts(string);}
|
|
||||||
|
|
||||||
void enumerate_string(char test_array[]) { |
|
||||||
char *ptr; |
|
||||||
ptr = &(test_array[0]); |
|
||||||
for (int i=0; i<5; i++) { |
|
||||||
printf("%c", *(ptr + i)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
int copy_str(char * out_string, char * string) { |
|
||||||
/* A drop in replacement for strcpy() from <string.h>*/ |
|
||||||
int len = 0; |
|
||||||
while (*(string + len) != '\0') { |
|
||||||
*(out_string + len) = *(string + len); |
|
||||||
len++; |
|
||||||
} |
|
||||||
*(out_string + len) = '\0'; |
|
||||||
return (1); |
|
||||||
} |
|
||||||
|
|
||||||
int get_str_len(char * string) { |
|
||||||
int len = 0; |
|
||||||
while (*(string + len) != '\0') { |
|
||||||
len++; |
|
||||||
} |
|
||||||
return(len); |
|
||||||
} |
|
||||||
|
|
||||||
void replace_char(char * array, char * charac) { |
|
||||||
int length; |
|
||||||
length = sizeof(*array)/sizeof(char); |
|
||||||
char combined[length]; |
|
||||||
|
|
||||||
int i = 0; |
|
||||||
int counter = 0; |
|
||||||
|
|
||||||
while (*(array + i) != '\0') { |
|
||||||
if (*(array + i) != *charac) { |
|
||||||
*(array + counter) = *(array + i); |
|
||||||
counter++; |
|
||||||
} |
|
||||||
i++; |
|
||||||
} |
|
||||||
*(array + counter + 1) = '\0'; |
|
||||||
} |
|
||||||
|
|
||||||
void join_strings(char * return_val, char * str_1, char * str_2) { |
|
||||||
|
|
||||||
int len1 = get_str_len(str_1); |
|
||||||
int len2 = get_str_len(str_2); |
|
||||||
|
|
||||||
int length = len1 + len2; |
|
||||||
char combined[length+1]; |
|
||||||
int i = 0; |
|
||||||
int j = 0; |
|
||||||
|
|
||||||
while (*(str_1 + i) != '\0') { |
|
||||||
combined[i] = *(str_1 + i); |
|
||||||
i++; |
|
||||||
} |
|
||||||
|
|
||||||
while (*(str_2 + j) != '\0') { |
|
||||||
combined[len1+j] = *(str_2 + j); |
|
||||||
j++; |
|
||||||
} |
|
||||||
copy_str(return_val, combined); |
|
||||||
} |
|
||||||
|
|
||||||
void get_time(void) { |
|
||||||
char time_str[100]; |
|
||||||
time_t current_time; |
|
||||||
time(¤t_time);
|
|
||||||
copy_str(time_str, asctime(localtime(¤t_time))); |
|
||||||
|
|
||||||
strcat(time_str, "hello world"); |
|
||||||
//replace_char(&(time_str[0]), "\n");
|
|
||||||
printf("%s", time_str); |
|
||||||
|
|
||||||
char string[20]; |
|
||||||
copy_str(string, "NONEWLINEhello"); |
|
||||||
|
|
||||||
|
|
||||||
replace_char(&(time_str[0]), "\n"); |
|
||||||
char newstr[120]; |
|
||||||
join_strings(&(newstr[0]), &(time_str[0]), &(string[0])); |
|
||||||
replace_char(&(newstr[0]), "\n"); |
|
||||||
|
|
||||||
printf("%s", newstr); |
|
||||||
} |
|
||||||
|
|
@ -1,238 +0,0 @@ |
|||||||
#include "colours.h" |
|
||||||
|
|
||||||
struct colour get_random_color(unsigned int seed) { |
|
||||||
srand(seed); |
|
||||||
int red = rand() % 255; |
|
||||||
int blue = rand() % 255; |
|
||||||
int green = rand() % 255; |
|
||||||
|
|
||||||
struct colour col; |
|
||||||
col.r = red; |
|
||||||
col.g = green; |
|
||||||
col.b = blue; |
|
||||||
return col; |
|
||||||
} |
|
||||||
|
|
||||||
double m_min(double arr[], int len) { |
|
||||||
double largest = arr[0]; |
|
||||||
for (int i = 0; i < len; i ++) { |
|
||||||
if (arr[i] < largest) { |
|
||||||
largest = arr[i]; |
|
||||||
} |
|
||||||
} |
|
||||||
return largest; |
|
||||||
} |
|
||||||
|
|
||||||
double m_max(double arr[], int len) { |
|
||||||
double largest = arr[0]; |
|
||||||
for (int i = 0; i < len; i ++) { |
|
||||||
if (arr[i] > largest) { |
|
||||||
largest = arr[i]; |
|
||||||
} |
|
||||||
} |
|
||||||
return largest; |
|
||||||
} |
|
||||||
|
|
||||||
bool m_equal(double a, double b) { |
|
||||||
return (a - b) * (a - b) < 0.00001; |
|
||||||
} |
|
||||||
|
|
||||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
|
|
||||||
// h = [0,360], s = [0,1], v = [0,1]
|
|
||||||
// if s == 0, then h = -1 (undefined)
|
|
||||||
struct colour get_hs_l_v(struct colour c, enum colour_space sp) { |
|
||||||
struct colour ret; |
|
||||||
memset(&ret, 0, sizeof(struct colour)); |
|
||||||
double r = (double)c.r / 255; |
|
||||||
double g = (double)c.g / 255; |
|
||||||
double b = (double)c.b / 255; |
|
||||||
|
|
||||||
double arr[] = {r, g, b}; |
|
||||||
double max = m_max(arr, 3); |
|
||||||
double min = m_min(arr, 3); |
|
||||||
|
|
||||||
ret.v = max; |
|
||||||
|
|
||||||
double chroma = max - min; |
|
||||||
|
|
||||||
double lum = (max + min) / 2; |
|
||||||
ret.l = lum; |
|
||||||
|
|
||||||
if (m_equal(chroma, 0)) { |
|
||||||
ret.h = 0; |
|
||||||
} else if (m_equal(ret.v,r)) { |
|
||||||
ret.h = (g - b) / chroma; |
|
||||||
} else if (m_equal(max,g)) { |
|
||||||
ret.h = 2 + (b - r) / chroma; |
|
||||||
} else if (m_equal(max,b)) { |
|
||||||
ret.h = 4 + (r - g) / chroma; |
|
||||||
} else { |
|
||||||
printf("NOPE BAD ERROR\n"); |
|
||||||
}
|
|
||||||
|
|
||||||
ret.h *= 60; |
|
||||||
ret.h = fmod(ret.h, 360); |
|
||||||
if (ret.h < 0) { |
|
||||||
ret.h += 360; |
|
||||||
} |
|
||||||
|
|
||||||
if (sp == CS_HSV) { |
|
||||||
if (m_equal(max,0)) { |
|
||||||
ret.s = 0; |
|
||||||
} else { |
|
||||||
ret.s = chroma / max; |
|
||||||
} |
|
||||||
} else { |
|
||||||
double arr[] = {ret.l, 1 - ret.l}; |
|
||||||
if (m_equal(0, lum) || m_equal(1, lum)) { |
|
||||||
ret.s = 0; |
|
||||||
} else { |
|
||||||
ret.s = (ret.v - ret.l) / m_min(arr, 2);
|
|
||||||
} |
|
||||||
} |
|
||||||
ret.sp = CS_HSL; |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
struct colour get_hsl(struct colour c) { |
|
||||||
return get_hs_l_v(c, CS_HSL);
|
|
||||||
} |
|
||||||
|
|
||||||
struct colour get_hsv(struct colour c) { |
|
||||||
return get_hs_l_v(c, CS_HSV);
|
|
||||||
} |
|
||||||
|
|
||||||
double magic_hsv_function(int n, struct colour c) { |
|
||||||
double res = 0; |
|
||||||
double k = fmod(n + (c.h / 60), 6); |
|
||||||
double arr[] = {k, 4 - k, 1}; |
|
||||||
double k_b = m_min(arr, 3); |
|
||||||
double k_c = 0 > k_b ? 0 : k_b; |
|
||||||
res = c.v - c.v * c.s * k_c;
|
|
||||||
return res; |
|
||||||
} |
|
||||||
|
|
||||||
struct colour get_rgb_from_hsv(struct colour c) { |
|
||||||
|
|
||||||
double r = magic_hsv_function(5, c); |
|
||||||
double g = magic_hsv_function(3, c); |
|
||||||
double b = magic_hsv_function(1, c); |
|
||||||
|
|
||||||
struct colour res; |
|
||||||
res.r = round(r * 255); |
|
||||||
res.g = round(g * 255); |
|
||||||
res.b = round(b * 255); |
|
||||||
return res; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
double magic_hsl_function(int n, struct colour c) { |
|
||||||
double arr[] = {c.l, 1-c.l}; |
|
||||||
double a = c.s * ( c.l < (1-c.l) ? c.l : 1 - c.l ); |
|
||||||
double k = fmod(n + c.h / 30, 12); |
|
||||||
|
|
||||||
double b[] = {k - 3, 9 -k, 1}; |
|
||||||
double d[] = {-1, m_min(b, 3)}; |
|
||||||
return c.l - a * (d[0] > d[1] ? d[0] : d[1]); |
|
||||||
} |
|
||||||
|
|
||||||
struct colour get_rgb_from_hsl(struct colour c) { |
|
||||||
double r = magic_hsl_function(0, c); |
|
||||||
double g = magic_hsl_function(8, c); |
|
||||||
double b = magic_hsl_function(4, c); |
|
||||||
|
|
||||||
struct colour res; |
|
||||||
res.r = round(r * 255); |
|
||||||
res.g = round(g * 255); |
|
||||||
res.b = round(b * 255); |
|
||||||
return res; |
|
||||||
} |
|
||||||
|
|
||||||
struct colour get_rgb(struct colour c) { |
|
||||||
if (c.sp == CS_HSL) { |
|
||||||
return get_rgb_from_hsl(c); |
|
||||||
} |
|
||||||
if (c.sp == CS_HSV) { |
|
||||||
return get_rgb_from_hsv(c); |
|
||||||
} |
|
||||||
|
|
||||||
struct colour d; |
|
||||||
memset(&d, 0, sizeof(struct colour)); |
|
||||||
return d; |
|
||||||
} |
|
||||||
|
|
||||||
int compare_perceived_lum(const void* c1, const void* c2) { |
|
||||||
struct colour rgb_c1 = *(struct colour*)c1; |
|
||||||
struct colour rgb_c2 = *(struct colour*)c2; |
|
||||||
|
|
||||||
double lum1 = 0.299*rgb_c1.r + 0.587*rgb_c1.g + 0.114*rgb_c1.b; |
|
||||||
double lum2 = 0.299*rgb_c2.r + 0.587*rgb_c2.g + 0.114*rgb_c2.b; |
|
||||||
return lum1 - lum2; |
|
||||||
} |
|
||||||
|
|
||||||
struct colour *get_adjacent(struct colour base, int deg, int num) { |
|
||||||
struct colour col = get_hsl(base); |
|
||||||
num += 1; |
|
||||||
|
|
||||||
struct colour* colours = calloc(sizeof(struct colour), num);
|
|
||||||
|
|
||||||
for (int i = 0; i < num; i++) { |
|
||||||
int m = (i % 2 == 0) ? -i : i; |
|
||||||
|
|
||||||
colours[i] = col; |
|
||||||
colours[i].h += m * deg; |
|
||||||
colours[i].h += fmod(colours[i].h, 360); |
|
||||||
} |
|
||||||
|
|
||||||
struct colour *ret_colours = calloc(num, sizeof(struct colour) * num); |
|
||||||
|
|
||||||
for (int i = 0; i < num; i++) { |
|
||||||
ret_colours[i] = get_rgb(colours[i]); |
|
||||||
} |
|
||||||
|
|
||||||
// sort from dark to bright
|
|
||||||
qsort(ret_colours, num, sizeof(struct colour), compare_perceived_lum); |
|
||||||
|
|
||||||
free(colours); |
|
||||||
return ret_colours; |
|
||||||
} |
|
||||||
|
|
||||||
void print_colour(struct colour c) { |
|
||||||
char *colour = calloc(20, sizeof(char)); |
|
||||||
sprintf(colour, "#%02x%02x%02x", c.r, c.g, c.b); |
|
||||||
|
|
||||||
printf("\x1b[38;2;%d;%d;%dm%s\x1b[0m\n", c.r, c.g, c.b, colour); |
|
||||||
free(colour); |
|
||||||
} |
|
||||||
|
|
||||||
void test(int seed) { |
|
||||||
struct colour c = get_random_color(seed); |
|
||||||
//print_colour(c);
|
|
||||||
struct colour hsl = get_hsl(c); |
|
||||||
struct colour hsv = get_hsv(c); |
|
||||||
/*printf("RGB: %d %d %d\n",c.r,c.g,c.b);*/ |
|
||||||
/*printf("HSL: %f %f %f\n",hsl.h, hsl.s, hsl.l);*/ |
|
||||||
/*printf("HSV: %f %f %f\n",hsv.h, hsv.s, hsv.v);*/ |
|
||||||
|
|
||||||
struct colour *adj = get_adjacent(c, 5, 4); |
|
||||||
for (int i = 0; i < 5; i++) { |
|
||||||
print_colour(adj[i]); |
|
||||||
} |
|
||||||
|
|
||||||
free(adj); |
|
||||||
printf("\n"); |
|
||||||
} |
|
||||||
|
|
||||||
void test_print_wheel() { |
|
||||||
struct colour c; |
|
||||||
c.s = 0.999; |
|
||||||
c.v = 0.99; |
|
||||||
c.l = 0.5; |
|
||||||
c.sp = CS_HSV; |
|
||||||
for(int i = 0; i < 360; i+=5) { |
|
||||||
c.h = (double)i; |
|
||||||
struct colour rgb = get_rgb(c); |
|
||||||
print_colour(rgb); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,43 +0,0 @@ |
|||||||
|
|
||||||
#ifndef COSMOPOLITAN |
|
||||||
#include <stdbool.h> |
|
||||||
#include <stdlib.h> |
|
||||||
#include <string.h> |
|
||||||
#include <math.h> |
|
||||||
#include <stdio.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
#ifndef H_COLOURS |
|
||||||
#define H_COLOURS |
|
||||||
|
|
||||||
enum colour_space { |
|
||||||
CS_INVALID = 0, |
|
||||||
CS_RGB = 1, // default to RGB
|
|
||||||
CS_HSV = 2, |
|
||||||
CS_HSL = 3, |
|
||||||
}; |
|
||||||
|
|
||||||
struct colour { |
|
||||||
double h; |
|
||||||
double s; |
|
||||||
double v; |
|
||||||
double l; |
|
||||||
int r; |
|
||||||
int g; |
|
||||||
int b; |
|
||||||
enum colour_space sp; |
|
||||||
}; |
|
||||||
|
|
||||||
struct colour get_random_color(unsigned int seed); |
|
||||||
|
|
||||||
// doesn't support hsl-hsv or converse, conversion
|
|
||||||
struct colour get_hsl(struct colour c); |
|
||||||
struct colour get_hsv(struct colour c);
|
|
||||||
|
|
||||||
struct colour get_rgb(struct colour c);
|
|
||||||
|
|
||||||
struct colour *get_adjacent(struct colour base, int deg, int num);
|
|
||||||
|
|
||||||
void print_colour(struct colour c);
|
|
||||||
|
|
||||||
#endif |
|
@ -1,106 +0,0 @@ |
|||||||
|
|
||||||
#include "controlscheme.h" |
|
||||||
#include <SDL_scancode.h> |
|
||||||
|
|
||||||
#ifdef LOAD_INPUTS |
|
||||||
#include <sys/stat.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
struct InputMap input_map; |
|
||||||
|
|
||||||
#define INPUT_MAP_ID 83921864 |
|
||||||
#define INPUT_MAP_VERSION 0 |
|
||||||
#define CONTROLS_FNAME "controls.bin" |
|
||||||
|
|
||||||
struct InputMap_Ser { |
|
||||||
unsigned int id; |
|
||||||
unsigned int ver; |
|
||||||
struct InputMap input_map; |
|
||||||
}; |
|
||||||
|
|
||||||
int load_controls(void);
|
|
||||||
|
|
||||||
void get_input_map(void) { |
|
||||||
|
|
||||||
#ifdef LOAD_INPUTS |
|
||||||
if (load_controls()) { |
|
||||||
return; |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
input_map.player_down = SDL_SCANCODE_S; |
|
||||||
input_map.player_up = SDL_SCANCODE_W; |
|
||||||
input_map.player_right = SDL_SCANCODE_D; |
|
||||||
input_map.player_left = SDL_SCANCODE_A; |
|
||||||
input_map.player_rope = SDL_SCANCODE_E; |
|
||||||
input_map.player_pull_rope = SDL_SCANCODE_Q; |
|
||||||
input_map.mute = SDL_SCANCODE_M; |
|
||||||
input_map.pause = SDL_SCANCODE_ESCAPE; |
|
||||||
input_map.quit = SDL_SCANCODE_Q; |
|
||||||
input_map.goto_level = SDL_SCANCODE_G; |
|
||||||
input_map.mouse_attach_rope_pull = SDL_BUTTON_LEFT; |
|
||||||
input_map.mouse_attach_rope = SDL_BUTTON_RIGHT; |
|
||||||
} |
|
||||||
|
|
||||||
#ifdef LOAD_INPUTS |
|
||||||
struct Buffer { |
|
||||||
size_t len; |
|
||||||
char *data; |
|
||||||
}; |
|
||||||
|
|
||||||
struct Buffer read_whole_file(char const *file_name) { |
|
||||||
struct stat sb; |
|
||||||
struct Buffer b = {}; |
|
||||||
|
|
||||||
if (stat (file_name, & sb) != 0) { |
|
||||||
return b; |
|
||||||
} |
|
||||||
|
|
||||||
char *buffer = malloc(sb.st_size + 1); |
|
||||||
|
|
||||||
FILE *f = fopen(file_name, "r"); |
|
||||||
size_t bytes_read = fread(buffer, sizeof (unsigned char), sb.st_size, f); |
|
||||||
if (bytes_read != sb.st_size) { |
|
||||||
fclose(f); |
|
||||||
free(buffer); |
|
||||||
return b; |
|
||||||
} |
|
||||||
|
|
||||||
fclose(f); |
|
||||||
|
|
||||||
b.data = buffer; |
|
||||||
b.len = bytes_read; |
|
||||||
return b; |
|
||||||
} |
|
||||||
|
|
||||||
int load_controls(void) { |
|
||||||
struct Buffer b = read_whole_file(CONTROLS_FNAME); |
|
||||||
|
|
||||||
if (b.len != sizeof (struct InputMap_Ser)) { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
struct InputMap_Ser *im = (struct InputMap_Ser *)b.data; |
|
||||||
|
|
||||||
if (im->id != INPUT_MAP_ID) |
|
||||||
return 0; |
|
||||||
|
|
||||||
if (im->ver != INPUT_MAP_VERSION) |
|
||||||
return 0; |
|
||||||
|
|
||||||
memcpy(&input_map, &im->input_map, sizeof(struct InputMap)); |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
void save_controls(void) { |
|
||||||
FILE *f = fopen(CONTROLS_FNAME, "w"); |
|
||||||
|
|
||||||
struct InputMap_Ser im; |
|
||||||
im.id = INPUT_MAP_ID; |
|
||||||
im.ver = INPUT_MAP_VERSION; |
|
||||||
im.input_map = input_map; |
|
||||||
|
|
||||||
fwrite(&im, sizeof(unsigned char), sizeof(struct InputMap_Ser), f); |
|
||||||
fclose(f); |
|
||||||
} |
|
||||||
#endif |
|
@ -1,159 +0,0 @@ |
|||||||
#include "datatypes.h" |
|
||||||
#include <string.h> |
|
||||||
#include <stdlib.h> |
|
||||||
|
|
||||||
ArrayList new_arlst(int num_elems) { |
|
||||||
ArrayList new_list; |
|
||||||
new_list.free = NULL; |
|
||||||
new_list.size = 0; |
|
||||||
new_list.capacity = num_elems; |
|
||||||
new_list.items = calloc(num_elems, sizeof(void *)); |
|
||||||
|
|
||||||
return new_list; |
|
||||||
} |
|
||||||
|
|
||||||
ArrayList new_arlst_wfree(int num_elems, void (*nfree)(void *ptr)) { |
|
||||||
ArrayList new_list = new_arlst(num_elems); |
|
||||||
new_list.free = nfree; |
|
||||||
return new_list; |
|
||||||
} |
|
||||||
|
|
||||||
ArrayList new_arlst_using_array(void **array, int length) { |
|
||||||
ArrayList l = new_arlst(length); |
|
||||||
free(l.items); |
|
||||||
l.items = array; |
|
||||||
return l; |
|
||||||
} |
|
||||||
|
|
||||||
ArrayList new_arlst_using_array_wfree(void **array, int length,
|
|
||||||
void (*f)(void *)) { |
|
||||||
ArrayList l = new_arlst_using_array(array, length); |
|
||||||
l.free = f; |
|
||||||
return l; |
|
||||||
} |
|
||||||
|
|
||||||
ArrayList new_arlst_from_array(void *array, size_t elem_size, int length) { |
|
||||||
ArrayList l = new_arlst(length); |
|
||||||
l.free = free; |
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) { |
|
||||||
void *item = calloc(1, elem_size); |
|
||||||
void *start = array + i * elem_size; |
|
||||||
memmove(item, start, elem_size); |
|
||||||
arlst_add(&l, item); |
|
||||||
} |
|
||||||
return l; |
|
||||||
} |
|
||||||
|
|
||||||
void *arlst_get(ArrayList *l, int id) { |
|
||||||
// out of bounds
|
|
||||||
if (id < 0 || id >= l->size) { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
return l->items[id]; |
|
||||||
} |
|
||||||
|
|
||||||
void * arlst_del(ArrayList *l, int id) { |
|
||||||
void *item = arlst_get(l, id); |
|
||||||
|
|
||||||
if (!item) { |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
l->size--; |
|
||||||
// move elements backward
|
|
||||||
for (int i = id; i < l->size; i++) { |
|
||||||
l->items[i] = l->items[i+1]; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// shrink capacity if neccessary
|
|
||||||
if (D_SHRINK_THRESHOLD != 0
|
|
||||||
|| l->size < (100 / D_SHRINK_THRESHOLD) * l->capacity) { |
|
||||||
|
|
||||||
size_t new_size = l-> size + (l->capacity * (100 / D_SHRINK_THRESHOLD) *
|
|
||||||
100 / D_GROW_AMOUNT); |
|
||||||
|
|
||||||
// l->items = reallocarray(l->items, new_size, sizeof(void *));
|
|
||||||
l->items = realloc(l->items, new_size * sizeof(void *)); |
|
||||||
} |
|
||||||
|
|
||||||
return item; |
|
||||||
} |
|
||||||
|
|
||||||
int arlst_add(ArrayList *l, void *item) { |
|
||||||
int item_index = l->size; |
|
||||||
|
|
||||||
// grow if neccessary
|
|
||||||
if (l->size == l->capacity) { |
|
||||||
size_t new_size = l->capacity + (100 / D_GROW_AMOUNT) * l->capacity; |
|
||||||
l->capacity = new_size; |
|
||||||
//l->items = (void **)reallocarray(l->items, new_size, sizeof(void *));
|
|
||||||
l->items = (void **)realloc(l->items, new_size * sizeof(void *)); |
|
||||||
} |
|
||||||
|
|
||||||
l->items[item_index] = item; |
|
||||||
l->size++; |
|
||||||
|
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
void * arlst_pop(ArrayList *l) { |
|
||||||
l->size--; |
|
||||||
return l->items[l->size]; |
|
||||||
} |
|
||||||
|
|
||||||
int arlst_push(ArrayList *l, void *item) { |
|
||||||
return arlst_add(l, item); |
|
||||||
} |
|
||||||
|
|
||||||
int arlst_destroy(ArrayList *l) { |
|
||||||
if (l->free != NULL) { |
|
||||||
for (int i = 0; i < l->size; i++) { |
|
||||||
l->free(l->items[i]); |
|
||||||
} |
|
||||||
} |
|
||||||
free(l->items); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
ListFiFo new_fifo(int start_size) { |
|
||||||
ListFiFo l; |
|
||||||
memset(&l, 0, sizeof(ListFiFo)); |
|
||||||
l.inner = new_arlst(start_size); |
|
||||||
l.size = &l.inner.size; |
|
||||||
return l; |
|
||||||
} |
|
||||||
|
|
||||||
void *fifo_get(ListFiFo *l) { |
|
||||||
if (l->fifo_head >= l->inner.size) { |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
void *value = arlst_get(&l->inner, l->fifo_head); |
|
||||||
|
|
||||||
if (value != NULL) { |
|
||||||
l->fifo_head++; |
|
||||||
} |
|
||||||
|
|
||||||
if (l->fifo_head == l->inner.capacity |
|
||||||
|| (l->fifo_head == l->inner.size
|
|
||||||
&& l->inner.size >= D_MAX_QUEUE_LEN)) { |
|
||||||
// start rewriting from the beginning
|
|
||||||
l->inner.size = 0; |
|
||||||
l->fifo_head = 0; |
|
||||||
// memset(l->inner.items, 0, sizeof(void *) * l->inner.capacity);
|
|
||||||
} |
|
||||||
return value; |
|
||||||
} |
|
||||||
|
|
||||||
/* It is up to the caller to free any data stored */ |
|
||||||
int fifo_add(ListFiFo *l, void *i) { |
|
||||||
if (l->inner.size >= D_MAX_QUEUE_LEN) { |
|
||||||
return -1; |
|
||||||
} |
|
||||||
return arlst_add(&l->inner, i); |
|
||||||
} |
|
||||||
|
|
@ -1,61 +0,0 @@ |
|||||||
#ifndef DTYPE_H |
|
||||||
#define DTYPE_H |
|
||||||
|
|
||||||
#include <stdlib.h> |
|
||||||
|
|
||||||
enum { |
|
||||||
D_SHRINK_THRESHOLD = 50, // percentage of capacity
|
|
||||||
// 0 = never shrink
|
|
||||||
// 100 = always shrink
|
|
||||||
D_GROW_AMOUNT = 50, // percentage of size
|
|
||||||
// 0 = 1 = grow by 1 on every add
|
|
||||||
// 100 = double size whenever space runs out
|
|
||||||
D_MAX_QUEUE_LEN = 400 // maximum num of items allowed in a fifo
|
|
||||||
}; |
|
||||||
|
|
||||||
struct array_list { |
|
||||||
size_t size; |
|
||||||
size_t capacity; |
|
||||||
|
|
||||||
void **items; |
|
||||||
void (*free)(void *ptr); // free function
|
|
||||||
}; |
|
||||||
|
|
||||||
struct list_fifo { |
|
||||||
struct array_list inner; |
|
||||||
size_t fifo_head; |
|
||||||
size_t *size; |
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct array_list ArrayList; |
|
||||||
typedef struct list_fifo ListFiFo; |
|
||||||
|
|
||||||
/* FIFOs */ |
|
||||||
|
|
||||||
ListFiFo new_fifo(int start_size);
|
|
||||||
int fifo_add(ListFiFo *l, void *i);
|
|
||||||
void *fifo_get(ListFiFo *l);
|
|
||||||
|
|
||||||
/* Stacks */ |
|
||||||
|
|
||||||
int arlst_push(ArrayList *l, void *item);
|
|
||||||
void * arlst_pop(ArrayList *l);
|
|
||||||
|
|
||||||
/* Array Lists */ |
|
||||||
|
|
||||||
// constructors
|
|
||||||
ArrayList new_arlst_from_array(void *array, size_t elem_size, int length); |
|
||||||
ArrayList new_arlst_using_array_wfree(void **, int, void (*)(void *));
|
|
||||||
ArrayList new_arlst_using_array(void **array, int length);
|
|
||||||
ArrayList new_arlst_wfree(int num_elems, void (*nfree)(void *ptr));
|
|
||||||
ArrayList new_arlst(int num_elems);
|
|
||||||
|
|
||||||
// destructors
|
|
||||||
int arlst_destroy(ArrayList *l);
|
|
||||||
void * arlst_del(ArrayList *l, int id); |
|
||||||
|
|
||||||
// functions
|
|
||||||
int arlst_add(ArrayList *l, void *item);
|
|
||||||
void *arlst_get(ArrayList *l, int id); |
|
||||||
|
|
||||||
#endif |
|
@ -1,983 +0,0 @@ |
|||||||
#include "draw.h" |
|
||||||
#include "game.h" |
|
||||||
#include "types.h" |
|
||||||
#include <SDL_mutex.h> |
|
||||||
#include <SDL_render.h> |
|
||||||
#include <time.h> |
|
||||||
|
|
||||||
Vect viewport_pos; |
|
||||||
int width, height; |
|
||||||
|
|
||||||
bool high_contrast_mode = 0; |
|
||||||
|
|
||||||
/* generic rendering functions */ |
|
||||||
int MAX_ONSCREEN_OBJECTS = 99; |
|
||||||
|
|
||||||
int num_onscreen = 0; |
|
||||||
|
|
||||||
double time_delta = 0; |
|
||||||
|
|
||||||
void render_texture_at(struct SDL_Renderer * ren, struct SDL_Texture * texture,int x, int y) { |
|
||||||
/* draw a texture at x.y */ |
|
||||||
|
|
||||||
SDL_Rect destination; |
|
||||||
destination.x = x; |
|
||||||
destination.y = y; |
|
||||||
|
|
||||||
SDL_QueryTexture(texture, NULL, NULL, &destination.w, &destination.h); |
|
||||||
|
|
||||||
SDL_RenderCopy(ren, texture, NULL, &destination); |
|
||||||
} |
|
||||||
|
|
||||||
/*SDL_Texture * load_image(SDL_Renderer * ren, char fname[]) {*/ |
|
||||||
/*[> Load an image into a texture <]*/ |
|
||||||
|
|
||||||
/*SDL_Surface * surface = IMG_Load(fname) ;*/ |
|
||||||
/*if(!surface) {*/ |
|
||||||
/*printf("IMG_Load: %s\n", IMG_GetError());*/ |
|
||||||
/*// handle error*/ |
|
||||||
/*}*/ |
|
||||||
|
|
||||||
/*SDL_Texture * png_image = SDL_CreateTextureFromSurface(ren, surface);*/ |
|
||||||
/*cleanup(surface, SURFACE);*/ |
|
||||||
/*return (png_image);*/ |
|
||||||
/*}*/ |
|
||||||
|
|
||||||
|
|
||||||
double sigmoid(double x) { |
|
||||||
return exp(x) / (exp(x) + 1); |
|
||||||
} |
|
||||||
|
|
||||||
struct timespec get_now_d() { |
|
||||||
struct timespec now; |
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now); |
|
||||||
if (now.tv_nsec >= 1000000000) { |
|
||||||
now.tv_nsec -= 1000000000; |
|
||||||
} |
|
||||||
return now; |
|
||||||
} |
|
||||||
|
|
||||||
Vect in_view(Vect V) { |
|
||||||
Vect ret; |
|
||||||
ret.x = V.x -viewport_pos.x; |
|
||||||
ret.y = V.y -viewport_pos.y; |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
/* Game Specific rendering functions */ |
|
||||||
void draw_player(SDL_Renderer * ren, int x, int y, bool red) { |
|
||||||
// translate to viewport
|
|
||||||
|
|
||||||
Vect V; |
|
||||||
V.x = x; V.y = y; |
|
||||||
V = in_view(V); |
|
||||||
|
|
||||||
/* draw the player as a coloured rect */ |
|
||||||
SDL_Rect player_rect; |
|
||||||
|
|
||||||
player_rect.x = V.x -10;
|
|
||||||
player_rect.y = V.y -10;
|
|
||||||
|
|
||||||
player_rect.w = 20; |
|
||||||
player_rect.h = 20; |
|
||||||
|
|
||||||
struct colour c = get_scene_watch()->colours.bg; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, c.r, c.g, c.b, 255); |
|
||||||
|
|
||||||
SDL_RenderDrawRect(ren, &player_rect); |
|
||||||
SDL_RenderFillRect(ren, &player_rect); |
|
||||||
// draw strings
|
|
||||||
for (int i = 0; i < player.physics->num_strings; i++) { |
|
||||||
if (!player.physics->strings[i].attached) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
Vect B = {x, y}; |
|
||||||
B = in_view(B); |
|
||||||
Vect E; |
|
||||||
E = in_view(player.physics->strings[i].end_point); |
|
||||||
|
|
||||||
for (int j = -3; j < 3; j++) { |
|
||||||
for (int k = -3; k < 3; k++) { |
|
||||||
SDL_RenderDrawLine(ren, B.x + j, B.y + k, E.x + j, E.y + k); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void draw_floor(SDL_Renderer *ren, FloorPoly *poly, bool down) { |
|
||||||
SDL_Point left; |
|
||||||
SDL_Point right; |
|
||||||
left.x = poly->left.x - viewport_pos.x; |
|
||||||
|
|
||||||
if (left.x > width) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
right.x = poly->right.x - viewport_pos.x; |
|
||||||
if (right.x < 0) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
left.y = poly->left.y - viewport_pos.y; |
|
||||||
right.y = poly->right.y - viewport_pos.y; |
|
||||||
|
|
||||||
if (left.y <= 0 && right.y <= 0) { |
|
||||||
return; |
|
||||||
} |
|
||||||
if (left.y >= height && right.y >= height) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 100,100,100, 255); |
|
||||||
|
|
||||||
int end = down ? height : 0; |
|
||||||
|
|
||||||
double m = (double)(right.y - left.y) / (double)(right.x - left.x); |
|
||||||
double c = (double)left.y - ((double)left.x * m); |
|
||||||
|
|
||||||
for (int i = left.x; i <= right.x; i++) { |
|
||||||
int y = (int)(m * i + c); |
|
||||||
if (y > 0) { |
|
||||||
SDL_RenderDrawLine(ren, i, y, i, end); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
// draw collision poly
|
|
||||||
void draw_collision_poly(SDL_Renderer* ren, Body *body) { |
|
||||||
if (!SHOWCOLLISION) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if (body->colliding) { |
|
||||||
SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); |
|
||||||
} else { |
|
||||||
SDL_SetRenderDrawColor(ren, 0, 255, 0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
// draw strings
|
|
||||||
for (int i = 0; i < body->num_strings; i++) { |
|
||||||
if (!body->strings[i].attached) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
Vect B; |
|
||||||
B = in_view(body->position); |
|
||||||
Vect E; |
|
||||||
E = in_view(body->strings[i].end_point); |
|
||||||
SDL_RenderDrawLine(ren, B.x, B.y, E.x, E.y); |
|
||||||
} |
|
||||||
|
|
||||||
if (body->collision_poly_size == 1) { |
|
||||||
SDL_Rect dot; |
|
||||||
Vect V; |
|
||||||
V.x = body->collision_poly[0].x; |
|
||||||
V.y = body->collision_poly[0].y; |
|
||||||
Vect T = in_view(V); |
|
||||||
dot.x = T.x; |
|
||||||
dot.y = T.y; |
|
||||||
dot.w = 4; |
|
||||||
dot.h = 4; |
|
||||||
SDL_RenderDrawRect(ren, &dot); |
|
||||||
SDL_RenderFillRect(ren, &dot); |
|
||||||
} else if (body->collision_poly_size == 2) { |
|
||||||
int x_st = body->collision_poly[0].x -viewport_pos.x; |
|
||||||
int y_st = body->collision_poly[0].y -viewport_pos.y; |
|
||||||
int x_en = body->collision_poly[1].x -viewport_pos.x; |
|
||||||
int y_en = body->collision_poly[1].y -viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
} else if (body->collision_poly_size > 2) { |
|
||||||
int x_st = body->collision_poly[0].x -viewport_pos.x; |
|
||||||
int y_st = body->collision_poly[0].y -viewport_pos.y; |
|
||||||
int x_en, y_en; |
|
||||||
for (int i = 1; i < body->collision_poly_size; i++) { |
|
||||||
x_en = body->collision_poly[i].x -viewport_pos.x; |
|
||||||
y_en = body->collision_poly[i].y -viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
x_st = x_en; |
|
||||||
y_st = y_en; |
|
||||||
} |
|
||||||
x_en = body->collision_poly[0].x-viewport_pos.x; |
|
||||||
y_en = body->collision_poly[0].y-viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
} |
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
// draw indicator of forces acting on an object
|
|
||||||
void draw_forces(SDL_Renderer *ren, Body *body) { |
|
||||||
if (!SHOWFORCES) { |
|
||||||
return; |
|
||||||
} |
|
||||||
Vect start; |
|
||||||
start.x = (int)body->position.x -viewport_pos.x; |
|
||||||
start.y = (int)body->position.y -viewport_pos.y; |
|
||||||
|
|
||||||
Vect F; |
|
||||||
for (int i = 0; i < body->num_motors; i++) { |
|
||||||
if (!get_motor_active(body, i)) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
F.x += body->motors[i].x; |
|
||||||
F.y += body->motors[i].y; |
|
||||||
Vect end = vect_add(start, F); |
|
||||||
SDL_SetRenderDrawColor(ren, 255,0,0, 255); |
|
||||||
SDL_RenderDrawLine(ren, start.x, start.y, start.x, end.y); |
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,255, 255); |
|
||||||
SDL_RenderDrawLine(ren, start.x, start.y, end.x, start.y); |
|
||||||
} |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
void draw_wall(SDL_Renderer *ren, Wall *wall) { |
|
||||||
SDL_SetRenderDrawColor(ren, 120, 85, 188, 255); |
|
||||||
int x_st, x_en, y_st, y_en; |
|
||||||
x_st = wall->nodes[0].x + wall->physics->position.x -viewport_pos.x; |
|
||||||
y_st = wall->nodes[0].y + wall->physics->position.y -viewport_pos.y; |
|
||||||
for (int i = 1; i < wall->numNodes; i++) { |
|
||||||
x_en = wall->nodes[i].x + wall->physics->position.x -viewport_pos.x; |
|
||||||
y_en = wall->nodes[i].y + wall->physics->position.y -viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
x_st = x_en; |
|
||||||
y_st = y_en; |
|
||||||
} |
|
||||||
x_en = wall->nodes[0].x + wall->physics->position.x -viewport_pos.x; |
|
||||||
y_en = wall->nodes[0].y + wall->physics->position.y -viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
int distance_colour(int x, int y, int x2, int y2, int blackpoint) { |
|
||||||
|
|
||||||
int dist = (int) sqrt((x2 - x)*(x2 - x) + (y2 - y)*(y2 - y) ); |
|
||||||
|
|
||||||
if (dist == 0) { |
|
||||||
return 255; |
|
||||||
} |
|
||||||
if (dist > blackpoint) { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
int frac = blackpoint / dist; |
|
||||||
|
|
||||||
// int frac = 255 * (int) sin((double)dist / blackpoint);
|
|
||||||
if (frac > 255) { |
|
||||||
return 255; |
|
||||||
} |
|
||||||
|
|
||||||
return frac; |
|
||||||
} |
|
||||||
|
|
||||||
void new_update_viewport(Body const * const pl) { |
|
||||||
int const xmargin = 100; // pixels
|
|
||||||
int const ymargin = 100; // pixels
|
|
||||||
int const xmovmagin = width / 4; |
|
||||||
int const ymovmagin = height / 3; |
|
||||||
double const xrange = width - (2 * xmargin); |
|
||||||
double const yrange = height - (2 * ymargin); |
|
||||||
double const x_max = 2; |
|
||||||
double const y_max = 3; |
|
||||||
static Vect target = {}; |
|
||||||
static double dirchange = 0; |
|
||||||
static Vect last_plpos = {}; |
|
||||||
if (last_plpos.x == 0 && last_plpos.y == 0) |
|
||||||
last_plpos = pl->position; |
|
||||||
|
|
||||||
static Vect lmove = {}; |
|
||||||
|
|
||||||
Vect iv = in_view(pl->position); |
|
||||||
|
|
||||||
Vect left_pos = {0, 2 * height / 4}; |
|
||||||
left_pos = vect_add(pl->position, vect_scalar(left_pos, -1)); |
|
||||||
|
|
||||||
Vect right_pos = {7 * (width / 8), 2 * height / 4}; |
|
||||||
right_pos = vect_add(pl->position, vect_scalar(right_pos, -1)); |
|
||||||
|
|
||||||
bool recover = false; |
|
||||||
|
|
||||||
Vect screen_dist = vect_add(in_view(pl->position), vect_scalar(lmove, -1)); |
|
||||||
|
|
||||||
static double swap = 0; |
|
||||||
if (iv.x > width
|
|
||||||
|| (iv.x < 0 |
|
||||||
|| iv.y > height |
|
||||||
|| iv.y < 0))
|
|
||||||
recover = true; |
|
||||||
|
|
||||||
Vect delta = vect_add(vect_scalar(pl->position, -1), last_plpos); |
|
||||||
double dist_change = vect_mag(delta); |
|
||||||
if ((recover) //|| vect_mag((Vect){pl->vel.x, 0}) > 0.4
|
|
||||||
|| (dist_change > width / 100)) { |
|
||||||
if (iv.x < width / 6) { |
|
||||||
target = right_pos; |
|
||||||
} else { |
|
||||||
target = left_pos; |
|
||||||
} |
|
||||||
lmove = target; |
|
||||||
|
|
||||||
last_plpos = pl->position; |
|
||||||
} |
|
||||||
|
|
||||||
if (recover) |
|
||||||
viewport_pos = target; |
|
||||||
// emergency
|
|
||||||
|
|
||||||
/*if (!(iv.x > width / 3 && iv.x < (2 * (width / 3)))) {*/ |
|
||||||
/*if (!(iv.y > height / 3 && iv.y < (2 * (height / 3)))) {*/ |
|
||||||
|
|
||||||
/*if ( true ||*/ |
|
||||||
/*( in_view(pl->position).x > xmargin + xrange */ |
|
||||||
/*|| in_view(pl->position).x < xmargin)*/ |
|
||||||
/*) */ |
|
||||||
|
|
||||||
/*{*/ |
|
||||||
|
|
||||||
|
|
||||||
/*double m = (width / 2) / (2.0 * x_max);*/ |
|
||||||
/*double x = m * v;*/ |
|
||||||
/*target.x = pl->position.x - x;*/ |
|
||||||
|
|
||||||
|
|
||||||
/*}*/ |
|
||||||
|
|
||||||
//target.y = pl->position.y - height/2; // + y;
|
|
||||||
|
|
||||||
/*}*/ |
|
||||||
/*}*/ |
|
||||||
|
|
||||||
double v = pl->vel.x; |
|
||||||
if (v > x_max)
|
|
||||||
v = x_max; |
|
||||||
if (v < -x_max)
|
|
||||||
v = -x_max; |
|
||||||
if (v < 0) |
|
||||||
v = -v; |
|
||||||
|
|
||||||
// move towards target a set proportion
|
|
||||||
Vect urgency = vect_add(target, vect_scalar(pl->position, -1)); |
|
||||||
Vect p = vect_add(target, vect_scalar(viewport_pos, -1)); |
|
||||||
|
|
||||||
double proportion = (sigmoid(time_delta) / 100); |
|
||||||
proportion = 2 * (pl->vel.x * pl->vel.x / (width)); |
|
||||||
proportion = proportion < 0 ? -proportion : proportion; |
|
||||||
|
|
||||||
proportion > 0.4 ? proportion = 0.4 : 0; |
|
||||||
proportion < 0 ? proportion = 0.000001 : 0; |
|
||||||
|
|
||||||
p = vect_scalar(p, proportion); |
|
||||||
viewport_pos = vect_add(viewport_pos, p); |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void update_viewport(Body *pl) { |
|
||||||
float xmargin = 0.5; |
|
||||||
float ymargin = 0.2; |
|
||||||
|
|
||||||
if (pl->position.x - viewport_pos.x > (1-xmargin) * width) { |
|
||||||
viewport_pos.x = - ((1-xmargin) * width - pl->position.x); |
|
||||||
} |
|
||||||
|
|
||||||
if (pl->position.x - viewport_pos.x < xmargin * width) { |
|
||||||
viewport_pos.x = -(xmargin * width - pl->position.x); |
|
||||||
} |
|
||||||
|
|
||||||
if (pl->position.y - viewport_pos.y > (1-ymargin) * height) { |
|
||||||
viewport_pos.y = -((1-ymargin) * height - pl->position.y); |
|
||||||
} |
|
||||||
|
|
||||||
if (pl->position.y - viewport_pos.y < ymargin * height) { |
|
||||||
viewport_pos.y = -(ymargin * height - pl->position.y); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void accel_update_viewport(Body *pl) { |
|
||||||
const double accel = 0.0001; |
|
||||||
const float xmargin = 0.5; |
|
||||||
const float ymargin = 0.2; |
|
||||||
|
|
||||||
static Vect target_pos = (Vect) {.x=0, .y=0}; |
|
||||||
static Vect vel = (Vect) {.x=0.0, .y=0.0}; |
|
||||||
|
|
||||||
|
|
||||||
if (pl->position.x - viewport_pos.x > (1-xmargin) * width) { |
|
||||||
target_pos.x = - ((1-xmargin) * width - pl->position.x); |
|
||||||
}
|
|
||||||
|
|
||||||
if (pl->position.x - target_pos.x < xmargin * width) { |
|
||||||
target_pos.x = -(xmargin * width - pl->position.x); |
|
||||||
} |
|
||||||
|
|
||||||
if (pl->position.y - target_pos.y > (1-ymargin) * height) { |
|
||||||
target_pos.y = -((1-ymargin) * height - pl->position.y); |
|
||||||
}
|
|
||||||
|
|
||||||
if (pl->position.y - target_pos.y < ymargin * height) { |
|
||||||
target_pos.y = -(ymargin * height - pl->position.y); |
|
||||||
} |
|
||||||
|
|
||||||
viewport_pos = target_pos; |
|
||||||
return; |
|
||||||
|
|
||||||
Vect delta = vect_add(target_pos, vect_scalar(viewport_pos, -1)); |
|
||||||
printf("d %f %f\n", delta.x, delta.y); |
|
||||||
printf("d %f\n", vect_mag(delta)); |
|
||||||
|
|
||||||
if ((vect_mag(delta) < 0.001 )) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
Vect dir = vect_scalar(delta, 1/vect_mag(delta)); |
|
||||||
Vect vel_delta = vect_scalar(dir, accel * time_delta); |
|
||||||
vel = vect_add(vel, vel_delta); |
|
||||||
|
|
||||||
Vect pos_delta = vect_scalar(vel, time_delta/2); |
|
||||||
|
|
||||||
viewport_pos = vect_add(viewport_pos, pos_delta); |
|
||||||
} |
|
||||||
|
|
||||||
double interpolate_h(Vect left, Vect right, double x) { |
|
||||||
static Vect v; |
|
||||||
|
|
||||||
double m = (double)(right.y - left.y) / (double)(right.x - left.x);
|
|
||||||
double c = (double)left.y - ((double)left.x * m);
|
|
||||||
|
|
||||||
return x * m + c; |
|
||||||
} |
|
||||||
|
|
||||||
void draw_environment(SDL_Renderer * ren, const struct environment *scene) { |
|
||||||
struct colour c1 = scene->colours.bg; |
|
||||||
struct colour c2 = scene->colours.fg1; |
|
||||||
struct colour c3 = scene->colours.fg2; |
|
||||||
struct colour c4 = scene->colours.fg3; |
|
||||||
|
|
||||||
/*c1->r = 255;*/ |
|
||||||
/*c2->g = 255;*/ |
|
||||||
/*c3->b = 255;*/ |
|
||||||
/*c4->g = 255;*/ |
|
||||||
/*c4->b = 255;*/ |
|
||||||
|
|
||||||
// background colour
|
|
||||||
SDL_SetRenderDrawColor(ren, c1.r, c1.g, c1.b, 255); |
|
||||||
/*SDL_SetRenderDrawColor(ren, 255, 0, 0, 255);*/ |
|
||||||
|
|
||||||
SDL_Rect rect;
|
|
||||||
rect.x = 0; |
|
||||||
rect.y = 0; |
|
||||||
rect.w = width; |
|
||||||
rect.h = height; |
|
||||||
SDL_RenderFillRect(ren, &rect); |
|
||||||
|
|
||||||
/*
|
|
||||||
* double m = (double)(right.y - left.y) / (double)(right.x - left.x); |
|
||||||
* double c = (double)left.y - ((double)left.x * m); |
|
||||||
* |
|
||||||
* for (int i = left.x; i <= right.x; i++) { |
|
||||||
* int y = (int)(m * i + c); |
|
||||||
* if (y > 0) { |
|
||||||
* SDL_RenderDrawLine(ren, i, y, i, end); |
|
||||||
* } |
|
||||||
* } |
|
||||||
*/ |
|
||||||
|
|
||||||
int k = 0; |
|
||||||
// printf("from 0 to (room tiles) %d - 1, res %d width %d\n", E_ROOM_TILES, E_ROOM_RES, E_ROOM_WIDTH);
|
|
||||||
for (int i = 0; i < E_ROOM_TILES - 1; i++) { |
|
||||||
for (int j = 0; j < E_ROOM_RES; j++) { |
|
||||||
k++; |
|
||||||
Vect *left; |
|
||||||
Vect *right; |
|
||||||
|
|
||||||
int x = (i * E_ROOM_RES) + j; |
|
||||||
if (x - viewport_pos.x > width) { |
|
||||||
break; |
|
||||||
} |
|
||||||
if (x - viewport_pos.x < 0) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
left = arlst_get(&scene->ceil, i); |
|
||||||
right = arlst_get(&scene->ceil, i+1); |
|
||||||
|
|
||||||
int y0 = interpolate_h(*left, *right, x) - viewport_pos.y; |
|
||||||
|
|
||||||
left = arlst_get(&scene->bg1, i); |
|
||||||
right = arlst_get(&scene->bg1, i+1); |
|
||||||
|
|
||||||
int y1 = interpolate_h(*left, *right, x) - viewport_pos.y; |
|
||||||
|
|
||||||
left = arlst_get(&scene->bg2, i); |
|
||||||
right = arlst_get(&scene->bg2, i+1); |
|
||||||
|
|
||||||
int y2 = interpolate_h(*left, *right, x) - viewport_pos.y; |
|
||||||
|
|
||||||
left = arlst_get(&scene->floor, i); |
|
||||||
right = arlst_get(&scene->floor, i+1); |
|
||||||
|
|
||||||
int y3 = interpolate_h(*left, *right, x) - viewport_pos.y; |
|
||||||
|
|
||||||
x = x - viewport_pos.x; |
|
||||||
/*printf("x: %d, ", x);*/ |
|
||||||
/*printf("y: %d %d %d %d\n", y0, y1, y2, y3);*/ |
|
||||||
|
|
||||||
// 3. bg2 to floor
|
|
||||||
SDL_SetRenderDrawColor(ren, c4.r, c4.g, c4.b, 255); |
|
||||||
SDL_RenderDrawLine(ren, x, y2, x, y3); |
|
||||||
|
|
||||||
// 1. ceil to bg1
|
|
||||||
SDL_SetRenderDrawColor(ren, c2.r, c2.g, c2.b, 255); |
|
||||||
SDL_RenderDrawLine(ren, x, y0, x, y1); |
|
||||||
|
|
||||||
// 2. bg1 to bg2
|
|
||||||
SDL_SetRenderDrawColor(ren, c3.r, c3.g, c3.b, 255); |
|
||||||
SDL_RenderDrawLine(ren, x, y1, x, y2); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void draw_text(SDL_Renderer *rend, Vect pos, struct colour colour, char *text) { |
|
||||||
static SDL_Renderer *ren = NULL; |
|
||||||
static TTF_Font* font = NULL; |
|
||||||
if (!font) { |
|
||||||
font = TTF_OpenFont("res/TerminusTTF.ttf", 44); |
|
||||||
const char *err = SDL_GetError(); |
|
||||||
if (err) { |
|
||||||
printf("%s\n", err); |
|
||||||
} |
|
||||||
} |
|
||||||
if (!ren) { |
|
||||||
ren = rend; |
|
||||||
} |
|
||||||
|
|
||||||
SDL_Colour sdl_col = {colour.r, colour.g, colour.b, 255};
|
|
||||||
SDL_Rect position = {.x = pos.x, .y = pos.y}; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, colour.r, colour.g, colour.b, 255); |
|
||||||
SDL_Surface *surf = TTF_RenderText_Solid(font, text, sdl_col); |
|
||||||
|
|
||||||
SDL_Texture *texture = SDL_CreateTextureFromSurface(ren, surf); |
|
||||||
SDL_QueryTexture(texture, NULL, NULL, &position.w, &position.h); |
|
||||||
SDL_RenderCopy(ren, texture, NULL, &position); |
|
||||||
|
|
||||||
SDL_DestroyTexture(texture); |
|
||||||
SDL_FreeSurface(surf); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void draw_level_chooser_tbox(SDL_Renderer *ren) { |
|
||||||
|
|
||||||
char string[250]; |
|
||||||
snprintf(string, 250,"GOTO LEVEL: %s", gameui.currently_bound_textbox->text_input); |
|
||||||
|
|
||||||
const struct environment *scene = get_scene_watch(); |
|
||||||
|
|
||||||
Vect pos = {.x= width - (width / 4), .y = height - (height / 10)}; |
|
||||||
draw_text(ren, pos, scene->colours.fg1, string); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int draw_end_screen(SDL_Renderer *ren) { |
|
||||||
const struct environment *scene = get_scene_watch(); |
|
||||||
|
|
||||||
struct colour bg = scene->colours.bg; |
|
||||||
struct colour colour = scene->colours.fg1; |
|
||||||
struct colour_pallete pal = scene->colours; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, bg.r, bg.g, bg.b,255); |
|
||||||
|
|
||||||
SDL_RenderClear(ren); |
|
||||||
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, pal.fg2.r, pal.fg2.g, pal.fg2.b,255); |
|
||||||
for (int i = width - 300; i < width; i++) { |
|
||||||
SDL_RenderDrawLine(ren, i, height, width, height - i); |
|
||||||
if (!(i % 240)) { |
|
||||||
SDL_SetRenderDrawColor(ren, pal.fg3.r, pal.fg3.g, pal.fg3.b,255); |
|
||||||
} |
|
||||||
if (!(i % 350)) { |
|
||||||
SDL_SetRenderDrawColor(ren, pal.fg1.r, pal.fg1.g, pal.fg1.b,255); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int margin = height / 10; |
|
||||||
// Vect position = {.x = width - width / 10, .y = height - margin};
|
|
||||||
|
|
||||||
long fastest = draw_watch.best_time; |
|
||||||
|
|
||||||
int minutes = level_time / 60000; |
|
||||||
float seconds = level_time * 0.001; |
|
||||||
char time_string[250]; |
|
||||||
|
|
||||||
|
|
||||||
char * end_str = "level over."; |
|
||||||
|
|
||||||
Vect position = {.x = width/4, .y = height / 4}; |
|
||||||
draw_text(ren, position, colour, end_str); |
|
||||||
position.y += 60; |
|
||||||
|
|
||||||
char level_string[250]; |
|
||||||
snprintf(level_string, 250,"course: %d", level); |
|
||||||
draw_text(ren, position, colour, level_string); |
|
||||||
position.y += 40; |
|
||||||
|
|
||||||
char fastest_time[250]; |
|
||||||
minutes = fastest / 60000; |
|
||||||
seconds = fastest * 0.001; |
|
||||||
if (fastest > 0) { |
|
||||||
snprintf(fastest_time, 250, "old best time: %d:%.4f", minutes, seconds); |
|
||||||
draw_text(ren, position, colour, fastest_time); |
|
||||||
position.y += 40; |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
char qual_str[250]; |
|
||||||
snprintf(qual_str, 250, "physics quality: %d", quality); |
|
||||||
draw_text(ren, position, colour, qual_str); |
|
||||||
position.y += 40; |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
minutes = level_time / 60000; |
|
||||||
seconds = level_time * 0.001; |
|
||||||
if (level_time > fastest) { |
|
||||||
// base time not set yet.
|
|
||||||
snprintf(time_string, 250, "TIME: %d:%.4f", minutes, seconds); |
|
||||||
} else { |
|
||||||
snprintf(time_string, 250, "NEW BEST TIME: %d:%.4f", minutes, seconds); |
|
||||||
} |
|
||||||
|
|
||||||
Vect position2 = {.x = position.x + width/3, .y = 60 + height / 4}; |
|
||||||
|
|
||||||
if (fastest > 0) { |
|
||||||
//position.y += 40;
|
|
||||||
long diff = level_time - fastest; |
|
||||||
char diff_str[250]; |
|
||||||
minutes = diff / 60000; |
|
||||||
seconds = diff * 0.001; |
|
||||||
if (minutes > 0) { |
|
||||||
snprintf(diff_str, 250, "DIFF: %d:%.4f", minutes, fabs(seconds)); |
|
||||||
} else { |
|
||||||
snprintf(diff_str, 250, "DIFF: %.4f s", seconds); |
|
||||||
} |
|
||||||
|
|
||||||
draw_text(ren, position2, colour, diff_str); |
|
||||||
position2.y += 40; |
|
||||||
} |
|
||||||
|
|
||||||
draw_text(ren, position2, colour, time_string); |
|
||||||
|
|
||||||
position.y += 200; |
|
||||||
char * ct_str = "press any key to continue"; |
|
||||||
draw_text(ren, position, colour, ct_str); |
|
||||||
|
|
||||||
SDL_RenderPresent(ren); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void draw_level_time(SDL_Renderer *ren, const struct environment * e) { |
|
||||||
|
|
||||||
int margin = height / 10; |
|
||||||
|
|
||||||
struct colour colour = e->colours.fg1; |
|
||||||
|
|
||||||
int minutes = level_time / 60000; |
|
||||||
float seconds = level_time * 0.001; |
|
||||||
char time_string[250]; |
|
||||||
snprintf(time_string, 250, "time: %d:%.4f", minutes, seconds); |
|
||||||
|
|
||||||
char level_string[250]; |
|
||||||
snprintf(level_string, 250,"course: %d", level); |
|
||||||
|
|
||||||
Vect position = {.x = margin, .y = height - margin}; |
|
||||||
draw_text(ren, position, colour, level_string); |
|
||||||
position.y += 40; |
|
||||||
draw_text(ren, position, colour, time_string); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void draw_mute_button(SDL_Renderer *ren) { |
|
||||||
|
|
||||||
struct colour c = get_scene_watch()->colours.fg1; |
|
||||||
struct colour i = get_scene_watch()->colours.bg; |
|
||||||
|
|
||||||
if (mute_button.held) { |
|
||||||
struct colour t = c; |
|
||||||
c = i;
|
|
||||||
i = t; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
SDL_Rect rect; |
|
||||||
|
|
||||||
rect.x = mute_button.x; |
|
||||||
rect.y = mute_button.y;
|
|
||||||
rect.w = mute_button.w; |
|
||||||
rect.h = mute_button.h; |
|
||||||
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, c.r, c.g, c.b, 255); |
|
||||||
SDL_RenderFillRect(ren, &rect); |
|
||||||
|
|
||||||
rect.x += mute_button.w / 6; |
|
||||||
rect.y += mute_button.w / 4; |
|
||||||
rect.w = mute_button.w / 5; |
|
||||||
rect.h = mute_button.h / 2; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, i.r, i.g, i.b, 255); |
|
||||||
SDL_RenderFillRect(ren, &rect); |
|
||||||
|
|
||||||
int j = 0; |
|
||||||
for (int i = rect.x + rect.w; i < rect.x + rect.w + mute_button.w / 5; i++) { |
|
||||||
SDL_RenderDrawLine(ren, i, rect.y + j + rect.h, i, rect.y - j); |
|
||||||
j++; |
|
||||||
} |
|
||||||
|
|
||||||
j -= 8; |
|
||||||
int bars = 0; |
|
||||||
int bar_width = mute_button.w / 6; |
|
||||||
if (!mute_button.state) { |
|
||||||
for (int i = rect.x + rect.w + mute_button.w / 5;
|
|
||||||
i < mute_button.x + mute_button.w - 5; i++) { |
|
||||||
if ((bars++) % bar_width >= bar_width / 2) { |
|
||||||
SDL_RenderDrawLine(ren, i, rect.y + j + rect.h, i, rect.y - j); |
|
||||||
} |
|
||||||
if (i % 8 == 0) j += 4; |
|
||||||
|
|
||||||
} |
|
||||||
} else { |
|
||||||
int w = mute_button.w / 5; |
|
||||||
int i = rect.x + rect.w + mute_button.w / 5 + w/2; |
|
||||||
int j = rect.y + w / 2; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
i += 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
i -= 1; |
|
||||||
|
|
||||||
j += 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
j -= 1; |
|
||||||
|
|
||||||
j += 1; |
|
||||||
i += 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
j -= 1; |
|
||||||
i -= 1; |
|
||||||
|
|
||||||
i -= 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
i += 1; |
|
||||||
|
|
||||||
j -= 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
j += 1; |
|
||||||
|
|
||||||
j -= 1; |
|
||||||
i -= 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
j += 1; |
|
||||||
i += 1; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void draw_pause_screen(SDL_Renderer *ren, struct environment *e) { |
|
||||||
|
|
||||||
char *te[] = { "GAME PAUSED.", |
|
||||||
"controls", |
|
||||||
"________", |
|
||||||
"pause/unpause: esc", |
|
||||||
"grapple: right click", |
|
||||||
"grapple and pull: left click", |
|
||||||
"go to level: g", |
|
||||||
"mute/unmute: m", |
|
||||||
"quit: q" |
|
||||||
}; |
|
||||||
|
|
||||||
struct colour textc = e->colours.fg1; |
|
||||||
struct colour bg = e->colours.bg; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, bg.r, bg.g, bg.b, 255); |
|
||||||
int boxwidth = 360; |
|
||||||
int boxheight = 348; |
|
||||||
int box_x = (2 * width / 3) - (boxwidth / 2); |
|
||||||
int box_y = (height - boxheight) / 2; |
|
||||||
SDL_Rect r = {.w = boxwidth, .h = boxheight, .x = box_x, .y = box_y}; |
|
||||||
SDL_RenderFillRect(ren, &r); |
|
||||||
|
|
||||||
Vect p = {.x = box_x + 10, .y = box_y + 10}; |
|
||||||
draw_text(ren, p, textc, te[0]); |
|
||||||
p.y += 60; |
|
||||||
|
|
||||||
draw_text(ren, p, textc, te[1]); |
|
||||||
p.y += 5; |
|
||||||
draw_text(ren, p, textc, te[2]); |
|
||||||
p.y += 35; |
|
||||||
|
|
||||||
draw_text(ren, p, textc, te[3]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text(ren, p, textc, te[4]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text(ren, p, textc, te[5]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text(ren, p, textc, te[6]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text(ren, p, textc, te[7]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text(ren, p, textc, te[8]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void redraw_buffer(SDL_Renderer * ren) { |
|
||||||
static int mousex = 0; |
|
||||||
static int mousey = 0; |
|
||||||
static int newmousex = 0;
|
|
||||||
static int newmousey = 0; |
|
||||||
static SDL_Point *bgPixels[256]; |
|
||||||
static int numpixels[256]; |
|
||||||
|
|
||||||
/*if (!width && !height) {*/ |
|
||||||
/*for (int i = 0; i < 256; i++) {*/ |
|
||||||
/*bgPixels[i] = malloc(sizeof(SDL_Point) * width * height);*/ |
|
||||||
/*memset(bgPixels[i], 0, sizeof(SDL_Point) * width * height);*/ |
|
||||||
/*memset(numpixels, 0, (sizeof(int) * 256));*/ |
|
||||||
/*}*/ |
|
||||||
/*}*/ |
|
||||||
|
|
||||||
int col = 0; |
|
||||||
Body lplayer; |
|
||||||
|
|
||||||
if (SDL_LockMutex(player.physics->lock) == 0){ |
|
||||||
lplayer = *player.physics; |
|
||||||
update_viewport(&lplayer); |
|
||||||
} else { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
static struct timespec last = {}; |
|
||||||
static struct timespec now; |
|
||||||
now = get_now_d(); |
|
||||||
time_delta = now.tv_nsec - last.tv_nsec; |
|
||||||
time_delta *= 0.000001; // convert to ms from ns
|
|
||||||
|
|
||||||
last = now; |
|
||||||
|
|
||||||
//SDL_GetMouseState(&newmousex, &newmousey);
|
|
||||||
|
|
||||||
const struct environment* scene = get_scene_watch(); |
|
||||||
draw_environment(ren, scene); |
|
||||||
draw_level_time(ren, scene); |
|
||||||
SDL_UnlockMutex(player.physics->lock); |
|
||||||
|
|
||||||
for (int i=0; i < world.items.size; i++) { |
|
||||||
world_thing thing; |
|
||||||
thing = world.get(i); |
|
||||||
|
|
||||||
switch (thing.kind) { |
|
||||||
case STATIC_WALL_W: |
|
||||||
draw_wall(ren, thing.wall); |
|
||||||
draw_collision_poly(ren, thing.wall->physics); |
|
||||||
continue; |
|
||||||
case FLOOR: |
|
||||||
for (int i = 0; i < thing.floor->numPolys; i++) { |
|
||||||
draw_floor(ren, &thing.floor->polys[i], true); |
|
||||||
draw_collision_poly(ren, thing.floor->polys[i].physics); |
|
||||||
} |
|
||||||
continue; |
|
||||||
case CEILING: |
|
||||||
for (int i = 0; i < thing.floor->numPolys; i++) { |
|
||||||
draw_floor(ren, &thing.floor->polys[i], false); |
|
||||||
draw_collision_poly(ren, thing.floor->polys[i].physics); |
|
||||||
} |
|
||||||
continue; |
|
||||||
case ROOM_W: |
|
||||||
for (int i = 0; i < thing.room->ceil.numItems; i++) { |
|
||||||
draw_collision_poly(ren, thing.room->ceil.items[i]); |
|
||||||
} |
|
||||||
for (int i = 0; i < thing.room->floor.numItems; i++) { |
|
||||||
draw_collision_poly(ren, thing.room->floor.items[i]); |
|
||||||
} |
|
||||||
default: |
|
||||||
continue; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
draw_player(ren, lplayer.position.x, lplayer.position.y,
|
|
||||||
lplayer.colliding); |
|
||||||
draw_collision_poly(ren, &lplayer); |
|
||||||
draw_forces(ren, &lplayer); |
|
||||||
draw_mute_button(ren); |
|
||||||
|
|
||||||
if (gameui.currently_bound_textbox) { |
|
||||||
draw_level_chooser_tbox(ren); |
|
||||||
} |
|
||||||
|
|
||||||
if (game_paused) { |
|
||||||
SDL_Rect r = {.x = 0, .y = 0, .w = width, .h = height}; |
|
||||||
SDL_SetRenderDrawColor(ren, 0, 0, 0, 90); |
|
||||||
SDL_RenderFillRect(ren, &r); |
|
||||||
if (in_game) |
|
||||||
draw_pause_screen(ren, scene); |
|
||||||
} |
|
||||||
|
|
||||||
/*if (newmousex != mousex || newmousey != mousey) {*/ /*mousey = newmousey;*/ |
|
||||||
/*mousex = newmousex;*/ |
|
||||||
/*for (int i = 0; i < 256; i++) {*/ |
|
||||||
/*memset(bgPixels[i], 0, sizeof(SDL_Point) * width * height);*/ |
|
||||||
/*memset(numpixels, 0, (sizeof(int) * 256));*/ |
|
||||||
/*}*/ |
|
||||||
/*for (int i=0; i < width; i++) {*/ |
|
||||||
/*for (int j = 0; j < height; j++) {*/ |
|
||||||
/*col = distance_colour(i, j, mousex, mousey, 10000);*/ |
|
||||||
|
|
||||||
/*SDL_Point *row = bgPixels[col];*/ |
|
||||||
/*SDL_Point point;*/ |
|
||||||
/*point.x = i;*/ |
|
||||||
/*point.y = j;*/ |
|
||||||
/*row[numpixels[col]] = point;*/ |
|
||||||
/*numpixels[col] += 1;*/ |
|
||||||
|
|
||||||
/*}*/ |
|
||||||
/*}*/ |
|
||||||
/*}*/ |
|
||||||
|
|
||||||
/*for (int i = 0; i < 255; i++) {*/ |
|
||||||
/*SDL_Point *row = bgPixels[i];*/ |
|
||||||
/*col = i;*/ |
|
||||||
/*SDL_SetRenderDrawColor(ren, col, col, col, 255);*/ |
|
||||||
/*SDL_RenderDrawPoints(ren, row, numpixels[i]);*/ |
|
||||||
/*}*/ |
|
||||||
|
|
||||||
} |
|
||||||
|
|
@ -1,82 +0,0 @@ |
|||||||
#ifndef _DEFGAME |
|
||||||
#define _DEFGAME |
|
||||||
|
|
||||||
#include "environment.h" |
|
||||||
#include "datatypes.h" |
|
||||||
#include "vect.h" |
|
||||||
#include "controlscheme.h" |
|
||||||
#include "colours.h" |
|
||||||
#include "types.h" |
|
||||||
#include "draw.h" |
|
||||||
|
|
||||||
extern GlobWorld world; |
|
||||||
extern int level; |
|
||||||
extern bool in_game; |
|
||||||
extern int quality; |
|
||||||
|
|
||||||
struct draw_watcher { |
|
||||||
long best_time; |
|
||||||
bool finish_level; |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
struct ui_state { |
|
||||||
struct textbox_info *currently_bound_textbox; |
|
||||||
int goto_new_level; |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
enum TextBoxId { |
|
||||||
TB_LEVEL_CHOOSER = 0 |
|
||||||
}; |
|
||||||
|
|
||||||
struct textbox_info { |
|
||||||
enum TextBoxId id; |
|
||||||
bool capture_input_text_field; |
|
||||||
char text_input[32]; |
|
||||||
int text_input_bufpos; |
|
||||||
void (*close_callback)(struct textbox_info *textbox, void*callback); |
|
||||||
}; |
|
||||||
|
|
||||||
extern struct draw_watcher draw_watch; |
|
||||||
extern struct textbox_info* texboxes; |
|
||||||
extern struct ui_state gameui; |
|
||||||
|
|
||||||
|
|
||||||
void handle_input_event(SDL_Event event); |
|
||||||
|
|
||||||
// add a motor to the world
|
|
||||||
void add_motor(Body *thing, double x, double y);
|
|
||||||
|
|
||||||
bool get_motor_active(Body *thing, int i);
|
|
||||||
|
|
||||||
/* temporary storage variable *n should be initialised to the seed value */ |
|
||||||
int get_rand(int *n);
|
|
||||||
|
|
||||||
void next_level(int lvl);
|
|
||||||
|
|
||||||
int step(void); |
|
||||||
|
|
||||||
struct sg_times_list { |
|
||||||
long *times; |
|
||||||
int size; |
|
||||||
int capacity; |
|
||||||
void (*sort)(void); |
|
||||||
char *filename; |
|
||||||
}; |
|
||||||
|
|
||||||
int load_score_times(char *filename);
|
|
||||||
|
|
||||||
|
|
||||||
/* array of all the things in the world and their kinds */ |
|
||||||
|
|
||||||
extern struct sg_times_list save_times_lst; |
|
||||||
int add_time(long time);
|
|
||||||
int write_times(void);
|
|
||||||
extern void startgame(SDL_Renderer * ren) ; |
|
||||||
extern void process_keydown(SDL_Keysym key); |
|
||||||
extern void process_keyup(SDL_Keysym key); |
|
||||||
extern player_st player; |
|
||||||
extern long level_time; |
|
||||||
extern bool game_paused; |
|
||||||
#endif |
|
@ -1,185 +0,0 @@ |
|||||||
#include <SDL_mutex.h> |
|
||||||
#include <SDL_audio.h> |
|
||||||
#include <SDL_scancode.h> |
|
||||||
#include <SDL_mixer.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <stdlib.h> |
|
||||||
#include <string.h> |
|
||||||
#include <SDL.h> |
|
||||||
#include <string.h> |
|
||||||
#include <time.h> |
|
||||||
#include <stdbool.h> |
|
||||||
#include <math.h> |
|
||||||
|
|
||||||
#include "audio.h" // only for mkdirat lol |
|
||||||
#include <fcntl.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
|
|
||||||
#include "game.h" |
|
||||||
#include "draw.h" |
|
||||||
#include "types.h" |
|
||||||
|
|
||||||
const int screen_width = 800; |
|
||||||
const int screen_height = 600; |
|
||||||
|
|
||||||
|
|
||||||
SDL_sem *resume; |
|
||||||
|
|
||||||
|
|
||||||
struct SDL_Window* make_window(void) { |
|
||||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
|
||||||
printf("error initializing SDL: %s\n", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return SDL_CreateWindow("space_game",
|
|
||||||
SDL_WINDOWPOS_CENTERED,
|
|
||||||
SDL_WINDOWPOS_CENTERED,
|
|
||||||
0, 0,
|
|
||||||
SDL_WINDOW_FULLSCREEN_DESKTOP);
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void redraw(struct SDL_Renderer * ren) { |
|
||||||
SDL_RenderClear(ren); |
|
||||||
redraw_buffer(ren); |
|
||||||
SDL_RenderPresent(ren); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void godophysics(void) { |
|
||||||
int lvl; |
|
||||||
if ((lvl = step())) { |
|
||||||
// display end level screen
|
|
||||||
in_game = false; |
|
||||||
game_paused = true; |
|
||||||
SDL_Delay(300); |
|
||||||
SDL_SemWait(resume); |
|
||||||
#ifdef SCORE_SYSTEM |
|
||||||
add_time(level_time); |
|
||||||
#endif |
|
||||||
|
|
||||||
SDL_LockMutex(player.physics->lock); |
|
||||||
next_level(lvl); |
|
||||||
in_game = true; |
|
||||||
SDL_UnlockMutex(player.physics->lock); |
|
||||||
game_paused = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
int physics_loop(void *ptr) { |
|
||||||
game_paused = 1; |
|
||||||
while (1) { |
|
||||||
godophysics(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int game(void) { |
|
||||||
//SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "2" );
|
|
||||||
|
|
||||||
SDL_Window * win = make_window(); |
|
||||||
SDL_Renderer * ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); |
|
||||||
// | SDL_RENDERER_PRESENTVSYNC);
|
|
||||||
SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); |
|
||||||
|
|
||||||
|
|
||||||
in_game = true; |
|
||||||
resume = SDL_CreateSemaphore(0); |
|
||||||
|
|
||||||
// IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
|
|
||||||
|
|
||||||
if (ren == NULL) { |
|
||||||
SDL_DestroyWindow(win); |
|
||||||
SDL_Quit(); |
|
||||||
} |
|
||||||
|
|
||||||
TTF_Init(); |
|
||||||
|
|
||||||
int close = 0; |
|
||||||
|
|
||||||
//draw_pictures(ren);
|
|
||||||
|
|
||||||
SDL_Thread *physics_thread; |
|
||||||
int ignore; |
|
||||||
|
|
||||||
startgame(ren); |
|
||||||
|
|
||||||
physics_thread = SDL_CreateThread(physics_loop, "physics", (void *)ren); |
|
||||||
|
|
||||||
int count = 0; |
|
||||||
|
|
||||||
while (!close) { |
|
||||||
SDL_Event event;
|
|
||||||
while(SDL_PollEvent(&event)) { |
|
||||||
switch (event.type) { |
|
||||||
case SDL_QUIT: |
|
||||||
goto endfunc; |
|
||||||
case SDL_KEYDOWN: |
|
||||||
if (event.key.keysym.scancode == SDL_SCANCODE_Q) { |
|
||||||
goto endfunc; |
|
||||||
} |
|
||||||
if (!in_game && !SDL_SemValue(resume)) { |
|
||||||
SDL_SemPost(resume); |
|
||||||
} |
|
||||||
case SDL_KEYUP: |
|
||||||
case SDL_MOUSEBUTTONDOWN: |
|
||||||
if (!in_game && !SDL_SemValue(resume)) { |
|
||||||
SDL_SemPost(resume); |
|
||||||
break; |
|
||||||
} |
|
||||||
case SDL_MOUSEBUTTONUP: |
|
||||||
handle_input_event (event); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (!in_game && draw_watch.finish_level) { |
|
||||||
draw_end_screen(ren); |
|
||||||
} else { |
|
||||||
redraw(ren); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
endfunc: |
|
||||||
|
|
||||||
SDL_DestroyRenderer(ren); |
|
||||||
SDL_DestroyWindow(win); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int main (int argc, char** argv) { |
|
||||||
|
|
||||||
#ifdef __linux__ |
|
||||||
mkdirat(AT_FDCWD, "saves", 0777); |
|
||||||
#elif WIN32 |
|
||||||
if (access("saves", 0) == 0) { |
|
||||||
struct stat status; |
|
||||||
stat("saves", &status ); |
|
||||||
if ((status.st_mode & S_IFDIR) == 0) { |
|
||||||
_mkdir("saves"); |
|
||||||
} |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
game(); |
|
||||||
|
|
||||||
SDL_Quit(); |
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO:
|
|
||||||
* - Allow setting and saving/loading differnet control schemes |
|
||||||
* - Allow starting a specific level |
|
||||||
* - Allow adjusging level lengths? |
|
||||||
* - Ensure next_level doesn't leak memory |
|
||||||
* - fix that weird jitter |
|
||||||
* - make the end of level look sane |
|
||||||
* - restart level |
|
||||||
* - make sure goto level doesn't log an end-0f-level time |
|
||||||
*/ |
|
||||||
|
|
@ -1,61 +0,0 @@ |
|||||||
#include <SDL.h> |
|
||||||
#include <stdio.h> |
|
||||||
|
|
||||||
int main(int /*argc*/, char* /*argv*/[]) { |
|
||||||
|
|
||||||
SDL_Window *window; // Declare a pointer
|
|
||||||
|
|
||||||
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
|
|
||||||
|
|
||||||
// Create an application window with the following settings:
|
|
||||||
window = SDL_CreateWindow( |
|
||||||
"An SDL2 window", // window title
|
|
||||||
SDL_WINDOWPOS_UNDEFINED, // initial x position
|
|
||||||
SDL_WINDOWPOS_UNDEFINED, // initial y position
|
|
||||||
640, // width, in pixels
|
|
||||||
480, // height, in pixels
|
|
||||||
SDL_WINDOW_OPENGL // flags - see below
|
|
||||||
); |
|
||||||
|
|
||||||
// Check that the window was successfully created
|
|
||||||
if (window == NULL) { |
|
||||||
// In the case that the window could not be made...
|
|
||||||
printf("Could not create window: %s\n", SDL_GetError()); |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
// The window is open: could enter program loop here (see SDL_PollEvent())
|
|
||||||
// Setup renderer
|
|
||||||
SDL_Renderer* renderer = NULL; |
|
||||||
renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED); |
|
||||||
|
|
||||||
// Set render color to red ( background will be rendered in this color )
|
|
||||||
SDL_SetRenderDrawColor( renderer, 255, 0, 0, 255 ); |
|
||||||
|
|
||||||
// Clear winow
|
|
||||||
SDL_RenderClear( renderer ); |
|
||||||
|
|
||||||
// bouyatest
|
|
||||||
|
|
||||||
// Creat a rect at pos ( 50, 50 ) that's 50 pixels wide and 50 pixels high.
|
|
||||||
SDL_Rect r; |
|
||||||
r.x = 50; |
|
||||||
r.y = 50; |
|
||||||
r.w = 500; |
|
||||||
r.h = 500; |
|
||||||
|
|
||||||
// Set render color to blue ( rect will be rendered in this color )
|
|
||||||
SDL_SetRenderDrawColor( renderer, 0, 200, 255, 255 ); |
|
||||||
|
|
||||||
// Render the rect to the screen
|
|
||||||
SDL_RenderPresent(renderer); |
|
||||||
|
|
||||||
SDL_Delay(1000); // Pause execution for 3000 milliseconds, for example
|
|
||||||
|
|
||||||
// Close and destroy the window
|
|
||||||
SDL_DestroyWindow(window); |
|
||||||
|
|
||||||
// Clean up
|
|
||||||
SDL_Quit(); |
|
||||||
return 0; |
|
||||||
} |
|
@ -1 +1 @@ |
|||||||
Subproject commit ebf612394a92e9f697ed56c55fc236cb72b511c7 |
Subproject commit e2078d705069515d84b934c92ff99f55add77036 |
@ -0,0 +1,14 @@ |
|||||||
|
|
||||||
|
#include "controlscheme.h" |
||||||
|
|
||||||
|
struct InputMap input_map; |
||||||
|
|
||||||
|
void get_input_map(void) { |
||||||
|
input_map.player_down = SDL_SCANCODE_S; |
||||||
|
input_map.player_up = SDL_SCANCODE_W; |
||||||
|
input_map.player_right = SDL_SCANCODE_D; |
||||||
|
input_map.player_left = SDL_SCANCODE_A; |
||||||
|
input_map.player_rope = SDL_SCANCODE_E; |
||||||
|
input_map.player_pull_rope = SDL_SCANCODE_Q; |
||||||
|
} |
||||||
|
|
@ -1 +1 @@ |
|||||||
Subproject commit f3d3d3c18a46a8f75becf219fe42c4a01466f252 |
Subproject commit 4fcbd1c152a7ab8e749e3601a26861b4daf88a7b |
@ -0,0 +1,469 @@ |
|||||||
|
#include "draw.h" |
||||||
|
|
||||||
|
Vect viewport_pos; |
||||||
|
int width, height; |
||||||
|
|
||||||
|
/* generic rendering functions */ |
||||||
|
int MAX_ONSCREEN_OBJECTS = 99; |
||||||
|
|
||||||
|
int num_onscreen = 0; |
||||||
|
|
||||||
|
void render_texture_at(struct SDL_Renderer * ren, struct SDL_Texture * texture,int x, int y) { |
||||||
|
/* draw a texture at x.y */ |
||||||
|
|
||||||
|
SDL_Rect destination; |
||||||
|
destination.x = x; |
||||||
|
destination.y = y; |
||||||
|
|
||||||
|
SDL_QueryTexture(texture, NULL, NULL, &destination.w, &destination.h); |
||||||
|
|
||||||
|
SDL_RenderCopy(ren, texture, NULL, &destination); |
||||||
|
} |
||||||
|
|
||||||
|
/*SDL_Texture * load_image(SDL_Renderer * ren, char fname[]) {*/ |
||||||
|
/*[> Load an image into a texture <]*/ |
||||||
|
|
||||||
|
/*SDL_Surface * surface = IMG_Load(fname) ;*/ |
||||||
|
/*if(!surface) {*/ |
||||||
|
/*printf("IMG_Load: %s\n", IMG_GetError());*/ |
||||||
|
/*// handle error*/ |
||||||
|
/*}*/ |
||||||
|
|
||||||
|
/*SDL_Texture * png_image = SDL_CreateTextureFromSurface(ren, surface);*/ |
||||||
|
/*cleanup(surface, SURFACE);*/ |
||||||
|
/*return (png_image);*/ |
||||||
|
/*}*/ |
||||||
|
|
||||||
|
Vect in_view(Vect V) { |
||||||
|
Vect ret; |
||||||
|
ret.x = V.x -viewport_pos.x; |
||||||
|
ret.y = V.y -viewport_pos.y; |
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
/* Game Specific rendering functions */ |
||||||
|
void draw_player(SDL_Renderer * ren, int x, int y, bool red) { |
||||||
|
// translate to viewport
|
||||||
|
|
||||||
|
Vect V; |
||||||
|
V.x = x; V.y = y; |
||||||
|
V = in_view(V); |
||||||
|
|
||||||
|
/* draw the player as a coloured rect */ |
||||||
|
SDL_Rect player_rect; |
||||||
|
|
||||||
|
player_rect.x = V.x -10;
|
||||||
|
player_rect.y = V.y -10;
|
||||||
|
|
||||||
|
player_rect.w = 20; |
||||||
|
player_rect.h = 20; |
||||||
|
|
||||||
|
if (red) { |
||||||
|
SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); |
||||||
|
} else { |
||||||
|
struct colour c = get_scene_at(viewport_pos, level).colours.bg; |
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(ren, c.r, c.g, c.b, 255); |
||||||
|
} |
||||||
|
|
||||||
|
SDL_RenderDrawRect(ren, &player_rect); |
||||||
|
SDL_RenderFillRect(ren, &player_rect); |
||||||
|
// draw strings
|
||||||
|
for (int i = 0; i < player.physics->num_strings; i++) { |
||||||
|
if (!player.physics->strings[i].attached) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Vect B; |
||||||
|
B = in_view(player.physics->position); |
||||||
|
Vect E; |
||||||
|
E = in_view(player.physics->strings[i].end_point); |
||||||
|
SDL_RenderDrawLine(ren, B.x, B.y, E.x, E.y); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void draw_floor(SDL_Renderer *ren, FloorPoly *poly, bool down) { |
||||||
|
SDL_Point left; |
||||||
|
SDL_Point right; |
||||||
|
left.x = poly->left.x - viewport_pos.x; |
||||||
|
|
||||||
|
if (left.x > width) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
right.x = poly->right.x - viewport_pos.x; |
||||||
|
if (right.x < 0) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
left.y = poly->left.y - viewport_pos.y; |
||||||
|
right.y = poly->right.y - viewport_pos.y; |
||||||
|
|
||||||
|
if (left.y <= 0 && right.y <= 0) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (left.y >= height && right.y >= height) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(ren, 100,100,100, 255); |
||||||
|
|
||||||
|
int end = down ? height : 0; |
||||||
|
|
||||||
|
double m = (double)(right.y - left.y) / (double)(right.x - left.x); |
||||||
|
double c = (double)left.y - ((double)left.x * m); |
||||||
|
|
||||||
|
for (int i = left.x; i <= right.x; i++) { |
||||||
|
int y = (int)(m * i + c); |
||||||
|
if (y > 0) { |
||||||
|
SDL_RenderDrawLine(ren, i, y, i, end); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
||||||
|
} |
||||||
|
|
||||||
|
// draw collision poly
|
||||||
|
void draw_collision_poly(SDL_Renderer* ren, Body *body) { |
||||||
|
if (!SHOWCOLLISION) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (body->colliding) { |
||||||
|
SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); |
||||||
|
} else { |
||||||
|
SDL_SetRenderDrawColor(ren, 0, 255, 0, 255); |
||||||
|
} |
||||||
|
|
||||||
|
// draw strings
|
||||||
|
for (int i = 0; i < body->num_strings; i++) { |
||||||
|
if (!body->strings[i].attached) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Vect B; |
||||||
|
B = in_view(body->position); |
||||||
|
Vect E; |
||||||
|
E = in_view(body->strings[i].end_point); |
||||||
|
SDL_RenderDrawLine(ren, B.x, B.y, E.x, E.y); |
||||||
|
} |
||||||
|
|
||||||
|
if (body->collision_poly_size == 1) { |
||||||
|
SDL_Rect dot; |
||||||
|
Vect V; |
||||||
|
V.x = body->collision_poly[0].x; |
||||||
|
V.y = body->collision_poly[0].y; |
||||||
|
Vect T = in_view(V); |
||||||
|
dot.x = T.x; |
||||||
|
dot.y = T.y; |
||||||
|
dot.w = 4; |
||||||
|
dot.h = 4; |
||||||
|
SDL_RenderDrawRect(ren, &dot); |
||||||
|
SDL_RenderFillRect(ren, &dot); |
||||||
|
} else if (body->collision_poly_size == 2) { |
||||||
|
int x_st = body->collision_poly[0].x -viewport_pos.x; |
||||||
|
int y_st = body->collision_poly[0].y -viewport_pos.y; |
||||||
|
int x_en = body->collision_poly[1].x -viewport_pos.x; |
||||||
|
int y_en = body->collision_poly[1].y -viewport_pos.y; |
||||||
|
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
||||||
|
} else if (body->collision_poly_size > 2) { |
||||||
|
int x_st = body->collision_poly[0].x -viewport_pos.x; |
||||||
|
int y_st = body->collision_poly[0].y -viewport_pos.y; |
||||||
|
int x_en, y_en; |
||||||
|
for (int i = 1; i < body->collision_poly_size; i++) { |
||||||
|
x_en = body->collision_poly[i].x -viewport_pos.x; |
||||||
|
y_en = body->collision_poly[i].y -viewport_pos.y; |
||||||
|
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
||||||
|
x_st = x_en; |
||||||
|
y_st = y_en; |
||||||
|
} |
||||||
|
x_en = body->collision_poly[0].x-viewport_pos.x; |
||||||
|
y_en = body->collision_poly[0].y-viewport_pos.y; |
||||||
|
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
||||||
|
} |
||||||
|
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
||||||
|
} |
||||||
|
|
||||||
|
// draw indicator of forces acting on an object
|
||||||
|
void draw_forces(SDL_Renderer *ren, Body *body) { |
||||||
|
if (!SHOWFORCES) { |
||||||
|
return; |
||||||
|
} |
||||||
|
Vect start; |
||||||
|
start.x = (int)body->position.x -viewport_pos.x; |
||||||
|
start.y = (int)body->position.y -viewport_pos.y; |
||||||
|
|
||||||
|
Vect F; |
||||||
|
for (int i = 0; i < body->num_motors; i++) { |
||||||
|
if (!get_motor_active(body, i)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
F.x += body->motors[i].x; |
||||||
|
F.y += body->motors[i].y; |
||||||
|
Vect end = vect_add(start, F); |
||||||
|
SDL_SetRenderDrawColor(ren, 255,0,0, 255); |
||||||
|
SDL_RenderDrawLine(ren, start.x, start.y, start.x, end.y); |
||||||
|
SDL_SetRenderDrawColor(ren, 0,0,255, 255); |
||||||
|
SDL_RenderDrawLine(ren, start.x, start.y, end.x, start.y); |
||||||
|
} |
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
||||||
|
} |
||||||
|
|
||||||
|
void draw_wall(SDL_Renderer *ren, Wall *wall) { |
||||||
|
SDL_SetRenderDrawColor(ren, 120, 85, 188, 255); |
||||||
|
int x_st, x_en, y_st, y_en; |
||||||
|
x_st = wall->nodes[0].x + wall->physics->position.x -viewport_pos.x; |
||||||
|
y_st = wall->nodes[0].y + wall->physics->position.y -viewport_pos.y; |
||||||
|
for (int i = 1; i < wall->numNodes; i++) { |
||||||
|
x_en = wall->nodes[i].x + wall->physics->position.x -viewport_pos.x; |
||||||
|
y_en = wall->nodes[i].y + wall->physics->position.y -viewport_pos.y; |
||||||
|
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
||||||
|
x_st = x_en; |
||||||
|
y_st = y_en; |
||||||
|
} |
||||||
|
x_en = wall->nodes[0].x + wall->physics->position.x -viewport_pos.x; |
||||||
|
y_en = wall->nodes[0].y + wall->physics->position.y -viewport_pos.y; |
||||||
|
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
||||||
|
} |
||||||
|
|
||||||
|
int distance_colour(int x, int y, int x2, int y2, int blackpoint) { |
||||||
|
|
||||||
|
int dist = (int) sqrt((x2 - x)*(x2 - x) + (y2 - y)*(y2 - y) ); |
||||||
|
|
||||||
|
if (dist == 0) { |
||||||
|
return 255; |
||||||
|
} |
||||||
|
if (dist > blackpoint) { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int frac = blackpoint / dist; |
||||||
|
|
||||||
|
// int frac = 255 * (int) sin((double)dist / blackpoint);
|
||||||
|
if (frac > 255) { |
||||||
|
return 255; |
||||||
|
} |
||||||
|
|
||||||
|
return frac; |
||||||
|
} |
||||||
|
|
||||||
|
void update_viewport(double x, double y) { |
||||||
|
float xmargin = 0.5; |
||||||
|
float ymargin = 0.2; |
||||||
|
|
||||||
|
if (player.physics->position.x - viewport_pos.x > (1-xmargin) * width) { |
||||||
|
viewport_pos.x = - ((1-xmargin) * width - player.physics->position.x); |
||||||
|
} |
||||||
|
|
||||||
|
if (player.physics->position.x - viewport_pos.x < xmargin * width) { |
||||||
|
viewport_pos.x = -(xmargin * width - player.physics->position.x); |
||||||
|
} |
||||||
|
|
||||||
|
if (player.physics->position.y - viewport_pos.y > (1-ymargin) * height) { |
||||||
|
viewport_pos.y = -((1-ymargin) * height - player.physics->position.y); |
||||||
|
} |
||||||
|
|
||||||
|
if (player.physics->position.y - viewport_pos.y < ymargin * height) { |
||||||
|
viewport_pos.y = -(ymargin * height - player.physics->position.y); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
double interpolate_h(Vect left, Vect right, double x) { |
||||||
|
static Vect v; |
||||||
|
|
||||||
|
double m = (double)(right.y - left.y) / (double)(right.x - left.x);
|
||||||
|
double c = (double)left.y - ((double)left.x * m);
|
||||||
|
|
||||||
|
return x * m + c; |
||||||
|
} |
||||||
|
|
||||||
|
void draw_environment(SDL_Renderer * ren, struct environment *scene) { |
||||||
|
struct colour c1 = scene->colours.bg; |
||||||
|
struct colour c2 = scene->colours.fg1; |
||||||
|
struct colour c3 = scene->colours.fg2; |
||||||
|
struct colour c4 = scene->colours.fg3; |
||||||
|
|
||||||
|
/*c1->r = 255;*/ |
||||||
|
/*c2->g = 255;*/ |
||||||
|
/*c3->b = 255;*/ |
||||||
|
/*c4->g = 255;*/ |
||||||
|
/*c4->b = 255;*/ |
||||||
|
|
||||||
|
// background colour
|
||||||
|
SDL_SetRenderDrawColor(ren, c1.r, c1.g, c1.b, 255); |
||||||
|
/*SDL_SetRenderDrawColor(ren, 255, 0, 0, 255);*/ |
||||||
|
|
||||||
|
SDL_Rect rect;
|
||||||
|
rect.x = 0; |
||||||
|
rect.y = 0; |
||||||
|
rect.w = width; |
||||||
|
rect.h = height; |
||||||
|
SDL_RenderFillRect(ren, &rect); |
||||||
|
|
||||||
|
/*
|
||||||
|
* double m = (double)(right.y - left.y) / (double)(right.x - left.x); |
||||||
|
* double c = (double)left.y - ((double)left.x * m); |
||||||
|
* |
||||||
|
* for (int i = left.x; i <= right.x; i++) { |
||||||
|
* int y = (int)(m * i + c); |
||||||
|
* if (y > 0) { |
||||||
|
* SDL_RenderDrawLine(ren, i, y, i, end); |
||||||
|
* } |
||||||
|
* } |
||||||
|
*/ |
||||||
|
|
||||||
|
int k = 0; |
||||||
|
// printf("from 0 to (room tiles) %d - 1, res %d width %d\n", E_ROOM_TILES, E_ROOM_RES, E_ROOM_WIDTH);
|
||||||
|
for (int i = 0; i < E_ROOM_TILES - 1; i++) { |
||||||
|
for (int j = 0; j < E_ROOM_RES; j++) { |
||||||
|
k++; |
||||||
|
Vect *left; |
||||||
|
Vect *right; |
||||||
|
|
||||||
|
int x = (i * E_ROOM_RES) + j; |
||||||
|
if (x - viewport_pos.x > width) { |
||||||
|
break; |
||||||
|
} |
||||||
|
if (x - viewport_pos.x < 0) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
left = arlst_get(&scene->ceil, i); |
||||||
|
right = arlst_get(&scene->ceil, i+1); |
||||||
|
|
||||||
|
int y0 = interpolate_h(*left, *right, x) - viewport_pos.y; |
||||||
|
|
||||||
|
left = arlst_get(&scene->bg1, i); |
||||||
|
right = arlst_get(&scene->bg1, i+1); |
||||||
|
|
||||||
|
int y1 = interpolate_h(*left, *right, x) - viewport_pos.y; |
||||||
|
|
||||||
|
left = arlst_get(&scene->bg2, i); |
||||||
|
right = arlst_get(&scene->bg2, i+1); |
||||||
|
|
||||||
|
int y2 = interpolate_h(*left, *right, x) - viewport_pos.y; |
||||||
|
|
||||||
|
left = arlst_get(&scene->floor, i); |
||||||
|
right = arlst_get(&scene->floor, i+1); |
||||||
|
|
||||||
|
int y3 = interpolate_h(*left, *right, x) - viewport_pos.y; |
||||||
|
|
||||||
|
x = x - viewport_pos.x; |
||||||
|
/*printf("x: %d, ", x);*/ |
||||||
|
/*printf("y: %d %d %d %d\n", y0, y1, y2, y3);*/ |
||||||
|
|
||||||
|
// 3. bg2 to floor
|
||||||
|
SDL_SetRenderDrawColor(ren, c4.r, c4.g, c4.b, 255); |
||||||
|
SDL_RenderDrawLine(ren, x, y2, x, y3); |
||||||
|
|
||||||
|
// 1. ceil to bg1
|
||||||
|
SDL_SetRenderDrawColor(ren, c2.r, c2.g, c2.b, 255); |
||||||
|
SDL_RenderDrawLine(ren, x, y0, x, y1); |
||||||
|
|
||||||
|
// 2. bg1 to bg2
|
||||||
|
SDL_SetRenderDrawColor(ren, c3.r, c3.g, c3.b, 255); |
||||||
|
SDL_RenderDrawLine(ren, x, y1, x, y2); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void redraw_buffer(SDL_Renderer * ren) { |
||||||
|
static int mousex = 0; |
||||||
|
static int mousey = 0; |
||||||
|
static int newmousex = 0;
|
||||||
|
static int newmousey = 0; |
||||||
|
static SDL_Point *bgPixels[256]; |
||||||
|
static int numpixels[256]; |
||||||
|
|
||||||
|
/*if (!width && !height) {*/ |
||||||
|
/*for (int i = 0; i < 256; i++) {*/ |
||||||
|
/*bgPixels[i] = malloc(sizeof(SDL_Point) * width * height);*/ |
||||||
|
/*memset(bgPixels[i], 0, sizeof(SDL_Point) * width * height);*/ |
||||||
|
/*memset(numpixels, 0, (sizeof(int) * 256));*/ |
||||||
|
/*}*/ |
||||||
|
/*}*/ |
||||||
|
|
||||||
|
int col = 0; |
||||||
|
|
||||||
|
//SDL_GetMouseState(&newmousex, &newmousey);
|
||||||
|
update_viewport(player.physics->position.x, player.physics->position.y); |
||||||
|
|
||||||
|
struct environment scene = get_scene_at(viewport_pos, level); |
||||||
|
draw_environment(ren, &scene); |
||||||
|
|
||||||
|
for (int i=0; i < world.items.size; i++) { |
||||||
|
world_thing thing; |
||||||
|
thing = world.get(i); |
||||||
|
|
||||||
|
switch (thing.kind) { |
||||||
|
case PLAYER: |
||||||
|
draw_player(ren, (*thing.player).physics->position.x, (*thing.player).physics->position.y, thing.player->colliding); |
||||||
|
draw_collision_poly(ren, thing.player->physics); |
||||||
|
draw_forces(ren, thing.player->physics); |
||||||
|
continue; |
||||||
|
case STATIC_WALL_W: |
||||||
|
draw_wall(ren, thing.wall); |
||||||
|
draw_collision_poly(ren, thing.wall->physics); |
||||||
|
continue; |
||||||
|
case FLOOR: |
||||||
|
for (int i = 0; i < thing.floor->numPolys; i++) { |
||||||
|
draw_floor(ren, &thing.floor->polys[i], true); |
||||||
|
draw_collision_poly(ren, thing.floor->polys[i].physics); |
||||||
|
} |
||||||
|
continue; |
||||||
|
case CEILING: |
||||||
|
for (int i = 0; i < thing.floor->numPolys; i++) { |
||||||
|
draw_floor(ren, &thing.floor->polys[i], false); |
||||||
|
draw_collision_poly(ren, thing.floor->polys[i].physics); |
||||||
|
} |
||||||
|
continue; |
||||||
|
case ROOM_W: |
||||||
|
for (int i = 0; i < thing.room->ceil.numItems; i++) { |
||||||
|
draw_collision_poly(ren, thing.room->ceil.items[i]); |
||||||
|
} |
||||||
|
for (int i = 0; i < thing.room->floor.numItems; i++) { |
||||||
|
draw_collision_poly(ren, thing.room->floor.items[i]); |
||||||
|
} |
||||||
|
default: |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/*if (newmousex != mousex || newmousey != mousey) {*/ /*mousey = newmousey;*/ |
||||||
|
/*mousex = newmousex;*/ |
||||||
|
/*for (int i = 0; i < 256; i++) {*/ |
||||||
|
/*memset(bgPixels[i], 0, sizeof(SDL_Point) * width * height);*/ |
||||||
|
/*memset(numpixels, 0, (sizeof(int) * 256));*/ |
||||||
|
/*}*/ |
||||||
|
/*for (int i=0; i < width; i++) {*/ |
||||||
|
/*for (int j = 0; j < height; j++) {*/ |
||||||
|
/*col = distance_colour(i, j, mousex, mousey, 10000);*/ |
||||||
|
|
||||||
|
/*SDL_Point *row = bgPixels[col];*/ |
||||||
|
/*SDL_Point point;*/ |
||||||
|
/*point.x = i;*/ |
||||||
|
/*point.y = j;*/ |
||||||
|
/*row[numpixels[col]] = point;*/ |
||||||
|
/*numpixels[col] += 1;*/ |
||||||
|
|
||||||
|
/*}*/ |
||||||
|
/*}*/ |
||||||
|
/*}*/ |
||||||
|
|
||||||
|
/*for (int i = 0; i < 255; i++) {*/ |
||||||
|
/*SDL_Point *row = bgPixels[i];*/ |
||||||
|
/*col = i;*/ |
||||||
|
/*SDL_SetRenderDrawColor(ren, col, col, col, 255);*/ |
||||||
|
/*SDL_RenderDrawPoints(ren, row, numpixels[i]);*/ |
||||||
|
/*}*/ |
||||||
|
|
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
#ifndef _DEFGAME |
||||||
|
#define _DEFGAME |
||||||
|
|
||||||
|
#include "environment.h" |
||||||
|
#include "datastructures/datatypes.h" |
||||||
|
#include "vect.h" |
||||||
|
#include "garbo.h" |
||||||
|
#include "controlscheme.h" |
||||||
|
#include "c-colours/colours.h" |
||||||
|
#include "types.h" |
||||||
|
#include "draw.h" |
||||||
|
|
||||||
|
extern GlobWorld world; |
||||||
|
extern int level; |
||||||
|
|
||||||
|
void handle_input_event(SDL_Event event); |
||||||
|
|
||||||
|
// add a motor to the world
|
||||||
|
void add_motor(Body *thing, double x, double y);
|
||||||
|
|
||||||
|
bool get_motor_active(Body *thing, int i);
|
||||||
|
|
||||||
|
/* array of all the things in the world and their kinds */ |
||||||
|
extern void startgame(SDL_Renderer * ren) ; |
||||||
|
extern void process_keydown(SDL_Keysym key); |
||||||
|
extern void process_keyup(SDL_Keysym key); |
||||||
|
extern void step(int interval); |
||||||
|
extern player_st player; |
||||||
|
extern int level; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,65 @@ |
|||||||
|
#include "garbo.h" |
||||||
|
|
||||||
|
static sdl_abstract cleanup_queue[100]; |
||||||
|
static int cleanup_queue_length = 0; |
||||||
|
|
||||||
|
void queue_for_cleanup(void * SDL_thing, sdl_types kind) { |
||||||
|
// add item to queue for later cleanup
|
||||||
|
// TODO: support multiple cleanup queues
|
||||||
|
|
||||||
|
sdl_abstract obj; |
||||||
|
obj.kind = kind; |
||||||
|
switch (kind) { |
||||||
|
case TEXTURE: |
||||||
|
obj.thing.texture = SDL_thing; |
||||||
|
break; |
||||||
|
case WINDOW: |
||||||
|
obj.thing.window = SDL_thing; |
||||||
|
break; |
||||||
|
case RENDERER: |
||||||
|
obj.thing.renderer = SDL_thing; |
||||||
|
break; |
||||||
|
case SURFACE: |
||||||
|
obj.thing.surface = SDL_thing; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
cleanup_queue_length++;
|
||||||
|
cleanup_queue[cleanup_queue_length] = obj; |
||||||
|
} |
||||||
|
|
||||||
|
void cleanup(void * thing, sdl_types thing_type) { |
||||||
|
// Destroy an SDL object immediately
|
||||||
|
if (!thing) { |
||||||
|
logwrite(DEBUG, "Null passed to cleanup\n"); |
||||||
|
return; |
||||||
|
} |
||||||
|
switch(thing_type) { |
||||||
|
case SURFACE: |
||||||
|
SDL_FreeSurface(thing); |
||||||
|
logwrite(DEBUG, "Freed surface\n"); |
||||||
|
break; |
||||||
|
case TEXTURE: |
||||||
|
SDL_DestroyTexture(thing); |
||||||
|
logwrite(DEBUG, "Destroyed texture\n"); |
||||||
|
break; |
||||||
|
case RENDERER: |
||||||
|
SDL_DestroyRenderer(thing); |
||||||
|
logwrite(DEBUG, "Destroyed renderer\n"); |
||||||
|
break; |
||||||
|
case WINDOW: |
||||||
|
SDL_DestroyWindow(thing); |
||||||
|
logwrite(DEBUG, "Destroyed window\n"); |
||||||
|
break; |
||||||
|
case NO: |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void empty_cleanup_queue(void) { |
||||||
|
// empty the queue of items scheduled for cleanup
|
||||||
|
for (; cleanup_queue_length > 0; cleanup_queue_length--) { |
||||||
|
sdl_abstract thing = cleanup_queue[cleanup_queue_length]; |
||||||
|
cleanup(thing.thing.generic, thing.kind); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
|
||||||
|
#ifndef _DEFGARBO |
||||||
|
#define _DEFGARBO |
||||||
|
|
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <SDL2/SDL.h> |
||||||
|
#include <SDL2/SDL_image.h> |
||||||
|
#include <string.h> |
||||||
|
#include "logger.h" |
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
|
||||||
|
/* Type definition for object cleanups */ |
||||||
|
typedef enum { |
||||||
|
NO, SURFACE, TEXTURE, RENDERER, WINDOW |
||||||
|
} sdl_types; |
||||||
|
|
||||||
|
typedef union { |
||||||
|
SDL_Window * window; |
||||||
|
SDL_Renderer * renderer; |
||||||
|
SDL_Surface * surface; |
||||||
|
SDL_Texture * texture; |
||||||
|
void * generic; |
||||||
|
} thing_for_cleanup ; |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
sdl_types kind; |
||||||
|
thing_for_cleanup thing; |
||||||
|
} sdl_abstract; |
||||||
|
|
||||||
|
|
||||||
|
/* Function prototypes */ |
||||||
|
|
||||||
|
void queue_for_cleanup(void * SDL_thing, sdl_types kind);
|
||||||
|
|
||||||
|
void cleanup(void * thing, sdl_types thing_type);
|
||||||
|
|
||||||
|
void empty_cleanup_queue(void);
|
||||||
|
|
||||||
|
#endif |
||||||
|
|
@ -0,0 +1,70 @@ |
|||||||
|
#include "logger.h" |
||||||
|
|
||||||
|
// Defaults
|
||||||
|
|
||||||
|
loggerlevel LOGLEVEL = SILENT; |
||||||
|
loggerlevel STDOUTLEVEL = SILENT; |
||||||
|
|
||||||
|
void set_loglevel(loggerlevel echo, loggerlevel write) { |
||||||
|
LOGLEVEL = write; |
||||||
|
STDOUTLEVEL = echo; |
||||||
|
} |
||||||
|
|
||||||
|
int copy_str(char * out_string, char * string) { |
||||||
|
/* A drop in replacement for strcpy() from <string.h>*/ |
||||||
|
int len = 0; |
||||||
|
while (*(string + len) != '\0') { |
||||||
|
*(out_string + len) = *(string + len); |
||||||
|
len++; |
||||||
|
} |
||||||
|
*(out_string + len) = '\0'; |
||||||
|
return (1); |
||||||
|
} |
||||||
|
|
||||||
|
void logwrite(loggerlevel level, char message[]) { |
||||||
|
// write a string message
|
||||||
|
char time_str[100]; |
||||||
|
time_t current_time; |
||||||
|
time(¤t_time);
|
||||||
|
|
||||||
|
copy_str(time_str, asctime(localtime(¤t_time))); |
||||||
|
|
||||||
|
// delete the \n
|
||||||
|
time_str[24] = ' '; |
||||||
|
|
||||||
|
char prepend[15]; |
||||||
|
copy_str(prepend, time_str); |
||||||
|
|
||||||
|
|
||||||
|
switch (level) { |
||||||
|
case DEBUG: |
||||||
|
strcat(prepend, "DEBUG"); |
||||||
|
break; |
||||||
|
case INFO: |
||||||
|
strcat(prepend, "INFO "); |
||||||
|
break; |
||||||
|
case WARN: |
||||||
|
strcat(prepend, "WARN "); |
||||||
|
break; |
||||||
|
case ERROR: |
||||||
|
strcat(prepend, "ERROR"); |
||||||
|
break; |
||||||
|
case SILENT:
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
strcat(prepend, ": "); |
||||||
|
|
||||||
|
if (level <= LOGLEVEL) { |
||||||
|
FILE * logfile = fopen("debug.log", "a"); |
||||||
|
fprintf(logfile, "%s", prepend); |
||||||
|
fprintf(logfile, message); |
||||||
|
fclose(logfile); |
||||||
|
} |
||||||
|
|
||||||
|
if (level <= STDOUTLEVEL) { |
||||||
|
printf("%s", prepend); |
||||||
|
printf(message); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
#include <time.h> |
||||||
|
#include <string.h> |
||||||
|
#include <stdio.h> |
||||||
|
|
||||||
|
#ifndef _DEFLOGGER |
||||||
|
#define _DEFLOGGER |
||||||
|
|
||||||
|
|
||||||
|
typedef enum { |
||||||
|
// high-low priority
|
||||||
|
// low-high verbosity
|
||||||
|
SILENT, ERROR, WARN, INFO, DEBUG |
||||||
|
} loggerlevel; |
||||||
|
|
||||||
|
|
||||||
|
extern loggerlevel LOGLEVEL; |
||||||
|
extern loggerlevel STDOUTLEVEL; |
||||||
|
|
||||||
|
void logwrite(loggerlevel level, char message[]); |
||||||
|
|
||||||
|
void set_loglevel(loggerlevel echo, loggerlevel write); |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,109 @@ |
|||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <SDL2/SDL.h> |
||||||
|
#include <SDL2/SDL_image.h> |
||||||
|
#include <string.h> |
||||||
|
#include <time.h> |
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
#include "logger.h" |
||||||
|
#include "game.h" |
||||||
|
#include "draw.h" |
||||||
|
#include "garbo.h" |
||||||
|
|
||||||
|
const int screen_width = 800; |
||||||
|
const int screen_height = 600; |
||||||
|
|
||||||
|
struct SDL_Window* make_window(void) { |
||||||
|
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
||||||
|
printf("error initializing SDL: %s\n", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return SDL_CreateWindow("sdl_tester",
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
0, 0,
|
||||||
|
SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void redraw(struct SDL_Renderer * ren) { |
||||||
|
// check time
|
||||||
|
// redraw if 1/60th of second passed
|
||||||
|
|
||||||
|
SDL_RenderClear(ren); |
||||||
|
redraw_buffer(ren); |
||||||
|
SDL_RenderPresent(ren); |
||||||
|
} |
||||||
|
|
||||||
|
int physics_loop(void *ptr) { |
||||||
|
while (true) { |
||||||
|
SDL_Delay(10); |
||||||
|
step(10); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int game(void) { |
||||||
|
LOGLEVEL = DEBUG; |
||||||
|
STDOUTLEVEL = DEBUG; |
||||||
|
|
||||||
|
SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "2" ); |
||||||
|
|
||||||
|
logwrite(INFO, "Starting\n"); |
||||||
|
SDL_Window * win = make_window(); |
||||||
|
SDL_Renderer * ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); |
||||||
|
// | SDL_RENDERER_PRESENTVSYNC);
|
||||||
|
|
||||||
|
queue_for_cleanup(win, WINDOW); |
||||||
|
queue_for_cleanup(ren, RENDERER); |
||||||
|
|
||||||
|
// IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
|
||||||
|
|
||||||
|
if (ren == NULL) { |
||||||
|
SDL_DestroyWindow(win); |
||||||
|
SDL_Quit(); |
||||||
|
} |
||||||
|
|
||||||
|
int close = 0; |
||||||
|
|
||||||
|
//draw_pictures(ren);
|
||||||
|
|
||||||
|
SDL_Thread *physics_thread; |
||||||
|
int ignore; |
||||||
|
// physics_thread = SDL_CreateThread(physics_loop, "Physics", (void *)NULL);
|
||||||
|
|
||||||
|
bool once = true; |
||||||
|
startgame(ren); |
||||||
|
while (!close) { |
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
while(SDL_PollEvent(&event)) { |
||||||
|
switch (event.type) { |
||||||
|
case SDL_QUIT: |
||||||
|
close = 1; |
||||||
|
return 0; |
||||||
|
case SDL_KEYDOWN: |
||||||
|
case SDL_KEYUP: |
||||||
|
case SDL_MOUSEBUTTONDOWN: |
||||||
|
case SDL_MOUSEBUTTONUP: |
||||||
|
handle_input_event (event); |
||||||
|
} |
||||||
|
} |
||||||
|
/* Redraw Screen */ |
||||||
|
step(10); |
||||||
|
redraw(ren); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
int main (int argc, char** argv) { |
||||||
|
|
||||||
|
game(); |
||||||
|
SDL_Quit(); |
||||||
|
//empty_cleanup_queue();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1 @@ |
|||||||
#include "physics.h" |
#include "physics.h" |
||||||
#include "types.h" |
|
@ -1,231 +0,0 @@ |
|||||||
#include "audio.h" |
|
||||||
#include <SDL2/SDL_keycode.h> |
|
||||||
#include <SDL2/SDL_mixer.h> |
|
||||||
#include <SDL2/SDL_mutex.h> |
|
||||||
|
|
||||||
void generate_audio(void); |
|
||||||
struct game_sounds game_sounds; |
|
||||||
|
|
||||||
Uint8 big_hum(unsigned int t);
|
|
||||||
Uint8 func0(unsigned int t);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ---------------------------------------------------------------------------- |
|
||||||
* Audio |
|
||||||
* ---------------------------------------------------------------------------- |
|
||||||
* |
|
||||||
* Sound-effects are generated at startup, and synthesised using 8-bit |
|
||||||
* integer overflow a la bytebeat https://arxiv.org/pdf/1112.1368.pdf.
|
|
||||||
* |
|
||||||
* see generate_audio() |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
int mute = false; |
|
||||||
|
|
||||||
void fill_audio(void *func, Uint8 *stream, int len) { |
|
||||||
Uint8 (*wavegen)(unsigned int) = func; |
|
||||||
|
|
||||||
unsigned int t = 1; |
|
||||||
for(int i = 0; i < len; i++,t++) { |
|
||||||
stream[i] = wavegen(t); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void callbackfn3(void *unused, Uint8 *stream, int len) { |
|
||||||
static int t = 1; |
|
||||||
for(int i = 0; i < len; i++,t++) { |
|
||||||
stream[i] = big_hum(t); |
|
||||||
stream[i] = 0;
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void start_audio(void) { |
|
||||||
|
|
||||||
if (Mix_OpenAudio(G_AUDIO_SFREQ,AUDIO_S8,1,G_AUDIO_BSIZE) < 0) { |
|
||||||
fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError()); |
|
||||||
exit(1); |
|
||||||
} |
|
||||||
|
|
||||||
if (Mix_AllocateChannels(20) < 0) { |
|
||||||
fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError()); |
|
||||||
} |
|
||||||
|
|
||||||
generate_audio(); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void
|
|
||||||
play_game_sound(Mix_Chunk *chunk, int len, int channel)
|
|
||||||
{ |
|
||||||
if (mute || Mix_Playing(channel)) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if(Mix_PlayChannelTimed(channel, chunk, -1, len) < 0) |
|
||||||
fprintf(stderr, "Unable to play audio: %s\n", SDL_GetError()); |
|
||||||
//Mix_FadeInChannelTimed(channel, chunk, -1, 1, len);
|
|
||||||
} |
|
||||||
|
|
||||||
Uint8
|
|
||||||
pitchshift_hit(unsigned int t, void *arg)
|
|
||||||
{ |
|
||||||
double *hitt = arg; |
|
||||||
double hit = *hitt; |
|
||||||
hit = 6 - hit; |
|
||||||
int lower = 10 + 2 * (hit > 6 ? 6 : hit); |
|
||||||
int higher = 1 + (hit > 6 ? 6 : hit); |
|
||||||
|
|
||||||
const double R=8000; // sample rate (samples per second)
|
|
||||||
const double C=125; // frequency of middle-C (hertz)
|
|
||||||
const double F=R/256; // bytebeat frequency of 1*t due to 8-bit truncation (hertz)
|
|
||||||
const double V=127; // a volume constant
|
|
||||||
double volume = (((t / 3000) > 2) ? 2 : t / 3000); |
|
||||||
|
|
||||||
return ((sin(t*2*M_PI/R*(125 + hit))+1)*10 + (sin(t*2*M_PI/R*(250 + hit))+1)*(50 + hit) + (sin(t*2*M_PI/R*(900 + hit))+1)*100 + (sin(t*2*M_PI/R*(150+ hit))+1)*5) ; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void
|
|
||||||
synthplay_now(Uint8 (*bbgen)(unsigned int t, void *), void *arg, int len)
|
|
||||||
{ |
|
||||||
static Mix_Chunk *new_chunk = NULL; |
|
||||||
|
|
||||||
if (Mix_Playing(1)) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if (new_chunk) |
|
||||||
Mix_FreeChunk(new_chunk); |
|
||||||
|
|
||||||
int generate_len = len * (512); |
|
||||||
|
|
||||||
Uint8 raw_data[generate_len]; |
|
||||||
|
|
||||||
unsigned int t = 1; |
|
||||||
for(int i = 0; i < generate_len; i++,t++) { |
|
||||||
raw_data[i] = bbgen(t, arg); |
|
||||||
} |
|
||||||
|
|
||||||
new_chunk = Mix_QuickLoad_RAW(raw_data, generate_len); |
|
||||||
Mix_PlayChannelTimed(1, new_chunk, -1, len); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void callbackfn2(void *unused, Uint8 *stream, int len) { |
|
||||||
static int t = 1; |
|
||||||
int i; |
|
||||||
int yeet = rand(); |
|
||||||
for(i=0; i < len; i++,t++) { |
|
||||||
stream[i] = func0(t); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void callbackfn(void *unused, Uint8 *stream, int len) |
|
||||||
{ |
|
||||||
static int t = 0; |
|
||||||
int i; |
|
||||||
int yeet = rand(); |
|
||||||
for( i=0; i < len; i++,t++) { |
|
||||||
/*
|
|
||||||
stream[i] = (t*5&(t>>7))|(t*3&(t>>8)); |
|
||||||
*/ |
|
||||||
//stream[i] = (( t >> 10 ) & 42) * t;
|
|
||||||
stream[i] = (t & yeet) % 73; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* Waveform Generators */ |
|
||||||
|
|
||||||
Uint8 big_hum(unsigned int t) { |
|
||||||
return ( (sin(t*2*3.14159265/8000*200)+1) * 20) + ( (sin(t*2*3.14159265/8000*110)+1) * 20) + ( (sin(t*2*3.14159265/8000*230)+1) * 20) + ( (sin((t % 80)*2*3.14159265/8000 * 6)+1) * 12); |
|
||||||
} |
|
||||||
|
|
||||||
unsigned int sine_wave_sound(unsigned int t) { |
|
||||||
const double R=8000; // sample rate (samples per second)
|
|
||||||
const double C=261.625565; // frequency of middle-C (hertz)
|
|
||||||
const double F=R/256; // bytebeat frequency of 1*t due to 8-bit truncation (hertz)
|
|
||||||
const double V=127; // a volume constant
|
|
||||||
return (sin(t*2*M_PI/R*C)+1)*V; |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 winch_sound(unsigned t) { |
|
||||||
return (((t % 80) | (t % 36) | (6 * (t % 6))) + 20) * 1.6; |
|
||||||
return ((t % 80) | (t % 36) | (6 * (t % 6))); |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 beat_2(unsigned t) { |
|
||||||
return ((((t % 250) / 2)) | (t % 129)) % 110; |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 func0(unsigned t) { |
|
||||||
int note = 18; |
|
||||||
if (!(t % 1240)) { |
|
||||||
note = (1 + rand()) % 18 + 1; |
|
||||||
} |
|
||||||
|
|
||||||
fflush(stdout); |
|
||||||
return (t % note); |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 func1(unsigned int t) { |
|
||||||
int note = 10; |
|
||||||
if (!(t % 8000)) { |
|
||||||
note = (1 + rand()) % 10 + 5; |
|
||||||
} |
|
||||||
return ((t & 110) % 73 | (t % 1711)); |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 collision_test(unsigned int t) { |
|
||||||
// try not to loop
|
|
||||||
return ((t < 3000) * ((t % 5) * (3000 - t % 3000) * 0.00351))
|
|
||||||
+ ((t < 3500) * ((3500 - t % 3500)) * 0.0002 * (t % 14)); |
|
||||||
return ((t < 3000) * ((t % 5) * (3000 - t % 3000) * 0.00351))
|
|
||||||
+ ((4000 - t % 4000) * 0.0003 * (t % 128))
|
|
||||||
+ ((t < 3500) * ((3500 - t % 3500)) * 0.0002 * (t % 64)); // has a big low sound
|
|
||||||
return (t % 4) * (4000 - t % 4000) * 0.01; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
Uint8 boop_noise(unsigned int t) { |
|
||||||
return ((t >> 10) & 42) * t; |
|
||||||
} |
|
||||||
|
|
||||||
Uint8 rope_attach(unsigned int t) { |
|
||||||
return (((2000 - (t % 2000)))/40 * (t % 20) | (t % 44) + 20) * 1.6; |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* Called by startgame() to initialise sound effects. |
|
||||||
*/ |
|
||||||
void generate_audio(void) { |
|
||||||
const int sfx_len_ms = 1000; |
|
||||||
unsigned int sfx_len = (G_AUDIO_SFREQ/1000) * G_AUDIO_BSIZE * sfx_len_ms; |
|
||||||
sfx_len = G_AUDIO_BSIZE; |
|
||||||
|
|
||||||
Uint8 *raw_data = malloc(sfx_len);
|
|
||||||
fill_audio(winch_sound, raw_data, sfx_len); |
|
||||||
game_sounds.rope_pull = Mix_QuickLoad_RAW(raw_data, sfx_len); |
|
||||||
Mix_Volume(BC_ROPE_PULL, MIX_MAX_VOLUME * 0.3); |
|
||||||
|
|
||||||
Uint8 *raw_data2 = malloc(sfx_len);
|
|
||||||
fill_audio(collision_test, raw_data2, sfx_len); |
|
||||||
game_sounds.collision = Mix_QuickLoad_RAW(raw_data2, sfx_len); |
|
||||||
Mix_Volume(BC_COLLISION, MIX_MAX_VOLUME * 1.2); |
|
||||||
|
|
||||||
Uint8 *raw_data3 = malloc(sfx_len);
|
|
||||||
fill_audio(big_hum, raw_data3, sfx_len); |
|
||||||
game_sounds.background = Mix_QuickLoad_RAW(raw_data3, sfx_len); |
|
||||||
Mix_Volume(BC_MUSIC, MIX_MAX_VOLUME * 0.1); |
|
||||||
|
|
||||||
Uint8 *raw_data4 = malloc(sfx_len);
|
|
||||||
fill_audio(rope_attach, raw_data4, sfx_len); |
|
||||||
game_sounds.rope_attach = Mix_QuickLoad_RAW(raw_data4, sfx_len); |
|
||||||
Mix_Volume(BC_ROPE_ATTACH, MIX_MAX_VOLUME * 0.1); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
@ -1,37 +0,0 @@ |
|||||||
|
|
||||||
#ifndef AUDIO_H |
|
||||||
#define AUDIO_H |
|
||||||
|
|
||||||
#include <SDL2/SDL_audio.h> |
|
||||||
#include "types.h" |
|
||||||
#include <math.h> |
|
||||||
#include <stdlib.h> |
|
||||||
|
|
||||||
#define G_AUDIO_SFREQ 8000 |
|
||||||
#define G_AUDIO_BSIZE 512 |
|
||||||
|
|
||||||
struct game_sounds { |
|
||||||
unsigned int t; |
|
||||||
Mix_Chunk *collision; |
|
||||||
Mix_Chunk *rope_attach; |
|
||||||
Mix_Chunk *rope_pull; |
|
||||||
Mix_Chunk *background; |
|
||||||
/* Looping samples (need backbuffer to fill while playing ) */ |
|
||||||
Mix_Chunk *menu; |
|
||||||
}; |
|
||||||
|
|
||||||
extern struct game_sounds game_sounds; |
|
||||||
|
|
||||||
void play_game_sound(Mix_Chunk *chunk, int len, int channel); |
|
||||||
void start_audio(void);
|
|
||||||
|
|
||||||
Uint8 pitchshift_hit(unsigned int t, void *arg); |
|
||||||
void synthplay_now(Uint8 (*bbgen)(unsigned int t, void *), void *arg, int len);
|
|
||||||
|
|
||||||
enum audio_channel_names { |
|
||||||
BC_COLLISION = 1, |
|
||||||
BC_ROPE_PULL = 2, |
|
||||||
BC_ROPE_ATTACH = 3, |
|
||||||
BC_MUSIC = 4, |
|
||||||
}; |
|
||||||
#endif |
|
@ -1,115 +0,0 @@ |
|||||||
|
|
||||||
#include "controlscheme.h" |
|
||||||
#include <SDL2/SDL_scancode.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
|
|
||||||
struct InputMap input_map; |
|
||||||
|
|
||||||
#define INPUT_MAP_ID 83921864 |
|
||||||
#define INPUT_MAP_VERSION 0 |
|
||||||
#define CONTROLS_FNAME "controls.bin" |
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Serialise controlscheme using simple (char *) cast. It is obviously not cross |
|
||||||
* platform but it doesnt need to be. Takes a very tentative approach to error |
|
||||||
* handling, if something is wrong it resets. |
|
||||||
* |
|
||||||
* There is no UI for setting controls yet.
|
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
struct InputMap_Ser { |
|
||||||
unsigned int id; |
|
||||||
unsigned int ver; |
|
||||||
size_t size; |
|
||||||
struct InputMap input_map; |
|
||||||
}; |
|
||||||
|
|
||||||
int load_controls(void);
|
|
||||||
|
|
||||||
void get_input_map(void) { |
|
||||||
|
|
||||||
if (load_controls()) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
input_map.player_down = SDL_SCANCODE_S; |
|
||||||
input_map.player_up = SDL_SCANCODE_W; |
|
||||||
input_map.player_right = SDL_SCANCODE_D; |
|
||||||
input_map.player_left = SDL_SCANCODE_A; |
|
||||||
input_map.player_rope = SDL_SCANCODE_E; |
|
||||||
input_map.player_pull_rope = SDL_SCANCODE_Q; |
|
||||||
input_map.mute = SDL_SCANCODE_M; |
|
||||||
input_map.pause = SDL_SCANCODE_ESCAPE; |
|
||||||
input_map.quit = SDL_SCANCODE_Q; |
|
||||||
input_map.goto_level = SDL_SCANCODE_G; |
|
||||||
input_map.high_contrast_mode = SDL_SCANCODE_H; |
|
||||||
input_map.mouse_attach_rope_pull = SDL_BUTTON_LEFT; |
|
||||||
input_map.mouse_attach_rope = SDL_BUTTON_RIGHT; |
|
||||||
} |
|
||||||
|
|
||||||
struct Buffer { |
|
||||||
size_t len; |
|
||||||
char *data; |
|
||||||
}; |
|
||||||
|
|
||||||
struct Buffer read_whole_file(char const *file_name) { |
|
||||||
struct stat sb; |
|
||||||
struct Buffer b = {}; |
|
||||||
|
|
||||||
if (stat (file_name, & sb) != 0) { |
|
||||||
return b; |
|
||||||
} |
|
||||||
|
|
||||||
char *buffer = malloc(sb.st_size + 1); |
|
||||||
|
|
||||||
FILE *f = fopen(file_name, "r"); |
|
||||||
size_t bytes_read = fread(buffer, sizeof (unsigned char), sb.st_size, f); |
|
||||||
if (bytes_read != sb.st_size) { |
|
||||||
fclose(f); |
|
||||||
free(buffer); |
|
||||||
return b; |
|
||||||
} |
|
||||||
|
|
||||||
fclose(f); |
|
||||||
|
|
||||||
b.data = buffer; |
|
||||||
b.len = bytes_read; |
|
||||||
return b; |
|
||||||
} |
|
||||||
|
|
||||||
int load_controls(void) { |
|
||||||
struct Buffer b = read_whole_file(CONTROLS_FNAME); |
|
||||||
|
|
||||||
if (b.len != sizeof (struct InputMap_Ser)) { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
struct InputMap_Ser *im = (struct InputMap_Ser *)b.data; |
|
||||||
|
|
||||||
if (im->size != sizeof(struct InputMap_Ser)) |
|
||||||
return 0; |
|
||||||
|
|
||||||
if (im->id != INPUT_MAP_ID) |
|
||||||
return 0; |
|
||||||
|
|
||||||
if (im->ver != INPUT_MAP_VERSION) |
|
||||||
return 0; |
|
||||||
|
|
||||||
memcpy(&input_map, &im->input_map, sizeof(struct InputMap)); |
|
||||||
return 1; |
|
||||||
} |
|
||||||
|
|
||||||
void save_controls(void) { |
|
||||||
FILE *f = fopen(CONTROLS_FNAME, "w"); |
|
||||||
|
|
||||||
struct InputMap_Ser im; |
|
||||||
im.id = INPUT_MAP_ID; |
|
||||||
im.ver = INPUT_MAP_VERSION; |
|
||||||
im.size = sizeof(struct InputMap_Ser); |
|
||||||
im.input_map = input_map; |
|
||||||
|
|
||||||
fwrite(&im, sizeof(unsigned char), sizeof(struct InputMap_Ser), f); |
|
||||||
fclose(f); |
|
||||||
} |
|
@ -1,36 +0,0 @@ |
|||||||
#include <SDL2/SDL.h> |
|
||||||
|
|
||||||
#ifndef CRTL_H |
|
||||||
#define CRTL_H |
|
||||||
|
|
||||||
enum Game_Interaction { |
|
||||||
PLAYER_UP, |
|
||||||
PLAYER_DOWN, |
|
||||||
PLAYER_RIGHT, |
|
||||||
PLAYER_LEFT |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
struct InputMap {
|
|
||||||
SDL_Scancode player_up; |
|
||||||
SDL_Scancode player_down; |
|
||||||
SDL_Scancode player_left; |
|
||||||
SDL_Scancode player_right; |
|
||||||
SDL_Scancode player_rope; |
|
||||||
SDL_Scancode player_pull_rope; |
|
||||||
SDL_Scancode mute; |
|
||||||
SDL_Scancode quit; |
|
||||||
SDL_Scancode pause; |
|
||||||
SDL_Scancode goto_level; |
|
||||||
SDL_Scancode high_contrast_mode; |
|
||||||
Uint8 mouse_attach_rope_pull; |
|
||||||
Uint8 mouse_attach_rope; |
|
||||||
}; |
|
||||||
|
|
||||||
extern struct InputMap input_map; |
|
||||||
|
|
||||||
void get_input_map(void);
|
|
||||||
void save_controls(void);
|
|
||||||
|
|
||||||
#endif |
|
||||||
|
|
@ -1,917 +0,0 @@ |
|||||||
#include "draw.h" |
|
||||||
#include "environment.h" |
|
||||||
#include "game.h" |
|
||||||
#include "types.h" |
|
||||||
#include <SDL2/SDL_mutex.h> |
|
||||||
#include <SDL2/SDL_render.h> |
|
||||||
#include <time.h> |
|
||||||
|
|
||||||
Vect viewport_pos; |
|
||||||
int width, height; |
|
||||||
|
|
||||||
/* generic rendering functions */ |
|
||||||
int MAX_ONSCREEN_OBJECTS = 99; |
|
||||||
|
|
||||||
int num_onscreen = 0; |
|
||||||
|
|
||||||
double time_delta = 0; |
|
||||||
|
|
||||||
void render_texture_at(struct SDL_Renderer * ren, struct SDL_Texture * texture,int x, int y) { |
|
||||||
/* draw a texture at x.y */ |
|
||||||
|
|
||||||
SDL_Rect destination; |
|
||||||
destination.x = x; |
|
||||||
destination.y = y; |
|
||||||
|
|
||||||
SDL_QueryTexture(texture, NULL, NULL, &destination.w, &destination.h); |
|
||||||
|
|
||||||
SDL_RenderCopy(ren, texture, NULL, &destination); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
double sigmoid(double x) { |
|
||||||
return exp(x) / (exp(x) + 1); |
|
||||||
} |
|
||||||
|
|
||||||
struct timespec get_now_d() { |
|
||||||
struct timespec now; |
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now); |
|
||||||
if (now.tv_nsec >= 1000000000) { |
|
||||||
now.tv_nsec -= 1000000000; |
|
||||||
} |
|
||||||
return now; |
|
||||||
} |
|
||||||
|
|
||||||
Vect in_view(Vect V) { |
|
||||||
Vect ret; |
|
||||||
ret.x = V.x -viewport_pos.x; |
|
||||||
ret.y = V.y -viewport_pos.y; |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
/* Game Specific rendering functions */ |
|
||||||
void draw_player(SDL_Renderer * ren, int x, int y, bool red) { |
|
||||||
// translate to viewport
|
|
||||||
|
|
||||||
Vect V; |
|
||||||
V.x = x; V.y = y; |
|
||||||
V = in_view(V); |
|
||||||
|
|
||||||
/* draw the player as a coloured rect */ |
|
||||||
SDL_Rect player_rect; |
|
||||||
|
|
||||||
player_rect.x = V.x -10;
|
|
||||||
player_rect.y = V.y -10;
|
|
||||||
|
|
||||||
player_rect.w = 20; |
|
||||||
player_rect.h = 20; |
|
||||||
|
|
||||||
struct colour c = get_scene_watch()->colours.bg; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, c.r, c.g, c.b, 255); |
|
||||||
|
|
||||||
SDL_RenderDrawRect(ren, &player_rect); |
|
||||||
SDL_RenderFillRect(ren, &player_rect); |
|
||||||
// draw strings
|
|
||||||
for (int i = 0; i < player.physics->num_strings; i++) { |
|
||||||
if (!player.physics->strings[i].attached) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
Vect B = {x, y}; |
|
||||||
B = in_view(B); |
|
||||||
Vect E; |
|
||||||
E = in_view(player.physics->strings[i].end_point); |
|
||||||
SDL_RenderDrawLine(ren, B.x, B.y, E.x, E.y); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void draw_floor(SDL_Renderer *ren, FloorPoly *poly, bool down) { |
|
||||||
SDL_Point left; |
|
||||||
SDL_Point right; |
|
||||||
left.x = poly->left.x - viewport_pos.x; |
|
||||||
|
|
||||||
if (left.x > width) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
right.x = poly->right.x - viewport_pos.x; |
|
||||||
if (right.x < 0) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
left.y = poly->left.y - viewport_pos.y; |
|
||||||
right.y = poly->right.y - viewport_pos.y; |
|
||||||
|
|
||||||
if (left.y <= 0 && right.y <= 0) { |
|
||||||
return; |
|
||||||
} |
|
||||||
if (left.y >= height && right.y >= height) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 100,100,100, 255); |
|
||||||
|
|
||||||
int end = down ? height : 0; |
|
||||||
|
|
||||||
double m = (double)(right.y - left.y) / (double)(right.x - left.x); |
|
||||||
double c = (double)left.y - ((double)left.x * m); |
|
||||||
|
|
||||||
for (int i = left.x; i <= right.x; i++) { |
|
||||||
int y = (int)(m * i + c); |
|
||||||
if (y > 0) { |
|
||||||
SDL_RenderDrawLine(ren, i, y, i, end); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
// draw collision poly
|
|
||||||
void draw_collision_poly(SDL_Renderer* ren, Body *body) { |
|
||||||
if (!SHOWCOLLISION) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if (body->colliding) { |
|
||||||
SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); |
|
||||||
} else { |
|
||||||
SDL_SetRenderDrawColor(ren, 0, 255, 0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
// draw strings
|
|
||||||
for (int i = 0; i < body->num_strings; i++) { |
|
||||||
if (!body->strings[i].attached) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
Vect B; |
|
||||||
B = in_view(body->position); |
|
||||||
Vect E; |
|
||||||
E = in_view(body->strings[i].end_point); |
|
||||||
SDL_RenderDrawLine(ren, B.x, B.y, E.x, E.y); |
|
||||||
} |
|
||||||
|
|
||||||
if (body->collision_poly_size == 1) { |
|
||||||
SDL_Rect dot; |
|
||||||
Vect V; |
|
||||||
V.x = body->collision_poly[0].x; |
|
||||||
V.y = body->collision_poly[0].y; |
|
||||||
Vect T = in_view(V); |
|
||||||
dot.x = T.x; |
|
||||||
dot.y = T.y; |
|
||||||
dot.w = 4; |
|
||||||
dot.h = 4; |
|
||||||
SDL_RenderDrawRect(ren, &dot); |
|
||||||
SDL_RenderFillRect(ren, &dot); |
|
||||||
} else if (body->collision_poly_size == 2) { |
|
||||||
int x_st = body->collision_poly[0].x -viewport_pos.x; |
|
||||||
int y_st = body->collision_poly[0].y -viewport_pos.y; |
|
||||||
int x_en = body->collision_poly[1].x -viewport_pos.x; |
|
||||||
int y_en = body->collision_poly[1].y -viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
} else if (body->collision_poly_size > 2) { |
|
||||||
int x_st = body->collision_poly[0].x -viewport_pos.x; |
|
||||||
int y_st = body->collision_poly[0].y -viewport_pos.y; |
|
||||||
int x_en, y_en; |
|
||||||
for (int i = 1; i < body->collision_poly_size; i++) { |
|
||||||
x_en = body->collision_poly[i].x -viewport_pos.x; |
|
||||||
y_en = body->collision_poly[i].y -viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
x_st = x_en; |
|
||||||
y_st = y_en; |
|
||||||
} |
|
||||||
x_en = body->collision_poly[0].x-viewport_pos.x; |
|
||||||
y_en = body->collision_poly[0].y-viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
} |
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
// draw indicator of forces acting on an object
|
|
||||||
void draw_forces(SDL_Renderer *ren, Body *body) { |
|
||||||
if (!SHOWFORCES) { |
|
||||||
return; |
|
||||||
} |
|
||||||
Vect start; |
|
||||||
start.x = (int)body->position.x -viewport_pos.x; |
|
||||||
start.y = (int)body->position.y -viewport_pos.y; |
|
||||||
|
|
||||||
Vect F; |
|
||||||
for (int i = 0; i < body->num_motors; i++) { |
|
||||||
if (!get_motor_active(body, i)) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
F.x += body->motors[i].x; |
|
||||||
F.y += body->motors[i].y; |
|
||||||
Vect end = vect_add(start, F); |
|
||||||
SDL_SetRenderDrawColor(ren, 255,0,0, 255); |
|
||||||
SDL_RenderDrawLine(ren, start.x, start.y, start.x, end.y); |
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,255, 255); |
|
||||||
SDL_RenderDrawLine(ren, start.x, start.y, end.x, start.y); |
|
||||||
} |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
void draw_wall(SDL_Renderer *ren, Wall *wall) { |
|
||||||
SDL_SetRenderDrawColor(ren, 120, 85, 188, 255); |
|
||||||
int x_st, x_en, y_st, y_en; |
|
||||||
x_st = wall->nodes[0].x + wall->physics->position.x -viewport_pos.x; |
|
||||||
y_st = wall->nodes[0].y + wall->physics->position.y -viewport_pos.y; |
|
||||||
for (int i = 1; i < wall->numNodes; i++) { |
|
||||||
x_en = wall->nodes[i].x + wall->physics->position.x -viewport_pos.x; |
|
||||||
y_en = wall->nodes[i].y + wall->physics->position.y -viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
x_st = x_en; |
|
||||||
y_st = y_en; |
|
||||||
} |
|
||||||
x_en = wall->nodes[0].x + wall->physics->position.x -viewport_pos.x; |
|
||||||
y_en = wall->nodes[0].y + wall->physics->position.y -viewport_pos.y; |
|
||||||
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en); |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, 0,0,0, 255); |
|
||||||
} |
|
||||||
|
|
||||||
int distance_colour(int x, int y, int x2, int y2, int blackpoint) { |
|
||||||
|
|
||||||
int dist = (int) sqrt((x2 - x)*(x2 - x) + (y2 - y)*(y2 - y) ); |
|
||||||
|
|
||||||
if (dist == 0) { |
|
||||||
return 255; |
|
||||||
} |
|
||||||
if (dist > blackpoint) { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
int frac = blackpoint / dist; |
|
||||||
|
|
||||||
// int frac = 255 * (int) sin((double)dist / blackpoint);
|
|
||||||
if (frac > 255) { |
|
||||||
return 255; |
|
||||||
} |
|
||||||
|
|
||||||
return frac; |
|
||||||
} |
|
||||||
|
|
||||||
void new_update_viewport(Body const * const pl) { |
|
||||||
int const xmargin = 100; // pixels
|
|
||||||
int const ymargin = 100; // pixels
|
|
||||||
int const xmovmagin = width / 4; |
|
||||||
int const ymovmagin = height / 3; |
|
||||||
double const xrange = width - (2 * xmargin); |
|
||||||
double const yrange = height - (2 * ymargin); |
|
||||||
double const x_max = 2; |
|
||||||
double const y_max = 3; |
|
||||||
static Vect target = {}; |
|
||||||
static double dirchange = 0; |
|
||||||
static Vect last_plpos = {}; |
|
||||||
if (last_plpos.x == 0 && last_plpos.y == 0) |
|
||||||
last_plpos = pl->position; |
|
||||||
|
|
||||||
static Vect lmove = {}; |
|
||||||
|
|
||||||
Vect iv = in_view(pl->position); |
|
||||||
|
|
||||||
Vect left_pos = {0, 2 * height / 4}; |
|
||||||
left_pos = vect_add(pl->position, vect_scalar(left_pos, -1)); |
|
||||||
|
|
||||||
Vect right_pos = {7 * (width / 8), 2 * height / 4}; |
|
||||||
right_pos = vect_add(pl->position, vect_scalar(right_pos, -1)); |
|
||||||
|
|
||||||
bool recover = false; |
|
||||||
|
|
||||||
Vect screen_dist = vect_add(in_view(pl->position), vect_scalar(lmove, -1)); |
|
||||||
|
|
||||||
static double swap = 0; |
|
||||||
if (iv.x > width
|
|
||||||
|| (iv.x < 0 |
|
||||||
|| iv.y > height |
|
||||||
|| iv.y < 0))
|
|
||||||
recover = true; |
|
||||||
|
|
||||||
Vect delta = vect_add(vect_scalar(pl->position, -1), last_plpos); |
|
||||||
double dist_change = vect_mag(delta); |
|
||||||
if ((recover) //|| vect_mag((Vect){pl->vel.x, 0}) > 0.4
|
|
||||||
|| (dist_change > width / 100)) { |
|
||||||
if (iv.x < width / 6) { |
|
||||||
target = right_pos; |
|
||||||
} else { |
|
||||||
target = left_pos; |
|
||||||
} |
|
||||||
lmove = target; |
|
||||||
|
|
||||||
last_plpos = pl->position; |
|
||||||
} |
|
||||||
|
|
||||||
if (recover) |
|
||||||
viewport_pos = target; |
|
||||||
|
|
||||||
double v = pl->vel.x; |
|
||||||
if (v > x_max)
|
|
||||||
v = x_max; |
|
||||||
if (v < -x_max)
|
|
||||||
v = -x_max; |
|
||||||
if (v < 0) |
|
||||||
v = -v; |
|
||||||
|
|
||||||
// move towards target a set proportion
|
|
||||||
Vect urgency = vect_add(target, vect_scalar(pl->position, -1)); |
|
||||||
Vect p = vect_add(target, vect_scalar(viewport_pos, -1)); |
|
||||||
|
|
||||||
double proportion = (sigmoid(time_delta) / 100); |
|
||||||
proportion = 2 * (pl->vel.x * pl->vel.x / (width)); |
|
||||||
proportion = proportion < 0 ? -proportion : proportion; |
|
||||||
|
|
||||||
proportion > 0.4 ? proportion = 0.4 : 0; |
|
||||||
proportion < 0 ? proportion = 0.000001 : 0; |
|
||||||
|
|
||||||
p = vect_scalar(p, proportion); |
|
||||||
viewport_pos = vect_add(viewport_pos, p); |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void update_viewport(Body *pl) { |
|
||||||
float xmargin = 0.5; |
|
||||||
float ymargin = 0.2; |
|
||||||
|
|
||||||
if (pl->position.x - viewport_pos.x > (1-xmargin) * width) { |
|
||||||
viewport_pos.x = - ((1-xmargin) * width - pl->position.x); |
|
||||||
} |
|
||||||
|
|
||||||
if (pl->position.x - viewport_pos.x < xmargin * width) { |
|
||||||
viewport_pos.x = -(xmargin * width - pl->position.x); |
|
||||||
} |
|
||||||
|
|
||||||
if (pl->position.y - viewport_pos.y > (1-ymargin) * height) { |
|
||||||
viewport_pos.y = -((1-ymargin) * height - pl->position.y); |
|
||||||
} |
|
||||||
|
|
||||||
if (pl->position.y - viewport_pos.y < ymargin * height) { |
|
||||||
viewport_pos.y = -(ymargin * height - pl->position.y); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void accel_update_viewport(Body *pl) { |
|
||||||
const double accel = 0.0001; |
|
||||||
const float xmargin = 0.5; |
|
||||||
const float ymargin = 0.2; |
|
||||||
|
|
||||||
static Vect target_pos = (Vect) {.x=0, .y=0}; |
|
||||||
static Vect vel = (Vect) {.x=0.0, .y=0.0}; |
|
||||||
|
|
||||||
|
|
||||||
if (pl->position.x - viewport_pos.x > (1-xmargin) * width) { |
|
||||||
target_pos.x = - ((1-xmargin) * width - pl->position.x); |
|
||||||
}
|
|
||||||
|
|
||||||
if (pl->position.x - target_pos.x < xmargin * width) { |
|
||||||
target_pos.x = -(xmargin * width - pl->position.x); |
|
||||||
} |
|
||||||
|
|
||||||
if (pl->position.y - target_pos.y > (1-ymargin) * height) { |
|
||||||
target_pos.y = -((1-ymargin) * height - pl->position.y); |
|
||||||
}
|
|
||||||
|
|
||||||
if (pl->position.y - target_pos.y < ymargin * height) { |
|
||||||
target_pos.y = -(ymargin * height - pl->position.y); |
|
||||||
} |
|
||||||
|
|
||||||
viewport_pos = target_pos; |
|
||||||
return; |
|
||||||
|
|
||||||
Vect delta = vect_add(target_pos, vect_scalar(viewport_pos, -1)); |
|
||||||
printf("d %f %f\n", delta.x, delta.y); |
|
||||||
printf("d %f\n", vect_mag(delta)); |
|
||||||
|
|
||||||
if ((vect_mag(delta) < 0.001 )) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
Vect dir = vect_scalar(delta, 1/vect_mag(delta)); |
|
||||||
Vect vel_delta = vect_scalar(dir, accel * time_delta); |
|
||||||
vel = vect_add(vel, vel_delta); |
|
||||||
|
|
||||||
Vect pos_delta = vect_scalar(vel, time_delta/2); |
|
||||||
|
|
||||||
viewport_pos = vect_add(viewport_pos, pos_delta); |
|
||||||
} |
|
||||||
|
|
||||||
double interpolate_h(Vect left, Vect right, double x) { |
|
||||||
static Vect v; |
|
||||||
|
|
||||||
double m = (double)(right.y - left.y) / (double)(right.x - left.x);
|
|
||||||
double c = (double)left.y - ((double)left.x * m);
|
|
||||||
|
|
||||||
return x * m + c; |
|
||||||
} |
|
||||||
|
|
||||||
void draw_environment(SDL_Renderer * ren, const struct environment *scene) { |
|
||||||
struct colour c1 = scene->colours.bg; |
|
||||||
struct colour c2 = scene->colours.fg1; |
|
||||||
struct colour c3 = scene->colours.fg2; |
|
||||||
struct colour c4 = scene->colours.fg3; |
|
||||||
|
|
||||||
// background colour
|
|
||||||
SDL_SetRenderDrawColor(ren, c1.r, c1.g, c1.b, 255); |
|
||||||
|
|
||||||
SDL_Rect rect;
|
|
||||||
rect.x = 0; |
|
||||||
rect.y = 0; |
|
||||||
rect.w = width; |
|
||||||
rect.h = height; |
|
||||||
SDL_RenderFillRect(ren, &rect); |
|
||||||
|
|
||||||
|
|
||||||
int k = 0; |
|
||||||
for (int i = 0; i < E_ROOM_TILES - 2; i++) { |
|
||||||
for (int j = 0; j < E_ROOM_RES; j++) { |
|
||||||
k++; |
|
||||||
Vect *left; |
|
||||||
Vect *right; |
|
||||||
|
|
||||||
int x = (i * E_ROOM_RES) + j; |
|
||||||
if (x - viewport_pos.x > width) { |
|
||||||
break; |
|
||||||
} |
|
||||||
if (x - viewport_pos.x < 0) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
left = arlst_get(&scene->ceil, i); |
|
||||||
right = arlst_get(&scene->ceil, i+1); |
|
||||||
|
|
||||||
int y0 = interpolate_h(*left, *right, x) - viewport_pos.y; |
|
||||||
|
|
||||||
left = arlst_get(&scene->bg1, i); |
|
||||||
right = arlst_get(&scene->bg1, i+1); |
|
||||||
|
|
||||||
int y1 = interpolate_h(*left, *right, x) - viewport_pos.y; |
|
||||||
|
|
||||||
left = arlst_get(&scene->bg2, i); |
|
||||||
right = arlst_get(&scene->bg2, i+1); |
|
||||||
|
|
||||||
int y2 = interpolate_h(*left, *right, x) - viewport_pos.y; |
|
||||||
|
|
||||||
left = arlst_get(&scene->floor, i); |
|
||||||
right = arlst_get(&scene->floor, i+1); |
|
||||||
|
|
||||||
int y3 = interpolate_h(*left, *right, x) - viewport_pos.y; |
|
||||||
|
|
||||||
x = x - viewport_pos.x; |
|
||||||
|
|
||||||
// 3. bg2 to floor
|
|
||||||
SDL_SetRenderDrawColor(ren, c4.r, c4.g, c4.b, 255); |
|
||||||
SDL_RenderDrawLine(ren, x, y2, x, y3); |
|
||||||
|
|
||||||
// 1. ceil to bg1
|
|
||||||
SDL_SetRenderDrawColor(ren, c2.r, c2.g, c2.b, 255); |
|
||||||
SDL_RenderDrawLine(ren, x, y0, x, y1); |
|
||||||
|
|
||||||
// 2. bg1 to bg2
|
|
||||||
SDL_SetRenderDrawColor(ren, c3.r, c3.g, c3.b, 255); |
|
||||||
SDL_RenderDrawLine(ren, x, y1, x, y2); |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static TTF_Font *fonts[3]; |
|
||||||
|
|
||||||
void load_fonts(void) { |
|
||||||
fonts[0] = TTF_OpenFont("TerminusTTF.ttf", 22); |
|
||||||
fonts[1] = TTF_OpenFont("TerminusTTF.ttf", 66); |
|
||||||
const char *err = SDL_GetError(); |
|
||||||
if (err) { |
|
||||||
printf("%s\n", err); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void draw_text(SDL_Renderer *ren, enum FontNames fontID, Vect pos, struct colour colour, char *text) { |
|
||||||
|
|
||||||
TTF_Font *font = fonts[fontID]; |
|
||||||
|
|
||||||
SDL_Colour sdl_col = {colour.r, colour.g, colour.b, 255};
|
|
||||||
SDL_Rect position = {.x = pos.x, .y = pos.y}; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, colour.r, colour.g, colour.b, 255); |
|
||||||
SDL_Surface *surf = TTF_RenderText_Solid(font, text, sdl_col); |
|
||||||
|
|
||||||
SDL_Texture *texture = SDL_CreateTextureFromSurface(ren, surf); |
|
||||||
SDL_QueryTexture(texture, NULL, NULL, &position.w, &position.h); |
|
||||||
SDL_RenderCopy(ren, texture, NULL, &position); |
|
||||||
|
|
||||||
SDL_DestroyTexture(texture); |
|
||||||
SDL_FreeSurface(surf); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void draw_text_default(SDL_Renderer *ren, Vect pos, struct colour colour, char *text) { |
|
||||||
TTF_Font* font = fonts[0]; |
|
||||||
|
|
||||||
SDL_Colour sdl_col = {colour.r, colour.g, colour.b, 255};
|
|
||||||
SDL_Rect position = {.x = pos.x, .y = pos.y}; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, colour.r, colour.g, colour.b, 255); |
|
||||||
SDL_Surface *surf = TTF_RenderText_Solid(font, text, sdl_col); |
|
||||||
|
|
||||||
SDL_Texture *texture = SDL_CreateTextureFromSurface(ren, surf); |
|
||||||
SDL_QueryTexture(texture, NULL, NULL, &position.w, &position.h); |
|
||||||
SDL_RenderCopy(ren, texture, NULL, &position); |
|
||||||
|
|
||||||
SDL_DestroyTexture(texture); |
|
||||||
SDL_FreeSurface(surf); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void draw_level_chooser_tbox(SDL_Renderer *ren) { |
|
||||||
|
|
||||||
char string[250]; |
|
||||||
snprintf(string, 250,"GOTO LEVEL: %s", gameui.currently_bound_textbox->text_input); |
|
||||||
|
|
||||||
const struct environment *scene = get_scene_watch(); |
|
||||||
|
|
||||||
Vect pos = {.x= width - (width / 4), .y = height - (height / 10)}; |
|
||||||
draw_text_default(ren, pos, scene->colours.fg1, string); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int draw_end_screen(SDL_Renderer *ren) { |
|
||||||
const struct environment *scene = get_scene_watch(); |
|
||||||
|
|
||||||
struct colour bg = scene->colours.bg; |
|
||||||
struct colour colour = scene->colours.fg1; |
|
||||||
struct colour_pallete pal = scene->colours; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, bg.r, bg.g, bg.b,255); |
|
||||||
|
|
||||||
SDL_RenderClear(ren); |
|
||||||
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, pal.fg2.r, pal.fg2.g, pal.fg2.b,255); |
|
||||||
for (int i = width - 300; i < width; i++) { |
|
||||||
SDL_RenderDrawLine(ren, i, height, width, height - i); |
|
||||||
if (!(i % 240)) { |
|
||||||
SDL_SetRenderDrawColor(ren, pal.fg3.r, pal.fg3.g, pal.fg3.b,255); |
|
||||||
} |
|
||||||
if (!(i % 350)) { |
|
||||||
SDL_SetRenderDrawColor(ren, pal.fg1.r, pal.fg1.g, pal.fg1.b,255); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int margin = height / 10; |
|
||||||
|
|
||||||
long fastest = draw_watch.best_time; |
|
||||||
|
|
||||||
int minutes = level_time / 60000; |
|
||||||
float seconds = level_time * 0.001; |
|
||||||
char time_string[250]; |
|
||||||
|
|
||||||
|
|
||||||
char * end_str = "level over."; |
|
||||||
|
|
||||||
Vect position = {.x = width/4, .y = height / 4}; |
|
||||||
draw_text_default(ren, position, colour, end_str); |
|
||||||
position.y += 60; |
|
||||||
|
|
||||||
char level_string[250]; |
|
||||||
snprintf(level_string, 250,"course: %d", level); |
|
||||||
draw_text_default(ren, position, colour, level_string); |
|
||||||
position.y += 40; |
|
||||||
|
|
||||||
char fastest_time[250]; |
|
||||||
minutes = fastest / 60000; |
|
||||||
seconds = fastest * 0.001; |
|
||||||
if (fastest > 0) { |
|
||||||
snprintf(fastest_time, 250, "old best time: %d:%.4f", minutes, seconds); |
|
||||||
draw_text_default(ren, position, colour, fastest_time); |
|
||||||
position.y += 40; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
minutes = level_time / 60000; |
|
||||||
seconds = level_time * 0.001; |
|
||||||
if (level_time > fastest) { |
|
||||||
// base time not set yet.
|
|
||||||
snprintf(time_string, 250, "TIME: %d:%.4f", minutes, seconds); |
|
||||||
} else { |
|
||||||
snprintf(time_string, 250, "NEW BEST TIME: %d:%.4f", minutes, seconds); |
|
||||||
} |
|
||||||
|
|
||||||
Vect position2 = {.x = position.x + width/3, .y = 60 + height / 4}; |
|
||||||
|
|
||||||
if (fastest > 0) { |
|
||||||
//position.y += 40;
|
|
||||||
long diff = level_time - fastest; |
|
||||||
char diff_str[250]; |
|
||||||
minutes = diff / 60000; |
|
||||||
seconds = diff * 0.001; |
|
||||||
if (minutes > 0) { |
|
||||||
snprintf(diff_str, 250, "DIFF: %d:%.4f", minutes, fabs(seconds)); |
|
||||||
} else { |
|
||||||
snprintf(diff_str, 250, "DIFF: %.4f s", seconds); |
|
||||||
} |
|
||||||
|
|
||||||
draw_text_default(ren, position2, colour, diff_str); |
|
||||||
position2.y += 40; |
|
||||||
} |
|
||||||
|
|
||||||
draw_text_default(ren, position2, colour, time_string); |
|
||||||
|
|
||||||
position.y += 200; |
|
||||||
char * ct_str = "press any key to continue"; |
|
||||||
draw_text_default(ren, position, colour, ct_str); |
|
||||||
|
|
||||||
SDL_RenderPresent(ren); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void draw_level_time(SDL_Renderer *ren, const struct environment * e) { |
|
||||||
|
|
||||||
int margin = height / 10; |
|
||||||
|
|
||||||
struct colour colour = e->colours.fg1; |
|
||||||
|
|
||||||
int minutes = level_time / 60000; |
|
||||||
float seconds = level_time * 0.001; |
|
||||||
char time_string[250]; |
|
||||||
snprintf(time_string, 250, "time: %d:%.4f", minutes, seconds); |
|
||||||
|
|
||||||
char level_string[250]; |
|
||||||
snprintf(level_string, 250,"course: %d", level); |
|
||||||
|
|
||||||
Vect position = {.x = margin, .y = height - margin}; |
|
||||||
draw_text_default(ren, position, colour, level_string); |
|
||||||
position.y += 40; |
|
||||||
draw_text_default(ren, position, colour, time_string); |
|
||||||
|
|
||||||
} |
|
||||||
void draw_mute_button(SDL_Renderer *ren) { |
|
||||||
|
|
||||||
struct colour c = get_scene_watch()->colours.fg1; |
|
||||||
struct colour i = get_scene_watch()->colours.bg; |
|
||||||
|
|
||||||
if (mute_button.held) { |
|
||||||
struct colour t = c; |
|
||||||
c = i;
|
|
||||||
i = t; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
SDL_Rect rect; |
|
||||||
|
|
||||||
rect.x = mute_button.x; |
|
||||||
rect.y = mute_button.y;
|
|
||||||
rect.w = mute_button.w; |
|
||||||
rect.h = mute_button.h; |
|
||||||
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, c.r, c.g, c.b, 255); |
|
||||||
SDL_RenderFillRect(ren, &rect); |
|
||||||
|
|
||||||
rect.x += mute_button.w / 6; |
|
||||||
rect.y += mute_button.w / 4; |
|
||||||
rect.w = mute_button.w / 5; |
|
||||||
rect.h = mute_button.h / 2; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, i.r, i.g, i.b, 255); |
|
||||||
SDL_RenderFillRect(ren, &rect); |
|
||||||
|
|
||||||
int j = 0; |
|
||||||
for (int i = rect.x + rect.w; i < rect.x + rect.w + mute_button.w / 5; i++) { |
|
||||||
SDL_RenderDrawLine(ren, i, rect.y + j + rect.h, i, rect.y - j); |
|
||||||
j++; |
|
||||||
} |
|
||||||
|
|
||||||
j -= 8; |
|
||||||
if (!mute_button.state) { |
|
||||||
for (int i = rect.x + rect.w + mute_button.w / 5;
|
|
||||||
i < mute_button.x + mute_button.w - 5; i++) { |
|
||||||
if ((i) % 8 < 4) { |
|
||||||
SDL_RenderDrawLine(ren, i, rect.y + j + rect.h, i, rect.y - j); |
|
||||||
} |
|
||||||
if (i % 8 == 0) j += 4; |
|
||||||
|
|
||||||
} |
|
||||||
} else { |
|
||||||
int w = mute_button.w / 5; |
|
||||||
int i = rect.x + rect.w + mute_button.w / 5 + w/2; |
|
||||||
int j = rect.y + w / 2; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
i += 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
i -= 1; |
|
||||||
|
|
||||||
j += 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
j -= 1; |
|
||||||
|
|
||||||
j += 1; |
|
||||||
i += 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
j -= 1; |
|
||||||
i -= 1; |
|
||||||
|
|
||||||
i -= 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
i += 1; |
|
||||||
|
|
||||||
j -= 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
j += 1; |
|
||||||
|
|
||||||
j -= 1; |
|
||||||
i -= 1; |
|
||||||
SDL_RenderDrawLine(ren, i, j + w, i + w, j); |
|
||||||
SDL_RenderDrawLine(ren, i + w, j + w, i, j); |
|
||||||
j += 1; |
|
||||||
i += 1; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void draw_pause_screen(SDL_Renderer *ren, struct environment *e) { |
|
||||||
|
|
||||||
char *game_name[] = { |
|
||||||
"A_s",
|
|
||||||
"Y_et",
|
|
||||||
"U_ntitled",
|
|
||||||
"G_ame",
|
|
||||||
"I_nvolving", |
|
||||||
"a",
|
|
||||||
"R_ock",
|
|
||||||
"W_ith",
|
|
||||||
"a",
|
|
||||||
"G_rappling",
|
|
||||||
"H_ook"}; |
|
||||||
|
|
||||||
char *te[] = { "GAME PAUSED.", |
|
||||||
"controls", |
|
||||||
"________", |
|
||||||
"pause/unpause: esc", |
|
||||||
"grapple and winch: left click", |
|
||||||
"grapple: right click", |
|
||||||
"go to level: g", |
|
||||||
"mute/unmute: m", |
|
||||||
"high contrast mode: h", |
|
||||||
"quit: q" |
|
||||||
}; |
|
||||||
|
|
||||||
struct colour textc = e->colours.fg1; |
|
||||||
struct colour bg = e->colours.bg; |
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(ren, bg.r, bg.g, bg.b, 255); |
|
||||||
int boxwidth = 360; |
|
||||||
int boxheight = 388; |
|
||||||
int box_x = (2 * width / 3) - (boxwidth / 2); |
|
||||||
int box_y = (height - boxheight) / 2; |
|
||||||
SDL_Rect r = {.w = boxwidth, .h = boxheight, .x = box_x, .y = box_y}; |
|
||||||
SDL_RenderFillRect(ren, &r); |
|
||||||
|
|
||||||
Vect p = {.x = box_x + 10, .y = box_y + 10}; |
|
||||||
draw_text_default(ren, p, textc, te[0]); |
|
||||||
p.y += 60; |
|
||||||
|
|
||||||
draw_text_default(ren, p, textc, te[1]); |
|
||||||
p.y += 5; |
|
||||||
draw_text_default(ren, p, textc, te[2]); |
|
||||||
p.y += 35; |
|
||||||
|
|
||||||
draw_text_default(ren, p, textc, te[3]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text_default(ren, p, textc, te[4]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text_default(ren, p, textc, te[5]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text_default(ren, p, textc, te[6]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text_default(ren, p, textc, te[7]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text_default(ren, p, textc, te[8]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
draw_text_default(ren, p, textc, te[9]); |
|
||||||
p.y += 40; |
|
||||||
|
|
||||||
|
|
||||||
p.x = width / 8; |
|
||||||
p.y = height / 9; |
|
||||||
int arlen = sizeof(game_name) / sizeof(game_name[0]); |
|
||||||
for (int i = 0; i < arlen; i ++) { |
|
||||||
draw_text(ren, LARGE, p, textc, game_name[i]); |
|
||||||
p.y += 75; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void redraw_buffer(SDL_Renderer * ren) { |
|
||||||
static int mousex = 0; |
|
||||||
static int mousey = 0; |
|
||||||
static int newmousex = 0;
|
|
||||||
static int newmousey = 0; |
|
||||||
static SDL_Point *bgPixels[256]; |
|
||||||
static int numpixels[256]; |
|
||||||
|
|
||||||
int col = 0; |
|
||||||
Body lplayer; |
|
||||||
|
|
||||||
if (SDL_LockMutex(player.physics->lock) == 0){ |
|
||||||
lplayer = *player.physics; |
|
||||||
update_viewport(&lplayer); |
|
||||||
} else { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
static struct timespec last = {}; |
|
||||||
static struct timespec now; |
|
||||||
now = get_now_d(); |
|
||||||
time_delta = now.tv_nsec - last.tv_nsec; |
|
||||||
time_delta *= 0.000001; // convert to ms from ns
|
|
||||||
|
|
||||||
last = now; |
|
||||||
|
|
||||||
const struct environment* scene = get_scene_watch(); |
|
||||||
draw_environment(ren, scene); |
|
||||||
if (!game_paused) |
|
||||||
draw_level_time(ren, scene); |
|
||||||
SDL_UnlockMutex(player.physics->lock); |
|
||||||
|
|
||||||
for (int i=0; i < world.items.size; i++) { |
|
||||||
world_thing thing; |
|
||||||
thing = world.get(i); |
|
||||||
|
|
||||||
switch (thing.kind) { |
|
||||||
case STATIC_WALL_W: |
|
||||||
draw_wall(ren, thing.wall); |
|
||||||
draw_collision_poly(ren, thing.wall->physics); |
|
||||||
continue; |
|
||||||
case FLOOR: |
|
||||||
for (int i = 0; i < thing.floor->numPolys; i++) { |
|
||||||
draw_floor(ren, &thing.floor->polys[i], true); |
|
||||||
draw_collision_poly(ren, thing.floor->polys[i].physics); |
|
||||||
} |
|
||||||
continue; |
|
||||||
case CEILING: |
|
||||||
for (int i = 0; i < thing.floor->numPolys; i++) { |
|
||||||
draw_floor(ren, &thing.floor->polys[i], false); |
|
||||||
draw_collision_poly(ren, thing.floor->polys[i].physics); |
|
||||||
} |
|
||||||
continue; |
|
||||||
case ROOM_W: |
|
||||||
for (int i = 0; i < thing.room->ceil.numItems; i++) { |
|
||||||
draw_collision_poly(ren, thing.room->ceil.items[i]); |
|
||||||
} |
|
||||||
for (int i = 0; i < thing.room->floor.numItems; i++) { |
|
||||||
draw_collision_poly(ren, thing.room->floor.items[i]); |
|
||||||
} |
|
||||||
default: |
|
||||||
continue; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
draw_player(ren, lplayer.position.x, lplayer.position.y,
|
|
||||||
lplayer.colliding); |
|
||||||
draw_collision_poly(ren, &lplayer); |
|
||||||
draw_forces(ren, &lplayer); |
|
||||||
draw_mute_button(ren); |
|
||||||
|
|
||||||
if (gameui.currently_bound_textbox) { |
|
||||||
draw_level_chooser_tbox(ren); |
|
||||||
} |
|
||||||
|
|
||||||
if (game_paused) { |
|
||||||
SDL_Rect r = {.x = 0, .y = 0, .w = width, .h = height}; |
|
||||||
SDL_SetRenderDrawColor(ren, 0, 0, 0, 90); |
|
||||||
SDL_RenderFillRect(ren, &r); |
|
||||||
if (in_game) |
|
||||||
draw_pause_screen(ren, scene); |
|
||||||
} |
|
||||||
|
|
||||||
if (draw_watch.goto_level && in_game == false) { |
|
||||||
Vect pos = {.x=width/3, .y=height- height/4}; |
|
||||||
draw_text(ren, LARGE, pos, scene->colours.fg1, "Press a Key to Continue"); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
@ -1,54 +0,0 @@ |
|||||||
#ifndef _DEFDRAW |
|
||||||
#define _DEFDRAW |
|
||||||
|
|
||||||
#include <SDL2/SDL.h> |
|
||||||
#include <SDL2/SDL_ttf.h> |
|
||||||
|
|
||||||
#include "c-colours/colours.h" |
|
||||||
#include "vect.h" |
|
||||||
#include "environment.h" |
|
||||||
#include "game.h" |
|
||||||
|
|
||||||
#define SHOWCOLLISION 0 |
|
||||||
#define SHOWFORCES 0 |
|
||||||
|
|
||||||
typedef enum { |
|
||||||
PLAYER |
|
||||||
} draw_type; |
|
||||||
|
|
||||||
void render_texture_at(struct SDL_Renderer * ren, struct SDL_Texture * texture,int x, int y) ; |
|
||||||
/* draw a texture at x.y */ |
|
||||||
|
|
||||||
SDL_Texture * load_image(SDL_Renderer * ren, char fname[]);
|
|
||||||
/* Load an image into a texture */ |
|
||||||
|
|
||||||
void draw_player(SDL_Renderer * ren, int x, int y, bool red);
|
|
||||||
/* draw the player as a coloured rect */ |
|
||||||
|
|
||||||
//void queue_draw_item(void * object, draw_type kind);
|
|
||||||
void add_to_view(draw_type kind, void * object);
|
|
||||||
|
|
||||||
void redraw_buffer(SDL_Renderer * ren);
|
|
||||||
|
|
||||||
void draw_text_default(SDL_Renderer *ren, Vect pos, struct colour colour, char *text);
|
|
||||||
|
|
||||||
enum FontNames { |
|
||||||
DEFAULT, |
|
||||||
LARGE |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
void load_fonts(void);
|
|
||||||
|
|
||||||
void draw_text(SDL_Renderer *ren, enum FontNames fontID, Vect pos, struct colour colour, char *text);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int draw_end_screen(SDL_Renderer *ren);
|
|
||||||
|
|
||||||
extern Vect viewport_pos; |
|
||||||
extern int width, height; |
|
||||||
extern bool high_contrast_mode; |
|
||||||
|
|
||||||
|
|
||||||
#endif |
|
@ -1,262 +0,0 @@ |
|||||||
#include "environment.h" |
|
||||||
#include "game.h" |
|
||||||
#include "types.h" |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct environment * environment_watch = NULL; |
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Environment / World Generation |
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
* |
|
||||||
* Worlds have to be shared across threads, since they contain both collision |
|
||||||
* bodies and drawing information. Realistically, these should be stored in |
|
||||||
* separate datastructures. My solution has been to just store a copy in each |
|
||||||
* thread, and lock everything when you move to the next level and need to |
|
||||||
* generate a new one.
|
|
||||||
* |
|
||||||
* An 'environment' consists of the cave structure with the collision bodies, |
|
||||||
* as well as the colourscheme for drawing it. These are procedurally |
|
||||||
* generated. A custom PRNG function is used so the same levels are given on |
|
||||||
* every platform. |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
const struct environment* get_scene_watch(void) { |
|
||||||
return environment_watch; |
|
||||||
} |
|
||||||
|
|
||||||
double linear_interpolate(double a0, double a1, double w) { |
|
||||||
return (1.0f - w) * a0 + w * a1; |
|
||||||
} |
|
||||||
|
|
||||||
int destroy_environment(struct environment *e) { |
|
||||||
|
|
||||||
arlst_destroy(&e->ceil); |
|
||||||
arlst_destroy(&e->floor); |
|
||||||
arlst_destroy(&e->bg1); |
|
||||||
arlst_destroy(&e->bg2); |
|
||||||
|
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
double perlin(Vect coordinate) { |
|
||||||
Vect a = coordinate; |
|
||||||
Vect b = coordinate; |
|
||||||
a.x = (int)a.x; |
|
||||||
a.y = (int)a.y; |
|
||||||
b.x = a.x + 1; |
|
||||||
b.y = a.y + 1; |
|
||||||
|
|
||||||
double sx = coordinate.x - a.x; |
|
||||||
double sy = coordinate.y - a.y; |
|
||||||
|
|
||||||
Vect d = b; |
|
||||||
d.y = a.y; |
|
||||||
|
|
||||||
double n0 = vect_dot(a, coordinate); |
|
||||||
double n1 = vect_dot(d, coordinate); |
|
||||||
|
|
||||||
double ix0 = linear_interpolate(n0, n1, sx); |
|
||||||
|
|
||||||
Vect c; |
|
||||||
c.x = a.x; |
|
||||||
c.y = b.y; |
|
||||||
|
|
||||||
n0 = vect_dot(c, coordinate); |
|
||||||
n1 = vect_dot(b, coordinate); |
|
||||||
double ix1 = linear_interpolate(n0, n1, sy); |
|
||||||
|
|
||||||
return linear_interpolate(ix0, ix1, sy); |
|
||||||
} |
|
||||||
|
|
||||||
struct colour_pallete get_pallete_high_contrast(void) { |
|
||||||
struct colour white = {.r = 255, .g=255,.b=255, .sp=CS_RGB}; |
|
||||||
struct colour black = {.r = 0, .g=0,.b=0, .sp=CS_RGB}; |
|
||||||
struct colour_pallete p = {.bg = black, .fg1 = white, .fg2 = white, .fg3 = white}; |
|
||||||
return p; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
struct colour_pallete get_pallete (int seed) { |
|
||||||
struct colour base; |
|
||||||
|
|
||||||
int n = seed; |
|
||||||
int red = get_rand(&n) % 255; |
|
||||||
int blue = get_rand(&n) % 255; |
|
||||||
int green = get_rand(&n) % 255; |
|
||||||
|
|
||||||
base.r = red; |
|
||||||
base.g = green; |
|
||||||
base.b = blue; |
|
||||||
|
|
||||||
struct colour c1 = get_hsv(base); |
|
||||||
c1 = get_hsv(base); |
|
||||||
struct colour_pallete cols; |
|
||||||
|
|
||||||
c1.l = 0.1; |
|
||||||
cols.bg = get_rgb(c1); |
|
||||||
c1.l += 0.3; |
|
||||||
|
|
||||||
c1.h += 30; |
|
||||||
cols.fg1 = get_rgb(c1); |
|
||||||
|
|
||||||
c1.h += 30; |
|
||||||
cols.fg2 = get_rgb(c1); |
|
||||||
|
|
||||||
c1.h += 30; |
|
||||||
cols.fg3 = get_rgb(c1); |
|
||||||
|
|
||||||
return cols; |
|
||||||
|
|
||||||
struct colour *adj = get_adjacent(base, 20, 4); |
|
||||||
ArrayList l = new_arlst_wfree(4, free); |
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) { |
|
||||||
arlst_add(&l, adj + i); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
int comp(const void *one, const void *two) { |
|
||||||
return *(int*)one >= *(int*)two; |
|
||||||
} |
|
||||||
|
|
||||||
void swap_palletes(struct environment *e) { |
|
||||||
struct colour_pallete b = e->colours; |
|
||||||
e->colours = e->coloursb; |
|
||||||
e->coloursb = b; |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* |
|
||||||
* Generate or just return the environment seeded by the current level number. |
|
||||||
* |
|
||||||
*/ |
|
||||||
struct environment get_scene_at(Vect coordinate, int seed) { |
|
||||||
// TODO: Environment needs to be shared between threads
|
|
||||||
// - this implementation duplicates it: each thread that calls
|
|
||||||
// get_scene_at gets manages its state in its own static vairables in
|
|
||||||
// this function but share pointers to the malloced environment object-
|
|
||||||
// it is thoroughly broken.
|
|
||||||
// - Fix by having a heap allocated environment object that the draw thread
|
|
||||||
// (T0) can watch and the physics thread (T3) can modify
|
|
||||||
// - the entry point can either be through a function returning
|
|
||||||
// a pointer or just a global const pointer
|
|
||||||
//
|
|
||||||
// basic cache for the last room generated
|
|
||||||
static bool init; |
|
||||||
static Vect last_room; |
|
||||||
static struct environment e; |
|
||||||
static int oldseed; |
|
||||||
Vect room_coord; |
|
||||||
room_coord.x = (int)coordinate.x - (int)coordinate.x % E_ROOM_WIDTH; |
|
||||||
room_coord.y = 0; |
|
||||||
|
|
||||||
if (init && room_coord.x == last_room.x && oldseed == seed) { |
|
||||||
return e; |
|
||||||
} else if (init) { |
|
||||||
destroy_environment(&e); |
|
||||||
} |
|
||||||
last_room = room_coord; |
|
||||||
oldseed = seed; |
|
||||||
|
|
||||||
e.floor = new_arlst_wfree(E_ROOM_TILES, free); |
|
||||||
e.ceil = new_arlst_wfree(E_ROOM_TILES, free); |
|
||||||
e.bg1 = new_arlst_wfree(E_ROOM_TILES, free); |
|
||||||
e.bg2 = new_arlst_wfree(E_ROOM_TILES, free); |
|
||||||
|
|
||||||
e.colours = get_pallete(seed); |
|
||||||
e.coloursb = get_pallete_high_contrast(); |
|
||||||
|
|
||||||
if (draw_watch.high_contrast_mode)
|
|
||||||
swap_palletes(&e); |
|
||||||
|
|
||||||
Vect bit; |
|
||||||
bit.y = 100 * seed; |
|
||||||
Vect pos; |
|
||||||
|
|
||||||
int n = seed; |
|
||||||
get_rand(&n); |
|
||||||
|
|
||||||
Vect node; |
|
||||||
node.y = 0; |
|
||||||
|
|
||||||
for (int i = 0; i < E_ROOM_WIDTH; i += E_ROOM_RES) { |
|
||||||
bit.x = room_coord.x + i; |
|
||||||
bit.y = seed; |
|
||||||
node.x = bit.x; |
|
||||||
|
|
||||||
int r1 = 1.5*(get_rand(&n) % 500) - (get_rand(&n) % 100);
|
|
||||||
int r2 = 1.5*(get_rand(&n) % 200) - (get_rand(&n) % 200); |
|
||||||
int r3 = (get_rand(&n) % 100) - (get_rand(&n) % 500); |
|
||||||
int r4 = 50; |
|
||||||
|
|
||||||
int r[4] = {r1, r2, r3, r4}; |
|
||||||
qsort(r, 4, sizeof(int), comp); |
|
||||||
|
|
||||||
int h[4] = {node.y,node.y,node.y,node.y}; |
|
||||||
h[0] += r[0]; |
|
||||||
h[1] = h[0] + r[1]; |
|
||||||
h[2] += h[0] + r[2]; |
|
||||||
h[3] += h[0] + r[3]; |
|
||||||
qsort(h, 4, sizeof(int), comp); |
|
||||||
|
|
||||||
Vect *z = malloc(sizeof(Vect)); |
|
||||||
*z = node; |
|
||||||
z->y = h[0]; |
|
||||||
|
|
||||||
arlst_add(&e.floor, z); |
|
||||||
|
|
||||||
z = malloc(sizeof(Vect)); |
|
||||||
*z = node; |
|
||||||
z->y = h[1]; |
|
||||||
arlst_add(&e.bg1, z); |
|
||||||
|
|
||||||
z = malloc(sizeof(Vect)); |
|
||||||
*z = node; |
|
||||||
z->y = h[2]; |
|
||||||
arlst_add(&e.bg2, z); |
|
||||||
|
|
||||||
|
|
||||||
z = malloc(sizeof(Vect)); |
|
||||||
*z = node; |
|
||||||
z->y = h[3]; |
|
||||||
arlst_add(&e.ceil, z); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
Vect *v = arlst_get(&e.floor, 0);
|
|
||||||
Vect v2 = *(Vect *)arlst_get(&e.ceil, 0);
|
|
||||||
|
|
||||||
Vect v3 = vect_add(v2, vect_scalar(vect_add(*v, vect_scalar(v2, -1)) , 0.5)); |
|
||||||
|
|
||||||
int d[] = {0, E_ROOM_TILES - 1}; |
|
||||||
int a; |
|
||||||
for (int i = 0; i <= 1; i++) { |
|
||||||
a = d[i]; |
|
||||||
v = arlst_get(&e.floor, a);
|
|
||||||
v->y = v3.x; |
|
||||||
v = arlst_get(&e.ceil, a);
|
|
||||||
v->y = v3.x; |
|
||||||
v = arlst_get(&e.bg1, a);
|
|
||||||
v->y = v3.x; |
|
||||||
v = arlst_get(&e.bg2, a);
|
|
||||||
v->y = v3.x; |
|
||||||
} |
|
||||||
|
|
||||||
// join the end and start together
|
|
||||||
|
|
||||||
if (!init) { |
|
||||||
struct environment *ee = malloc(sizeof(struct environment)); |
|
||||||
environment_watch = ee; |
|
||||||
} |
|
||||||
|
|
||||||
*environment_watch = e; |
|
||||||
|
|
||||||
init = true; |
|
||||||
|
|
||||||
return e; |
|
||||||
} |
|
@ -1,16 +0,0 @@ |
|||||||
#ifndef ENVIRO_H |
|
||||||
#define ENVIRO_H |
|
||||||
|
|
||||||
#include "vect.h" |
|
||||||
#include "types.h" |
|
||||||
|
|
||||||
struct environment get_scene_at(Vect coordinate, int seed);
|
|
||||||
int destroy_environment(struct environment *e); |
|
||||||
|
|
||||||
const struct environment *get_scene_watch(void); |
|
||||||
|
|
||||||
extern struct environment *environment_watch; |
|
||||||
|
|
||||||
void swap_palletes(struct environment *e);
|
|
||||||
|
|
||||||
#endif |
|
@ -1,85 +0,0 @@ |
|||||||
#ifndef _DEFGAME |
|
||||||
#define _DEFGAME |
|
||||||
|
|
||||||
#include "environment.h" |
|
||||||
#include "datastructures/datatypes.h" |
|
||||||
#include "vect.h" |
|
||||||
#include "controlscheme.h" |
|
||||||
#include "c-colours/colours.h" |
|
||||||
#include "types.h" |
|
||||||
#include "draw.h" |
|
||||||
|
|
||||||
extern GlobWorld world; |
|
||||||
extern int level; |
|
||||||
extern bool in_game; |
|
||||||
extern int quality; |
|
||||||
|
|
||||||
|
|
||||||
struct draw_watcher { |
|
||||||
long best_time; |
|
||||||
bool finish_level; |
|
||||||
bool goto_level; |
|
||||||
bool high_contrast_mode; |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
struct ui_state { |
|
||||||
struct textbox_info *currently_bound_textbox; |
|
||||||
int goto_new_level; |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
enum TextBoxId { |
|
||||||
TB_LEVEL_CHOOSER = 0 |
|
||||||
}; |
|
||||||
|
|
||||||
struct textbox_info { |
|
||||||
enum TextBoxId id; |
|
||||||
bool capture_input_text_field; |
|
||||||
char text_input[32]; |
|
||||||
int text_input_bufpos; |
|
||||||
void (*close_callback)(struct textbox_info *textbox, void*callback); |
|
||||||
}; |
|
||||||
|
|
||||||
extern struct draw_watcher draw_watch; |
|
||||||
extern struct textbox_info* texboxes; |
|
||||||
extern struct ui_state gameui; |
|
||||||
|
|
||||||
|
|
||||||
void handle_input_event(SDL_Event event); |
|
||||||
|
|
||||||
// add a motor to the world
|
|
||||||
void add_motor(Body *thing, double x, double y);
|
|
||||||
|
|
||||||
bool get_motor_active(Body *thing, int i);
|
|
||||||
|
|
||||||
/* temporary storage variable *n should be initialised to the seed value */ |
|
||||||
int get_rand(int *n);
|
|
||||||
|
|
||||||
void next_level(int lvl);
|
|
||||||
|
|
||||||
int step(void); |
|
||||||
|
|
||||||
struct sg_times_list { |
|
||||||
long *times; |
|
||||||
int size; |
|
||||||
int capacity; |
|
||||||
void (*sort)(void); |
|
||||||
char *filename; |
|
||||||
}; |
|
||||||
|
|
||||||
int load_score_times(char *filename);
|
|
||||||
|
|
||||||
|
|
||||||
/* array of all the things in the world and their kinds */ |
|
||||||
|
|
||||||
extern struct sg_times_list save_times_lst; |
|
||||||
int add_time(long time);
|
|
||||||
int write_times(void);
|
|
||||||
extern void startgame(SDL_Renderer * ren) ; |
|
||||||
extern void process_keydown(SDL_Keysym key); |
|
||||||
extern void process_keyup(SDL_Keysym key); |
|
||||||
extern player_st player; |
|
||||||
extern long level_time; |
|
||||||
extern bool game_paused; |
|
||||||
#endif |
|
@ -1,181 +0,0 @@ |
|||||||
#include <SDL2/SDL_mutex.h> |
|
||||||
#include <SDL2/SDL_audio.h> |
|
||||||
#include <SDL2/SDL_scancode.h> |
|
||||||
#include <SDL2/SDL_mixer.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <stdlib.h> |
|
||||||
#include <string.h> |
|
||||||
#include <SDL2/SDL.h> |
|
||||||
#include <string.h> |
|
||||||
#include <time.h> |
|
||||||
#include <stdbool.h> |
|
||||||
#include <math.h> |
|
||||||
#include <stdbool.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <sys/stat.h> |
|
||||||
|
|
||||||
#include "audio.h" |
|
||||||
|
|
||||||
#include "game.h" |
|
||||||
#include "draw.h" |
|
||||||
#include "types.h" |
|
||||||
|
|
||||||
const int screen_width = 800; |
|
||||||
const int screen_height = 600; |
|
||||||
|
|
||||||
|
|
||||||
SDL_sem *resume; |
|
||||||
|
|
||||||
|
|
||||||
struct SDL_Window* make_window(void) { |
|
||||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
|
||||||
printf("error initializing SDL: %s\n", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return SDL_CreateWindow("space_game",
|
|
||||||
SDL_WINDOWPOS_CENTERED,
|
|
||||||
SDL_WINDOWPOS_CENTERED,
|
|
||||||
0, 0,
|
|
||||||
SDL_WINDOW_FULLSCREEN_DESKTOP);
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void redraw(struct SDL_Renderer * ren) { |
|
||||||
SDL_RenderClear(ren); |
|
||||||
redraw_buffer(ren); |
|
||||||
SDL_RenderPresent(ren); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void godophysics(void) { |
|
||||||
int lvl; |
|
||||||
if ((lvl = step())) { |
|
||||||
// display end level screen
|
|
||||||
in_game = false; |
|
||||||
game_paused = true; |
|
||||||
SDL_Delay(300); |
|
||||||
SDL_SemWait(resume); |
|
||||||
add_time(level_time); |
|
||||||
|
|
||||||
SDL_LockMutex(player.physics->lock); |
|
||||||
next_level(lvl); |
|
||||||
in_game = true; |
|
||||||
SDL_UnlockMutex(player.physics->lock); |
|
||||||
SDL_Delay(1000); |
|
||||||
game_paused = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
int physics_loop(void *ptr) { |
|
||||||
game_paused = 1; |
|
||||||
while (1) { |
|
||||||
godophysics(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int game(void) { |
|
||||||
|
|
||||||
SDL_Window * win = make_window(); |
|
||||||
SDL_Renderer * ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED |
|
||||||
#ifdef USE_VSYNC |
|
||||||
| SDL_RENDERER_PRESENTVSYNC |
|
||||||
#endif |
|
||||||
); |
|
||||||
SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); |
|
||||||
|
|
||||||
|
|
||||||
in_game = true; |
|
||||||
resume = SDL_CreateSemaphore(0); |
|
||||||
|
|
||||||
if (ren == NULL) { |
|
||||||
SDL_DestroyWindow(win); |
|
||||||
SDL_Quit(); |
|
||||||
} |
|
||||||
|
|
||||||
TTF_Init(); |
|
||||||
|
|
||||||
int close = 0; |
|
||||||
|
|
||||||
//draw_pictures(ren);
|
|
||||||
|
|
||||||
SDL_Thread *physics_thread; |
|
||||||
int ignore; |
|
||||||
|
|
||||||
startgame(ren); |
|
||||||
|
|
||||||
physics_thread = SDL_CreateThread(physics_loop, "physics", (void *)ren); |
|
||||||
|
|
||||||
int count = 0; |
|
||||||
|
|
||||||
while (!close) { |
|
||||||
SDL_Event event;
|
|
||||||
while(SDL_PollEvent(&event)) { |
|
||||||
switch (event.type) { |
|
||||||
case SDL_QUIT: |
|
||||||
goto endfunc; |
|
||||||
case SDL_KEYDOWN: |
|
||||||
if (event.key.keysym.scancode == SDL_SCANCODE_Q) { |
|
||||||
goto endfunc; |
|
||||||
} |
|
||||||
if (!in_game && !SDL_SemValue(resume)) { |
|
||||||
SDL_SemPost(resume); |
|
||||||
} |
|
||||||
case SDL_KEYUP: |
|
||||||
case SDL_MOUSEBUTTONDOWN: |
|
||||||
case SDL_MOUSEBUTTONUP: |
|
||||||
handle_input_event (event); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (!in_game && draw_watch.finish_level) { |
|
||||||
draw_end_screen(ren); |
|
||||||
} else { |
|
||||||
redraw(ren); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
endfunc: |
|
||||||
|
|
||||||
SDL_DestroyRenderer(ren); |
|
||||||
SDL_DestroyWindow(win); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int main (int argc, char** argv) { |
|
||||||
|
|
||||||
#ifdef __linux__ |
|
||||||
mkdirat(AT_FDCWD, "saves", 0777); |
|
||||||
#elif WIN32 |
|
||||||
if (access("saves", 0) == 0) { |
|
||||||
struct stat status; |
|
||||||
stat("saves", &status ); |
|
||||||
if ((status.st_mode & S_IFDIR) == 0) { |
|
||||||
_mkdir("saves"); |
|
||||||
} |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
game(); |
|
||||||
|
|
||||||
SDL_Quit(); |
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO:
|
|
||||||
* - Allow setting and saving/loading differnet control schemes |
|
||||||
* - Allow adjusging level lengths? |
|
||||||
* - fix that weird jitter |
|
||||||
* - Fix open screen and pause screens |
|
||||||
* - make the end of level look sane |
|
||||||
* - restart level |
|
||||||
* - make sure goto level doesn't log an end-0f-level time? |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
@ -1,238 +0,0 @@ |
|||||||
|
|
||||||
#ifndef PTYPES_H |
|
||||||
#define PTYPES_H |
|
||||||
|
|
||||||
#include <SDL2/SDL_mutex.h> |
|
||||||
#include <SDL2/SDL_audio.h> |
|
||||||
#include <SDL2/SDL_scancode.h> |
|
||||||
#include <SDL2/SDL_mixer.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <stdlib.h> |
|
||||||
#include <string.h> |
|
||||||
#include <SDL2/SDL.h> |
|
||||||
#include <string.h> |
|
||||||
#include <time.h> |
|
||||||
#include <stdbool.h> |
|
||||||
#include <math.h> |
|
||||||
|
|
||||||
#include "c-colours/colours.h" |
|
||||||
#include "datastructures/datatypes.h" |
|
||||||
#include "vect.h" |
|
||||||
|
|
||||||
enum motors { |
|
||||||
M_GRAVITY = 0, |
|
||||||
M_FRICTION = 1, |
|
||||||
M_PLAYER_WALK = 2, |
|
||||||
M_WINCH = 3 |
|
||||||
}; |
|
||||||
|
|
||||||
enum world_thing_kind { |
|
||||||
PLAYER_W = 0, |
|
||||||
FLOOR = 1, |
|
||||||
CEILING = 2, |
|
||||||
ROOM_W, |
|
||||||
STATIC_WALL_W,
|
|
||||||
PROJECTILE |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
// used to exert a force on an object
|
|
||||||
typedef struct motorstruct { |
|
||||||
double x; // positive is right
|
|
||||||
double y; // positive is down
|
|
||||||
double torque; // positive is anticlockwise
|
|
||||||
double max_velocity; // max motor output velocity
|
|
||||||
// does not apply force if the velocity in the
|
|
||||||
// direction of the motor vector is greater than
|
|
||||||
// max_velocity
|
|
||||||
|
|
||||||
struct timespec timeout;// absolute time (in ns, from when the program starts)
|
|
||||||
// for how long the motor runs before stopping
|
|
||||||
// automatically
|
|
||||||
// set to -1 for infinity
|
|
||||||
bool stop; // turn the motor off or on
|
|
||||||
void (*update_motor)(struct motorstruct *motor); // function pointer for generating
|
|
||||||
// the motor's output curve
|
|
||||||
struct BodyStruct *end_object; |
|
||||||
} Motor; |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
int x; |
|
||||||
int y; |
|
||||||
} Point; |
|
||||||
|
|
||||||
/* String structure, used as a sub-element of a Body, compressible, but not
|
|
||||||
* stretchable. */ |
|
||||||
struct String { |
|
||||||
bool attached; |
|
||||||
double max_length; |
|
||||||
Vect end_point; |
|
||||||
int (*update_end_point)(struct String*); // method to update the end pt
|
|
||||||
// say if string is attached
|
|
||||||
// to another object
|
|
||||||
int (*set_end_point)(struct String*, Vect *); // manually set the end point of
|
|
||||||
// string
|
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct String String; |
|
||||||
|
|
||||||
typedef struct BodyStruct{ |
|
||||||
// turn on dynamic physics
|
|
||||||
// For moving objects.
|
|
||||||
// eg. on for payer, off for walls
|
|
||||||
bool dynamics; |
|
||||||
|
|
||||||
// unique identifier
|
|
||||||
int uid; |
|
||||||
|
|
||||||
bool colliding; |
|
||||||
int was_colliding; |
|
||||||
|
|
||||||
// position in viewport (pixels)
|
|
||||||
SDL_Point screen_pos; |
|
||||||
SDL_mutex * lock; |
|
||||||
|
|
||||||
// SI Unit kinematics
|
|
||||||
/*------------------*/ |
|
||||||
Vect position; |
|
||||||
Vect next_position; // used for casting collision
|
|
||||||
Vect vel; |
|
||||||
Vect acc; |
|
||||||
|
|
||||||
// properties
|
|
||||||
double obj_mass; // kgs
|
|
||||||
double obj_elasticity; // rho
|
|
||||||
double obj_friction; // between 0 and 1 (fraction of lateral velocity
|
|
||||||
// that is removed)
|
|
||||||
|
|
||||||
// collisions
|
|
||||||
Vect *collision_poly; |
|
||||||
Vect *collision_shape; |
|
||||||
int collision_poly_size; |
|
||||||
int collision_shape_size; |
|
||||||
void (*updateCollisionPoly)(struct BodyStruct *); |
|
||||||
|
|
||||||
// fields
|
|
||||||
double glob_friction; |
|
||||||
bool glob_gravity; // t/f
|
|
||||||
|
|
||||||
// uint32_t last_advance_time;
|
|
||||||
|
|
||||||
struct timespec last_advance_time; |
|
||||||
|
|
||||||
// applying forces
|
|
||||||
int num_motors; |
|
||||||
int max_motors; |
|
||||||
Motor *motors; |
|
||||||
|
|
||||||
int num_strings; |
|
||||||
int max_strings; |
|
||||||
String *strings; |
|
||||||
|
|
||||||
} Body; |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
bool has_physics; |
|
||||||
Body *physics; |
|
||||||
int max_walking_speed; |
|
||||||
int colliding; |
|
||||||
} player_st; |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
int numNodes; |
|
||||||
SDL_Point *nodes; |
|
||||||
Body *physics; |
|
||||||
} Wall; |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
Vect left; |
|
||||||
Vect right; |
|
||||||
Body *physics;
|
|
||||||
} FloorPoly; |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
FloorPoly *polys; |
|
||||||
int numPolys; |
|
||||||
} Floor; |
|
||||||
|
|
||||||
struct physics_collection { |
|
||||||
int numItems; |
|
||||||
Body **items; |
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct Projectile { |
|
||||||
Body *physics; |
|
||||||
void*(*on_collision)(struct Projectile*); |
|
||||||
void*(*on_step)(struct Projectile*); |
|
||||||
} Projectile; |
|
||||||
|
|
||||||
struct colour_pallete { |
|
||||||
struct colour bg; |
|
||||||
struct colour fg1; |
|
||||||
struct colour fg2; |
|
||||||
struct colour fg3; |
|
||||||
};
|
|
||||||
|
|
||||||
struct environment { |
|
||||||
int level; |
|
||||||
Vect position; |
|
||||||
ArrayList ceil; // doubles
|
|
||||||
ArrayList floor; // doubles
|
|
||||||
ArrayList bg1; // doubles
|
|
||||||
ArrayList bg2; // doubles
|
|
||||||
struct colour_pallete colours; |
|
||||||
struct colour_pallete coloursb; |
|
||||||
struct physics_collection physics; |
|
||||||
}; |
|
||||||
|
|
||||||
struct room { |
|
||||||
struct environment env; |
|
||||||
struct physics_collection ceil; |
|
||||||
struct physics_collection floor; |
|
||||||
}; |
|
||||||
|
|
||||||
struct world_thing { |
|
||||||
enum world_thing_kind kind; |
|
||||||
int nid; |
|
||||||
bool collisions; |
|
||||||
bool physics; |
|
||||||
// free function for the below type
|
|
||||||
void (*free)(void *);
|
|
||||||
union { |
|
||||||
player_st *player; |
|
||||||
Wall *wall; |
|
||||||
Floor *floor; |
|
||||||
Projectile *projectile; |
|
||||||
struct room *room; |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct world_thing world_thing; |
|
||||||
|
|
||||||
struct world { |
|
||||||
world_thing (*get)(int i); |
|
||||||
ArrayList items; |
|
||||||
int modified; |
|
||||||
world_thing** uniques_index; |
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct world GlobWorld; |
|
||||||
|
|
||||||
// environment
|
|
||||||
|
|
||||||
enum { |
|
||||||
E_ROOM_WIDTH = 10000, |
|
||||||
E_ROOM_RES = 500, |
|
||||||
E_ROOM_TILES = E_ROOM_WIDTH / E_ROOM_RES, |
|
||||||
}; |
|
||||||
|
|
||||||
struct button { |
|
||||||
char *name; |
|
||||||
bool state; |
|
||||||
bool held; |
|
||||||
int x, y, w, h; |
|
||||||
}; |
|
||||||
|
|
||||||
extern struct button mute_button; |
|
||||||
|
|
||||||
#endif |
|
@ -1,81 +0,0 @@ |
|||||||
#include "vect.h" |
|
||||||
|
|
||||||
double vect_dot(Vect V, Vect B) { |
|
||||||
return V.x * B.x + V.y * B.y; |
|
||||||
} |
|
||||||
|
|
||||||
double vect_mag(Vect v) { |
|
||||||
double mag = sqrt((v.x * v.x) + (v.y * v.y)); |
|
||||||
return mag; |
|
||||||
} |
|
||||||
|
|
||||||
Vect vect_scalar(Vect V, double s) { |
|
||||||
Vect ret; |
|
||||||
ret.x = V.x * s; |
|
||||||
ret.y = V.y * s; |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
double vect_arg(Vect v) { |
|
||||||
return atan2(v.y, v.x); |
|
||||||
} |
|
||||||
|
|
||||||
Vect vect_modarg(double mod, double arg) { |
|
||||||
Vect ret; |
|
||||||
ret.x = mod * cos(arg); |
|
||||||
ret.y = mod * sin(arg); |
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
Vect vect_rotate(Vect v, double radians) { |
|
||||||
Vect res; |
|
||||||
|
|
||||||
res.x = v.x * cos(radians) - v.y * sin(radians); |
|
||||||
res.y = v.x * sin(radians) + v.y * cos(radians); |
|
||||||
return res; |
|
||||||
} |
|
||||||
|
|
||||||
Vect vect_add(Vect v1, Vect v2) { |
|
||||||
Vect res; |
|
||||||
res.x = v1.x + v2.x; |
|
||||||
res.y = v1.y + v2.y; |
|
||||||
return res; |
|
||||||
} |
|
||||||
|
|
||||||
// project one onto two
|
|
||||||
Vect project_vect(Vect one, Vect two) { |
|
||||||
// $$ a \cdot \frac {|b|} {b} $$
|
|
||||||
Vect unittwo; |
|
||||||
unittwo.x = two.x / vect_mag(two); |
|
||||||
unittwo.y = two.y / vect_mag(two); |
|
||||||
|
|
||||||
Vect proj; |
|
||||||
proj.x = unittwo.x * one.x; |
|
||||||
proj.y = unittwo.y * one.y; |
|
||||||
|
|
||||||
return proj; |
|
||||||
} |
|
||||||
|
|
||||||
// project V onto P
|
|
||||||
double old_vect_scalar_projection(Vect V, Vect P) { |
|
||||||
double angle = vect_dir(V) - vect_dir(P); |
|
||||||
return cos(angle) * vect_mag(V); |
|
||||||
} |
|
||||||
|
|
||||||
double vect_scalar_projection(Vect v, Vect p) { |
|
||||||
double num = vect_dot(v, p); |
|
||||||
return num / vect_mag(p); |
|
||||||
} |
|
||||||
|
|
||||||
double vect_dir(Vect V) { |
|
||||||
return atan2(V.y, V.x); |
|
||||||
} |
|
||||||
|
|
||||||
// distance between two points
|
|
||||||
double vect_distance(Vect A, Vect B) { |
|
||||||
double y = (B.y - A.y); |
|
||||||
double x = (B.x - A.x); |
|
||||||
y = y * y; |
|
||||||
x = x * x; |
|
||||||
return sqrt(x + y); |
|
||||||
} |
|
@ -1,45 +0,0 @@ |
|||||||
|
|
||||||
#ifndef VECT_H |
|
||||||
#define VECT_H |
|
||||||
#include <math.h> |
|
||||||
|
|
||||||
// origin-centred vector
|
|
||||||
typedef struct { |
|
||||||
double x; |
|
||||||
double y; |
|
||||||
} Vect; |
|
||||||
|
|
||||||
/* Return the magnitude of two vectors */ |
|
||||||
double vect_mag(Vect v);
|
|
||||||
|
|
||||||
/* Return the angle of a vector in radians (using atan2) */ |
|
||||||
double vect_dir(Vect V); |
|
||||||
|
|
||||||
/* Return the dot product of two vectors */ |
|
||||||
double vect_dot(Vect V, Vect B);
|
|
||||||
|
|
||||||
/* return a vector multiplied by a scalar */ |
|
||||||
Vect vect_scalar(Vect V, double s); |
|
||||||
|
|
||||||
/* Return the sum of two vectors */ |
|
||||||
Vect vect_add(Vect v1, Vect v2);
|
|
||||||
|
|
||||||
/* Return the projection of vector one onto vector two */ |
|
||||||
Vect project_vect(Vect one, Vect two);
|
|
||||||
|
|
||||||
/* Return the scalar projection of V onto P */ |
|
||||||
double vect_scalar_projection(Vect V, Vect P);
|
|
||||||
|
|
||||||
/* Return the vector v rotated by radians radians. */ |
|
||||||
Vect vect_rotate(Vect v, double radians); |
|
||||||
|
|
||||||
/* Return the argument of v in radians */ |
|
||||||
double vect_arg(Vect v); |
|
||||||
|
|
||||||
/* create a vector using modarg form */ |
|
||||||
Vect vect_modarg(double mod, double arg);
|
|
||||||
|
|
||||||
/* Return the distance between two point vectors A and B */ |
|
||||||
double vect_distance(Vect A, Vect B);
|
|
||||||
|
|
||||||
#endif |
|
Loading…
Reference in new issue