Compare commits
57 Commits
release0.1
...
master
87 changed files with 8935 additions and 990 deletions
@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
|
||||
[submodule "datastructures"] |
||||
path = datastructures |
||||
url = git@git.topost.net:alistair/datastructures.git |
||||
url = https://git.topost.net/alistair/datastructures.git |
||||
[submodule "c-colours"] |
||||
path = c-colours |
||||
url = git@git.topost.net:alistair/c-colours.git |
||||
url = https://git.topost.net/alistair/c-colours.git |
||||
|
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
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/>. |
@ -0,0 +1,97 @@
@@ -0,0 +1,97 @@
|
||||
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. |
@ -0,0 +1,173 @@
@@ -0,0 +1,173 @@
|
||||
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 --- |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
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. |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
|
||||
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 |
||||
|
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
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 |
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
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 |
@ -0,0 +1,674 @@
@@ -0,0 +1,674 @@
|
||||
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,85 +1,99 @@
@@ -1,85 +1,99 @@
|
||||
|
||||
EXE = main
|
||||
|
||||
.PHONY: windows |
||||
.PHONY: linux |
||||
|
||||
sdl2ibdir = sdllib
|
||||
|
||||
ifndef target
|
||||
target=linux
|
||||
endif |
||||
|
||||
ifeq ($(target),windows) |
||||
CC=x86_64-w64-mingw32-gcc
|
||||
SDL_INCLUDE = -Dmain=SDL_main -Lsdllib -lSDL2main -lSDL2main -lSDL2 -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,-static -lpthread -lm
|
||||
CCFLAGS=$(SDL_INCLUDE) -O3
|
||||
CC=x86_64-w64-mingw32-gcc -DWIN32 -g
|
||||
SDL_INCLUDE = -Dmain=SDL_main -Lsdllib -lSDL2main -lSDL2main -lSDL2_mixer -lSDL2_ttf -lSDL2 -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,-static -lpthread -lm
|
||||
CCFLAGS=$(SDL_INCLUDE) -O2
|
||||
else |
||||
CC=gcc
|
||||
SDL_INCLUDE= -lSDL2 -lm
|
||||
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 |
||||
CC=gcc -D__linux__
|
||||
SDL_INCLUDE= -lSDL2 -lSDL2_ttf -lSDL2_mixer -lm
|
||||
CCFLAGS=$(SDL_INCLUDE) -O3
|
||||
endif |
||||
endif |
||||
|
||||
ifdef debug |
||||
CC = $(CC) -g -Wall
|
||||
CC += -fsanitize=address -g -ggdb -fno-omit-frame-pointer -Wall
|
||||
endif |
||||
|
||||
.PHONY: default |
||||
.PHONY: all |
||||
.PHONY: run |
||||
.PHONY: dist |
||||
.PHONY: web |
||||
|
||||
default: all |
||||
|
||||
dist: all |
||||
mkdir -p dist
|
||||
mkdir -p dist/windows
|
||||
mkdir -p dist/linux
|
||||
cp main dist/linux
|
||||
cp main.exe dist/windows
|
||||
cp SDL2.dll 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
|
||||
cd dist && tar -czvf linux.tar.gz linux
|
||||
|
||||
distlin: all |
||||
mkdir -p dist
|
||||
mkdir -p dist/linux
|
||||
cp build/main dist/linux
|
||||
cp README.md dist/linux
|
||||
cd dist && zip -r linux.zip linux
|
||||
|
||||
|
||||
run: all |
||||
./main
|
||||
|
||||
all: $(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 $(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)
|
||||
web: $(EXE) |
||||
$(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)
|
||||
|
||||
|
||||
c-colours/colours.o: c-colours/colours.c c-colours/colours.h |
||||
$(CC) -c c-colours/colours.c -o c-colours/colours.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 |
||||
cd build && $(CC) -o $(EXE) main.o vect.o game.o draw.o environment.o controlscheme.o colours.o datatypes.o audio.o $(CCFLAGS)
|
||||
|
||||
datastructures/datatypes.o: datastructures/datatypes.c datastructures/datatypes.h |
||||
$(CC) -c datastructures/datatypes.c -o datastructures/datatypes.o $(CCFLAGS)
|
||||
build/colours.o: c-colours/colours.c c-colours/colours.h |
||||
$(CC) -c c-colours/colours.c -o build/colours.o $(CCFLAGS)
|
||||
|
||||
main.o: main.c logger.h game.h garbo.h draw.h |
||||
$(CC) -c main.c $(CCFLAGS)
|
||||
build/datatypes.o: datastructures/datatypes.c datastructures/datatypes.h |
||||
$(CC) -c datastructures/datatypes.c -o build/datatypes.o $(CCFLAGS)
|
||||
|
||||
logger.o: logger.c logger.h |
||||
$(CC) -c logger.c $(CCFLAGS)
|
||||
build/main.o: src/main.c |
||||
$(CC) -c src/main.c -o build/main.o $(CCFLAGS)
|
||||
|
||||
game.o: game.c game.h draw.h |
||||
$(CC) -c game.c $(CCFLAGS)
|
||||
build/game.o: src/game.c src/game.h |
||||
$(CC) -c src/game.c -o build/game.o $(CCFLAGS)
|
||||
|
||||
garbo.o: garbo.c garbo.h |
||||
$(CC) -c garbo.c $(CCFLAGS)
|
||||
build/draw.o: src/draw.c src/draw.h |
||||
$(CC) -c src/draw.c -o build/draw.o $(CCFLAGS)
|
||||
|
||||
draw.o: draw.c draw.h |
||||
$(CC) -c draw.c $(CCFLAGS)
|
||||
build/vect.o: src/vect.c src/vect.h |
||||
$(CC) -c src/vect.c -o build/vect.o $(CCFLAGS)
|
||||
|
||||
vect.o: vect.c vect.h |
||||
$(CC) -c vect.c $(CCFLAGS)
|
||||
build/controlscheme.o: src/controlscheme.c src/controlscheme.h |
||||
$(CC) -c src/controlscheme.c -o build/controlscheme.o $(CCFLAGS)
|
||||
|
||||
controlscheme.o: controlscheme.c controlscheme.h |
||||
$(CC) -c controlscheme.c $(CCFLAGS)
|
||||
build/environment.o: src/environment.c src/environment.h |
||||
$(CC) -c src/environment.c -o build/environment.o $(CCFLAGS)
|
||||
|
||||
environment.o: environment.c environment.h |
||||
$(CC) -c environment.c $(CCFLAGS)
|
||||
build/audio.o: src/audio.c src/audio.h |
||||
$(CC) -c src/audio.c -o build/audio.o $(CCFLAGS)
|
||||
|
||||
clean: |
||||
rm c-colours/*.o
|
||||
rm datastructures/*.o
|
||||
rm *.o
|
||||
rm -rf dist
|
||||
rm build/*.o
|
||||
|
||||
prebuild: |
||||
mkdir -p build
|
||||
ln -srf datastructures src/
|
||||
ln -srf c-colours src/
|
||||
|
||||
|
@ -1,22 +1,94 @@
@@ -1,22 +1,94 @@
|
||||
# A computer game |
||||
|
||||
[Developemnt Blog](https://alistairmichael.com/projects/game/) |
||||
[Developement Blog](https://alistairmichael.com/projects/game/) |
||||
|
||||
![image](https://alistairmichael.com/media/game3.png) |
||||
|
||||
# Build Instructions |
||||
This is a simple game where you play as a bouncy square rock that has a grappling hook. It can use the grappling hook to swing to the end of the cave. There is no reward for doing so, but there is a timer. |
||||
|
||||
### Description and Features |
||||
|
||||
- Entirely written in C using only the SDL2 graphics and audio libraries. |
||||
- Procedurally generated cave environment using a random walk and procedurally |
||||
generated colour palettes. |
||||
- Cute synthesized sound effects using integer overflow a la [bytebeat](https://arxiv.org/pdf/1112.1368.pdf). |
||||
- 2D Graphics using the SDL2 API, no assets are used aside from the font. |
||||
- Point mass elastic physics with elastic collisions. |
||||
- Separating Axis Theorem collision test for convex polygons. |
||||
- Framerate independent physics uses a fixed timestep and completes as many |
||||
steps as neccessary to catch up to each frame. |
||||
- Physics runs in a separate thread and state is managed using shared memory and |
||||
locks. |
||||
- Player physics interactions use forces applied to physics bodies which are |
||||
integrated into impulses and positions. |
||||
- Grappling hook. |
||||
|
||||
# Installation |
||||
|
||||
## Prebuilt Binary |
||||
|
||||
See the releases tab. |
||||
|
||||
On Linux and other Unix-Like operating systems you will need to install the SDL2 |
||||
package from your package maintainer. |
||||
|
||||
## Linux |
||||
```sh |
||||
# on Fedora |
||||
sudo dnf install SDL2 |
||||
``` |
||||
|
||||
# Build Instructions |
||||
|
||||
## On Linux / Unix |
||||
|
||||
Download the SDL2 runtime and SDL2 development packages from your package |
||||
distributor. [official page](http://libsdl.org/download-2.0.php) |
||||
Install the [libSDL2](http://libsdl.org/download-2.0.php) runtime and SDL2 |
||||
development packages from your package distributor. On Fedora, this |
||||
is the `SDL2` and `SDL2-devel` packages. |
||||
|
||||
```bash |
||||
```sh |
||||
git clone --recurse-submodules https://git.topost.net/alistair/space_game.git |
||||
cd space_game |
||||
make |
||||
``` |
||||
|
||||
By default it is built using debug flags. |
||||
(if you forget `--recurse-submodules` you can use, `git submodule init`, `git submodule update`.) |
||||
|
||||
### For Linux |
||||
|
||||
```sh |
||||
make clean |
||||
make target=linux |
||||
``` |
||||
|
||||
### For Windows |
||||
|
||||
You have to have mingw and the mingw libsdl library (I think). |
||||
|
||||
```sh |
||||
sudo dnf install mingw64-SDL2 mingw64-SDL2_image mingw64-SDL2_ttf mingw64-winpthreads mingw64-winpthreads-static |
||||
``` |
||||
|
||||
Run setup.sh to download the SDL2 static libraries and `SDL2.dll`. |
||||
|
||||
``` |
||||
./setup.sh |
||||
make clean |
||||
make target=windows |
||||
``` |
||||
|
||||
## FreeBSD |
||||
|
||||
You need to download the header files and put them in the source folder, with |
||||
the folder name SDL2. You also need the `sdl2` and `gmake` packages. |
||||
|
||||
Something like this: |
||||
|
||||
```sh |
||||
cd /tmp && wget https://www.libsdl.org/release/SDL2-2.0.12.zip && unzip SDL2-2.0.12.zip |
||||
mv /tmp/SDL2-2.0.12/include $source_dir/SDL2 |
||||
pkg install sdl2 gmake |
||||
cd $source_dir |
||||
gmake |
||||
``` |
||||
|
||||
### With debug flags |
||||
|
||||
Append `debug=true` to the make command. |
||||
|
Binary file not shown.
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
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) |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
|
||||
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. |
||||
|
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
# 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 |
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
distribution/ |
||||
.gradle/ |
||||
.idea/ |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
.externalNativeBuild/ |
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
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' |
||||
} |
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
# 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 |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
.externalNativeBuild/ |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
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' |
||||
} |
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
# 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.
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
[{"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":{}}] |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
// 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 |
||||
} |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
# 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.
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
#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 |
@ -0,0 +1,160 @@
@@ -0,0 +1,160 @@
|
||||
#!/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 "$@" |
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
@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 |
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
include ':app' |
||||
// Uncomment this line to build SDL2 |
||||
// Uncomment the dependency line in app/build.gradle as well |
||||
include ':SDL2' |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
#!/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.
@ -0,0 +1,235 @@
@@ -0,0 +1,235 @@
|
||||
#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); |
||||
|
||||
} |
||||
|
||||
|
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
|
||||
#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 |
@ -0,0 +1,238 @@
@@ -0,0 +1,238 @@
|
||||
#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); |
||||
|
||||
} |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
|
||||
#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 |
@ -0,0 +1,106 @@
@@ -0,0 +1,106 @@
|
||||
|
||||
#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 |
@ -0,0 +1,159 @@
@@ -0,0 +1,159 @@
|
||||
#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); |
||||
} |
||||
|
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
#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 |
@ -0,0 +1,983 @@
@@ -0,0 +1,983 @@
|
||||
#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]);*/ |
||||
/*}*/ |
||||
|
||||
} |
||||
|
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
#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 |
@ -0,0 +1,185 @@
@@ -0,0 +1,185 @@
|
||||
#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 |
||||
*/ |
||||
|
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
#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,2 @@
@@ -1 +1,2 @@
|
||||
#include "physics.h" |
||||
#include "types.h" |
@ -1 +1 @@
@@ -1 +1 @@
|
||||
Subproject commit e2078d705069515d84b934c92ff99f55add77036 |
||||
Subproject commit ebf612394a92e9f697ed56c55fc236cb72b511c7 |
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
|
||||
#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 @@
@@ -1 +1 @@
|
||||
Subproject commit 4fcbd1c152a7ab8e749e3601a26861b4daf88a7b |
||||
Subproject commit f3d3d3c18a46a8f75becf219fe42c4a01466f252 |
@ -1,469 +0,0 @@
@@ -1,469 +0,0 @@
|
||||
#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]);*/ |
||||
/*}*/ |
||||
|
||||
} |
@ -1,31 +0,0 @@
@@ -1,31 +0,0 @@
|
||||
#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 |
@ -1,65 +0,0 @@
@@ -1,65 +0,0 @@
|
||||
#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); |
||||
} |
||||
} |
@ -1,42 +0,0 @@
@@ -1,42 +0,0 @@
|
||||
|
||||
#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 |
||||
|
@ -1,70 +0,0 @@
@@ -1,70 +0,0 @@
|
||||
#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); |
||||
} |
||||
|
||||
} |
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
#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 |
@ -1,109 +0,0 @@
@@ -1,109 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
|
@ -0,0 +1,231 @@
@@ -0,0 +1,231 @@
|
||||
#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); |
||||
|
||||
} |
||||
|
||||
|
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
|
||||
#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 |
@ -0,0 +1,97 @@
@@ -0,0 +1,97 @@
|
||||
#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); |
||||
} |
||||
|
@ -0,0 +1,115 @@
@@ -0,0 +1,115 @@
|
||||
|
||||
#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); |
||||
} |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
#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 |
||||
|
@ -0,0 +1,917 @@
@@ -0,0 +1,917 @@
|
||||
#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"); |
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
#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 |
@ -0,0 +1,262 @@
@@ -0,0 +1,262 @@
|
||||
#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; |
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
#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 |
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
#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 |
@ -0,0 +1,181 @@
@@ -0,0 +1,181 @@
|
||||
#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? |
||||
*/ |
||||
|
||||
|
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
#include "physics.h" |
||||
#include "types.h" |
@ -0,0 +1,238 @@
@@ -0,0 +1,238 @@
|
||||
|
||||
#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 |
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
#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); |
||||
} |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
|
||||
#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